From 92c15a5155134d792b251ad458180402f98e0c68 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 12 Oct 2020 19:12:33 +0100 Subject: [PATCH 1/4] Ensure that popups and menus fit within the screen bounds for mobile devices Fixes #1358 --- driver/mobile/device.go | 5 +++++ internal/driver/glfw/canvas.go | 1 + internal/driver/gomobile/canvas.go | 19 +++++-------------- internal/driver/gomobile/device.go | 12 ++++++++++++ internal/driver/gomobile/menu.go | 5 ++++- internal/overlay_stack.go | 17 +++++++++++++++++ internal/overlay_stack_test.go | 3 ++- test/testcanvas.go | 5 +++-- widget/menu.go | 8 +++++++- 9 files changed, 56 insertions(+), 19 deletions(-) diff --git a/driver/mobile/device.go b/driver/mobile/device.go index 44446286f5..0201e785c6 100644 --- a/driver/mobile/device.go +++ b/driver/mobile/device.go @@ -1,8 +1,13 @@ // Package mobile provides mobile specific driver functionality. package mobile +import "fyne.io/fyne" + // Device describes functionality only available on mobile type Device interface { + // ScreenInsets returns the space around a mobile screen that should not be drawn used for interactive elements + ScreenInsets() (topLeft, bottomRight fyne.Size) + // Request that the mobile device show the touch screen keyboard (standard layout) ShowVirtualKeyboard() // Request that the mobile device show the touch screen keyboard (custom layout) diff --git a/internal/driver/glfw/canvas.go b/internal/driver/glfw/canvas.go index 9dd5f99dc9..27433f21f1 100644 --- a/internal/driver/glfw/canvas.go +++ b/internal/driver/glfw/canvas.go @@ -602,6 +602,7 @@ func newCanvas() *glCanvas { c.overlays = &overlayStack{ OverlayStack: internal.OverlayStack{ OnChange: c.overlayChanged, + Canvas: c, }, } diff --git a/internal/driver/gomobile/canvas.go b/internal/driver/gomobile/canvas.go index 205c097383..2a9b1c05a3 100644 --- a/internal/driver/gomobile/canvas.go +++ b/internal/driver/gomobile/canvas.go @@ -85,25 +85,16 @@ func (c *mobileCanvas) Refresh(obj fyne.CanvasObject) { } } -func (c *mobileCanvas) edgePadding() (topLeft, bottomRight fyne.Size) { - scale := fyne.CurrentDevice().SystemScaleForWindow(nil) // we don't need a window parameter on mobile - - dev, ok := fyne.CurrentDevice().(*device) - if !ok { - return fyne.NewSize(0, 0), fyne.NewSize(0, 0) // running in test mode - } - - return fyne.NewSize(int(float32(dev.insetLeft)/scale), int(float32(dev.insetTop)/scale)), - fyne.NewSize(int(float32(dev.insetRight)/scale), int(float32(dev.insetBottom)/scale)) -} - func (c *mobileCanvas) sizeContent(size fyne.Size) { if c.content == nil { // window may not be configured yet return } offset := fyne.NewPos(0, 0) - devicePadTopLeft, devicePadBottomRight := c.edgePadding() + devicePadTopLeft, devicePadBottomRight := fyne.Size{}, fyne.Size{} + if dev, ok := fyne.CurrentDevice().(mobile.Device); ok { // not present in testing + devicePadTopLeft, devicePadBottomRight = dev.ScreenInsets() + } if c.windowHead != nil { topHeight := c.windowHead.MinSize().Height @@ -519,7 +510,7 @@ func NewCanvas() fyne.Canvas { ret.lastTapDownPos = make(map[int]fyne.Position) ret.lastTapDown = make(map[int]time.Time) ret.minSizeCache = make(map[fyne.CanvasObject]fyne.Size) - ret.overlays = &internal.OverlayStack{} + ret.overlays = &internal.OverlayStack{Canvas: ret} ret.setupThemeListener() diff --git a/internal/driver/gomobile/device.go b/internal/driver/gomobile/device.go index 05a3a8a104..c2e48f770d 100644 --- a/internal/driver/gomobile/device.go +++ b/internal/driver/gomobile/device.go @@ -20,6 +20,18 @@ var ( // Declare conformity with Device var _ fyne.Device = (*device)(nil) +func (*device) ScreenInsets() (topLeft, bottomRight fyne.Size) { + scale := fyne.CurrentDevice().SystemScaleForWindow(nil) // we don't need a window parameter on mobile + + dev, ok := fyne.CurrentDevice().(*device) + if !ok { + return fyne.NewSize(0, 0), fyne.NewSize(0, 0) // running in test mode + } + + return fyne.NewSize(int(float32(dev.insetLeft)/scale), int(float32(dev.insetTop)/scale)), + fyne.NewSize(int(float32(dev.insetRight)/scale), int(float32(dev.insetBottom)/scale)) +} + func (*device) Orientation() fyne.DeviceOrientation { switch currentOrientation { case size.OrientationLandscape: diff --git a/internal/driver/gomobile/menu.go b/internal/driver/gomobile/menu.go index 512e715cfb..d7bcabf2db 100644 --- a/internal/driver/gomobile/menu.go +++ b/internal/driver/gomobile/menu.go @@ -59,7 +59,10 @@ func (c *mobileCanvas) showMenu(menu *fyne.MainMenu) { shadow := canvas.NewHorizontalGradient(theme.ShadowColor(), color.Transparent) c.menu = fyne.NewContainer(panel, shadow) - devicePadTopLeft, devicePadBottomRight := c.edgePadding() + devicePadTopLeft, devicePadBottomRight := fyne.Size{}, fyne.Size{} + if dev, ok := fyne.CurrentDevice().(*device); ok { // not present in testing + devicePadTopLeft, devicePadBottomRight = dev.ScreenInsets() + } padY := devicePadTopLeft.Height + devicePadBottomRight.Height panel.Move(fyne.NewPos(devicePadTopLeft.Width, devicePadTopLeft.Height)) panel.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), c.size.Height-padY)) diff --git a/internal/overlay_stack.go b/internal/overlay_stack.go index ea1f812f4c..9562504dc6 100644 --- a/internal/overlay_stack.go +++ b/internal/overlay_stack.go @@ -4,12 +4,15 @@ import ( "sync" "fyne.io/fyne" + "fyne.io/fyne/driver/mobile" "fyne.io/fyne/internal/app" + "fyne.io/fyne/internal/widget" ) // OverlayStack implements fyne.OverlayStack type OverlayStack struct { OnChange func() + Canvas fyne.Canvas focusManagers []*app.FocusManager overlays []fyne.CanvasObject propertyLock sync.RWMutex @@ -28,6 +31,20 @@ func (s *OverlayStack) Add(overlay fyne.CanvasObject) { return } s.overlays = append(s.overlays, overlay) + + devicePadTopLeft, devicePadBottomRight := fyne.Size{}, fyne.Size{} + if dev, ok := fyne.CurrentDevice().(mobile.Device); ok { // not present in testing + devicePadTopLeft, devicePadBottomRight = dev.ScreenInsets() + } + innerSize := s.Canvas.Size().Subtract(devicePadTopLeft).Subtract(devicePadBottomRight) + topLeft := fyne.NewPos(devicePadTopLeft.Width, devicePadTopLeft.Height) + + // TODO this should probably apply to all once #707 is addressed + if _, ok := overlay.(*widget.OverlayContainer); ok { + overlay.Resize(innerSize) + overlay.Move(topLeft) + } + s.focusManagers = append(s.focusManagers, app.NewFocusManager(overlay)) if s.OnChange != nil { s.OnChange() diff --git a/internal/overlay_stack_test.go b/internal/overlay_stack_test.go index 170472ef4a..d890d052e4 100644 --- a/internal/overlay_stack_test.go +++ b/internal/overlay_stack_test.go @@ -7,11 +7,12 @@ import ( "fyne.io/fyne" "fyne.io/fyne/internal" + "fyne.io/fyne/test" "fyne.io/fyne/widget" ) func TestOverlayStack(t *testing.T) { - s := &internal.OverlayStack{} + s := &internal.OverlayStack{Canvas: test.NewCanvas()} o1 := widget.NewLabel("A") o2 := widget.NewLabel("B") o3 := widget.NewLabel("C") diff --git a/test/testcanvas.go b/test/testcanvas.go index f5bdc8dd00..f1f5e7d035 100644 --- a/test/testcanvas.go +++ b/test/testcanvas.go @@ -55,13 +55,14 @@ func Canvas() fyne.Canvas { // NewCanvas returns a single use in-memory canvas used for testing func NewCanvas() WindowlessCanvas { - return &testCanvas{ + c := &testCanvas{ focusMgr: app.NewFocusManager(nil), - overlays: &internal.OverlayStack{}, padded: true, scale: 1.0, size: fyne.NewSize(10, 10), } + c.overlays = &internal.OverlayStack{Canvas: c} + return c } // NewCanvasWithPainter allows creation of an in-memory canvas with a specific painter. diff --git a/widget/menu.go b/widget/menu.go index de2f66a97b..20a5ff2416 100644 --- a/widget/menu.go +++ b/widget/menu.go @@ -3,6 +3,7 @@ package widget import ( "fyne.io/fyne" "fyne.io/fyne/canvas" + "fyne.io/fyne/driver/mobile" "fyne.io/fyne/internal/widget" "fyne.io/fyne/layout" "fyne.io/fyne/theme" @@ -160,7 +161,12 @@ func (r *menuRenderer) Layout(s fyne.Size) { scrollSize := boxSize if c := fyne.CurrentApp().Driver().CanvasForObject(r.m); c != nil { ap := fyne.CurrentApp().Driver().AbsolutePositionForObject(r.m) - if ah := c.Size().Height - ap.Y; ah < boxSize.Height { + bottomEdge := 0 + if dev, ok := fyne.CurrentDevice().(mobile.Device); ok { + _, bottomRight := dev.ScreenInsets() + bottomEdge = bottomRight.Height + } + if ah := c.Size().Height - bottomEdge - ap.Y; ah < boxSize.Height { scrollSize = fyne.NewSize(boxSize.Width, ah) } } From e1969d29222be5e790149181e3b7018f509d1d9f Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 12 Oct 2020 23:27:16 +0100 Subject: [PATCH 2/4] Move from ScreenInsets to ScreenInteractiveArea --- driver/mobile/device.go | 5 +++-- internal/driver/gomobile/canvas.go | 16 +++++++--------- internal/driver/gomobile/device.go | 15 ++++++++++----- internal/driver/gomobile/driver.go | 8 ++++---- internal/driver/gomobile/menu.go | 13 ++++++------- internal/overlay_stack.go | 10 ++++------ widget/menu.go | 4 ++-- 7 files changed, 36 insertions(+), 35 deletions(-) diff --git a/driver/mobile/device.go b/driver/mobile/device.go index 0201e785c6..4a355266cb 100644 --- a/driver/mobile/device.go +++ b/driver/mobile/device.go @@ -5,8 +5,9 @@ import "fyne.io/fyne" // Device describes functionality only available on mobile type Device interface { - // ScreenInsets returns the space around a mobile screen that should not be drawn used for interactive elements - ScreenInsets() (topLeft, bottomRight fyne.Size) + // ScreenInteractiveArea returns the position and size of the central interactive area. + // Operating system elements may overlap the portions outside this area. + ScreenInteractiveArea() (fyne.Position, fyne.Size) // Request that the mobile device show the touch screen keyboard (standard layout) ShowVirtualKeyboard() diff --git a/internal/driver/gomobile/canvas.go b/internal/driver/gomobile/canvas.go index 2a9b1c05a3..97e7818fd5 100644 --- a/internal/driver/gomobile/canvas.go +++ b/internal/driver/gomobile/canvas.go @@ -91,32 +91,30 @@ func (c *mobileCanvas) sizeContent(size fyne.Size) { } offset := fyne.NewPos(0, 0) - devicePadTopLeft, devicePadBottomRight := fyne.Size{}, fyne.Size{} + areaPos, areaSize := fyne.Position{}, size if dev, ok := fyne.CurrentDevice().(mobile.Device); ok { // not present in testing - devicePadTopLeft, devicePadBottomRight = dev.ScreenInsets() + areaPos, areaSize = dev.ScreenInteractiveArea() } if c.windowHead != nil { topHeight := c.windowHead.MinSize().Height if len(c.windowHead.(*widget.Box).Children) > 1 { - c.windowHead.Resize(fyne.NewSize(size.Width-devicePadTopLeft.Width-devicePadBottomRight.Width, topHeight)) + c.windowHead.Resize(fyne.NewSize(areaSize.Width, topHeight)) offset = fyne.NewPos(0, topHeight) } else { c.windowHead.Resize(c.windowHead.MinSize()) } - c.windowHead.Move(fyne.NewPos(devicePadTopLeft.Width, devicePadTopLeft.Height)) + c.windowHead.Move(areaPos) } - innerSize := size.Subtract(devicePadTopLeft).Subtract(devicePadBottomRight) - topLeft := offset.Add(fyne.NewPos(devicePadTopLeft.Width, devicePadTopLeft.Height)) - + topLeft := areaPos.Add(offset) c.size = size if c.padded { - c.content.Resize(innerSize.Subtract(fyne.NewSize(theme.Padding()*2, theme.Padding()*2))) + c.content.Resize(areaSize.Subtract(fyne.NewSize(theme.Padding()*2, theme.Padding()*2))) c.content.Move(topLeft.Add(fyne.NewPos(theme.Padding(), theme.Padding()))) } else { - c.content.Resize(innerSize) + c.content.Resize(areaSize) c.content.Move(topLeft) } } diff --git a/internal/driver/gomobile/device.go b/internal/driver/gomobile/device.go index c2e48f770d..3677d0a676 100644 --- a/internal/driver/gomobile/device.go +++ b/internal/driver/gomobile/device.go @@ -8,7 +8,7 @@ import ( ) type device struct { - insetTop, insetBottom, insetLeft, insetRight int + safeTop, safeLeft, safeWidth, safeHeight int } //lint:file-ignore U1000 Var currentDPI is used in other files, but not here @@ -20,16 +20,21 @@ var ( // Declare conformity with Device var _ fyne.Device = (*device)(nil) -func (*device) ScreenInsets() (topLeft, bottomRight fyne.Size) { +func (*device) ScreenInteractiveArea() (fyne.Position, fyne.Size) { scale := fyne.CurrentDevice().SystemScaleForWindow(nil) // we don't need a window parameter on mobile dev, ok := fyne.CurrentDevice().(*device) if !ok { - return fyne.NewSize(0, 0), fyne.NewSize(0, 0) // running in test mode + wins := fyne.CurrentApp().Driver().AllWindows() + size := fyne.Size{} + if len(wins) > 0 { + size = wins[0].Canvas().Size() + } + return fyne.NewPos(0, 0), size // running in test mode } - return fyne.NewSize(int(float32(dev.insetLeft)/scale), int(float32(dev.insetTop)/scale)), - fyne.NewSize(int(float32(dev.insetRight)/scale), int(float32(dev.insetBottom)/scale)) + return fyne.NewPos(int(float32(dev.safeLeft)/scale), int(float32(dev.safeTop)/scale)), + fyne.NewSize(int(float32(dev.safeWidth)/scale), int(float32(dev.safeHeight)/scale)) } func (*device) Orientation() fyne.DeviceOrientation { diff --git a/internal/driver/gomobile/driver.go b/internal/driver/gomobile/driver.go index c7c7b1dc28..fea8869b49 100644 --- a/internal/driver/gomobile/driver.go +++ b/internal/driver/gomobile/driver.go @@ -125,10 +125,10 @@ func (d *mobileDriver) Run() { currentDPI = e.PixelsPerPt * 72 dev := d.device - dev.insetTop = e.InsetTopPx - dev.insetBottom = e.InsetBottomPx - dev.insetLeft = e.InsetLeftPx - dev.insetRight = e.InsetRightPx + dev.safeTop = e.InsetTopPx + dev.safeLeft = e.InsetLeftPx + dev.safeHeight = e.HeightPx - e.InsetTopPx - e.InsetBottomPx + dev.safeWidth = e.WidthPx - e.InsetLeftPx - e.InsetRightPx canvas.SetScale(0) // value is ignored // make sure that we paint on the next frame diff --git a/internal/driver/gomobile/menu.go b/internal/driver/gomobile/menu.go index d7bcabf2db..87ee432d04 100644 --- a/internal/driver/gomobile/menu.go +++ b/internal/driver/gomobile/menu.go @@ -59,15 +59,14 @@ func (c *mobileCanvas) showMenu(menu *fyne.MainMenu) { shadow := canvas.NewHorizontalGradient(theme.ShadowColor(), color.Transparent) c.menu = fyne.NewContainer(panel, shadow) - devicePadTopLeft, devicePadBottomRight := fyne.Size{}, fyne.Size{} + safePos, safeSize := fyne.Position{}, c.size if dev, ok := fyne.CurrentDevice().(*device); ok { // not present in testing - devicePadTopLeft, devicePadBottomRight = dev.ScreenInsets() + safePos, safeSize = dev.ScreenInteractiveArea() } - padY := devicePadTopLeft.Height + devicePadBottomRight.Height - panel.Move(fyne.NewPos(devicePadTopLeft.Width, devicePadTopLeft.Height)) - panel.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), c.size.Height-padY)) - shadow.Resize(fyne.NewSize(theme.Padding()/2, c.size.Height-padY)) - shadow.Move(fyne.NewPos(panel.Size().Width+devicePadTopLeft.Width, devicePadTopLeft.Height)) + panel.Move(safePos) + panel.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), safeSize.Height)) + shadow.Resize(fyne.NewSize(theme.Padding()/2, safeSize.Height)) + shadow.Move(fyne.NewPos(panel.Size().Width+safePos.X, safePos.Y)) } func (d *mobileDriver) findMenu(win *window) *fyne.MainMenu { diff --git a/internal/overlay_stack.go b/internal/overlay_stack.go index 9562504dc6..7ed81de3e5 100644 --- a/internal/overlay_stack.go +++ b/internal/overlay_stack.go @@ -32,17 +32,15 @@ func (s *OverlayStack) Add(overlay fyne.CanvasObject) { } s.overlays = append(s.overlays, overlay) - devicePadTopLeft, devicePadBottomRight := fyne.Size{}, fyne.Size{} + safePos, safeSize := fyne.Position{}, s.Canvas.Size() if dev, ok := fyne.CurrentDevice().(mobile.Device); ok { // not present in testing - devicePadTopLeft, devicePadBottomRight = dev.ScreenInsets() + safePos, safeSize = dev.ScreenInteractiveArea() } - innerSize := s.Canvas.Size().Subtract(devicePadTopLeft).Subtract(devicePadBottomRight) - topLeft := fyne.NewPos(devicePadTopLeft.Width, devicePadTopLeft.Height) // TODO this should probably apply to all once #707 is addressed if _, ok := overlay.(*widget.OverlayContainer); ok { - overlay.Resize(innerSize) - overlay.Move(topLeft) + overlay.Resize(safeSize) + overlay.Move(safePos) } s.focusManagers = append(s.focusManagers, app.NewFocusManager(overlay)) diff --git a/widget/menu.go b/widget/menu.go index 20a5ff2416..0f4b18cd94 100644 --- a/widget/menu.go +++ b/widget/menu.go @@ -163,8 +163,8 @@ func (r *menuRenderer) Layout(s fyne.Size) { ap := fyne.CurrentApp().Driver().AbsolutePositionForObject(r.m) bottomEdge := 0 if dev, ok := fyne.CurrentDevice().(mobile.Device); ok { - _, bottomRight := dev.ScreenInsets() - bottomEdge = bottomRight.Height + pos, size := dev.ScreenInteractiveArea() + bottomEdge = c.Size().Height - pos.Y - size.Height } if ah := c.Size().Height - bottomEdge - ap.Y; ah < boxSize.Height { scrollSize = fyne.NewSize(boxSize.Width, ah) From c5ddf5bbee7e55fa74525b99e4aa1c692f2c1b26 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 13 Oct 2020 20:52:41 +0100 Subject: [PATCH 3/4] Move mobile.Device.ScreeenInteractiveArea to Canvas.InteractiveArea Makes sense, and is fairly neat except a little complex driver test code --- canvas.go | 4 ++++ driver/mobile/device.go | 6 ------ internal/driver/glfw/canvas.go | 4 ++++ internal/driver/gomobile/canvas.go | 21 +++++++++++++++------ internal/driver/gomobile/device.go | 17 ----------------- internal/driver/gomobile/menu.go | 5 +---- internal/overlay_stack.go | 8 ++------ test/testcanvas.go | 4 ++++ widget/menu.go | 10 +++------- 9 files changed, 33 insertions(+), 46 deletions(-) diff --git a/canvas.go b/canvas.go index 1e5035700e..3b35bb2392 100644 --- a/canvas.go +++ b/canvas.go @@ -53,4 +53,8 @@ type Canvas interface { // PixelCoordinateForPosition returns the x and y pixel coordinate for a given position on this canvas. // This can be used to find absolute pixel positions or pixel offsets relative to an object top left. PixelCoordinateForPosition(Position) (int, int) + + // InteractiveArea returns the position and size of the central interactive area. + // Operating system elements may overlap the portions outside this area and widgets should avoid being outside. + InteractiveArea() (Position, Size) } diff --git a/driver/mobile/device.go b/driver/mobile/device.go index 4a355266cb..44446286f5 100644 --- a/driver/mobile/device.go +++ b/driver/mobile/device.go @@ -1,14 +1,8 @@ // Package mobile provides mobile specific driver functionality. package mobile -import "fyne.io/fyne" - // Device describes functionality only available on mobile type Device interface { - // ScreenInteractiveArea returns the position and size of the central interactive area. - // Operating system elements may overlap the portions outside this area. - ScreenInteractiveArea() (fyne.Position, fyne.Size) - // Request that the mobile device show the touch screen keyboard (standard layout) ShowVirtualKeyboard() // Request that the mobile device show the touch screen keyboard (custom layout) diff --git a/internal/driver/glfw/canvas.go b/internal/driver/glfw/canvas.go index 27433f21f1..12369e93e5 100644 --- a/internal/driver/glfw/canvas.go +++ b/internal/driver/glfw/canvas.go @@ -88,6 +88,10 @@ func (c *glCanvas) FocusPrevious() { c.focusManager().FocusPrevious() } +func (c *glCanvas) InteractiveArea() (fyne.Position, fyne.Size) { + return fyne.Position{}, c.Size() +} + func (c *glCanvas) MinSize() fyne.Size { c.RLock() defer c.RUnlock() diff --git a/internal/driver/gomobile/canvas.go b/internal/driver/gomobile/canvas.go index 97e7818fd5..d99453d74a 100644 --- a/internal/driver/gomobile/canvas.go +++ b/internal/driver/gomobile/canvas.go @@ -53,10 +53,22 @@ func (c *mobileCanvas) Content() fyne.CanvasObject { return c.content } +func (c *mobileCanvas) InteractiveArea() (fyne.Position, fyne.Size) { + scale := fyne.CurrentDevice().SystemScaleForWindow(nil) // we don't need a window parameter on mobile + + dev, ok := fyne.CurrentDevice().(*device) + if !ok || dev.safeWidth == 0 || dev.safeHeight == 0 { + return fyne.NewPos(0, 0), c.Size() // running in test mode + } + + return fyne.NewPos(int(float32(dev.safeLeft)/scale), int(float32(dev.safeTop)/scale)), + fyne.NewSize(int(float32(dev.safeWidth)/scale), int(float32(dev.safeHeight)/scale)) +} + func (c *mobileCanvas) SetContent(content fyne.CanvasObject) { c.content = content - c.sizeContent(c.Size().Union(content.MinSize())) + c.sizeContent(c.Size().Max(content.MinSize())) } // Deprecated: Use Overlays() instead. @@ -89,12 +101,10 @@ func (c *mobileCanvas) sizeContent(size fyne.Size) { if c.content == nil { // window may not be configured yet return } + c.size = size offset := fyne.NewPos(0, 0) - areaPos, areaSize := fyne.Position{}, size - if dev, ok := fyne.CurrentDevice().(mobile.Device); ok { // not present in testing - areaPos, areaSize = dev.ScreenInteractiveArea() - } + areaPos, areaSize := c.InteractiveArea() if c.windowHead != nil { topHeight := c.windowHead.MinSize().Height @@ -109,7 +119,6 @@ func (c *mobileCanvas) sizeContent(size fyne.Size) { } topLeft := areaPos.Add(offset) - c.size = size if c.padded { c.content.Resize(areaSize.Subtract(fyne.NewSize(theme.Padding()*2, theme.Padding()*2))) c.content.Move(topLeft.Add(fyne.NewPos(theme.Padding(), theme.Padding()))) diff --git a/internal/driver/gomobile/device.go b/internal/driver/gomobile/device.go index 3677d0a676..15e2962876 100644 --- a/internal/driver/gomobile/device.go +++ b/internal/driver/gomobile/device.go @@ -20,23 +20,6 @@ var ( // Declare conformity with Device var _ fyne.Device = (*device)(nil) -func (*device) ScreenInteractiveArea() (fyne.Position, fyne.Size) { - scale := fyne.CurrentDevice().SystemScaleForWindow(nil) // we don't need a window parameter on mobile - - dev, ok := fyne.CurrentDevice().(*device) - if !ok { - wins := fyne.CurrentApp().Driver().AllWindows() - size := fyne.Size{} - if len(wins) > 0 { - size = wins[0].Canvas().Size() - } - return fyne.NewPos(0, 0), size // running in test mode - } - - return fyne.NewPos(int(float32(dev.safeLeft)/scale), int(float32(dev.safeTop)/scale)), - fyne.NewSize(int(float32(dev.safeWidth)/scale), int(float32(dev.safeHeight)/scale)) -} - func (*device) Orientation() fyne.DeviceOrientation { switch currentOrientation { case size.OrientationLandscape: diff --git a/internal/driver/gomobile/menu.go b/internal/driver/gomobile/menu.go index 87ee432d04..72322bfb81 100644 --- a/internal/driver/gomobile/menu.go +++ b/internal/driver/gomobile/menu.go @@ -59,10 +59,7 @@ func (c *mobileCanvas) showMenu(menu *fyne.MainMenu) { shadow := canvas.NewHorizontalGradient(theme.ShadowColor(), color.Transparent) c.menu = fyne.NewContainer(panel, shadow) - safePos, safeSize := fyne.Position{}, c.size - if dev, ok := fyne.CurrentDevice().(*device); ok { // not present in testing - safePos, safeSize = dev.ScreenInteractiveArea() - } + safePos, safeSize := c.InteractiveArea() panel.Move(safePos) panel.Resize(fyne.NewSize(panel.MinSize().Width+theme.Padding(), safeSize.Height)) shadow.Resize(fyne.NewSize(theme.Padding()/2, safeSize.Height)) diff --git a/internal/overlay_stack.go b/internal/overlay_stack.go index 7ed81de3e5..925fe8ea13 100644 --- a/internal/overlay_stack.go +++ b/internal/overlay_stack.go @@ -4,7 +4,6 @@ import ( "sync" "fyne.io/fyne" - "fyne.io/fyne/driver/mobile" "fyne.io/fyne/internal/app" "fyne.io/fyne/internal/widget" ) @@ -32,13 +31,10 @@ func (s *OverlayStack) Add(overlay fyne.CanvasObject) { } s.overlays = append(s.overlays, overlay) - safePos, safeSize := fyne.Position{}, s.Canvas.Size() - if dev, ok := fyne.CurrentDevice().(mobile.Device); ok { // not present in testing - safePos, safeSize = dev.ScreenInteractiveArea() - } - // TODO this should probably apply to all once #707 is addressed if _, ok := overlay.(*widget.OverlayContainer); ok { + safePos, safeSize := s.Canvas.InteractiveArea() + overlay.Resize(safeSize) overlay.Move(safePos) } diff --git a/test/testcanvas.go b/test/testcanvas.go index f1f5e7d035..b48a18bb2e 100644 --- a/test/testcanvas.go +++ b/test/testcanvas.go @@ -102,6 +102,10 @@ func (c *testCanvas) Focused() fyne.Focusable { return c.focusManager().Focused() } +func (c *testCanvas) InteractiveArea() (fyne.Position, fyne.Size) { + return fyne.Position{}, c.Size() +} + func (c *testCanvas) OnTypedKey() func(*fyne.KeyEvent) { c.propertyLock.RLock() defer c.propertyLock.RUnlock() diff --git a/widget/menu.go b/widget/menu.go index 0f4b18cd94..a782b6e5c5 100644 --- a/widget/menu.go +++ b/widget/menu.go @@ -3,7 +3,6 @@ package widget import ( "fyne.io/fyne" "fyne.io/fyne/canvas" - "fyne.io/fyne/driver/mobile" "fyne.io/fyne/internal/widget" "fyne.io/fyne/layout" "fyne.io/fyne/theme" @@ -161,12 +160,9 @@ func (r *menuRenderer) Layout(s fyne.Size) { scrollSize := boxSize if c := fyne.CurrentApp().Driver().CanvasForObject(r.m); c != nil { ap := fyne.CurrentApp().Driver().AbsolutePositionForObject(r.m) - bottomEdge := 0 - if dev, ok := fyne.CurrentDevice().(mobile.Device); ok { - pos, size := dev.ScreenInteractiveArea() - bottomEdge = c.Size().Height - pos.Y - size.Height - } - if ah := c.Size().Height - bottomEdge - ap.Y; ah < boxSize.Height { + pos, size := c.InteractiveArea() + bottomPad := c.Size().Height - pos.Y - size.Height + if ah := c.Size().Height - bottomPad - ap.Y; ah < boxSize.Height { scrollSize = fyne.NewSize(boxSize.Width, ah) } } From 16e40b204147dc02ce27ffcb2afa3c1a15ce1a98 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 13 Oct 2020 21:01:31 +0100 Subject: [PATCH 4/4] Fix bad merge --- internal/driver/gomobile/canvas.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/driver/gomobile/canvas.go b/internal/driver/gomobile/canvas.go index 41d7768878..0642d0d7ec 100644 --- a/internal/driver/gomobile/canvas.go +++ b/internal/driver/gomobile/canvas.go @@ -123,10 +123,10 @@ func (c *mobileCanvas) sizeContent(size fyne.Size) { if p, ok := overlay.(*widget.PopUp); ok { // TODO: remove this when #707 is being addressed. // “Notifies” the PopUp of the canvas size change. - size := p.Content.Size().Add(fyne.NewSize(theme.Padding()*2, theme.Padding()*2)).Min(innerSize) + size := p.Content.Size().Add(fyne.NewSize(theme.Padding()*2, theme.Padding()*2)).Min(areaSize) p.Resize(size) } else { - overlay.Resize(innerSize) + overlay.Resize(areaSize) overlay.Move(topLeft) } }