Elias Naur: 1 app: decorations WIP ~pierrec: 1 app: decorations WIP 5 files changed, 116 insertions(+), 26 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~eliasnaur/gio-patches/patches/28715/mbox | git am -3Learn more about email & git
From: Pierre Curto <pierre.curto@gmail.com> In app/window.go at L732, the modified size interferes with the content display. cmd/main.go is the program I use for testing.
Here's the change that seems to fix the issue for me: diff --git app/window.go app/window.go index e46c6510..12cbff07 100644 --- app/window.go +++ app/window.go @@ -587,12 +587,13 @@ func (w *Window) processEvent(d driver, e event.Event) { // Prepare the decorations and update the frame size. wrapper := &w.decorations.Ops wrapper.Reset() + orig := e2.Size e2.FrameEvent.Size = w.decorate(d, e2.FrameEvent, wrapper) w.out <- e2.FrameEvent frame, gotFrame := w.waitFrame() ops.AddCall(&wrapper.Internal, &frame.Internal, ops.PC{}, ops.PCFor(&frame.Internal)) - err := w.validateAndProcess(d, e2.Size, e2.Sync, wrapper) + err := w.validateAndProcess(d, orig, e2.Sync, wrapper) if gotFrame { // We're done with frame, let the client continue. w.frameAck <- struct{}{} @@ -680,7 +681,8 @@ func (w *Window) updateCursor(d driver) { } // decorate the window if enabled and returns the corresponding Insets. -func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (appSize image.Point) { +func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (contentSize image.Point) { + fmt.Println("here?", w.decorations.Config.Decorated) if w.decorations.Config.Decorated || w.decorations.Config.Mode == Fullscreen { return e.Size } @@ -710,7 +712,7 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (appSize ima case Fullscreen: actions |= system.ActionFullscreen default: - panic(fmt.Sprintf("unknown WindowMode %v", m)) + panic(fmt.Errorf("unknown WindowMode %v", m)) } deco.Perform(actions) // Update the window based on the actions on the decorations. @@ -726,9 +728,10 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (appSize ima decoRec := op.Record(o) dims := deco.Layout(gtx, w.decorations.Config.Title) decoCall := decoRec.Stop() + op.Defer(o, decoCall) _ = decoCall size := image.Point{Y: dims.Size.Y} - //op.Offset(f32.Point{Y: float32(size.Y)}).Add(o) + op.Offset(f32.Point{Y: float32(size.Y)}).Add(o) return e.Size.Sub(size) } I also fixed two nits. Elias
Signed-off-by: Pierre Curto <pierre.curto@gmail.com> --- app/os_ios.go | 4 +- app/window.go | 25 ++++----- cmd/windeco/main.go | 94 ++++++++++++++++++++++++++++++++++ widget/material/decorations.go | 8 ++- 4 files changed, 109 insertions(+), 22 deletions(-) create mode 100644 cmd/windeco/main.go diff --git a/app/os_ios.go b/app/os_ios.go index d7f3a6e3..f6fc6147 100644 --- a/app/os_ios.go +++ b/app/os_ios.go @@ -98,6 +98,7 @@ type window struct { visible bool cursor pointer.CursorName + config Config pointerMap []C.CFTypeRef } @@ -277,9 +278,6 @@ func (w *window) Configure([]Option) { prev := w.config // Decorations are never disabled. w.config.Decorated = true - if cnf.Decorated != prev.Decorated { - w.config.Decorated = cnf.Decorated - } if w.config != prev { w.w.Event(ConfigEvent{Config: w.config}) } diff --git a/app/window.go b/app/window.go index dc1576ee..e46c6510 100644 --- a/app/window.go +++ b/app/window.go @@ -584,13 +584,10 @@ func (w *Window) processEvent(d driver, e event.Event) { e2.Frame = w.update e2.Queue = &w.queue - // Prepare the decorations and update the frame insets. + // Prepare the decorations and update the frame size. wrapper := &w.decorations.Ops wrapper.Reset() - decoRec := op.Record(wrapper) - e2.FrameEvent.Insets = w.decorate(d, e2.FrameEvent, wrapper) - op.Defer(wrapper, decoRec.Stop()) - + e2.FrameEvent.Size = w.decorate(d, e2.FrameEvent, wrapper) w.out <- e2.FrameEvent frame, gotFrame := w.waitFrame() ops.AddCall(&wrapper.Internal, &frame.Internal, ops.PC{}, ops.PCFor(&frame.Internal)) @@ -683,9 +680,9 @@ func (w *Window) updateCursor(d driver) { } // decorate the window if enabled and returns the corresponding Insets. -func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) system.Insets { +func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (appSize image.Point) { if w.decorations.Config.Decorated || w.decorations.Config.Mode == Fullscreen { - return e.Insets + return e.Size } deco := w.decorations.Decorations if deco == nil { @@ -726,13 +723,13 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) system.Inset Metric: e.Metric, Constraints: layout.Exact(e.Size), } - insets := deco.Decorate(gtx, w.decorations.Config.Title) - return system.Insets{ - Top: unit.Add(e.Metric, e.Insets.Top, insets.Top), - Bottom: unit.Add(e.Metric, e.Insets.Bottom, insets.Bottom), - Left: unit.Add(e.Metric, e.Insets.Left, insets.Left), - Right: unit.Add(e.Metric, e.Insets.Right, insets.Right), - } + decoRec := op.Record(o) + dims := deco.Layout(gtx, w.decorations.Config.Title) + decoCall := decoRec.Stop() + _ = decoCall + size := image.Point{Y: dims.Size.Y} + //op.Offset(f32.Point{Y: float32(size.Y)}).Add(o) + return e.Size.Sub(size) } // Raise requests that the platform bring this window to the top of all open windows. diff --git a/cmd/windeco/main.go b/cmd/windeco/main.go new file mode 100644 index 00000000..28f72af9 --- /dev/null +++ b/cmd/windeco/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "fmt" + "image/color" + "log" + "os" + + "gioui.org/app" + "gioui.org/font/gofont" + "gioui.org/io/system" + "gioui.org/layout" + "gioui.org/op" + "gioui.org/op/paint" + "gioui.org/unit" + "gioui.org/widget" + "gioui.org/widget/material" +) + +func main() { + go func() { + theme := material.NewTheme(gofont.Collection()) + w := app.NewWindow( + app.Title("MyWindow"), + app.Size(unit.Dp(800), unit.Dp(600)), + ) + ui := new(UI) + *ui = UI{ + th: theme, + win: w, + } + //time.AfterFunc(4*time.Second, func() { + // w.Option(app.Fullscreen.Option()) + // w.Invalidate() + // fmt.Println("fullscreen") + //}) + //time.AfterFunc(8*time.Second, func() { + // w.Option(app.Windowed.Option()) + // w.Invalidate() + // fmt.Println("windowed") + //}) + ops := new(op.Ops) + for ev := range w.Events() { + switch ev := ev.(type) { + case system.DestroyEvent: + var code int + if ev.Err != nil { + code = 1 + log.Println(ev.Err) + } + os.Exit(code) + case system.FrameEvent: + gtx := layout.NewContext(ops, ev) + ui.Layout(gtx) + ev.Frame(gtx.Ops) + case app.ConfigEvent: + fmt.Println(ev.Config) + ui.config = ev.Config + } + } + }() + app.Main() +} + +type UI struct { + th *material.Theme + win *app.Window + config app.Config + btn widget.Bool + close widget.Clickable +} + +func (ui *UI) Layout(gtx layout.Context) layout.Dimensions { + col := color.NRGBA{R: 200, G: 200, B: 200, A: 255} + if ui.btn.Value { + col = color.NRGBA{R: 100, G: 100, B: 100, A: 255} + } + paint.Fill(gtx.Ops, col) + layout.N.Layout(gtx, material.Body1(ui.th, "Hello World").Layout) + layout.Center.Layout(gtx, func(gtx layout.Context) layout.Dimensions { + return ui.btn.Layout(gtx, func(gtx layout.Context) layout.Dimensions { + return material.Body1(ui.th, "Toggle color").Layout(gtx) + }) + }) + layout.SE.Layout(gtx, func(gtx layout.Context) layout.Dimensions { + if ui.close.Clicked() { + ui.win.Close() + } + return ui.close.Layout(gtx, func(gtx layout.Context) layout.Dimensions { + return material.Body1(ui.th, "Close").Layout(gtx) + }) + }) + return layout.Dimensions{} +} diff --git a/widget/material/decorations.go b/widget/material/decorations.go index 92f0861a..d6120392 100644 --- a/widget/material/decorations.go +++ b/widget/material/decorations.go @@ -54,10 +54,10 @@ type Decorations struct { maximized bool } -// Decorate a window with the title and actions defined in DecorationsStyle. +// Layout a window with the title and actions defined in DecorationsStyle. // The space used by the decorations is returned as an inset for the window // content. -func (d *Decorations) Decorate(gtx layout.Context, title string) layout.Inset { +func (d *Decorations) Layout(gtx layout.Context, title string) layout.Dimensions { rec := op.Record(gtx.Ops) dims := d.layoutDecorations(gtx, title) decos := rec.Stop() @@ -65,9 +65,7 @@ func (d *Decorations) Decorate(gtx layout.Context, title string) layout.Inset { paint.FillShape(gtx.Ops, d.DecorationsStyle.Background, r.Op()) decos.Add(gtx.Ops) d.layoutResizing(gtx) - return layout.Inset{ - Top: unit.Px(float32(dims.Size.Y)), - } + return dims } func (d *Decorations) layoutResizing(gtx layout.Context) { -- 2.32.0
builds.sr.ht <builds@sr.ht>gio/patches: FAILED in 2m13s [app: decorations WIP][0] from [~pierrec][1] [0]: https://lists.sr.ht/~eliasnaur/gio-patches/patches/28715 [1]: mailto:pierre.curto@gmail.com ✗ #680706 FAILED gio/patches/linux.yml https://builds.sr.ht/~eliasnaur/job/680706 ✗ #680707 FAILED gio/patches/openbsd.yml https://builds.sr.ht/~eliasnaur/job/680707 ✗ #680704 FAILED gio/patches/apple.yml https://builds.sr.ht/~eliasnaur/job/680704 ✗ #680705 FAILED gio/patches/freebsd.yml https://builds.sr.ht/~eliasnaur/job/680705
On Tue Jan 25, 2022 at 16:18, ~pierrec wrote: > From: Pierre Curto <pierre.curto@gmail.com> > > In app/window.go at L732, the modified size > interferes with the content display. > > cmd/main.go is the program I use for testing. > Here's the change that seems to fix the issue for me: diff --git app/window.go app/window.go index e46c6510..12cbff07 100644 --- app/window.go @@ -587,12 +587,13 @@ func (w *Window) processEvent(d driver, e event.Event) { // Prepare the decorations and update the frame size. wrapper := &w.decorations.Ops wrapper.Reset() + orig := e2.Size e2.FrameEvent.Size = w.decorate(d, e2.FrameEvent, wrapper) w.out <- e2.FrameEvent frame, gotFrame := w.waitFrame() ops.AddCall(&wrapper.Internal, &frame.Internal, ops.PC{}, ops.PCFor(&frame.Internal)) - err := w.validateAndProcess(d, e2.Size, e2.Sync, wrapper) + err := w.validateAndProcess(d, orig, e2.Sync, wrapper) if gotFrame { // We're done with frame, let the client continue. w.frameAck <- struct{}{} @@ -680,7 +681,8 @@ func (w *Window) updateCursor(d driver) { } // decorate the window if enabled and returns the corresponding Insets. -func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (appSize image.Point) { +func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (contentSize image.Point) { + fmt.Println("here?", w.decorations.Config.Decorated) if w.decorations.Config.Decorated || w.decorations.Config.Mode == Fullscreen { return e.Size } @@ -710,7 +712,7 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (appSize ima case Fullscreen: actions |= system.ActionFullscreen default: - panic(fmt.Sprintf("unknown WindowMode %v", m)) + panic(fmt.Errorf("unknown WindowMode %v", m)) } deco.Perform(actions) // Update the window based on the actions on the decorations. @@ -726,9 +728,10 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (appSize ima decoRec := op.Record(o) dims := deco.Layout(gtx, w.decorations.Config.Title) decoCall := decoRec.Stop() + op.Defer(o, decoCall) _ = decoCall size := image.Point{Y: dims.Size.Y} - //op.Offset(f32.Point{Y: float32(size.Y)}).Add(o) + op.Offset(f32.Point{Y: float32(size.Y)}).Add(o) return e.Size.Sub(size) } I also fixed two nits. Elias