From e31aa356224edba98b890f045dad6a3f2c1a9265 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 23 Jun 2022 13:41:34 +0200 Subject: [PATCH] app: draw fallback decorations on top Before this change, client-side decorations for Wayland were drawn before client content, which was prevented from drawing over decorations with a clip. While visually correct, resize handles would't work as long as client listeners are near the window edges to swallow pointer input. This change makes app.Window draw decorations last, fixing resizing and saves a clipping operation. This is an alternative to the original fix for #361, commit 20d4bc2. References: https://todo.sr.ht/~eliasnaur/gio/361 Signed-off-by: Elias Naur --- app/window.go | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/app/window.go b/app/window.go index 86a8a6af..9e480129 100644 --- a/app/window.go +++ b/app/window.go @@ -25,7 +25,6 @@ import ( "gioui.org/io/system" "gioui.org/layout" "gioui.org/op" - "gioui.org/op/clip" "gioui.org/unit" "gioui.org/widget" "gioui.org/widget/material" @@ -818,18 +817,22 @@ func (w *Window) processEvent(d driver, e event.Event) bool { w.queue.q.RevealFocus(viewport) } w.viewport = viewport - size := e2.Size // save the initial window size as the decorations will change it. - e2.FrameEvent.Size = w.decorate(d, e2.FrameEvent, wrapper) + viewSize := e2.Size + m := op.Record(wrapper) + size, offset := w.decorate(d, e2.FrameEvent, wrapper) + e2.FrameEvent.Size = size + deco := m.Stop() w.out <- e2.FrameEvent frame := w.waitFrame(d) var signal chan<- struct{} if frame != nil { signal = w.frameAck - cl := clip.Rect{Max: e2.FrameEvent.Size}.Push(wrapper) + off := op.Offset(offset).Push(wrapper) ops.AddCall(&wrapper.Internal, &frame.Internal, ops.PC{}, ops.PCFor(&frame.Internal)) - cl.Pop() + off.Pop() } - err := w.validateAndProcess(d, size, e2.Sync, wrapper, signal) + deco.Add(wrapper) + err := w.validateAndProcess(d, viewSize, e2.Sync, wrapper, signal) if err != nil { w.destroyGPU() w.out <- system.DestroyEvent{Err: err} @@ -942,9 +945,9 @@ func (w *Window) fallbackDecorate() bool { } // decorate the window if enabled and returns the corresponding Insets. -func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) image.Point { +func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (size, offset image.Point) { if !w.fallbackDecorate() { - return e.Size + return e.Size, image.Pt(0, 0) } theme := w.decorations.Theme if theme == nil { @@ -989,16 +992,15 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) image.Point // Update the window based on the actions on the decorations. w.Perform(deco.Actions()) // Offset to place the frame content below the decorations. - size := image.Point{Y: dims.Size.Y} - op.Offset(image.Pt(0, size.Y)).Add(o) - appSize := e.Size.Sub(size) - if w.decorations.size != size { - w.decorations.size = size + decoSize := image.Point{Y: dims.Size.Y} + appSize := e.Size.Sub(decoSize) + if w.decorations.size != decoSize { + w.decorations.size = decoSize cnf := w.decorations.Config cnf.Size = appSize w.out <- ConfigEvent{Config: cnf} } - return appSize + return appSize, image.Pt(0, decoSize.Y) } // Perform the actions on the window.