diff --git a/src/github.com/dkolbly/wl/common.go b/src/github.com/dkolbly/wl/common.go index 308014d3..e741da3a 100644 --- a/src/github.com/dkolbly/wl/common.go +++ b/src/github.com/dkolbly/wl/common.go @@ -1,8 +1,6 @@ package wl -import ( - "context" -) +import "context" type ProxyId uint32 diff --git a/src/github.com/dkolbly/wl/context.go b/src/github.com/dkolbly/wl/context.go index 3ab3852c..c02234d0 100644 --- a/src/github.com/dkolbly/wl/context.go +++ b/src/github.com/dkolbly/wl/context.go @@ -27,10 +27,15 @@ type Context struct { func (ctx *Context) Register(proxy Proxy) { ctx.mu.Lock() defer ctx.mu.Unlock() - ctx.currentId += 1 - proxy.SetId(ctx.currentId) + pid := proxy.Id() proxy.SetContext(ctx) - ctx.objects[ctx.currentId] = proxy + if pid > 0 { + ctx.objects[pid] = proxy + } else { + ctx.currentId += 1 + proxy.SetId(ctx.currentId) + ctx.objects[ctx.currentId] = proxy + } } func (ctx *Context) lookupProxy(id ProxyId) Proxy { diff --git a/src/ibus-bamboo/client.go b/src/ibus-bamboo/client.go index e648d3f5..481d8f5b 100644 --- a/src/ibus-bamboo/client.go +++ b/src/ibus-bamboo/client.go @@ -7,6 +7,7 @@ package main import ( + "context" "sync" wl "github.com/dkolbly/wl" @@ -67,12 +68,13 @@ func (p *ZwlrForeignToplevelManagerV1) RemoveFinishedHandler(h ZwlrForeignToplev } } -func (p *ZwlrForeignToplevelManagerV1) Dispatch(event *wl.Event) { +func (p *ZwlrForeignToplevelManagerV1) Dispatch(c context.Context, event *wl.Event) { switch event.Opcode { case 0: if len(p.toplevelHandlers) > 0 { ev := ZwlrForeignToplevelManagerV1ToplevelEvent{} - ev.Toplevel = event.Proxy(p.Context()).(*ZwlrForeignToplevelHandleV1) + // ev.Toplevel = event.Proxy(p.Context()).(*ZwlrForeignToplevelHandleV1) + ev.Toplevel = NewZwlrForeignToplevelHandleV1(p.Context(), wl.ProxyId(event.Uint32())) p.mu.RLock() for _, h := range p.toplevelHandlers { h.HandleZwlrForeignToplevelManagerV1Toplevel(ev) @@ -339,7 +341,7 @@ func (p *ZwlrForeignToplevelHandleV1) RemoveParentHandler(h ZwlrForeignToplevelH } } -func (p *ZwlrForeignToplevelHandleV1) Dispatch(event *wl.Event) { +func (p *ZwlrForeignToplevelHandleV1) Dispatch(c context.Context, event *wl.Event) { switch event.Opcode { case 0: if len(p.titleHandlers) > 0 { @@ -435,8 +437,9 @@ type ZwlrForeignToplevelHandleV1 struct { parentHandlers []ZwlrForeignToplevelHandleV1ParentHandler } -func NewZwlrForeignToplevelHandleV1(ctx *wl.Context) *ZwlrForeignToplevelHandleV1 { +func NewZwlrForeignToplevelHandleV1(ctx *wl.Context, pid wl.ProxyId) *ZwlrForeignToplevelHandleV1 { ret := new(ZwlrForeignToplevelHandleV1) + ret.SetId(pid) ctx.Register(ret) return ret } diff --git a/src/ibus-bamboo/version.go b/src/ibus-bamboo/version.go index 2ef87c97..5c7a42e3 100644 --- a/src/ibus-bamboo/version.go +++ b/src/ibus-bamboo/version.go @@ -19,4 +19,4 @@ package main -const Version = "v0.6.9" +const Version = "v0.7.0" diff --git a/src/ibus-bamboo/wl_introspector.go b/src/ibus-bamboo/wl_introspector.go index de64d02e..99e25912 100644 --- a/src/ibus-bamboo/wl_introspector.go +++ b/src/ibus-bamboo/wl_introspector.go @@ -13,38 +13,65 @@ func wlGetFocusWindowClass() error { if err != nil { return fmt.Errorf("Connect to Wayland server failed %s", err) } + appIdChan := make(chan string, 10) + err = registerGlobals(display, appIdChan) + if err != nil { + return err + } + for { + select { + case wlAppId = <-appIdChan: + fmt.Println("wlAppId = ", wlAppId) + case display.Context().Dispatch() <- struct{}{}: + } + } + display.Context().Close() + return nil +} + +func registerGlobals(display *wl.Display, appIdChan chan string) error { registry, err := display.GetRegistry() if err != nil { return fmt.Errorf("Display.GetRegistry failed : %s", err) } - _, err = display.Sync() + + callback, err := display.Sync() if err != nil { return fmt.Errorf("Display.Sync failed %s", err) } - appIdChan := make(chan string, 10) + rgeChan := make(chan wl.RegistryGlobalEvent) rgeHandler := registrar{rgeChan} registry.AddGlobalHandler(rgeHandler) + + cdeChan := make(chan wl.CallbackDoneEvent) + cdeHandler := doner{cdeChan} + + callback.AddDoneHandler(cdeHandler) + adHandler := appIdHandler{appIdChan, false} +loop: for { select { case ev := <-rgeChan: - if err := registerInterface(registry, ev, display.Context(), appIdChan); err != nil { + if err := registerInterface(registry, ev, display.Context(), &adHandler); err != nil { return err } - case wlAppId = <-appIdChan: case display.Context().Dispatch() <- struct{}{}: + case <-cdeChan: + break loop } } + registry.RemoveGlobalHandler(rgeHandler) - display.Context().Close() + callback.RemoveDoneHandler(cdeHandler) return nil } -func registerInterface(registry *wl.Registry, ev wl.RegistryGlobalEvent, ctx *wl.Context, appIdChan chan string) error { +func registerInterface(registry *wl.Registry, ev wl.RegistryGlobalEvent, ctx *wl.Context, adHandler *appIdHandler) error { switch ev.Interface { case "zwlr_foreign_toplevel_manager_v1": manager := NewZwlrForeignToplevelManagerV1(ctx) - manager.AddToplevelHandler(toplevelHandlers{appIdChan}) + manager.AddToplevelHandler(toplevelHandlers{adHandler}) err := registry.Bind(ev.Name, ev.Interface, ev.Version, manager) if err != nil { return fmt.Errorf("Unable to bind ZwlrForeignToplevelManagerV1 interface: %s", err) @@ -53,6 +80,14 @@ func registerInterface(registry *wl.Registry, ev wl.RegistryGlobalEvent, ctx *wl return nil } +type doner struct { + ch chan wl.CallbackDoneEvent +} + +func (d doner) HandleCallbackDone(ev wl.CallbackDoneEvent) { + d.ch <- ev +} + type registrar struct { ch chan wl.RegistryGlobalEvent } @@ -61,19 +96,28 @@ func (r registrar) HandleRegistryGlobal(ev wl.RegistryGlobalEvent) { r.ch <- ev } type toplevelHandlers struct { - ch chan string + adHandler *appIdHandler } func (t toplevelHandlers) HandleZwlrForeignToplevelManagerV1Toplevel(ev ZwlrForeignToplevelManagerV1ToplevelEvent) { - ev.Toplevel.AddAppIdHandler(appIdHandler{t.ch}) + ev.Toplevel.AddAppIdHandler(t.adHandler) + ev.Toplevel.AddDoneHandler(t.adHandler) } type appIdHandler struct { ch chan string + isAppIdUpdated bool } -func (a appIdHandler) HandleZwlrForeignToplevelHandleV1AppId(ev ZwlrForeignToplevelHandleV1AppIdEvent) { - print(ev.AppId) +func (a *appIdHandler) HandleZwlrForeignToplevelHandleV1AppId(ev ZwlrForeignToplevelHandleV1AppIdEvent) { a.ch <- ev.AppId + a.isAppIdUpdated = true +} + +func (a *appIdHandler) HandleZwlrForeignToplevelHandleV1Done(ev ZwlrForeignToplevelHandleV1DoneEvent) { + if !a.isAppIdUpdated { + a.ch <- "" + } + a.isAppIdUpdated = false }