merge: kde-loop (KDE decoration mode feedback loop, 40% idle CPU)
2 files · +67 -3
M internal/adapters/wayland/decoration.go +10 -3
| @@ -41,9 +41,16 @@ type kdeDecoration struct{} | |||
| 41 | 41 | ||
| 42 | 42 | func (kdeDecoration) Release(*kdedecoration.OrgKdeKwinServerDecoration) {} | |
| 43 | 43 | ||
| 44 | - | // Any requested mode is answered with server-side, like xdg-decoration. | |
| 45 | - | func (kdeDecoration) RequestMode(r *kdedecoration.OrgKdeKwinServerDecoration, _ uint32) { | |
| 46 | - | r.SendMode(uint32(kdedecoration.OrgKdeKwinServerDecorationModeServer)) | |
| 44 | + | // A requested mode is acknowledged as is: the protocol has no way to | |
| 45 | + | // refuse, and answering server to a client that insists on client-side | |
| 46 | + | // (Firefox) makes it ask again forever. The server default already makes | |
| 47 | + | // GTK drop its title bar. | |
| 48 | + | // Unknown modes are ignored: replacing them would restart the loop. | |
| 49 | + | func (kdeDecoration) RequestMode(r *kdedecoration.OrgKdeKwinServerDecoration, mode uint32) { | |
| 50 | + | if mode > uint32(kdedecoration.OrgKdeKwinServerDecorationModeServer) { | |
| 51 | + | return | |
| 52 | + | } | |
| 53 | + | r.SendMode(mode) | |
| 47 | 54 | } | |
| 48 | 55 | ||
| 49 | 56 | func (decorationManager) Destroy(*xdgdecoration.ZxdgDecorationManagerV1) {} | |
| @@ -41,9 +41,16 @@ type kdeDecoration struct{} | |||||
| 41 | 41 | ||||
| 42 | func (kdeDecoration) Release(*kdedecoration.OrgKdeKwinServerDecoration) {} | 42 | func (kdeDecoration) Release(*kdedecoration.OrgKdeKwinServerDecoration) {} | ||
| 43 | 43 | ||||
| 44 | - | // Any requested mode is answered with server-side, like xdg-decoration. | 44 | + | // A requested mode is acknowledged as is: the protocol has no way to |
| 45 | - | func (kdeDecoration) RequestMode(r *kdedecoration.OrgKdeKwinServerDecoration, _ uint32) { | 45 | + | // refuse, and answering server to a client that insists on client-side |
| 46 | - | r.SendMode(uint32(kdedecoration.OrgKdeKwinServerDecorationModeServer)) | 46 | + | // (Firefox) makes it ask again forever. The server default already makes |
| 47 | + | // GTK drop its title bar. | |||
| 48 | + | // Unknown modes are ignored: replacing them would restart the loop. | |||
| 49 | + | func (kdeDecoration) RequestMode(r *kdedecoration.OrgKdeKwinServerDecoration, mode uint32) { | |||
| 50 | + | if mode > uint32(kdedecoration.OrgKdeKwinServerDecorationModeServer) { | |||
| 51 | + | return | |||
| 52 | + | } | |||
| 53 | + | r.SendMode(mode) | |||
| 47 | } | 54 | } | ||
| 48 | 55 | ||||
| 49 | func (decorationManager) Destroy(*xdgdecoration.ZxdgDecorationManagerV1) {} | 56 | func (decorationManager) Destroy(*xdgdecoration.ZxdgDecorationManagerV1) {} | ||
A internal/adapters/wayland/decoration_test.go +57 -0
| @@ -0,0 +1,57 @@ | |||
| 1 | + | package wayland | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "testing" | |
| 5 | + | "time" | |
| 6 | + | ||
| 7 | + | "github.com/bnema/nefertty/internal/ports" | |
| 8 | + | "github.com/bnema/purego-libwayland/protocol/kdedecoration" | |
| 9 | + | "github.com/bnema/purego-libwayland/protocol/wayland" | |
| 10 | + | "github.com/bnema/wlturbo" | |
| 11 | + | ) | |
| 12 | + | ||
| 13 | + | type kdeModeProxy struct { | |
| 14 | + | wlturbo.BaseProxy | |
| 15 | + | modes chan uint32 | |
| 16 | + | } | |
| 17 | + | ||
| 18 | + | func (p *kdeModeProxy) Dispatch(e *wlturbo.Event) { p.modes <- e.Uint32() } | |
| 19 | + | ||
| 20 | + | // KDE decoration defaults to server-side and acknowledges the mode a client | |
| 21 | + | // asks for: answering server to Firefox's client request made it ask again | |
| 22 | + | // in a tight loop. | |
| 23 | + | func TestKDEDecorationAcknowledgesMode(t *testing.T) { | |
| 24 | + | s, _, _, dir := dmabufServer(t, ports.DMABufSupport{}) | |
| 25 | + | c := protocolClient(t, s, dir) | |
| 26 | + | comp := bindProtocol(t, c, "wl_compositor") | |
| 27 | + | mgr := bindProtocol(t, c, "org_kde_kwin_server_decoration_manager") | |
| 28 | + | registerProtocol(t, c, mgr) | |
| 29 | + | surf := c.AllocateID() | |
| 30 | + | requestProtocol(t, c, comp, wayland.CompositorRequestCreateSurface, surf) | |
| 31 | + | deco := c.AllocateID() | |
| 32 | + | proxy := &kdeModeProxy{modes: make(chan uint32, 8)} | |
| 33 | + | proxy.SetID(deco) | |
| 34 | + | c.Context().Register(proxy) | |
| 35 | + | requestProtocol(t, c, mgr, kdedecoration.OrgKdeKwinServerDecorationManagerRequestCreate, deco, surf) | |
| 36 | + | requestProtocol(t, c, deco, kdedecoration.OrgKdeKwinServerDecorationRequestRequestMode, uint32(kdedecoration.OrgKdeKwinServerDecorationModeClient)) | |
| 37 | + | // An undefined mode gets no answer. | |
| 38 | + | requestProtocol(t, c, deco, kdedecoration.OrgKdeKwinServerDecorationRequestRequestMode, uint32(3)) | |
| 39 | + | if err := c.Roundtrip(); err != nil { | |
| 40 | + | t.Fatal(err) | |
| 41 | + | } | |
| 42 | + | for _, want := range []kdedecoration.OrgKdeKwinServerDecorationMode{kdedecoration.OrgKdeKwinServerDecorationModeServer, kdedecoration.OrgKdeKwinServerDecorationModeClient} { | |
| 43 | + | select { | |
| 44 | + | case got := <-proxy.modes: | |
| 45 | + | if got != uint32(want) { | |
| 46 | + | t.Fatalf("mode %d want %d", got, want) | |
| 47 | + | } | |
| 48 | + | case <-time.After(2 * time.Second): | |
| 49 | + | t.Fatalf("no mode %d", want) | |
| 50 | + | } | |
| 51 | + | } | |
| 52 | + | select { | |
| 53 | + | case got := <-proxy.modes: | |
| 54 | + | t.Fatalf("extra mode %d", got) | |
| 55 | + | default: | |
| 56 | + | } | |
| 57 | + | } | |
| @@ -0,0 +1,57 @@ | |||||
| 1 | + | package wayland | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "testing" | |||
| 5 | + | "time" | |||
| 6 | + | ||||
| 7 | + | "github.com/bnema/nefertty/internal/ports" | |||
| 8 | + | "github.com/bnema/purego-libwayland/protocol/kdedecoration" | |||
| 9 | + | "github.com/bnema/purego-libwayland/protocol/wayland" | |||
| 10 | + | "github.com/bnema/wlturbo" | |||
| 11 | + | ) | |||
| 12 | + | ||||
| 13 | + | type kdeModeProxy struct { | |||
| 14 | + | wlturbo.BaseProxy | |||
| 15 | + | modes chan uint32 | |||
| 16 | + | } | |||
| 17 | + | ||||
| 18 | + | func (p *kdeModeProxy) Dispatch(e *wlturbo.Event) { p.modes <- e.Uint32() } | |||
| 19 | + | ||||
| 20 | + | // KDE decoration defaults to server-side and acknowledges the mode a client | |||
| 21 | + | // asks for: answering server to Firefox's client request made it ask again | |||
| 22 | + | // in a tight loop. | |||
| 23 | + | func TestKDEDecorationAcknowledgesMode(t *testing.T) { | |||
| 24 | + | s, _, _, dir := dmabufServer(t, ports.DMABufSupport{}) | |||
| 25 | + | c := protocolClient(t, s, dir) | |||
| 26 | + | comp := bindProtocol(t, c, "wl_compositor") | |||
| 27 | + | mgr := bindProtocol(t, c, "org_kde_kwin_server_decoration_manager") | |||
| 28 | + | registerProtocol(t, c, mgr) | |||
| 29 | + | surf := c.AllocateID() | |||
| 30 | + | requestProtocol(t, c, comp, wayland.CompositorRequestCreateSurface, surf) | |||
| 31 | + | deco := c.AllocateID() | |||
| 32 | + | proxy := &kdeModeProxy{modes: make(chan uint32, 8)} | |||
| 33 | + | proxy.SetID(deco) | |||
| 34 | + | c.Context().Register(proxy) | |||
| 35 | + | requestProtocol(t, c, mgr, kdedecoration.OrgKdeKwinServerDecorationManagerRequestCreate, deco, surf) | |||
| 36 | + | requestProtocol(t, c, deco, kdedecoration.OrgKdeKwinServerDecorationRequestRequestMode, uint32(kdedecoration.OrgKdeKwinServerDecorationModeClient)) | |||
| 37 | + | // An undefined mode gets no answer. | |||
| 38 | + | requestProtocol(t, c, deco, kdedecoration.OrgKdeKwinServerDecorationRequestRequestMode, uint32(3)) | |||
| 39 | + | if err := c.Roundtrip(); err != nil { | |||
| 40 | + | t.Fatal(err) | |||
| 41 | + | } | |||
| 42 | + | for _, want := range []kdedecoration.OrgKdeKwinServerDecorationMode{kdedecoration.OrgKdeKwinServerDecorationModeServer, kdedecoration.OrgKdeKwinServerDecorationModeClient} { | |||
| 43 | + | select { | |||
| 44 | + | case got := <-proxy.modes: | |||
| 45 | + | if got != uint32(want) { | |||
| 46 | + | t.Fatalf("mode %d want %d", got, want) | |||
| 47 | + | } | |||
| 48 | + | case <-time.After(2 * time.Second): | |||
| 49 | + | t.Fatalf("no mode %d", want) | |||
| 50 | + | } | |||
| 51 | + | } | |||
| 52 | + | select { | |||
| 53 | + | case got := <-proxy.modes: | |||
| 54 | + | t.Fatalf("extra mode %d", got) | |||
| 55 | + | default: | |||
| 56 | + | } | |||
| 57 | + | } | |||