diff --git a/astilectron.go b/astilectron.go index 51774ef..bcbbb84 100644 --- a/astilectron.go +++ b/astilectron.go @@ -51,6 +51,7 @@ type Astilectron struct { closeOnce sync.Once dispatcher *dispatcher displayPool *displayPool + dock *Dock executer Executer identifier *identifier listener net.Listener @@ -139,7 +140,7 @@ func (a *Astilectron) SetExecuter(e Executer) *Astilectron { // On implements the Listenable interface func (a *Astilectron) On(eventName string, l Listener) { - a.dispatcher.addListener(mainTargetID, eventName, l) + a.dispatcher.addListener(targetIDApp, eventName, l) } // Start starts Astilectron @@ -206,8 +207,8 @@ func (a *Astilectron) watchNoAccept(timeout time.Duration, chanAccepted chan boo return case <-t.C: astilog.Errorf("No TCP connection has been accepted in the past %s", timeout) - a.dispatcher.dispatch(Event{Name: EventNameAppNoAccept, TargetID: mainTargetID}) - a.dispatcher.dispatch(Event{Name: EventNameAppCmdStop, TargetID: mainTargetID}) + a.dispatcher.dispatch(Event{Name: EventNameAppNoAccept, TargetID: targetIDApp}) + a.dispatcher.dispatch(Event{Name: EventNameAppCmdStop, TargetID: targetIDApp}) return } } @@ -221,8 +222,8 @@ func (a *Astilectron) acceptTCP(chanAccepted chan bool) { var err error if conn, err = a.listener.Accept(); err != nil { astilog.Errorf("%s while TCP accepting", err) - a.dispatcher.dispatch(Event{Name: EventNameAppErrorAccept, TargetID: mainTargetID}) - a.dispatcher.dispatch(Event{Name: EventNameAppCmdStop, TargetID: mainTargetID}) + a.dispatcher.dispatch(Event{Name: EventNameAppErrorAccept, TargetID: targetIDApp}) + a.dispatcher.dispatch(Event{Name: EventNameAppCmdStop, TargetID: targetIDApp}) return } @@ -230,8 +231,8 @@ func (a *Astilectron) acceptTCP(chanAccepted chan bool) { // the app if i > 0 { astilog.Errorf("Too many TCP connections") - a.dispatcher.dispatch(Event{Name: EventNameAppTooManyAccept, TargetID: mainTargetID}) - a.dispatcher.dispatch(Event{Name: EventNameAppCmdStop, TargetID: mainTargetID}) + a.dispatcher.dispatch(Event{Name: EventNameAppTooManyAccept, TargetID: targetIDApp}) + a.dispatcher.dispatch(Event{Name: EventNameAppCmdStop, TargetID: targetIDApp}) conn.Close() return } @@ -276,6 +277,9 @@ func (a *Astilectron) executeCmd(cmd *exec.Cmd) (err error) { if e.Displays != nil { a.displayPool.update(e.Displays) } + + // Create dock + a.dock = newDock(e.Dock, a.canceller, a.dispatcher, a.identifier, a.writer) return } @@ -287,12 +291,12 @@ func (a *Astilectron) watchCmd(cmd *exec.Cmd) { // Check the canceller to check whether it was a crash if !a.canceller.Cancelled() { astilog.Debug("App has crashed") - a.dispatcher.dispatch(Event{Name: EventNameAppCrash, TargetID: mainTargetID}) + a.dispatcher.dispatch(Event{Name: EventNameAppCrash, TargetID: targetIDApp}) } else { astilog.Debug("App has closed") - a.dispatcher.dispatch(Event{Name: EventNameAppClose, TargetID: mainTargetID}) + a.dispatcher.dispatch(Event{Name: EventNameAppClose, TargetID: targetIDApp}) } - a.dispatcher.dispatch(Event{Name: EventNameAppCmdStop, TargetID: mainTargetID}) + a.dispatcher.dispatch(Event{Name: EventNameAppCmdStop, TargetID: targetIDApp}) } // Close closes Astilectron properly @@ -357,6 +361,11 @@ func (a *Astilectron) Displays() []*Display { return a.displayPool.all() } +// Dock returns the dock +func (a *Astilectron) Dock() *Dock { + return a.dock +} + // PrimaryDisplay returns the primary display func (a *Astilectron) PrimaryDisplay() *Display { return a.displayPool.primary() @@ -364,7 +373,7 @@ func (a *Astilectron) PrimaryDisplay() *Display { // NewMenu creates a new app menu func (a *Astilectron) NewMenu(i []*MenuItemOptions) *Menu { - return newMenu(nil, mainTargetID, i, a.canceller, a.dispatcher, a.identifier, a.writer) + return newMenu(nil, targetIDApp, i, a.canceller, a.dispatcher, a.identifier, a.writer) } // NewWindow creates a new window diff --git a/astilectron_test.go b/astilectron_test.go index 14bcc4f..b94da61 100644 --- a/astilectron_test.go +++ b/astilectron_test.go @@ -166,7 +166,7 @@ func TestAstilectron_NewMenu(t *testing.T) { a, err := New(Options{}) assert.NoError(t, err) m := a.NewMenu([]*MenuItemOptions{}) - assert.Equal(t, mainTargetID, m.rootID) + assert.Equal(t, targetIDApp, m.rootID) } func TestAstilectron_Actions(t *testing.T) { diff --git a/dock.go b/dock.go new file mode 100644 index 0000000..d3e96c8 --- /dev/null +++ b/dock.go @@ -0,0 +1,134 @@ +package astilectron + +import "github.com/asticode/go-astitools/context" + +// Dock event names +const ( + eventNameDockCmdBounce = "dock.cmd.bounce" + eventNameDockCmdBounceDownloads = "dock.cmd.bounce.downloads" + eventNameDockCmdCancelBounce = "dock.cmd.cancel.bounce" + eventNameDockCmdHide = "dock.cmd.hide" + eventNameDockCmdSetBadge = "dock.cmd.set.badge" + eventNameDockCmdSetIcon = "dock.cmd.set.icon" + eventNameDockCmdShow = "dock.cmd.show" + eventNameDockEventBadgeSet = "dock.event.badge.set" + eventNameDockEventBouncing = "dock.event.bouncing" + eventNameDockEventBouncingCancelled = "dock.event.bouncing.cancelled" + eventNameDockEventDownloadsBouncing = "dock.event.download.bouncing" + eventNameDockEventHidden = "dock.event.hidden" + eventNameDockEventIconSet = "dock.event.icon.set" + eventNameDockEventShown = "dock.event.shown" +) + +// Dock bounce types +const ( + DockBounceTypeCritical = "critical" + DockBounceTypeInformational = "informational" +) + +// Dock represents a dock +// https://github.com/electron/electron/blob/v1.8.1/docs/api/app.md#appdockbouncetype-macos +type Dock struct { + *object + o *DockOptions +} + +// DockOptions represents dock options +type DockOptions struct { + Badge string `json:"badge,omitempty"` + IsVisible *bool `json:"isVisible,omitempty"` +} + +func newDock(o *DockOptions, c *asticontext.Canceller, d *dispatcher, i *identifier, wrt *writer) *Dock { + return &Dock{ + o: o, + object: newObject(nil, c, d, i, wrt, targetIDDock), + } +} + +// Badge returns the badge +func (d *Dock) Badge() string { + return d.o.Badge +} + +// Bounce bounces the dock +func (d *Dock) Bounce(bounceType string) (id int, err error) { + if err = d.isActionable(); err != nil { + return + } + var e Event + if e, err = synchronousEvent(d.c, d, d.w, Event{Name: eventNameDockCmdBounce, TargetID: d.id, BounceType: bounceType}, eventNameDockEventBouncing); err != nil { + return + } + if e.ID != nil { + id = *e.ID + } + return +} + +// BounceDownloads bounces the downloads part of the dock +func (d *Dock) BounceDownloads(filePath string) (err error) { + if err = d.isActionable(); err != nil { + return + } + _, err = synchronousEvent(d.c, d, d.w, Event{Name: eventNameDockCmdBounceDownloads, TargetID: d.id, FilePath: filePath}, eventNameDockEventDownloadsBouncing) + return +} + +// CancelBounce cancels the dock bounce +func (d *Dock) CancelBounce(id int) (err error) { + if err = d.isActionable(); err != nil { + return + } + _, err = synchronousEvent(d.c, d, d.w, Event{Name: eventNameDockCmdCancelBounce, TargetID: d.id, ID: PtrInt(id)}, eventNameDockEventBouncingCancelled) + return +} + +// Hide hides the dock +func (d *Dock) Hide() (err error) { + if err = d.isActionable(); err != nil { + return + } + _, err = synchronousEvent(d.c, d, d.w, Event{Name: eventNameDockCmdHide, TargetID: d.id}, eventNameDockEventHidden) + d.o.IsVisible = PtrBool(false) + return +} + +// IsVisible returns whether the dock is visible +func (d *Dock) IsVisible() *bool { + return d.o.IsVisible +} + +// NewMenu creates a new dock menu +func (d *Dock) NewMenu(i []*MenuItemOptions) *Menu { + return newMenu(d.ctx, d.id, i, d.c, d.d, d.i, d.w) +} + +// SetBadge sets the badge of the dock +func (d *Dock) SetBadge(badge string) (err error) { + if err = d.isActionable(); err != nil { + return + } + _, err = synchronousEvent(d.c, d, d.w, Event{Name: eventNameDockCmdSetBadge, TargetID: d.id, Badge: badge}, eventNameDockEventBadgeSet) + d.o.Badge = badge + return +} + +// SetIcon sets the icon of the dock +func (d *Dock) SetIcon(image string) (err error) { + if err = d.isActionable(); err != nil { + return + } + _, err = synchronousEvent(d.c, d, d.w, Event{Name: eventNameDockCmdSetIcon, TargetID: d.id, Image: image}, eventNameDockEventIconSet) + return +} + +// Show shows the dock +func (d *Dock) Show() (err error) { + if err = d.isActionable(); err != nil { + return + } + _, err = synchronousEvent(d.c, d, d.w, Event{Name: eventNameDockCmdShow, TargetID: d.id}, eventNameDockEventShown) + d.o.IsVisible = PtrBool(true) + return +} diff --git a/event.go b/event.go index 4e13ce9..30c58fe 100644 --- a/event.go +++ b/event.go @@ -5,9 +5,10 @@ import ( "errors" ) -// Misc constants +// Target IDs const ( - mainTargetID = "main" + targetIDApp = "app" + targetIDDock = "dock" ) // Event represents an event @@ -19,8 +20,13 @@ type Event struct { // This is a list of all possible payloads. // A choice was made not to use interfaces since it's a pain in the ass asserting each an every payload afterwards // We use pointers so that omitempty works + Badge string `json:"badge,omitempty"` + BounceType string `json:"bounceType,omitempty"` CallbackID string `json:"callbackId,omitempty"` Displays *EventDisplays `json:"displays,omitempty"` + Dock *DockOptions `json:"dock,omitempty"` + FilePath string `json:"filePath,omitempty"` + ID *int `json:"id,omitempty"` Image string `json:"image,omitempty"` Menu *EventMenu `json:"menu,omitempty"` MenuItem *EventMenuItem `json:"menuItem,omitempty"` diff --git a/menu_item.go b/menu_item.go index f1bc9f2..8d9460e 100644 --- a/menu_item.go +++ b/menu_item.go @@ -97,7 +97,7 @@ type MenuItemOptions struct { func newMenuItem(parentCtx context.Context, rootID string, o *MenuItemOptions, c *asticontext.Canceller, d *dispatcher, i *identifier, w *writer) (m *MenuItem) { m = &MenuItem{ o: o, - object: newObject(parentCtx, c, d, i, w), + object: newObject(parentCtx, c, d, i, w, i.new()), rootID: rootID, } if o.OnClick != nil { diff --git a/menu_item_test.go b/menu_item_test.go index 771ccad..daec27b 100644 --- a/menu_item_test.go +++ b/menu_item_test.go @@ -10,9 +10,9 @@ import ( func TestMenuItem_ToEvent(t *testing.T) { var o = &MenuItemOptions{Label: PtrStr("1"), SubMenu: []*MenuItemOptions{{Label: PtrStr("2")}, {Label: PtrStr("3")}}} - var mi = newMenuItem(context.Background(), "main", o, nil, nil, newIdentifier(), nil) + var mi = newMenuItem(context.Background(), targetIDApp, o, nil, nil, newIdentifier(), nil) e := mi.toEvent() - assert.Equal(t, &EventMenuItem{ID: "1", RootID: "main", Options: o, SubMenu: &EventSubMenu{ID: "2", Items: []*EventMenuItem{{ID: "3", Options: &MenuItemOptions{Label: PtrStr("2")}, RootID: "main"}, {ID: "4", Options: &MenuItemOptions{Label: PtrStr("3")}, RootID: "main"}}, RootID: "main"}}, e) + assert.Equal(t, &EventMenuItem{ID: "1", RootID: targetIDApp, Options: o, SubMenu: &EventSubMenu{ID: "2", Items: []*EventMenuItem{{ID: "3", Options: &MenuItemOptions{Label: PtrStr("2")}, RootID: targetIDApp}, {ID: "4", Options: &MenuItemOptions{Label: PtrStr("3")}, RootID: targetIDApp}}, RootID: targetIDApp}}, e) assert.Len(t, mi.SubMenu().items, 2) } @@ -23,7 +23,7 @@ func TestMenuItem_Actions(t *testing.T) { var i = newIdentifier() var wrt = &mockedWriter{} var w = newWriter(wrt) - var mi = newMenuItem(context.Background(), "main", &MenuItemOptions{Label: PtrStr("label")}, c, d, i, w) + var mi = newMenuItem(context.Background(), targetIDApp, &MenuItemOptions{Label: PtrStr("label")}, c, d, i, w) // Actions testObjectAction(t, func() error { return mi.SetChecked(true) }, mi.object, wrt, "{\"name\":\""+EventNameMenuItemCmdSetChecked+"\",\"targetID\":\""+mi.id+"\",\"menuItemOptions\":{\"checked\":true}}\n", EventNameMenuItemEventCheckedSet) diff --git a/menu_test.go b/menu_test.go index 53db7a5..0322fde 100644 --- a/menu_test.go +++ b/menu_test.go @@ -9,9 +9,9 @@ import ( ) func TestMenu_ToEvent(t *testing.T) { - var m = newMenu(nil, "main", []*MenuItemOptions{{Label: PtrStr("1")}, {Label: PtrStr("2")}}, asticontext.NewCanceller(), newDispatcher(), newIdentifier(), nil) + var m = newMenu(nil, targetIDApp, []*MenuItemOptions{{Label: PtrStr("1")}, {Label: PtrStr("2")}}, asticontext.NewCanceller(), newDispatcher(), newIdentifier(), nil) e := m.toEvent() - assert.Equal(t, &EventMenu{EventSubMenu: &EventSubMenu{ID: "1", Items: []*EventMenuItem{{ID: "2", Options: &MenuItemOptions{Label: PtrStr("1")}, RootID: "main"}, {ID: "3", Options: &MenuItemOptions{Label: PtrStr("2")}, RootID: "main"}}, RootID: "main"}}, e) + assert.Equal(t, &EventMenu{EventSubMenu: &EventSubMenu{ID: "1", Items: []*EventMenuItem{{ID: "2", Options: &MenuItemOptions{Label: PtrStr("1")}, RootID: targetIDApp}, {ID: "3", Options: &MenuItemOptions{Label: PtrStr("2")}, RootID: targetIDApp}}, RootID: targetIDApp}}, e) } func TestMenu_Actions(t *testing.T) { @@ -21,10 +21,10 @@ func TestMenu_Actions(t *testing.T) { var i = newIdentifier() var wrt = &mockedWriter{} var w = newWriter(wrt) - var m = newMenu(context.Background(), "main", []*MenuItemOptions{{Label: PtrStr("1")}, {Label: PtrStr("2")}}, c, d, i, w) + var m = newMenu(context.Background(), targetIDApp, []*MenuItemOptions{{Label: PtrStr("1")}, {Label: PtrStr("2")}}, c, d, i, w) // Actions - testObjectAction(t, func() error { return m.Create() }, m.object, wrt, "{\"name\":\""+EventNameMenuCmdCreate+"\",\"targetID\":\""+m.id+"\",\"menu\":{\"id\":\"1\",\"items\":[{\"id\":\"2\",\"options\":{\"label\":\"1\"},\"rootId\":\"main\"},{\"id\":\"3\",\"options\":{\"label\":\"2\"},\"rootId\":\"main\"}],\"rootId\":\"main\"}}\n", EventNameMenuEventCreated) - testObjectAction(t, func() error { return m.Destroy() }, m.object, wrt, "{\"name\":\""+EventNameMenuCmdDestroy+"\",\"targetID\":\""+m.id+"\",\"menu\":{\"id\":\"1\",\"items\":[{\"id\":\"2\",\"options\":{\"label\":\"1\"},\"rootId\":\"main\"},{\"id\":\"3\",\"options\":{\"label\":\"2\"},\"rootId\":\"main\"}],\"rootId\":\"main\"}}\n", EventNameMenuEventDestroyed) + testObjectAction(t, func() error { return m.Create() }, m.object, wrt, "{\"name\":\""+EventNameMenuCmdCreate+"\",\"targetID\":\""+m.id+"\",\"menu\":{\"id\":\"1\",\"items\":[{\"id\":\"2\",\"options\":{\"label\":\"1\"},\"rootId\":\""+targetIDApp+"\"},{\"id\":\"3\",\"options\":{\"label\":\"2\"},\"rootId\":\""+targetIDApp+"\"}],\"rootId\":\""+targetIDApp+"\"}}\n", EventNameMenuEventCreated) + testObjectAction(t, func() error { return m.Destroy() }, m.object, wrt, "{\"name\":\""+EventNameMenuCmdDestroy+"\",\"targetID\":\""+m.id+"\",\"menu\":{\"id\":\"1\",\"items\":[{\"id\":\"2\",\"options\":{\"label\":\"1\"},\"rootId\":\""+targetIDApp+"\"},{\"id\":\"3\",\"options\":{\"label\":\"2\"},\"rootId\":\""+targetIDApp+"\"}],\"rootId\":\""+targetIDApp+"\"}}\n", EventNameMenuEventDestroyed) assert.True(t, m.IsDestroyed()) } diff --git a/object.go b/object.go index 5042854..84228cc 100644 --- a/object.go +++ b/object.go @@ -25,12 +25,12 @@ type object struct { } // newObject returns a new base object -func newObject(parentCtx context.Context, c *asticontext.Canceller, d *dispatcher, i *identifier, w *writer) (o *object) { +func newObject(parentCtx context.Context, c *asticontext.Canceller, d *dispatcher, i *identifier, w *writer, id string) (o *object) { o = &object{ c: c, d: d, i: i, - id: i.new(), + id: id, w: w, } if parentCtx != nil { diff --git a/object_test.go b/object_test.go index 3f50137..76e1286 100644 --- a/object_test.go +++ b/object_test.go @@ -10,7 +10,7 @@ import ( func TestObject_IsActionable(t *testing.T) { // Init var c = asticontext.NewCanceller() - var o = newObject(nil, c, nil, newIdentifier(), nil) + var o = newObject(nil, c, nil, newIdentifier(), nil, "") // Test success assert.NoError(t, o.isActionable()) diff --git a/session.go b/session.go index 2a3f9f1..f14d28c 100644 --- a/session.go +++ b/session.go @@ -22,7 +22,7 @@ type Session struct { // newSession creates a new session func newSession(parentCtx context.Context, c *asticontext.Canceller, d *dispatcher, i *identifier, w *writer) *Session { - return &Session{object: newObject(parentCtx, c, d, i, w)} + return &Session{object: newObject(parentCtx, c, d, i, w, i.new())} } // ClearCache clears the Session's HTTP cache diff --git a/sub_menu.go b/sub_menu.go index 7b367f8..887aff3 100644 --- a/sub_menu.go +++ b/sub_menu.go @@ -40,7 +40,7 @@ type subMenu struct { func newSubMenu(parentCtx context.Context, rootID string, items []*MenuItemOptions, c *asticontext.Canceller, d *dispatcher, i *identifier, w *writer) *subMenu { // Init var m = &subMenu{ - object: newObject(parentCtx, c, d, i, w), + object: newObject(parentCtx, c, d, i, w, i.new()), rootID: rootID, } diff --git a/sub_menu_test.go b/sub_menu_test.go index 0183096..d6918b5 100644 --- a/sub_menu_test.go +++ b/sub_menu_test.go @@ -10,9 +10,9 @@ import ( func TestSubMenu_ToEvent(t *testing.T) { // App sub menu - var s = newSubMenu(nil, "main", []*MenuItemOptions{{Label: PtrStr("1")}, {Label: PtrStr("2")}}, asticontext.NewCanceller(), newDispatcher(), newIdentifier(), nil) + var s = newSubMenu(nil, targetIDApp, []*MenuItemOptions{{Label: PtrStr("1")}, {Label: PtrStr("2")}}, asticontext.NewCanceller(), newDispatcher(), newIdentifier(), nil) e := s.toEvent() - assert.Equal(t, &EventSubMenu{ID: "1", Items: []*EventMenuItem{{ID: "2", Options: &MenuItemOptions{Label: PtrStr("1")}, RootID: "main"}, {ID: "3", Options: &MenuItemOptions{Label: PtrStr("2")}, RootID: "main"}}, RootID: "main"}, e) + assert.Equal(t, &EventSubMenu{ID: "1", Items: []*EventMenuItem{{ID: "2", Options: &MenuItemOptions{Label: PtrStr("1")}, RootID: targetIDApp}, {ID: "3", Options: &MenuItemOptions{Label: PtrStr("2")}, RootID: targetIDApp}}, RootID: targetIDApp}, e) // Window sub menu var i = newIdentifier() @@ -37,7 +37,7 @@ func TestSubMenu_SubMenu(t *testing.T) { }}, {}, } - var m = newMenu(context.Background(), "main", o, nil, newDispatcher(), newIdentifier(), nil) + var m = newMenu(context.Background(), targetIDApp, o, nil, newDispatcher(), newIdentifier(), nil) s, err := m.SubMenu(0, 1) assert.EqualError(t, err, "No submenu at 0") s, err = m.SubMenu(1) @@ -66,7 +66,7 @@ func TestSubMenu_Item(t *testing.T) { }}, {Label: PtrStr("3")}, } - var m = newMenu(context.Background(), "main", o, nil, newDispatcher(), newIdentifier(), nil) + var m = newMenu(context.Background(), targetIDApp, o, nil, newDispatcher(), newIdentifier(), nil) i, err := m.Item(3) assert.EqualError(t, err, "Submenu has 3 items, invalid index 3") i, err = m.Item(0) @@ -89,17 +89,17 @@ func TestSubMenu_Actions(t *testing.T) { var i = newIdentifier() var wrt = &mockedWriter{} var w = newWriter(wrt) - var s = newSubMenu(nil, "main", []*MenuItemOptions{{Label: PtrStr("0")}}, c, d, i, w) + var s = newSubMenu(nil, targetIDApp, []*MenuItemOptions{{Label: PtrStr("0")}}, c, d, i, w) // Actions var mi = s.NewItem(&MenuItemOptions{Label: PtrStr("1")}) - testObjectAction(t, func() error { return s.Append(mi) }, s.object, wrt, "{\"name\":\""+EventNameSubMenuCmdAppend+"\",\"targetID\":\""+s.id+"\",\"menuItem\":{\"id\":\"3\",\"options\":{\"label\":\"1\"},\"rootId\":\"main\"}}\n", EventNameSubMenuEventAppended) + testObjectAction(t, func() error { return s.Append(mi) }, s.object, wrt, "{\"name\":\""+EventNameSubMenuCmdAppend+"\",\"targetID\":\""+s.id+"\",\"menuItem\":{\"id\":\"3\",\"options\":{\"label\":\"1\"},\"rootId\":\""+targetIDApp+"\"}}\n", EventNameSubMenuEventAppended) assert.Len(t, s.items, 2) assert.Equal(t, "1", *s.items[1].o.Label) mi = s.NewItem(&MenuItemOptions{Label: PtrStr("2")}) err := s.Insert(3, mi) assert.EqualError(t, err, "Submenu has 2 items, position 3 is invalid") - testObjectAction(t, func() error { return s.Insert(1, mi) }, s.object, wrt, "{\"name\":\""+EventNameSubMenuCmdInsert+"\",\"targetID\":\""+s.id+"\",\"menuItem\":{\"id\":\"4\",\"options\":{\"label\":\"2\"},\"rootId\":\"main\"},\"menuItemPosition\":1}\n", EventNameSubMenuEventInserted) + testObjectAction(t, func() error { return s.Insert(1, mi) }, s.object, wrt, "{\"name\":\""+EventNameSubMenuCmdInsert+"\",\"targetID\":\""+s.id+"\",\"menuItem\":{\"id\":\"4\",\"options\":{\"label\":\"2\"},\"rootId\":\""+targetIDApp+"\"},\"menuItemPosition\":1}\n", EventNameSubMenuEventInserted) assert.Len(t, s.items, 3) assert.Equal(t, "2", *s.items[1].o.Label) testObjectAction(t, func() error { diff --git a/tray.go b/tray.go index 54d9947..5da59f9 100644 --- a/tray.go +++ b/tray.go @@ -35,7 +35,7 @@ func newTray(o *TrayOptions, c *asticontext.Canceller, d *dispatcher, i *identif // Init t = &Tray{ o: o, - object: newObject(nil, c, d, i, wrt), + object: newObject(nil, c, d, i, wrt, i.new()), } // Make sure the tray's context is cancelled once the destroyed event is received diff --git a/window.go b/window.go index 1c074f6..cda651e 100644 --- a/window.go +++ b/window.go @@ -159,7 +159,7 @@ func newWindow(o Options, url string, wo *WindowOptions, c *asticontext.Cancelle w = &Window{ callbackIdentifier: newIdentifier(), o: wo, - object: newObject(nil, c, d, i, wrt), + object: newObject(nil, c, d, i, wrt, i.new()), } w.Session = newSession(w.ctx, c, d, i, wrt)