From 1c741ceec5af72a6f69ca60270fc9fd0cb0c300f Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 3 Sep 2023 21:40:31 +0100 Subject: [PATCH 001/248] Stop using deprecated theme, improve docs Fixes #4208 --- cmd/fyne_demo/main.go | 4 ++-- cmd/fyne_demo/theme.go | 17 +++++++++++++++++ theme/theme.go | 2 ++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 cmd/fyne_demo/theme.go diff --git a/cmd/fyne_demo/main.go b/cmd/fyne_demo/main.go index ab7536024c..4c91df8dac 100644 --- a/cmd/fyne_demo/main.go +++ b/cmd/fyne_demo/main.go @@ -238,10 +238,10 @@ func makeNav(setTutorial func(tutorial tutorials.Tutorial), loadPrevious bool) f themes := container.NewGridWithColumns(2, widget.NewButton("Dark", func() { - a.Settings().SetTheme(theme.DarkTheme()) + a.Settings().SetTheme(&forceVariantTheme{Theme: theme.DefaultTheme(), variant: theme.VariantDark}) }), widget.NewButton("Light", func() { - a.Settings().SetTheme(theme.LightTheme()) + a.Settings().SetTheme(&forceVariantTheme{Theme: theme.DefaultTheme(), variant: theme.VariantLight}) }), ) diff --git a/cmd/fyne_demo/theme.go b/cmd/fyne_demo/theme.go new file mode 100644 index 0000000000..30ca28e0af --- /dev/null +++ b/cmd/fyne_demo/theme.go @@ -0,0 +1,17 @@ +package main + +import ( + "image/color" + + "fyne.io/fyne/v2" +) + +type forceVariantTheme struct { + fyne.Theme + + variant fyne.ThemeVariant +} + +func (f *forceVariantTheme) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color { + return f.Theme.Color(name, f.variant) +} diff --git a/theme/theme.go b/theme/theme.go index 0d7af723b9..933e125525 100644 --- a/theme/theme.go +++ b/theme/theme.go @@ -27,6 +27,7 @@ const ( // DarkTheme defines the built-in dark theme colors and sizes. // // Deprecated: This method ignores user preference and should not be used, it will be removed in v3.0. +// If developers want to ignore user preference for theme variant they can set a custom theme. func DarkTheme() fyne.Theme { theme := &builtinTheme{variant: VariantDark} @@ -48,6 +49,7 @@ func DefaultTheme() fyne.Theme { // LightTheme defines the built-in light theme colors and sizes. // // Deprecated: This method ignores user preference and should not be used, it will be removed in v3.0. +// If developers want to ignore user preference for theme variant they can set a custom theme. func LightTheme() fyne.Theme { theme := &builtinTheme{variant: VariantLight} From 6b2b8a24b1af21d02c3ec901b701d990423d7738 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 3 Sep 2023 21:46:26 +0100 Subject: [PATCH 002/248] And a test for the force variant theme --- cmd/fyne_demo/theme_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 cmd/fyne_demo/theme_test.go diff --git a/cmd/fyne_demo/theme_test.go b/cmd/fyne_demo/theme_test.go new file mode 100644 index 0000000000..9702db2407 --- /dev/null +++ b/cmd/fyne_demo/theme_test.go @@ -0,0 +1,18 @@ +package main + +import ( + "testing" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/theme" + "github.com/stretchr/testify/assert" +) + +func TestForceVariantTheme_Color(t *testing.T) { + dark := &forceVariantTheme{Theme: theme.DefaultTheme(), variant: theme.VariantDark} + light := &forceVariantTheme{Theme: theme.DefaultTheme(), variant: theme.VariantLight} + unspecified := fyne.ThemeVariant(99) + + assert.Equal(t, theme.DefaultTheme().Color(theme.ColorNameForeground, theme.VariantDark), dark.Color(theme.ColorNameForeground, unspecified)) + assert.Equal(t, theme.DefaultTheme().Color(theme.ColorNameForeground, theme.VariantLight), light.Color(theme.ColorNameForeground, unspecified)) +} From 724db0a12ddef05a3e99fb3f79cecc9f2fdf3675 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 4 Sep 2023 15:53:28 +0100 Subject: [PATCH 003/248] Updating README following release Various fixes too --- README.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 99d2f0cdc0..a7e456a083 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

Go API Reference Latest Release - Join us on Slack + Join us on Slack
Code Status Build Status @@ -14,22 +14,22 @@ It is designed to build applications that run on desktop and mobile devices with a single codebase. -Version 2.3 is the current release of the Fyne API, it added a refined theme design, -cloud storage, improved text handling for international languages and many +Version 2.4 is the current release of the Fyne API, it added rounded corners, emoji, +layout debug support and table headers, along with a large number of smaller feature additions. We are now working towards the next big release, codenamed -[Dalwhinnie](https://github.com/fyne-io/fyne/milestone/18) +[Elgin](https://github.com/fyne-io/fyne/milestone/21) and more news will follow in our news feeds and GitHub project. # Prerequisites -To develop apps using Fyne you will need Go version 1.14 or later, a C compiler and your system's development tools. +To develop apps using Fyne you will need Go version 1.17 or later, a C compiler and your system's development tools. If you're not sure if that's all installed or you don't know how then check out our [Getting Started](https://fyne.io/develop/) document. Using the standard go tools you can install Fyne's core library using: - go get fyne.io/fyne/v2 + go get fyne.io/fyne/v2@latest After importing a new module, run the following command before compiling the code for the first time. Avoid running it before writing code that uses the module to prevent accidental removal of dependencies: @@ -45,19 +45,19 @@ To run a showcase of the features of Fyne execute the following: And you should see something like this (after you click a few buttons):

- Fyne Demo Dark Theme + Fyne Demo Dark Theme

Or if you are using the light theme:

- Fyne Demo Light Theme + Fyne Demo Light Theme

And even running on a mobile device:

- Fyne Demo Mobile Light Theme + Fyne Demo Mobile Light Theme

# Getting Started @@ -102,16 +102,13 @@ It should look like this:
- Fyne Hello Dark Theme + Fyne Hello Dark Theme - Fyne Hello Dark Theme + Fyne Hello Dark Theme
-> Note that Windows applications load from a command prompt by default, which means if you click an icon you may see a command window. -> To fix this add the parameters `-ldflags -H=windowsgui` to your run or build commands. - ## Run in mobile simulation There is a helpful mobile simulation mode that gives a hint of how your app would work on a mobile device: @@ -186,4 +183,6 @@ These are optional applications but can help to create a more complete desktop e ## FyneDesk (Linux / BSD) -To go all the way with Fyne on your desktop / laptop computer you could install [FyneDesk](https://github.com/fyne-io/fynedesk) as well :) +To go all the way with Fyne on your desktop / laptop computer you could install [FyneDesk](https://github.com/fyshos/fynedesk) as well :) + +![FyneDesk screenshopt in dark mode](https://fyshos.com/img/desktop.png) From be9cd4b67990836a8d9f518b0c3b5a59b1f0349e Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sat, 9 Sep 2023 11:32:21 +0100 Subject: [PATCH 004/248] Update the version number --- cmd/fyne_demo/FyneApp.toml | 2 +- cmd/hello/FyneApp.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/fyne_demo/FyneApp.toml b/cmd/fyne_demo/FyneApp.toml index 6300dc49aa..eb3cd500c0 100644 --- a/cmd/fyne_demo/FyneApp.toml +++ b/cmd/fyne_demo/FyneApp.toml @@ -2,7 +2,7 @@ Icon = "../../theme/icons/fyne.png" Name = "Fyne Demo" ID = "io.fyne.demo" - Version = "2.3.0" + Version = "2.4.0" Build = 11 [Development] diff --git a/cmd/hello/FyneApp.toml b/cmd/hello/FyneApp.toml index d59c3ed642..12bf58730b 100644 --- a/cmd/hello/FyneApp.toml +++ b/cmd/hello/FyneApp.toml @@ -2,5 +2,5 @@ Icon = "../../theme/icons/fyne.png" Name = "Fyne Hello" ID = "io.fyne.hello" - Version = "2.3.0" + Version = "2.4.0" Build = 2 From ccc6a1c19a6d16988da3e468f08f25d8100cd4b4 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 9 Oct 2023 12:16:43 +0100 Subject: [PATCH 005/248] Revise reledase date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f4488539..399fb48b24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). -## 2.4.1 - 8 October 2023 +## 2.4.1 - 9 October 2023 ### Fixed From 848a78ebf9bdf4c80a65997d6343ef70f56b7a41 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 15 Oct 2023 13:33:21 -0700 Subject: [PATCH 006/248] resize underline and focus rectangles, track X position of tap and hover --- widget/hyperlink.go | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/widget/hyperlink.go b/widget/hyperlink.go index 6f424f50ff..dac2fdbe69 100644 --- a/widget/hyperlink.go +++ b/widget/hyperlink.go @@ -28,6 +28,7 @@ type Hyperlink struct { // Since: 2.2 OnTapped func() `json:"-"` + textWidth float32 // updated in syncSegments focused, hovered bool provider *RichText } @@ -67,7 +68,10 @@ func (hl *Hyperlink) CreateRenderer() fyne.WidgetRenderer { // Cursor returns the cursor type of this widget func (hl *Hyperlink) Cursor() desktop.Cursor { - return desktop.PointerCursor + if hl.hovered { + return desktop.PointerCursor + } + return desktop.DefaultCursor } // FocusGained is a hook called by the focus handling logic after this object gained the focus. @@ -83,13 +87,18 @@ func (hl *Hyperlink) FocusLost() { } // MouseIn is a hook that is called if the mouse pointer enters the element. -func (hl *Hyperlink) MouseIn(*desktop.MouseEvent) { - hl.hovered = true +func (hl *Hyperlink) MouseIn(e *desktop.MouseEvent) { + hl.hovered = hl.isPosOverText(e.Position) hl.BaseWidget.Refresh() } // MouseMoved is a hook that is called if the mouse pointer moved over the element. -func (hl *Hyperlink) MouseMoved(*desktop.MouseEvent) { +func (hl *Hyperlink) MouseMoved(e *desktop.MouseEvent) { + oldHovered := hl.hovered + hl.hovered = hl.isPosOverText(e.Position) + if hl.hovered != oldHovered { + hl.BaseWidget.Refresh() + } } // MouseOut is a hook that is called if the mouse pointer leaves the element. @@ -98,6 +107,10 @@ func (hl *Hyperlink) MouseOut() { hl.BaseWidget.Refresh() } +func (hl *Hyperlink) isPosOverText(pos fyne.Position) bool { + return pos.X <= hl.textWidth+theme.Padding()*2 +} + // Refresh triggers a redraw of the hyperlink. // // Implements: fyne.Widget @@ -156,12 +169,18 @@ func (hl *Hyperlink) SetURLFromString(str string) error { } // Tapped is called when a pointer tapped event is captured and triggers any change handler -func (hl *Hyperlink) Tapped(*fyne.PointEvent) { +func (hl *Hyperlink) Tapped(e *fyne.PointEvent) { + if !hl.isPosOverText(e.Position) { + return + } + hl.invokeAction() +} + +func (hl *Hyperlink) invokeAction() { if hl.OnTapped != nil { hl.OnTapped() return } - hl.openURL() } @@ -172,7 +191,7 @@ func (hl *Hyperlink) TypedRune(rune) { // TypedKey is a hook called by the input handling logic on key events if this object is focused. func (hl *Hyperlink) TypedKey(ev *fyne.KeyEvent) { if ev.Name == fyne.KeySpace { - hl.Tapped(nil) + hl.invokeAction() } } @@ -196,6 +215,7 @@ func (hl *Hyperlink) syncSegments() { }, Text: hl.Text, }} + hl.textWidth = fyne.MeasureText(hl.Text, theme.TextSize(), hl.TextStyle).Width } var _ fyne.WidgetRenderer = (*hyperlinkRenderer)(nil) @@ -212,11 +232,13 @@ func (r *hyperlinkRenderer) Destroy() { } func (r *hyperlinkRenderer) Layout(s fyne.Size) { + innerPad := theme.InnerPadding() r.hl.provider.Resize(s) - r.focus.Move(fyne.NewPos(theme.InnerPadding()/2, theme.InnerPadding()/2)) - r.focus.Resize(fyne.NewSize(s.Width-theme.InnerPadding(), s.Height-theme.InnerPadding())) - r.under.Move(fyne.NewPos(theme.InnerPadding(), s.Height-theme.InnerPadding())) - r.under.Resize(fyne.NewSize(s.Width-theme.InnerPadding()*2, 1)) + r.focus.Move(fyne.NewPos(innerPad/2, innerPad/2)) + w := fyne.Min(s.Width, r.hl.textWidth+innerPad+theme.Padding()*2) + r.focus.Resize(fyne.NewSize(w-innerPad, s.Height-innerPad)) + r.under.Move(fyne.NewPos(innerPad, s.Height-innerPad)) + r.under.Resize(fyne.NewSize(w-innerPad*2, 1)) } func (r *hyperlinkRenderer) MinSize() fyne.Size { From f7c6b334a224baa7efedcc6128629c8ba76e3113 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 15 Oct 2023 14:29:07 -0700 Subject: [PATCH 007/248] account for Y position as well and fix calculations --- widget/hyperlink.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/widget/hyperlink.go b/widget/hyperlink.go index dac2fdbe69..880c813564 100644 --- a/widget/hyperlink.go +++ b/widget/hyperlink.go @@ -28,7 +28,7 @@ type Hyperlink struct { // Since: 2.2 OnTapped func() `json:"-"` - textWidth float32 // updated in syncSegments + textSize fyne.Size // updated in syncSegments focused, hovered bool provider *RichText } @@ -108,7 +108,10 @@ func (hl *Hyperlink) MouseOut() { } func (hl *Hyperlink) isPosOverText(pos fyne.Position) bool { - return pos.X <= hl.textWidth+theme.Padding()*2 + innerPad := theme.InnerPadding() + pad := theme.Padding() + return pos.X >= innerPad/2 && pos.X <= hl.textSize.Width+pad*2+innerPad/2 && + pos.Y >= innerPad/2 && pos.Y <= hl.textSize.Height+pad*2+innerPad/2 } // Refresh triggers a redraw of the hyperlink. @@ -215,7 +218,7 @@ func (hl *Hyperlink) syncSegments() { }, Text: hl.Text, }} - hl.textWidth = fyne.MeasureText(hl.Text, theme.TextSize(), hl.TextStyle).Width + hl.textSize = fyne.MeasureText(hl.Text, theme.TextSize(), hl.TextStyle) } var _ fyne.WidgetRenderer = (*hyperlinkRenderer)(nil) @@ -235,9 +238,9 @@ func (r *hyperlinkRenderer) Layout(s fyne.Size) { innerPad := theme.InnerPadding() r.hl.provider.Resize(s) r.focus.Move(fyne.NewPos(innerPad/2, innerPad/2)) - w := fyne.Min(s.Width, r.hl.textWidth+innerPad+theme.Padding()*2) - r.focus.Resize(fyne.NewSize(w-innerPad, s.Height-innerPad)) - r.under.Move(fyne.NewPos(innerPad, s.Height-innerPad)) + w := fyne.Min(s.Width, r.hl.textSize.Width+innerPad+theme.Padding()*2) + r.focus.Resize(fyne.NewSize(w-innerPad, r.hl.textSize.Height+innerPad)) + r.under.Move(fyne.NewPos(innerPad, r.hl.textSize.Height+theme.Padding()*2)) r.under.Resize(fyne.NewSize(w-innerPad*2, 1)) } From 4e5663269a2598db5ab6052a52838a378765adb1 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Mon, 16 Oct 2023 09:24:16 -0700 Subject: [PATCH 008/248] handle word wrapping --- widget/hyperlink.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/widget/hyperlink.go b/widget/hyperlink.go index 880c813564..6fa8df1558 100644 --- a/widget/hyperlink.go +++ b/widget/hyperlink.go @@ -110,8 +110,9 @@ func (hl *Hyperlink) MouseOut() { func (hl *Hyperlink) isPosOverText(pos fyne.Position) bool { innerPad := theme.InnerPadding() pad := theme.Padding() + lineCount := float32(len(hl.provider.rowBounds)) return pos.X >= innerPad/2 && pos.X <= hl.textSize.Width+pad*2+innerPad/2 && - pos.Y >= innerPad/2 && pos.Y <= hl.textSize.Height+pad*2+innerPad/2 + pos.Y >= innerPad/2 && pos.Y <= hl.textSize.Height*lineCount+pad*2+innerPad/2 } // Refresh triggers a redraw of the hyperlink. @@ -235,12 +236,13 @@ func (r *hyperlinkRenderer) Destroy() { } func (r *hyperlinkRenderer) Layout(s fyne.Size) { - innerPad := theme.InnerPadding() r.hl.provider.Resize(s) + innerPad := theme.InnerPadding() + lineCount := float32(len(r.hl.provider.rowBounds)) r.focus.Move(fyne.NewPos(innerPad/2, innerPad/2)) w := fyne.Min(s.Width, r.hl.textSize.Width+innerPad+theme.Padding()*2) - r.focus.Resize(fyne.NewSize(w-innerPad, r.hl.textSize.Height+innerPad)) - r.under.Move(fyne.NewPos(innerPad, r.hl.textSize.Height+theme.Padding()*2)) + r.focus.Resize(fyne.NewSize(w-innerPad, r.hl.textSize.Height*lineCount+innerPad)) + r.under.Move(fyne.NewPos(innerPad, r.hl.textSize.Height*lineCount+theme.Padding()*2)) r.under.Resize(fyne.NewSize(w-innerPad*2, 1)) } From 2d520b7021819670d3710d2a0c58c115dab80a2c Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Mon, 16 Oct 2023 09:43:12 -0700 Subject: [PATCH 009/248] fix unit tests --- widget/hyperlink.go | 10 ++++++++-- widget/hyperlink_test.go | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/widget/hyperlink.go b/widget/hyperlink.go index 6fa8df1558..073bfbec90 100644 --- a/widget/hyperlink.go +++ b/widget/hyperlink.go @@ -110,7 +110,11 @@ func (hl *Hyperlink) MouseOut() { func (hl *Hyperlink) isPosOverText(pos fyne.Position) bool { innerPad := theme.InnerPadding() pad := theme.Padding() - lineCount := float32(len(hl.provider.rowBounds)) + // If not rendered yet provider will be nil + lineCount := float32(1) + if hl.provider != nil { + lineCount = fyne.Max(lineCount, float32(len(hl.provider.rowBounds))) + } return pos.X >= innerPad/2 && pos.X <= hl.textSize.Width+pad*2+innerPad/2 && pos.Y >= innerPad/2 && pos.Y <= hl.textSize.Height*lineCount+pad*2+innerPad/2 } @@ -174,7 +178,9 @@ func (hl *Hyperlink) SetURLFromString(str string) error { // Tapped is called when a pointer tapped event is captured and triggers any change handler func (hl *Hyperlink) Tapped(e *fyne.PointEvent) { - if !hl.isPosOverText(e.Position) { + // If not rendered yet (hl.provider == nil), register all taps + // in practice this probably only happens in our unit tests + if hl.provider != nil && !hl.isPosOverText(e.Position) { return } hl.invokeAction() diff --git a/widget/hyperlink_test.go b/widget/hyperlink_test.go index 29dc6e31fb..59f52506d3 100644 --- a/widget/hyperlink_test.go +++ b/widget/hyperlink_test.go @@ -39,6 +39,9 @@ func TestHyperlink_Cursor(t *testing.T) { hyperlink := NewHyperlink("Test", u) assert.Nil(t, err) + assert.Equal(t, desktop.DefaultCursor, hyperlink.Cursor()) + + hyperlink.hovered = true assert.Equal(t, desktop.PointerCursor, hyperlink.Cursor()) } From 9d9daaf6dc5f6c8ae2994fe12cb664caed93e53b Mon Sep 17 00:00:00 2001 From: Jacalz Date: Mon, 4 Sep 2023 20:26:20 +0200 Subject: [PATCH 010/248] Add back dummy variable but without a name Fixes #4216 --- widget/richtext_objects.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/widget/richtext_objects.go b/widget/richtext_objects.go index 7f01555a61..64a599f3ff 100644 --- a/widget/richtext_objects.go +++ b/widget/richtext_objects.go @@ -321,7 +321,9 @@ func (p *ParagraphSegment) Unselect() { // SeparatorSegment includes a horizontal separator in a rich text widget. // // Since: 2.1 -type SeparatorSegment struct{} +type SeparatorSegment struct { + _ bool // Without this a pointer to SeparatorSegment will always be the same. +} // Inline returns false as a separator should be full width. func (s *SeparatorSegment) Inline() bool { From 9f7f2fd4a1cb33de1834124a445920953186d6eb Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Tue, 17 Oct 2023 09:25:45 -0700 Subject: [PATCH 011/248] Fix bug in Box layout causing extra padding with hidden objects --- layout/boxlayout.go | 22 +++++++++++++++------- layout/boxlayout_test.go | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/layout/boxlayout.go b/layout/boxlayout.go index 38ae43c758..248505b745 100644 --- a/layout/boxlayout.go +++ b/layout/boxlayout.go @@ -51,16 +51,20 @@ func (g *boxLayout) isSpacer(obj fyne.CanvasObject) bool { // Any spacers added will pad the view, sharing the space if there are two or more. func (g *boxLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { spacers := 0 + visibleObjects := 0 + // Size taken up by visible objects total := float32(0) + for _, child := range objects { if !child.Visible() { continue } - if g.isSpacer(child) { spacers++ continue } + + visibleObjects++ if g.horizontal { total += child.MinSize().Width } else { @@ -69,15 +73,19 @@ func (g *boxLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { } padding := theme.Padding() + + // Amount of space not taken up by visible objects and inter-object padding var extra float32 if g.horizontal { - extra = size.Width - total - (padding * float32(len(objects)-spacers-1)) + extra = size.Width - total - (padding * float32(visibleObjects-1)) } else { - extra = size.Height - total - (padding * float32(len(objects)-spacers-1)) + extra = size.Height - total - (padding * float32(visibleObjects-1)) } - extraCell := float32(0) + + // Spacers split extra space equally + spacerSize := float32(0) if spacers > 0 { - extraCell = extra / float32(spacers) + spacerSize = extra / float32(spacers) } x, y := float32(0), float32(0) @@ -88,9 +96,9 @@ func (g *boxLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { if g.isSpacer(child) { if g.horizontal { - x += extraCell + x += spacerSize } else { - y += extraCell + y += spacerSize } continue } diff --git a/layout/boxlayout_test.go b/layout/boxlayout_test.go index 353949da50..310a8a0e9d 100644 --- a/layout/boxlayout_test.go +++ b/layout/boxlayout_test.go @@ -259,3 +259,20 @@ func TestVBoxLayout_MiddleSpacer(t *testing.T) { cell3Pos := fyne.NewPos(0, 250) assert.Equal(t, cell3Pos, obj3.Position()) } + +// Test for issue #4259 - spacer in HBox with hidden item causing add'l trailing padding +func TestHBoxLayout_MiddleSpacerHiddenItem(t *testing.T) { + cellSize := fyne.NewSize(100, 50) + + obj1 := NewMinSizeRect(cellSize) + obj2 := NewMinSizeRect(cellSize) + obj3 := NewMinSizeRect(cellSize) + + container := container.NewHBox(obj1, obj2, layout.NewSpacer(), obj3) + container.Resize(fyne.NewSize(400, 100)) + assert.Equal(t, fyne.NewPos(300, 0), obj3.Position()) + + obj2.Hide() + container.Refresh() + assert.Equal(t, fyne.NewPos(300, 0), obj3.Position()) +} From 5f15a7826e7636124e7fd8b68b1a8f94f0015379 Mon Sep 17 00:00:00 2001 From: Jordan Goulder Date: Fri, 6 Oct 2023 21:53:23 -0400 Subject: [PATCH 012/248] Remove call to Refresh() inside fileItemRenderer.Layout() which can cause crash in FileDialog --- dialog/fileitem.go | 1 - 1 file changed, 1 deletion(-) diff --git a/dialog/fileitem.go b/dialog/fileitem.go index ba1c0e0959..1ab2decf2d 100644 --- a/dialog/fileitem.go +++ b/dialog/fileitem.go @@ -102,7 +102,6 @@ func (s *fileItemRenderer) Layout(size fyne.Size) { s.text.Resize(fyne.NewSize(size.Width, textMin.Height)) s.text.Move(fyne.NewPos(fileInlineIconSize, (size.Height-textMin.Height)/2)) } - s.text.Refresh() } func (s *fileItemRenderer) MinSize() fyne.Size { From 6ed5a4203c712d44037b6526ffccb0eb6ec968d2 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 18 Oct 2023 17:22:54 +0100 Subject: [PATCH 013/248] Updating CHANGELOG with a few cherry-picks --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f4488539..91775165a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). +## 2.4.2 - In Progress + +### Fixed + +* Markdown only shows one horizontal rule (#4216) +* Spacer in HBox with hidden item will cause an additional trailing padding (#4259) +* Application crash when fast clicking the folders inside the file dialog (#4260) + + ## 2.4.1 - 8 October 2023 ### Fixed From 798f96fc412e269a9d76b1aace6ba8d60680e18d Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Wed, 18 Oct 2023 18:14:20 -0700 Subject: [PATCH 014/248] adjust window cursor test for hyperlink changes --- internal/driver/glfw/window_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index a39490672b..f0b8ebfe48 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -246,7 +246,7 @@ func TestWindow_Cursor(t *testing.T) { textCursor := desktop.TextCursor assert.Equal(t, textCursor, w.cursor) - w.mouseMoved(w.viewport, 10, float64(h.Position().Y+10)) + w.mouseMoved(w.viewport, float64(h.Position().X+10), float64(h.Position().Y+10)) pointerCursor := desktop.PointerCursor assert.Equal(t, pointerCursor, w.cursor) From eae759c7cbd8c2cfd28de59d1b0837dcd2722058 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Wed, 18 Oct 2023 20:18:39 -0700 Subject: [PATCH 015/248] handle hyperlink text alignment --- widget/hyperlink.go | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/widget/hyperlink.go b/widget/hyperlink.go index 073bfbec90..2301bb7428 100644 --- a/widget/hyperlink.go +++ b/widget/hyperlink.go @@ -107,6 +107,24 @@ func (hl *Hyperlink) MouseOut() { hl.BaseWidget.Refresh() } +func (hl *Hyperlink) focusWidth() float32 { + innerPad := theme.InnerPadding() + return fyne.Min(hl.size.Width, hl.textSize.Width+innerPad+theme.Padding()*2) - innerPad +} + +func (hl *Hyperlink) focusXPos() float32 { + switch hl.Alignment { + case fyne.TextAlignLeading: + return theme.InnerPadding() / 2 + case fyne.TextAlignCenter: + return (hl.size.Width - hl.focusWidth()) / 2 + case fyne.TextAlignTrailing: + return (hl.size.Width - hl.focusWidth()) - theme.InnerPadding()/2 + default: + return 0 // unreached + } +} + func (hl *Hyperlink) isPosOverText(pos fyne.Position) bool { innerPad := theme.InnerPadding() pad := theme.Padding() @@ -115,7 +133,9 @@ func (hl *Hyperlink) isPosOverText(pos fyne.Position) bool { if hl.provider != nil { lineCount = fyne.Max(lineCount, float32(len(hl.provider.rowBounds))) } - return pos.X >= innerPad/2 && pos.X <= hl.textSize.Width+pad*2+innerPad/2 && + + xpos := hl.focusXPos() + return pos.X >= xpos && pos.X <= xpos+hl.focusWidth() && pos.Y >= innerPad/2 && pos.Y <= hl.textSize.Height*lineCount+pad*2+innerPad/2 } @@ -242,14 +262,17 @@ func (r *hyperlinkRenderer) Destroy() { } func (r *hyperlinkRenderer) Layout(s fyne.Size) { - r.hl.provider.Resize(s) innerPad := theme.InnerPadding() + w := r.hl.focusWidth() + xposFocus := r.hl.focusXPos() + xposUnderline := xposFocus + innerPad/2 + + r.hl.provider.Resize(s) lineCount := float32(len(r.hl.provider.rowBounds)) - r.focus.Move(fyne.NewPos(innerPad/2, innerPad/2)) - w := fyne.Min(s.Width, r.hl.textSize.Width+innerPad+theme.Padding()*2) - r.focus.Resize(fyne.NewSize(w-innerPad, r.hl.textSize.Height*lineCount+innerPad)) - r.under.Move(fyne.NewPos(innerPad, r.hl.textSize.Height*lineCount+theme.Padding()*2)) - r.under.Resize(fyne.NewSize(w-innerPad*2, 1)) + r.focus.Move(fyne.NewPos(xposFocus, innerPad/2)) + r.focus.Resize(fyne.NewSize(w, r.hl.textSize.Height*lineCount+innerPad)) + r.under.Move(fyne.NewPos(xposUnderline, r.hl.textSize.Height*lineCount+theme.Padding()*2)) + r.under.Resize(fyne.NewSize(w-innerPad, 1)) } func (r *hyperlinkRenderer) MinSize() fyne.Size { From 66bc8a1ffb9ef420adf7564b3589bcd2d61aaada Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Wed, 18 Oct 2023 20:20:10 -0700 Subject: [PATCH 016/248] avoid unnecessary refreshes --- widget/hyperlink.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/widget/hyperlink.go b/widget/hyperlink.go index 2301bb7428..03b959011b 100644 --- a/widget/hyperlink.go +++ b/widget/hyperlink.go @@ -88,8 +88,7 @@ func (hl *Hyperlink) FocusLost() { // MouseIn is a hook that is called if the mouse pointer enters the element. func (hl *Hyperlink) MouseIn(e *desktop.MouseEvent) { - hl.hovered = hl.isPosOverText(e.Position) - hl.BaseWidget.Refresh() + hl.MouseMoved(e) } // MouseMoved is a hook that is called if the mouse pointer moved over the element. @@ -103,8 +102,11 @@ func (hl *Hyperlink) MouseMoved(e *desktop.MouseEvent) { // MouseOut is a hook that is called if the mouse pointer leaves the element. func (hl *Hyperlink) MouseOut() { + changed := hl.hovered hl.hovered = false - hl.BaseWidget.Refresh() + if changed { + hl.BaseWidget.Refresh() + } } func (hl *Hyperlink) focusWidth() float32 { From aaafe56ddfced208c44a518847bc28ab45216135 Mon Sep 17 00:00:00 2001 From: Mark Gascoyne Date: Tue, 10 Oct 2023 19:54:49 +0100 Subject: [PATCH 017/248] Fix windows dual graphics chip closes https://github.com/fyne-io/fyne/issues/437 Upgrade to opengl 2.1 --- internal/driver/glfw/glfw_core.go | 2 +- internal/driver/glfw/glfw_es.go | 2 +- internal/painter/gl/gl_core.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/driver/glfw/glfw_core.go b/internal/driver/glfw/glfw_core.go index ff6560800a..7026d449eb 100644 --- a/internal/driver/glfw/glfw_core.go +++ b/internal/driver/glfw/glfw_core.go @@ -10,7 +10,7 @@ import "github.com/go-gl/glfw/v3.3/glfw" func initWindowHints() { glfw.WindowHint(glfw.ContextVersionMajor, 2) - glfw.WindowHint(glfw.ContextVersionMinor, 0) + glfw.WindowHint(glfw.ContextVersionMinor, 1) glfw.WindowHint(glfw.CocoaGraphicsSwitching, glfw.True) } diff --git a/internal/driver/glfw/glfw_es.go b/internal/driver/glfw/glfw_es.go index 2dd30cf459..b3ec94a37a 100644 --- a/internal/driver/glfw/glfw_es.go +++ b/internal/driver/glfw/glfw_es.go @@ -12,5 +12,5 @@ import "github.com/go-gl/glfw/v3.3/glfw" func initWindowHints() { glfw.WindowHint(glfw.ClientAPI, glfw.OpenGLESAPI) glfw.WindowHint(glfw.ContextVersionMajor, 2) - glfw.WindowHint(glfw.ContextVersionMinor, 0) + glfw.WindowHint(glfw.ContextVersionMinor, 1) } diff --git a/internal/painter/gl/gl_core.go b/internal/painter/gl/gl_core.go index 25d9749130..2b9f45b5ee 100644 --- a/internal/painter/gl/gl_core.go +++ b/internal/painter/gl/gl_core.go @@ -6,7 +6,7 @@ package gl import ( "strings" - "github.com/go-gl/gl/v3.2-core/gl" + "github.com/go-gl/gl/v2.1/gl" "fyne.io/fyne/v2" ) From ddfc46e64236e3f8704329580399b29ec87e940d Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 20 Oct 2023 15:51:07 +0100 Subject: [PATCH 018/248] Update CHANGELOG for picked fix --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91775165a6..56ff51be04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ More detailed release notes can be found on the [releases page](https://github.c * Markdown only shows one horizontal rule (#4216) * Spacer in HBox with hidden item will cause an additional trailing padding (#4259) * Application crash when fast clicking the folders inside the file dialog (#4260) +* failed to initialise OpenGL (#437) ## 2.4.1 - 8 October 2023 From e435946a85c67f6b5b5ba76b9d76670650169198 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 21 Oct 2023 11:42:14 -0700 Subject: [PATCH 019/248] add triple tap support to Entry --- widget/entry.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/widget/entry.go b/widget/entry.go index a18da8d5b2..7e5383903c 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -21,6 +21,9 @@ import ( const ( bindIgnoreDelay = time.Millisecond * 100 // ignore incoming DataItem fire after we have called Set multiLineRows = 3 + + desktopDoubleClickDelay = 300 // ms - keep in sync with internal/driver/glfw/window.go + mobileDoubleClickDelay = 500 // ms - keep in sync with internal/driver/mobile/canvas.go ) // Declare conformity with interfaces @@ -101,6 +104,10 @@ type Entry struct { // undoStack stores the data necessary for undo/redo functionality // See entryUndoStack for implementation details. undoStack entryUndoStack + + // doubleTappedAtUnixMillis stores the time the entry was last DoubleTapped + // used for deciding whether the next MouseDown/TouchDown is a triple-tap or not + doubleTappedAtUnixMillis int64 } // NewEntry creates a new single line entry widget. @@ -228,6 +235,7 @@ func (e *Entry) Disabled() bool { // // Implements: fyne.DoubleTappable func (e *Entry) DoubleTapped(p *fyne.PointEvent) { + e.doubleTappedAtUnixMillis = time.Now().UnixMilli() row := e.textProvider().row(e.CursorRow) start, end := getTextWhitespaceRegion(row, e.CursorColumn, false) if start == -1 || end == -1 { @@ -249,6 +257,14 @@ func (e *Entry) DoubleTapped(p *fyne.PointEvent) { }) } +func (e *Entry) isTripleTap(nowMilli int64) bool { + doubleClickDelay := int64(desktopDoubleClickDelay) + if fyne.CurrentDevice().IsMobile() { + doubleClickDelay = mobileDoubleClickDelay + } + return nowMilli-e.doubleTappedAtUnixMillis <= doubleClickDelay +} + // DragEnd is called at end of a drag event. // // Implements: fyne.Draggable @@ -406,6 +422,10 @@ func (e *Entry) MinSize() fyne.Size { // // Implements: desktop.Mouseable func (e *Entry) MouseDown(m *desktop.MouseEvent) { + if e.isTripleTap(time.Now().UnixMilli()) { + e.selectCurrentRow() + return + } e.propertyLock.Lock() if e.selectKeyDown { e.selecting = true @@ -605,9 +625,14 @@ func (e *Entry) TappedSecondary(pe *fyne.PointEvent) { // // Implements: mobile.Touchable func (e *Entry) TouchDown(ev *mobile.TouchEvent) { + now := time.Now().UnixMilli() if !e.Disabled() { e.requestFocus() } + if e.isTripleTap(now) { + e.selectCurrentRow() + return + } e.updateMousePointer(ev.Position, false) } @@ -1500,6 +1525,22 @@ func (e *Entry) typedKeyReturn(provider *RichText, multiLine bool) { e.propertyLock.Unlock() } +// Selects the row where the CursorColumn is currently positioned +// Do not call while holding the proeprtyLock +func (e *Entry) selectCurrentRow() { + provider := e.textProvider() + e.propertyLock.Lock() + e.selectRow = e.CursorRow + e.selectColumn = 0 + if e.MultiLine { + e.CursorColumn = provider.rowLength(e.CursorRow) + } else { + e.CursorColumn = provider.len() + } + e.propertyLock.Unlock() + e.Refresh() +} + var _ fyne.WidgetRenderer = (*entryRenderer)(nil) type entryRenderer struct { From b82ae667f7bd553879760382eb933e300e54ad31 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 21 Oct 2023 11:53:54 -0700 Subject: [PATCH 020/248] add entry triple tap unit test --- widget/entry_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/widget/entry_test.go b/widget/entry_test.go index aacddc24ce..0c9eb5d3ab 100644 --- a/widget/entry_test.go +++ b/widget/entry_test.go @@ -1298,6 +1298,17 @@ func TestEntry_SelectSnapUp(t *testing.T) { assert.Equal(t, "", e.SelectedText()) } +func TestEntry_Select_TripleTap(t *testing.T) { + e, _ := setupSelection(t, false) + e.MultiLine = true + assert.Equal(t, 1, e.CursorRow) + assert.Equal(t, "sti", e.SelectedText()) + test.DoubleTap(e) + time.Sleep(50 * time.Millisecond) + e.MouseDown(&desktop.MouseEvent{PointEvent: fyne.PointEvent{Position: fyne.NewPos(1, 1)}}) + assert.Equal(t, "Testing", e.SelectedText()) +} + func TestEntry_SelectedText(t *testing.T) { e, window := setupImageTest(t, false) defer teardownImageTest(window) From 583af444e373d2d4b06c2fe6016b4fac6f6ac500 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 21 Oct 2023 12:04:26 -0700 Subject: [PATCH 021/248] fix double click test --- widget/entry_internal_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/widget/entry_internal_test.go b/widget/entry_internal_test.go index db56c05fc4..50fc43268d 100644 --- a/widget/entry_internal_test.go +++ b/widget/entry_internal_test.go @@ -42,12 +42,16 @@ func TestEntry_DoubleTapped(t *testing.T) { entry.DoubleTapped(ev) assert.Equal(t, "quick", entry.SelectedText()) + entry.doubleTappedAtUnixMillis = 0 // make sure we don't register a triple tap next + // select the whitespace after 'quick' ev = getClickPosition("The quick", 0) clickPrimary(entry, ev) entry.DoubleTapped(ev) assert.Equal(t, " ", entry.SelectedText()) + entry.doubleTappedAtUnixMillis = 0 + // select all whitespace after 'jumped' ev = getClickPosition("jumped ", 1) clickPrimary(entry, ev) From e7b024ae2636421f0e3842d17a3a268e27b34812 Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 18 Oct 2023 21:04:37 +0200 Subject: [PATCH 022/248] Run tests on Go 1.21 instead of 1.20 --- .github/workflows/license_check.yml | 2 +- .github/workflows/mobile_tests.yml | 2 +- .github/workflows/platform_tests.yml | 2 +- .github/workflows/static_analysis.yml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/license_check.yml b/.github/workflows/license_check.yml index 24c071b891..95108fda9f 100644 --- a/.github/workflows/license_check.yml +++ b/.github/workflows/license_check.yml @@ -12,7 +12,7 @@ jobs: persist-credentials: false - uses: WillAbides/setup-go-faster@v1.8.0 with: - go-version: '1.20.x' + go-version: '1.21.x' - name: Install lian run: go install lucor.dev/lian@latest diff --git a/.github/workflows/mobile_tests.yml b/.github/workflows/mobile_tests.yml index e3b4122371..0fce72d32e 100644 --- a/.github/workflows/mobile_tests.yml +++ b/.github/workflows/mobile_tests.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: ['1.17.x', '1.20.x'] + go-version: ['1.17.x', '1.21.x'] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/platform_tests.yml b/.github/workflows/platform_tests.yml index 324b7db5eb..0bd37d22ed 100644 --- a/.github/workflows/platform_tests.yml +++ b/.github/workflows/platform_tests.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: ['1.17.x', '1.20.x'] + go-version: ['1.17.x', '1.21.x'] os: [ubuntu-latest, windows-latest, macos-latest] include: - os: ubuntu-latest diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index e562338c9a..97d47d8070 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -15,7 +15,7 @@ jobs: persist-credentials: false - uses: WillAbides/setup-go-faster@v1.8.0 with: - go-version: '1.20.x' + go-version: '1.21.x' - name: Get dependencies run: >- @@ -33,7 +33,7 @@ jobs: run: | go install golang.org/x/tools/cmd/goimports@latest go install github.com/fzipp/gocyclo/cmd/gocyclo@latest - go install honnef.co/go/tools/cmd/staticcheck@v0.4.2 + go install honnef.co/go/tools/cmd/staticcheck@v0.4.6 go install github.com/mattn/goveralls@latest - name: Vet From 1caa28ede66500c0083a961e9bf377af475efea7 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Tue, 24 Oct 2023 10:34:33 -0700 Subject: [PATCH 023/248] share definitions of double click delay between driver and Entry widget --- internal/driver/common/driver.go | 8 ++++++++ internal/driver/glfw/window.go | 5 ++--- internal/driver/mobile/canvas.go | 6 +----- widget/entry.go | 8 +++----- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/internal/driver/common/driver.go b/internal/driver/common/driver.go index bcca9b8cde..b56fa80738 100644 --- a/internal/driver/common/driver.go +++ b/internal/driver/common/driver.go @@ -5,6 +5,14 @@ import ( "fyne.io/fyne/v2/internal/cache" ) +const ( + // moved here from the platform driver packages to allow + // referencing in widget package without an import cycle + + DesktopDoubleClickDelay = 300 // ms + MobileDoubleClickDelay = 500 // ms +) + // CanvasForObject returns the canvas for the specified object. func CanvasForObject(obj fyne.CanvasObject) fyne.Canvas { return cache.GetCanvasForObject(obj) diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 971fc486d0..7725a50ec1 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -17,8 +17,7 @@ import ( ) const ( - doubleClickDelay = 300 // ms (maximum interval between clicks for double click detection) - dragMoveThreshold = 2 // how far can we move before it is a drag + dragMoveThreshold = 2 // how far can we move before it is a drag windowIconSize = 256 ) @@ -652,7 +651,7 @@ func (w *window) mouseClickedHandleTapDoubleTap(co fyne.CanvasObject, ev *fyne.P func (w *window) waitForDoubleTap(co fyne.CanvasObject, ev *fyne.PointEvent) { var ctx context.Context w.mouseLock.Lock() - ctx, w.mouseCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*doubleClickDelay)) + ctx, w.mouseCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*common.DesktopDoubleClickDelay)) defer w.mouseCancelFunc() w.mouseLock.Unlock() diff --git a/internal/driver/mobile/canvas.go b/internal/driver/mobile/canvas.go index ec2375ba3b..4fd61cf06e 100644 --- a/internal/driver/mobile/canvas.go +++ b/internal/driver/mobile/canvas.go @@ -16,10 +16,6 @@ import ( "fyne.io/fyne/v2/widget" ) -const ( - doubleClickDelay = 500 // ms (maximum interval between clicks for double click detection) -) - var _ fyne.Canvas = (*mobileCanvas)(nil) type mobileCanvas struct { @@ -378,7 +374,7 @@ func (c *mobileCanvas) tapUp(pos fyne.Position, tapID int, func (c *mobileCanvas) waitForDoubleTap(co fyne.CanvasObject, ev *fyne.PointEvent, tapCallback func(fyne.Tappable, *fyne.PointEvent), doubleTapCallback func(fyne.DoubleTappable, *fyne.PointEvent)) { var ctx context.Context - ctx, c.touchCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*doubleClickDelay)) + ctx, c.touchCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*common.MobileDoubleClickDelay)) defer c.touchCancelFunc() <-ctx.Done() if c.touchTapCount == 2 && c.touchLastTapped == co { diff --git a/widget/entry.go b/widget/entry.go index 7e5383903c..c30d723015 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -14,6 +14,7 @@ import ( "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/driver/mobile" "fyne.io/fyne/v2/internal/cache" + "fyne.io/fyne/v2/internal/driver/common" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -21,9 +22,6 @@ import ( const ( bindIgnoreDelay = time.Millisecond * 100 // ignore incoming DataItem fire after we have called Set multiLineRows = 3 - - desktopDoubleClickDelay = 300 // ms - keep in sync with internal/driver/glfw/window.go - mobileDoubleClickDelay = 500 // ms - keep in sync with internal/driver/mobile/canvas.go ) // Declare conformity with interfaces @@ -258,9 +256,9 @@ func (e *Entry) DoubleTapped(p *fyne.PointEvent) { } func (e *Entry) isTripleTap(nowMilli int64) bool { - doubleClickDelay := int64(desktopDoubleClickDelay) + doubleClickDelay := int64(common.DesktopDoubleClickDelay) if fyne.CurrentDevice().IsMobile() { - doubleClickDelay = mobileDoubleClickDelay + doubleClickDelay = common.MobileDoubleClickDelay } return nowMilli-e.doubleTappedAtUnixMillis <= doubleClickDelay } From d638b4d8c5cf1d80aa07fbcad8a3561c310cf237 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Tue, 24 Oct 2023 10:47:31 -0700 Subject: [PATCH 024/248] fix mobile test compilation --- internal/driver/mobile/canvas_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/driver/mobile/canvas_test.go b/internal/driver/mobile/canvas_test.go index 63c35d8e84..cfca1d285c 100644 --- a/internal/driver/mobile/canvas_test.go +++ b/internal/driver/mobile/canvas_test.go @@ -13,6 +13,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/driver/mobile" + "fyne.io/fyne/v2/internal/driver/common" _ "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -298,7 +299,7 @@ func TestCanvas_Focusable(t *testing.T) { c.tapUp(pos, 0, func(wid fyne.Tappable, ev *fyne.PointEvent) { wid.Tapped(ev) }, nil, nil, nil) - time.Sleep(time.Millisecond * (doubleClickDelay + 150)) + time.Sleep(time.Millisecond * (common.MobileDoubleClickDelay + 150)) assert.Equal(t, 1, content.focusedTimes) assert.Equal(t, 0, content.unfocusedTimes) @@ -306,7 +307,7 @@ func TestCanvas_Focusable(t *testing.T) { c.tapUp(pos, 1, func(wid fyne.Tappable, ev *fyne.PointEvent) { wid.Tapped(ev) }, nil, nil, nil) - time.Sleep(time.Millisecond * (doubleClickDelay + 150)) + time.Sleep(time.Millisecond * (common.MobileDoubleClickDelay + 150)) assert.Equal(t, 1, content.focusedTimes) assert.Equal(t, 0, content.unfocusedTimes) From 5b8e84a885f3c0294c89beea61b1d8be9c389a86 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 27 Oct 2023 06:19:01 -0700 Subject: [PATCH 025/248] move consts to new package --- internal/driver/common/driver.go | 8 -------- internal/driver/consts/consts.go | 9 +++++++++ internal/driver/glfw/window.go | 3 ++- internal/driver/mobile/canvas.go | 3 ++- internal/driver/mobile/canvas_test.go | 6 +++--- widget/entry.go | 6 +++--- 6 files changed, 19 insertions(+), 16 deletions(-) create mode 100644 internal/driver/consts/consts.go diff --git a/internal/driver/common/driver.go b/internal/driver/common/driver.go index b56fa80738..bcca9b8cde 100644 --- a/internal/driver/common/driver.go +++ b/internal/driver/common/driver.go @@ -5,14 +5,6 @@ import ( "fyne.io/fyne/v2/internal/cache" ) -const ( - // moved here from the platform driver packages to allow - // referencing in widget package without an import cycle - - DesktopDoubleClickDelay = 300 // ms - MobileDoubleClickDelay = 500 // ms -) - // CanvasForObject returns the canvas for the specified object. func CanvasForObject(obj fyne.CanvasObject) fyne.Canvas { return cache.GetCanvasForObject(obj) diff --git a/internal/driver/consts/consts.go b/internal/driver/consts/consts.go new file mode 100644 index 0000000000..15d750c6b0 --- /dev/null +++ b/internal/driver/consts/consts.go @@ -0,0 +1,9 @@ +package consts + +const ( + // moved here from the platform driver packages to allow + // referencing in widget package without an import cycle + + DesktopDoubleClickDelay = 300 // ms + MobileDoubleClickDelay = 500 // ms +) diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 7725a50ec1..1bd456842a 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -13,6 +13,7 @@ import ( "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/driver" "fyne.io/fyne/v2/internal/driver/common" + "fyne.io/fyne/v2/internal/driver/consts" "fyne.io/fyne/v2/internal/scale" ) @@ -651,7 +652,7 @@ func (w *window) mouseClickedHandleTapDoubleTap(co fyne.CanvasObject, ev *fyne.P func (w *window) waitForDoubleTap(co fyne.CanvasObject, ev *fyne.PointEvent) { var ctx context.Context w.mouseLock.Lock() - ctx, w.mouseCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*common.DesktopDoubleClickDelay)) + ctx, w.mouseCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*consts.DesktopDoubleClickDelay)) defer w.mouseCancelFunc() w.mouseLock.Unlock() diff --git a/internal/driver/mobile/canvas.go b/internal/driver/mobile/canvas.go index 4fd61cf06e..8756f47a5c 100644 --- a/internal/driver/mobile/canvas.go +++ b/internal/driver/mobile/canvas.go @@ -12,6 +12,7 @@ import ( "fyne.io/fyne/v2/internal/app" "fyne.io/fyne/v2/internal/driver" "fyne.io/fyne/v2/internal/driver/common" + "fyne.io/fyne/v2/internal/driver/consts" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -374,7 +375,7 @@ func (c *mobileCanvas) tapUp(pos fyne.Position, tapID int, func (c *mobileCanvas) waitForDoubleTap(co fyne.CanvasObject, ev *fyne.PointEvent, tapCallback func(fyne.Tappable, *fyne.PointEvent), doubleTapCallback func(fyne.DoubleTappable, *fyne.PointEvent)) { var ctx context.Context - ctx, c.touchCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*common.MobileDoubleClickDelay)) + ctx, c.touchCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*consts.MobileDoubleClickDelay)) defer c.touchCancelFunc() <-ctx.Done() if c.touchTapCount == 2 && c.touchLastTapped == co { diff --git a/internal/driver/mobile/canvas_test.go b/internal/driver/mobile/canvas_test.go index cfca1d285c..92cfcb9e61 100644 --- a/internal/driver/mobile/canvas_test.go +++ b/internal/driver/mobile/canvas_test.go @@ -13,7 +13,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/driver/mobile" - "fyne.io/fyne/v2/internal/driver/common" + "fyne.io/fyne/v2/internal/driver/consts" _ "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -299,7 +299,7 @@ func TestCanvas_Focusable(t *testing.T) { c.tapUp(pos, 0, func(wid fyne.Tappable, ev *fyne.PointEvent) { wid.Tapped(ev) }, nil, nil, nil) - time.Sleep(time.Millisecond * (common.MobileDoubleClickDelay + 150)) + time.Sleep(time.Millisecond * (consts.MobileDoubleClickDelay + 150)) assert.Equal(t, 1, content.focusedTimes) assert.Equal(t, 0, content.unfocusedTimes) @@ -307,7 +307,7 @@ func TestCanvas_Focusable(t *testing.T) { c.tapUp(pos, 1, func(wid fyne.Tappable, ev *fyne.PointEvent) { wid.Tapped(ev) }, nil, nil, nil) - time.Sleep(time.Millisecond * (common.MobileDoubleClickDelay + 150)) + time.Sleep(time.Millisecond * (consts.MobileDoubleClickDelay + 150)) assert.Equal(t, 1, content.focusedTimes) assert.Equal(t, 0, content.unfocusedTimes) diff --git a/widget/entry.go b/widget/entry.go index c30d723015..e7c760c5ec 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -14,7 +14,7 @@ import ( "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/driver/mobile" "fyne.io/fyne/v2/internal/cache" - "fyne.io/fyne/v2/internal/driver/common" + driverconsts "fyne.io/fyne/v2/internal/driver/consts" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -256,9 +256,9 @@ func (e *Entry) DoubleTapped(p *fyne.PointEvent) { } func (e *Entry) isTripleTap(nowMilli int64) bool { - doubleClickDelay := int64(common.DesktopDoubleClickDelay) + doubleClickDelay := int64(driverconsts.DesktopDoubleClickDelay) if fyne.CurrentDevice().IsMobile() { - doubleClickDelay = common.MobileDoubleClickDelay + doubleClickDelay = driverconsts.MobileDoubleClickDelay } return nowMilli-e.doubleTappedAtUnixMillis <= doubleClickDelay } From 9a4008eb540fa11c5785552f95e44ad0bb85c565 Mon Sep 17 00:00:00 2001 From: Gage Cottom Date: Sat, 28 Oct 2023 23:22:27 -0500 Subject: [PATCH 026/248] this fix addresses issues with ctrl vs cmd key on mac in browser apps. previously when in the browser on a mac you would have to use the ctrl key to perform keyboard shortcuts which is not intuitive on a mac where cmd is typically used instead of ctrl. this change adds a check in window initialization that will check if the build is browser based (based on build constraints). At runtime there is a javascript check of the navigator.platform value. if this value contains mac, the modifier key handles default shortcut keys with cmd key instead of ctrl key. other operating systems will see no change. --- internal/driver/glfw/web_shortcuts_js.go | 19 +++++++++++++++++++ internal/driver/glfw/web_shortcuts_other.go | 9 +++++++++ internal/driver/glfw/web_shortcuts_wasm.go | 19 +++++++++++++++++++ internal/driver/glfw/window.go | 2 +- 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 internal/driver/glfw/web_shortcuts_js.go create mode 100644 internal/driver/glfw/web_shortcuts_other.go create mode 100644 internal/driver/glfw/web_shortcuts_wasm.go diff --git a/internal/driver/glfw/web_shortcuts_js.go b/internal/driver/glfw/web_shortcuts_js.go new file mode 100644 index 0000000000..90766f0a2a --- /dev/null +++ b/internal/driver/glfw/web_shortcuts_js.go @@ -0,0 +1,19 @@ +//go:build js && !wasm +// +build js,!wasm + +package glfw + +import ( + "strings" + + "github.com/gopherjs/gopherjs/js" +) + +// Checks if the browser is runnning on Mac OSX +func isMacOSBrowser() bool { + if strings.Contains(strings.ToLower(js.Global.Get("window").Get("navigator").Get("platform").String()), "mac") { + return true + } else { + return false + } +} diff --git a/internal/driver/glfw/web_shortcuts_other.go b/internal/driver/glfw/web_shortcuts_other.go new file mode 100644 index 0000000000..5db93da963 --- /dev/null +++ b/internal/driver/glfw/web_shortcuts_other.go @@ -0,0 +1,9 @@ +//go:build !js && !wasm +// +build !js,!wasm + +package glfw + +// Checks if browser is running on Mac OSX. Returns false because non-browser builds are a no op. +func isMacOSBrowser() bool { + return false +} diff --git a/internal/driver/glfw/web_shortcuts_wasm.go b/internal/driver/glfw/web_shortcuts_wasm.go new file mode 100644 index 0000000000..1e092ea780 --- /dev/null +++ b/internal/driver/glfw/web_shortcuts_wasm.go @@ -0,0 +1,19 @@ +//go:build js && wasm +// +build js,wasm + +package glfw + +import ( + "strings" + + "syscall/js" +) + +// Checks if the browser is runnning on Mac OSX +func isMacOSBrowser() bool { + if strings.Contains(strings.ToLower(js.Global().Get("window").Get("navigator").Get("platform").String()), "mac") { + return true + } else { + return false + } +} diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 540caf3fca..e476450ca0 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -832,7 +832,7 @@ func (w *window) processFocused(focus bool) { func (w *window) triggersShortcut(localizedKeyName fyne.KeyName, key fyne.KeyName, modifier fyne.KeyModifier) bool { var shortcut fyne.Shortcut ctrlMod := fyne.KeyModifierControl - if runtime.GOOS == "darwin" { + if runtime.GOOS == "darwin" || isMacOSBrowser() { ctrlMod = fyne.KeyModifierSuper } // User pressing physical keys Ctrl+V while using a Russian (or any non-ASCII) keyboard layout From 77e6612ee1cda6e9844f9dc723400b11e53cc4bd Mon Sep 17 00:00:00 2001 From: Gage Cottom Date: Sat, 28 Oct 2023 23:46:05 -0500 Subject: [PATCH 027/248] update test case --- internal/driver/glfw/window_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index b7d156bbe0..38d57ae3d7 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -1651,7 +1651,7 @@ func TestWindow_ClipboardCopy_DisabledEntry(t *testing.T) { assert.Equal(t, "Testing", e.SelectedText()) ctrlMod := glfw.ModControl - if runtime.GOOS == "darwin" { + if runtime.GOOS == "darwin" || isMacOSBrowser() { ctrlMod = glfw.ModSuper } w.keyPressed(nil, glfw.KeyC, 0, glfw.Repeat, ctrlMod) From 20f0505f66d4781a8a000c94ac6ea3ffe56f0db5 Mon Sep 17 00:00:00 2001 From: Gage Cottom Date: Sun, 29 Oct 2023 14:44:57 -0500 Subject: [PATCH 028/248] simplify os check/browser check. removes browser/web reference from the code. simplify return logic for mac check. --- internal/driver/glfw/shortcuts_js.go | 15 +++++++++++++++ internal/driver/glfw/shortcuts_other.go | 11 +++++++++++ internal/driver/glfw/shortcuts_wasm.go | 15 +++++++++++++++ internal/driver/glfw/web_shortcuts_js.go | 19 ------------------- internal/driver/glfw/web_shortcuts_other.go | 9 --------- internal/driver/glfw/web_shortcuts_wasm.go | 19 ------------------- internal/driver/glfw/window.go | 2 +- internal/driver/glfw/window_test.go | 2 +- 8 files changed, 43 insertions(+), 49 deletions(-) create mode 100644 internal/driver/glfw/shortcuts_js.go create mode 100644 internal/driver/glfw/shortcuts_other.go create mode 100644 internal/driver/glfw/shortcuts_wasm.go delete mode 100644 internal/driver/glfw/web_shortcuts_js.go delete mode 100644 internal/driver/glfw/web_shortcuts_other.go delete mode 100644 internal/driver/glfw/web_shortcuts_wasm.go diff --git a/internal/driver/glfw/shortcuts_js.go b/internal/driver/glfw/shortcuts_js.go new file mode 100644 index 0000000000..cc18b8b9d9 --- /dev/null +++ b/internal/driver/glfw/shortcuts_js.go @@ -0,0 +1,15 @@ +//go:build js && !wasm +// +build js,!wasm + +package glfw + +import ( + "strings" + + "github.com/gopherjs/gopherjs/js" +) + +// Checks if running on Mac OSX +func isMacOSRuntime() bool { + return strings.Contains(strings.ToLower(js.Global.Get("window").Get("navigator").Get("platform").String()), "mac") +} diff --git a/internal/driver/glfw/shortcuts_other.go b/internal/driver/glfw/shortcuts_other.go new file mode 100644 index 0000000000..d672aa6906 --- /dev/null +++ b/internal/driver/glfw/shortcuts_other.go @@ -0,0 +1,11 @@ +//go:build !js && !wasm +// +build !js,!wasm + +package glfw + +import "runtime" + +// Checks if running on Mac OSX +func isMacOSRuntime() bool { + return runtime.GOOS == "darwin" +} diff --git a/internal/driver/glfw/shortcuts_wasm.go b/internal/driver/glfw/shortcuts_wasm.go new file mode 100644 index 0000000000..21cac3b4c0 --- /dev/null +++ b/internal/driver/glfw/shortcuts_wasm.go @@ -0,0 +1,15 @@ +//go:build js && wasm +// +build js,wasm + +package glfw + +import ( + "strings" + + "syscall/js" +) + +// Checks if running on Mac OSX +func isMacOSRuntime() bool { + return strings.Contains(strings.ToLower(js.Global().Get("window").Get("navigator").Get("platform").String()), "mac") +} diff --git a/internal/driver/glfw/web_shortcuts_js.go b/internal/driver/glfw/web_shortcuts_js.go deleted file mode 100644 index 90766f0a2a..0000000000 --- a/internal/driver/glfw/web_shortcuts_js.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build js && !wasm -// +build js,!wasm - -package glfw - -import ( - "strings" - - "github.com/gopherjs/gopherjs/js" -) - -// Checks if the browser is runnning on Mac OSX -func isMacOSBrowser() bool { - if strings.Contains(strings.ToLower(js.Global.Get("window").Get("navigator").Get("platform").String()), "mac") { - return true - } else { - return false - } -} diff --git a/internal/driver/glfw/web_shortcuts_other.go b/internal/driver/glfw/web_shortcuts_other.go deleted file mode 100644 index 5db93da963..0000000000 --- a/internal/driver/glfw/web_shortcuts_other.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !js && !wasm -// +build !js,!wasm - -package glfw - -// Checks if browser is running on Mac OSX. Returns false because non-browser builds are a no op. -func isMacOSBrowser() bool { - return false -} diff --git a/internal/driver/glfw/web_shortcuts_wasm.go b/internal/driver/glfw/web_shortcuts_wasm.go deleted file mode 100644 index 1e092ea780..0000000000 --- a/internal/driver/glfw/web_shortcuts_wasm.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build js && wasm -// +build js,wasm - -package glfw - -import ( - "strings" - - "syscall/js" -) - -// Checks if the browser is runnning on Mac OSX -func isMacOSBrowser() bool { - if strings.Contains(strings.ToLower(js.Global().Get("window").Get("navigator").Get("platform").String()), "mac") { - return true - } else { - return false - } -} diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index e476450ca0..1bf9b0c616 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -832,7 +832,7 @@ func (w *window) processFocused(focus bool) { func (w *window) triggersShortcut(localizedKeyName fyne.KeyName, key fyne.KeyName, modifier fyne.KeyModifier) bool { var shortcut fyne.Shortcut ctrlMod := fyne.KeyModifierControl - if runtime.GOOS == "darwin" || isMacOSBrowser() { + if isMacOSRuntime() { ctrlMod = fyne.KeyModifierSuper } // User pressing physical keys Ctrl+V while using a Russian (or any non-ASCII) keyboard layout diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index 38d57ae3d7..f68a470aea 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -1651,7 +1651,7 @@ func TestWindow_ClipboardCopy_DisabledEntry(t *testing.T) { assert.Equal(t, "Testing", e.SelectedText()) ctrlMod := glfw.ModControl - if runtime.GOOS == "darwin" || isMacOSBrowser() { + if isMacOSRuntime() { ctrlMod = glfw.ModSuper } w.keyPressed(nil, glfw.KeyC, 0, glfw.Repeat, ctrlMod) From c8e06cdc5be1ee42b42c6d8fece67edf9b8afa41 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 15 Nov 2023 23:09:29 +0000 Subject: [PATCH 029/248] Add Remove to data binding lists and trees --- data/binding/bindlists.go | 232 ++++++++++++++++++++++++++++++++++++++ data/binding/bindtrees.go | 184 ++++++++++++++++++++++++++++++ data/binding/gen.go | 67 +++++++++++ 3 files changed, 483 insertions(+) diff --git a/data/binding/bindlists.go b/data/binding/bindlists.go index 005252791d..0f2ad91d5f 100644 --- a/data/binding/bindlists.go +++ b/data/binding/bindlists.go @@ -19,6 +19,7 @@ type BoolList interface { Get() ([]bool, error) GetValue(index int) (bool, error) Prepend(value bool) error + Remove(value bool) error Set(list []bool) error SetValue(index int, value bool) error } @@ -106,6 +107,34 @@ func (l *boundBoolList) Reload() error { return l.doReload() } +func (l *boundBoolList) Remove(val bool) error { + l.lock.Lock() + defer l.lock.Unlock() + + if len(*l.val) == 0 { + return nil + } + if (*l.val)[0] == val { + *l.val = (*l.val)[1:] + } else if (*l.val)[len(*l.val)-1] == val { + *l.val = (*l.val)[:len(*l.val)] + } else { + id := -1 + for i, v := range *l.val { + if v == val { + id = i + } + } + + if id == -1 { + return nil + } + *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + } + + return l.doReload() +} + func (l *boundBoolList) Set(v []bool) error { l.lock.Lock() defer l.lock.Unlock() @@ -241,6 +270,7 @@ type BytesList interface { Get() ([][]byte, error) GetValue(index int) ([]byte, error) Prepend(value []byte) error + Remove(value []byte) error Set(list [][]byte) error SetValue(index int, value []byte) error } @@ -328,6 +358,34 @@ func (l *boundBytesList) Reload() error { return l.doReload() } +func (l *boundBytesList) Remove(val []byte) error { + l.lock.Lock() + defer l.lock.Unlock() + + if len(*l.val) == 0 { + return nil + } + if bytes.Equal((*l.val)[0], val) { + *l.val = (*l.val)[1:] + } else if bytes.Equal((*l.val)[len(*l.val)-1], val) { + *l.val = (*l.val)[:len(*l.val)] + } else { + id := -1 + for i, v := range *l.val { + if bytes.Equal(v, val) { + id = i + } + } + + if id == -1 { + return nil + } + *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + } + + return l.doReload() +} + func (l *boundBytesList) Set(v [][]byte) error { l.lock.Lock() defer l.lock.Unlock() @@ -463,6 +521,7 @@ type FloatList interface { Get() ([]float64, error) GetValue(index int) (float64, error) Prepend(value float64) error + Remove(value float64) error Set(list []float64) error SetValue(index int, value float64) error } @@ -550,6 +609,34 @@ func (l *boundFloatList) Reload() error { return l.doReload() } +func (l *boundFloatList) Remove(val float64) error { + l.lock.Lock() + defer l.lock.Unlock() + + if len(*l.val) == 0 { + return nil + } + if (*l.val)[0] == val { + *l.val = (*l.val)[1:] + } else if (*l.val)[len(*l.val)-1] == val { + *l.val = (*l.val)[:len(*l.val)] + } else { + id := -1 + for i, v := range *l.val { + if v == val { + id = i + } + } + + if id == -1 { + return nil + } + *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + } + + return l.doReload() +} + func (l *boundFloatList) Set(v []float64) error { l.lock.Lock() defer l.lock.Unlock() @@ -685,6 +772,7 @@ type IntList interface { Get() ([]int, error) GetValue(index int) (int, error) Prepend(value int) error + Remove(value int) error Set(list []int) error SetValue(index int, value int) error } @@ -772,6 +860,34 @@ func (l *boundIntList) Reload() error { return l.doReload() } +func (l *boundIntList) Remove(val int) error { + l.lock.Lock() + defer l.lock.Unlock() + + if len(*l.val) == 0 { + return nil + } + if (*l.val)[0] == val { + *l.val = (*l.val)[1:] + } else if (*l.val)[len(*l.val)-1] == val { + *l.val = (*l.val)[:len(*l.val)] + } else { + id := -1 + for i, v := range *l.val { + if v == val { + id = i + } + } + + if id == -1 { + return nil + } + *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + } + + return l.doReload() +} + func (l *boundIntList) Set(v []int) error { l.lock.Lock() defer l.lock.Unlock() @@ -907,6 +1023,7 @@ type RuneList interface { Get() ([]rune, error) GetValue(index int) (rune, error) Prepend(value rune) error + Remove(value rune) error Set(list []rune) error SetValue(index int, value rune) error } @@ -994,6 +1111,34 @@ func (l *boundRuneList) Reload() error { return l.doReload() } +func (l *boundRuneList) Remove(val rune) error { + l.lock.Lock() + defer l.lock.Unlock() + + if len(*l.val) == 0 { + return nil + } + if (*l.val)[0] == val { + *l.val = (*l.val)[1:] + } else if (*l.val)[len(*l.val)-1] == val { + *l.val = (*l.val)[:len(*l.val)] + } else { + id := -1 + for i, v := range *l.val { + if v == val { + id = i + } + } + + if id == -1 { + return nil + } + *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + } + + return l.doReload() +} + func (l *boundRuneList) Set(v []rune) error { l.lock.Lock() defer l.lock.Unlock() @@ -1129,6 +1274,7 @@ type StringList interface { Get() ([]string, error) GetValue(index int) (string, error) Prepend(value string) error + Remove(value string) error Set(list []string) error SetValue(index int, value string) error } @@ -1216,6 +1362,34 @@ func (l *boundStringList) Reload() error { return l.doReload() } +func (l *boundStringList) Remove(val string) error { + l.lock.Lock() + defer l.lock.Unlock() + + if len(*l.val) == 0 { + return nil + } + if (*l.val)[0] == val { + *l.val = (*l.val)[1:] + } else if (*l.val)[len(*l.val)-1] == val { + *l.val = (*l.val)[:len(*l.val)] + } else { + id := -1 + for i, v := range *l.val { + if v == val { + id = i + } + } + + if id == -1 { + return nil + } + *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + } + + return l.doReload() +} + func (l *boundStringList) Set(v []string) error { l.lock.Lock() defer l.lock.Unlock() @@ -1351,6 +1525,7 @@ type UntypedList interface { Get() ([]interface{}, error) GetValue(index int) (interface{}, error) Prepend(value interface{}) error + Remove(value interface{}) error Set(list []interface{}) error SetValue(index int, value interface{}) error } @@ -1438,6 +1613,34 @@ func (l *boundUntypedList) Reload() error { return l.doReload() } +func (l *boundUntypedList) Remove(val interface{}) error { + l.lock.Lock() + defer l.lock.Unlock() + + if len(*l.val) == 0 { + return nil + } + if (*l.val)[0] == val { + *l.val = (*l.val)[1:] + } else if (*l.val)[len(*l.val)-1] == val { + *l.val = (*l.val)[:len(*l.val)] + } else { + id := -1 + for i, v := range *l.val { + if v == val { + id = i + } + } + + if id == -1 { + return nil + } + *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + } + + return l.doReload() +} + func (l *boundUntypedList) Set(v []interface{}) error { l.lock.Lock() defer l.lock.Unlock() @@ -1573,6 +1776,7 @@ type URIList interface { Get() ([]fyne.URI, error) GetValue(index int) (fyne.URI, error) Prepend(value fyne.URI) error + Remove(value fyne.URI) error Set(list []fyne.URI) error SetValue(index int, value fyne.URI) error } @@ -1660,6 +1864,34 @@ func (l *boundURIList) Reload() error { return l.doReload() } +func (l *boundURIList) Remove(val fyne.URI) error { + l.lock.Lock() + defer l.lock.Unlock() + + if len(*l.val) == 0 { + return nil + } + if compareURI((*l.val)[0], val) { + *l.val = (*l.val)[1:] + } else if compareURI((*l.val)[len(*l.val)-1], val) { + *l.val = (*l.val)[:len(*l.val)] + } else { + id := -1 + for i, v := range *l.val { + if compareURI(v, val) { + id = i + } + } + + if id == -1 { + return nil + } + *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + } + + return l.doReload() +} + func (l *boundURIList) Set(v []fyne.URI) error { l.lock.Lock() defer l.lock.Unlock() diff --git a/data/binding/bindtrees.go b/data/binding/bindtrees.go index aa1d4e7ea3..07d5f77612 100644 --- a/data/binding/bindtrees.go +++ b/data/binding/bindtrees.go @@ -19,6 +19,7 @@ type BoolTree interface { Get() (map[string][]string, map[string]bool, error) GetValue(id string) (bool, error) Prepend(parent, id string, value bool) error + Remove(id string) error Set(ids map[string][]string, values map[string]bool) error SetValue(id string, value bool) error } @@ -120,6 +121,28 @@ func (t *boundBoolTree) Prepend(parent, id string, val bool) error { return t.doReload() } +func (t *boundBoolTree) Remove(id string) error { + t.lock.Lock() + defer t.lock.Unlock() + + t.removeChildren(id) + delete(t.ids, id) + v := *t.val + delete(v, id) + + return t.doReload() +} + +func (t *boundBoolTree) removeChildren(id string) { + for _, cid := range t.ids[id] { + t.removeChildren(cid) + + delete(t.ids, cid) + v := *t.val + delete(v, cid) + } +} + func (t *boundBoolTree) Reload() error { t.lock.Lock() defer t.lock.Unlock() @@ -277,6 +300,7 @@ type BytesTree interface { Get() (map[string][]string, map[string][]byte, error) GetValue(id string) ([]byte, error) Prepend(parent, id string, value []byte) error + Remove(id string) error Set(ids map[string][]string, values map[string][]byte) error SetValue(id string, value []byte) error } @@ -378,6 +402,28 @@ func (t *boundBytesTree) Prepend(parent, id string, val []byte) error { return t.doReload() } +func (t *boundBytesTree) Remove(id string) error { + t.lock.Lock() + defer t.lock.Unlock() + + t.removeChildren(id) + delete(t.ids, id) + v := *t.val + delete(v, id) + + return t.doReload() +} + +func (t *boundBytesTree) removeChildren(id string) { + for _, cid := range t.ids[id] { + t.removeChildren(cid) + + delete(t.ids, cid) + v := *t.val + delete(v, cid) + } +} + func (t *boundBytesTree) Reload() error { t.lock.Lock() defer t.lock.Unlock() @@ -535,6 +581,7 @@ type FloatTree interface { Get() (map[string][]string, map[string]float64, error) GetValue(id string) (float64, error) Prepend(parent, id string, value float64) error + Remove(id string) error Set(ids map[string][]string, values map[string]float64) error SetValue(id string, value float64) error } @@ -636,6 +683,28 @@ func (t *boundFloatTree) Prepend(parent, id string, val float64) error { return t.doReload() } +func (t *boundFloatTree) Remove(id string) error { + t.lock.Lock() + defer t.lock.Unlock() + + t.removeChildren(id) + delete(t.ids, id) + v := *t.val + delete(v, id) + + return t.doReload() +} + +func (t *boundFloatTree) removeChildren(id string) { + for _, cid := range t.ids[id] { + t.removeChildren(cid) + + delete(t.ids, cid) + v := *t.val + delete(v, cid) + } +} + func (t *boundFloatTree) Reload() error { t.lock.Lock() defer t.lock.Unlock() @@ -793,6 +862,7 @@ type IntTree interface { Get() (map[string][]string, map[string]int, error) GetValue(id string) (int, error) Prepend(parent, id string, value int) error + Remove(id string) error Set(ids map[string][]string, values map[string]int) error SetValue(id string, value int) error } @@ -894,6 +964,28 @@ func (t *boundIntTree) Prepend(parent, id string, val int) error { return t.doReload() } +func (t *boundIntTree) Remove(id string) error { + t.lock.Lock() + defer t.lock.Unlock() + + t.removeChildren(id) + delete(t.ids, id) + v := *t.val + delete(v, id) + + return t.doReload() +} + +func (t *boundIntTree) removeChildren(id string) { + for _, cid := range t.ids[id] { + t.removeChildren(cid) + + delete(t.ids, cid) + v := *t.val + delete(v, cid) + } +} + func (t *boundIntTree) Reload() error { t.lock.Lock() defer t.lock.Unlock() @@ -1051,6 +1143,7 @@ type RuneTree interface { Get() (map[string][]string, map[string]rune, error) GetValue(id string) (rune, error) Prepend(parent, id string, value rune) error + Remove(id string) error Set(ids map[string][]string, values map[string]rune) error SetValue(id string, value rune) error } @@ -1152,6 +1245,28 @@ func (t *boundRuneTree) Prepend(parent, id string, val rune) error { return t.doReload() } +func (t *boundRuneTree) Remove(id string) error { + t.lock.Lock() + defer t.lock.Unlock() + + t.removeChildren(id) + delete(t.ids, id) + v := *t.val + delete(v, id) + + return t.doReload() +} + +func (t *boundRuneTree) removeChildren(id string) { + for _, cid := range t.ids[id] { + t.removeChildren(cid) + + delete(t.ids, cid) + v := *t.val + delete(v, cid) + } +} + func (t *boundRuneTree) Reload() error { t.lock.Lock() defer t.lock.Unlock() @@ -1309,6 +1424,7 @@ type StringTree interface { Get() (map[string][]string, map[string]string, error) GetValue(id string) (string, error) Prepend(parent, id string, value string) error + Remove(id string) error Set(ids map[string][]string, values map[string]string) error SetValue(id string, value string) error } @@ -1410,6 +1526,28 @@ func (t *boundStringTree) Prepend(parent, id string, val string) error { return t.doReload() } +func (t *boundStringTree) Remove(id string) error { + t.lock.Lock() + defer t.lock.Unlock() + + t.removeChildren(id) + delete(t.ids, id) + v := *t.val + delete(v, id) + + return t.doReload() +} + +func (t *boundStringTree) removeChildren(id string) { + for _, cid := range t.ids[id] { + t.removeChildren(cid) + + delete(t.ids, cid) + v := *t.val + delete(v, cid) + } +} + func (t *boundStringTree) Reload() error { t.lock.Lock() defer t.lock.Unlock() @@ -1567,6 +1705,7 @@ type UntypedTree interface { Get() (map[string][]string, map[string]interface{}, error) GetValue(id string) (interface{}, error) Prepend(parent, id string, value interface{}) error + Remove(id string) error Set(ids map[string][]string, values map[string]interface{}) error SetValue(id string, value interface{}) error } @@ -1668,6 +1807,28 @@ func (t *boundUntypedTree) Prepend(parent, id string, val interface{}) error { return t.doReload() } +func (t *boundUntypedTree) Remove(id string) error { + t.lock.Lock() + defer t.lock.Unlock() + + t.removeChildren(id) + delete(t.ids, id) + v := *t.val + delete(v, id) + + return t.doReload() +} + +func (t *boundUntypedTree) removeChildren(id string) { + for _, cid := range t.ids[id] { + t.removeChildren(cid) + + delete(t.ids, cid) + v := *t.val + delete(v, cid) + } +} + func (t *boundUntypedTree) Reload() error { t.lock.Lock() defer t.lock.Unlock() @@ -1825,6 +1986,7 @@ type URITree interface { Get() (map[string][]string, map[string]fyne.URI, error) GetValue(id string) (fyne.URI, error) Prepend(parent, id string, value fyne.URI) error + Remove(id string) error Set(ids map[string][]string, values map[string]fyne.URI) error SetValue(id string, value fyne.URI) error } @@ -1926,6 +2088,28 @@ func (t *boundURITree) Prepend(parent, id string, val fyne.URI) error { return t.doReload() } +func (t *boundURITree) Remove(id string) error { + t.lock.Lock() + defer t.lock.Unlock() + + t.removeChildren(id) + delete(t.ids, id) + v := *t.val + delete(v, id) + + return t.doReload() +} + +func (t *boundURITree) removeChildren(id string) { + for _, cid := range t.ids[id] { + t.removeChildren(cid) + + delete(t.ids, cid) + v := *t.val + delete(v, cid) + } +} + func (t *boundURITree) Reload() error { t.lock.Lock() defer t.lock.Unlock() diff --git a/data/binding/gen.go b/data/binding/gen.go index 36f05e7ba5..dc9e06a9a9 100644 --- a/data/binding/gen.go +++ b/data/binding/gen.go @@ -385,6 +385,7 @@ type {{ .Name }}List interface { Get() ([]{{ .Type }}, error) GetValue(index int) ({{ .Type }}, error) Prepend(value {{ .Type }}) error + Remove(value {{ .Type }}) error Set(list []{{ .Type }}) error SetValue(index int, value {{ .Type }}) error } @@ -472,6 +473,49 @@ func (l *bound{{ .Name }}List) Reload() error { return l.doReload() } +func (l *bound{{ .Name }}List) Remove(val {{ .Type }}) error { + l.lock.Lock() + defer l.lock.Unlock() + + if len(*l.val) == 0 { + return nil + } + + {{- if eq .Comparator "" }} + if (*l.val)[0] == val { + *l.val = (*l.val)[1:] + } else if (*l.val)[len(*l.val)-1] == val { + *l.val = (*l.val)[:len(*l.val)] + } else { + {{- else }} + if {{ .Comparator }}((*l.val)[0], val) { + *l.val = (*l.val)[1:] + } else if {{ .Comparator }}((*l.val)[len(*l.val)-1], val) { + *l.val = (*l.val)[:len(*l.val)] + } else { + {{- end }} + id := -1 + for i, v := range *l.val { + {{- if eq .Comparator "" }} + if v == val { + id = i + } + {{- else }} + if {{ .Comparator }}(v, val) { + id = i + } + {{- end }} + } + + if id == -1 { + return nil + } + *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + } + + return l.doReload() +} + func (l *bound{{ .Name }}List) Set(v []{{ .Type }}) error { l.lock.Lock() defer l.lock.Unlock() @@ -615,6 +659,7 @@ type {{ .Name }}Tree interface { Get() (map[string][]string, map[string]{{ .Type }}, error) GetValue(id string) ({{ .Type }}, error) Prepend(parent, id string, value {{ .Type }}) error + Remove(id string) error Set(ids map[string][]string, values map[string]{{ .Type }}) error SetValue(id string, value {{ .Type }}) error } @@ -716,6 +761,28 @@ func (t *bound{{ .Name }}Tree) Prepend(parent, id string, val {{ .Type }}) error return t.doReload() } +func (t *bound{{ .Name }}Tree) Remove(id string) error { + t.lock.Lock() + defer t.lock.Unlock() + + t.removeChildren(id) + delete(t.ids, id) + v := *t.val + delete(v, id) + + return t.doReload() +} + +func (t *bound{{ .Name }}Tree) removeChildren(id string) { + for _, cid := range t.ids[id] { + t.removeChildren(cid) + + delete(t.ids, cid) + v := *t.val + delete(v, cid) + } +} + func (t *bound{{ .Name }}Tree) Reload() error { t.lock.Lock() defer t.lock.Unlock() From f28c6cf3a48ff031e481247d83a2771bb461ce40 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 15 Nov 2023 23:17:31 +0000 Subject: [PATCH 030/248] Add missing docs --- data/binding/bindlists.go | 24 ++++++++++++++++++++++++ data/binding/bindtrees.go | 32 ++++++++++++++++++++++++++++++++ data/binding/gen.go | 7 +++++++ 3 files changed, 63 insertions(+) diff --git a/data/binding/bindlists.go b/data/binding/bindlists.go index 0f2ad91d5f..a3d074fea9 100644 --- a/data/binding/bindlists.go +++ b/data/binding/bindlists.go @@ -107,6 +107,9 @@ func (l *boundBoolList) Reload() error { return l.doReload() } +// Remove takes the specified bool out of the list. +// +// Since: 2.5 func (l *boundBoolList) Remove(val bool) error { l.lock.Lock() defer l.lock.Unlock() @@ -358,6 +361,9 @@ func (l *boundBytesList) Reload() error { return l.doReload() } +// Remove takes the specified []byte out of the list. +// +// Since: 2.5 func (l *boundBytesList) Remove(val []byte) error { l.lock.Lock() defer l.lock.Unlock() @@ -609,6 +615,9 @@ func (l *boundFloatList) Reload() error { return l.doReload() } +// Remove takes the specified float64 out of the list. +// +// Since: 2.5 func (l *boundFloatList) Remove(val float64) error { l.lock.Lock() defer l.lock.Unlock() @@ -860,6 +869,9 @@ func (l *boundIntList) Reload() error { return l.doReload() } +// Remove takes the specified int out of the list. +// +// Since: 2.5 func (l *boundIntList) Remove(val int) error { l.lock.Lock() defer l.lock.Unlock() @@ -1111,6 +1123,9 @@ func (l *boundRuneList) Reload() error { return l.doReload() } +// Remove takes the specified rune out of the list. +// +// Since: 2.5 func (l *boundRuneList) Remove(val rune) error { l.lock.Lock() defer l.lock.Unlock() @@ -1362,6 +1377,9 @@ func (l *boundStringList) Reload() error { return l.doReload() } +// Remove takes the specified string out of the list. +// +// Since: 2.5 func (l *boundStringList) Remove(val string) error { l.lock.Lock() defer l.lock.Unlock() @@ -1613,6 +1631,9 @@ func (l *boundUntypedList) Reload() error { return l.doReload() } +// Remove takes the specified interface{} out of the list. +// +// Since: 2.5 func (l *boundUntypedList) Remove(val interface{}) error { l.lock.Lock() defer l.lock.Unlock() @@ -1864,6 +1885,9 @@ func (l *boundURIList) Reload() error { return l.doReload() } +// Remove takes the specified fyne.URI out of the list. +// +// Since: 2.5 func (l *boundURIList) Remove(val fyne.URI) error { l.lock.Lock() defer l.lock.Unlock() diff --git a/data/binding/bindtrees.go b/data/binding/bindtrees.go index 07d5f77612..d7f39e1d82 100644 --- a/data/binding/bindtrees.go +++ b/data/binding/bindtrees.go @@ -121,6 +121,10 @@ func (t *boundBoolTree) Prepend(parent, id string, val bool) error { return t.doReload() } +// Remove takes the specified id out of the tree. +// It will also remove any child items from the data structure. +// +// Since: 2.5 func (t *boundBoolTree) Remove(id string) error { t.lock.Lock() defer t.lock.Unlock() @@ -402,6 +406,10 @@ func (t *boundBytesTree) Prepend(parent, id string, val []byte) error { return t.doReload() } +// Remove takes the specified id out of the tree. +// It will also remove any child items from the data structure. +// +// Since: 2.5 func (t *boundBytesTree) Remove(id string) error { t.lock.Lock() defer t.lock.Unlock() @@ -683,6 +691,10 @@ func (t *boundFloatTree) Prepend(parent, id string, val float64) error { return t.doReload() } +// Remove takes the specified id out of the tree. +// It will also remove any child items from the data structure. +// +// Since: 2.5 func (t *boundFloatTree) Remove(id string) error { t.lock.Lock() defer t.lock.Unlock() @@ -964,6 +976,10 @@ func (t *boundIntTree) Prepend(parent, id string, val int) error { return t.doReload() } +// Remove takes the specified id out of the tree. +// It will also remove any child items from the data structure. +// +// Since: 2.5 func (t *boundIntTree) Remove(id string) error { t.lock.Lock() defer t.lock.Unlock() @@ -1245,6 +1261,10 @@ func (t *boundRuneTree) Prepend(parent, id string, val rune) error { return t.doReload() } +// Remove takes the specified id out of the tree. +// It will also remove any child items from the data structure. +// +// Since: 2.5 func (t *boundRuneTree) Remove(id string) error { t.lock.Lock() defer t.lock.Unlock() @@ -1526,6 +1546,10 @@ func (t *boundStringTree) Prepend(parent, id string, val string) error { return t.doReload() } +// Remove takes the specified id out of the tree. +// It will also remove any child items from the data structure. +// +// Since: 2.5 func (t *boundStringTree) Remove(id string) error { t.lock.Lock() defer t.lock.Unlock() @@ -1807,6 +1831,10 @@ func (t *boundUntypedTree) Prepend(parent, id string, val interface{}) error { return t.doReload() } +// Remove takes the specified id out of the tree. +// It will also remove any child items from the data structure. +// +// Since: 2.5 func (t *boundUntypedTree) Remove(id string) error { t.lock.Lock() defer t.lock.Unlock() @@ -2088,6 +2116,10 @@ func (t *boundURITree) Prepend(parent, id string, val fyne.URI) error { return t.doReload() } +// Remove takes the specified id out of the tree. +// It will also remove any child items from the data structure. +// +// Since: 2.5 func (t *boundURITree) Remove(id string) error { t.lock.Lock() defer t.lock.Unlock() diff --git a/data/binding/gen.go b/data/binding/gen.go index dc9e06a9a9..cc697b04c8 100644 --- a/data/binding/gen.go +++ b/data/binding/gen.go @@ -473,6 +473,9 @@ func (l *bound{{ .Name }}List) Reload() error { return l.doReload() } +// Remove takes the specified {{ .Type }} out of the list. +// +// Since: 2.5 func (l *bound{{ .Name }}List) Remove(val {{ .Type }}) error { l.lock.Lock() defer l.lock.Unlock() @@ -761,6 +764,10 @@ func (t *bound{{ .Name }}Tree) Prepend(parent, id string, val {{ .Type }}) error return t.doReload() } +// Remove takes the specified id out of the tree. +// It will also remove any child items from the data structure. +// +// Since: 2.5 func (t *bound{{ .Name }}Tree) Remove(id string) error { t.lock.Lock() defer t.lock.Unlock() From e653a65a12874c969bfbe7e55ca8b3aeec8d7cf6 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Thu, 16 Nov 2023 22:06:03 +0000 Subject: [PATCH 031/248] Test removal --- data/binding/bindlists_test.go | 10 ++++++++++ data/binding/bindtrees_test.go | 13 +++++++++++++ 2 files changed, 23 insertions(+) diff --git a/data/binding/bindlists_test.go b/data/binding/bindlists_test.go index 1a0fa9c7bb..41b32a46bd 100644 --- a/data/binding/bindlists_test.go +++ b/data/binding/bindlists_test.go @@ -121,6 +121,16 @@ func TestFloatList_GetValue(t *testing.T) { assert.Equal(t, 0.5, v) } +func TestFloatList_Remove(t *testing.T) { + f := NewFloatList() + f.Append(0.5) + f.Append(0.3) + assert.Equal(t, 2, f.Length()) + + f.Remove(0.5) + assert.Equal(t, 1, f.Length()) +} + func TestFloatList_Set(t *testing.T) { l := []float64{1.0, 5.0, 2.3} f := BindFloatList(&l) diff --git a/data/binding/bindtrees_test.go b/data/binding/bindtrees_test.go index 9f84d26f97..579ca01ed3 100644 --- a/data/binding/bindtrees_test.go +++ b/data/binding/bindtrees_test.go @@ -123,6 +123,19 @@ func TestStringTree_GetValue(t *testing.T) { assert.Equal(t, "0.5", v) } +func TestStringTree_Remove(t *testing.T) { + f := NewStringTree() + f.Append(DataTreeRootID, "5", "five") + f.Append(DataTreeRootID, "3", "three") + f.Append("5", "53", "fifty three") + assert.Equal(t, 2, len(f.ChildIDs(DataTreeRootID))) + assert.Equal(t, 1, len(f.ChildIDs("5"))) + + f.Remove("5") + assert.Equal(t, 1, len(f.ChildIDs(DataTreeRootID))) + assert.Equal(t, 0, len(f.ChildIDs("5"))) +} + func TestFloatTree_Set(t *testing.T) { ids := map[string][]string{"": {"1", "2"}, "1": {"3"}} m := map[string]float64{"1": 1.0, "2": 5.0, "3": 2.3} From fc46552fd9f6b69fb92c34650fb9d7154a6cddd2 Mon Sep 17 00:00:00 2001 From: lucor Date: Sun, 5 Nov 2023 12:27:14 +0100 Subject: [PATCH 032/248] systray: ensure title is not empty Some desktop environments like the one provided by Ubuntu 22.04 requires the systray title to be not empty to be displayed. This commit ensure the title is always set trying to use the app name from metadata. If the app name is not set will fallback to the app ID Fixes #3678 --- internal/driver/glfw/driver_desktop.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/driver/glfw/driver_desktop.go b/internal/driver/glfw/driver_desktop.go index 6d6fd635cc..7d3ccfb8de 100644 --- a/internal/driver/glfw/driver_desktop.go +++ b/internal/driver/glfw/driver_desktop.go @@ -46,6 +46,12 @@ func (d *gLDriver) SetSystemTrayMenu(m *fyne.Menu) { d.SetSystemTrayIcon(theme.BrokenImageIcon()) } + title := fyne.CurrentApp().Metadata().Name + if title == "" { + title = fyne.CurrentApp().UniqueID() + } + systray.SetTitle(title) + // it must be refreshed after init, so an earlier call would have been ineffective d.refreshSystray(m) }, func() { From 031f3c63fdeffa9fd6fbec64794fb6e31cc38e6f Mon Sep 17 00:00:00 2001 From: Luca Corbo Date: Tue, 7 Nov 2023 14:20:35 +0100 Subject: [PATCH 033/248] Update internal/driver/glfw/driver_desktop.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jacob Alzén --- internal/driver/glfw/driver_desktop.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/driver/glfw/driver_desktop.go b/internal/driver/glfw/driver_desktop.go index 7d3ccfb8de..5660d745ed 100644 --- a/internal/driver/glfw/driver_desktop.go +++ b/internal/driver/glfw/driver_desktop.go @@ -46,9 +46,10 @@ func (d *gLDriver) SetSystemTrayMenu(m *fyne.Menu) { d.SetSystemTrayIcon(theme.BrokenImageIcon()) } - title := fyne.CurrentApp().Metadata().Name + app := fyne.CurrentApp() + title := app.Metadata().Name if title == "" { - title = fyne.CurrentApp().UniqueID() + title = app.UniqueID() } systray.SetTitle(title) From 48af0ad5112159d85d5855e4aae4d9423f120cbc Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 15 Nov 2023 14:01:07 +0000 Subject: [PATCH 034/248] upgrade systray --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0c9b4c4d46..ad1cf1ccac 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module fyne.io/fyne/v2 go 1.17 require ( - fyne.io/systray v1.10.1-0.20230722100817-88df1e0ffa9a + fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e github.com/BurntSushi/toml v1.3.2 github.com/fogleman/gg v1.3.0 github.com/fredbi/uri v1.0.0 diff --git a/go.sum b/go.sum index 0e6301abae..8dc553595e 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -fyne.io/systray v1.10.1-0.20230722100817-88df1e0ffa9a h1:6Xf9fP3/mt72NrqlQhJWhQGcNf6GoG9X96NTaXr+K6A= -fyne.io/systray v1.10.1-0.20230722100817-88df1e0ffa9a/go.mod h1:oM2AQqGJ1AMo4nNqZFYU8xYygSBZkW2hmdJ7n4yjedE= +fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e h1:Hvs+kW2VwCzNToF3FmnIAzmivNgrclwPgoUdVSrjkP8= +fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e/go.mod h1:oM2AQqGJ1AMo4nNqZFYU8xYygSBZkW2hmdJ7n4yjedE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= From 2e440819a8a7994594e6770b9603a806d564c20b Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Tue, 7 Nov 2023 17:21:03 -0800 Subject: [PATCH 035/248] avoid allocation on every drawSingleFrame --- internal/driver/glfw/loop.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/driver/glfw/loop.go b/internal/driver/glfw/loop.go index 34c5c2ecc4..5094b64bb3 100644 --- a/internal/driver/glfw/loop.go +++ b/internal/driver/glfw/loop.go @@ -74,8 +74,15 @@ func runOnDraw(w *window, f func()) { <-done } +// Preallocate to avoid allocations on every drawSingleFrame. +// Note that the capacity of this slice can only grow, +// but its length will never be longer than the total number of +// window canvases that are dirty on a single frame. +// So its memory impact should be negligible and does not +// need periodic shrinking. +var refreshingCanvases = make([]fyne.Canvas, 0) + func (d *gLDriver) drawSingleFrame() { - refreshingCanvases := make([]fyne.Canvas, 0) for _, win := range d.windowList() { w := win.(*window) w.viewLock.RLock() @@ -96,6 +103,12 @@ func (d *gLDriver) drawSingleFrame() { refreshingCanvases = append(refreshingCanvases, canvas) } cache.CleanCanvases(refreshingCanvases) + + // cleanup refreshingCanvases slice + for i := 0; i < len(refreshingCanvases); i++ { + refreshingCanvases[i] = nil + } + refreshingCanvases = refreshingCanvases[:0] } func (d *gLDriver) runGL() { From 64a995b7d5ebe2bb213dbd056b579e521e35f241 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Wed, 8 Nov 2023 13:44:06 -0800 Subject: [PATCH 036/248] commit jacalz's suggestion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jacob Alzén --- internal/driver/glfw/loop.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/driver/glfw/loop.go b/internal/driver/glfw/loop.go index 5094b64bb3..9098f39d01 100644 --- a/internal/driver/glfw/loop.go +++ b/internal/driver/glfw/loop.go @@ -80,7 +80,7 @@ func runOnDraw(w *window, f func()) { // window canvases that are dirty on a single frame. // So its memory impact should be negligible and does not // need periodic shrinking. -var refreshingCanvases = make([]fyne.Canvas, 0) +var refreshingCanvases []fyne.Canvas func (d *gLDriver) drawSingleFrame() { for _, win := range d.windowList() { From 37ae73b6536b2f01a375ca8294ed664264dd9210 Mon Sep 17 00:00:00 2001 From: Kirubel Adamu Date: Fri, 3 Nov 2023 11:22:24 +0300 Subject: [PATCH 037/248] updated URI.Extension() documentation Updated URI.Extension() documentation to clarify that it returns the extension with the dot included. --- uri.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uri.go b/uri.go index 36e5373116..c663728f8c 100644 --- a/uri.go +++ b/uri.go @@ -33,9 +33,9 @@ type URI interface { fmt.Stringer // Extension should return the file extension of the resource - // referenced by the URI. For example, the Extension() of - // 'file://foo/bar.baz' is 'baz'. May return an empty string if the - // referenced resource has none. + // (including the dot) referenced by the URI. For example, the + // Extension() of 'file://foo/bar.baz' is '.baz'. May return an + // empty string if the referenced resource has none. Extension() string // Name should return the base name of the item referenced by the URI. From 103eeb8d3f390ad1eab36e84cbe7401b134e6bfa Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 5 Nov 2023 09:28:04 -0800 Subject: [PATCH 038/248] fix lint - trailing space --- uri.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uri.go b/uri.go index c663728f8c..3bab3532ff 100644 --- a/uri.go +++ b/uri.go @@ -33,7 +33,7 @@ type URI interface { fmt.Stringer // Extension should return the file extension of the resource - // (including the dot) referenced by the URI. For example, the + // (including the dot) referenced by the URI. For example, the // Extension() of 'file://foo/bar.baz' is '.baz'. May return an // empty string if the referenced resource has none. Extension() string From 2efb0f2825e1d0953e1c532b31d63b2ba0487470 Mon Sep 17 00:00:00 2001 From: Michael B Date: Tue, 10 Oct 2023 02:21:15 +0300 Subject: [PATCH 039/248] add canvas refresh in richtext refresh ensures refresh happens even when segment slice completely replaced --- widget/richtext.go | 1 + 1 file changed, 1 insertion(+) diff --git a/widget/richtext.go b/widget/richtext.go index 9ef858d79e..6b14fb9f71 100644 --- a/widget/richtext.go +++ b/widget/richtext.go @@ -707,6 +707,7 @@ func (r *textRenderer) Refresh() { r.obj.propertyLock.Unlock() r.Layout(r.obj.Size()) + canvas.Refresh(r.obj.super()) } func (r *textRenderer) layoutRow(texts []fyne.CanvasObject, align fyne.TextAlign, xPos, yPos, lineWidth float32) (float32, float32) { From 5816efc6b47d824fd9c89ba54b4c3573046ebc8f Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 17 Oct 2023 21:02:29 +0200 Subject: [PATCH 040/248] Update golang.or/x/sys to bring in security fix --- go.mod | 6 +++--- go.sum | 11 ++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ad1cf1ccac..899268e30d 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( golang.org/x/image v0.11.0 golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda golang.org/x/mod v0.12.0 - golang.org/x/sys v0.11.0 + golang.org/x/sys v0.13.0 golang.org/x/tools v0.12.0 honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 ) @@ -45,7 +45,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/tevino/abool v1.2.0 // indirect - golang.org/x/net v0.14.0 // indirect - golang.org/x/text v0.12.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/text v0.13.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 8dc553595e..79b30237b6 100644 --- a/go.sum +++ b/go.sum @@ -338,6 +338,7 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -429,8 +430,9 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -515,14 +517,16 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -535,8 +539,9 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From d6661c68ef4915d0c2726270dcefd789549521da Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Tue, 17 Oct 2023 09:25:45 -0700 Subject: [PATCH 041/248] Prepping for v2.4.2 --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56ff51be04..d4005e85cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,16 @@ More detailed release notes can be found on the [releases page](https://github.c * Spacer in HBox with hidden item will cause an additional trailing padding (#4259) * Application crash when fast clicking the folders inside the file dialog (#4260) * failed to initialise OpenGL (#437) +* App panic when clicking on a notification panel if there's a systray icon (#4385) +* Systray cannot be shown on Ubuntu (#3678, #4381) +* failed to initialise OpenGL on Windows dual-chip graphics cards (#437) +* Reduce memory allocations for each frame painted +* RichText may not refresh if segments manually replaced +* Correct URI.Extension() documentation +* Update for security fixes to x/sys and x/net -## 2.4.1 - 8 October 2023 +## 2.4.1 - 9 October 2023 ### Fixed From 4ff741f28c7c52bc4b763b3bfb119a9ea127e2cb Mon Sep 17 00:00:00 2001 From: Paul C Brown Date: Thu, 21 Sep 2023 03:00:30 -0400 Subject: [PATCH 042/248] Make Button rendering consistent (#4246) Changed the default rendering of Button so that the animation background rectangle starts off with the same rendering as it has after the button has been clicked --- container/testdata/apptabs/desktop/hover_overflow.xml | 2 +- container/testdata/apptabs/desktop/tab_location_bottom.xml | 2 +- .../testdata/apptabs/desktop/tab_location_leading.xml | 2 +- container/testdata/apptabs/desktop/tab_location_top.xml | 2 +- .../testdata/apptabs/desktop/tab_location_trailing.xml | 2 +- .../testdata/apptabs/desktop/tapped_overflow_tabs.xml | 2 +- container/testdata/apptabs/mobile/tab_location_bottom.xml | 2 +- container/testdata/apptabs/mobile/tab_location_top.xml | 2 +- .../doctabs/desktop/change_content_change_hidden.xml | 2 +- .../doctabs/desktop/change_content_change_visible.xml | 2 +- .../testdata/doctabs/desktop/change_content_initial.xml | 2 +- .../doctabs/desktop/change_icon_change_selected.xml | 2 +- .../doctabs/desktop/change_icon_change_unselected.xml | 2 +- container/testdata/doctabs/desktop/change_icon_initial.xml | 2 +- .../doctabs/desktop/change_label_change_selected.xml | 2 +- .../doctabs/desktop/change_label_change_unselected.xml | 2 +- .../testdata/doctabs/desktop/change_label_initial.xml | 2 +- .../desktop/change_label_to_longer_text_selected.xml | 2 +- container/testdata/doctabs/desktop/dynamic_appended.xml | 2 +- .../doctabs/desktop/dynamic_appended_and_removed.xml | 2 +- .../doctabs/desktop/dynamic_appended_another_three.xml | 2 +- container/testdata/doctabs/desktop/dynamic_initial.xml | 2 +- .../doctabs/desktop/dynamic_replaced_completely.xml | 2 +- container/testdata/doctabs/desktop/hover_all_tabs.xml | 4 ++-- container/testdata/doctabs/desktop/hover_create_tab.xml | 4 ++-- container/testdata/doctabs/desktop/hover_first.xml | 4 ++-- container/testdata/doctabs/desktop/hover_first_close.xml | 4 ++-- container/testdata/doctabs/desktop/hover_none.xml | 4 ++-- container/testdata/doctabs/desktop/hover_second.xml | 4 ++-- container/testdata/doctabs/desktop/layout_bottom_icon.xml | 2 +- .../doctabs/desktop/layout_bottom_icon_and_text.xml | 2 +- container/testdata/doctabs/desktop/layout_bottom_text.xml | 2 +- container/testdata/doctabs/desktop/layout_leading_icon.xml | 2 +- .../doctabs/desktop/layout_leading_icon_and_text.xml | 2 +- container/testdata/doctabs/desktop/layout_leading_text.xml | 2 +- container/testdata/doctabs/desktop/layout_top_icon.xml | 2 +- .../testdata/doctabs/desktop/layout_top_icon_and_text.xml | 2 +- container/testdata/doctabs/desktop/layout_top_text.xml | 2 +- .../testdata/doctabs/desktop/layout_trailing_icon.xml | 2 +- .../doctabs/desktop/layout_trailing_icon_and_text.xml | 2 +- .../testdata/doctabs/desktop/layout_trailing_text.xml | 2 +- container/testdata/doctabs/desktop/tab_location_bottom.xml | 2 +- .../testdata/doctabs/desktop/tab_location_leading.xml | 2 +- container/testdata/doctabs/desktop/tab_location_top.xml | 2 +- .../testdata/doctabs/desktop/tab_location_trailing.xml | 2 +- container/testdata/doctabs/desktop/tapped_all_tabs.xml | 4 ++-- container/testdata/doctabs/desktop/tapped_create_tab.xml | 4 ++-- .../testdata/doctabs/desktop/tapped_first_selected.xml | 4 ++-- .../testdata/doctabs/desktop/tapped_second_selected.xml | 4 ++-- .../testdata/doctabs/desktop/tapped_third_selected.xml | 4 ++-- .../doctabs/mobile/change_content_change_hidden.xml | 2 +- .../doctabs/mobile/change_content_change_visible.xml | 2 +- .../testdata/doctabs/mobile/change_content_initial.xml | 2 +- .../doctabs/mobile/change_icon_change_selected.xml | 2 +- .../doctabs/mobile/change_icon_change_unselected.xml | 2 +- container/testdata/doctabs/mobile/change_icon_initial.xml | 2 +- .../doctabs/mobile/change_label_change_selected.xml | 2 +- .../doctabs/mobile/change_label_change_unselected.xml | 2 +- container/testdata/doctabs/mobile/change_label_initial.xml | 2 +- container/testdata/doctabs/mobile/dynamic_appended.xml | 2 +- .../doctabs/mobile/dynamic_appended_and_removed.xml | 2 +- .../doctabs/mobile/dynamic_appended_another_three.xml | 2 +- container/testdata/doctabs/mobile/dynamic_initial.xml | 2 +- .../doctabs/mobile/dynamic_replaced_completely.xml | 2 +- container/testdata/doctabs/mobile/hover_none.xml | 2 +- container/testdata/doctabs/mobile/layout_bottom_ico.xml | 2 +- .../doctabs/mobile/layout_bottom_icon_and_text.xml | 2 +- container/testdata/doctabs/mobile/layout_bottom_text.xml | 2 +- container/testdata/doctabs/mobile/layout_top_icon.xml | 2 +- .../testdata/doctabs/mobile/layout_top_icon_and_text.xml | 2 +- container/testdata/doctabs/mobile/layout_top_text.xml | 2 +- container/testdata/doctabs/mobile/tab_location_bottom.xml | 2 +- container/testdata/doctabs/mobile/tab_location_top.xml | 2 +- container/testdata/doctabs/mobile/tapped_all_tabs.xml | 4 ++-- container/testdata/doctabs/mobile/tapped_create_tab.xml | 4 ++-- .../testdata/doctabs/mobile/tapped_first_selected.xml | 4 ++-- .../testdata/doctabs/mobile/tapped_second_selected.xml | 4 ++-- .../testdata/doctabs/mobile/tapped_third_selected.xml | 4 ++-- dialog/testdata/dialog-custom-custom-buttons.xml | 6 +++--- widget/button.go | 7 ++++++- .../layout_expanded_multiple_open_multiple_items.xml | 4 ++-- ...layout_expanded_multiple_open_multiple_items_opened.xml | 4 ++-- .../accordion/layout_expanded_multiple_open_one_item.xml | 2 +- .../layout_expanded_multiple_open_one_item_opened.xml | 2 +- .../layout_expanded_single_open_multiple_items.xml | 4 ++-- .../layout_expanded_single_open_multiple_items_opened.xml | 4 ++-- .../accordion/layout_expanded_single_open_one_item.xml | 2 +- .../layout_expanded_single_open_one_item_opened.xml | 2 +- .../accordion/layout_multiple_open_multiple_items.xml | 4 ++-- .../layout_multiple_open_multiple_items_opened.xml | 4 ++-- .../testdata/accordion/layout_multiple_open_one_item.xml | 2 +- .../accordion/layout_multiple_open_one_item_opened.xml | 2 +- .../accordion/layout_single_open_multiple_items.xml | 4 ++-- .../accordion/layout_single_open_multiple_items_opened.xml | 4 ++-- widget/testdata/accordion/layout_single_open_one_item.xml | 2 +- .../accordion/layout_single_open_one_item_opened.xml | 2 +- widget/testdata/button/layout_icon_only_center_leading.xml | 2 +- .../testdata/button/layout_icon_only_center_trailing.xml | 2 +- .../testdata/button/layout_icon_only_leading_leading.xml | 2 +- .../testdata/button/layout_icon_only_leading_trailing.xml | 2 +- .../testdata/button/layout_icon_only_trailing_leading.xml | 2 +- .../testdata/button/layout_icon_only_trailing_trailing.xml | 2 +- widget/testdata/button/layout_text_icon_center_leading.xml | 2 +- .../testdata/button/layout_text_icon_center_trailing.xml | 2 +- .../testdata/button/layout_text_icon_leading_leading.xml | 2 +- .../testdata/button/layout_text_icon_leading_trailing.xml | 2 +- .../testdata/button/layout_text_icon_trailing_leading.xml | 2 +- .../testdata/button/layout_text_icon_trailing_trailing.xml | 2 +- widget/testdata/button/layout_text_only_center_leading.xml | 2 +- .../testdata/button/layout_text_only_center_trailing.xml | 2 +- .../testdata/button/layout_text_only_leading_leading.xml | 2 +- .../testdata/button/layout_text_only_leading_trailing.xml | 2 +- widget/testdata/button/layout_text_only_multiline.xml | 2 +- .../testdata/button/layout_text_only_trailing_leading.xml | 2 +- .../testdata/button/layout_text_only_trailing_trailing.xml | 2 +- widget/testdata/form/extended_entry.xml | 2 +- widget/testdata/form/layout.xml | 4 ++-- widget/testdata/select/center.xml | 2 +- widget/testdata/select/layout_empty_expanded.xml | 2 +- .../testdata/select/layout_empty_expanded_placeholder.xml | 2 +- widget/testdata/select/layout_multiple_expanded.xml | 2 +- .../select/layout_multiple_expanded_placeholder.xml | 2 +- .../testdata/select/layout_multiple_expanded_selected.xml | 2 +- .../layout_multiple_expanded_selected_placeholder.xml | 2 +- widget/testdata/select/layout_single_expanded.xml | 2 +- .../testdata/select/layout_single_expanded_placeholder.xml | 2 +- widget/testdata/select/layout_single_expanded_selected.xml | 2 +- .../select/layout_single_expanded_selected_placeholder.xml | 2 +- widget/testdata/select/move_moved.xml | 2 +- widget/testdata/select/move_tapped.xml | 2 +- widget/testdata/select/tapped.xml | 2 +- widget/testdata/select/tapped_constrained.xml | 2 +- widget/testdata/select/trailing.xml | 2 +- widget/testdata/select_entry/disableable_disabled.xml | 2 +- widget/testdata/select_entry/disableable_enabled.xml | 2 +- .../testdata/select_entry/disableable_enabled_opened.xml | 2 +- .../testdata/select_entry/disableable_enabled_tapped.xml | 2 +- .../select_entry/disableable_enabled_tapped_selected.xml | 2 +- widget/testdata/select_entry/dropdown_B_opened.xml | 2 +- widget/testdata/select_entry/dropdown_empty_opened.xml | 2 +- .../testdata/select_entry/dropdown_empty_opened_shrunk.xml | 2 +- widget/testdata/select_entry/dropdown_empty_setopts.xml | 2 +- widget/testdata/select_entry/dropdown_initial.xml | 2 +- widget/testdata/select_entry/dropdown_tapped_B.xml | 2 +- widget/testdata/select_entry/dropdown_tapped_C.xml | 2 +- 145 files changed, 177 insertions(+), 172 deletions(-) diff --git a/container/testdata/apptabs/desktop/hover_overflow.xml b/container/testdata/apptabs/desktop/hover_overflow.xml index 0e2a72050b..5fa6d5934e 100644 --- a/container/testdata/apptabs/desktop/hover_overflow.xml +++ b/container/testdata/apptabs/desktop/hover_overflow.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/apptabs/desktop/tab_location_bottom.xml b/container/testdata/apptabs/desktop/tab_location_bottom.xml index aa2101693d..db00c81d97 100644 --- a/container/testdata/apptabs/desktop/tab_location_bottom.xml +++ b/container/testdata/apptabs/desktop/tab_location_bottom.xml @@ -9,7 +9,7 @@ - + diff --git a/container/testdata/apptabs/desktop/tab_location_leading.xml b/container/testdata/apptabs/desktop/tab_location_leading.xml index 4491abdf4e..e30be399b8 100644 --- a/container/testdata/apptabs/desktop/tab_location_leading.xml +++ b/container/testdata/apptabs/desktop/tab_location_leading.xml @@ -9,7 +9,7 @@ - + diff --git a/container/testdata/apptabs/desktop/tab_location_top.xml b/container/testdata/apptabs/desktop/tab_location_top.xml index da4308cb1c..104d3c56e9 100644 --- a/container/testdata/apptabs/desktop/tab_location_top.xml +++ b/container/testdata/apptabs/desktop/tab_location_top.xml @@ -9,7 +9,7 @@ - + diff --git a/container/testdata/apptabs/desktop/tab_location_trailing.xml b/container/testdata/apptabs/desktop/tab_location_trailing.xml index 1506ce501c..73a335bf94 100644 --- a/container/testdata/apptabs/desktop/tab_location_trailing.xml +++ b/container/testdata/apptabs/desktop/tab_location_trailing.xml @@ -9,7 +9,7 @@ - + diff --git a/container/testdata/apptabs/desktop/tapped_overflow_tabs.xml b/container/testdata/apptabs/desktop/tapped_overflow_tabs.xml index f06e12ae4d..6f59f1e409 100644 --- a/container/testdata/apptabs/desktop/tapped_overflow_tabs.xml +++ b/container/testdata/apptabs/desktop/tapped_overflow_tabs.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/apptabs/mobile/tab_location_bottom.xml b/container/testdata/apptabs/mobile/tab_location_bottom.xml index b4c44f05a9..0860774227 100644 --- a/container/testdata/apptabs/mobile/tab_location_bottom.xml +++ b/container/testdata/apptabs/mobile/tab_location_bottom.xml @@ -9,7 +9,7 @@ - + diff --git a/container/testdata/apptabs/mobile/tab_location_top.xml b/container/testdata/apptabs/mobile/tab_location_top.xml index fa522452df..3e077a04df 100644 --- a/container/testdata/apptabs/mobile/tab_location_top.xml +++ b/container/testdata/apptabs/mobile/tab_location_top.xml @@ -9,7 +9,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_content_change_hidden.xml b/container/testdata/doctabs/desktop/change_content_change_hidden.xml index aa945434e0..7e40307730 100644 --- a/container/testdata/doctabs/desktop/change_content_change_hidden.xml +++ b/container/testdata/doctabs/desktop/change_content_change_hidden.xml @@ -23,7 +23,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_content_change_visible.xml b/container/testdata/doctabs/desktop/change_content_change_visible.xml index aa945434e0..7e40307730 100644 --- a/container/testdata/doctabs/desktop/change_content_change_visible.xml +++ b/container/testdata/doctabs/desktop/change_content_change_visible.xml @@ -23,7 +23,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_content_initial.xml b/container/testdata/doctabs/desktop/change_content_initial.xml index 354af74cb7..b6806c6d75 100644 --- a/container/testdata/doctabs/desktop/change_content_initial.xml +++ b/container/testdata/doctabs/desktop/change_content_initial.xml @@ -23,7 +23,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_icon_change_selected.xml b/container/testdata/doctabs/desktop/change_icon_change_selected.xml index 509b4c6620..dd2f4f5404 100644 --- a/container/testdata/doctabs/desktop/change_icon_change_selected.xml +++ b/container/testdata/doctabs/desktop/change_icon_change_selected.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_icon_change_unselected.xml b/container/testdata/doctabs/desktop/change_icon_change_unselected.xml index 050072b023..023eb33e1b 100644 --- a/container/testdata/doctabs/desktop/change_icon_change_unselected.xml +++ b/container/testdata/doctabs/desktop/change_icon_change_unselected.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_icon_initial.xml b/container/testdata/doctabs/desktop/change_icon_initial.xml index c7d976a0d8..eee5a47fac 100644 --- a/container/testdata/doctabs/desktop/change_icon_initial.xml +++ b/container/testdata/doctabs/desktop/change_icon_initial.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_label_change_selected.xml b/container/testdata/doctabs/desktop/change_label_change_selected.xml index eac41ce872..9aea6216c3 100644 --- a/container/testdata/doctabs/desktop/change_label_change_selected.xml +++ b/container/testdata/doctabs/desktop/change_label_change_selected.xml @@ -23,7 +23,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_label_change_unselected.xml b/container/testdata/doctabs/desktop/change_label_change_unselected.xml index 61b869fe93..20f093dd52 100644 --- a/container/testdata/doctabs/desktop/change_label_change_unselected.xml +++ b/container/testdata/doctabs/desktop/change_label_change_unselected.xml @@ -23,7 +23,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_label_initial.xml b/container/testdata/doctabs/desktop/change_label_initial.xml index 354af74cb7..b6806c6d75 100644 --- a/container/testdata/doctabs/desktop/change_label_initial.xml +++ b/container/testdata/doctabs/desktop/change_label_initial.xml @@ -23,7 +23,7 @@ - + diff --git a/container/testdata/doctabs/desktop/change_label_to_longer_text_selected.xml b/container/testdata/doctabs/desktop/change_label_to_longer_text_selected.xml index 6b0f2831de..90f2bd08c3 100644 --- a/container/testdata/doctabs/desktop/change_label_to_longer_text_selected.xml +++ b/container/testdata/doctabs/desktop/change_label_to_longer_text_selected.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/desktop/dynamic_appended.xml b/container/testdata/doctabs/desktop/dynamic_appended.xml index 0f18b9466a..04ae2fb5c6 100644 --- a/container/testdata/doctabs/desktop/dynamic_appended.xml +++ b/container/testdata/doctabs/desktop/dynamic_appended.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/desktop/dynamic_appended_and_removed.xml b/container/testdata/doctabs/desktop/dynamic_appended_and_removed.xml index 4f6a8a9786..a2c382bc9e 100644 --- a/container/testdata/doctabs/desktop/dynamic_appended_and_removed.xml +++ b/container/testdata/doctabs/desktop/dynamic_appended_and_removed.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/dynamic_appended_another_three.xml b/container/testdata/doctabs/desktop/dynamic_appended_another_three.xml index 5f85c42dec..0c80949d85 100644 --- a/container/testdata/doctabs/desktop/dynamic_appended_another_three.xml +++ b/container/testdata/doctabs/desktop/dynamic_appended_another_three.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/desktop/dynamic_initial.xml b/container/testdata/doctabs/desktop/dynamic_initial.xml index 8133a28245..408b09d6fb 100644 --- a/container/testdata/doctabs/desktop/dynamic_initial.xml +++ b/container/testdata/doctabs/desktop/dynamic_initial.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/dynamic_replaced_completely.xml b/container/testdata/doctabs/desktop/dynamic_replaced_completely.xml index d668d2870d..2e092ba78d 100644 --- a/container/testdata/doctabs/desktop/dynamic_replaced_completely.xml +++ b/container/testdata/doctabs/desktop/dynamic_replaced_completely.xml @@ -18,7 +18,7 @@ - + diff --git a/container/testdata/doctabs/desktop/hover_all_tabs.xml b/container/testdata/doctabs/desktop/hover_all_tabs.xml index 0daf3e6770..6d70345e15 100644 --- a/container/testdata/doctabs/desktop/hover_all_tabs.xml +++ b/container/testdata/doctabs/desktop/hover_all_tabs.xml @@ -23,12 +23,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/hover_create_tab.xml b/container/testdata/doctabs/desktop/hover_create_tab.xml index dc9f06267b..70a1ee8722 100644 --- a/container/testdata/doctabs/desktop/hover_create_tab.xml +++ b/container/testdata/doctabs/desktop/hover_create_tab.xml @@ -23,12 +23,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/hover_first.xml b/container/testdata/doctabs/desktop/hover_first.xml index cccd88f86c..e790ea6c0f 100644 --- a/container/testdata/doctabs/desktop/hover_first.xml +++ b/container/testdata/doctabs/desktop/hover_first.xml @@ -27,12 +27,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/hover_first_close.xml b/container/testdata/doctabs/desktop/hover_first_close.xml index dc9f06267b..70a1ee8722 100644 --- a/container/testdata/doctabs/desktop/hover_first_close.xml +++ b/container/testdata/doctabs/desktop/hover_first_close.xml @@ -23,12 +23,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/hover_none.xml b/container/testdata/doctabs/desktop/hover_none.xml index fc6ccb6ad1..9238870cd7 100644 --- a/container/testdata/doctabs/desktop/hover_none.xml +++ b/container/testdata/doctabs/desktop/hover_none.xml @@ -23,12 +23,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/hover_second.xml b/container/testdata/doctabs/desktop/hover_second.xml index dc9f06267b..70a1ee8722 100644 --- a/container/testdata/doctabs/desktop/hover_second.xml +++ b/container/testdata/doctabs/desktop/hover_second.xml @@ -23,12 +23,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/layout_bottom_icon.xml b/container/testdata/doctabs/desktop/layout_bottom_icon.xml index a3386be2a2..df477efb78 100644 --- a/container/testdata/doctabs/desktop/layout_bottom_icon.xml +++ b/container/testdata/doctabs/desktop/layout_bottom_icon.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_bottom_icon_and_text.xml b/container/testdata/doctabs/desktop/layout_bottom_icon_and_text.xml index a9bae05b14..b7582a83b4 100644 --- a/container/testdata/doctabs/desktop/layout_bottom_icon_and_text.xml +++ b/container/testdata/doctabs/desktop/layout_bottom_icon_and_text.xml @@ -13,7 +13,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_bottom_text.xml b/container/testdata/doctabs/desktop/layout_bottom_text.xml index d92591475c..0d5725dfed 100644 --- a/container/testdata/doctabs/desktop/layout_bottom_text.xml +++ b/container/testdata/doctabs/desktop/layout_bottom_text.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_leading_icon.xml b/container/testdata/doctabs/desktop/layout_leading_icon.xml index e3b82c37cf..9ed4062f8b 100644 --- a/container/testdata/doctabs/desktop/layout_leading_icon.xml +++ b/container/testdata/doctabs/desktop/layout_leading_icon.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_leading_icon_and_text.xml b/container/testdata/doctabs/desktop/layout_leading_icon_and_text.xml index 18a028a616..3ad2dda74d 100644 --- a/container/testdata/doctabs/desktop/layout_leading_icon_and_text.xml +++ b/container/testdata/doctabs/desktop/layout_leading_icon_and_text.xml @@ -13,7 +13,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_leading_text.xml b/container/testdata/doctabs/desktop/layout_leading_text.xml index 8d6b6b1b18..ed08c0184c 100644 --- a/container/testdata/doctabs/desktop/layout_leading_text.xml +++ b/container/testdata/doctabs/desktop/layout_leading_text.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_top_icon.xml b/container/testdata/doctabs/desktop/layout_top_icon.xml index b7401cfdd8..f2faf7b3cf 100644 --- a/container/testdata/doctabs/desktop/layout_top_icon.xml +++ b/container/testdata/doctabs/desktop/layout_top_icon.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_top_icon_and_text.xml b/container/testdata/doctabs/desktop/layout_top_icon_and_text.xml index dd42213281..ab7bf8f0b4 100644 --- a/container/testdata/doctabs/desktop/layout_top_icon_and_text.xml +++ b/container/testdata/doctabs/desktop/layout_top_icon_and_text.xml @@ -13,7 +13,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_top_text.xml b/container/testdata/doctabs/desktop/layout_top_text.xml index 73284ecdc6..2cbd507db2 100644 --- a/container/testdata/doctabs/desktop/layout_top_text.xml +++ b/container/testdata/doctabs/desktop/layout_top_text.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_trailing_icon.xml b/container/testdata/doctabs/desktop/layout_trailing_icon.xml index 17a33b3cf0..9a3c5bfd1f 100644 --- a/container/testdata/doctabs/desktop/layout_trailing_icon.xml +++ b/container/testdata/doctabs/desktop/layout_trailing_icon.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_trailing_icon_and_text.xml b/container/testdata/doctabs/desktop/layout_trailing_icon_and_text.xml index ecf16c865e..9eb08deb0c 100644 --- a/container/testdata/doctabs/desktop/layout_trailing_icon_and_text.xml +++ b/container/testdata/doctabs/desktop/layout_trailing_icon_and_text.xml @@ -13,7 +13,7 @@ - + diff --git a/container/testdata/doctabs/desktop/layout_trailing_text.xml b/container/testdata/doctabs/desktop/layout_trailing_text.xml index c56abff84e..f4f90e9056 100644 --- a/container/testdata/doctabs/desktop/layout_trailing_text.xml +++ b/container/testdata/doctabs/desktop/layout_trailing_text.xml @@ -12,7 +12,7 @@ - + diff --git a/container/testdata/doctabs/desktop/tab_location_bottom.xml b/container/testdata/doctabs/desktop/tab_location_bottom.xml index 5191fb5122..26f1989548 100644 --- a/container/testdata/doctabs/desktop/tab_location_bottom.xml +++ b/container/testdata/doctabs/desktop/tab_location_bottom.xml @@ -26,7 +26,7 @@ - + diff --git a/container/testdata/doctabs/desktop/tab_location_leading.xml b/container/testdata/doctabs/desktop/tab_location_leading.xml index 9ac2e6898d..d8eeba8396 100644 --- a/container/testdata/doctabs/desktop/tab_location_leading.xml +++ b/container/testdata/doctabs/desktop/tab_location_leading.xml @@ -26,7 +26,7 @@ - + diff --git a/container/testdata/doctabs/desktop/tab_location_top.xml b/container/testdata/doctabs/desktop/tab_location_top.xml index 4fb8f5829a..470ac3f6d4 100644 --- a/container/testdata/doctabs/desktop/tab_location_top.xml +++ b/container/testdata/doctabs/desktop/tab_location_top.xml @@ -26,7 +26,7 @@ - + diff --git a/container/testdata/doctabs/desktop/tab_location_trailing.xml b/container/testdata/doctabs/desktop/tab_location_trailing.xml index b6e21a8911..2e5b318e81 100644 --- a/container/testdata/doctabs/desktop/tab_location_trailing.xml +++ b/container/testdata/doctabs/desktop/tab_location_trailing.xml @@ -26,7 +26,7 @@ - + diff --git a/container/testdata/doctabs/desktop/tapped_all_tabs.xml b/container/testdata/doctabs/desktop/tapped_all_tabs.xml index 24acd51009..a5a92b2161 100644 --- a/container/testdata/doctabs/desktop/tapped_all_tabs.xml +++ b/container/testdata/doctabs/desktop/tapped_all_tabs.xml @@ -29,12 +29,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/tapped_create_tab.xml b/container/testdata/doctabs/desktop/tapped_create_tab.xml index 68b78b240d..ab8c51f3b7 100644 --- a/container/testdata/doctabs/desktop/tapped_create_tab.xml +++ b/container/testdata/doctabs/desktop/tapped_create_tab.xml @@ -29,12 +29,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/tapped_first_selected.xml b/container/testdata/doctabs/desktop/tapped_first_selected.xml index 52de64cb9d..0dcf631cfa 100644 --- a/container/testdata/doctabs/desktop/tapped_first_selected.xml +++ b/container/testdata/doctabs/desktop/tapped_first_selected.xml @@ -26,12 +26,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/tapped_second_selected.xml b/container/testdata/doctabs/desktop/tapped_second_selected.xml index 1865f3c8c5..82360a1e7d 100644 --- a/container/testdata/doctabs/desktop/tapped_second_selected.xml +++ b/container/testdata/doctabs/desktop/tapped_second_selected.xml @@ -26,12 +26,12 @@ - + - + diff --git a/container/testdata/doctabs/desktop/tapped_third_selected.xml b/container/testdata/doctabs/desktop/tapped_third_selected.xml index 1bb613e9d1..5f4bc40757 100644 --- a/container/testdata/doctabs/desktop/tapped_third_selected.xml +++ b/container/testdata/doctabs/desktop/tapped_third_selected.xml @@ -26,12 +26,12 @@ - + - + diff --git a/container/testdata/doctabs/mobile/change_content_change_hidden.xml b/container/testdata/doctabs/mobile/change_content_change_hidden.xml index c1438ab9f3..300aea2165 100644 --- a/container/testdata/doctabs/mobile/change_content_change_hidden.xml +++ b/container/testdata/doctabs/mobile/change_content_change_hidden.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/change_content_change_visible.xml b/container/testdata/doctabs/mobile/change_content_change_visible.xml index c1438ab9f3..300aea2165 100644 --- a/container/testdata/doctabs/mobile/change_content_change_visible.xml +++ b/container/testdata/doctabs/mobile/change_content_change_visible.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/change_content_initial.xml b/container/testdata/doctabs/mobile/change_content_initial.xml index 8e168b83e2..9f24e17f28 100644 --- a/container/testdata/doctabs/mobile/change_content_initial.xml +++ b/container/testdata/doctabs/mobile/change_content_initial.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/change_icon_change_selected.xml b/container/testdata/doctabs/mobile/change_icon_change_selected.xml index 84828719c7..e0456fcfc3 100644 --- a/container/testdata/doctabs/mobile/change_icon_change_selected.xml +++ b/container/testdata/doctabs/mobile/change_icon_change_selected.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/change_icon_change_unselected.xml b/container/testdata/doctabs/mobile/change_icon_change_unselected.xml index 41eef7a8a2..d3123d2712 100644 --- a/container/testdata/doctabs/mobile/change_icon_change_unselected.xml +++ b/container/testdata/doctabs/mobile/change_icon_change_unselected.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/change_icon_initial.xml b/container/testdata/doctabs/mobile/change_icon_initial.xml index 74f9f1aded..8777680652 100644 --- a/container/testdata/doctabs/mobile/change_icon_initial.xml +++ b/container/testdata/doctabs/mobile/change_icon_initial.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/change_label_change_selected.xml b/container/testdata/doctabs/mobile/change_label_change_selected.xml index 0add78acf5..63a6859578 100644 --- a/container/testdata/doctabs/mobile/change_label_change_selected.xml +++ b/container/testdata/doctabs/mobile/change_label_change_selected.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/change_label_change_unselected.xml b/container/testdata/doctabs/mobile/change_label_change_unselected.xml index d3362c4f6e..11b5e1d393 100644 --- a/container/testdata/doctabs/mobile/change_label_change_unselected.xml +++ b/container/testdata/doctabs/mobile/change_label_change_unselected.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/change_label_initial.xml b/container/testdata/doctabs/mobile/change_label_initial.xml index 8e168b83e2..9f24e17f28 100644 --- a/container/testdata/doctabs/mobile/change_label_initial.xml +++ b/container/testdata/doctabs/mobile/change_label_initial.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/dynamic_appended.xml b/container/testdata/doctabs/mobile/dynamic_appended.xml index 3173d85c1d..11cd223128 100644 --- a/container/testdata/doctabs/mobile/dynamic_appended.xml +++ b/container/testdata/doctabs/mobile/dynamic_appended.xml @@ -21,7 +21,7 @@ - + diff --git a/container/testdata/doctabs/mobile/dynamic_appended_and_removed.xml b/container/testdata/doctabs/mobile/dynamic_appended_and_removed.xml index a953c54846..59a354a729 100644 --- a/container/testdata/doctabs/mobile/dynamic_appended_and_removed.xml +++ b/container/testdata/doctabs/mobile/dynamic_appended_and_removed.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/mobile/dynamic_appended_another_three.xml b/container/testdata/doctabs/mobile/dynamic_appended_another_three.xml index fdc1ad07bf..b4e262ec87 100644 --- a/container/testdata/doctabs/mobile/dynamic_appended_another_three.xml +++ b/container/testdata/doctabs/mobile/dynamic_appended_another_three.xml @@ -41,7 +41,7 @@ - + diff --git a/container/testdata/doctabs/mobile/dynamic_initial.xml b/container/testdata/doctabs/mobile/dynamic_initial.xml index 58ea830ed2..6b79f71956 100644 --- a/container/testdata/doctabs/mobile/dynamic_initial.xml +++ b/container/testdata/doctabs/mobile/dynamic_initial.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/mobile/dynamic_replaced_completely.xml b/container/testdata/doctabs/mobile/dynamic_replaced_completely.xml index 57e9d8c958..b52b0bad50 100644 --- a/container/testdata/doctabs/mobile/dynamic_replaced_completely.xml +++ b/container/testdata/doctabs/mobile/dynamic_replaced_completely.xml @@ -27,7 +27,7 @@ - + diff --git a/container/testdata/doctabs/mobile/hover_none.xml b/container/testdata/doctabs/mobile/hover_none.xml index 4f270f5fc8..10523657c6 100644 --- a/container/testdata/doctabs/mobile/hover_none.xml +++ b/container/testdata/doctabs/mobile/hover_none.xml @@ -29,7 +29,7 @@ - + diff --git a/container/testdata/doctabs/mobile/layout_bottom_ico.xml b/container/testdata/doctabs/mobile/layout_bottom_ico.xml index 5c16035703..ce7b86ee72 100644 --- a/container/testdata/doctabs/mobile/layout_bottom_ico.xml +++ b/container/testdata/doctabs/mobile/layout_bottom_ico.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/mobile/layout_bottom_icon_and_text.xml b/container/testdata/doctabs/mobile/layout_bottom_icon_and_text.xml index 135bb2fa73..be9e00add3 100644 --- a/container/testdata/doctabs/mobile/layout_bottom_icon_and_text.xml +++ b/container/testdata/doctabs/mobile/layout_bottom_icon_and_text.xml @@ -16,7 +16,7 @@ - + diff --git a/container/testdata/doctabs/mobile/layout_bottom_text.xml b/container/testdata/doctabs/mobile/layout_bottom_text.xml index 76fc19208c..704d9466a8 100644 --- a/container/testdata/doctabs/mobile/layout_bottom_text.xml +++ b/container/testdata/doctabs/mobile/layout_bottom_text.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/mobile/layout_top_icon.xml b/container/testdata/doctabs/mobile/layout_top_icon.xml index 0e7606cd6d..c2639051ef 100644 --- a/container/testdata/doctabs/mobile/layout_top_icon.xml +++ b/container/testdata/doctabs/mobile/layout_top_icon.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/mobile/layout_top_icon_and_text.xml b/container/testdata/doctabs/mobile/layout_top_icon_and_text.xml index 96f85c3e24..8b50f0680f 100644 --- a/container/testdata/doctabs/mobile/layout_top_icon_and_text.xml +++ b/container/testdata/doctabs/mobile/layout_top_icon_and_text.xml @@ -16,7 +16,7 @@ - + diff --git a/container/testdata/doctabs/mobile/layout_top_text.xml b/container/testdata/doctabs/mobile/layout_top_text.xml index 5afd27435c..e2a0b4f244 100644 --- a/container/testdata/doctabs/mobile/layout_top_text.xml +++ b/container/testdata/doctabs/mobile/layout_top_text.xml @@ -15,7 +15,7 @@ - + diff --git a/container/testdata/doctabs/mobile/tab_location_bottom.xml b/container/testdata/doctabs/mobile/tab_location_bottom.xml index 77de64a704..8b4e701db1 100644 --- a/container/testdata/doctabs/mobile/tab_location_bottom.xml +++ b/container/testdata/doctabs/mobile/tab_location_bottom.xml @@ -35,7 +35,7 @@ - + diff --git a/container/testdata/doctabs/mobile/tab_location_top.xml b/container/testdata/doctabs/mobile/tab_location_top.xml index 2a38647c57..a78ea73487 100644 --- a/container/testdata/doctabs/mobile/tab_location_top.xml +++ b/container/testdata/doctabs/mobile/tab_location_top.xml @@ -35,7 +35,7 @@ - + diff --git a/container/testdata/doctabs/mobile/tapped_all_tabs.xml b/container/testdata/doctabs/mobile/tapped_all_tabs.xml index 38a8ef6dd9..94d4bf8792 100644 --- a/container/testdata/doctabs/mobile/tapped_all_tabs.xml +++ b/container/testdata/doctabs/mobile/tapped_all_tabs.xml @@ -41,12 +41,12 @@ - + - + diff --git a/container/testdata/doctabs/mobile/tapped_create_tab.xml b/container/testdata/doctabs/mobile/tapped_create_tab.xml index aaa359edd7..00e6cb6711 100644 --- a/container/testdata/doctabs/mobile/tapped_create_tab.xml +++ b/container/testdata/doctabs/mobile/tapped_create_tab.xml @@ -41,12 +41,12 @@ - + - + diff --git a/container/testdata/doctabs/mobile/tapped_first_selected.xml b/container/testdata/doctabs/mobile/tapped_first_selected.xml index 950c5071d7..8299dcc854 100644 --- a/container/testdata/doctabs/mobile/tapped_first_selected.xml +++ b/container/testdata/doctabs/mobile/tapped_first_selected.xml @@ -27,12 +27,12 @@ - + - + diff --git a/container/testdata/doctabs/mobile/tapped_second_selected.xml b/container/testdata/doctabs/mobile/tapped_second_selected.xml index a0db030e7d..dd421a8a68 100644 --- a/container/testdata/doctabs/mobile/tapped_second_selected.xml +++ b/container/testdata/doctabs/mobile/tapped_second_selected.xml @@ -27,12 +27,12 @@ - + - + diff --git a/container/testdata/doctabs/mobile/tapped_third_selected.xml b/container/testdata/doctabs/mobile/tapped_third_selected.xml index 3b0b0fda9e..eb3338ff1e 100644 --- a/container/testdata/doctabs/mobile/tapped_third_selected.xml +++ b/container/testdata/doctabs/mobile/tapped_third_selected.xml @@ -27,12 +27,12 @@ - + - + diff --git a/dialog/testdata/dialog-custom-custom-buttons.xml b/dialog/testdata/dialog-custom-custom-buttons.xml index 6548865cee..54a9928653 100644 --- a/dialog/testdata/dialog-custom-custom-buttons.xml +++ b/dialog/testdata/dialog-custom-custom-buttons.xml @@ -27,21 +27,21 @@ - + 1 - + 2 - + 3 diff --git a/widget/button.go b/widget/button.go index 53f30e1701..40d5dad6b1 100644 --- a/widget/button.go +++ b/widget/button.go @@ -282,6 +282,7 @@ type buttonRenderer struct { // Layout the components of the button widget func (r *buttonRenderer) Layout(size fyne.Size) { r.background.Resize(size) + r.tapBG.Resize(size) hasIcon := r.icon != nil hasLabel := r.label.Segments[0].(*TextSegment).Text != "" @@ -452,7 +453,11 @@ func newButtonTapAnimation(bg *canvas.Rectangle, w fyne.Widget) *fyne.Animation r, g, bb, a := col.ToNRGBA(theme.PressedColor()) aa := uint8(a) fade := aa - uint8(float32(aa)*done) - bg.FillColor = &color.NRGBA{R: uint8(r), G: uint8(g), B: uint8(bb), A: fade} + if fade > 0 { + bg.FillColor = &color.NRGBA{R: uint8(r), G: uint8(g), B: uint8(bb), A: fade} + } else { + bg.FillColor = color.Transparent + } canvas.Refresh(bg) }) } diff --git a/widget/testdata/accordion/layout_expanded_multiple_open_multiple_items.xml b/widget/testdata/accordion/layout_expanded_multiple_open_multiple_items.xml index 9a5dc5e3c7..954e3534de 100644 --- a/widget/testdata/accordion/layout_expanded_multiple_open_multiple_items.xml +++ b/widget/testdata/accordion/layout_expanded_multiple_open_multiple_items.xml @@ -4,7 +4,7 @@ - + A @@ -12,7 +12,7 @@ - + B diff --git a/widget/testdata/accordion/layout_expanded_multiple_open_multiple_items_opened.xml b/widget/testdata/accordion/layout_expanded_multiple_open_multiple_items_opened.xml index 3c1d9517cd..f04c797c0e 100644 --- a/widget/testdata/accordion/layout_expanded_multiple_open_multiple_items_opened.xml +++ b/widget/testdata/accordion/layout_expanded_multiple_open_multiple_items_opened.xml @@ -4,7 +4,7 @@ - + A @@ -12,7 +12,7 @@ - + B diff --git a/widget/testdata/accordion/layout_expanded_multiple_open_one_item.xml b/widget/testdata/accordion/layout_expanded_multiple_open_one_item.xml index 4e1c44b7a6..ad0531f594 100644 --- a/widget/testdata/accordion/layout_expanded_multiple_open_one_item.xml +++ b/widget/testdata/accordion/layout_expanded_multiple_open_one_item.xml @@ -4,7 +4,7 @@ - + A diff --git a/widget/testdata/accordion/layout_expanded_multiple_open_one_item_opened.xml b/widget/testdata/accordion/layout_expanded_multiple_open_one_item_opened.xml index a3c2e487f3..131934a3e9 100644 --- a/widget/testdata/accordion/layout_expanded_multiple_open_one_item_opened.xml +++ b/widget/testdata/accordion/layout_expanded_multiple_open_one_item_opened.xml @@ -4,7 +4,7 @@ - + A diff --git a/widget/testdata/accordion/layout_expanded_single_open_multiple_items.xml b/widget/testdata/accordion/layout_expanded_single_open_multiple_items.xml index 9a5dc5e3c7..954e3534de 100644 --- a/widget/testdata/accordion/layout_expanded_single_open_multiple_items.xml +++ b/widget/testdata/accordion/layout_expanded_single_open_multiple_items.xml @@ -4,7 +4,7 @@ - + A @@ -12,7 +12,7 @@ - + B diff --git a/widget/testdata/accordion/layout_expanded_single_open_multiple_items_opened.xml b/widget/testdata/accordion/layout_expanded_single_open_multiple_items_opened.xml index f9ac150210..f6ab3f6ddc 100644 --- a/widget/testdata/accordion/layout_expanded_single_open_multiple_items_opened.xml +++ b/widget/testdata/accordion/layout_expanded_single_open_multiple_items_opened.xml @@ -4,7 +4,7 @@ - + A @@ -12,7 +12,7 @@ - + B diff --git a/widget/testdata/accordion/layout_expanded_single_open_one_item.xml b/widget/testdata/accordion/layout_expanded_single_open_one_item.xml index 4e1c44b7a6..ad0531f594 100644 --- a/widget/testdata/accordion/layout_expanded_single_open_one_item.xml +++ b/widget/testdata/accordion/layout_expanded_single_open_one_item.xml @@ -4,7 +4,7 @@ - + A diff --git a/widget/testdata/accordion/layout_expanded_single_open_one_item_opened.xml b/widget/testdata/accordion/layout_expanded_single_open_one_item_opened.xml index a3c2e487f3..131934a3e9 100644 --- a/widget/testdata/accordion/layout_expanded_single_open_one_item_opened.xml +++ b/widget/testdata/accordion/layout_expanded_single_open_one_item_opened.xml @@ -4,7 +4,7 @@ - + A diff --git a/widget/testdata/accordion/layout_multiple_open_multiple_items.xml b/widget/testdata/accordion/layout_multiple_open_multiple_items.xml index bb1c7b7d8f..637b97f8d2 100644 --- a/widget/testdata/accordion/layout_multiple_open_multiple_items.xml +++ b/widget/testdata/accordion/layout_multiple_open_multiple_items.xml @@ -4,7 +4,7 @@ - + A @@ -12,7 +12,7 @@ - + B diff --git a/widget/testdata/accordion/layout_multiple_open_multiple_items_opened.xml b/widget/testdata/accordion/layout_multiple_open_multiple_items_opened.xml index 9c0e2adf6a..2d3974044b 100644 --- a/widget/testdata/accordion/layout_multiple_open_multiple_items_opened.xml +++ b/widget/testdata/accordion/layout_multiple_open_multiple_items_opened.xml @@ -4,7 +4,7 @@ - + A @@ -12,7 +12,7 @@ - + B diff --git a/widget/testdata/accordion/layout_multiple_open_one_item.xml b/widget/testdata/accordion/layout_multiple_open_one_item.xml index 17017f30bb..8835a72d89 100644 --- a/widget/testdata/accordion/layout_multiple_open_one_item.xml +++ b/widget/testdata/accordion/layout_multiple_open_one_item.xml @@ -4,7 +4,7 @@ - + A diff --git a/widget/testdata/accordion/layout_multiple_open_one_item_opened.xml b/widget/testdata/accordion/layout_multiple_open_one_item_opened.xml index 217136f83e..a6ed74265f 100644 --- a/widget/testdata/accordion/layout_multiple_open_one_item_opened.xml +++ b/widget/testdata/accordion/layout_multiple_open_one_item_opened.xml @@ -4,7 +4,7 @@ - + A diff --git a/widget/testdata/accordion/layout_single_open_multiple_items.xml b/widget/testdata/accordion/layout_single_open_multiple_items.xml index bb1c7b7d8f..637b97f8d2 100644 --- a/widget/testdata/accordion/layout_single_open_multiple_items.xml +++ b/widget/testdata/accordion/layout_single_open_multiple_items.xml @@ -4,7 +4,7 @@ - + A @@ -12,7 +12,7 @@ - + B diff --git a/widget/testdata/accordion/layout_single_open_multiple_items_opened.xml b/widget/testdata/accordion/layout_single_open_multiple_items_opened.xml index 13f2bb1166..46335054c2 100644 --- a/widget/testdata/accordion/layout_single_open_multiple_items_opened.xml +++ b/widget/testdata/accordion/layout_single_open_multiple_items_opened.xml @@ -4,7 +4,7 @@ - + A @@ -12,7 +12,7 @@ - + B diff --git a/widget/testdata/accordion/layout_single_open_one_item.xml b/widget/testdata/accordion/layout_single_open_one_item.xml index 17017f30bb..8835a72d89 100644 --- a/widget/testdata/accordion/layout_single_open_one_item.xml +++ b/widget/testdata/accordion/layout_single_open_one_item.xml @@ -4,7 +4,7 @@ - + A diff --git a/widget/testdata/accordion/layout_single_open_one_item_opened.xml b/widget/testdata/accordion/layout_single_open_one_item_opened.xml index 217136f83e..a6ed74265f 100644 --- a/widget/testdata/accordion/layout_single_open_one_item_opened.xml +++ b/widget/testdata/accordion/layout_single_open_one_item_opened.xml @@ -4,7 +4,7 @@ - + A diff --git a/widget/testdata/button/layout_icon_only_center_leading.xml b/widget/testdata/button/layout_icon_only_center_leading.xml index fcbd520e18..21fb65892a 100644 --- a/widget/testdata/button/layout_icon_only_center_leading.xml +++ b/widget/testdata/button/layout_icon_only_center_leading.xml @@ -2,7 +2,7 @@ - + diff --git a/widget/testdata/button/layout_icon_only_center_trailing.xml b/widget/testdata/button/layout_icon_only_center_trailing.xml index fcbd520e18..21fb65892a 100644 --- a/widget/testdata/button/layout_icon_only_center_trailing.xml +++ b/widget/testdata/button/layout_icon_only_center_trailing.xml @@ -2,7 +2,7 @@ - + diff --git a/widget/testdata/button/layout_icon_only_leading_leading.xml b/widget/testdata/button/layout_icon_only_leading_leading.xml index 34cc8ff549..2a533961a1 100644 --- a/widget/testdata/button/layout_icon_only_leading_leading.xml +++ b/widget/testdata/button/layout_icon_only_leading_leading.xml @@ -2,7 +2,7 @@ - + diff --git a/widget/testdata/button/layout_icon_only_leading_trailing.xml b/widget/testdata/button/layout_icon_only_leading_trailing.xml index 34cc8ff549..2a533961a1 100644 --- a/widget/testdata/button/layout_icon_only_leading_trailing.xml +++ b/widget/testdata/button/layout_icon_only_leading_trailing.xml @@ -2,7 +2,7 @@ - + diff --git a/widget/testdata/button/layout_icon_only_trailing_leading.xml b/widget/testdata/button/layout_icon_only_trailing_leading.xml index fef05fce42..c288a884fd 100644 --- a/widget/testdata/button/layout_icon_only_trailing_leading.xml +++ b/widget/testdata/button/layout_icon_only_trailing_leading.xml @@ -2,7 +2,7 @@ - + diff --git a/widget/testdata/button/layout_icon_only_trailing_trailing.xml b/widget/testdata/button/layout_icon_only_trailing_trailing.xml index fef05fce42..c288a884fd 100644 --- a/widget/testdata/button/layout_icon_only_trailing_trailing.xml +++ b/widget/testdata/button/layout_icon_only_trailing_trailing.xml @@ -2,7 +2,7 @@ - + diff --git a/widget/testdata/button/layout_text_icon_center_leading.xml b/widget/testdata/button/layout_text_icon_center_leading.xml index 9afdb568f3..47fe2c5f23 100644 --- a/widget/testdata/button/layout_text_icon_center_leading.xml +++ b/widget/testdata/button/layout_text_icon_center_leading.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_icon_center_trailing.xml b/widget/testdata/button/layout_text_icon_center_trailing.xml index 6bfb5b7ea1..14a97153c7 100644 --- a/widget/testdata/button/layout_text_icon_center_trailing.xml +++ b/widget/testdata/button/layout_text_icon_center_trailing.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_icon_leading_leading.xml b/widget/testdata/button/layout_text_icon_leading_leading.xml index 55bf7a9019..9c92ec23d0 100644 --- a/widget/testdata/button/layout_text_icon_leading_leading.xml +++ b/widget/testdata/button/layout_text_icon_leading_leading.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_icon_leading_trailing.xml b/widget/testdata/button/layout_text_icon_leading_trailing.xml index c43ddc95ba..1f6a482bcd 100644 --- a/widget/testdata/button/layout_text_icon_leading_trailing.xml +++ b/widget/testdata/button/layout_text_icon_leading_trailing.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_icon_trailing_leading.xml b/widget/testdata/button/layout_text_icon_trailing_leading.xml index 285c83a24d..98004a5386 100644 --- a/widget/testdata/button/layout_text_icon_trailing_leading.xml +++ b/widget/testdata/button/layout_text_icon_trailing_leading.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_icon_trailing_trailing.xml b/widget/testdata/button/layout_text_icon_trailing_trailing.xml index 49214268a6..293aa6c307 100644 --- a/widget/testdata/button/layout_text_icon_trailing_trailing.xml +++ b/widget/testdata/button/layout_text_icon_trailing_trailing.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_only_center_leading.xml b/widget/testdata/button/layout_text_only_center_leading.xml index e418e45420..020ebe919f 100644 --- a/widget/testdata/button/layout_text_only_center_leading.xml +++ b/widget/testdata/button/layout_text_only_center_leading.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_only_center_trailing.xml b/widget/testdata/button/layout_text_only_center_trailing.xml index e418e45420..020ebe919f 100644 --- a/widget/testdata/button/layout_text_only_center_trailing.xml +++ b/widget/testdata/button/layout_text_only_center_trailing.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_only_leading_leading.xml b/widget/testdata/button/layout_text_only_leading_leading.xml index f961a3eb0a..d33959fcfa 100644 --- a/widget/testdata/button/layout_text_only_leading_leading.xml +++ b/widget/testdata/button/layout_text_only_leading_leading.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_only_leading_trailing.xml b/widget/testdata/button/layout_text_only_leading_trailing.xml index f961a3eb0a..d33959fcfa 100644 --- a/widget/testdata/button/layout_text_only_leading_trailing.xml +++ b/widget/testdata/button/layout_text_only_leading_trailing.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_only_multiline.xml b/widget/testdata/button/layout_text_only_multiline.xml index 28538c9997..57e795d704 100644 --- a/widget/testdata/button/layout_text_only_multiline.xml +++ b/widget/testdata/button/layout_text_only_multiline.xml @@ -2,7 +2,7 @@ - + Test Line2 diff --git a/widget/testdata/button/layout_text_only_trailing_leading.xml b/widget/testdata/button/layout_text_only_trailing_leading.xml index 2bbdd56d8d..495cdd1622 100644 --- a/widget/testdata/button/layout_text_only_trailing_leading.xml +++ b/widget/testdata/button/layout_text_only_trailing_leading.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/button/layout_text_only_trailing_trailing.xml b/widget/testdata/button/layout_text_only_trailing_trailing.xml index 2bbdd56d8d..495cdd1622 100644 --- a/widget/testdata/button/layout_text_only_trailing_trailing.xml +++ b/widget/testdata/button/layout_text_only_trailing_trailing.xml @@ -2,7 +2,7 @@ - + Test diff --git a/widget/testdata/form/extended_entry.xml b/widget/testdata/form/extended_entry.xml index 027474e8b9..6161c15217 100644 --- a/widget/testdata/form/extended_entry.xml +++ b/widget/testdata/form/extended_entry.xml @@ -19,7 +19,7 @@ - + diff --git a/widget/testdata/form/layout.xml b/widget/testdata/form/layout.xml index c36d8b4c1d..16d5ab033f 100644 --- a/widget/testdata/form/layout.xml +++ b/widget/testdata/form/layout.xml @@ -38,7 +38,7 @@ - + Cancel @@ -46,7 +46,7 @@ - + Submit diff --git a/widget/testdata/select/center.xml b/widget/testdata/select/center.xml index fb67246fd2..3ccd92e4c2 100644 --- a/widget/testdata/select/center.xml +++ b/widget/testdata/select/center.xml @@ -3,7 +3,7 @@ - + (Select one) diff --git a/widget/testdata/select/layout_empty_expanded.xml b/widget/testdata/select/layout_empty_expanded.xml index 4eefc763d6..630abc1f28 100644 --- a/widget/testdata/select/layout_empty_expanded.xml +++ b/widget/testdata/select/layout_empty_expanded.xml @@ -3,7 +3,7 @@ - + (Select one) diff --git a/widget/testdata/select/layout_empty_expanded_placeholder.xml b/widget/testdata/select/layout_empty_expanded_placeholder.xml index c17a62e069..cb2478c249 100644 --- a/widget/testdata/select/layout_empty_expanded_placeholder.xml +++ b/widget/testdata/select/layout_empty_expanded_placeholder.xml @@ -3,7 +3,7 @@ - + (Pick 1) diff --git a/widget/testdata/select/layout_multiple_expanded.xml b/widget/testdata/select/layout_multiple_expanded.xml index a353cc025a..6a2d3207bb 100644 --- a/widget/testdata/select/layout_multiple_expanded.xml +++ b/widget/testdata/select/layout_multiple_expanded.xml @@ -3,7 +3,7 @@ - + (Select one) diff --git a/widget/testdata/select/layout_multiple_expanded_placeholder.xml b/widget/testdata/select/layout_multiple_expanded_placeholder.xml index de28019da3..2364830489 100644 --- a/widget/testdata/select/layout_multiple_expanded_placeholder.xml +++ b/widget/testdata/select/layout_multiple_expanded_placeholder.xml @@ -3,7 +3,7 @@ - + (Pick 1) diff --git a/widget/testdata/select/layout_multiple_expanded_selected.xml b/widget/testdata/select/layout_multiple_expanded_selected.xml index 31095a8c53..3b3b7f69cd 100644 --- a/widget/testdata/select/layout_multiple_expanded_selected.xml +++ b/widget/testdata/select/layout_multiple_expanded_selected.xml @@ -3,7 +3,7 @@ - + Foo diff --git a/widget/testdata/select/layout_multiple_expanded_selected_placeholder.xml b/widget/testdata/select/layout_multiple_expanded_selected_placeholder.xml index 17b36e4101..47b7a639c2 100644 --- a/widget/testdata/select/layout_multiple_expanded_selected_placeholder.xml +++ b/widget/testdata/select/layout_multiple_expanded_selected_placeholder.xml @@ -3,7 +3,7 @@ - + Foo diff --git a/widget/testdata/select/layout_single_expanded.xml b/widget/testdata/select/layout_single_expanded.xml index 89486fc35d..adad72e40c 100644 --- a/widget/testdata/select/layout_single_expanded.xml +++ b/widget/testdata/select/layout_single_expanded.xml @@ -3,7 +3,7 @@ - + (Select one) diff --git a/widget/testdata/select/layout_single_expanded_placeholder.xml b/widget/testdata/select/layout_single_expanded_placeholder.xml index 072403378d..a9b34ec610 100644 --- a/widget/testdata/select/layout_single_expanded_placeholder.xml +++ b/widget/testdata/select/layout_single_expanded_placeholder.xml @@ -3,7 +3,7 @@ - + (Pick 1) diff --git a/widget/testdata/select/layout_single_expanded_selected.xml b/widget/testdata/select/layout_single_expanded_selected.xml index 2b9a8d54fc..1fdb491d9a 100644 --- a/widget/testdata/select/layout_single_expanded_selected.xml +++ b/widget/testdata/select/layout_single_expanded_selected.xml @@ -3,7 +3,7 @@ - + Test diff --git a/widget/testdata/select/layout_single_expanded_selected_placeholder.xml b/widget/testdata/select/layout_single_expanded_selected_placeholder.xml index c5abfef16d..df46cffae4 100644 --- a/widget/testdata/select/layout_single_expanded_selected_placeholder.xml +++ b/widget/testdata/select/layout_single_expanded_selected_placeholder.xml @@ -3,7 +3,7 @@ - + Test diff --git a/widget/testdata/select/move_moved.xml b/widget/testdata/select/move_moved.xml index f08525a41b..e311ab9cea 100644 --- a/widget/testdata/select/move_moved.xml +++ b/widget/testdata/select/move_moved.xml @@ -2,7 +2,7 @@ - + (Select one) diff --git a/widget/testdata/select/move_tapped.xml b/widget/testdata/select/move_tapped.xml index ee5cf9c5fc..017960f3ed 100644 --- a/widget/testdata/select/move_tapped.xml +++ b/widget/testdata/select/move_tapped.xml @@ -2,7 +2,7 @@ - + (Select one) diff --git a/widget/testdata/select/tapped.xml b/widget/testdata/select/tapped.xml index 7ddf051a42..df409ff160 100644 --- a/widget/testdata/select/tapped.xml +++ b/widget/testdata/select/tapped.xml @@ -2,7 +2,7 @@ - + (Select one) diff --git a/widget/testdata/select/tapped_constrained.xml b/widget/testdata/select/tapped_constrained.xml index 22a2029a77..52da061503 100644 --- a/widget/testdata/select/tapped_constrained.xml +++ b/widget/testdata/select/tapped_constrained.xml @@ -2,7 +2,7 @@ - + (Select one) diff --git a/widget/testdata/select/trailing.xml b/widget/testdata/select/trailing.xml index 512e2cea16..44760dd9e0 100644 --- a/widget/testdata/select/trailing.xml +++ b/widget/testdata/select/trailing.xml @@ -3,7 +3,7 @@ - + (Select one) diff --git a/widget/testdata/select_entry/disableable_disabled.xml b/widget/testdata/select_entry/disableable_disabled.xml index 6ab6eacf02..fb1040ca2a 100644 --- a/widget/testdata/select_entry/disableable_disabled.xml +++ b/widget/testdata/select_entry/disableable_disabled.xml @@ -15,7 +15,7 @@ - + diff --git a/widget/testdata/select_entry/disableable_enabled.xml b/widget/testdata/select_entry/disableable_enabled.xml index 6d461450ae..9957cf2710 100644 --- a/widget/testdata/select_entry/disableable_enabled.xml +++ b/widget/testdata/select_entry/disableable_enabled.xml @@ -15,7 +15,7 @@ - + diff --git a/widget/testdata/select_entry/disableable_enabled_opened.xml b/widget/testdata/select_entry/disableable_enabled_opened.xml index abedfa159f..62fa2866c8 100644 --- a/widget/testdata/select_entry/disableable_enabled_opened.xml +++ b/widget/testdata/select_entry/disableable_enabled_opened.xml @@ -15,7 +15,7 @@ - + diff --git a/widget/testdata/select_entry/disableable_enabled_tapped.xml b/widget/testdata/select_entry/disableable_enabled_tapped.xml index 40b0311b14..9957cf2710 100644 --- a/widget/testdata/select_entry/disableable_enabled_tapped.xml +++ b/widget/testdata/select_entry/disableable_enabled_tapped.xml @@ -15,7 +15,7 @@ - + diff --git a/widget/testdata/select_entry/disableable_enabled_tapped_selected.xml b/widget/testdata/select_entry/disableable_enabled_tapped_selected.xml index 40b0311b14..9957cf2710 100644 --- a/widget/testdata/select_entry/disableable_enabled_tapped_selected.xml +++ b/widget/testdata/select_entry/disableable_enabled_tapped_selected.xml @@ -15,7 +15,7 @@ - + diff --git a/widget/testdata/select_entry/dropdown_B_opened.xml b/widget/testdata/select_entry/dropdown_B_opened.xml index 9420e4eec5..7658b53182 100644 --- a/widget/testdata/select_entry/dropdown_B_opened.xml +++ b/widget/testdata/select_entry/dropdown_B_opened.xml @@ -12,7 +12,7 @@ - + diff --git a/widget/testdata/select_entry/dropdown_empty_opened.xml b/widget/testdata/select_entry/dropdown_empty_opened.xml index abedfa159f..62fa2866c8 100644 --- a/widget/testdata/select_entry/dropdown_empty_opened.xml +++ b/widget/testdata/select_entry/dropdown_empty_opened.xml @@ -15,7 +15,7 @@ - + diff --git a/widget/testdata/select_entry/dropdown_empty_opened_shrunk.xml b/widget/testdata/select_entry/dropdown_empty_opened_shrunk.xml index 0652a27566..eeca93551d 100644 --- a/widget/testdata/select_entry/dropdown_empty_opened_shrunk.xml +++ b/widget/testdata/select_entry/dropdown_empty_opened_shrunk.xml @@ -15,7 +15,7 @@ - + diff --git a/widget/testdata/select_entry/dropdown_empty_setopts.xml b/widget/testdata/select_entry/dropdown_empty_setopts.xml index fd7742658f..71315bf58e 100644 --- a/widget/testdata/select_entry/dropdown_empty_setopts.xml +++ b/widget/testdata/select_entry/dropdown_empty_setopts.xml @@ -15,7 +15,7 @@ - + diff --git a/widget/testdata/select_entry/dropdown_initial.xml b/widget/testdata/select_entry/dropdown_initial.xml index 6d461450ae..9957cf2710 100644 --- a/widget/testdata/select_entry/dropdown_initial.xml +++ b/widget/testdata/select_entry/dropdown_initial.xml @@ -15,7 +15,7 @@ - + diff --git a/widget/testdata/select_entry/dropdown_tapped_B.xml b/widget/testdata/select_entry/dropdown_tapped_B.xml index 982e407781..1b80ad5998 100644 --- a/widget/testdata/select_entry/dropdown_tapped_B.xml +++ b/widget/testdata/select_entry/dropdown_tapped_B.xml @@ -12,7 +12,7 @@ - + diff --git a/widget/testdata/select_entry/dropdown_tapped_C.xml b/widget/testdata/select_entry/dropdown_tapped_C.xml index 81efc192aa..7ac03caf30 100644 --- a/widget/testdata/select_entry/dropdown_tapped_C.xml +++ b/widget/testdata/select_entry/dropdown_tapped_C.xml @@ -12,7 +12,7 @@ - + From c1ddcaa5fe7467b17b9e3533a4ba4a493b2cf493 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 18 Oct 2023 16:49:21 +0100 Subject: [PATCH 043/248] Ensure segments are up to date on first draw Fixes #4312 --- widget/entry.go | 1 + widget/entry_password_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 widget/entry_password_test.go diff --git a/widget/entry.go b/widget/entry.go index 15629c48e7..c6825a4af6 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -197,6 +197,7 @@ func (e *Entry) CreateRenderer() fyne.WidgetRenderer { objects = append(objects, e.ActionItem) } + e.syncSegments() return &entryRenderer{box, border, e.scroll, objects, e} } diff --git a/widget/entry_password_test.go b/widget/entry_password_test.go new file mode 100644 index 0000000000..10742737fa --- /dev/null +++ b/widget/entry_password_test.go @@ -0,0 +1,25 @@ +package widget_test + +import ( + "testing" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/test" + "fyne.io/fyne/v2/widget" + "github.com/stretchr/testify/assert" +) + +func TestNewPasswordEntry(t *testing.T) { + p := widget.NewPasswordEntry() + p.Text = "visible" + r := test.WidgetRenderer(p) + + cont := r.Objects()[2].(*container.Scroll).Content.(fyne.Widget) + r = test.WidgetRenderer(cont) + rich := r.Objects()[1].(*widget.RichText) + r = test.WidgetRenderer(rich) + + assert.Equal(t, "•••••••", r.Objects()[0].(*canvas.Text).Text) +} From 55ca6584ec36152347d303921e524e41ea5b49a9 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 17 Nov 2023 19:35:04 +0000 Subject: [PATCH 044/248] More changes for release --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4005e85cd..a2b08bcb5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ More detailed release notes can be found on the [releases page](https://github.c * RichText may not refresh if segments manually replaced * Correct URI.Extension() documentation * Update for security fixes to x/sys and x/net +* Inconsistent rendering of Button widget (#4243) +* PasswordEntry initial text is not obscured (#4312) ## 2.4.1 - 9 October 2023 From 5f83d9e12c2d1be43ce53218c8bf9abd65413caf Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 17 Nov 2023 09:31:19 +0000 Subject: [PATCH 045/248] Ensure the widget updates to show cursor position Fixes #4181 --- widget/entry.go | 1 + 1 file changed, 1 insertion(+) diff --git a/widget/entry.go b/widget/entry.go index c6825a4af6..1cbb707fcf 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -911,6 +911,7 @@ func (e *Entry) pasteFromClipboard(clipboard fyne.Clipboard) { e.updateTextAndRefresh(provider.String()) e.CursorRow, e.CursorColumn = e.rowColFromTextPos(pos + len(runes)) + e.Refresh() // placing the cursor (and refreshing) happens last } // placeholderProvider returns the placeholder text handler for this entry From ed283a7d91ef7725d2cbcd1a4c18287c86a9bc94 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 17 Nov 2023 19:53:01 +0000 Subject: [PATCH 046/248] Get a release candidate for v2.4.2 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2b08bcb5a..a77ef35f57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). -## 2.4.2 - In Progress +## 2.4.2 - 21 November 2023 ### Fixed @@ -20,6 +20,7 @@ More detailed release notes can be found on the [releases page](https://github.c * Update for security fixes to x/sys and x/net * Inconsistent rendering of Button widget (#4243) * PasswordEntry initial text is not obscured (#4312) +* Pasting text in Entry does not update cursor position display (#4181) ## 2.4.1 - 9 October 2023 From ed7cb8a0715159ce46f69efaf4a60bf9369bf806 Mon Sep 17 00:00:00 2001 From: Gage Cottom Date: Sat, 28 Oct 2023 23:22:27 -0500 Subject: [PATCH 047/248] this fix addresses issues with ctrl vs cmd key on mac in browser apps. previously when in the browser on a mac you would have to use the ctrl key to perform keyboard shortcuts which is not intuitive on a mac where cmd is typically used instead of ctrl. this change adds a check in window initialization that will check if the build is browser based (based on build constraints). At runtime there is a javascript check of the navigator.platform value. if this value contains mac, the modifier key handles default shortcut keys with cmd key instead of ctrl key. other operating systems will see no change. --- internal/driver/glfw/web_shortcuts_js.go | 19 +++++++++++++++++++ internal/driver/glfw/web_shortcuts_other.go | 9 +++++++++ internal/driver/glfw/web_shortcuts_wasm.go | 19 +++++++++++++++++++ internal/driver/glfw/window.go | 2 +- 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 internal/driver/glfw/web_shortcuts_js.go create mode 100644 internal/driver/glfw/web_shortcuts_other.go create mode 100644 internal/driver/glfw/web_shortcuts_wasm.go diff --git a/internal/driver/glfw/web_shortcuts_js.go b/internal/driver/glfw/web_shortcuts_js.go new file mode 100644 index 0000000000..90766f0a2a --- /dev/null +++ b/internal/driver/glfw/web_shortcuts_js.go @@ -0,0 +1,19 @@ +//go:build js && !wasm +// +build js,!wasm + +package glfw + +import ( + "strings" + + "github.com/gopherjs/gopherjs/js" +) + +// Checks if the browser is runnning on Mac OSX +func isMacOSBrowser() bool { + if strings.Contains(strings.ToLower(js.Global.Get("window").Get("navigator").Get("platform").String()), "mac") { + return true + } else { + return false + } +} diff --git a/internal/driver/glfw/web_shortcuts_other.go b/internal/driver/glfw/web_shortcuts_other.go new file mode 100644 index 0000000000..5db93da963 --- /dev/null +++ b/internal/driver/glfw/web_shortcuts_other.go @@ -0,0 +1,9 @@ +//go:build !js && !wasm +// +build !js,!wasm + +package glfw + +// Checks if browser is running on Mac OSX. Returns false because non-browser builds are a no op. +func isMacOSBrowser() bool { + return false +} diff --git a/internal/driver/glfw/web_shortcuts_wasm.go b/internal/driver/glfw/web_shortcuts_wasm.go new file mode 100644 index 0000000000..1e092ea780 --- /dev/null +++ b/internal/driver/glfw/web_shortcuts_wasm.go @@ -0,0 +1,19 @@ +//go:build js && wasm +// +build js,wasm + +package glfw + +import ( + "strings" + + "syscall/js" +) + +// Checks if the browser is runnning on Mac OSX +func isMacOSBrowser() bool { + if strings.Contains(strings.ToLower(js.Global().Get("window").Get("navigator").Get("platform").String()), "mac") { + return true + } else { + return false + } +} diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 971fc486d0..4db1ce021c 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -828,7 +828,7 @@ func (w *window) processFocused(focus bool) { func (w *window) triggersShortcut(localizedKeyName fyne.KeyName, key fyne.KeyName, modifier fyne.KeyModifier) bool { var shortcut fyne.Shortcut ctrlMod := fyne.KeyModifierControl - if runtime.GOOS == "darwin" { + if runtime.GOOS == "darwin" || isMacOSBrowser() { ctrlMod = fyne.KeyModifierSuper } // User pressing physical keys Ctrl+V while using a Russian (or any non-ASCII) keyboard layout From 02db700318b07a7042a9c7242dc22c08f63e0166 Mon Sep 17 00:00:00 2001 From: Gage Cottom Date: Sat, 28 Oct 2023 23:46:05 -0500 Subject: [PATCH 048/248] update test case --- internal/driver/glfw/window_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index a39490672b..0b06e6ec71 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -1652,7 +1652,7 @@ func TestWindow_ClipboardCopy_DisabledEntry(t *testing.T) { assert.Equal(t, "Testing", e.SelectedText()) ctrlMod := glfw.ModControl - if runtime.GOOS == "darwin" { + if runtime.GOOS == "darwin" || isMacOSBrowser() { ctrlMod = glfw.ModSuper } w.keyPressed(nil, glfw.KeyC, 0, glfw.Repeat, ctrlMod) From 8b6be9ce2b563c64c7e1ff07c2be39b9ff450198 Mon Sep 17 00:00:00 2001 From: Gage Cottom Date: Sun, 29 Oct 2023 14:44:57 -0500 Subject: [PATCH 049/248] simplify os check/browser check. removes browser/web reference from the code. simplify return logic for mac check. --- internal/driver/glfw/shortcuts_js.go | 15 +++++++++++++++ internal/driver/glfw/shortcuts_other.go | 11 +++++++++++ internal/driver/glfw/shortcuts_wasm.go | 15 +++++++++++++++ internal/driver/glfw/web_shortcuts_js.go | 19 ------------------- internal/driver/glfw/web_shortcuts_other.go | 9 --------- internal/driver/glfw/web_shortcuts_wasm.go | 19 ------------------- internal/driver/glfw/window.go | 2 +- internal/driver/glfw/window_test.go | 2 +- 8 files changed, 43 insertions(+), 49 deletions(-) create mode 100644 internal/driver/glfw/shortcuts_js.go create mode 100644 internal/driver/glfw/shortcuts_other.go create mode 100644 internal/driver/glfw/shortcuts_wasm.go delete mode 100644 internal/driver/glfw/web_shortcuts_js.go delete mode 100644 internal/driver/glfw/web_shortcuts_other.go delete mode 100644 internal/driver/glfw/web_shortcuts_wasm.go diff --git a/internal/driver/glfw/shortcuts_js.go b/internal/driver/glfw/shortcuts_js.go new file mode 100644 index 0000000000..cc18b8b9d9 --- /dev/null +++ b/internal/driver/glfw/shortcuts_js.go @@ -0,0 +1,15 @@ +//go:build js && !wasm +// +build js,!wasm + +package glfw + +import ( + "strings" + + "github.com/gopherjs/gopherjs/js" +) + +// Checks if running on Mac OSX +func isMacOSRuntime() bool { + return strings.Contains(strings.ToLower(js.Global.Get("window").Get("navigator").Get("platform").String()), "mac") +} diff --git a/internal/driver/glfw/shortcuts_other.go b/internal/driver/glfw/shortcuts_other.go new file mode 100644 index 0000000000..d672aa6906 --- /dev/null +++ b/internal/driver/glfw/shortcuts_other.go @@ -0,0 +1,11 @@ +//go:build !js && !wasm +// +build !js,!wasm + +package glfw + +import "runtime" + +// Checks if running on Mac OSX +func isMacOSRuntime() bool { + return runtime.GOOS == "darwin" +} diff --git a/internal/driver/glfw/shortcuts_wasm.go b/internal/driver/glfw/shortcuts_wasm.go new file mode 100644 index 0000000000..21cac3b4c0 --- /dev/null +++ b/internal/driver/glfw/shortcuts_wasm.go @@ -0,0 +1,15 @@ +//go:build js && wasm +// +build js,wasm + +package glfw + +import ( + "strings" + + "syscall/js" +) + +// Checks if running on Mac OSX +func isMacOSRuntime() bool { + return strings.Contains(strings.ToLower(js.Global().Get("window").Get("navigator").Get("platform").String()), "mac") +} diff --git a/internal/driver/glfw/web_shortcuts_js.go b/internal/driver/glfw/web_shortcuts_js.go deleted file mode 100644 index 90766f0a2a..0000000000 --- a/internal/driver/glfw/web_shortcuts_js.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build js && !wasm -// +build js,!wasm - -package glfw - -import ( - "strings" - - "github.com/gopherjs/gopherjs/js" -) - -// Checks if the browser is runnning on Mac OSX -func isMacOSBrowser() bool { - if strings.Contains(strings.ToLower(js.Global.Get("window").Get("navigator").Get("platform").String()), "mac") { - return true - } else { - return false - } -} diff --git a/internal/driver/glfw/web_shortcuts_other.go b/internal/driver/glfw/web_shortcuts_other.go deleted file mode 100644 index 5db93da963..0000000000 --- a/internal/driver/glfw/web_shortcuts_other.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !js && !wasm -// +build !js,!wasm - -package glfw - -// Checks if browser is running on Mac OSX. Returns false because non-browser builds are a no op. -func isMacOSBrowser() bool { - return false -} diff --git a/internal/driver/glfw/web_shortcuts_wasm.go b/internal/driver/glfw/web_shortcuts_wasm.go deleted file mode 100644 index 1e092ea780..0000000000 --- a/internal/driver/glfw/web_shortcuts_wasm.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build js && wasm -// +build js,wasm - -package glfw - -import ( - "strings" - - "syscall/js" -) - -// Checks if the browser is runnning on Mac OSX -func isMacOSBrowser() bool { - if strings.Contains(strings.ToLower(js.Global().Get("window").Get("navigator").Get("platform").String()), "mac") { - return true - } else { - return false - } -} diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 4db1ce021c..321316a27f 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -828,7 +828,7 @@ func (w *window) processFocused(focus bool) { func (w *window) triggersShortcut(localizedKeyName fyne.KeyName, key fyne.KeyName, modifier fyne.KeyModifier) bool { var shortcut fyne.Shortcut ctrlMod := fyne.KeyModifierControl - if runtime.GOOS == "darwin" || isMacOSBrowser() { + if isMacOSRuntime() { ctrlMod = fyne.KeyModifierSuper } // User pressing physical keys Ctrl+V while using a Russian (or any non-ASCII) keyboard layout diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index 0b06e6ec71..c0e8718ed5 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -1652,7 +1652,7 @@ func TestWindow_ClipboardCopy_DisabledEntry(t *testing.T) { assert.Equal(t, "Testing", e.SelectedText()) ctrlMod := glfw.ModControl - if runtime.GOOS == "darwin" || isMacOSBrowser() { + if isMacOSRuntime() { ctrlMod = glfw.ModSuper } w.keyPressed(nil, glfw.KeyC, 0, glfw.Repeat, ctrlMod) From 6b611d7916a1522c7f3ee8ea2dcdae9f283d1f02 Mon Sep 17 00:00:00 2001 From: Gage Cottom Date: Fri, 17 Nov 2023 14:53:21 -0600 Subject: [PATCH 050/248] update glfw-js dependency --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 899268e30d..728d8858c6 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/fredbi/uri v1.0.0 github.com/fsnotify/fsnotify v1.6.0 github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe - github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 + github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33 github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b diff --git a/go.sum b/go.sum index 79b30237b6..fd9a55f095 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe h1:A/wiwvQ0CAjPkuJyt github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe/go.mod h1:d4clgH0/GrRwWjRzJJQXxT/h1TyuNSfF/X64zb/3Ggg= github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 h1:+31CdF/okdokeFNoy9L/2PccG3JFidQT3ev64/r4pYU= github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504/go.mod h1:gLRWYfYnMA9TONeppRSikMdXlHQ97xVsPojddUv3b/E= +github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33 h1:0Ayg0/do/sqX2R7NonoLZvWxGrd9utTVf3A0QvCbC88= +github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33/go.mod h1:gLRWYfYnMA9TONeppRSikMdXlHQ97xVsPojddUv3b/E= github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 h1:hnLq+55b7Zh7/2IRzWCpiTcAvjv/P8ERF+N7+xXbZhk= github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2/go.mod h1:eO7W361vmlPOrykIg+Rsh1SZ3tQBaOsfzZhsIOb/Lm0= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= From 488b28b4f07f69aea958a729bf5405604626408e Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 17:48:44 -0800 Subject: [PATCH 051/248] don't allocate new children and objects slices every updateList --- widget/list.go | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/widget/list.go b/widget/list.go index 0aeb686c31..4e9a9e2eab 100644 --- a/widget/list.go +++ b/widget/list.go @@ -647,7 +647,8 @@ func (l *listLayout) updateList(newOnly bool) { } visible := make(map[ListItemID]*listItem, len(visibleRowHeights)) - cells := make([]fyne.CanvasObject, len(visibleRowHeights)) + oldChildrenLen := len(l.children) + l.children = l.children[:0] y := offY for index, itemHeight := range visibleRowHeights { @@ -668,7 +669,15 @@ func (l *listLayout) updateList(newOnly bool) { y += itemHeight + separatorThickness visible[row] = c - cells[index] = c + l.children = append(l.children, c) + } + if ln := len(l.children); oldChildrenLen > ln { + // nil out slice's unreferenced items + l.children = l.children[:oldChildrenLen] + for i := ln; i < oldChildrenLen; i++ { + l.children[i] = nil + } + l.children = l.children[:ln] } l.visible = visible @@ -678,13 +687,22 @@ func (l *listLayout) updateList(newOnly bool) { l.itemPool.Release(old) } } - l.children = cells l.updateSeparators() - objects := l.children - objects = append(objects, l.separators...) - l.list.scroller.Content.(*fyne.Container).Objects = objects + c := l.list.scroller.Content.(*fyne.Container) + oldObjLen := len(c.Objects) + c.Objects = c.Objects[:0] + c.Objects = append(c.Objects, l.children...) + c.Objects = append(c.Objects, l.separators...) + if ln := len(c.Objects); oldObjLen > ln { + // nil out slice's unreferenced items + c.Objects = c.Objects[:oldObjLen] + for i := ln; i < oldObjLen; i++ { + c.Objects[i] = nil + } + c.Objects = c.Objects[:ln] + } l.renderLock.Unlock() // user code should not be locked if newOnly { @@ -701,11 +719,11 @@ func (l *listLayout) updateList(newOnly bool) { } func (l *listLayout) updateSeparators() { - if len(l.children) > 1 { - if len(l.separators) > len(l.children) { - l.separators = l.separators[:len(l.children)] + if lenChildren := len(l.children); lenChildren > 1 { + if lenSep := len(l.separators); lenSep > lenChildren { + l.separators = l.separators[:lenChildren] } else { - for i := len(l.separators); i < len(l.children); i++ { + for i := lenSep; i < lenChildren; i++ { l.separators = append(l.separators, NewSeparator()) } } From 38aba32b7e11da631727eb1ec515ac6ecdbabb9b Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 18:33:31 -0800 Subject: [PATCH 052/248] don't allocate a slice of visible row heights on every updateList --- widget/list.go | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/widget/list.go b/widget/list.go index 4e9a9e2eab..c314a38b86 100644 --- a/widget/list.go +++ b/widget/list.go @@ -318,24 +318,25 @@ func (l *List) UnselectAll() { } } -func (l *List) visibleItemHeights(itemHeight float32, length int) (visible []float32, offY float32, minRow int) { +// fills l.visibleRowHeights and also returns offY and minRow +func (l *listLayout) calculateVisibleRowHeights(itemHeight float32, length int) (offY float32, minRow int) { rowOffset := float32(0) isVisible := false - visible = []float32{} + l.visibleRowHeights = l.visibleRowHeights[:0] - if l.scroller.Size().Height <= 0 { + if l.list.scroller.Size().Height <= 0 { return } // theme.Padding is a slow call, so we cache it padding := theme.Padding() - if len(l.itemHeights) == 0 { + if len(l.list.itemHeights) == 0 { paddedItemHeight := itemHeight + padding - offY = float32(math.Floor(float64(l.offsetY/paddedItemHeight))) * paddedItemHeight + offY = float32(math.Floor(float64(l.list.offsetY/paddedItemHeight))) * paddedItemHeight minRow = int(math.Floor(float64(offY / paddedItemHeight))) - maxRow := int(math.Ceil(float64((offY + l.scroller.Size().Height) / paddedItemHeight))) + maxRow := int(math.Ceil(float64((offY + l.list.scroller.Size().Height) / paddedItemHeight))) if minRow > length-1 { minRow = length - 1 @@ -349,33 +350,32 @@ func (l *List) visibleItemHeights(itemHeight float32, length int) (visible []flo maxRow = length } - visible = make([]float32, maxRow-minRow) for i := 0; i < maxRow-minRow; i++ { - visible[i] = itemHeight + l.visibleRowHeights = append(l.visibleRowHeights, itemHeight) } return } for i := 0; i < length; i++ { height := itemHeight - if h, ok := l.itemHeights[i]; ok { + if h, ok := l.list.itemHeights[i]; ok { height = h } - if rowOffset <= l.offsetY-height-padding { + if rowOffset <= l.list.offsetY-height-padding { // before scroll - } else if rowOffset <= l.offsetY { + } else if rowOffset <= l.list.offsetY { minRow = i offY = rowOffset isVisible = true } - if rowOffset >= l.offsetY+l.scroller.Size().Height { + if rowOffset >= l.list.offsetY+l.list.scroller.Size().Height { break } rowOffset += height + padding if isVisible { - visible = append(visible, height) + l.visibleRowHeights = append(l.visibleRowHeights, height) } } return @@ -528,9 +528,10 @@ type listLayout struct { separators []fyne.CanvasObject children []fyne.CanvasObject - itemPool *syncPool - visible map[ListItemID]*listItem - renderLock sync.Mutex + itemPool *syncPool + visible map[ListItemID]*listItem + visibleRowHeights []float32 + renderLock sync.Mutex } func newListLayout(list *List) fyne.Layout { @@ -639,19 +640,19 @@ func (l *listLayout) updateList(newOnly bool) { wasVisible := l.visible l.list.propertyLock.Lock() - visibleRowHeights, offY, minRow := l.list.visibleItemHeights(l.list.itemMin.Height, length) + offY, minRow := l.calculateVisibleRowHeights(l.list.itemMin.Height, length) l.list.propertyLock.Unlock() - if len(visibleRowHeights) == 0 && length > 0 { // we can't show anything until we have some dimensions + if len(l.visibleRowHeights) == 0 && length > 0 { // we can't show anything until we have some dimensions l.renderLock.Unlock() // user code should not be locked return } - visible := make(map[ListItemID]*listItem, len(visibleRowHeights)) + visible := make(map[ListItemID]*listItem, len(l.visibleRowHeights)) oldChildrenLen := len(l.children) l.children = l.children[:0] y := offY - for index, itemHeight := range visibleRowHeights { + for index, itemHeight := range l.visibleRowHeights { row := index + minRow size := fyne.NewSize(width, itemHeight) From 1f9735d9773c2e2dffd949379f2a105842d1f7c3 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 19:35:11 -0800 Subject: [PATCH 053/248] don't allocate a new map for visible objects on every updateList --- widget/list.go | 97 +++++++++++++++++++++++++++++---------------- widget/list_test.go | 22 +++++----- 2 files changed, 75 insertions(+), 44 deletions(-) diff --git a/widget/list.go b/widget/list.go index c314a38b86..e43b4c0aae 100644 --- a/widget/list.go +++ b/widget/list.go @@ -122,9 +122,8 @@ func (l *List) RefreshItem(id ListItemID) { } l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) - visible := lo.visible - if item, ok := visible[id]; ok { - lo.setupListItem(item, id, l.focused && l.currentFocus == id) + if idx := lo.searchVisible(lo.visible, id); idx >= 0 { + lo.setupListItem(lo.visible[idx].item, id, l.focused && l.currentFocus == id) } } @@ -523,19 +522,25 @@ func (li *listItemRenderer) Refresh() { // Declare conformity with Layout interface. var _ fyne.Layout = (*listLayout)(nil) +type itemAndID struct { + item *listItem + id ListItemID +} + type listLayout struct { list *List separators []fyne.CanvasObject children []fyne.CanvasObject itemPool *syncPool - visible map[ListItemID]*listItem + visible []itemAndID + wasVisible []itemAndID visibleRowHeights []float32 renderLock sync.Mutex } func newListLayout(list *List) fyne.Layout { - l := &listLayout{list: list, itemPool: &syncPool{}, visible: make(map[ListItemID]*listItem)} + l := &listLayout{list: list, itemPool: &syncPool{}} list.offsetUpdated = l.offsetUpdated return l } @@ -637,7 +642,11 @@ func (l *listLayout) updateList(newOnly bool) { fyne.LogError("Missing UpdateCell callback required for List", nil) } - wasVisible := l.visible + for i := 0; i < len(l.wasVisible); i++ { + l.wasVisible[i].item = nil + } + l.wasVisible = l.wasVisible[:0] + l.wasVisible = append(l.wasVisible, l.visible...) l.list.propertyLock.Lock() offY, minRow := l.calculateVisibleRowHeights(l.list.itemMin.Height, length) @@ -647,7 +656,8 @@ func (l *listLayout) updateList(newOnly bool) { return } - visible := make(map[ListItemID]*listItem, len(l.visibleRowHeights)) + oldVisibleLen := len(l.visible) + l.visible = l.visible[:0] oldChildrenLen := len(l.children) l.children = l.children[:0] @@ -656,36 +666,39 @@ func (l *listLayout) updateList(newOnly bool) { row := index + minRow size := fyne.NewSize(width, itemHeight) - c, ok := wasVisible[row] - if !ok { + visIdx := l.searchVisible(l.wasVisible, row) + var c *listItem + if visIdx < 0 { c = l.getItem() if c == nil { continue } c.Resize(size) + } else { + c = l.wasVisible[visIdx].item } c.Move(fyne.NewPos(0, y)) c.Resize(size) y += itemHeight + separatorThickness - visible[row] = c + l.visible = append(l.visible, itemAndID{id: row, item: c}) l.children = append(l.children, c) } - if ln := len(l.children); oldChildrenLen > ln { - // nil out slice's unreferenced items - l.children = l.children[:oldChildrenLen] - for i := ln; i < oldChildrenLen; i++ { - l.children[i] = nil + l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) + // nil out l.visible slice's unreferenced items + if ln := len(l.visible); oldVisibleLen > ln { + l.visible = l.visible[:oldVisibleLen] + for i := ln; i < oldVisibleLen; i++ { + l.visible[i].item = nil } - l.children = l.children[:ln] + l.visible = l.visible[:ln] } - l.visible = visible - - for id, old := range wasVisible { - if _, ok := l.visible[id]; !ok { - l.itemPool.Release(old) + for _, item := range l.wasVisible { + if idx := l.searchVisible(l.visible, item.id); idx < 0 { + l.itemPool.Release(item.item) + item.item = nil } } @@ -696,27 +709,25 @@ func (l *listLayout) updateList(newOnly bool) { c.Objects = c.Objects[:0] c.Objects = append(c.Objects, l.children...) c.Objects = append(c.Objects, l.separators...) - if ln := len(c.Objects); oldObjLen > ln { - // nil out slice's unreferenced items - c.Objects = c.Objects[:oldObjLen] - for i := ln; i < oldObjLen; i++ { - c.Objects[i] = nil - } - c.Objects = c.Objects[:ln] - } + l.nilOldSliceData(c.Objects, len(c.Objects), oldObjLen) l.renderLock.Unlock() // user code should not be locked if newOnly { - for row, obj := range visible { - if _, ok := wasVisible[row]; !ok { - l.setupListItem(obj, row, l.list.focused && l.list.currentFocus == row) + for _, item := range l.visible { + if idx := l.searchVisible(l.wasVisible, item.id); idx < 0 { + l.setupListItem(item.item, item.id, l.list.focused && l.list.currentFocus == item.id) } } } else { - for row, obj := range visible { - l.setupListItem(obj, row, l.list.focused && l.list.currentFocus == row) + for _, item := range l.visible { + l.setupListItem(item.item, item.id, l.list.focused && l.list.currentFocus == item.id) } } + + // we don't need wasVisible's data anymore; nil out all references + for i := 0; i < len(l.wasVisible); i++ { + l.wasVisible[i].item = nil + } } func (l *listLayout) updateSeparators() { @@ -743,3 +754,21 @@ func (l *listLayout) updateSeparators() { l.separators[i].Show() } } + +func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) int { + for i, v := range visible { + if v.id == id { + return i + } + } + return -1 +} + +func (l *listLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) { + if oldLen > len { + objs = objs[:oldLen] // gain view into old data + for i := len; i < oldLen; i++ { + objs[i] = nil + } + } +} diff --git a/widget/list_test.go b/widget/list_test.go index 99001bfc25..b97ae16178 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -275,22 +275,24 @@ func TestList_Select(t *testing.T) { assert.Equal(t, float32(0), list.offsetY) list.Select(50) assert.Equal(t, 988, int(list.offsetY)) - visible := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible - assert.Equal(t, visible[50].background.FillColor, theme.SelectionColor()) - assert.True(t, visible[50].background.Visible()) + lo := list.scroller.Content.(*fyne.Container).Layout.(*listLayout) + visible50 := lo.visible[lo.searchVisible(lo.visible, 50)].item + assert.Equal(t, visible50.background.FillColor, theme.SelectionColor()) + assert.True(t, visible50.background.Visible()) list.Select(5) assert.Equal(t, 195, int(list.offsetY)) - visible = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible - assert.Equal(t, visible[5].background.FillColor, theme.SelectionColor()) - assert.True(t, visible[5].background.Visible()) + visible5 := lo.visible[lo.searchVisible(lo.visible, 5)].item + assert.Equal(t, visible5.background.FillColor, theme.SelectionColor()) + assert.True(t, visible5.background.Visible()) list.Select(6) assert.Equal(t, 195, int(list.offsetY)) - visible = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible - assert.False(t, visible[5].background.Visible()) - assert.Equal(t, visible[6].background.FillColor, theme.SelectionColor()) - assert.True(t, visible[6].background.Visible()) + visible5 = lo.visible[lo.searchVisible(lo.visible, 5)].item + visible6 := lo.visible[lo.searchVisible(lo.visible, 6)].item + assert.False(t, visible5.background.Visible()) + assert.Equal(t, visible6.background.FillColor, theme.SelectionColor()) + assert.True(t, visible6.background.Visible()) } func TestList_Unselect(t *testing.T) { From 420a945f42ff08b169aa7d49af278809aa308318 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 19:44:09 -0800 Subject: [PATCH 054/248] get rid of redundant data-nilling loop --- widget/list.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/widget/list.go b/widget/list.go index e43b4c0aae..cbde9bdb79 100644 --- a/widget/list.go +++ b/widget/list.go @@ -642,10 +642,7 @@ func (l *listLayout) updateList(newOnly bool) { fyne.LogError("Missing UpdateCell callback required for List", nil) } - for i := 0; i < len(l.wasVisible); i++ { - l.wasVisible[i].item = nil - } - l.wasVisible = l.wasVisible[:0] + l.wasVisible = l.wasVisible[:0] // data already nilled out at end of this func l.wasVisible = append(l.wasVisible, l.visible...) l.list.propertyLock.Lock() From 8afdc1835fa7aade5da73fa5b09a0babdf966c54 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 20:13:29 -0800 Subject: [PATCH 055/248] use binary search to search visible slices --- widget/list.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/widget/list.go b/widget/list.go index cbde9bdb79..e300e3fc98 100644 --- a/widget/list.go +++ b/widget/list.go @@ -752,10 +752,20 @@ func (l *listLayout) updateSeparators() { } } +// invariant: visible is in ascending order of IDs func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) int { - for i, v := range visible { - if v.id == id { - return i + // binary search + low := 0 + high := len(visible) - 1 + for low <= high { + mid := (low + high) / 2 + if visible[mid].id == id { + return mid + } + if visible[mid].id > id { + high = mid - 1 + } else { + low = mid + 1 } } return -1 From 13f5c4bb3fe5d98e4a24d4dcde7ee8d3783d674c Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 20:16:53 -0800 Subject: [PATCH 056/248] use compact if statement --- widget/list.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/widget/list.go b/widget/list.go index e300e3fc98..489ccc72d3 100644 --- a/widget/list.go +++ b/widget/list.go @@ -663,16 +663,15 @@ func (l *listLayout) updateList(newOnly bool) { row := index + minRow size := fyne.NewSize(width, itemHeight) - visIdx := l.searchVisible(l.wasVisible, row) var c *listItem - if visIdx < 0 { + if idx := l.searchVisible(l.wasVisible, row); idx < 0 { c = l.getItem() if c == nil { continue } c.Resize(size) } else { - c = l.wasVisible[visIdx].item + c = l.wasVisible[idx].item } c.Move(fyne.NewPos(0, y)) From 39fdeb3daf1cd0a7ffb15ab1be70bb1517e4e986 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 20:41:52 -0800 Subject: [PATCH 057/248] change interface of searchVisible to match that of map --- widget/list.go | 34 ++++++++++++++++------------------ widget/list_test.go | 8 ++++---- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/widget/list.go b/widget/list.go index 489ccc72d3..d745841c33 100644 --- a/widget/list.go +++ b/widget/list.go @@ -122,8 +122,8 @@ func (l *List) RefreshItem(id ListItemID) { } l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) - if idx := lo.searchVisible(lo.visible, id); idx >= 0 { - lo.setupListItem(lo.visible[idx].item, id, l.focused && l.currentFocus == id) + if item, ok := lo.searchVisible(lo.visible, id); ok { + lo.setupListItem(item, id, l.focused && l.currentFocus == id) } } @@ -663,15 +663,13 @@ func (l *listLayout) updateList(newOnly bool) { row := index + minRow size := fyne.NewSize(width, itemHeight) - var c *listItem - if idx := l.searchVisible(l.wasVisible, row); idx < 0 { + c, ok := l.searchVisible(l.wasVisible, row) + if !ok { c = l.getItem() if c == nil { continue } c.Resize(size) - } else { - c = l.wasVisible[idx].item } c.Move(fyne.NewPos(0, y)) @@ -691,10 +689,10 @@ func (l *listLayout) updateList(newOnly bool) { l.visible = l.visible[:ln] } - for _, item := range l.wasVisible { - if idx := l.searchVisible(l.visible, item.id); idx < 0 { - l.itemPool.Release(item.item) - item.item = nil + for _, wasVis := range l.wasVisible { + if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { + l.itemPool.Release(wasVis.item) + wasVis.item = nil } } @@ -709,14 +707,14 @@ func (l *listLayout) updateList(newOnly bool) { l.renderLock.Unlock() // user code should not be locked if newOnly { - for _, item := range l.visible { - if idx := l.searchVisible(l.wasVisible, item.id); idx < 0 { - l.setupListItem(item.item, item.id, l.list.focused && l.list.currentFocus == item.id) + for _, vis := range l.visible { + if _, ok := l.searchVisible(l.wasVisible, vis.id); !ok { + l.setupListItem(vis.item, vis.id, l.list.focused && l.list.currentFocus == vis.id) } } } else { - for _, item := range l.visible { - l.setupListItem(item.item, item.id, l.list.focused && l.list.currentFocus == item.id) + for _, vis := range l.visible { + l.setupListItem(vis.item, vis.id, l.list.focused && l.list.currentFocus == vis.id) } } @@ -752,14 +750,14 @@ func (l *listLayout) updateSeparators() { } // invariant: visible is in ascending order of IDs -func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) int { +func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) (*listItem, bool) { // binary search low := 0 high := len(visible) - 1 for low <= high { mid := (low + high) / 2 if visible[mid].id == id { - return mid + return visible[mid].item, true } if visible[mid].id > id { high = mid - 1 @@ -767,7 +765,7 @@ func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) int { low = mid + 1 } } - return -1 + return nil, false } func (l *listLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) { diff --git a/widget/list_test.go b/widget/list_test.go index b97ae16178..9f109f6550 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -276,20 +276,20 @@ func TestList_Select(t *testing.T) { list.Select(50) assert.Equal(t, 988, int(list.offsetY)) lo := list.scroller.Content.(*fyne.Container).Layout.(*listLayout) - visible50 := lo.visible[lo.searchVisible(lo.visible, 50)].item + visible50, _ := lo.searchVisible(lo.visible, 50) assert.Equal(t, visible50.background.FillColor, theme.SelectionColor()) assert.True(t, visible50.background.Visible()) list.Select(5) assert.Equal(t, 195, int(list.offsetY)) - visible5 := lo.visible[lo.searchVisible(lo.visible, 5)].item + visible5, _ := lo.searchVisible(lo.visible, 5) assert.Equal(t, visible5.background.FillColor, theme.SelectionColor()) assert.True(t, visible5.background.Visible()) list.Select(6) assert.Equal(t, 195, int(list.offsetY)) - visible5 = lo.visible[lo.searchVisible(lo.visible, 5)].item - visible6 := lo.visible[lo.searchVisible(lo.visible, 6)].item + visible5, _ = lo.searchVisible(lo.visible, 5) + visible6, _ := lo.searchVisible(lo.visible, 6) assert.False(t, visible5.background.Visible()) assert.Equal(t, visible6.background.FillColor, theme.SelectionColor()) assert.True(t, visible6.background.Visible()) From b0ef58c0506115ecd37e78ac4d582687547f3f22 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 20:45:03 -0800 Subject: [PATCH 058/248] get rid of redundant nilling --- widget/list.go | 1 - 1 file changed, 1 deletion(-) diff --git a/widget/list.go b/widget/list.go index d745841c33..bc85ea9dbf 100644 --- a/widget/list.go +++ b/widget/list.go @@ -692,7 +692,6 @@ func (l *listLayout) updateList(newOnly bool) { for _, wasVis := range l.wasVisible { if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { l.itemPool.Release(wasVis.item) - wasVis.item = nil } } From 622f3e7f0155ef9adb19f717aa41a2305567f220 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 18 Nov 2023 14:35:58 +0100 Subject: [PATCH 059/248] Update fsnotify to v1.7.0 Various bufixes and improvements. See changelog for more info: https://github.com/fsnotify/fsnotify/releases/tag/v1.7.0 --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 899268e30d..8a6f594d22 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/BurntSushi/toml v1.3.2 github.com/fogleman/gg v1.3.0 github.com/fredbi/uri v1.0.0 - github.com/fsnotify/fsnotify v1.6.0 + github.com/fsnotify/fsnotify v1.7.0 github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 diff --git a/go.sum b/go.sum index 79b30237b6..a44e514ac4 100644 --- a/go.sum +++ b/go.sum @@ -83,8 +83,8 @@ github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzP github.com/fredbi/uri v1.0.0 h1:s4QwUAZ8fz+mbTsukND+4V5f+mJ/wjaTokwstGUAemg= github.com/fredbi/uri v1.0.0/go.mod h1:1xC40RnIOGCaQzswaOvrzvG/3M3F0hyDVb3aO/1iGy0= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe h1:A/wiwvQ0CAjPkuJytaD+SsXkPU0asQ+guQEIg1BJGX4= github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe/go.mod h1:d4clgH0/GrRwWjRzJJQXxT/h1TyuNSfF/X64zb/3Ggg= github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 h1:+31CdF/okdokeFNoy9L/2PccG3JFidQT3ev64/r4pYU= @@ -512,8 +512,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 294322bd412306038395c41ae614e80550e4985a Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 18 Nov 2023 16:05:04 +0100 Subject: [PATCH 060/248] Remove constant debug field from canvas Thisclears out a small amount of memory usageby moving a build-constant field to a global constant variable. Most importantly, it makes Go have a better time deadcode eliminating methods that we only want to compile in for debug (especially the reflect code that gets the name of the canvasobject). --- internal/debug_disabled.go | 8 ++++++++ internal/debug_enabled.go | 8 ++++++++ internal/driver/glfw/canvas.go | 11 +++++------ internal/driver/mobile/canvas.go | 5 ++--- internal/driver/mobile/driver.go | 2 +- internal/painter/gl/gl.go | 4 ++-- 6 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 internal/debug_disabled.go create mode 100644 internal/debug_enabled.go diff --git a/internal/debug_disabled.go b/internal/debug_disabled.go new file mode 100644 index 0000000000..b970163114 --- /dev/null +++ b/internal/debug_disabled.go @@ -0,0 +1,8 @@ +//go:build !debug +// +build !debug + +package internal + +// BuildTypeIsDebug is true if built with -tags debug. This value exists as a constant +// so the Go compiler can deadcode eliminate reflect from non-debug builds. +const BuildTypeIsDebug = false diff --git a/internal/debug_enabled.go b/internal/debug_enabled.go new file mode 100644 index 0000000000..916413ed58 --- /dev/null +++ b/internal/debug_enabled.go @@ -0,0 +1,8 @@ +//go:build debug +// +build debug + +package internal + +// BuildTypeIsDebug is true if built with -tags debug. This value exists as a constant +// so the Go compiler can deadcode eliminate reflect from non-debug builds. +const BuildTypeIsDebug = true diff --git a/internal/driver/glfw/canvas.go b/internal/driver/glfw/canvas.go index fbd294de54..66862493b9 100644 --- a/internal/driver/glfw/canvas.go +++ b/internal/driver/glfw/canvas.go @@ -20,10 +20,10 @@ var _ fyne.Canvas = (*glCanvas)(nil) type glCanvas struct { common.Canvas - content fyne.CanvasObject - menu fyne.CanvasObject - padded, debug bool - size fyne.Size + content fyne.CanvasObject + menu fyne.CanvasObject + padded bool + size fyne.Size onTypedRune func(rune) onTypedKey func(*fyne.KeyEvent) @@ -298,7 +298,7 @@ func (c *glCanvas) paint(size fyne.Size) { } } - if c.debug { + if internal.BuildTypeIsDebug { c.DrawDebugOverlay(node.Obj(), pos, size) } } @@ -339,6 +339,5 @@ func newCanvas() *glCanvas { c := &glCanvas{scale: 1.0, texScale: 1.0, padded: true} c.Initialize(c, c.overlayChanged) c.setContent(&canvas.Rectangle{FillColor: theme.BackgroundColor()}) - c.debug = fyne.CurrentApp().Settings().BuildType() == fyne.BuildDebug return c } diff --git a/internal/driver/mobile/canvas.go b/internal/driver/mobile/canvas.go index ec2375ba3b..35c20f58bc 100644 --- a/internal/driver/mobile/canvas.go +++ b/internal/driver/mobile/canvas.go @@ -30,8 +30,8 @@ type mobileCanvas struct { scale float32 size fyne.Size - touched map[int]mobile.Touchable - padded, debug bool + touched map[int]mobile.Touchable + padded bool onTypedRune func(rune) onTypedKey func(event *fyne.KeyEvent) @@ -50,7 +50,6 @@ type mobileCanvas struct { // NewCanvas creates a new gomobile mobileCanvas. This is a mobileCanvas that will render on a mobile device using OpenGL. func NewCanvas() fyne.Canvas { ret := &mobileCanvas{padded: true} - ret.debug = fyne.CurrentApp().Settings().BuildType() == fyne.BuildDebug ret.scale = fyne.CurrentDevice().SystemScaleForWindow(nil) // we don't need a window parameter on mobile ret.touched = make(map[int]mobile.Touchable) ret.lastTapDownPos = make(map[int]fyne.Position) diff --git a/internal/driver/mobile/driver.go b/internal/driver/mobile/driver.go index 5e06cffbdc..2114838dd5 100644 --- a/internal/driver/mobile/driver.go +++ b/internal/driver/mobile/driver.go @@ -315,7 +315,7 @@ func (d *mobileDriver) paintWindow(window fyne.Window, size fyne.Size) { } } - if c.debug { + if internal.BuildTypeIsDebug { c.DrawDebugOverlay(node.Obj(), pos, size) } } diff --git a/internal/painter/gl/gl.go b/internal/painter/gl/gl.go index 65fea635db..65dad1b786 100644 --- a/internal/painter/gl/gl.go +++ b/internal/painter/gl/gl.go @@ -6,7 +6,7 @@ import ( "log" "runtime" - "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal" ) const floatSize = 4 @@ -17,7 +17,7 @@ const max16bit = float32(255 * 255) // Receives a function as parameter, to lazily get the error code only when // needed, avoiding unneeded overhead. func logGLError(getError func() uint32) { - if fyne.CurrentApp().Settings().BuildType() != fyne.BuildDebug { + if !internal.BuildTypeIsDebug { return } From e7e3628741a8a1e6799573661db9dc8cee6b7013 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 18 Nov 2023 07:44:30 -0800 Subject: [PATCH 061/248] do less overall work by swapping l.visible and l.wasVisible at beginning of updateList --- widget/list.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/widget/list.go b/widget/list.go index bc85ea9dbf..0cb805feac 100644 --- a/widget/list.go +++ b/widget/list.go @@ -642,8 +642,13 @@ func (l *listLayout) updateList(newOnly bool) { fyne.LogError("Missing UpdateCell callback required for List", nil) } - l.wasVisible = l.wasVisible[:0] // data already nilled out at end of this func - l.wasVisible = append(l.wasVisible, l.visible...) + // Swap l.wasVisible and l.visible + // since l.wasVisible contains only nil references at this point, + // we don't need to overwrite old data if we fill l.visible to less than + // the previous length of l.wasVisible + tmp := l.wasVisible + l.wasVisible = l.visible + l.visible = tmp l.list.propertyLock.Lock() offY, minRow := l.calculateVisibleRowHeights(l.list.itemMin.Height, length) @@ -653,7 +658,6 @@ func (l *listLayout) updateList(newOnly bool) { return } - oldVisibleLen := len(l.visible) l.visible = l.visible[:0] oldChildrenLen := len(l.children) l.children = l.children[:0] @@ -680,14 +684,6 @@ func (l *listLayout) updateList(newOnly bool) { l.children = append(l.children, c) } l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) - // nil out l.visible slice's unreferenced items - if ln := len(l.visible); oldVisibleLen > ln { - l.visible = l.visible[:oldVisibleLen] - for i := ln; i < oldVisibleLen; i++ { - l.visible[i].item = nil - } - l.visible = l.visible[:ln] - } for _, wasVis := range l.wasVisible { if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { From 819d2907aa8ea315e1731b3a90b9017dbadcddc6 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 18 Nov 2023 17:30:13 +0100 Subject: [PATCH 062/248] Cache some sizes to local variables in internal/painter --- internal/painter/draw.go | 23 +++++++++++++---------- internal/painter/image.go | 9 +++++---- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/internal/painter/draw.go b/internal/painter/draw.go index b48d615a8d..6a943fde28 100644 --- a/internal/painter/draw.go +++ b/internal/painter/draw.go @@ -47,20 +47,22 @@ func DrawCircle(circle *canvas.Circle, vectorPad float32, scale func(float32) fl // The scale function is used to understand how many pixels are required per unit of size. func DrawLine(line *canvas.Line, vectorPad float32, scale func(float32) float32) *image.RGBA { col := line.StrokeColor - width := int(scale(line.Size().Width + vectorPad*2)) - height := int(scale(line.Size().Height + vectorPad*2)) + size := line.Size() + width := int(scale(size.Width + vectorPad*2)) + height := int(scale(size.Height + vectorPad*2)) stroke := scale(line.StrokeWidth) if stroke < 1 { // software painter doesn't fade lines to compensate stroke = 1 } raw := image.NewRGBA(image.Rect(0, 0, width, height)) - scanner := rasterx.NewScannerGV(int(line.Size().Width), int(line.Size().Height), raw, raw.Bounds()) + scanner := rasterx.NewScannerGV(int(size.Width), int(size.Height), raw, raw.Bounds()) dasher := rasterx.NewDasher(width, height, scanner) dasher.SetColor(col) dasher.SetStroke(fixed.Int26_6(float64(stroke)*64), 0, nil, nil, nil, 0, nil, 0) - p1x, p1y := scale(line.Position1.X-line.Position().X+vectorPad), scale(line.Position1.Y-line.Position().Y+vectorPad) - p2x, p2y := scale(line.Position2.X-line.Position().X+vectorPad), scale(line.Position2.Y-line.Position().Y+vectorPad) + positon := line.Position() + p1x, p1y := scale(line.Position1.X-positon.X+vectorPad), scale(line.Position1.Y-positon.Y+vectorPad) + p2x, p2y := scale(line.Position2.X-positon.X+vectorPad), scale(line.Position2.Y-positon.Y+vectorPad) if stroke <= 1.5 { // adjust to support 1px if p1x == p2x { @@ -85,17 +87,18 @@ func DrawLine(line *canvas.Line, vectorPad float32, scale func(float32) float32) // The bounds of the output image will be increased by vectorPad to allow for stroke overflow at the edges. // The scale function is used to understand how many pixels are required per unit of size. func DrawRectangle(rect *canvas.Rectangle, vectorPad float32, scale func(float32) float32) *image.RGBA { - width := int(scale(rect.Size().Width + vectorPad*2)) - height := int(scale(rect.Size().Height + vectorPad*2)) + size := rect.Size() + width := int(scale(size.Width + vectorPad*2)) + height := int(scale(size.Height + vectorPad*2)) stroke := scale(rect.StrokeWidth) raw := image.NewRGBA(image.Rect(0, 0, width, height)) - scanner := rasterx.NewScannerGV(int(rect.Size().Width), int(rect.Size().Height), raw, raw.Bounds()) + scanner := rasterx.NewScannerGV(int(size.Width), int(size.Height), raw, raw.Bounds()) scaledPad := scale(vectorPad) p1x, p1y := scaledPad, scaledPad - p2x, p2y := scale(rect.Size().Width)+scaledPad, scaledPad - p3x, p3y := scale(rect.Size().Width)+scaledPad, scale(rect.Size().Height)+scaledPad + p2x, p2y := scale(size.Width)+scaledPad, scaledPad + p3x, p3y := scale(size.Width)+scaledPad, scale(size.Height)+scaledPad p4x, p4y := scaledPad, scale(rect.Size().Height)+scaledPad if rect.FillColor != nil { diff --git a/internal/painter/image.go b/internal/painter/image.go index 13b81bc6e8..a9e2a8adb9 100644 --- a/internal/painter/image.go +++ b/internal/painter/image.go @@ -50,18 +50,19 @@ func scaleImage(pixels image.Image, scaledW, scaledH int, scale canvas.ImageScal return pixels } - pixW := int(fyne.Min(float32(scaledW), float32(pixels.Bounds().Dx()))) // don't push more pixels than we have to - pixH := int(fyne.Min(float32(scaledH), float32(pixels.Bounds().Dy()))) // the GL calls will scale this up on GPU. + bounds := pixels.Bounds() + pixW := int(fyne.Min(float32(scaledW), float32(bounds.Dx()))) // don't push more pixels than we have to + pixH := int(fyne.Min(float32(scaledH), float32(bounds.Dy()))) // the GL calls will scale this up on GPU. scaledBounds := image.Rect(0, 0, pixW, pixH) tex := image.NewNRGBA(scaledBounds) switch scale { case canvas.ImageScalePixels: - draw.NearestNeighbor.Scale(tex, scaledBounds, pixels, pixels.Bounds(), draw.Over, nil) + draw.NearestNeighbor.Scale(tex, scaledBounds, pixels, bounds, draw.Over, nil) default: if scale != canvas.ImageScaleSmooth { fyne.LogError("Invalid canvas.ImageScale value, using canvas.ImageScaleSmooth", nil) } - draw.CatmullRom.Scale(tex, scaledBounds, pixels, pixels.Bounds(), draw.Over, nil) + draw.CatmullRom.Scale(tex, scaledBounds, pixels, bounds, draw.Over, nil) } return tex } From e7d74b49d3c1122e9722c1c8cdd5d07020b0ba1d Mon Sep 17 00:00:00 2001 From: Nikola Ubavic <53820106+ubavic@users.noreply.github.com> Date: Sat, 18 Nov 2023 18:10:03 +0100 Subject: [PATCH 063/248] Fix comment on theme variants --- theme/theme.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/theme.go b/theme/theme.go index 0d7af723b9..6f8ed78745 100644 --- a/theme/theme.go +++ b/theme/theme.go @@ -10,12 +10,12 @@ import ( ) const ( - // VariantDark is the version of a theme that satisfies a user preference for a light look. + // VariantDark is the version of a theme that satisfies a user preference for a dark look. // // Since: 2.0 VariantDark fyne.ThemeVariant = 0 - // VariantLight is the version of a theme that satisfies a user preference for a dark look. + // VariantLight is the version of a theme that satisfies a user preference for a light look. // // Since: 2.0 VariantLight fyne.ThemeVariant = 1 From 913e656cbe507fe19f59b9535eb5be7f54b23d23 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 18 Nov 2023 09:14:33 -0800 Subject: [PATCH 064/248] use sort.Search instead of own binary search impl --- widget/list.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/widget/list.go b/widget/list.go index 0cb805feac..f4660ee6c9 100644 --- a/widget/list.go +++ b/widget/list.go @@ -3,6 +3,7 @@ package widget import ( "fmt" "math" + "sort" "sync" "fyne.io/fyne/v2" @@ -746,19 +747,10 @@ func (l *listLayout) updateSeparators() { // invariant: visible is in ascending order of IDs func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) (*listItem, bool) { - // binary search - low := 0 - high := len(visible) - 1 - for low <= high { - mid := (low + high) / 2 - if visible[mid].id == id { - return visible[mid].item, true - } - if visible[mid].id > id { - high = mid - 1 - } else { - low = mid + 1 - } + ln := len(visible) + idx := sort.Search(ln, func(i int) bool { return visible[i].id >= id }) + if idx < ln && visible[idx].id == id { + return visible[idx].item, true } return nil, false } From 98d80b1b0cfaf7505b225fb51e226fe929aab80a Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 18 Nov 2023 10:18:16 -0800 Subject: [PATCH 065/248] add locking in RefreshItem --- widget/list.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/widget/list.go b/widget/list.go index f4660ee6c9..7e11fed705 100644 --- a/widget/list.go +++ b/widget/list.go @@ -123,7 +123,10 @@ func (l *List) RefreshItem(id ListItemID) { } l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) - if item, ok := lo.searchVisible(lo.visible, id); ok { + lo.renderLock.RLock() // ensures we are not changing visible info in render code during the search + item, ok := lo.searchVisible(lo.visible, id) + lo.renderLock.RUnlock() + if ok { lo.setupListItem(item, id, l.focused && l.currentFocus == id) } } @@ -537,7 +540,7 @@ type listLayout struct { visible []itemAndID wasVisible []itemAndID visibleRowHeights []float32 - renderLock sync.Mutex + renderLock sync.RWMutex } func newListLayout(list *List) fyne.Layout { From 8580df76bc4fe24c058b47a36d4ebc113779877e Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 21:29:03 +0100 Subject: [PATCH 066/248] Create a new package for buildtags --- app/app_debug.go | 8 -------- app/app_release.go | 8 -------- app/app_standard.go | 8 -------- app/settings.go | 3 ++- app/settings_test.go | 3 ++- internal/build/build.go | 2 ++ internal/build/driver_notwayland.go | 7 +++++++ internal/build/driver_wayland.go | 7 +++++++ internal/build/mode_debug.go | 9 +++++++++ internal/build/mode_release.go | 9 +++++++++ internal/build/mode_standard.go | 9 +++++++++ internal/debug_disabled.go | 8 -------- internal/debug_enabled.go | 8 -------- internal/driver/glfw/canvas.go | 3 ++- internal/driver/glfw/driver_notwayland.go | 6 ------ internal/driver/glfw/driver_wayland.go | 6 ------ internal/driver/glfw/window_desktop.go | 9 +++++---- internal/driver/mobile/driver.go | 3 ++- internal/painter/gl/gl.go | 5 +++-- 19 files changed, 59 insertions(+), 62 deletions(-) delete mode 100644 app/app_debug.go delete mode 100644 app/app_release.go delete mode 100644 app/app_standard.go create mode 100644 internal/build/build.go create mode 100644 internal/build/driver_notwayland.go create mode 100644 internal/build/driver_wayland.go create mode 100644 internal/build/mode_debug.go create mode 100644 internal/build/mode_release.go create mode 100644 internal/build/mode_standard.go delete mode 100644 internal/debug_disabled.go delete mode 100644 internal/debug_enabled.go delete mode 100644 internal/driver/glfw/driver_notwayland.go delete mode 100644 internal/driver/glfw/driver_wayland.go diff --git a/app/app_debug.go b/app/app_debug.go deleted file mode 100644 index f6b274dc73..0000000000 --- a/app/app_debug.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build debug -// +build debug - -package app - -import "fyne.io/fyne/v2" - -const buildMode = fyne.BuildDebug diff --git a/app/app_release.go b/app/app_release.go deleted file mode 100644 index 37b0a353fd..0000000000 --- a/app/app_release.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build release -// +build release - -package app - -import "fyne.io/fyne/v2" - -const buildMode = fyne.BuildRelease diff --git a/app/app_standard.go b/app/app_standard.go deleted file mode 100644 index 01f2ccc560..0000000000 --- a/app/app_standard.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !debug && !release -// +build !debug,!release - -package app - -import "fyne.io/fyne/v2" - -const buildMode = fyne.BuildStandard diff --git a/app/settings.go b/app/settings.go index c3b576b79b..cc0d32ed42 100644 --- a/app/settings.go +++ b/app/settings.go @@ -7,6 +7,7 @@ import ( "sync" "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/theme" ) @@ -44,7 +45,7 @@ type settings struct { } func (s *settings) BuildType() fyne.BuildType { - return buildMode + return build.Mode } func (s *settings) PrimaryColor() string { diff --git a/app/settings_test.go b/app/settings_test.go index 07388b857b..68f954b9a7 100644 --- a/app/settings_test.go +++ b/app/settings_test.go @@ -8,6 +8,7 @@ import ( "fyne.io/fyne/v2" "github.com/stretchr/testify/assert" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" ) @@ -17,7 +18,7 @@ func TestSettingsBuildType(t *testing.T) { assert.Equal(t, fyne.BuildStandard, set.BuildType()) // during test we should have a normal build set = &settings{} - assert.Equal(t, buildMode, set.BuildType()) // when testing this package only it could be debug or release + assert.Equal(t, build.Mode, set.BuildType()) // when testing this package only it could be debug or release } func TestSettingsLoad(t *testing.T) { diff --git a/internal/build/build.go b/internal/build/build.go new file mode 100644 index 0000000000..7db2881d5e --- /dev/null +++ b/internal/build/build.go @@ -0,0 +1,2 @@ +// Package build contains information about they type of build currently running. +package build diff --git a/internal/build/driver_notwayland.go b/internal/build/driver_notwayland.go new file mode 100644 index 0000000000..dbe88559c7 --- /dev/null +++ b/internal/build/driver_notwayland.go @@ -0,0 +1,7 @@ +//go:build !wayland +// +build !wayland + +package build + +// IsWayland is true when compiling for the wayland windowing system. +const IsWayland = false diff --git a/internal/build/driver_wayland.go b/internal/build/driver_wayland.go new file mode 100644 index 0000000000..eaa86cf1c1 --- /dev/null +++ b/internal/build/driver_wayland.go @@ -0,0 +1,7 @@ +//go:build wayland +// +build wayland + +package build + +// IsWayland is true when compiling for the wayland windowing system. +const IsWayland = true diff --git a/internal/build/mode_debug.go b/internal/build/mode_debug.go new file mode 100644 index 0000000000..e89ac6c13a --- /dev/null +++ b/internal/build/mode_debug.go @@ -0,0 +1,9 @@ +//go:build debug +// +build debug + +package build + +import "fyne.io/fyne/v2" + +// Mode is the application's build mode. +const Mode = fyne.BuildDebug diff --git a/internal/build/mode_release.go b/internal/build/mode_release.go new file mode 100644 index 0000000000..8c4f6604f6 --- /dev/null +++ b/internal/build/mode_release.go @@ -0,0 +1,9 @@ +//go:build release +// +build release + +package build + +import "fyne.io/fyne/v2" + +// Mode is the application's build mode. +const Mode = fyne.BuildRelease diff --git a/internal/build/mode_standard.go b/internal/build/mode_standard.go new file mode 100644 index 0000000000..c46dac9992 --- /dev/null +++ b/internal/build/mode_standard.go @@ -0,0 +1,9 @@ +//go:build !debug && !release +// +build !debug,!release + +package build + +import "fyne.io/fyne/v2" + +// Mode is the application's build mode. +const Mode = fyne.BuildStandard diff --git a/internal/debug_disabled.go b/internal/debug_disabled.go deleted file mode 100644 index b970163114..0000000000 --- a/internal/debug_disabled.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !debug -// +build !debug - -package internal - -// BuildTypeIsDebug is true if built with -tags debug. This value exists as a constant -// so the Go compiler can deadcode eliminate reflect from non-debug builds. -const BuildTypeIsDebug = false diff --git a/internal/debug_enabled.go b/internal/debug_enabled.go deleted file mode 100644 index 916413ed58..0000000000 --- a/internal/debug_enabled.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build debug -// +build debug - -package internal - -// BuildTypeIsDebug is true if built with -tags debug. This value exists as a constant -// so the Go compiler can deadcode eliminate reflect from non-debug builds. -const BuildTypeIsDebug = true diff --git a/internal/driver/glfw/canvas.go b/internal/driver/glfw/canvas.go index 66862493b9..2cb47f9755 100644 --- a/internal/driver/glfw/canvas.go +++ b/internal/driver/glfw/canvas.go @@ -8,6 +8,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/internal" "fyne.io/fyne/v2/internal/app" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/driver" "fyne.io/fyne/v2/internal/driver/common" "fyne.io/fyne/v2/theme" @@ -298,7 +299,7 @@ func (c *glCanvas) paint(size fyne.Size) { } } - if internal.BuildTypeIsDebug { + if build.Mode == fyne.BuildDebug { c.DrawDebugOverlay(node.Obj(), pos, size) } } diff --git a/internal/driver/glfw/driver_notwayland.go b/internal/driver/glfw/driver_notwayland.go deleted file mode 100644 index 941c833825..0000000000 --- a/internal/driver/glfw/driver_notwayland.go +++ /dev/null @@ -1,6 +0,0 @@ -//go:build !wayland -// +build !wayland - -package glfw - -const isWayland = false diff --git a/internal/driver/glfw/driver_wayland.go b/internal/driver/glfw/driver_wayland.go deleted file mode 100644 index 810ff92517..0000000000 --- a/internal/driver/glfw/driver_wayland.go +++ /dev/null @@ -1,6 +0,0 @@ -//go:build wayland -// +build wayland - -package glfw - -const isWayland = true diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index d04fccd421..ba3dc0845a 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -14,6 +14,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/driver/common" "fyne.io/fyne/v2/internal/painter" "fyne.io/fyne/v2/internal/painter/gl" @@ -184,7 +185,7 @@ func (w *window) doCenterOnScreen() { } func (w *window) RequestFocus() { - if isWayland || w.view() == nil { + if build.IsWayland || w.view() == nil { return } @@ -296,7 +297,7 @@ func (w *window) getMonitorForWindow() *glfw.Monitor { } func (w *window) detectScale() float32 { - if isWayland { // Wayland controls scale through content scaling + if build.IsWayland { // Wayland controls scale through content scaling return 1.0 } monitor := w.getMonitorForWindow() @@ -319,7 +320,7 @@ func (w *window) resized(_ *glfw.Window, width, height int) { } func (w *window) scaled(_ *glfw.Window, x float32, y float32) { - if !isWayland { // other platforms handle this using older APIs + if !build.IsWayland { // other platforms handle this using older APIs return } @@ -707,7 +708,7 @@ func (w *window) rescaleOnMain() { func (w *window) create() { runOnMain(func() { - if !isWayland { + if !build.IsWayland { // make the window hidden, we will set it up and then show it later glfw.WindowHint(glfw.Visible, glfw.False) } diff --git a/internal/driver/mobile/driver.go b/internal/driver/mobile/driver.go index 2114838dd5..dcb9a028dd 100644 --- a/internal/driver/mobile/driver.go +++ b/internal/driver/mobile/driver.go @@ -12,6 +12,7 @@ import ( "fyne.io/fyne/v2/internal" "fyne.io/fyne/v2/internal/animation" intapp "fyne.io/fyne/v2/internal/app" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/driver" "fyne.io/fyne/v2/internal/driver/common" @@ -315,7 +316,7 @@ func (d *mobileDriver) paintWindow(window fyne.Window, size fyne.Size) { } } - if internal.BuildTypeIsDebug { + if build.Mode == fyne.BuildDebug { c.DrawDebugOverlay(node.Obj(), pos, size) } } diff --git a/internal/painter/gl/gl.go b/internal/painter/gl/gl.go index 65dad1b786..482447a25d 100644 --- a/internal/painter/gl/gl.go +++ b/internal/painter/gl/gl.go @@ -6,7 +6,8 @@ import ( "log" "runtime" - "fyne.io/fyne/v2/internal" + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/build" ) const floatSize = 4 @@ -17,7 +18,7 @@ const max16bit = float32(255 * 255) // Receives a function as parameter, to lazily get the error code only when // needed, avoiding unneeded overhead. func logGLError(getError func() uint32) { - if !internal.BuildTypeIsDebug { + if build.Mode != fyne.BuildDebug { return } From 57d9b87d761d7b232c415cad477c4a04d3f68e3d Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 22 Nov 2023 10:08:49 +0000 Subject: [PATCH 067/248] Update release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a77ef35f57..797b360df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). -## 2.4.2 - 21 November 2023 +## 2.4.2 - 22 November 2023 ### Fixed From 224edd03c8181b9d65fa465ff60d999cced61772 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 22 Nov 2023 10:55:26 +0000 Subject: [PATCH 068/248] Fixing bad test data merge --- .../doctabs/mobile/change_icon_change_selected.xml | 10 +++++----- .../doctabs/mobile/change_icon_change_unselected.xml | 10 +++++----- .../testdata/doctabs/mobile/change_icon_initial.xml | 10 +++++----- .../testdata/doctabs/mobile/layout_bottom_ico.xml | 10 +++++----- .../doctabs/mobile/layout_bottom_icon_and_text.xml | 10 +++++----- container/testdata/doctabs/mobile/layout_top_icon.xml | 10 +++++----- .../doctabs/mobile/layout_top_icon_and_text.xml | 10 +++++----- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/container/testdata/doctabs/mobile/change_icon_change_selected.xml b/container/testdata/doctabs/mobile/change_icon_change_selected.xml index 6dd8bb5cc0..bd61382688 100644 --- a/container/testdata/doctabs/mobile/change_icon_change_selected.xml +++ b/container/testdata/doctabs/mobile/change_icon_change_selected.xml @@ -18,11 +18,11 @@ - - - - - + + + + + diff --git a/container/testdata/doctabs/mobile/change_icon_change_unselected.xml b/container/testdata/doctabs/mobile/change_icon_change_unselected.xml index 301d0914d9..79530754a1 100644 --- a/container/testdata/doctabs/mobile/change_icon_change_unselected.xml +++ b/container/testdata/doctabs/mobile/change_icon_change_unselected.xml @@ -18,11 +18,11 @@ - - - - - + + + + + diff --git a/container/testdata/doctabs/mobile/change_icon_initial.xml b/container/testdata/doctabs/mobile/change_icon_initial.xml index 6ec23a54be..aecf735ec1 100644 --- a/container/testdata/doctabs/mobile/change_icon_initial.xml +++ b/container/testdata/doctabs/mobile/change_icon_initial.xml @@ -18,11 +18,11 @@ - - - - - + + + + + diff --git a/container/testdata/doctabs/mobile/layout_bottom_ico.xml b/container/testdata/doctabs/mobile/layout_bottom_ico.xml index 145b8cda3c..1df0bd559d 100644 --- a/container/testdata/doctabs/mobile/layout_bottom_ico.xml +++ b/container/testdata/doctabs/mobile/layout_bottom_ico.xml @@ -12,11 +12,11 @@ - - - - - + + + + + diff --git a/container/testdata/doctabs/mobile/layout_bottom_icon_and_text.xml b/container/testdata/doctabs/mobile/layout_bottom_icon_and_text.xml index 5984599241..a7a8acf5e5 100644 --- a/container/testdata/doctabs/mobile/layout_bottom_icon_and_text.xml +++ b/container/testdata/doctabs/mobile/layout_bottom_icon_and_text.xml @@ -13,11 +13,11 @@ - - - - - + + + + + diff --git a/container/testdata/doctabs/mobile/layout_top_icon.xml b/container/testdata/doctabs/mobile/layout_top_icon.xml index cc753eb1d5..087896f2b4 100644 --- a/container/testdata/doctabs/mobile/layout_top_icon.xml +++ b/container/testdata/doctabs/mobile/layout_top_icon.xml @@ -12,11 +12,11 @@ - - - - - + + + + + diff --git a/container/testdata/doctabs/mobile/layout_top_icon_and_text.xml b/container/testdata/doctabs/mobile/layout_top_icon_and_text.xml index 673af7693b..f326c67766 100644 --- a/container/testdata/doctabs/mobile/layout_top_icon_and_text.xml +++ b/container/testdata/doctabs/mobile/layout_top_icon_and_text.xml @@ -13,11 +13,11 @@ - - - - - + + + + + From 0ab2a60635f883faba5108f39dd33ba4a2874cf0 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 23 Nov 2023 19:39:02 +0100 Subject: [PATCH 069/248] Remove old clipboard workarounds after changes in GLFW See https://github.com/fyne-io/fyne/pull/1136. The clipboard no longer crashes when pasting empy content (also verified locally). The clipboard also no longer require access to the window struct. Clean up the code. As the clipboard no longer needs the viewport, we can also remove a possible crash when getting a clipboard from a window that has yet to be set up. --- internal/driver/glfw/clipboard.go | 10 +--------- internal/driver/glfw/window.go | 9 +-------- internal/driver/glfw/window_desktop.go | 2 -- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/internal/driver/glfw/clipboard.go b/internal/driver/glfw/clipboard.go index a0bd540135..41fb2edd07 100644 --- a/internal/driver/glfw/clipboard.go +++ b/internal/driver/glfw/clipboard.go @@ -16,9 +16,7 @@ import ( var _ fyne.Clipboard = (*clipboard)(nil) // clipboard represents the system clipboard -type clipboard struct { - window *glfw.Window -} +type clipboard struct{} // Content returns the clipboard content func (c *clipboard) Content() string { @@ -64,12 +62,6 @@ func (c *clipboard) SetContent(content string) { func (c *clipboard) setContent(content string) { runOnMain(func() { - defer func() { - if r := recover(); r != nil { - fyne.LogError("GLFW clipboard error (details above)", nil) - } - }() - glfw.SetClipboardString(content) }) } diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 971fc486d0..c0f1dd21d3 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -229,14 +229,7 @@ func (w *window) ShowAndRun() { // Clipboard returns the system clipboard func (w *window) Clipboard() fyne.Clipboard { - if w.view() == nil { - return nil - } - - if w.clipboard == nil { - w.clipboard = &clipboard{window: w.viewport} - } - return w.clipboard + return &clipboard{} } func (w *window) Content() fyne.CanvasObject { diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index d04fccd421..48515ed858 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -77,8 +77,6 @@ type window struct { icon fyne.Resource mainmenu *fyne.MainMenu - clipboard fyne.Clipboard - master bool fullScreen bool centered bool From 529a3d6bf6dc83a2cd4d602abfee7aa002cf0799 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 23 Nov 2023 19:39:22 +0100 Subject: [PATCH 070/248] Add comments to GLFW workarounds still needed --- internal/driver/glfw/loop_desktop.go | 1 + internal/driver/glfw/loop_goxjs.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/driver/glfw/loop_desktop.go b/internal/driver/glfw/loop_desktop.go index 652e6cf023..988cbd5bf5 100644 --- a/internal/driver/glfw/loop_desktop.go +++ b/internal/driver/glfw/loop_desktop.go @@ -26,6 +26,7 @@ func (d *gLDriver) initGLFW() { func (d *gLDriver) tryPollEvents() { defer func() { + // See https://github.com/glfw/glfw/issues/1785 and https://github.com/fyne-io/fyne/issues/1024. if r := recover(); r != nil { fyne.LogError(fmt.Sprint("GLFW poll event error: ", r), nil) } diff --git a/internal/driver/glfw/loop_goxjs.go b/internal/driver/glfw/loop_goxjs.go index e5082800ac..baa46fac3c 100644 --- a/internal/driver/glfw/loop_goxjs.go +++ b/internal/driver/glfw/loop_goxjs.go @@ -26,6 +26,7 @@ func (d *gLDriver) initGLFW() { func (d *gLDriver) tryPollEvents() { defer func() { + // See https://github.com/glfw/glfw/issues/1785 and https://github.com/fyne-io/fyne/issues/1024. if r := recover(); r != nil { fyne.LogError(fmt.Sprint("GLFW poll event error: ", r), nil) } From 3d7e02ead20c0e645542a32304d88d48751e9d0f Mon Sep 17 00:00:00 2001 From: Jacob Date: Fri, 24 Nov 2023 10:09:18 +0100 Subject: [PATCH 071/248] Update go-gl/glfw for image fix and minor cleanup This includes a fix for https://github.com/go-gl/glfw/issues/379 and my PR for cleaning up an old workaround that hasn't been needed for a while now (https://github.com/go-gl/glfw/commit/2de0cf0c80afef18cbe6bb0517ed4cb4eade1b19). --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 899268e30d..82fb3ffade 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 - github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b + github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231124074035-2de0cf0c80af github.com/go-ole/go-ole v1.2.6 github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a diff --git a/go.sum b/go.sum index 79b30237b6..4c77a44397 100644 --- a/go.sum +++ b/go.sum @@ -99,8 +99,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b h1:GgabKamyOYguHqHjSkDACcgoPIz3w0Dis/zJ1wyHHHU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231124074035-2de0cf0c80af h1:zclgNFqP+NXDgGX2BiDvIonxKIom8j65wQlOyFtyujc= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231124074035-2de0cf0c80af/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 h1:VkKnvzbvHqgEfm351rfr8Uclu5fnwq8HP2ximUzJsBM= From c1a271e9e294339c3530cbcbf09a1e32d5b6d42e Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 24 Nov 2023 10:15:00 +0000 Subject: [PATCH 072/248] 2.1 is not a valid GLES version --- internal/driver/glfw/glfw_es.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/driver/glfw/glfw_es.go b/internal/driver/glfw/glfw_es.go index b3ec94a37a..2dd30cf459 100644 --- a/internal/driver/glfw/glfw_es.go +++ b/internal/driver/glfw/glfw_es.go @@ -12,5 +12,5 @@ import "github.com/go-gl/glfw/v3.3/glfw" func initWindowHints() { glfw.WindowHint(glfw.ClientAPI, glfw.OpenGLESAPI) glfw.WindowHint(glfw.ContextVersionMajor, 2) - glfw.WindowHint(glfw.ContextVersionMinor, 1) + glfw.WindowHint(glfw.ContextVersionMinor, 0) } From 1580bb0a4c4a3f9b35e27980f26f1933d213c84d Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 26 Nov 2023 21:44:58 +0000 Subject: [PATCH 073/248] Fix to remove systray id from Windows and macOS --- internal/driver/glfw/driver_desktop.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/internal/driver/glfw/driver_desktop.go b/internal/driver/glfw/driver_desktop.go index 5660d745ed..b317bc35c0 100644 --- a/internal/driver/glfw/driver_desktop.go +++ b/internal/driver/glfw/driver_desktop.go @@ -46,12 +46,16 @@ func (d *gLDriver) SetSystemTrayMenu(m *fyne.Menu) { d.SetSystemTrayIcon(theme.BrokenImageIcon()) } - app := fyne.CurrentApp() - title := app.Metadata().Name - if title == "" { - title = app.UniqueID() + // Some XDG systray crash without a title (See #3678) + if runtime.GOOS == "linux" || runtime.GOOS == "openbsd" || runtime.GOOS == "freebsd" || runtime.GOOS == "netbsd" { + app := fyne.CurrentApp() + title := app.Metadata().Name + if title == "" { + title = app.UniqueID() + } + + systray.SetTitle(title) } - systray.SetTitle(title) // it must be refreshed after init, so an earlier call would have been ineffective d.refreshSystray(m) From adf017782ecc02960699e80d7e92196708e6587b Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 26 Nov 2023 21:44:58 +0000 Subject: [PATCH 074/248] Fix to remove systray id from Windows and macOS --- internal/driver/glfw/driver_desktop.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/internal/driver/glfw/driver_desktop.go b/internal/driver/glfw/driver_desktop.go index 5660d745ed..b317bc35c0 100644 --- a/internal/driver/glfw/driver_desktop.go +++ b/internal/driver/glfw/driver_desktop.go @@ -46,12 +46,16 @@ func (d *gLDriver) SetSystemTrayMenu(m *fyne.Menu) { d.SetSystemTrayIcon(theme.BrokenImageIcon()) } - app := fyne.CurrentApp() - title := app.Metadata().Name - if title == "" { - title = app.UniqueID() + // Some XDG systray crash without a title (See #3678) + if runtime.GOOS == "linux" || runtime.GOOS == "openbsd" || runtime.GOOS == "freebsd" || runtime.GOOS == "netbsd" { + app := fyne.CurrentApp() + title := app.Metadata().Name + if title == "" { + title = app.UniqueID() + } + + systray.SetTitle(title) } - systray.SetTitle(title) // it must be refreshed after init, so an earlier call would have been ineffective d.refreshSystray(m) From 50765e0ed1c5d88a68a64bdad051418c61645618 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 27 Nov 2023 09:22:46 +0000 Subject: [PATCH 075/248] Tracking changes for next release --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a77ef35f57..952c7d8323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). +## 2.4.3 - Ongoing + +### Fixes + +* Fix OpenGL init for arm64 desktop devices +* System tray icon on Mac is showing the app ID (#4416) + + ## 2.4.2 - 21 November 2023 ### Fixed From 03c82b21c7e42e975b9c12fca3607aa606af5dc1 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 23:20:43 +0100 Subject: [PATCH 076/248] Fix *BSD systems using the wrong (and slow) window resize --- internal/driver/glfw/{window_notlinux.go => window_notxdg.go} | 4 ++-- internal/driver/glfw/{window_linux.go => window_xdg.go} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename internal/driver/glfw/{window_notlinux.go => window_notxdg.go} (81%) rename internal/driver/glfw/{window_linux.go => window_xdg.go} (100%) diff --git a/internal/driver/glfw/window_notlinux.go b/internal/driver/glfw/window_notxdg.go similarity index 81% rename from internal/driver/glfw/window_notlinux.go rename to internal/driver/glfw/window_notxdg.go index ed30559c3b..6c693bf2ef 100644 --- a/internal/driver/glfw/window_notlinux.go +++ b/internal/driver/glfw/window_notxdg.go @@ -1,5 +1,5 @@ -//go:build !linux -// +build !linux +//go:build !linux && !freebsd && !openbsd && !netbsd +// +build !linux,!freebsd,!openbsd,!netbsd package glfw diff --git a/internal/driver/glfw/window_linux.go b/internal/driver/glfw/window_xdg.go similarity index 100% rename from internal/driver/glfw/window_linux.go rename to internal/driver/glfw/window_xdg.go From 2c5349fb3f52f7ffe33ed356bdb34cb305ebfeb9 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 23:36:08 +0100 Subject: [PATCH 077/248] Try to make the buildtag work on not unix --- internal/driver/glfw/window_xdg.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/driver/glfw/window_xdg.go b/internal/driver/glfw/window_xdg.go index 9d56dd06a4..a8f4331a8a 100644 --- a/internal/driver/glfw/window_xdg.go +++ b/internal/driver/glfw/window_xdg.go @@ -1,3 +1,6 @@ +//go:build linux || freebsd || openbsd || netbsd +// +build linux freebsd openbsd netbsd + package glfw import "fyne.io/fyne/v2" From eba8c46187b610a79a48c9af084f2e400639d6a9 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 18 Nov 2023 19:00:13 +0100 Subject: [PATCH 078/248] Initial support for notifications through xdg-desktop-portal --- app/app_xdg.go | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/app/app_xdg.go b/app/app_xdg.go index 832bb52707..fe1da93247 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -12,6 +12,7 @@ import ( "net/url" "os" "path/filepath" + "strconv" "sync" "github.com/godbus/dbus/v5" @@ -81,18 +82,44 @@ func (a *fyneApp) SendNotification(n *fyne.Notification) { return } - appName := fyne.CurrentApp().UniqueID() + if a.sendXDGDesktopPortalNotification(conn, n) == nil { + return // No need to use the fallback path. + } + appIcon := a.cachedIconPath() timeout := int32(0) // we don't support this yet obj := conn.Object("org.freedesktop.Notifications", "/org/freedesktop/Notifications") - call := obj.Call("org.freedesktop.Notifications.Notify", 0, appName, uint32(0), + call := obj.Call("org.freedesktop.Notifications.Notify", 0, a.uniqueID, uint32(0), appIcon, n.Title, n.Content, []string{}, map[string]dbus.Variant{}, timeout) if call.Err != nil { fyne.LogError("Failed to send message to bus", call.Err) } } +// Sending with same ID replaces the old notification. +var notificationID int = 0 + +// See https://flatpak.github.io/xdg-desktop-portal/docs/#gdbus-org.freedesktop.portal.Notification. +func (a *fyneApp) sendXDGDesktopPortalNotification(conn *dbus.Conn, n *fyne.Notification) error { + id := strconv.Itoa(notificationID) + data := map[string]dbus.Variant{ + "title": dbus.MakeVariant(n.Title), + "body": dbus.MakeVariant(n.Content), + "icon": dbus.MakeVariant(a.uniqueID), + } + + obj := conn.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop") + call := obj.Call("org.freedesktop.portal.Notification.AddNotification", 0, id, data) + if call.Err != nil { + fyne.LogError("Failed to send notification to xdg-desktop-portal", call.Err) + return call.Err + } + + notificationID++ + return nil +} + func (a *fyneApp) saveIconToCache(dirPath, filePath string) error { err := os.MkdirAll(dirPath, 0700) if err != nil { From 1bd9c07e45eb4f762bbdadf18f2d8504419c1324 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 18 Nov 2023 23:11:10 +0100 Subject: [PATCH 079/248] Update OpenURL to use portal if possible --- app/app_xdg.go | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/app/app_xdg.go b/app/app_xdg.go index fe1da93247..f9e3c7eb17 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -29,11 +29,36 @@ func defaultVariant() fyne.ThemeVariant { } func (a *fyneApp) OpenURL(url *url.URL) error { + if openURLThroughPortal(url) == nil { + return nil + } + cmd := execabs.Command("xdg-open", url.String()) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr return cmd.Start() } +func openURLThroughPortal(url *url.URL) error { + conn, err := dbus.SessionBus() // shared connection, don't close + if err != nil { + fyne.LogError("Unable to connect to session D-Bus", err) + return err + } + + parentWindow := "" + uri := url.String() + options := map[string]dbus.Variant{} + + obj := conn.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop") + call := obj.Call("org.freedesktop.portal.OpenURI.OpenURI", 0, parentWindow, uri, options) + if call.Err != nil { + fyne.LogError("Failed to open url with xdg-desktop-portal", call.Err) + return call.Err + } + + return nil +} + // fetch color variant from dbus portal desktop settings. func findFreedestktopColorScheme() fyne.ThemeVariant { dbusConn, err := dbus.SessionBus() @@ -82,7 +107,7 @@ func (a *fyneApp) SendNotification(n *fyne.Notification) { return } - if a.sendXDGDesktopPortalNotification(conn, n) == nil { + if a.sendNotificationThroughPortal(conn, n) == nil { return // No need to use the fallback path. } @@ -98,11 +123,11 @@ func (a *fyneApp) SendNotification(n *fyne.Notification) { } // Sending with same ID replaces the old notification. -var notificationID int = 0 +var notificationID uint64 = 0 // See https://flatpak.github.io/xdg-desktop-portal/docs/#gdbus-org.freedesktop.portal.Notification. -func (a *fyneApp) sendXDGDesktopPortalNotification(conn *dbus.Conn, n *fyne.Notification) error { - id := strconv.Itoa(notificationID) +func (a *fyneApp) sendNotificationThroughPortal(conn *dbus.Conn, n *fyne.Notification) error { + id := strconv.FormatUint(notificationID, 10) data := map[string]dbus.Variant{ "title": dbus.MakeVariant(n.Title), "body": dbus.MakeVariant(n.Content), From fb32438be90cdf6aabd492bbdc99c723ab1be0fa Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 12:01:09 +0100 Subject: [PATCH 080/248] Don't use deprecated .Read call --- app/app_xdg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app_xdg.go b/app/app_xdg.go index f9e3c7eb17..6e1fa7fa8c 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -69,7 +69,7 @@ func findFreedestktopColorScheme() fyne.ThemeVariant { dbusObj := dbusConn.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop") call := dbusObj.Call( - "org.freedesktop.portal.Settings.Read", + "org.freedesktop.portal.Settings.ReadOne", dbus.FlagNoAutoStart, "org.freedesktop.appearance", "color-scheme", From 349c6cbf86c0a9a199c4cfc9a719c6aa088286b5 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 12:16:20 +0100 Subject: [PATCH 081/248] Simplify code by using rymdport/portal package --- app/app_xdg.go | 55 +++++++++++++++++--------------------------------- go.mod | 1 + go.sum | 2 ++ 3 files changed, 21 insertions(+), 37 deletions(-) diff --git a/app/app_xdg.go b/app/app_xdg.go index 6e1fa7fa8c..ba6d38b25e 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -12,10 +12,11 @@ import ( "net/url" "os" "path/filepath" - "strconv" "sync" "github.com/godbus/dbus/v5" + "github.com/rymdport/portal/notification" + "github.com/rymdport/portal/openuri" "golang.org/x/sys/execabs" "fyne.io/fyne/v2" @@ -29,8 +30,10 @@ func defaultVariant() fyne.ThemeVariant { } func (a *fyneApp) OpenURL(url *url.URL) error { - if openURLThroughPortal(url) == nil { + if err := openuri.OpenURI(url.String()); err == nil { return nil + } else { + fyne.LogError("Opening url in portal failed", err) } cmd := execabs.Command("xdg-open", url.String()) @@ -38,27 +41,6 @@ func (a *fyneApp) OpenURL(url *url.URL) error { return cmd.Start() } -func openURLThroughPortal(url *url.URL) error { - conn, err := dbus.SessionBus() // shared connection, don't close - if err != nil { - fyne.LogError("Unable to connect to session D-Bus", err) - return err - } - - parentWindow := "" - uri := url.String() - options := map[string]dbus.Variant{} - - obj := conn.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop") - call := obj.Call("org.freedesktop.portal.OpenURI.OpenURI", 0, parentWindow, uri, options) - if call.Err != nil { - fyne.LogError("Failed to open url with xdg-desktop-portal", call.Err) - return call.Err - } - - return nil -} - // fetch color variant from dbus portal desktop settings. func findFreedestktopColorScheme() fyne.ThemeVariant { dbusConn, err := dbus.SessionBus() @@ -107,8 +89,10 @@ func (a *fyneApp) SendNotification(n *fyne.Notification) { return } - if a.sendNotificationThroughPortal(conn, n) == nil { + if err := a.sendNotificationThroughPortal(conn, n); err == nil { return // No need to use the fallback path. + } else { + fyne.LogError("Sending notification using portal failed", err) } appIcon := a.cachedIconPath() @@ -123,22 +107,19 @@ func (a *fyneApp) SendNotification(n *fyne.Notification) { } // Sending with same ID replaces the old notification. -var notificationID uint64 = 0 +var notificationID uint = 0 // See https://flatpak.github.io/xdg-desktop-portal/docs/#gdbus-org.freedesktop.portal.Notification. func (a *fyneApp) sendNotificationThroughPortal(conn *dbus.Conn, n *fyne.Notification) error { - id := strconv.FormatUint(notificationID, 10) - data := map[string]dbus.Variant{ - "title": dbus.MakeVariant(n.Title), - "body": dbus.MakeVariant(n.Content), - "icon": dbus.MakeVariant(a.uniqueID), - } - - obj := conn.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop") - call := obj.Call("org.freedesktop.portal.Notification.AddNotification", 0, id, data) - if call.Err != nil { - fyne.LogError("Failed to send notification to xdg-desktop-portal", call.Err) - return call.Err + err := notification.Add(notificationID, + ¬ification.Content{ + Title: n.Title, + Body: n.Content, + Icon: a.uniqueID, + }, + ) + if err != nil { + return err } notificationID++ diff --git a/go.mod b/go.mod index c4068cf2a6..a2d2b1ec69 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/lucor/goinfo v0.9.0 github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 + github.com/rymdport/portal v0.0.0-20231119111435-f007cc4c83bb github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index 1c01831966..e1f3900b23 100644 --- a/go.sum +++ b/go.sum @@ -266,6 +266,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/rymdport/portal v0.0.0-20231119111435-f007cc4c83bb h1:G7vOtmOMTjkjbApmz4Rfa9vSft+8faoe8i9kBqmzBuo= +github.com/rymdport/portal v0.0.0-20231119111435-f007cc4c83bb/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= From 03bc57baeb93c126de67b929226819822d97b6d3 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 12:35:34 +0100 Subject: [PATCH 082/248] Update portal to get parentWindow inputs --- app/app_xdg.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/app_xdg.go b/app/app_xdg.go index ba6d38b25e..0f39cbad60 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -30,7 +30,7 @@ func defaultVariant() fyne.ThemeVariant { } func (a *fyneApp) OpenURL(url *url.URL) error { - if err := openuri.OpenURI(url.String()); err == nil { + if err := openuri.OpenURI("", url.String()); err == nil { return nil } else { fyne.LogError("Opening url in portal failed", err) diff --git a/go.mod b/go.mod index a2d2b1ec69..8ed08b4b7f 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/lucor/goinfo v0.9.0 github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 - github.com/rymdport/portal v0.0.0-20231119111435-f007cc4c83bb + github.com/rymdport/portal v0.0.0-20231119112124-889a3dbc2075 github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index e1f3900b23..6c99a0c0ab 100644 --- a/go.sum +++ b/go.sum @@ -266,8 +266,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/rymdport/portal v0.0.0-20231119111435-f007cc4c83bb h1:G7vOtmOMTjkjbApmz4Rfa9vSft+8faoe8i9kBqmzBuo= -github.com/rymdport/portal v0.0.0-20231119111435-f007cc4c83bb/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= +github.com/rymdport/portal v0.0.0-20231119112124-889a3dbc2075 h1:21ZHdpquG8LPmbQK4XKzcog9F6Y2kyskMJ4euID06U8= +github.com/rymdport/portal v0.0.0-20231119112124-889a3dbc2075/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= From 475db660e94f89ccce66858712caffd867b0f5f5 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 13:01:04 +0100 Subject: [PATCH 083/248] Wire up initial support for file and folder dialogs --- dialog/file_notunix.go | 11 ++++++++ dialog/file_unix.go | 8 ------ dialog/file_xdg.go | 59 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 dialog/file_notunix.go diff --git a/dialog/file_notunix.go b/dialog/file_notunix.go new file mode 100644 index 0000000000..f5a6637efe --- /dev/null +++ b/dialog/file_notunix.go @@ -0,0 +1,11 @@ +//go:build (!linux && !openbsd && !freebsd && !netbsd) || android || wasm || js + +package dialog + +func fileOpenOSOverride(*FileDialog) bool { + return false +} + +func fileSaveOSOverride(*FileDialog) bool { + return false +} diff --git a/dialog/file_unix.go b/dialog/file_unix.go index bcb6b3cc08..dea11fbe4a 100644 --- a/dialog/file_unix.go +++ b/dialog/file_unix.go @@ -37,11 +37,3 @@ func isHidden(file fyne.URI) bool { func hideFile(filename string) error { return nil } - -func fileOpenOSOverride(*FileDialog) bool { - return false -} - -func fileSaveOSOverride(*FileDialog) bool { - return false -} diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 824aa1bce3..846567902a 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -12,6 +12,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/storage" + "github.com/rymdport/portal/filechooser" "golang.org/x/sys/execabs" ) @@ -74,3 +75,61 @@ func getFavoriteLocations() (map[string]fyne.ListableURI, error) { return favoriteLocations, err } + +func fileOpenOSOverride(d *FileDialog) bool { + go func() { + callback, folder := d.callback.(func(fyne.ListableURI, error)) + options := &filechooser.OpenOptions{Modal: true, Directory: folder} + + uris, err := filechooser.OpenFile("", "Open File", options) + if !folder { + callback := d.callback.(func(fyne.URIReadCloser, error)) + if err != nil { + callback(nil, err) + return + } + + uri, err := storage.ParseURI(uris[0]) + if err != nil { + callback(nil, err) + return + } + + callback(storage.Reader(uri)) + return + } + if err != nil { + callback(nil, err) + } + + uri, err := storage.ParseURI(uris[0]) + if err != nil { + callback(nil, err) + return + } + + callback(storage.ListerForURI(uri)) + }() + + return true +} + +func fileSaveOSOverride(d *FileDialog) bool { + go func() { + callback := d.callback.(func(fyne.URIWriteCloser, error)) + uris, err := filechooser.SaveFile("", "Open File", &filechooser.SaveSingleOptions{Modal: true}) + if err != nil { + callback(nil, err) + return + } + + uri, err := storage.ParseURI(uris[0]) + if err != nil { + callback(nil, err) + return + } + + callback(storage.Writer(uri)) + }() + return true +} From 54e960bd79337ef92cc7288377cbcbdd819838f9 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 13:07:41 +0100 Subject: [PATCH 084/248] Use the correct name for the folder portal --- dialog/file_xdg.go | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 846567902a..4ae1492c27 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -78,39 +78,40 @@ func getFavoriteLocations() (map[string]fyne.ListableURI, error) { func fileOpenOSOverride(d *FileDialog) bool { go func() { - callback, folder := d.callback.(func(fyne.ListableURI, error)) + folderCallback, folder := d.callback.(func(fyne.ListableURI, error)) options := &filechooser.OpenOptions{Modal: true, Directory: folder} - uris, err := filechooser.OpenFile("", "Open File", options) - if !folder { - callback := d.callback.(func(fyne.URIReadCloser, error)) + if folder { + uris, err := filechooser.OpenFile("", "Open Folder", options) if err != nil { - callback(nil, err) - return + folderCallback(nil, err) } uri, err := storage.ParseURI(uris[0]) if err != nil { - callback(nil, err) + folderCallback(nil, err) return } - callback(storage.Reader(uri)) + folderCallback(storage.ListerForURI(uri)) return } + + uris, err := filechooser.OpenFile("", "Open File", options) + fileCallback := d.callback.(func(fyne.URIReadCloser, error)) if err != nil { - callback(nil, err) + fileCallback(nil, err) + return } uri, err := storage.ParseURI(uris[0]) if err != nil { - callback(nil, err) + fileCallback(nil, err) return } - callback(storage.ListerForURI(uri)) + fileCallback(storage.Reader(uri)) }() - return true } From b59b45886d84d73b47fed29c4e19798d8e822a5b Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 13:21:31 +0100 Subject: [PATCH 085/248] Handle cancelled dialogs --- dialog/file_xdg.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 4ae1492c27..d8317b9c04 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -87,6 +87,11 @@ func fileOpenOSOverride(d *FileDialog) bool { folderCallback(nil, err) } + if len(uris) == 0 { + folderCallback(nil, nil) + return + } + uri, err := storage.ParseURI(uris[0]) if err != nil { folderCallback(nil, err) @@ -104,6 +109,11 @@ func fileOpenOSOverride(d *FileDialog) bool { return } + if len(uris) == 0 { + folderCallback(nil, nil) + return + } + uri, err := storage.ParseURI(uris[0]) if err != nil { fileCallback(nil, err) @@ -124,6 +134,11 @@ func fileSaveOSOverride(d *FileDialog) bool { return } + if len(uris) == 0 { + callback(nil, nil) + return + } + uri, err := storage.ParseURI(uris[0]) if err != nil { callback(nil, err) From 6531028bb01cc6b7290e84e1a1fe4b15986d6e51 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 13:24:22 +0100 Subject: [PATCH 086/248] Pull new portal with license --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8ed08b4b7f..bc2c6ef44b 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/lucor/goinfo v0.9.0 github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 - github.com/rymdport/portal v0.0.0-20231119112124-889a3dbc2075 + github.com/rymdport/portal v0.0.0-20231119122349-dd7585c58dd5 github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index 6c99a0c0ab..1129d84e79 100644 --- a/go.sum +++ b/go.sum @@ -266,8 +266,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/rymdport/portal v0.0.0-20231119112124-889a3dbc2075 h1:21ZHdpquG8LPmbQK4XKzcog9F6Y2kyskMJ4euID06U8= -github.com/rymdport/portal v0.0.0-20231119112124-889a3dbc2075/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= +github.com/rymdport/portal v0.0.0-20231119122349-dd7585c58dd5 h1:6giNhU8lSefa4cdl7YCRWB2bGm0g7MNbWAC3MxIZpug= +github.com/rymdport/portal v0.0.0-20231119122349-dd7585c58dd5/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= From 4dd8904fe05ec3434c8a1ffed2b60c96761cfe6b Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 20:47:47 +0100 Subject: [PATCH 087/248] Implement more file/folder dialog options --- dialog/file_xdg.go | 16 +++++++++++++--- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index d8317b9c04..75c3769cbe 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -79,7 +79,11 @@ func getFavoriteLocations() (map[string]fyne.ListableURI, error) { func fileOpenOSOverride(d *FileDialog) bool { go func() { folderCallback, folder := d.callback.(func(fyne.ListableURI, error)) - options := &filechooser.OpenOptions{Modal: true, Directory: folder} + options := &filechooser.OpenOptions{ + Modal: true, + Directory: folder, + AcceptLabel: d.confirmText, + } if folder { uris, err := filechooser.OpenFile("", "Open Folder", options) @@ -110,7 +114,7 @@ func fileOpenOSOverride(d *FileDialog) bool { } if len(uris) == 0 { - folderCallback(nil, nil) + fileCallback(nil, nil) return } @@ -128,7 +132,13 @@ func fileOpenOSOverride(d *FileDialog) bool { func fileSaveOSOverride(d *FileDialog) bool { go func() { callback := d.callback.(func(fyne.URIWriteCloser, error)) - uris, err := filechooser.SaveFile("", "Open File", &filechooser.SaveSingleOptions{Modal: true}) + uris, err := filechooser.SaveFile("", "Open File", + &filechooser.SaveSingleOptions{ + Modal: true, + AcceptLabel: d.confirmText, + FileName: d.initialFileName, + }, + ) if err != nil { callback(nil, err) return diff --git a/go.mod b/go.mod index bc2c6ef44b..198ef6cbf7 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/lucor/goinfo v0.9.0 github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 - github.com/rymdport/portal v0.0.0-20231119122349-dd7585c58dd5 + github.com/rymdport/portal v0.0.0-20231119194321-d452ead565fd github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index 1129d84e79..a5ea80265b 100644 --- a/go.sum +++ b/go.sum @@ -266,8 +266,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/rymdport/portal v0.0.0-20231119122349-dd7585c58dd5 h1:6giNhU8lSefa4cdl7YCRWB2bGm0g7MNbWAC3MxIZpug= -github.com/rymdport/portal v0.0.0-20231119122349-dd7585c58dd5/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= +github.com/rymdport/portal v0.0.0-20231119194321-d452ead565fd h1:nHVuLKAtBcunYBBiuclbtYllz+gW9TB3uHR8e1uMoM0= +github.com/rymdport/portal v0.0.0-20231119194321-d452ead565fd/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= From 828eb3028485c5cecffc19c3036dac0b8beeefe3 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 21:01:12 +0100 Subject: [PATCH 088/248] Set up starting location for dialog --- dialog/file_xdg.go | 22 ++++++++++++++-------- go.mod | 2 +- go.sum | 2 ++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 75c3769cbe..1574853825 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -78,13 +78,16 @@ func getFavoriteLocations() (map[string]fyne.ListableURI, error) { func fileOpenOSOverride(d *FileDialog) bool { go func() { - folderCallback, folder := d.callback.(func(fyne.ListableURI, error)) options := &filechooser.OpenOptions{ Modal: true, Directory: folder, AcceptLabel: d.confirmText, } + if d.startingLocation != nil { + options.Location = d.startingLocation.Path() + } + folderCallback, folder := d.callback.(func(fyne.ListableURI, error)) if folder { uris, err := filechooser.OpenFile("", "Open Folder", options) if err != nil { @@ -131,14 +134,17 @@ func fileOpenOSOverride(d *FileDialog) bool { func fileSaveOSOverride(d *FileDialog) bool { go func() { + options := &filechooser.SaveSingleOptions{ + Modal: true, + AcceptLabel: d.confirmText, + FileName: d.initialFileName, + } + if d.startingLocation != nil { + options.Location = d.startingLocation.Path() + } + callback := d.callback.(func(fyne.URIWriteCloser, error)) - uris, err := filechooser.SaveFile("", "Open File", - &filechooser.SaveSingleOptions{ - Modal: true, - AcceptLabel: d.confirmText, - FileName: d.initialFileName, - }, - ) + uris, err := filechooser.SaveFile("", "Open File", options) if err != nil { callback(nil, err) return diff --git a/go.mod b/go.mod index 198ef6cbf7..05365f741d 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/lucor/goinfo v0.9.0 github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 - github.com/rymdport/portal v0.0.0-20231119194321-d452ead565fd + github.com/rymdport/portal v0.0.0-20231119195719-fb11153c815d github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index a5ea80265b..c0b601a249 100644 --- a/go.sum +++ b/go.sum @@ -268,6 +268,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/rymdport/portal v0.0.0-20231119194321-d452ead565fd h1:nHVuLKAtBcunYBBiuclbtYllz+gW9TB3uHR8e1uMoM0= github.com/rymdport/portal v0.0.0-20231119194321-d452ead565fd/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= +github.com/rymdport/portal v0.0.0-20231119195719-fb11153c815d h1:q+VIAL+ZpA2fP/9k6dn+720s4YJGVATDTj35L2CWsIA= +github.com/rymdport/portal v0.0.0-20231119195719-fb11153c815d/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= From 53a7273c34bccd22492df64dc1c302e43b1dfa42 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 21:15:30 +0100 Subject: [PATCH 089/248] Make the code compile again --- dialog/file_xdg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 1574853825..dd16a02866 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -78,6 +78,7 @@ func getFavoriteLocations() (map[string]fyne.ListableURI, error) { func fileOpenOSOverride(d *FileDialog) bool { go func() { + folderCallback, folder := d.callback.(func(fyne.ListableURI, error)) options := &filechooser.OpenOptions{ Modal: true, Directory: folder, @@ -87,7 +88,6 @@ func fileOpenOSOverride(d *FileDialog) bool { options.Location = d.startingLocation.Path() } - folderCallback, folder := d.callback.(func(fyne.ListableURI, error)) if folder { uris, err := filechooser.OpenFile("", "Open Folder", options) if err != nil { From 626ab0ae44030a255beb0c71bd780c6878c7f565 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 19 Nov 2023 21:40:56 +0100 Subject: [PATCH 090/248] Attach the file chooser dialogs to the current window --- dialog/file_xdg.go | 13 ++++++++++--- internal/driver/glfw/window_desktop.go | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index dd16a02866..7c481b483a 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -9,6 +9,7 @@ package dialog import ( "fmt" "os" + "strconv" "fyne.io/fyne/v2" "fyne.io/fyne/v2/storage" @@ -88,8 +89,11 @@ func fileOpenOSOverride(d *FileDialog) bool { options.Location = d.startingLocation.Path() } + xid := d.parent.(interface{ GetX11ID() uint }).GetX11ID() + parentWindow := "x11:" + strconv.FormatUint(uint64(xid), 16) + if folder { - uris, err := filechooser.OpenFile("", "Open Folder", options) + uris, err := filechooser.OpenFile(parentWindow, "Open Folder", options) if err != nil { folderCallback(nil, err) } @@ -109,7 +113,7 @@ func fileOpenOSOverride(d *FileDialog) bool { return } - uris, err := filechooser.OpenFile("", "Open File", options) + uris, err := filechooser.OpenFile(parentWindow, "Open File", options) fileCallback := d.callback.(func(fyne.URIReadCloser, error)) if err != nil { fileCallback(nil, err) @@ -143,8 +147,11 @@ func fileSaveOSOverride(d *FileDialog) bool { options.Location = d.startingLocation.Path() } + xid := d.parent.(interface{ GetX11ID() uint }).GetX11ID() + parentWindow := "x11:" + strconv.FormatUint(uint64(xid), 16) + callback := d.callback.(func(fyne.URIWriteCloser, error)) - uris, err := filechooser.SaveFile("", "Open File", options) + uris, err := filechooser.SaveFile(parentWindow, "Open File", options) if err != nil { callback(nil, err) return diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index 32bf0c0406..08175ed286 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -704,6 +704,10 @@ func (w *window) rescaleOnMain() { w.viewport.SetSize(newWidth, newHeight) } +func (w *window) GetX11ID() uint { + return uint(w.viewport.GetX11Window()) +} + func (w *window) create() { runOnMain(func() { if !build.IsWayland { From 31b1f205484101b8c586b16d59b9b5d1fd2b71a9 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 22:15:20 +0100 Subject: [PATCH 091/248] Only use the new portal implementation with -tags flatpak --- app/app_xdg.go | 21 ++++-- dialog/file_xdg.go | 98 ------------------------ dialog/file_xdg_flatpak.go | 112 ++++++++++++++++++++++++++++ dialog/file_xdg_notflatpak.go | 16 ++++ internal/build/driver_flatpak.go | 7 ++ internal/build/driver_notflatpak.go | 7 ++ 6 files changed, 155 insertions(+), 106 deletions(-) create mode 100644 dialog/file_xdg_flatpak.go create mode 100644 dialog/file_xdg_notflatpak.go create mode 100644 internal/build/driver_flatpak.go create mode 100644 internal/build/driver_notflatpak.go diff --git a/app/app_xdg.go b/app/app_xdg.go index 0f39cbad60..cfbd95b4b5 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -20,6 +20,7 @@ import ( "golang.org/x/sys/execabs" "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/theme" ) @@ -30,10 +31,12 @@ func defaultVariant() fyne.ThemeVariant { } func (a *fyneApp) OpenURL(url *url.URL) error { - if err := openuri.OpenURI("", url.String()); err == nil { - return nil - } else { - fyne.LogError("Opening url in portal failed", err) + if build.IsFlatpak { + err := openuri.OpenURI("", url.String()) + if err != nil { + fyne.LogError("Opening url in portal failed", err) + } + return err } cmd := execabs.Command("xdg-open", url.String()) @@ -89,10 +92,12 @@ func (a *fyneApp) SendNotification(n *fyne.Notification) { return } - if err := a.sendNotificationThroughPortal(conn, n); err == nil { - return // No need to use the fallback path. - } else { - fyne.LogError("Sending notification using portal failed", err) + if build.IsFlatpak { + err := a.sendNotificationThroughPortal(conn, n) + if err != nil { + fyne.LogError("Sending notification using portal failed", err) + } + return } appIcon := a.cachedIconPath() diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 7c481b483a..824aa1bce3 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -9,11 +9,9 @@ package dialog import ( "fmt" "os" - "strconv" "fyne.io/fyne/v2" "fyne.io/fyne/v2/storage" - "github.com/rymdport/portal/filechooser" "golang.org/x/sys/execabs" ) @@ -76,99 +74,3 @@ func getFavoriteLocations() (map[string]fyne.ListableURI, error) { return favoriteLocations, err } - -func fileOpenOSOverride(d *FileDialog) bool { - go func() { - folderCallback, folder := d.callback.(func(fyne.ListableURI, error)) - options := &filechooser.OpenOptions{ - Modal: true, - Directory: folder, - AcceptLabel: d.confirmText, - } - if d.startingLocation != nil { - options.Location = d.startingLocation.Path() - } - - xid := d.parent.(interface{ GetX11ID() uint }).GetX11ID() - parentWindow := "x11:" + strconv.FormatUint(uint64(xid), 16) - - if folder { - uris, err := filechooser.OpenFile(parentWindow, "Open Folder", options) - if err != nil { - folderCallback(nil, err) - } - - if len(uris) == 0 { - folderCallback(nil, nil) - return - } - - uri, err := storage.ParseURI(uris[0]) - if err != nil { - folderCallback(nil, err) - return - } - - folderCallback(storage.ListerForURI(uri)) - return - } - - uris, err := filechooser.OpenFile(parentWindow, "Open File", options) - fileCallback := d.callback.(func(fyne.URIReadCloser, error)) - if err != nil { - fileCallback(nil, err) - return - } - - if len(uris) == 0 { - fileCallback(nil, nil) - return - } - - uri, err := storage.ParseURI(uris[0]) - if err != nil { - fileCallback(nil, err) - return - } - - fileCallback(storage.Reader(uri)) - }() - return true -} - -func fileSaveOSOverride(d *FileDialog) bool { - go func() { - options := &filechooser.SaveSingleOptions{ - Modal: true, - AcceptLabel: d.confirmText, - FileName: d.initialFileName, - } - if d.startingLocation != nil { - options.Location = d.startingLocation.Path() - } - - xid := d.parent.(interface{ GetX11ID() uint }).GetX11ID() - parentWindow := "x11:" + strconv.FormatUint(uint64(xid), 16) - - callback := d.callback.(func(fyne.URIWriteCloser, error)) - uris, err := filechooser.SaveFile(parentWindow, "Open File", options) - if err != nil { - callback(nil, err) - return - } - - if len(uris) == 0 { - callback(nil, nil) - return - } - - uri, err := storage.ParseURI(uris[0]) - if err != nil { - callback(nil, err) - return - } - - callback(storage.Writer(uri)) - }() - return true -} diff --git a/dialog/file_xdg_flatpak.go b/dialog/file_xdg_flatpak.go new file mode 100644 index 0000000000..aacfdb3b58 --- /dev/null +++ b/dialog/file_xdg_flatpak.go @@ -0,0 +1,112 @@ +//go:build flatpak && (linux || openbsd || freebsd || netbsd) && !android && !wasm && !js +// +build flatpak +// +build linux openbsd freebsd netbsd +// +build !android +// +build !wasm +// +build !js + +package dialog + +import ( + "strconv" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/storage" + "github.com/rymdport/portal/filechooser" +) + +func fileOpenOSOverride(d *FileDialog) bool { + go func() { + folderCallback, folder := d.callback.(func(fyne.ListableURI, error)) + options := &filechooser.OpenOptions{ + Modal: true, + Directory: folder, + AcceptLabel: d.confirmText, + } + if d.startingLocation != nil { + options.Location = d.startingLocation.Path() + } + + xid := d.parent.(interface{ GetX11ID() uint }).GetX11ID() + parentWindow := "x11:" + strconv.FormatUint(uint64(xid), 16) + + if folder { + uris, err := filechooser.OpenFile(parentWindow, "Open Folder", options) + if err != nil { + folderCallback(nil, err) + } + + if len(uris) == 0 { + folderCallback(nil, nil) + return + } + + uri, err := storage.ParseURI(uris[0]) + if err != nil { + folderCallback(nil, err) + return + } + + folderCallback(storage.ListerForURI(uri)) + return + } + + uris, err := filechooser.OpenFile(parentWindow, "Open File", options) + fileCallback := d.callback.(func(fyne.URIReadCloser, error)) + if err != nil { + fileCallback(nil, err) + return + } + + if len(uris) == 0 { + fileCallback(nil, nil) + return + } + + uri, err := storage.ParseURI(uris[0]) + if err != nil { + fileCallback(nil, err) + return + } + + fileCallback(storage.Reader(uri)) + }() + return true +} + +func fileSaveOSOverride(d *FileDialog) bool { + go func() { + options := &filechooser.SaveSingleOptions{ + Modal: true, + AcceptLabel: d.confirmText, + FileName: d.initialFileName, + } + if d.startingLocation != nil { + options.Location = d.startingLocation.Path() + } + + xid := d.parent.(interface{ GetX11ID() uint }).GetX11ID() + parentWindow := "x11:" + strconv.FormatUint(uint64(xid), 16) + + callback := d.callback.(func(fyne.URIWriteCloser, error)) + uris, err := filechooser.SaveFile(parentWindow, "Open File", options) + if err != nil { + callback(nil, err) + return + } + + if len(uris) == 0 { + callback(nil, nil) + return + } + + uri, err := storage.ParseURI(uris[0]) + if err != nil { + callback(nil, err) + return + } + + callback(storage.Writer(uri)) + }() + return true +} diff --git a/dialog/file_xdg_notflatpak.go b/dialog/file_xdg_notflatpak.go new file mode 100644 index 0000000000..fc42f6215b --- /dev/null +++ b/dialog/file_xdg_notflatpak.go @@ -0,0 +1,16 @@ +//go:build !flatpak && (linux || openbsd || freebsd || netbsd) && !android && !wasm && !js +// +build !flatpak +// +build linux openbsd freebsd netbsd +// +build !android +// +build !wasm +// +build !js + +package dialog + +func fileOpenOSOverride(d *FileDialog) bool { + return false +} + +func fileSaveOSOverride(d *FileDialog) bool { + return false +} diff --git a/internal/build/driver_flatpak.go b/internal/build/driver_flatpak.go new file mode 100644 index 0000000000..96f3315a4e --- /dev/null +++ b/internal/build/driver_flatpak.go @@ -0,0 +1,7 @@ +//go:build flatpak +// +build flatpak + +package build + +// IsFlatpak is true if the binary is compiled for a Flatpak package. +const IsFlatpak = true diff --git a/internal/build/driver_notflatpak.go b/internal/build/driver_notflatpak.go new file mode 100644 index 0000000000..d2f79cdc46 --- /dev/null +++ b/internal/build/driver_notflatpak.go @@ -0,0 +1,7 @@ +//go:build !flatpak +// +build !flatpak + +package build + +// IsFlatpak is true if the binary is compiled for a Flatpak package. +const IsFlatpak = false From b385ca224edaf398e42e00c644bc33bdff516d72 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 22:54:25 +0100 Subject: [PATCH 092/248] Make sure that we can compile outside of X11 --- dialog/file_xdg_flatpak.go | 16 ++++++++-------- internal/driver/glfw/window_desktop.go | 4 ---- internal/driver/glfw/window_notxdg.go | 5 +++++ internal/driver/glfw/window_wayland.go | 10 ++++++++++ internal/driver/glfw/window_x11.go | 13 +++++++++++++ 5 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 internal/driver/glfw/window_wayland.go create mode 100644 internal/driver/glfw/window_x11.go diff --git a/dialog/file_xdg_flatpak.go b/dialog/file_xdg_flatpak.go index aacfdb3b58..758a4fea9b 100644 --- a/dialog/file_xdg_flatpak.go +++ b/dialog/file_xdg_flatpak.go @@ -8,7 +8,7 @@ package dialog import ( - "strconv" + "fmt" "fyne.io/fyne/v2" "fyne.io/fyne/v2/storage" @@ -27,11 +27,11 @@ func fileOpenOSOverride(d *FileDialog) bool { options.Location = d.startingLocation.Path() } - xid := d.parent.(interface{ GetX11ID() uint }).GetX11ID() - parentWindow := "x11:" + strconv.FormatUint(uint64(xid), 16) + parentWindowHandle := d.parent.(interface{ GetWindowHandle() string }).GetWindowHandle() + fmt.Println(parentWindowHandle) if folder { - uris, err := filechooser.OpenFile(parentWindow, "Open Folder", options) + uris, err := filechooser.OpenFile(parentWindowHandle, "Open Folder", options) if err != nil { folderCallback(nil, err) } @@ -51,7 +51,7 @@ func fileOpenOSOverride(d *FileDialog) bool { return } - uris, err := filechooser.OpenFile(parentWindow, "Open File", options) + uris, err := filechooser.OpenFile(parentWindowHandle, "Open File", options) fileCallback := d.callback.(func(fyne.URIReadCloser, error)) if err != nil { fileCallback(nil, err) @@ -85,11 +85,11 @@ func fileSaveOSOverride(d *FileDialog) bool { options.Location = d.startingLocation.Path() } - xid := d.parent.(interface{ GetX11ID() uint }).GetX11ID() - parentWindow := "x11:" + strconv.FormatUint(uint64(xid), 16) + parentWindowHandle := d.parent.(interface{ GetWindowHandle() string }).GetWindowHandle() + fmt.Println(parentWindowHandle) callback := d.callback.(func(fyne.URIWriteCloser, error)) - uris, err := filechooser.SaveFile(parentWindow, "Open File", options) + uris, err := filechooser.SaveFile(parentWindowHandle, "Open File", options) if err != nil { callback(nil, err) return diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index 08175ed286..32bf0c0406 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -704,10 +704,6 @@ func (w *window) rescaleOnMain() { w.viewport.SetSize(newWidth, newHeight) } -func (w *window) GetX11ID() uint { - return uint(w.viewport.GetX11Window()) -} - func (w *window) create() { runOnMain(func() { if !build.IsWayland { diff --git a/internal/driver/glfw/window_notxdg.go b/internal/driver/glfw/window_notxdg.go index 6c693bf2ef..bc16385e5d 100644 --- a/internal/driver/glfw/window_notxdg.go +++ b/internal/driver/glfw/window_notxdg.go @@ -22,3 +22,8 @@ func (w *window) platformResize(canvasSize fyne.Size) { }) } } + +// GetWindowHandle returns the window handle. Only implemented for X11 and Wayland currently. +func (w *window) GetWindowHandle() string { + return "" +} diff --git a/internal/driver/glfw/window_wayland.go b/internal/driver/glfw/window_wayland.go new file mode 100644 index 0000000000..648997e615 --- /dev/null +++ b/internal/driver/glfw/window_wayland.go @@ -0,0 +1,10 @@ +//go:build wayland && (linux || freebsd || openbsd || netbsd) +// +build wayland +// +build linux freebsd openbsd netbsd + +package glfw + +// GetWindowHandle returns the window handle. Only implemented for X11 and Wayland currently. +func (w *window) GetWindowHandle() string { + return "" // TODO: Find a way to get the Wayland handle for xdg_foreign protocol. Return "wayland:{id}". +} diff --git a/internal/driver/glfw/window_x11.go b/internal/driver/glfw/window_x11.go new file mode 100644 index 0000000000..9fa467ae96 --- /dev/null +++ b/internal/driver/glfw/window_x11.go @@ -0,0 +1,13 @@ +//go:build !wayland && (linux || freebsd || openbsd || netbsd) +// +build !wayland +// +build linux freebsd openbsd netbsd + +package glfw + +import "strconv" + +// GetWindowHandle returns the window handle. Only implemented for X11 and Wayland currently. +func (w *window) GetWindowHandle() string { + xid := uint(w.viewport.GetX11Window()) + return "x11:" + strconv.FormatUint(uint64(xid), 16) +} From b8aebdd29fe330416e01903c397940e92b9f38ec Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 22:57:00 +0100 Subject: [PATCH 093/248] Remove leftover file --- dialog/file_notunix.go | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 dialog/file_notunix.go diff --git a/dialog/file_notunix.go b/dialog/file_notunix.go deleted file mode 100644 index f5a6637efe..0000000000 --- a/dialog/file_notunix.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build (!linux && !openbsd && !freebsd && !netbsd) || android || wasm || js - -package dialog - -func fileOpenOSOverride(*FileDialog) bool { - return false -} - -func fileSaveOSOverride(*FileDialog) bool { - return false -} From d8433d6d6c2e0c92031935de261353bb24f54645 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 22:58:20 +0100 Subject: [PATCH 094/248] Fix an incorrect comment --- internal/driver/glfw/window_notxdg.go | 2 +- internal/driver/glfw/window_wayland.go | 2 +- internal/driver/glfw/window_x11.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/driver/glfw/window_notxdg.go b/internal/driver/glfw/window_notxdg.go index bc16385e5d..34e34a879f 100644 --- a/internal/driver/glfw/window_notxdg.go +++ b/internal/driver/glfw/window_notxdg.go @@ -23,7 +23,7 @@ func (w *window) platformResize(canvasSize fyne.Size) { } } -// GetWindowHandle returns the window handle. Only implemented for X11 and Wayland currently. +// GetWindowHandle returns the window handle. Only implemented for X11 currently. func (w *window) GetWindowHandle() string { return "" } diff --git a/internal/driver/glfw/window_wayland.go b/internal/driver/glfw/window_wayland.go index 648997e615..84909d9310 100644 --- a/internal/driver/glfw/window_wayland.go +++ b/internal/driver/glfw/window_wayland.go @@ -4,7 +4,7 @@ package glfw -// GetWindowHandle returns the window handle. Only implemented for X11 and Wayland currently. +// GetWindowHandle returns the window handle. Only implemented for X11 currently. func (w *window) GetWindowHandle() string { return "" // TODO: Find a way to get the Wayland handle for xdg_foreign protocol. Return "wayland:{id}". } diff --git a/internal/driver/glfw/window_x11.go b/internal/driver/glfw/window_x11.go index 9fa467ae96..af6381b7b4 100644 --- a/internal/driver/glfw/window_x11.go +++ b/internal/driver/glfw/window_x11.go @@ -6,7 +6,7 @@ package glfw import "strconv" -// GetWindowHandle returns the window handle. Only implemented for X11 and Wayland currently. +// GetWindowHandle returns the window handle. Only implemented for X11 currently. func (w *window) GetWindowHandle() string { xid := uint(w.viewport.GetX11Window()) return "x11:" + strconv.FormatUint(uint64(xid), 16) From 73b59535a1de76210cb68e744b5b4ad4b1c23db8 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 23:14:43 +0100 Subject: [PATCH 095/248] Try to get the buildtags working --- dialog/file_xdg_flatpak.go | 8 ++------ dialog/file_xdg_notflatpak.go | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/dialog/file_xdg_flatpak.go b/dialog/file_xdg_flatpak.go index 758a4fea9b..c64321175d 100644 --- a/dialog/file_xdg_flatpak.go +++ b/dialog/file_xdg_flatpak.go @@ -1,9 +1,5 @@ -//go:build flatpak && (linux || openbsd || freebsd || netbsd) && !android && !wasm && !js -// +build flatpak -// +build linux openbsd freebsd netbsd -// +build !android -// +build !wasm -// +build !js +//go:build flatpak && !windows && !android && !ios && !wasm && !js +// +build flatpak,!windows,!android,!ios,!wasm,!js package dialog diff --git a/dialog/file_xdg_notflatpak.go b/dialog/file_xdg_notflatpak.go index fc42f6215b..5531a6476a 100644 --- a/dialog/file_xdg_notflatpak.go +++ b/dialog/file_xdg_notflatpak.go @@ -1,9 +1,5 @@ -//go:build !flatpak && (linux || openbsd || freebsd || netbsd) && !android && !wasm && !js -// +build !flatpak -// +build linux openbsd freebsd netbsd -// +build !android -// +build !wasm -// +build !js +//go:build !flatpak && !windows && !android && !ios && !wasm && !js +// +build !flatpak,!windows,!android,!ios,!wasm,!js package dialog From a34f95bb87bfea908caf9670450a1afbd330627f Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 23:29:57 +0100 Subject: [PATCH 096/248] Try to fix weird web compile error --- internal/driver/glfw/window_x11.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/driver/glfw/window_x11.go b/internal/driver/glfw/window_x11.go index af6381b7b4..99efc4b4de 100644 --- a/internal/driver/glfw/window_x11.go +++ b/internal/driver/glfw/window_x11.go @@ -1,6 +1,9 @@ -//go:build !wayland && (linux || freebsd || openbsd || netbsd) +//go:build !wayland && (linux || freebsd || openbsd || netbsd) && !js && !wasm && !test_web_driver // +build !wayland // +build linux freebsd openbsd netbsd +// +build !js +// +build !wasm +// +build !test_web_driver package glfw From 212042dfdfce3d7d930f1da7a54babe65984c3c3 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 23 Nov 2023 21:28:46 +0100 Subject: [PATCH 097/248] Minor improvements to portal code --- dialog/file_xdg_flatpak.go | 1 - go.mod | 2 +- go.sum | 6 ++---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/dialog/file_xdg_flatpak.go b/dialog/file_xdg_flatpak.go index c64321175d..c69c9fdf5b 100644 --- a/dialog/file_xdg_flatpak.go +++ b/dialog/file_xdg_flatpak.go @@ -24,7 +24,6 @@ func fileOpenOSOverride(d *FileDialog) bool { } parentWindowHandle := d.parent.(interface{ GetWindowHandle() string }).GetWindowHandle() - fmt.Println(parentWindowHandle) if folder { uris, err := filechooser.OpenFile(parentWindowHandle, "Open Folder", options) diff --git a/go.mod b/go.mod index 05365f741d..dea38c8b9e 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/lucor/goinfo v0.9.0 github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 - github.com/rymdport/portal v0.0.0-20231119195719-fb11153c815d + github.com/rymdport/portal v0.0.0-20231123202536-da45518a87bb github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index c0b601a249..b227b22fea 100644 --- a/go.sum +++ b/go.sum @@ -266,10 +266,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/rymdport/portal v0.0.0-20231119194321-d452ead565fd h1:nHVuLKAtBcunYBBiuclbtYllz+gW9TB3uHR8e1uMoM0= -github.com/rymdport/portal v0.0.0-20231119194321-d452ead565fd/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= -github.com/rymdport/portal v0.0.0-20231119195719-fb11153c815d h1:q+VIAL+ZpA2fP/9k6dn+720s4YJGVATDTj35L2CWsIA= -github.com/rymdport/portal v0.0.0-20231119195719-fb11153c815d/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= +github.com/rymdport/portal v0.0.0-20231123202536-da45518a87bb h1:ejEomhJX7G4p8dFImv2zcQd2Oa0IpWIeB/FUZRnpQKg= +github.com/rymdport/portal v0.0.0-20231123202536-da45518a87bb/go.mod h1:RYYAnv4sssTQ7ceErKl7UD8auER/0yFV7CgmfS/uAD8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= From 089dbe1ffd92aa8a66ed00d44450dc9c0f8d0f5c Mon Sep 17 00:00:00 2001 From: Jacob Date: Fri, 1 Dec 2023 12:21:23 +0100 Subject: [PATCH 098/248] Move hints check into internal/build --- app/app.go | 3 ++- container/tabs.go | 3 ++- internal/build/hints_disabled.go | 8 ++++++++ internal/build/hints_enabled.go | 7 +++++++ internal/hints_disabled.go | 4 ---- internal/hints_enabled.go | 3 --- 6 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 internal/build/hints_disabled.go create mode 100644 internal/build/hints_enabled.go diff --git a/app/app.go b/app/app.go index 545b94b492..8115b0bf5c 100644 --- a/app/app.go +++ b/app/app.go @@ -11,6 +11,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/internal" "fyne.io/fyne/v2/internal/app" + "fyne.io/fyne/v2/internal/build" intRepo "fyne.io/fyne/v2/internal/repository" "fyne.io/fyne/v2/storage/repository" ) @@ -110,7 +111,7 @@ func (a *fyneApp) newDefaultPreferences() *preferences { // New returns a new application instance with the default driver and no unique ID (unless specified in FyneApp.toml) func New() fyne.App { - if meta.ID == "" { + if build.HasHints && meta.ID == "" { internal.LogHint("Applications should be created with a unique ID using app.NewWithID()") } return NewWithID(meta.ID) diff --git a/container/tabs.go b/container/tabs.go index ac3d65c3dd..4d60d82c56 100644 --- a/container/tabs.go +++ b/container/tabs.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/internal" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -209,7 +210,7 @@ func selectItem(t baseTabs, item *TabItem) { } func setItems(t baseTabs, items []*TabItem) { - if internal.HintsEnabled && mismatchedTabItems(items) { + if build.HasHints && mismatchedTabItems(items) { internal.LogHint("Tab items should all have the same type of content (text, icons or both)") } t.setItems(items) diff --git a/internal/build/hints_disabled.go b/internal/build/hints_disabled.go new file mode 100644 index 0000000000..42274ae37f --- /dev/null +++ b/internal/build/hints_disabled.go @@ -0,0 +1,8 @@ +//go:build !hints +// +build !hints + +package build + +// HasHints is false to indicate that hints are not currently switched on. +// To enable please rebuild with "-tags hints" parameters. +const HasHints = false diff --git a/internal/build/hints_enabled.go b/internal/build/hints_enabled.go new file mode 100644 index 0000000000..041dd985d7 --- /dev/null +++ b/internal/build/hints_enabled.go @@ -0,0 +1,7 @@ +//go:build hints +// +build hints + +package build + +// HasHints is true to indicate that hints are currently switched on. +const HasHints = true diff --git a/internal/hints_disabled.go b/internal/hints_disabled.go index e00a643ba4..b7b0432bb7 100644 --- a/internal/hints_disabled.go +++ b/internal/hints_disabled.go @@ -3,10 +3,6 @@ package internal -// HintsEnabled is false to indicate that hints are not currently switched on. -// To enable please rebuild with "-tags hints" parameters. -const HintsEnabled = false - // LogHint reports a developer hint that should be followed to improve their app. // This does nothing unless the "hints" build flag is used. func LogHint(reason string) { diff --git a/internal/hints_enabled.go b/internal/hints_enabled.go index 9b34412c0b..5f1038ed8f 100644 --- a/internal/hints_enabled.go +++ b/internal/hints_enabled.go @@ -8,9 +8,6 @@ import ( "runtime" ) -// HintsEnabled is true to indicate that hints are currently switched on. -const HintsEnabled = true - // LogHint reports a developer hint that should be followed to improve their app. func LogHint(reason string) { log.Println("Fyne hint: ", reason) From 2b8bec5d1ef723f7956ef78a292a16a2ca2a2a8e Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 1 Dec 2023 16:39:25 +0000 Subject: [PATCH 099/248] Support setting the title of InnerWindow No since: 2.5 needed as this is a new type so the parent has that info --- container/innerwindow.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/container/innerwindow.go b/container/innerwindow.go index c0a76d6064..16e332a0d0 100644 --- a/container/innerwindow.go +++ b/container/innerwindow.go @@ -88,6 +88,11 @@ func (w *InnerWindow) CreateRenderer() fyne.WidgetRenderer { win: w, bar: bar, bg: bg, corner: corner, contentBG: contentBG} } +func (w *InnerWindow) SetTitle(title string) { + w.title = title + w.Refresh() +} + var _ fyne.WidgetRenderer = (*innerWindowRenderer)(nil) type innerWindowRenderer struct { @@ -145,6 +150,8 @@ func (i *innerWindowRenderer) Refresh() { i.contentBG.Refresh() i.bar.Refresh() + title := i.bar.Objects[0].(*draggableLabel) + title.SetText(i.win.title) i.ShadowingRenderer.RefreshShadow() } From bf7f59cb8a50c154f1e11ad5a492003652eebb62 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 1 Dec 2023 16:41:02 +0000 Subject: [PATCH 100/248] Also don't make it so windows can never shrink That was misguided... I think an artefact of bad MultiWindow code that was in earlier --- container/innerwindow.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/container/innerwindow.go b/container/innerwindow.go index 16e332a0d0..ee522aa08b 100644 --- a/container/innerwindow.go +++ b/container/innerwindow.go @@ -97,7 +97,6 @@ var _ fyne.WidgetRenderer = (*innerWindowRenderer)(nil) type innerWindowRenderer struct { *intWidget.ShadowingRenderer - min fyne.Size win *InnerWindow bar *fyne.Container @@ -135,9 +134,6 @@ func (i *innerWindowRenderer) MinSize() fyne.Size { contentMin := i.win.content.MinSize() barMin := i.bar.MinSize() - // only allow windows to grow, as per normal windows - contentMin = contentMin.Max(i.min) - i.min = contentMin innerWidth := fyne.Max(barMin.Width, contentMin.Width) return fyne.NewSize(innerWidth+pad*2, contentMin.Height+pad+barMin.Height).Add(fyne.NewSquareSize(pad)) From 3c2ec306fab633b7c64666387022a1e3f7d2490a Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 1 Dec 2023 16:48:24 +0000 Subject: [PATCH 101/248] Add setTitle test --- container/innerwindow_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/container/innerwindow_test.go b/container/innerwindow_test.go index 7a0e4936ef..51e87e6a5d 100644 --- a/container/innerwindow_test.go +++ b/container/innerwindow_test.go @@ -4,6 +4,7 @@ import ( "testing" "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -48,3 +49,13 @@ func TestInnerWindow_MinSize(t *testing.T) { w2 := NewInnerWindow("Much longer title that will truncate", widget.NewLabel("Content")) assert.Equal(t, winMin, w2.MinSize()) } + +func TestInnerWindow_SetTitle(t *testing.T) { + w := NewInnerWindow("Title1", widget.NewLabel("Content")) + r := cache.Renderer(w).(*innerWindowRenderer) + title := r.bar.Objects[0].(*draggableLabel) + assert.Equal(t, "Title1", title.Text) + + w.SetTitle("Title2") + assert.Equal(t, "Title2", title.Text) +} From 56127d6b2044ef5ad92b3a4ef16399cea42deef3 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Mon, 4 Dec 2023 10:37:01 +0100 Subject: [PATCH 102/248] Remove a useless addition --- app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app.go b/app/app.go index 8115b0bf5c..57715e72eb 100644 --- a/app/app.go +++ b/app/app.go @@ -111,7 +111,7 @@ func (a *fyneApp) newDefaultPreferences() *preferences { // New returns a new application instance with the default driver and no unique ID (unless specified in FyneApp.toml) func New() fyne.App { - if build.HasHints && meta.ID == "" { + if meta.ID == "" { internal.LogHint("Applications should be created with a unique ID using app.NewWithID()") } return NewWithID(meta.ID) From 4916310cee405d57847f4fcc1a4c9737d037d1c8 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Mon, 4 Dec 2023 10:41:01 +0100 Subject: [PATCH 103/248] I forgot that micro doesn't remove imports automatically --- app/app.go | 1 - 1 file changed, 1 deletion(-) diff --git a/app/app.go b/app/app.go index 57715e72eb..545b94b492 100644 --- a/app/app.go +++ b/app/app.go @@ -11,7 +11,6 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/internal" "fyne.io/fyne/v2/internal/app" - "fyne.io/fyne/v2/internal/build" intRepo "fyne.io/fyne/v2/internal/repository" "fyne.io/fyne/v2/storage/repository" ) From b005cdf24e2dc4939e15c627715c312b7c9ca632 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 5 Dec 2023 01:52:18 +0100 Subject: [PATCH 104/248] driver/glfw: Avoid calling slow functions twice in a row This avoids various cases where we were calling "slow" (C-calls for glfw or locking mutexes) functions multiple times in a row. Lets save the value and use it instead. --- internal/driver/glfw/canvas.go | 3 ++- internal/driver/glfw/window.go | 33 +++++++++++++++----------- internal/driver/glfw/window_desktop.go | 2 +- internal/driver/mobile/window.go | 3 ++- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/internal/driver/glfw/canvas.go b/internal/driver/glfw/canvas.go index 2cb47f9755..ec9c1ae655 100644 --- a/internal/driver/glfw/canvas.go +++ b/internal/driver/glfw/canvas.go @@ -96,8 +96,9 @@ func (c *glCanvas) Padded() bool { func (c *glCanvas) PixelCoordinateForPosition(pos fyne.Position) (int, int) { c.RLock() texScale := c.texScale + scale := c.scale c.RUnlock() - multiple := c.Scale() * texScale + multiple := scale * texScale scaleInt := func(x float32) int { return int(math.Round(float64(x * multiple))) } diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index c0f1dd21d3..767b066c5e 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -119,8 +119,9 @@ func (w *window) calculatedScale() float32 { } func (w *window) detectTextureScale() float32 { - winWidth, _ := w.view().GetSize() - texWidth, _ := w.view().GetFramebufferSize() + view := w.view() + winWidth, _ := view.GetSize() + texWidth, _ := view.GetFramebufferSize() return float32(texWidth) / float32(winWidth) } @@ -145,15 +146,16 @@ func (w *window) doShow() { w.viewLock.Lock() w.visible = true w.viewLock.Unlock() - w.view().SetTitle(w.title) + view := w.view() + view.SetTitle(w.title) if w.centered { w.doCenterOnScreen() // lastly center if that was requested } - w.view().Show() + view.Show() // save coordinates - w.xpos, w.ypos = w.view().GetPos() + w.xpos, w.ypos = view.GetPos() if w.fullScreen { // this does not work if called before viewport.Show() go func() { @@ -164,8 +166,8 @@ func (w *window) doShow() { }) // show top canvas element - if w.canvas.Content() != nil { - w.canvas.Content().Show() + if content := w.canvas.Content(); content != nil { + content.Show() runOnDraw(w, func() { w.driver.repaintWindow(w) @@ -188,8 +190,8 @@ func (w *window) Hide() { v.Hide() // hide top canvas element - if w.canvas.Content() != nil { - w.canvas.Content().Hide() + if content := w.canvas.Content(); content != nil { + content.Hide() } }) } @@ -210,8 +212,10 @@ func (w *window) Close() { w.closing = true w.viewLock.Unlock() w.viewport.SetShouldClose(true) + + painter := w.canvas.Painter() cache.RangeTexturesFor(w.canvas, func(obj fyne.CanvasObject) { - w.canvas.Painter().Free(obj) + painter.Free(obj) }) }) @@ -968,12 +972,13 @@ func (w *window) doShowAgain() { runOnMain(func() { // show top canvas element - if w.canvas.Content() != nil { - w.canvas.Content().Show() + if content := w.canvas.Content(); content != nil { + content.Show() } - w.view().SetPos(w.xpos, w.ypos) - w.view().Show() + view := w.view() + view.SetPos(w.xpos, w.ypos) + view.Show() w.viewLock.Lock() w.visible = true w.viewLock.Unlock() diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index 32bf0c0406..5ee94ccdde 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -278,7 +278,7 @@ func (w *window) getMonitorForWindow() *glfw.Monitor { if x > xOff || y > yOff { continue } - if x+monitor.GetVideoMode().Width <= xOff || y+monitor.GetVideoMode().Height <= yOff { + if videoMode := monitor.GetVideoMode(); x+videoMode.Width <= xOff || y+videoMode.Height <= yOff { continue } diff --git a/internal/driver/mobile/window.go b/internal/driver/mobile/window.go index 7d3128f251..4227f97374 100644 --- a/internal/driver/mobile/window.go +++ b/internal/driver/mobile/window.go @@ -161,8 +161,9 @@ func (w *window) Close() { d.windows = append(d.windows[:pos], d.windows[pos+1:]...) } + painter := w.canvas.Painter() cache.RangeTexturesFor(w.canvas, func(obj fyne.CanvasObject) { - w.canvas.Painter().Free(obj) + painter.Free(obj) }) w.canvas.WalkTrees(nil, func(node *common.RenderCacheNode, _ fyne.Position) { From 9cc314fbb31934fe81a251f9a02542dbe0572f9b Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 5 Dec 2023 01:56:03 +0100 Subject: [PATCH 105/248] Pass function directly instead --- internal/driver/glfw/window.go | 5 +---- internal/driver/mobile/window.go | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 767b066c5e..eadcb6e6ad 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -213,10 +213,7 @@ func (w *window) Close() { w.viewLock.Unlock() w.viewport.SetShouldClose(true) - painter := w.canvas.Painter() - cache.RangeTexturesFor(w.canvas, func(obj fyne.CanvasObject) { - painter.Free(obj) - }) + cache.RangeTexturesFor(w.canvas, w.canvas.Painter().Free) }) w.canvas.WalkTrees(nil, func(node *common.RenderCacheNode, _ fyne.Position) { diff --git a/internal/driver/mobile/window.go b/internal/driver/mobile/window.go index 4227f97374..c3ad9d03b2 100644 --- a/internal/driver/mobile/window.go +++ b/internal/driver/mobile/window.go @@ -161,10 +161,7 @@ func (w *window) Close() { d.windows = append(d.windows[:pos], d.windows[pos+1:]...) } - painter := w.canvas.Painter() - cache.RangeTexturesFor(w.canvas, func(obj fyne.CanvasObject) { - painter.Free(obj) - }) + cache.RangeTexturesFor(w.canvas, w.canvas.Painter().Free) w.canvas.WalkTrees(nil, func(node *common.RenderCacheNode, _ fyne.Position) { if wid, ok := node.Obj().(fyne.Widget); ok { From bf0e3b0b79494f1959d679e4ee05fd0b792a15e4 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 5 Dec 2023 02:00:40 +0100 Subject: [PATCH 106/248] driver/common: Hoist nil check out of loop and pass function directly --- internal/driver/common/canvas.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/internal/driver/common/canvas.go b/internal/driver/common/canvas.go index ef22c29ee6..c70c0f13ff 100644 --- a/internal/driver/common/canvas.go +++ b/internal/driver/common/canvas.go @@ -283,11 +283,9 @@ func (c *Canvas) FreeDirtyTextures() (freed uint64) { } } - cache.RangeExpiredTexturesFor(c.impl, func(obj fyne.CanvasObject) { - if c.painter != nil { - c.painter.Free(obj) - } - }) + if c.painter != nil { + cache.RangeExpiredTexturesFor(c.impl, c.painter.Free) + } return } From 2a5d472730e59e9a0d2d8bcec6dae33dee4dd95a Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 5 Dec 2023 22:53:39 +0100 Subject: [PATCH 107/248] internal: Last bit of code cleanup and improvements Refactors some code to be more readable, makes sure that we run MinSize() less often for the scroller and caches some sizes. I think all of the internal/ packages should be up to our usual standards now. --- internal/overlay_stack.go | 8 ++++---- internal/svg/svg.go | 4 ++-- internal/widget/scroller.go | 33 ++++++++++++++++++--------------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/internal/overlay_stack.go b/internal/overlay_stack.go index ade53791c4..099ec27e6a 100644 --- a/internal/overlay_stack.go +++ b/internal/overlay_stack.go @@ -115,9 +115,9 @@ func (s *OverlayStack) TopFocusManager() *app.FocusManager { } func (s *OverlayStack) topFocusManager() *app.FocusManager { - var fm *app.FocusManager - if len(s.focusManagers) > 0 { - fm = s.focusManagers[len(s.focusManagers)-1] + if len(s.focusManagers) == 0 { + return nil } - return fm + + return s.focusManagers[len(s.focusManagers)-1] } diff --git a/internal/svg/svg.go b/internal/svg/svg.go index 131f5faac0..c89be41d8b 100644 --- a/internal/svg/svg.go +++ b/internal/svg/svg.go @@ -95,12 +95,12 @@ func (d *Decoder) Draw(width, height int) (*image.NRGBA, error) { } func IsFileSVG(path string) bool { - return strings.ToLower(filepath.Ext(path)) == ".svg" + return strings.EqualFold(filepath.Ext(path), ".svg") } // IsResourceSVG checks if the resource is an SVG or not. func IsResourceSVG(res fyne.Resource) bool { - if strings.ToLower(filepath.Ext(res.Name())) == ".svg" { + if IsFileSVG(res.Name()) { return true } diff --git a/internal/widget/scroller.go b/internal/widget/scroller.go index e1e69ea54a..63889d3126 100644 --- a/internal/widget/scroller.go +++ b/internal/widget/scroller.go @@ -159,12 +159,11 @@ func (r *scrollBarAreaRenderer) Refresh() { } func (r *scrollBarAreaRenderer) barSizeAndOffset(contentOffset, contentLength, scrollLength float32) (length, width, lengthOffset, widthOffset float32) { + scrollBarSize := theme.ScrollBarSize() if scrollLength < contentLength { portion := scrollLength / contentLength length = float32(int(scrollLength)) * portion - if length < theme.ScrollBarSize() { - length = theme.ScrollBarSize() - } + length = fyne.Max(length, scrollBarSize) } else { length = scrollLength } @@ -172,10 +171,10 @@ func (r *scrollBarAreaRenderer) barSizeAndOffset(contentOffset, contentLength, s lengthOffset = (scrollLength - length) * (contentOffset / (contentLength - scrollLength)) } if r.area.isLarge { - width = theme.ScrollBarSize() + width = scrollBarSize } else { widthOffset = theme.ScrollBarSmallSize() - width = theme.ScrollBarSmallSize() + width = widthOffset } return } @@ -287,13 +286,14 @@ func (r *scrollContainerRenderer) Refresh() { // push updated content object to baseRenderer r.BaseRenderer.Objects()[0] = r.scroll.Content } - if r.oldMinSize == r.scroll.Content.MinSize() && r.oldMinSize == r.scroll.Content.Size() && + newMin := r.scroll.Content.MinSize() + if r.oldMinSize == newMin && r.oldMinSize == r.scroll.Content.Size() && (r.scroll.Size().Width <= r.oldMinSize.Width && r.scroll.Size().Height <= r.oldMinSize.Height) { r.layoutBars(r.scroll.Size()) return } - r.oldMinSize = r.scroll.Content.MinSize() + r.oldMinSize = newMin r.Layout(r.scroll.Size()) } @@ -463,7 +463,9 @@ func (s *Scroll) Scrolled(ev *fyne.ScrollEvent) { } func (s *Scroll) scrollBy(dx, dy float32) { - if s.Size().Width < s.Content.MinSize().Width && s.Size().Height >= s.Content.MinSize().Height && dx == 0 { + min := s.Content.MinSize() + size := s.Size() + if size.Width < min.Width && size.Height >= min.Height && dx == 0 { dx, dy = dy, dx } if s.updateOffset(dx, dy) { @@ -472,7 +474,10 @@ func (s *Scroll) scrollBy(dx, dy float32) { } func (s *Scroll) updateOffset(deltaX, deltaY float32) bool { - if s.Content.Size().Width <= s.Size().Width && s.Content.Size().Height <= s.Size().Height { + min := s.Content.MinSize() + contentSize := s.Content.Size() + size := s.Size() + if contentSize.Width <= size.Width && contentSize.Height <= size.Height { if s.Offset.X != 0 || s.Offset.Y != 0 { s.Offset.X = 0 s.Offset.Y = 0 @@ -482,8 +487,8 @@ func (s *Scroll) updateOffset(deltaX, deltaY float32) bool { } oldX := s.Offset.X oldY := s.Offset.Y - s.Offset.X = computeOffset(s.Offset.X, -deltaX, s.Size().Width, s.Content.MinSize().Width) - s.Offset.Y = computeOffset(s.Offset.Y, -deltaY, s.Size().Height, s.Content.MinSize().Height) + s.Offset.X = computeOffset(s.Offset.X, -deltaX, size.Width, min.Width) + s.Offset.Y = computeOffset(s.Offset.Y, -deltaY, size.Height, min.Height) if f := s.OnScrolled; f != nil && (s.Offset.X != oldX || s.Offset.Y != oldY) { f(s.Offset) } @@ -495,10 +500,8 @@ func computeOffset(start, delta, outerWidth, innerWidth float32) float32 { if offset+outerWidth >= innerWidth { offset = innerWidth - outerWidth } - if offset < 0 { - offset = 0 - } - return offset + + return fyne.Max(offset, 0) } // NewScroll creates a scrollable parent wrapping the specified content. From 37ce6b97c78f5cea6dabb69a71e548155d81a7da Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 5 Dec 2023 23:01:31 +0100 Subject: [PATCH 108/248] internal/widget: Some more scroller cleanups --- internal/widget/scroller.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/widget/scroller.go b/internal/widget/scroller.go index 63889d3126..ccc2bc9340 100644 --- a/internal/widget/scroller.go +++ b/internal/widget/scroller.go @@ -286,15 +286,16 @@ func (r *scrollContainerRenderer) Refresh() { // push updated content object to baseRenderer r.BaseRenderer.Objects()[0] = r.scroll.Content } + size := r.scroll.Size() newMin := r.scroll.Content.MinSize() if r.oldMinSize == newMin && r.oldMinSize == r.scroll.Content.Size() && - (r.scroll.Size().Width <= r.oldMinSize.Width && r.scroll.Size().Height <= r.oldMinSize.Height) { - r.layoutBars(r.scroll.Size()) + (size.Width <= r.oldMinSize.Width && size.Height <= r.oldMinSize.Height) { + r.layoutBars(size) return } r.oldMinSize = newMin - r.Layout(r.scroll.Size()) + r.Layout(size) } func (r *scrollContainerRenderer) handleAreaVisibility(contentSize, scrollSize float32, area *scrollBarArea) { @@ -474,9 +475,8 @@ func (s *Scroll) scrollBy(dx, dy float32) { } func (s *Scroll) updateOffset(deltaX, deltaY float32) bool { - min := s.Content.MinSize() - contentSize := s.Content.Size() size := s.Size() + contentSize := s.Content.Size() if contentSize.Width <= size.Width && contentSize.Height <= size.Height { if s.Offset.X != 0 || s.Offset.Y != 0 { s.Offset.X = 0 @@ -487,6 +487,7 @@ func (s *Scroll) updateOffset(deltaX, deltaY float32) bool { } oldX := s.Offset.X oldY := s.Offset.Y + min := s.Content.MinSize() s.Offset.X = computeOffset(s.Offset.X, -deltaX, size.Width, min.Width) s.Offset.Y = computeOffset(s.Offset.Y, -deltaY, size.Height, min.Height) if f := s.OnScrolled; f != nil && (s.Offset.X != oldX || s.Offset.Y != oldY) { From 2be5bd7a18fc9f6c88811052ecb4d553e7e10257 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 6 Dec 2023 11:48:09 +0400 Subject: [PATCH 109/248] Fix glitches caught in PR --- data/binding/bindlists.go | 128 +++++++++++++++++++++----------------- data/binding/gen.go | 25 ++++---- 2 files changed, 86 insertions(+), 67 deletions(-) diff --git a/data/binding/bindlists.go b/data/binding/bindlists.go index a3d074fea9..77aaa80ba9 100644 --- a/data/binding/bindlists.go +++ b/data/binding/bindlists.go @@ -114,25 +114,27 @@ func (l *boundBoolList) Remove(val bool) error { l.lock.Lock() defer l.lock.Unlock() - if len(*l.val) == 0 { + v := *l.val + if len(v) == 0 { return nil } - if (*l.val)[0] == val { - *l.val = (*l.val)[1:] - } else if (*l.val)[len(*l.val)-1] == val { - *l.val = (*l.val)[:len(*l.val)] + if v[0] == val { + *l.val = v[1:] + } else if v[len(v)-1] == val { + *l.val = v[:len(v)] } else { id := -1 - for i, v := range *l.val { + for i, v := range v { if v == val { id = i + break } } if id == -1 { return nil } - *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + *l.val = append(v[:id], v[id+1:]...) } return l.doReload() @@ -368,25 +370,27 @@ func (l *boundBytesList) Remove(val []byte) error { l.lock.Lock() defer l.lock.Unlock() - if len(*l.val) == 0 { + v := *l.val + if len(v) == 0 { return nil } - if bytes.Equal((*l.val)[0], val) { - *l.val = (*l.val)[1:] - } else if bytes.Equal((*l.val)[len(*l.val)-1], val) { - *l.val = (*l.val)[:len(*l.val)] + if bytes.Equal(v[0], val) { + *l.val = v[1:] + } else if bytes.Equal(v[len(v)-1], val) { + *l.val = v[:len(v)] } else { id := -1 - for i, v := range *l.val { + for i, v := range v { if bytes.Equal(v, val) { id = i + break } } if id == -1 { return nil } - *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + *l.val = append(v[:id], v[id+1:]...) } return l.doReload() @@ -622,25 +626,27 @@ func (l *boundFloatList) Remove(val float64) error { l.lock.Lock() defer l.lock.Unlock() - if len(*l.val) == 0 { + v := *l.val + if len(v) == 0 { return nil } - if (*l.val)[0] == val { - *l.val = (*l.val)[1:] - } else if (*l.val)[len(*l.val)-1] == val { - *l.val = (*l.val)[:len(*l.val)] + if v[0] == val { + *l.val = v[1:] + } else if v[len(v)-1] == val { + *l.val = v[:len(v)] } else { id := -1 - for i, v := range *l.val { + for i, v := range v { if v == val { id = i + break } } if id == -1 { return nil } - *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + *l.val = append(v[:id], v[id+1:]...) } return l.doReload() @@ -876,25 +882,27 @@ func (l *boundIntList) Remove(val int) error { l.lock.Lock() defer l.lock.Unlock() - if len(*l.val) == 0 { + v := *l.val + if len(v) == 0 { return nil } - if (*l.val)[0] == val { - *l.val = (*l.val)[1:] - } else if (*l.val)[len(*l.val)-1] == val { - *l.val = (*l.val)[:len(*l.val)] + if v[0] == val { + *l.val = v[1:] + } else if v[len(v)-1] == val { + *l.val = v[:len(v)] } else { id := -1 - for i, v := range *l.val { + for i, v := range v { if v == val { id = i + break } } if id == -1 { return nil } - *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + *l.val = append(v[:id], v[id+1:]...) } return l.doReload() @@ -1130,25 +1138,27 @@ func (l *boundRuneList) Remove(val rune) error { l.lock.Lock() defer l.lock.Unlock() - if len(*l.val) == 0 { + v := *l.val + if len(v) == 0 { return nil } - if (*l.val)[0] == val { - *l.val = (*l.val)[1:] - } else if (*l.val)[len(*l.val)-1] == val { - *l.val = (*l.val)[:len(*l.val)] + if v[0] == val { + *l.val = v[1:] + } else if v[len(v)-1] == val { + *l.val = v[:len(v)] } else { id := -1 - for i, v := range *l.val { + for i, v := range v { if v == val { id = i + break } } if id == -1 { return nil } - *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + *l.val = append(v[:id], v[id+1:]...) } return l.doReload() @@ -1384,25 +1394,27 @@ func (l *boundStringList) Remove(val string) error { l.lock.Lock() defer l.lock.Unlock() - if len(*l.val) == 0 { + v := *l.val + if len(v) == 0 { return nil } - if (*l.val)[0] == val { - *l.val = (*l.val)[1:] - } else if (*l.val)[len(*l.val)-1] == val { - *l.val = (*l.val)[:len(*l.val)] + if v[0] == val { + *l.val = v[1:] + } else if v[len(v)-1] == val { + *l.val = v[:len(v)] } else { id := -1 - for i, v := range *l.val { + for i, v := range v { if v == val { id = i + break } } if id == -1 { return nil } - *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + *l.val = append(v[:id], v[id+1:]...) } return l.doReload() @@ -1638,25 +1650,27 @@ func (l *boundUntypedList) Remove(val interface{}) error { l.lock.Lock() defer l.lock.Unlock() - if len(*l.val) == 0 { + v := *l.val + if len(v) == 0 { return nil } - if (*l.val)[0] == val { - *l.val = (*l.val)[1:] - } else if (*l.val)[len(*l.val)-1] == val { - *l.val = (*l.val)[:len(*l.val)] + if v[0] == val { + *l.val = v[1:] + } else if v[len(v)-1] == val { + *l.val = v[:len(v)] } else { id := -1 - for i, v := range *l.val { + for i, v := range v { if v == val { id = i + break } } if id == -1 { return nil } - *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + *l.val = append(v[:id], v[id+1:]...) } return l.doReload() @@ -1892,25 +1906,27 @@ func (l *boundURIList) Remove(val fyne.URI) error { l.lock.Lock() defer l.lock.Unlock() - if len(*l.val) == 0 { + v := *l.val + if len(v) == 0 { return nil } - if compareURI((*l.val)[0], val) { - *l.val = (*l.val)[1:] - } else if compareURI((*l.val)[len(*l.val)-1], val) { - *l.val = (*l.val)[:len(*l.val)] + if compareURI(v[0], val) { + *l.val = v[1:] + } else if compareURI(v[len(v)-1], val) { + *l.val = v[:len(v)] } else { id := -1 - for i, v := range *l.val { + for i, v := range v { if compareURI(v, val) { id = i + break } } if id == -1 { return nil } - *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + *l.val = append(v[:id], v[id+1:]...) } return l.doReload() diff --git a/data/binding/gen.go b/data/binding/gen.go index cc697b04c8..9888ad7c54 100644 --- a/data/binding/gen.go +++ b/data/binding/gen.go @@ -480,32 +480,35 @@ func (l *bound{{ .Name }}List) Remove(val {{ .Type }}) error { l.lock.Lock() defer l.lock.Unlock() - if len(*l.val) == 0 { + v := *l.val + if len(v) == 0 { return nil } {{- if eq .Comparator "" }} - if (*l.val)[0] == val { - *l.val = (*l.val)[1:] - } else if (*l.val)[len(*l.val)-1] == val { - *l.val = (*l.val)[:len(*l.val)] + if v[0] == val { + *l.val = v[1:] + } else if v[len(v)-1] == val { + *l.val = v[:len(v)] } else { {{- else }} - if {{ .Comparator }}((*l.val)[0], val) { - *l.val = (*l.val)[1:] - } else if {{ .Comparator }}((*l.val)[len(*l.val)-1], val) { - *l.val = (*l.val)[:len(*l.val)] + if {{ .Comparator }}(v[0], val) { + *l.val = v[1:] + } else if {{ .Comparator }}(v[len(v)-1], val) { + *l.val = v[:len(v)] } else { {{- end }} id := -1 - for i, v := range *l.val { + for i, v := range v { {{- if eq .Comparator "" }} if v == val { id = i + break } {{- else }} if {{ .Comparator }}(v, val) { id = i + break } {{- end }} } @@ -513,7 +516,7 @@ func (l *bound{{ .Name }}List) Remove(val {{ .Type }}) error { if id == -1 { return nil } - *l.val = append((*l.val)[:id], (*l.val)[id+1:]...) + *l.val = append(v[:id], v[id+1:]...) } return l.doReload() From 450d8755dc5d3f5643f7c9e076ca7f0e2b16afa6 Mon Sep 17 00:00:00 2001 From: Ju-B Date: Tue, 28 Nov 2023 22:23:46 +0100 Subject: [PATCH 110/248] Correct row header width/height in widget.Table Allows to set width and height of headers using methods: SetColumnWidth and SetRowHeight with index -1 --- widget/table.go | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/widget/table.go b/widget/table.go index 41b8c15e99..d492487fa3 100644 --- a/widget/table.go +++ b/widget/table.go @@ -133,6 +133,16 @@ func (t *Table) CreateRenderer() fyne.WidgetRenderer { t.propertyLock.Lock() t.headerSize = t.createHeader().MinSize() + if t.columnWidths != nil { + if v, ok := t.columnWidths[-1]; ok { + t.headerSize.Width = v + } + } + if t.rowHeights != nil { + if v, ok := t.rowHeights[-1]; ok { + t.headerSize.Height = v + } + } t.cellSize = t.templateSize() t.cells = newTableCells(t) t.content = widget.NewScroll(t.cells) @@ -281,9 +291,14 @@ func (t *Table) Select(id TableCellID) { // Since: 1.4.1 func (t *Table) SetColumnWidth(id int, width float32) { t.propertyLock.Lock() + if id < 0 { + t.headerSize.Width = width + } + if t.columnWidths == nil { t.columnWidths = make(map[int]float32) } + t.columnWidths[id] = width t.propertyLock.Unlock() @@ -297,9 +312,14 @@ func (t *Table) SetColumnWidth(id int, width float32) { // Since: 2.3 func (t *Table) SetRowHeight(id int, height float32) { t.propertyLock.Lock() + if id < 0 { + t.headerSize.Height = height + } + if t.rowHeights == nil { t.rowHeights = make(map[int]float32) } + t.rowHeights[id] = height t.propertyLock.Unlock() @@ -1061,6 +1081,16 @@ func (t *tableRenderer) MinSize() fyne.Size { func (t *tableRenderer) Refresh() { t.t.propertyLock.Lock() t.t.headerSize = t.t.createHeader().MinSize() + if t.t.columnWidths != nil { + if v, ok := t.t.columnWidths[-1]; ok { + t.t.headerSize.Width = v + } + } + if t.t.rowHeights != nil { + if v, ok := t.t.rowHeights[-1]; ok { + t.t.headerSize.Height = v + } + } t.t.cellSize = t.t.templateSize() t.calculateHeaderSizes() t.t.propertyLock.Unlock() @@ -1536,7 +1566,7 @@ func (r *tableCellsRenderer) refreshHeaders(visibleRowHeights, visibleColWidths startRow, maxRow, startCol, maxCol int, separatorThickness float32) []fyne.CanvasObject { wasVisible := r.headers r.headers = make(map[TableCellID]fyne.CanvasObject) - headerMin := r.cells.t.createHeader().MinSize() + headerMin := r.cells.t.headerSize rowHeight := headerMin.Height colWidth := headerMin.Width From 5cbf0169ae66b6c4353c9bb789ff4a85244b572c Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 6 Dec 2023 12:21:28 +0400 Subject: [PATCH 111/248] Fix bug in remove, thanks staticheck and Jacalz! --- data/binding/bindlists.go | 16 ++++++++-------- data/binding/bindlists_test.go | 5 ++++- data/binding/gen.go | 4 ++-- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/data/binding/bindlists.go b/data/binding/bindlists.go index 77aaa80ba9..9b2430f4f7 100644 --- a/data/binding/bindlists.go +++ b/data/binding/bindlists.go @@ -121,7 +121,7 @@ func (l *boundBoolList) Remove(val bool) error { if v[0] == val { *l.val = v[1:] } else if v[len(v)-1] == val { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { id := -1 for i, v := range v { @@ -377,7 +377,7 @@ func (l *boundBytesList) Remove(val []byte) error { if bytes.Equal(v[0], val) { *l.val = v[1:] } else if bytes.Equal(v[len(v)-1], val) { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { id := -1 for i, v := range v { @@ -633,7 +633,7 @@ func (l *boundFloatList) Remove(val float64) error { if v[0] == val { *l.val = v[1:] } else if v[len(v)-1] == val { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { id := -1 for i, v := range v { @@ -889,7 +889,7 @@ func (l *boundIntList) Remove(val int) error { if v[0] == val { *l.val = v[1:] } else if v[len(v)-1] == val { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { id := -1 for i, v := range v { @@ -1145,7 +1145,7 @@ func (l *boundRuneList) Remove(val rune) error { if v[0] == val { *l.val = v[1:] } else if v[len(v)-1] == val { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { id := -1 for i, v := range v { @@ -1401,7 +1401,7 @@ func (l *boundStringList) Remove(val string) error { if v[0] == val { *l.val = v[1:] } else if v[len(v)-1] == val { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { id := -1 for i, v := range v { @@ -1657,7 +1657,7 @@ func (l *boundUntypedList) Remove(val interface{}) error { if v[0] == val { *l.val = v[1:] } else if v[len(v)-1] == val { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { id := -1 for i, v := range v { @@ -1913,7 +1913,7 @@ func (l *boundURIList) Remove(val fyne.URI) error { if compareURI(v[0], val) { *l.val = v[1:] } else if compareURI(v[len(v)-1], val) { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { id := -1 for i, v := range v { diff --git a/data/binding/bindlists_test.go b/data/binding/bindlists_test.go index 41b32a46bd..c14e0e5ef7 100644 --- a/data/binding/bindlists_test.go +++ b/data/binding/bindlists_test.go @@ -124,10 +124,13 @@ func TestFloatList_GetValue(t *testing.T) { func TestFloatList_Remove(t *testing.T) { f := NewFloatList() f.Append(0.5) + f.Append(0.7) f.Append(0.3) - assert.Equal(t, 2, f.Length()) + assert.Equal(t, 3, f.Length()) f.Remove(0.5) + assert.Equal(t, 2, f.Length()) + f.Remove(0.3) assert.Equal(t, 1, f.Length()) } diff --git a/data/binding/gen.go b/data/binding/gen.go index 9888ad7c54..8e56d0c215 100644 --- a/data/binding/gen.go +++ b/data/binding/gen.go @@ -489,13 +489,13 @@ func (l *bound{{ .Name }}List) Remove(val {{ .Type }}) error { if v[0] == val { *l.val = v[1:] } else if v[len(v)-1] == val { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { {{- else }} if {{ .Comparator }}(v[0], val) { *l.val = v[1:] } else if {{ .Comparator }}(v[len(v)-1], val) { - *l.val = v[:len(v)] + *l.val = v[:len(v)-1] } else { {{- end }} id := -1 From 430104cd7954fbb60af338d763cac53fa5539501 Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 6 Dec 2023 22:16:33 +0100 Subject: [PATCH 112/248] Reduce string allocations in mimetype code The code handling mimetypes was using strings.Split() to split the string and that allocates. We can use strings.IndexByte() to get an index and subslice instead. I also refactored some code to avoid duplicating mimetype split logic. The new internal/repository/mime package exists to avoid cycling imports. NOTE: The split logic is slightly different because a second / would be includes as part of the subtype now but as far as I can see from reading the spec (https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.21.html) it should not be a problem as the format is "mainType/subType;weight" so there should not be any more separators. --- internal/repository/mime/mime.go | 18 ++++++++++++++ internal/repository/mime/mime_test.go | 21 ++++++++++++++++ storage/filter.go | 35 ++++++++++----------------- storage/repository/uri.go | 8 ++++-- widget/fileicon.go | 14 +++-------- 5 files changed, 61 insertions(+), 35 deletions(-) create mode 100644 internal/repository/mime/mime.go create mode 100644 internal/repository/mime/mime_test.go diff --git a/internal/repository/mime/mime.go b/internal/repository/mime/mime.go new file mode 100644 index 0000000000..198698aaf7 --- /dev/null +++ b/internal/repository/mime/mime.go @@ -0,0 +1,18 @@ +package mime + +import ( + "strings" +) + +// Split spits the mimetype into its main type and subtype. +func Split(mimeTypeFull string) (mimeType, mimeSubType string) { + // Replace with strings.Cut() when Go 1.18 is our new base version. + separatorIndex := strings.IndexByte(mimeTypeFull, '/') + if separatorIndex == -1 || mimeTypeFull[separatorIndex+1:] == "" { + return "", "" // Empty or only one part. Ignore. + } + + mimeType = mimeTypeFull[:separatorIndex] + mimeSubType = mimeTypeFull[separatorIndex+1:] + return +} diff --git a/internal/repository/mime/mime_test.go b/internal/repository/mime/mime_test.go new file mode 100644 index 0000000000..5cedb2034a --- /dev/null +++ b/internal/repository/mime/mime_test.go @@ -0,0 +1,21 @@ +package mime + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSplitMimeType(t *testing.T) { + main, sub := Split("text/plain") + assert.Equal(t, "text", main) + assert.Equal(t, "plain", sub) + + main, sub = Split("text/") + assert.Empty(t, main) + assert.Empty(t, sub) + + main, sub = Split("") + assert.Empty(t, main) + assert.Empty(t, sub) +} diff --git a/storage/filter.go b/storage/filter.go index c6bec67c42..bcc9adac05 100644 --- a/storage/filter.go +++ b/storage/filter.go @@ -4,6 +4,7 @@ import ( "strings" "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/repository/mime" ) // FileFilter is an interface that can be implemented to provide a filter to a file dialog. @@ -42,18 +43,21 @@ func NewExtensionFileFilter(extensions []string) FileFilter { // Matches returns true if a file URI has one of the filtered mimetypes. func (mt *MimeTypeFileFilter) Matches(uri fyne.URI) bool { - mimeType, mimeSubType := splitMimeType(uri) + mimeType, mimeSubType := mime.Split(uri.MimeType()) for _, mimeTypeFull := range mt.MimeTypes { - mimeTypeSplit := strings.Split(mimeTypeFull, "/") - if len(mimeTypeSplit) <= 1 { + mType, mSubType := mime.Split(mimeTypeFull) + if mType == "" || mSubType == "" { continue } - mType := mimeTypeSplit[0] - mSubType := strings.Split(mimeTypeSplit[1], ";")[0] - if mType == mimeType { - if mSubType == mimeSubType || mSubType == "*" { - return true - } + + // Replace with strings.Cut() when Go 1.18 is our new base version. + subTypeSeparatorIndex := strings.IndexByte(mSubType, ';') + if subTypeSeparatorIndex != -1 { + mSubType = mSubType[:subTypeSeparatorIndex] + } + + if mType == mimeType && (mSubType == mimeSubType || mSubType == "*") { + return true } } return false @@ -64,16 +68,3 @@ func (mt *MimeTypeFileFilter) Matches(uri fyne.URI) bool { func NewMimeTypeFileFilter(mimeTypes []string) FileFilter { return &MimeTypeFileFilter{MimeTypes: mimeTypes} } - -func splitMimeType(uri fyne.URI) (mimeType, mimeSubType string) { - mimeTypeFull := uri.MimeType() - mimeTypeSplit := strings.Split(mimeTypeFull, "/") - if len(mimeTypeSplit) <= 1 { - mimeType, mimeSubType = "", "" - return - } - mimeType = mimeTypeSplit[0] - mimeSubType = mimeTypeSplit[1] - - return -} diff --git a/storage/repository/uri.go b/storage/repository/uri.go index bb07544dfb..44a5416b19 100644 --- a/storage/repository/uri.go +++ b/storage/repository/uri.go @@ -30,7 +30,6 @@ func (u *uri) Name() string { } func (u *uri) MimeType() string { - mimeTypeFull := mime.TypeByExtension(u.Extension()) if mimeTypeFull == "" { mimeTypeFull = "text/plain" @@ -50,7 +49,12 @@ func (u *uri) MimeType() string { } } - return strings.Split(mimeTypeFull, ";")[0] + // Replace with strings.Cut() when Go 1.18 is our new base version. + semicolonIndex := strings.IndexByte(mimeTypeFull, ';') + if semicolonIndex == -1 { + return mimeTypeFull + } + return mimeTypeFull[:semicolonIndex] } func (u *uri) Scheme() string { diff --git a/widget/fileicon.go b/widget/fileicon.go index 60041e481a..0ea2ea1833 100644 --- a/widget/fileicon.go +++ b/widget/fileicon.go @@ -1,10 +1,9 @@ package widget import ( - "strings" - "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/internal/repository/mime" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/storage" "fyne.io/fyne/v2/theme" @@ -99,7 +98,8 @@ func (i *FileIcon) lookupIcon(uri fyne.URI) fyne.Resource { return theme.FolderIcon() } - switch splitMimeType(uri) { + mainMimeType, _ := mime.Split(uri.MimeType()) + switch mainMimeType { case "application": return theme.FileApplicationIcon() case "audio": @@ -201,11 +201,3 @@ func trimmedExtension(uri fyne.URI) string { } return ext } - -func splitMimeType(uri fyne.URI) string { - mimeTypeSplit := strings.Split(uri.MimeType(), "/") - if len(mimeTypeSplit) <= 1 { - return "" - } - return mimeTypeSplit[0] -} From 7bc2e067fc55706ef3cb20e5fd90df22a59120a7 Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 6 Dec 2023 22:18:23 +0100 Subject: [PATCH 113/248] Remove unnecessary verbose import --- internal/repository/mime/mime.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/repository/mime/mime.go b/internal/repository/mime/mime.go index 198698aaf7..ef39897531 100644 --- a/internal/repository/mime/mime.go +++ b/internal/repository/mime/mime.go @@ -1,8 +1,6 @@ package mime -import ( - "strings" -) +import "strings" // Split spits the mimetype into its main type and subtype. func Split(mimeTypeFull string) (mimeType, mimeSubType string) { From ed5eb1c2d83c615162ec0400ed7a96f2695ff7cc Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 9 Dec 2023 14:05:38 -0800 Subject: [PATCH 114/248] use sync.Pool and local copies of visible/wasVisible to avoid data races --- widget/list.go | 51 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/widget/list.go b/widget/list.go index 7e11fed705..5c24d0444c 100644 --- a/widget/list.go +++ b/widget/list.go @@ -536,15 +536,19 @@ type listLayout struct { separators []fyne.CanvasObject children []fyne.CanvasObject - itemPool *syncPool + itemPool syncPool visible []itemAndID - wasVisible []itemAndID + slicePool sync.Pool // *[]itemAndID visibleRowHeights []float32 renderLock sync.RWMutex } func newListLayout(list *List) fyne.Layout { - l := &listLayout{list: list, itemPool: &syncPool{}} + l := &listLayout{list: list} + l.slicePool.New = func() interface{} { + s := make([]itemAndID, 0) + return &s + } list.offsetUpdated = l.offsetUpdated return l } @@ -646,13 +650,11 @@ func (l *listLayout) updateList(newOnly bool) { fyne.LogError("Missing UpdateCell callback required for List", nil) } - // Swap l.wasVisible and l.visible - // since l.wasVisible contains only nil references at this point, - // we don't need to overwrite old data if we fill l.visible to less than - // the previous length of l.wasVisible - tmp := l.wasVisible - l.wasVisible = l.visible - l.visible = tmp + // Keep pointer reference for copying slice header when returning to the pool + // https://blog.mike.norgate.xyz/unlocking-go-slice-performance-navigating-sync-pool-for-enhanced-efficiency-7cb63b0b453e + wasVisiblePtr := l.slicePool.Get().(*[]itemAndID) + wasVisible := (*wasVisiblePtr)[:0] + wasVisible = append(wasVisible, l.visible...) l.list.propertyLock.Lock() offY, minRow := l.calculateVisibleRowHeights(l.list.itemMin.Height, length) @@ -671,7 +673,7 @@ func (l *listLayout) updateList(newOnly bool) { row := index + minRow size := fyne.NewSize(width, itemHeight) - c, ok := l.searchVisible(l.wasVisible, row) + c, ok := l.searchVisible(wasVisible, row) if !ok { c = l.getItem() if c == nil { @@ -689,7 +691,7 @@ func (l *listLayout) updateList(newOnly bool) { } l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) - for _, wasVis := range l.wasVisible { + for _, wasVis := range wasVisible { if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { l.itemPool.Release(wasVis.item) } @@ -703,24 +705,37 @@ func (l *listLayout) updateList(newOnly bool) { c.Objects = append(c.Objects, l.children...) c.Objects = append(c.Objects, l.separators...) l.nilOldSliceData(c.Objects, len(c.Objects), oldObjLen) + + // make a local deep copy of l.visible since rest of this function is unlocked + // and cannot safely access l.visible + visiblePtr := l.slicePool.Get().(*[]itemAndID) + visible := (*visiblePtr)[:0] + visible = append(visible, l.visible...) l.renderLock.Unlock() // user code should not be locked if newOnly { - for _, vis := range l.visible { - if _, ok := l.searchVisible(l.wasVisible, vis.id); !ok { + for _, vis := range visible { + if _, ok := l.searchVisible(wasVisible, vis.id); !ok { l.setupListItem(vis.item, vis.id, l.list.focused && l.list.currentFocus == vis.id) } } } else { - for _, vis := range l.visible { + for _, vis := range visible { l.setupListItem(vis.item, vis.id, l.list.focused && l.list.currentFocus == vis.id) } } - // we don't need wasVisible's data anymore; nil out all references - for i := 0; i < len(l.wasVisible); i++ { - l.wasVisible[i].item = nil + // nil out all references before returning slices to pool + for i := 0; i < len(wasVisible); i++ { + wasVisible[i].item = nil + } + for i := 0; i < len(visible); i++ { + visible[i].item = nil } + *wasVisiblePtr = wasVisible // Copy the stack header over to the heap + *visiblePtr = visible + l.slicePool.Put(wasVisiblePtr) + l.slicePool.Put(visiblePtr) } func (l *listLayout) updateSeparators() { From 81f4c1bcf93d00ee19b7b009ec527bfe3b1ef94b Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 9 Dec 2023 15:25:22 -0800 Subject: [PATCH 115/248] use reusable slices to keep track of visible/wasVisible --- widget/gridwrap.go | 109 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 26 deletions(-) diff --git a/widget/gridwrap.go b/widget/gridwrap.go index 8a782edd5e..b8cdab9a49 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -3,6 +3,7 @@ package widget import ( "fmt" "math" + "sort" "sync" "fyne.io/fyne/v2" @@ -137,8 +138,10 @@ func (l *GridWrap) RefreshItem(id GridWrapItemID) { } l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*gridWrapLayout) - visible := lo.visible - if item, ok := visible[id]; ok { + lo.renderLock.Lock() // ensures we are not changing visible info in render code during the search + item, ok := lo.searchVisible(lo.visible, id) + lo.renderLock.Unlock() + if ok { lo.setupGridItem(item, id, l.focused && l.currentFocus == id) } } @@ -461,17 +464,27 @@ func (gw *gridWrapItemRenderer) Refresh() { // Declare conformity with Layout interface. var _ fyne.Layout = (*gridWrapLayout)(nil) +type itemAndID struct { + item *gridWrapItem + id GridWrapItemID +} + type gridWrapLayout struct { list *GridWrap children []fyne.CanvasObject - itemPool *syncPool - visible map[GridWrapItemID]*gridWrapItem + itemPool syncPool + slicePool sync.Pool // *[]itemAndID + visible []itemAndID renderLock sync.Mutex } func newGridWrapLayout(list *GridWrap) fyne.Layout { - l := &gridWrapLayout{list: list, itemPool: &syncPool{}, visible: make(map[GridWrapItemID]*gridWrapItem)} + l := &gridWrapLayout{list: list} + l.slicePool.New = func() interface{} { + s := make([]itemAndID, 0) + return &s + } list.offsetUpdated = l.offsetUpdated return l } @@ -573,48 +586,92 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { fyne.LogError("Missing UpdateCell callback required for GridWrap", nil) } - wasVisible := l.visible - l.visible = make(map[GridWrapItemID]*gridWrapItem) + // Keep pointer reference for copying slice header when returning to the pool + // https://blog.mike.norgate.xyz/unlocking-go-slice-performance-navigating-sync-pool-for-enhanced-efficiency-7cb63b0b453e + wasVisiblePtr := l.slicePool.Get().(*[]itemAndID) + wasVisible := (*wasVisiblePtr)[:0] + wasVisible = append(wasVisible, l.visible...) + + oldVisibleLen := len(l.visible) + l.visible = l.visible[:0] + var cells []fyne.CanvasObject y := offY - curItem := minItem - for row := minRow; row <= maxRow && curItem <= maxItem; row++ { + curItemID := minItem + for row := minRow; row <= maxRow && curItemID <= maxItem; row++ { x := float32(0) - for col := 0; col < colCount && curItem <= maxItem; col++ { - c, ok := wasVisible[curItem] + for col := 0; col < colCount && curItemID <= maxItem; col++ { + item, ok := l.searchVisible(wasVisible, curItemID) if !ok { - c = l.getItem() - if c == nil { + item = l.getItem() + if item == nil { continue } - c.Resize(l.list.itemMin) + item.Resize(l.list.itemMin) } - c.Move(fyne.NewPos(x, y)) + item.Move(fyne.NewPos(x, y)) if refresh { - c.Resize(l.list.itemMin) + item.Resize(l.list.itemMin) } x += l.list.itemMin.Width + theme.Padding() - l.visible[curItem] = c - cells = append(cells, c) - curItem++ + l.visible = append(l.visible, itemAndID{item: item, id: curItemID}) + cells = append(cells, item) + curItemID++ } y += l.list.itemMin.Height + theme.Padding() } + l.nilOldVisibleSliceData(l.visible, len(l.visible), oldVisibleLen) - for id, old := range wasVisible { - if _, ok := l.visible[id]; !ok { - l.itemPool.Release(old) + for _, old := range wasVisible { + if _, ok := l.searchVisible(l.visible, old.id); !ok { + l.itemPool.Release(old.item) } } l.children = cells - objects := l.children - l.list.scroller.Content.(*fyne.Container).Objects = objects + l.list.scroller.Content.(*fyne.Container).Objects = l.children + + // make a local deep copy of l.visible since rest of this function is unlocked + // and cannot safely access l.visible + visiblePtr := l.slicePool.Get().(*[]itemAndID) + visible := (*visiblePtr)[:0] + visible = append(visible, l.visible...) l.renderLock.Unlock() // user code should not be locked - for row, obj := range l.visible { - l.setupGridItem(obj, row, l.list.focused && l.list.currentFocus == row) + for _, obj := range visible { + l.setupGridItem(obj.item, obj.id, l.list.focused && l.list.currentFocus == obj.id) + } + + // nil out all references before returning slices to pool + for i := 0; i < len(wasVisible); i++ { + wasVisible[i].item = nil + } + for i := 0; i < len(visible); i++ { + visible[i].item = nil + } + *wasVisiblePtr = wasVisible // Copy the stack header over to the heap + *visiblePtr = visible + l.slicePool.Put(wasVisiblePtr) + l.slicePool.Put(visiblePtr) +} + +// invariant: visible is in ascending order of IDs +func (l *gridWrapLayout) searchVisible(visible []itemAndID, id GridWrapItemID) (*gridWrapItem, bool) { + ln := len(visible) + idx := sort.Search(ln, func(i int) bool { return visible[i].id >= id }) + if idx < ln && visible[idx].id == id { + return visible[idx].item, true + } + return nil, false +} + +func (l *gridWrapLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { + if oldLen > len { + objs = objs[:oldLen] // gain view into old data + for i := len; i < oldLen; i++ { + objs[i].item = nil + } } } From c31211ec555ee5bb993c3868a82b2dffae9735f6 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 9 Dec 2023 15:58:10 -0800 Subject: [PATCH 116/248] make sure to nil out excess capacity in l.visible slice --- widget/list.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/widget/list.go b/widget/list.go index 5c24d0444c..80c63b63fd 100644 --- a/widget/list.go +++ b/widget/list.go @@ -664,6 +664,7 @@ func (l *listLayout) updateList(newOnly bool) { return } + oldVisibleLen := len(l.visible) l.visible = l.visible[:0] oldChildrenLen := len(l.children) l.children = l.children[:0] @@ -690,6 +691,7 @@ func (l *listLayout) updateList(newOnly bool) { l.children = append(l.children, c) } l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) + l.nilOldVisibleSliceData(l.visible, len(l.visible), oldVisibleLen) for _, wasVis := range wasVisible { if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { @@ -781,3 +783,12 @@ func (l *listLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) } } } + +func (l *listLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { + if oldLen > len { + objs = objs[:oldLen] // gain view into old data + for i := len; i < oldLen; i++ { + objs[i].item = nil + } + } +} From 5032db375c54ab39791732ce2ab4ba98e6f132f2 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 9 Dec 2023 19:20:00 -0800 Subject: [PATCH 117/248] reuse allocated mem from container.Objects slice --- widget/gridwrap.go | 22 +++++++++++++++------- widget/gridwrap_test.go | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/widget/gridwrap.go b/widget/gridwrap.go index b8cdab9a49..6b74976de7 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -470,8 +470,7 @@ type itemAndID struct { } type gridWrapLayout struct { - list *GridWrap - children []fyne.CanvasObject + list *GridWrap itemPool syncPool slicePool sync.Pool // *[]itemAndID @@ -595,7 +594,9 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { oldVisibleLen := len(l.visible) l.visible = l.visible[:0] - var cells []fyne.CanvasObject + c := l.list.scroller.Content.(*fyne.Container) + oldObjLen := len(c.Objects) + c.Objects = c.Objects[:0] y := offY curItemID := minItem for row := minRow; row <= maxRow && curItemID <= maxItem; row++ { @@ -617,11 +618,12 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { x += l.list.itemMin.Width + theme.Padding() l.visible = append(l.visible, itemAndID{item: item, id: curItemID}) - cells = append(cells, item) + c.Objects = append(c.Objects, item) curItemID++ } y += l.list.itemMin.Height + theme.Padding() } + l.nilOldSliceData(c.Objects, len(c.Objects), oldObjLen) l.nilOldVisibleSliceData(l.visible, len(l.visible), oldVisibleLen) for _, old := range wasVisible { @@ -629,9 +631,6 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { l.itemPool.Release(old.item) } } - l.children = cells - - l.list.scroller.Content.(*fyne.Container).Objects = l.children // make a local deep copy of l.visible since rest of this function is unlocked // and cannot safely access l.visible @@ -667,6 +666,15 @@ func (l *gridWrapLayout) searchVisible(visible []itemAndID, id GridWrapItemID) ( return nil, false } +func (l *gridWrapLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) { + if oldLen > len { + objs = objs[:oldLen] // gain view into old data + for i := len; i < oldLen; i++ { + objs[i] = nil + } + } +} + func (l *gridWrapLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { if oldLen > len { objs = objs[:oldLen] // gain view into old data diff --git a/widget/gridwrap_test.go b/widget/gridwrap_test.go index 238389e5ed..af8fe03b2c 100644 --- a/widget/gridwrap_test.go +++ b/widget/gridwrap_test.go @@ -23,7 +23,7 @@ func TestGridWrap_Focus(t *testing.T) { assert.NotNil(t, canvas.Focused()) assert.Equal(t, 0, canvas.Focused().(*GridWrap).currentFocus) - children := list.scroller.Content.(*fyne.Container).Layout.(*gridWrapLayout).children + children := list.scroller.Content.(*fyne.Container).Objects assert.True(t, children[0].(*gridWrapItem).hovered) assert.False(t, children[1].(*gridWrapItem).hovered) assert.False(t, children[6].(*gridWrapItem).hovered) @@ -182,7 +182,7 @@ func TestGridWrap_RefreshItem(t *testing.T) { data[2] = "Replace" list.RefreshItem(2) - children := list.scroller.Content.(*fyne.Container).Layout.(*gridWrapLayout).children + children := list.scroller.Content.(*fyne.Container).Objects assert.Equal(t, children[1].(*gridWrapItem).child.(*Label).Text, "Text") assert.Equal(t, children[2].(*gridWrapItem).child.(*Label).Text, "Replace") } From 0b4594330f37fc6b0f7e0c4d86656fbb05ca34c8 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 10 Dec 2023 15:08:24 +0400 Subject: [PATCH 118/248] If the keyboard is visible hide it instead of actually going back Fixes #4257 --- internal/driver/mobile/app/GoNativeActivity.java | 8 ++++++++ internal/driver/mobile/app/android.go | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/driver/mobile/app/GoNativeActivity.java b/internal/driver/mobile/app/GoNativeActivity.java index 5521b957ae..bb1c9b97c3 100644 --- a/internal/driver/mobile/app/GoNativeActivity.java +++ b/internal/driver/mobile/app/GoNativeActivity.java @@ -48,6 +48,7 @@ public class GoNativeActivity extends NativeActivity { private EditText mTextEdit; private boolean ignoreKey = false; + private boolean keyboardUp = false; public GoNativeActivity() { super(); @@ -79,6 +80,7 @@ void updateLayout() { static void showKeyboard(int keyboardType) { goNativeActivity.doShowKeyboard(keyboardType); + goNativeActivity.keyboardUp = true; } void doShowKeyboard(final int keyboardType) { @@ -135,6 +137,7 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { static void hideKeyboard() { goNativeActivity.doHideKeyboard(); + goNativeActivity.keyboardUp = false; } void doHideKeyboard() { @@ -316,6 +319,11 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { @Override public void onBackPressed() { + if (goNativeActivity.keyboardUp) { + hideKeyboard(); + return; + } + // skip the default behaviour - we can call finishActivity if we want to go back backPressed(); } diff --git a/internal/driver/mobile/app/android.go b/internal/driver/mobile/app/android.go index 24eb000330..dc874199db 100644 --- a/internal/driver/mobile/app/android.go +++ b/internal/driver/mobile/app/android.go @@ -142,7 +142,6 @@ func onBackPressed() { Code: key.CodeBackButton, Direction: key.DirPress, } - log.Println("Logging key event back") theApp.events.In() <- k k.Direction = key.DirRelease From 0ebdaf048b4c37662b8e158d04b538b24ff44a6c Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 10 Dec 2023 07:55:56 -0800 Subject: [PATCH 119/248] typo fix --- widget/gridwrap.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/gridwrap.go b/widget/gridwrap.go index 6b74976de7..1bd25e8311 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -650,7 +650,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { for i := 0; i < len(visible); i++ { visible[i].item = nil } - *wasVisiblePtr = wasVisible // Copy the stack header over to the heap + *wasVisiblePtr = wasVisible // Copy the slice header over to the heap *visiblePtr = visible l.slicePool.Put(wasVisiblePtr) l.slicePool.Put(visiblePtr) From f710676e45f2c6039f8754ffa6acbc0bf66ff27e Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 10 Dec 2023 11:00:20 -0800 Subject: [PATCH 120/248] create new Driver API DoubleTapDelay --- driver.go | 8 ++++++++ internal/driver/consts/consts.go | 9 --------- internal/driver/glfw/driver.go | 7 +++++++ internal/driver/glfw/window.go | 3 +-- internal/driver/mobile/canvas.go | 3 +-- internal/driver/mobile/canvas_test.go | 5 ++--- internal/driver/mobile/driver.go | 5 +++++ test/testdriver.go | 5 +++++ widget/entry.go | 7 +------ 9 files changed, 30 insertions(+), 22 deletions(-) delete mode 100644 internal/driver/consts/consts.go diff --git a/driver.go b/driver.go index 8737f69148..2cc7cecd2f 100644 --- a/driver.go +++ b/driver.go @@ -1,5 +1,7 @@ package fyne +import "time" + // Driver defines an abstract concept of a Fyne render driver. // Any implementation must provide at least these methods. type Driver interface { @@ -29,4 +31,10 @@ type Driver interface { StartAnimation(*Animation) // StopAnimation stops an animation and unregisters from this driver. StopAnimation(*Animation) + + // DoubleTapDelay returns the maximum duration where a second tap after a first one + // will be considered a DoubleTap instead of two distinct Tap events. + // + // Since: 2.5 + DoubleTapDelay() time.Duration } diff --git a/internal/driver/consts/consts.go b/internal/driver/consts/consts.go deleted file mode 100644 index 15d750c6b0..0000000000 --- a/internal/driver/consts/consts.go +++ /dev/null @@ -1,9 +0,0 @@ -package consts - -const ( - // moved here from the platform driver packages to allow - // referencing in widget package without an import cycle - - DesktopDoubleClickDelay = 300 // ms - MobileDoubleClickDelay = 500 // ms -) diff --git a/internal/driver/glfw/driver.go b/internal/driver/glfw/driver.go index 241b5e09e1..6a44a1c45d 100644 --- a/internal/driver/glfw/driver.go +++ b/internal/driver/glfw/driver.go @@ -9,6 +9,7 @@ import ( "runtime" "sync" "sync/atomic" + "time" "github.com/fyne-io/image/ico" @@ -36,6 +37,8 @@ var _ fyne.Driver = (*gLDriver)(nil) // A workaround on Apple M1/M2, just use 1 thread until fixed upstream. const drawOnMainThread bool = runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" +const doubleTapDelay = 300 * time.Millisecond + type gLDriver struct { windowLock sync.RWMutex windows []fyne.Window @@ -168,6 +171,10 @@ func (d *gLDriver) Run() { d.runGL() } +func (d *gLDriver) DoubleTapDelay() time.Duration { + return doubleTapDelay +} + // NewGLDriver sets up a new Driver instance implemented using the GLFW Go library and OpenGL bindings. func NewGLDriver() *gLDriver { repository.Register("file", intRepo.NewFileRepository()) diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 1bd456842a..b58ef13650 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -13,7 +13,6 @@ import ( "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/driver" "fyne.io/fyne/v2/internal/driver/common" - "fyne.io/fyne/v2/internal/driver/consts" "fyne.io/fyne/v2/internal/scale" ) @@ -652,7 +651,7 @@ func (w *window) mouseClickedHandleTapDoubleTap(co fyne.CanvasObject, ev *fyne.P func (w *window) waitForDoubleTap(co fyne.CanvasObject, ev *fyne.PointEvent) { var ctx context.Context w.mouseLock.Lock() - ctx, w.mouseCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*consts.DesktopDoubleClickDelay)) + ctx, w.mouseCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(doubleTapDelay)) defer w.mouseCancelFunc() w.mouseLock.Unlock() diff --git a/internal/driver/mobile/canvas.go b/internal/driver/mobile/canvas.go index 8756f47a5c..806ffea6f5 100644 --- a/internal/driver/mobile/canvas.go +++ b/internal/driver/mobile/canvas.go @@ -12,7 +12,6 @@ import ( "fyne.io/fyne/v2/internal/app" "fyne.io/fyne/v2/internal/driver" "fyne.io/fyne/v2/internal/driver/common" - "fyne.io/fyne/v2/internal/driver/consts" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -375,7 +374,7 @@ func (c *mobileCanvas) tapUp(pos fyne.Position, tapID int, func (c *mobileCanvas) waitForDoubleTap(co fyne.CanvasObject, ev *fyne.PointEvent, tapCallback func(fyne.Tappable, *fyne.PointEvent), doubleTapCallback func(fyne.DoubleTappable, *fyne.PointEvent)) { var ctx context.Context - ctx, c.touchCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(time.Millisecond*consts.MobileDoubleClickDelay)) + ctx, c.touchCancelFunc = context.WithDeadline(context.TODO(), time.Now().Add(tapDoubleDelay)) defer c.touchCancelFunc() <-ctx.Done() if c.touchTapCount == 2 && c.touchLastTapped == co { diff --git a/internal/driver/mobile/canvas_test.go b/internal/driver/mobile/canvas_test.go index 92cfcb9e61..68468ea6ae 100644 --- a/internal/driver/mobile/canvas_test.go +++ b/internal/driver/mobile/canvas_test.go @@ -13,7 +13,6 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/driver/mobile" - "fyne.io/fyne/v2/internal/driver/consts" _ "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -299,7 +298,7 @@ func TestCanvas_Focusable(t *testing.T) { c.tapUp(pos, 0, func(wid fyne.Tappable, ev *fyne.PointEvent) { wid.Tapped(ev) }, nil, nil, nil) - time.Sleep(time.Millisecond * (consts.MobileDoubleClickDelay + 150)) + time.Sleep(tapDoubleDelay + 150*time.Millisecond) assert.Equal(t, 1, content.focusedTimes) assert.Equal(t, 0, content.unfocusedTimes) @@ -307,7 +306,7 @@ func TestCanvas_Focusable(t *testing.T) { c.tapUp(pos, 1, func(wid fyne.Tappable, ev *fyne.PointEvent) { wid.Tapped(ev) }, nil, nil, nil) - time.Sleep(time.Millisecond * (consts.MobileDoubleClickDelay + 150)) + time.Sleep(tapDoubleDelay + 150*time.Millisecond) assert.Equal(t, 1, content.focusedTimes) assert.Equal(t, 0, content.unfocusedTimes) diff --git a/internal/driver/mobile/driver.go b/internal/driver/mobile/driver.go index 5e06cffbdc..53000d9d79 100644 --- a/internal/driver/mobile/driver.go +++ b/internal/driver/mobile/driver.go @@ -31,6 +31,7 @@ import ( const ( tapMoveThreshold = 4.0 // how far can we move before it is a drag tapSecondaryDelay = 300 * time.Millisecond // how long before secondary tap + tapDoubleDelay = 500 * time.Millisecond // max duration between taps for a DoubleTap event ) // Configuration is the system information about the current device @@ -549,6 +550,10 @@ func (d *mobileDriver) SetOnConfigurationChanged(f func(*Configuration)) { d.onConfigChanged = f } +func (d *mobileDriver) DoubleTapDelay() time.Duration { + return tapDoubleDelay +} + // NewGoMobileDriver sets up a new Driver instance implemented using the Go // Mobile extension and OpenGL bindings. func NewGoMobileDriver() fyne.Driver { diff --git a/test/testdriver.go b/test/testdriver.go index 146e44e1ff..6bc2a2269a 100644 --- a/test/testdriver.go +++ b/test/testdriver.go @@ -3,6 +3,7 @@ package test import ( "image" "sync" + "time" "fyne.io/fyne/v2" "fyne.io/fyne/v2/internal/driver" @@ -129,3 +130,7 @@ func (d *testDriver) removeWindow(w *testWindow) { d.windows = append(d.windows[:i], d.windows[i+1:]...) d.windowsMutex.Unlock() } + +func (d *testDriver) DoubleTapDelay() time.Duration { + return 300 * time.Millisecond +} diff --git a/widget/entry.go b/widget/entry.go index e7c760c5ec..2ab8f8871d 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -14,7 +14,6 @@ import ( "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/driver/mobile" "fyne.io/fyne/v2/internal/cache" - driverconsts "fyne.io/fyne/v2/internal/driver/consts" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -256,11 +255,7 @@ func (e *Entry) DoubleTapped(p *fyne.PointEvent) { } func (e *Entry) isTripleTap(nowMilli int64) bool { - doubleClickDelay := int64(driverconsts.DesktopDoubleClickDelay) - if fyne.CurrentDevice().IsMobile() { - doubleClickDelay = driverconsts.MobileDoubleClickDelay - } - return nowMilli-e.doubleTappedAtUnixMillis <= doubleClickDelay + return nowMilli-e.doubleTappedAtUnixMillis <= fyne.CurrentApp().Driver().DoubleTapDelay().Milliseconds() } // DragEnd is called at end of a drag event. From 934668f1058e978a743c3f24c5b8ce092e6c11dd Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sat, 16 Dec 2023 09:41:41 +0000 Subject: [PATCH 121/248] Fix name/path when using android arch --- cmd/fyne/internal/mobile/build.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/fyne/internal/mobile/build.go b/cmd/fyne/internal/mobile/build.go index 4b115fa364..db3100d43c 100644 --- a/cmd/fyne/internal/mobile/build.go +++ b/cmd/fyne/internal/mobile/build.go @@ -81,7 +81,7 @@ func runBuild(cmd *command) (err error) { // AppOutputName provides the name of a build resource for a given os - "ios" or "android". func AppOutputName(os, name string, release bool) string { switch os { - case "android": + case "android/arm", "android/arm64", "android/amd64", "android/386", "android": if release { return androidPkgName(name) + ".aab" } else { From 434f4fff29c397764d3b9b37ba02ff7eb7a212bf Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sat, 16 Dec 2023 09:42:03 +0000 Subject: [PATCH 122/248] Fix docs location --- cmd/fyne/internal/mobile/build_androidapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/fyne/internal/mobile/build_androidapp.go b/cmd/fyne/internal/mobile/build_androidapp.go index e4982ba245..1d2373dca3 100644 --- a/cmd/fyne/internal/mobile/build_androidapp.go +++ b/cmd/fyne/internal/mobile/build_androidapp.go @@ -153,7 +153,7 @@ func goAndroidBuild(pkg *packages.Package, bundleID string, androidArchs []strin _, err := execabs.LookPath("bundletool") if err != nil { _, _ = fmt.Fprint(os.Stderr, "Required command 'bundletool' not found when building Android for release.\n") - _, _ = fmt.Fprint(os.Stderr, "For more information see https://g.co/androidappbundle.\n") + _, _ = fmt.Fprint(os.Stderr, "For more information see https://developer.android.com/tools/bundletool.\n") return nil, fmt.Errorf("bundletool: command not found") } err = convertAPKToAAB(buildO) From 484d8b67cbdaa28199ad0efae459b676c872cb9f Mon Sep 17 00:00:00 2001 From: Dorbmon Date: Sun, 17 Dec 2023 11:34:11 -0500 Subject: [PATCH 123/248] fix conflicts name of structure itemAndID under the same package --- widget/gridwrap.go | 16 ++++++++-------- widget/list.go | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/widget/gridwrap.go b/widget/gridwrap.go index 1bd25e8311..0221c9bb08 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -464,7 +464,7 @@ func (gw *gridWrapItemRenderer) Refresh() { // Declare conformity with Layout interface. var _ fyne.Layout = (*gridWrapLayout)(nil) -type itemAndID struct { +type gridItemAndID struct { item *gridWrapItem id GridWrapItemID } @@ -474,14 +474,14 @@ type gridWrapLayout struct { itemPool syncPool slicePool sync.Pool // *[]itemAndID - visible []itemAndID + visible []gridItemAndID renderLock sync.Mutex } func newGridWrapLayout(list *GridWrap) fyne.Layout { l := &gridWrapLayout{list: list} l.slicePool.New = func() interface{} { - s := make([]itemAndID, 0) + s := make([]gridItemAndID, 0) return &s } list.offsetUpdated = l.offsetUpdated @@ -587,7 +587,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { // Keep pointer reference for copying slice header when returning to the pool // https://blog.mike.norgate.xyz/unlocking-go-slice-performance-navigating-sync-pool-for-enhanced-efficiency-7cb63b0b453e - wasVisiblePtr := l.slicePool.Get().(*[]itemAndID) + wasVisiblePtr := l.slicePool.Get().(*[]gridItemAndID) wasVisible := (*wasVisiblePtr)[:0] wasVisible = append(wasVisible, l.visible...) @@ -617,7 +617,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { } x += l.list.itemMin.Width + theme.Padding() - l.visible = append(l.visible, itemAndID{item: item, id: curItemID}) + l.visible = append(l.visible, gridItemAndID{item: item, id: curItemID}) c.Objects = append(c.Objects, item) curItemID++ } @@ -634,7 +634,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { // make a local deep copy of l.visible since rest of this function is unlocked // and cannot safely access l.visible - visiblePtr := l.slicePool.Get().(*[]itemAndID) + visiblePtr := l.slicePool.Get().(*[]gridItemAndID) visible := (*visiblePtr)[:0] visible = append(visible, l.visible...) l.renderLock.Unlock() // user code should not be locked @@ -657,7 +657,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { } // invariant: visible is in ascending order of IDs -func (l *gridWrapLayout) searchVisible(visible []itemAndID, id GridWrapItemID) (*gridWrapItem, bool) { +func (l *gridWrapLayout) searchVisible(visible []gridItemAndID, id GridWrapItemID) (*gridWrapItem, bool) { ln := len(visible) idx := sort.Search(ln, func(i int) bool { return visible[i].id >= id }) if idx < ln && visible[idx].id == id { @@ -675,7 +675,7 @@ func (l *gridWrapLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen i } } -func (l *gridWrapLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { +func (l *gridWrapLayout) nilOldVisibleSliceData(objs []gridItemAndID, len, oldLen int) { if oldLen > len { objs = objs[:oldLen] // gain view into old data for i := len; i < oldLen; i++ { diff --git a/widget/list.go b/widget/list.go index 80c63b63fd..23636edbb2 100644 --- a/widget/list.go +++ b/widget/list.go @@ -526,7 +526,7 @@ func (li *listItemRenderer) Refresh() { // Declare conformity with Layout interface. var _ fyne.Layout = (*listLayout)(nil) -type itemAndID struct { +type listItemAndID struct { item *listItem id ListItemID } @@ -537,7 +537,7 @@ type listLayout struct { children []fyne.CanvasObject itemPool syncPool - visible []itemAndID + visible []listItemAndID slicePool sync.Pool // *[]itemAndID visibleRowHeights []float32 renderLock sync.RWMutex @@ -546,7 +546,7 @@ type listLayout struct { func newListLayout(list *List) fyne.Layout { l := &listLayout{list: list} l.slicePool.New = func() interface{} { - s := make([]itemAndID, 0) + s := make([]listItemAndID, 0) return &s } list.offsetUpdated = l.offsetUpdated @@ -652,7 +652,7 @@ func (l *listLayout) updateList(newOnly bool) { // Keep pointer reference for copying slice header when returning to the pool // https://blog.mike.norgate.xyz/unlocking-go-slice-performance-navigating-sync-pool-for-enhanced-efficiency-7cb63b0b453e - wasVisiblePtr := l.slicePool.Get().(*[]itemAndID) + wasVisiblePtr := l.slicePool.Get().(*[]listItemAndID) wasVisible := (*wasVisiblePtr)[:0] wasVisible = append(wasVisible, l.visible...) @@ -687,7 +687,7 @@ func (l *listLayout) updateList(newOnly bool) { c.Resize(size) y += itemHeight + separatorThickness - l.visible = append(l.visible, itemAndID{id: row, item: c}) + l.visible = append(l.visible, listItemAndID{id: row, item: c}) l.children = append(l.children, c) } l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) @@ -710,7 +710,7 @@ func (l *listLayout) updateList(newOnly bool) { // make a local deep copy of l.visible since rest of this function is unlocked // and cannot safely access l.visible - visiblePtr := l.slicePool.Get().(*[]itemAndID) + visiblePtr := l.slicePool.Get().(*[]listItemAndID) visible := (*visiblePtr)[:0] visible = append(visible, l.visible...) l.renderLock.Unlock() // user code should not be locked @@ -766,7 +766,7 @@ func (l *listLayout) updateSeparators() { } // invariant: visible is in ascending order of IDs -func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) (*listItem, bool) { +func (l *listLayout) searchVisible(visible []listItemAndID, id ListItemID) (*listItem, bool) { ln := len(visible) idx := sort.Search(ln, func(i int) bool { return visible[i].id >= id }) if idx < ln && visible[idx].id == id { @@ -784,7 +784,7 @@ func (l *listLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) } } -func (l *listLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { +func (l *listLayout) nilOldVisibleSliceData(objs []listItemAndID, len, oldLen int) { if oldLen > len { objs = objs[:oldLen] // gain view into old data for i := len; i < oldLen; i++ { From dafe4ba6f99d232b95d628d65dc7524f5da5dcf1 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 10 Dec 2023 15:08:24 +0400 Subject: [PATCH 124/248] If the keyboard is visible hide it instead of actually going back Fixes #4257 --- internal/driver/mobile/app/GoNativeActivity.java | 8 ++++++++ internal/driver/mobile/app/android.go | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/driver/mobile/app/GoNativeActivity.java b/internal/driver/mobile/app/GoNativeActivity.java index 5521b957ae..bb1c9b97c3 100644 --- a/internal/driver/mobile/app/GoNativeActivity.java +++ b/internal/driver/mobile/app/GoNativeActivity.java @@ -48,6 +48,7 @@ public class GoNativeActivity extends NativeActivity { private EditText mTextEdit; private boolean ignoreKey = false; + private boolean keyboardUp = false; public GoNativeActivity() { super(); @@ -79,6 +80,7 @@ void updateLayout() { static void showKeyboard(int keyboardType) { goNativeActivity.doShowKeyboard(keyboardType); + goNativeActivity.keyboardUp = true; } void doShowKeyboard(final int keyboardType) { @@ -135,6 +137,7 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { static void hideKeyboard() { goNativeActivity.doHideKeyboard(); + goNativeActivity.keyboardUp = false; } void doHideKeyboard() { @@ -316,6 +319,11 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { @Override public void onBackPressed() { + if (goNativeActivity.keyboardUp) { + hideKeyboard(); + return; + } + // skip the default behaviour - we can call finishActivity if we want to go back backPressed(); } diff --git a/internal/driver/mobile/app/android.go b/internal/driver/mobile/app/android.go index 24eb000330..dc874199db 100644 --- a/internal/driver/mobile/app/android.go +++ b/internal/driver/mobile/app/android.go @@ -142,7 +142,6 @@ func onBackPressed() { Code: key.CodeBackButton, Direction: key.DirPress, } - log.Println("Logging key event back") theApp.events.In() <- k k.Direction = key.DirRelease From 67c9b42be4a0c654d6f2210f0a4f16c7b0b898a3 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 17:48:44 -0800 Subject: [PATCH 125/248] don't allocate new children and objects slices every updateList --- widget/list.go | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/widget/list.go b/widget/list.go index 0aeb686c31..4e9a9e2eab 100644 --- a/widget/list.go +++ b/widget/list.go @@ -647,7 +647,8 @@ func (l *listLayout) updateList(newOnly bool) { } visible := make(map[ListItemID]*listItem, len(visibleRowHeights)) - cells := make([]fyne.CanvasObject, len(visibleRowHeights)) + oldChildrenLen := len(l.children) + l.children = l.children[:0] y := offY for index, itemHeight := range visibleRowHeights { @@ -668,7 +669,15 @@ func (l *listLayout) updateList(newOnly bool) { y += itemHeight + separatorThickness visible[row] = c - cells[index] = c + l.children = append(l.children, c) + } + if ln := len(l.children); oldChildrenLen > ln { + // nil out slice's unreferenced items + l.children = l.children[:oldChildrenLen] + for i := ln; i < oldChildrenLen; i++ { + l.children[i] = nil + } + l.children = l.children[:ln] } l.visible = visible @@ -678,13 +687,22 @@ func (l *listLayout) updateList(newOnly bool) { l.itemPool.Release(old) } } - l.children = cells l.updateSeparators() - objects := l.children - objects = append(objects, l.separators...) - l.list.scroller.Content.(*fyne.Container).Objects = objects + c := l.list.scroller.Content.(*fyne.Container) + oldObjLen := len(c.Objects) + c.Objects = c.Objects[:0] + c.Objects = append(c.Objects, l.children...) + c.Objects = append(c.Objects, l.separators...) + if ln := len(c.Objects); oldObjLen > ln { + // nil out slice's unreferenced items + c.Objects = c.Objects[:oldObjLen] + for i := ln; i < oldObjLen; i++ { + c.Objects[i] = nil + } + c.Objects = c.Objects[:ln] + } l.renderLock.Unlock() // user code should not be locked if newOnly { @@ -701,11 +719,11 @@ func (l *listLayout) updateList(newOnly bool) { } func (l *listLayout) updateSeparators() { - if len(l.children) > 1 { - if len(l.separators) > len(l.children) { - l.separators = l.separators[:len(l.children)] + if lenChildren := len(l.children); lenChildren > 1 { + if lenSep := len(l.separators); lenSep > lenChildren { + l.separators = l.separators[:lenChildren] } else { - for i := len(l.separators); i < len(l.children); i++ { + for i := lenSep; i < lenChildren; i++ { l.separators = append(l.separators, NewSeparator()) } } From 38eed72cd54ec41163f9a7287ae83b5ffde3a587 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 18:33:31 -0800 Subject: [PATCH 126/248] don't allocate a slice of visible row heights on every updateList --- widget/list.go | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/widget/list.go b/widget/list.go index 4e9a9e2eab..c314a38b86 100644 --- a/widget/list.go +++ b/widget/list.go @@ -318,24 +318,25 @@ func (l *List) UnselectAll() { } } -func (l *List) visibleItemHeights(itemHeight float32, length int) (visible []float32, offY float32, minRow int) { +// fills l.visibleRowHeights and also returns offY and minRow +func (l *listLayout) calculateVisibleRowHeights(itemHeight float32, length int) (offY float32, minRow int) { rowOffset := float32(0) isVisible := false - visible = []float32{} + l.visibleRowHeights = l.visibleRowHeights[:0] - if l.scroller.Size().Height <= 0 { + if l.list.scroller.Size().Height <= 0 { return } // theme.Padding is a slow call, so we cache it padding := theme.Padding() - if len(l.itemHeights) == 0 { + if len(l.list.itemHeights) == 0 { paddedItemHeight := itemHeight + padding - offY = float32(math.Floor(float64(l.offsetY/paddedItemHeight))) * paddedItemHeight + offY = float32(math.Floor(float64(l.list.offsetY/paddedItemHeight))) * paddedItemHeight minRow = int(math.Floor(float64(offY / paddedItemHeight))) - maxRow := int(math.Ceil(float64((offY + l.scroller.Size().Height) / paddedItemHeight))) + maxRow := int(math.Ceil(float64((offY + l.list.scroller.Size().Height) / paddedItemHeight))) if minRow > length-1 { minRow = length - 1 @@ -349,33 +350,32 @@ func (l *List) visibleItemHeights(itemHeight float32, length int) (visible []flo maxRow = length } - visible = make([]float32, maxRow-minRow) for i := 0; i < maxRow-minRow; i++ { - visible[i] = itemHeight + l.visibleRowHeights = append(l.visibleRowHeights, itemHeight) } return } for i := 0; i < length; i++ { height := itemHeight - if h, ok := l.itemHeights[i]; ok { + if h, ok := l.list.itemHeights[i]; ok { height = h } - if rowOffset <= l.offsetY-height-padding { + if rowOffset <= l.list.offsetY-height-padding { // before scroll - } else if rowOffset <= l.offsetY { + } else if rowOffset <= l.list.offsetY { minRow = i offY = rowOffset isVisible = true } - if rowOffset >= l.offsetY+l.scroller.Size().Height { + if rowOffset >= l.list.offsetY+l.list.scroller.Size().Height { break } rowOffset += height + padding if isVisible { - visible = append(visible, height) + l.visibleRowHeights = append(l.visibleRowHeights, height) } } return @@ -528,9 +528,10 @@ type listLayout struct { separators []fyne.CanvasObject children []fyne.CanvasObject - itemPool *syncPool - visible map[ListItemID]*listItem - renderLock sync.Mutex + itemPool *syncPool + visible map[ListItemID]*listItem + visibleRowHeights []float32 + renderLock sync.Mutex } func newListLayout(list *List) fyne.Layout { @@ -639,19 +640,19 @@ func (l *listLayout) updateList(newOnly bool) { wasVisible := l.visible l.list.propertyLock.Lock() - visibleRowHeights, offY, minRow := l.list.visibleItemHeights(l.list.itemMin.Height, length) + offY, minRow := l.calculateVisibleRowHeights(l.list.itemMin.Height, length) l.list.propertyLock.Unlock() - if len(visibleRowHeights) == 0 && length > 0 { // we can't show anything until we have some dimensions + if len(l.visibleRowHeights) == 0 && length > 0 { // we can't show anything until we have some dimensions l.renderLock.Unlock() // user code should not be locked return } - visible := make(map[ListItemID]*listItem, len(visibleRowHeights)) + visible := make(map[ListItemID]*listItem, len(l.visibleRowHeights)) oldChildrenLen := len(l.children) l.children = l.children[:0] y := offY - for index, itemHeight := range visibleRowHeights { + for index, itemHeight := range l.visibleRowHeights { row := index + minRow size := fyne.NewSize(width, itemHeight) From 35fb5c249b95ca454f6e6df56307d20a2d7a7006 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 19:35:11 -0800 Subject: [PATCH 127/248] don't allocate a new map for visible objects on every updateList --- widget/list.go | 97 +++++++++++++++++++++++++++++---------------- widget/list_test.go | 22 +++++----- 2 files changed, 75 insertions(+), 44 deletions(-) diff --git a/widget/list.go b/widget/list.go index c314a38b86..e43b4c0aae 100644 --- a/widget/list.go +++ b/widget/list.go @@ -122,9 +122,8 @@ func (l *List) RefreshItem(id ListItemID) { } l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) - visible := lo.visible - if item, ok := visible[id]; ok { - lo.setupListItem(item, id, l.focused && l.currentFocus == id) + if idx := lo.searchVisible(lo.visible, id); idx >= 0 { + lo.setupListItem(lo.visible[idx].item, id, l.focused && l.currentFocus == id) } } @@ -523,19 +522,25 @@ func (li *listItemRenderer) Refresh() { // Declare conformity with Layout interface. var _ fyne.Layout = (*listLayout)(nil) +type itemAndID struct { + item *listItem + id ListItemID +} + type listLayout struct { list *List separators []fyne.CanvasObject children []fyne.CanvasObject itemPool *syncPool - visible map[ListItemID]*listItem + visible []itemAndID + wasVisible []itemAndID visibleRowHeights []float32 renderLock sync.Mutex } func newListLayout(list *List) fyne.Layout { - l := &listLayout{list: list, itemPool: &syncPool{}, visible: make(map[ListItemID]*listItem)} + l := &listLayout{list: list, itemPool: &syncPool{}} list.offsetUpdated = l.offsetUpdated return l } @@ -637,7 +642,11 @@ func (l *listLayout) updateList(newOnly bool) { fyne.LogError("Missing UpdateCell callback required for List", nil) } - wasVisible := l.visible + for i := 0; i < len(l.wasVisible); i++ { + l.wasVisible[i].item = nil + } + l.wasVisible = l.wasVisible[:0] + l.wasVisible = append(l.wasVisible, l.visible...) l.list.propertyLock.Lock() offY, minRow := l.calculateVisibleRowHeights(l.list.itemMin.Height, length) @@ -647,7 +656,8 @@ func (l *listLayout) updateList(newOnly bool) { return } - visible := make(map[ListItemID]*listItem, len(l.visibleRowHeights)) + oldVisibleLen := len(l.visible) + l.visible = l.visible[:0] oldChildrenLen := len(l.children) l.children = l.children[:0] @@ -656,36 +666,39 @@ func (l *listLayout) updateList(newOnly bool) { row := index + minRow size := fyne.NewSize(width, itemHeight) - c, ok := wasVisible[row] - if !ok { + visIdx := l.searchVisible(l.wasVisible, row) + var c *listItem + if visIdx < 0 { c = l.getItem() if c == nil { continue } c.Resize(size) + } else { + c = l.wasVisible[visIdx].item } c.Move(fyne.NewPos(0, y)) c.Resize(size) y += itemHeight + separatorThickness - visible[row] = c + l.visible = append(l.visible, itemAndID{id: row, item: c}) l.children = append(l.children, c) } - if ln := len(l.children); oldChildrenLen > ln { - // nil out slice's unreferenced items - l.children = l.children[:oldChildrenLen] - for i := ln; i < oldChildrenLen; i++ { - l.children[i] = nil + l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) + // nil out l.visible slice's unreferenced items + if ln := len(l.visible); oldVisibleLen > ln { + l.visible = l.visible[:oldVisibleLen] + for i := ln; i < oldVisibleLen; i++ { + l.visible[i].item = nil } - l.children = l.children[:ln] + l.visible = l.visible[:ln] } - l.visible = visible - - for id, old := range wasVisible { - if _, ok := l.visible[id]; !ok { - l.itemPool.Release(old) + for _, item := range l.wasVisible { + if idx := l.searchVisible(l.visible, item.id); idx < 0 { + l.itemPool.Release(item.item) + item.item = nil } } @@ -696,27 +709,25 @@ func (l *listLayout) updateList(newOnly bool) { c.Objects = c.Objects[:0] c.Objects = append(c.Objects, l.children...) c.Objects = append(c.Objects, l.separators...) - if ln := len(c.Objects); oldObjLen > ln { - // nil out slice's unreferenced items - c.Objects = c.Objects[:oldObjLen] - for i := ln; i < oldObjLen; i++ { - c.Objects[i] = nil - } - c.Objects = c.Objects[:ln] - } + l.nilOldSliceData(c.Objects, len(c.Objects), oldObjLen) l.renderLock.Unlock() // user code should not be locked if newOnly { - for row, obj := range visible { - if _, ok := wasVisible[row]; !ok { - l.setupListItem(obj, row, l.list.focused && l.list.currentFocus == row) + for _, item := range l.visible { + if idx := l.searchVisible(l.wasVisible, item.id); idx < 0 { + l.setupListItem(item.item, item.id, l.list.focused && l.list.currentFocus == item.id) } } } else { - for row, obj := range visible { - l.setupListItem(obj, row, l.list.focused && l.list.currentFocus == row) + for _, item := range l.visible { + l.setupListItem(item.item, item.id, l.list.focused && l.list.currentFocus == item.id) } } + + // we don't need wasVisible's data anymore; nil out all references + for i := 0; i < len(l.wasVisible); i++ { + l.wasVisible[i].item = nil + } } func (l *listLayout) updateSeparators() { @@ -743,3 +754,21 @@ func (l *listLayout) updateSeparators() { l.separators[i].Show() } } + +func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) int { + for i, v := range visible { + if v.id == id { + return i + } + } + return -1 +} + +func (l *listLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) { + if oldLen > len { + objs = objs[:oldLen] // gain view into old data + for i := len; i < oldLen; i++ { + objs[i] = nil + } + } +} diff --git a/widget/list_test.go b/widget/list_test.go index 99001bfc25..b97ae16178 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -275,22 +275,24 @@ func TestList_Select(t *testing.T) { assert.Equal(t, float32(0), list.offsetY) list.Select(50) assert.Equal(t, 988, int(list.offsetY)) - visible := list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible - assert.Equal(t, visible[50].background.FillColor, theme.SelectionColor()) - assert.True(t, visible[50].background.Visible()) + lo := list.scroller.Content.(*fyne.Container).Layout.(*listLayout) + visible50 := lo.visible[lo.searchVisible(lo.visible, 50)].item + assert.Equal(t, visible50.background.FillColor, theme.SelectionColor()) + assert.True(t, visible50.background.Visible()) list.Select(5) assert.Equal(t, 195, int(list.offsetY)) - visible = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible - assert.Equal(t, visible[5].background.FillColor, theme.SelectionColor()) - assert.True(t, visible[5].background.Visible()) + visible5 := lo.visible[lo.searchVisible(lo.visible, 5)].item + assert.Equal(t, visible5.background.FillColor, theme.SelectionColor()) + assert.True(t, visible5.background.Visible()) list.Select(6) assert.Equal(t, 195, int(list.offsetY)) - visible = list.scroller.Content.(*fyne.Container).Layout.(*listLayout).visible - assert.False(t, visible[5].background.Visible()) - assert.Equal(t, visible[6].background.FillColor, theme.SelectionColor()) - assert.True(t, visible[6].background.Visible()) + visible5 = lo.visible[lo.searchVisible(lo.visible, 5)].item + visible6 := lo.visible[lo.searchVisible(lo.visible, 6)].item + assert.False(t, visible5.background.Visible()) + assert.Equal(t, visible6.background.FillColor, theme.SelectionColor()) + assert.True(t, visible6.background.Visible()) } func TestList_Unselect(t *testing.T) { From 5059027ba436e70db137a10057a2c256b4ab267c Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 19:44:09 -0800 Subject: [PATCH 128/248] get rid of redundant data-nilling loop --- widget/list.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/widget/list.go b/widget/list.go index e43b4c0aae..cbde9bdb79 100644 --- a/widget/list.go +++ b/widget/list.go @@ -642,10 +642,7 @@ func (l *listLayout) updateList(newOnly bool) { fyne.LogError("Missing UpdateCell callback required for List", nil) } - for i := 0; i < len(l.wasVisible); i++ { - l.wasVisible[i].item = nil - } - l.wasVisible = l.wasVisible[:0] + l.wasVisible = l.wasVisible[:0] // data already nilled out at end of this func l.wasVisible = append(l.wasVisible, l.visible...) l.list.propertyLock.Lock() From 46b1446dd5449a2aa8361ba211a1a439926064d7 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 20:13:29 -0800 Subject: [PATCH 129/248] use binary search to search visible slices --- widget/list.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/widget/list.go b/widget/list.go index cbde9bdb79..e300e3fc98 100644 --- a/widget/list.go +++ b/widget/list.go @@ -752,10 +752,20 @@ func (l *listLayout) updateSeparators() { } } +// invariant: visible is in ascending order of IDs func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) int { - for i, v := range visible { - if v.id == id { - return i + // binary search + low := 0 + high := len(visible) - 1 + for low <= high { + mid := (low + high) / 2 + if visible[mid].id == id { + return mid + } + if visible[mid].id > id { + high = mid - 1 + } else { + low = mid + 1 } } return -1 From 5c66324083c934d6c3bfc4b8662b93d5b61a9ac5 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 20:16:53 -0800 Subject: [PATCH 130/248] use compact if statement --- widget/list.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/widget/list.go b/widget/list.go index e300e3fc98..489ccc72d3 100644 --- a/widget/list.go +++ b/widget/list.go @@ -663,16 +663,15 @@ func (l *listLayout) updateList(newOnly bool) { row := index + minRow size := fyne.NewSize(width, itemHeight) - visIdx := l.searchVisible(l.wasVisible, row) var c *listItem - if visIdx < 0 { + if idx := l.searchVisible(l.wasVisible, row); idx < 0 { c = l.getItem() if c == nil { continue } c.Resize(size) } else { - c = l.wasVisible[visIdx].item + c = l.wasVisible[idx].item } c.Move(fyne.NewPos(0, y)) From ec83bd165c83422445972994e4564ef4ce445d2c Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 20:41:52 -0800 Subject: [PATCH 131/248] change interface of searchVisible to match that of map --- widget/list.go | 34 ++++++++++++++++------------------ widget/list_test.go | 8 ++++---- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/widget/list.go b/widget/list.go index 489ccc72d3..d745841c33 100644 --- a/widget/list.go +++ b/widget/list.go @@ -122,8 +122,8 @@ func (l *List) RefreshItem(id ListItemID) { } l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) - if idx := lo.searchVisible(lo.visible, id); idx >= 0 { - lo.setupListItem(lo.visible[idx].item, id, l.focused && l.currentFocus == id) + if item, ok := lo.searchVisible(lo.visible, id); ok { + lo.setupListItem(item, id, l.focused && l.currentFocus == id) } } @@ -663,15 +663,13 @@ func (l *listLayout) updateList(newOnly bool) { row := index + minRow size := fyne.NewSize(width, itemHeight) - var c *listItem - if idx := l.searchVisible(l.wasVisible, row); idx < 0 { + c, ok := l.searchVisible(l.wasVisible, row) + if !ok { c = l.getItem() if c == nil { continue } c.Resize(size) - } else { - c = l.wasVisible[idx].item } c.Move(fyne.NewPos(0, y)) @@ -691,10 +689,10 @@ func (l *listLayout) updateList(newOnly bool) { l.visible = l.visible[:ln] } - for _, item := range l.wasVisible { - if idx := l.searchVisible(l.visible, item.id); idx < 0 { - l.itemPool.Release(item.item) - item.item = nil + for _, wasVis := range l.wasVisible { + if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { + l.itemPool.Release(wasVis.item) + wasVis.item = nil } } @@ -709,14 +707,14 @@ func (l *listLayout) updateList(newOnly bool) { l.renderLock.Unlock() // user code should not be locked if newOnly { - for _, item := range l.visible { - if idx := l.searchVisible(l.wasVisible, item.id); idx < 0 { - l.setupListItem(item.item, item.id, l.list.focused && l.list.currentFocus == item.id) + for _, vis := range l.visible { + if _, ok := l.searchVisible(l.wasVisible, vis.id); !ok { + l.setupListItem(vis.item, vis.id, l.list.focused && l.list.currentFocus == vis.id) } } } else { - for _, item := range l.visible { - l.setupListItem(item.item, item.id, l.list.focused && l.list.currentFocus == item.id) + for _, vis := range l.visible { + l.setupListItem(vis.item, vis.id, l.list.focused && l.list.currentFocus == vis.id) } } @@ -752,14 +750,14 @@ func (l *listLayout) updateSeparators() { } // invariant: visible is in ascending order of IDs -func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) int { +func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) (*listItem, bool) { // binary search low := 0 high := len(visible) - 1 for low <= high { mid := (low + high) / 2 if visible[mid].id == id { - return mid + return visible[mid].item, true } if visible[mid].id > id { high = mid - 1 @@ -767,7 +765,7 @@ func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) int { low = mid + 1 } } - return -1 + return nil, false } func (l *listLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) { diff --git a/widget/list_test.go b/widget/list_test.go index b97ae16178..9f109f6550 100644 --- a/widget/list_test.go +++ b/widget/list_test.go @@ -276,20 +276,20 @@ func TestList_Select(t *testing.T) { list.Select(50) assert.Equal(t, 988, int(list.offsetY)) lo := list.scroller.Content.(*fyne.Container).Layout.(*listLayout) - visible50 := lo.visible[lo.searchVisible(lo.visible, 50)].item + visible50, _ := lo.searchVisible(lo.visible, 50) assert.Equal(t, visible50.background.FillColor, theme.SelectionColor()) assert.True(t, visible50.background.Visible()) list.Select(5) assert.Equal(t, 195, int(list.offsetY)) - visible5 := lo.visible[lo.searchVisible(lo.visible, 5)].item + visible5, _ := lo.searchVisible(lo.visible, 5) assert.Equal(t, visible5.background.FillColor, theme.SelectionColor()) assert.True(t, visible5.background.Visible()) list.Select(6) assert.Equal(t, 195, int(list.offsetY)) - visible5 = lo.visible[lo.searchVisible(lo.visible, 5)].item - visible6 := lo.visible[lo.searchVisible(lo.visible, 6)].item + visible5, _ = lo.searchVisible(lo.visible, 5) + visible6, _ := lo.searchVisible(lo.visible, 6) assert.False(t, visible5.background.Visible()) assert.Equal(t, visible6.background.FillColor, theme.SelectionColor()) assert.True(t, visible6.background.Visible()) From 196927de3ab0407c026ffdd46df416d431cc0b8b Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Fri, 17 Nov 2023 20:45:03 -0800 Subject: [PATCH 132/248] get rid of redundant nilling --- widget/list.go | 1 - 1 file changed, 1 deletion(-) diff --git a/widget/list.go b/widget/list.go index d745841c33..bc85ea9dbf 100644 --- a/widget/list.go +++ b/widget/list.go @@ -692,7 +692,6 @@ func (l *listLayout) updateList(newOnly bool) { for _, wasVis := range l.wasVisible { if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { l.itemPool.Release(wasVis.item) - wasVis.item = nil } } From f1d6b2b1d7ae6ec1a3ab26a24018bb9a1552b3d8 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 18 Nov 2023 07:44:30 -0800 Subject: [PATCH 133/248] do less overall work by swapping l.visible and l.wasVisible at beginning of updateList --- widget/list.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/widget/list.go b/widget/list.go index bc85ea9dbf..0cb805feac 100644 --- a/widget/list.go +++ b/widget/list.go @@ -642,8 +642,13 @@ func (l *listLayout) updateList(newOnly bool) { fyne.LogError("Missing UpdateCell callback required for List", nil) } - l.wasVisible = l.wasVisible[:0] // data already nilled out at end of this func - l.wasVisible = append(l.wasVisible, l.visible...) + // Swap l.wasVisible and l.visible + // since l.wasVisible contains only nil references at this point, + // we don't need to overwrite old data if we fill l.visible to less than + // the previous length of l.wasVisible + tmp := l.wasVisible + l.wasVisible = l.visible + l.visible = tmp l.list.propertyLock.Lock() offY, minRow := l.calculateVisibleRowHeights(l.list.itemMin.Height, length) @@ -653,7 +658,6 @@ func (l *listLayout) updateList(newOnly bool) { return } - oldVisibleLen := len(l.visible) l.visible = l.visible[:0] oldChildrenLen := len(l.children) l.children = l.children[:0] @@ -680,14 +684,6 @@ func (l *listLayout) updateList(newOnly bool) { l.children = append(l.children, c) } l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) - // nil out l.visible slice's unreferenced items - if ln := len(l.visible); oldVisibleLen > ln { - l.visible = l.visible[:oldVisibleLen] - for i := ln; i < oldVisibleLen; i++ { - l.visible[i].item = nil - } - l.visible = l.visible[:ln] - } for _, wasVis := range l.wasVisible { if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { From 4c70de73dcbdfff7e276495f1f6a489aeb83cf5d Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 18 Nov 2023 09:14:33 -0800 Subject: [PATCH 134/248] use sort.Search instead of own binary search impl --- widget/list.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/widget/list.go b/widget/list.go index 0cb805feac..f4660ee6c9 100644 --- a/widget/list.go +++ b/widget/list.go @@ -3,6 +3,7 @@ package widget import ( "fmt" "math" + "sort" "sync" "fyne.io/fyne/v2" @@ -746,19 +747,10 @@ func (l *listLayout) updateSeparators() { // invariant: visible is in ascending order of IDs func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) (*listItem, bool) { - // binary search - low := 0 - high := len(visible) - 1 - for low <= high { - mid := (low + high) / 2 - if visible[mid].id == id { - return visible[mid].item, true - } - if visible[mid].id > id { - high = mid - 1 - } else { - low = mid + 1 - } + ln := len(visible) + idx := sort.Search(ln, func(i int) bool { return visible[i].id >= id }) + if idx < ln && visible[idx].id == id { + return visible[idx].item, true } return nil, false } From d2657d5d5b01d5ee761547b55b038300c04ef832 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 18 Nov 2023 10:18:16 -0800 Subject: [PATCH 135/248] add locking in RefreshItem --- widget/list.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/widget/list.go b/widget/list.go index f4660ee6c9..7e11fed705 100644 --- a/widget/list.go +++ b/widget/list.go @@ -123,7 +123,10 @@ func (l *List) RefreshItem(id ListItemID) { } l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*listLayout) - if item, ok := lo.searchVisible(lo.visible, id); ok { + lo.renderLock.RLock() // ensures we are not changing visible info in render code during the search + item, ok := lo.searchVisible(lo.visible, id) + lo.renderLock.RUnlock() + if ok { lo.setupListItem(item, id, l.focused && l.currentFocus == id) } } @@ -537,7 +540,7 @@ type listLayout struct { visible []itemAndID wasVisible []itemAndID visibleRowHeights []float32 - renderLock sync.Mutex + renderLock sync.RWMutex } func newListLayout(list *List) fyne.Layout { From 1546ac6a1b8613a216572b03cc7b166205e56749 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 9 Dec 2023 14:05:38 -0800 Subject: [PATCH 136/248] use sync.Pool and local copies of visible/wasVisible to avoid data races --- widget/list.go | 51 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/widget/list.go b/widget/list.go index 7e11fed705..5c24d0444c 100644 --- a/widget/list.go +++ b/widget/list.go @@ -536,15 +536,19 @@ type listLayout struct { separators []fyne.CanvasObject children []fyne.CanvasObject - itemPool *syncPool + itemPool syncPool visible []itemAndID - wasVisible []itemAndID + slicePool sync.Pool // *[]itemAndID visibleRowHeights []float32 renderLock sync.RWMutex } func newListLayout(list *List) fyne.Layout { - l := &listLayout{list: list, itemPool: &syncPool{}} + l := &listLayout{list: list} + l.slicePool.New = func() interface{} { + s := make([]itemAndID, 0) + return &s + } list.offsetUpdated = l.offsetUpdated return l } @@ -646,13 +650,11 @@ func (l *listLayout) updateList(newOnly bool) { fyne.LogError("Missing UpdateCell callback required for List", nil) } - // Swap l.wasVisible and l.visible - // since l.wasVisible contains only nil references at this point, - // we don't need to overwrite old data if we fill l.visible to less than - // the previous length of l.wasVisible - tmp := l.wasVisible - l.wasVisible = l.visible - l.visible = tmp + // Keep pointer reference for copying slice header when returning to the pool + // https://blog.mike.norgate.xyz/unlocking-go-slice-performance-navigating-sync-pool-for-enhanced-efficiency-7cb63b0b453e + wasVisiblePtr := l.slicePool.Get().(*[]itemAndID) + wasVisible := (*wasVisiblePtr)[:0] + wasVisible = append(wasVisible, l.visible...) l.list.propertyLock.Lock() offY, minRow := l.calculateVisibleRowHeights(l.list.itemMin.Height, length) @@ -671,7 +673,7 @@ func (l *listLayout) updateList(newOnly bool) { row := index + minRow size := fyne.NewSize(width, itemHeight) - c, ok := l.searchVisible(l.wasVisible, row) + c, ok := l.searchVisible(wasVisible, row) if !ok { c = l.getItem() if c == nil { @@ -689,7 +691,7 @@ func (l *listLayout) updateList(newOnly bool) { } l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) - for _, wasVis := range l.wasVisible { + for _, wasVis := range wasVisible { if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { l.itemPool.Release(wasVis.item) } @@ -703,24 +705,37 @@ func (l *listLayout) updateList(newOnly bool) { c.Objects = append(c.Objects, l.children...) c.Objects = append(c.Objects, l.separators...) l.nilOldSliceData(c.Objects, len(c.Objects), oldObjLen) + + // make a local deep copy of l.visible since rest of this function is unlocked + // and cannot safely access l.visible + visiblePtr := l.slicePool.Get().(*[]itemAndID) + visible := (*visiblePtr)[:0] + visible = append(visible, l.visible...) l.renderLock.Unlock() // user code should not be locked if newOnly { - for _, vis := range l.visible { - if _, ok := l.searchVisible(l.wasVisible, vis.id); !ok { + for _, vis := range visible { + if _, ok := l.searchVisible(wasVisible, vis.id); !ok { l.setupListItem(vis.item, vis.id, l.list.focused && l.list.currentFocus == vis.id) } } } else { - for _, vis := range l.visible { + for _, vis := range visible { l.setupListItem(vis.item, vis.id, l.list.focused && l.list.currentFocus == vis.id) } } - // we don't need wasVisible's data anymore; nil out all references - for i := 0; i < len(l.wasVisible); i++ { - l.wasVisible[i].item = nil + // nil out all references before returning slices to pool + for i := 0; i < len(wasVisible); i++ { + wasVisible[i].item = nil + } + for i := 0; i < len(visible); i++ { + visible[i].item = nil } + *wasVisiblePtr = wasVisible // Copy the stack header over to the heap + *visiblePtr = visible + l.slicePool.Put(wasVisiblePtr) + l.slicePool.Put(visiblePtr) } func (l *listLayout) updateSeparators() { From b6cd53a10a519ece7c14eae5839bb46e03d097a2 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 9 Dec 2023 15:58:10 -0800 Subject: [PATCH 137/248] make sure to nil out excess capacity in l.visible slice --- widget/list.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/widget/list.go b/widget/list.go index 5c24d0444c..80c63b63fd 100644 --- a/widget/list.go +++ b/widget/list.go @@ -664,6 +664,7 @@ func (l *listLayout) updateList(newOnly bool) { return } + oldVisibleLen := len(l.visible) l.visible = l.visible[:0] oldChildrenLen := len(l.children) l.children = l.children[:0] @@ -690,6 +691,7 @@ func (l *listLayout) updateList(newOnly bool) { l.children = append(l.children, c) } l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) + l.nilOldVisibleSliceData(l.visible, len(l.visible), oldVisibleLen) for _, wasVis := range wasVisible { if _, ok := l.searchVisible(l.visible, wasVis.id); !ok { @@ -781,3 +783,12 @@ func (l *listLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) } } } + +func (l *listLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { + if oldLen > len { + objs = objs[:oldLen] // gain view into old data + for i := len; i < oldLen; i++ { + objs[i].item = nil + } + } +} From 7b14fca98695ef9549552f5b9abd316974a2293e Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 9 Dec 2023 15:25:22 -0800 Subject: [PATCH 138/248] use reusable slices to keep track of visible/wasVisible --- widget/gridwrap.go | 109 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 26 deletions(-) diff --git a/widget/gridwrap.go b/widget/gridwrap.go index 8a782edd5e..b8cdab9a49 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -3,6 +3,7 @@ package widget import ( "fmt" "math" + "sort" "sync" "fyne.io/fyne/v2" @@ -137,8 +138,10 @@ func (l *GridWrap) RefreshItem(id GridWrapItemID) { } l.BaseWidget.Refresh() lo := l.scroller.Content.(*fyne.Container).Layout.(*gridWrapLayout) - visible := lo.visible - if item, ok := visible[id]; ok { + lo.renderLock.Lock() // ensures we are not changing visible info in render code during the search + item, ok := lo.searchVisible(lo.visible, id) + lo.renderLock.Unlock() + if ok { lo.setupGridItem(item, id, l.focused && l.currentFocus == id) } } @@ -461,17 +464,27 @@ func (gw *gridWrapItemRenderer) Refresh() { // Declare conformity with Layout interface. var _ fyne.Layout = (*gridWrapLayout)(nil) +type itemAndID struct { + item *gridWrapItem + id GridWrapItemID +} + type gridWrapLayout struct { list *GridWrap children []fyne.CanvasObject - itemPool *syncPool - visible map[GridWrapItemID]*gridWrapItem + itemPool syncPool + slicePool sync.Pool // *[]itemAndID + visible []itemAndID renderLock sync.Mutex } func newGridWrapLayout(list *GridWrap) fyne.Layout { - l := &gridWrapLayout{list: list, itemPool: &syncPool{}, visible: make(map[GridWrapItemID]*gridWrapItem)} + l := &gridWrapLayout{list: list} + l.slicePool.New = func() interface{} { + s := make([]itemAndID, 0) + return &s + } list.offsetUpdated = l.offsetUpdated return l } @@ -573,48 +586,92 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { fyne.LogError("Missing UpdateCell callback required for GridWrap", nil) } - wasVisible := l.visible - l.visible = make(map[GridWrapItemID]*gridWrapItem) + // Keep pointer reference for copying slice header when returning to the pool + // https://blog.mike.norgate.xyz/unlocking-go-slice-performance-navigating-sync-pool-for-enhanced-efficiency-7cb63b0b453e + wasVisiblePtr := l.slicePool.Get().(*[]itemAndID) + wasVisible := (*wasVisiblePtr)[:0] + wasVisible = append(wasVisible, l.visible...) + + oldVisibleLen := len(l.visible) + l.visible = l.visible[:0] + var cells []fyne.CanvasObject y := offY - curItem := minItem - for row := minRow; row <= maxRow && curItem <= maxItem; row++ { + curItemID := minItem + for row := minRow; row <= maxRow && curItemID <= maxItem; row++ { x := float32(0) - for col := 0; col < colCount && curItem <= maxItem; col++ { - c, ok := wasVisible[curItem] + for col := 0; col < colCount && curItemID <= maxItem; col++ { + item, ok := l.searchVisible(wasVisible, curItemID) if !ok { - c = l.getItem() - if c == nil { + item = l.getItem() + if item == nil { continue } - c.Resize(l.list.itemMin) + item.Resize(l.list.itemMin) } - c.Move(fyne.NewPos(x, y)) + item.Move(fyne.NewPos(x, y)) if refresh { - c.Resize(l.list.itemMin) + item.Resize(l.list.itemMin) } x += l.list.itemMin.Width + theme.Padding() - l.visible[curItem] = c - cells = append(cells, c) - curItem++ + l.visible = append(l.visible, itemAndID{item: item, id: curItemID}) + cells = append(cells, item) + curItemID++ } y += l.list.itemMin.Height + theme.Padding() } + l.nilOldVisibleSliceData(l.visible, len(l.visible), oldVisibleLen) - for id, old := range wasVisible { - if _, ok := l.visible[id]; !ok { - l.itemPool.Release(old) + for _, old := range wasVisible { + if _, ok := l.searchVisible(l.visible, old.id); !ok { + l.itemPool.Release(old.item) } } l.children = cells - objects := l.children - l.list.scroller.Content.(*fyne.Container).Objects = objects + l.list.scroller.Content.(*fyne.Container).Objects = l.children + + // make a local deep copy of l.visible since rest of this function is unlocked + // and cannot safely access l.visible + visiblePtr := l.slicePool.Get().(*[]itemAndID) + visible := (*visiblePtr)[:0] + visible = append(visible, l.visible...) l.renderLock.Unlock() // user code should not be locked - for row, obj := range l.visible { - l.setupGridItem(obj, row, l.list.focused && l.list.currentFocus == row) + for _, obj := range visible { + l.setupGridItem(obj.item, obj.id, l.list.focused && l.list.currentFocus == obj.id) + } + + // nil out all references before returning slices to pool + for i := 0; i < len(wasVisible); i++ { + wasVisible[i].item = nil + } + for i := 0; i < len(visible); i++ { + visible[i].item = nil + } + *wasVisiblePtr = wasVisible // Copy the stack header over to the heap + *visiblePtr = visible + l.slicePool.Put(wasVisiblePtr) + l.slicePool.Put(visiblePtr) +} + +// invariant: visible is in ascending order of IDs +func (l *gridWrapLayout) searchVisible(visible []itemAndID, id GridWrapItemID) (*gridWrapItem, bool) { + ln := len(visible) + idx := sort.Search(ln, func(i int) bool { return visible[i].id >= id }) + if idx < ln && visible[idx].id == id { + return visible[idx].item, true + } + return nil, false +} + +func (l *gridWrapLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { + if oldLen > len { + objs = objs[:oldLen] // gain view into old data + for i := len; i < oldLen; i++ { + objs[i].item = nil + } } } From 86cc22107e8febab38c3cc9bb5568b25075905b2 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 9 Dec 2023 19:20:00 -0800 Subject: [PATCH 139/248] reuse allocated mem from container.Objects slice --- widget/gridwrap.go | 22 +++++++++++++++------- widget/gridwrap_test.go | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/widget/gridwrap.go b/widget/gridwrap.go index b8cdab9a49..6b74976de7 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -470,8 +470,7 @@ type itemAndID struct { } type gridWrapLayout struct { - list *GridWrap - children []fyne.CanvasObject + list *GridWrap itemPool syncPool slicePool sync.Pool // *[]itemAndID @@ -595,7 +594,9 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { oldVisibleLen := len(l.visible) l.visible = l.visible[:0] - var cells []fyne.CanvasObject + c := l.list.scroller.Content.(*fyne.Container) + oldObjLen := len(c.Objects) + c.Objects = c.Objects[:0] y := offY curItemID := minItem for row := minRow; row <= maxRow && curItemID <= maxItem; row++ { @@ -617,11 +618,12 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { x += l.list.itemMin.Width + theme.Padding() l.visible = append(l.visible, itemAndID{item: item, id: curItemID}) - cells = append(cells, item) + c.Objects = append(c.Objects, item) curItemID++ } y += l.list.itemMin.Height + theme.Padding() } + l.nilOldSliceData(c.Objects, len(c.Objects), oldObjLen) l.nilOldVisibleSliceData(l.visible, len(l.visible), oldVisibleLen) for _, old := range wasVisible { @@ -629,9 +631,6 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { l.itemPool.Release(old.item) } } - l.children = cells - - l.list.scroller.Content.(*fyne.Container).Objects = l.children // make a local deep copy of l.visible since rest of this function is unlocked // and cannot safely access l.visible @@ -667,6 +666,15 @@ func (l *gridWrapLayout) searchVisible(visible []itemAndID, id GridWrapItemID) ( return nil, false } +func (l *gridWrapLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) { + if oldLen > len { + objs = objs[:oldLen] // gain view into old data + for i := len; i < oldLen; i++ { + objs[i] = nil + } + } +} + func (l *gridWrapLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { if oldLen > len { objs = objs[:oldLen] // gain view into old data diff --git a/widget/gridwrap_test.go b/widget/gridwrap_test.go index 238389e5ed..af8fe03b2c 100644 --- a/widget/gridwrap_test.go +++ b/widget/gridwrap_test.go @@ -23,7 +23,7 @@ func TestGridWrap_Focus(t *testing.T) { assert.NotNil(t, canvas.Focused()) assert.Equal(t, 0, canvas.Focused().(*GridWrap).currentFocus) - children := list.scroller.Content.(*fyne.Container).Layout.(*gridWrapLayout).children + children := list.scroller.Content.(*fyne.Container).Objects assert.True(t, children[0].(*gridWrapItem).hovered) assert.False(t, children[1].(*gridWrapItem).hovered) assert.False(t, children[6].(*gridWrapItem).hovered) @@ -182,7 +182,7 @@ func TestGridWrap_RefreshItem(t *testing.T) { data[2] = "Replace" list.RefreshItem(2) - children := list.scroller.Content.(*fyne.Container).Layout.(*gridWrapLayout).children + children := list.scroller.Content.(*fyne.Container).Objects assert.Equal(t, children[1].(*gridWrapItem).child.(*Label).Text, "Text") assert.Equal(t, children[2].(*gridWrapItem).child.(*Label).Text, "Replace") } From 5815f7baf1637c81565206c5210aedbd5b74b3ca Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 10 Dec 2023 07:55:56 -0800 Subject: [PATCH 140/248] typo fix --- widget/gridwrap.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/gridwrap.go b/widget/gridwrap.go index 6b74976de7..1bd25e8311 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -650,7 +650,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { for i := 0; i < len(visible); i++ { visible[i].item = nil } - *wasVisiblePtr = wasVisible // Copy the stack header over to the heap + *wasVisiblePtr = wasVisible // Copy the slice header over to the heap *visiblePtr = visible l.slicePool.Put(wasVisiblePtr) l.slicePool.Put(visiblePtr) From 175af0240c87c99fa167c715855d49b05a651177 Mon Sep 17 00:00:00 2001 From: Dorbmon Date: Sun, 17 Dec 2023 11:34:11 -0500 Subject: [PATCH 141/248] fix conflicts name of structure itemAndID under the same package --- widget/gridwrap.go | 16 ++++++++-------- widget/list.go | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/widget/gridwrap.go b/widget/gridwrap.go index 1bd25e8311..0221c9bb08 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -464,7 +464,7 @@ func (gw *gridWrapItemRenderer) Refresh() { // Declare conformity with Layout interface. var _ fyne.Layout = (*gridWrapLayout)(nil) -type itemAndID struct { +type gridItemAndID struct { item *gridWrapItem id GridWrapItemID } @@ -474,14 +474,14 @@ type gridWrapLayout struct { itemPool syncPool slicePool sync.Pool // *[]itemAndID - visible []itemAndID + visible []gridItemAndID renderLock sync.Mutex } func newGridWrapLayout(list *GridWrap) fyne.Layout { l := &gridWrapLayout{list: list} l.slicePool.New = func() interface{} { - s := make([]itemAndID, 0) + s := make([]gridItemAndID, 0) return &s } list.offsetUpdated = l.offsetUpdated @@ -587,7 +587,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { // Keep pointer reference for copying slice header when returning to the pool // https://blog.mike.norgate.xyz/unlocking-go-slice-performance-navigating-sync-pool-for-enhanced-efficiency-7cb63b0b453e - wasVisiblePtr := l.slicePool.Get().(*[]itemAndID) + wasVisiblePtr := l.slicePool.Get().(*[]gridItemAndID) wasVisible := (*wasVisiblePtr)[:0] wasVisible = append(wasVisible, l.visible...) @@ -617,7 +617,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { } x += l.list.itemMin.Width + theme.Padding() - l.visible = append(l.visible, itemAndID{item: item, id: curItemID}) + l.visible = append(l.visible, gridItemAndID{item: item, id: curItemID}) c.Objects = append(c.Objects, item) curItemID++ } @@ -634,7 +634,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { // make a local deep copy of l.visible since rest of this function is unlocked // and cannot safely access l.visible - visiblePtr := l.slicePool.Get().(*[]itemAndID) + visiblePtr := l.slicePool.Get().(*[]gridItemAndID) visible := (*visiblePtr)[:0] visible = append(visible, l.visible...) l.renderLock.Unlock() // user code should not be locked @@ -657,7 +657,7 @@ func (l *gridWrapLayout) updateGrid(refresh bool) { } // invariant: visible is in ascending order of IDs -func (l *gridWrapLayout) searchVisible(visible []itemAndID, id GridWrapItemID) (*gridWrapItem, bool) { +func (l *gridWrapLayout) searchVisible(visible []gridItemAndID, id GridWrapItemID) (*gridWrapItem, bool) { ln := len(visible) idx := sort.Search(ln, func(i int) bool { return visible[i].id >= id }) if idx < ln && visible[idx].id == id { @@ -675,7 +675,7 @@ func (l *gridWrapLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen i } } -func (l *gridWrapLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { +func (l *gridWrapLayout) nilOldVisibleSliceData(objs []gridItemAndID, len, oldLen int) { if oldLen > len { objs = objs[:oldLen] // gain view into old data for i := len; i < oldLen; i++ { diff --git a/widget/list.go b/widget/list.go index 80c63b63fd..23636edbb2 100644 --- a/widget/list.go +++ b/widget/list.go @@ -526,7 +526,7 @@ func (li *listItemRenderer) Refresh() { // Declare conformity with Layout interface. var _ fyne.Layout = (*listLayout)(nil) -type itemAndID struct { +type listItemAndID struct { item *listItem id ListItemID } @@ -537,7 +537,7 @@ type listLayout struct { children []fyne.CanvasObject itemPool syncPool - visible []itemAndID + visible []listItemAndID slicePool sync.Pool // *[]itemAndID visibleRowHeights []float32 renderLock sync.RWMutex @@ -546,7 +546,7 @@ type listLayout struct { func newListLayout(list *List) fyne.Layout { l := &listLayout{list: list} l.slicePool.New = func() interface{} { - s := make([]itemAndID, 0) + s := make([]listItemAndID, 0) return &s } list.offsetUpdated = l.offsetUpdated @@ -652,7 +652,7 @@ func (l *listLayout) updateList(newOnly bool) { // Keep pointer reference for copying slice header when returning to the pool // https://blog.mike.norgate.xyz/unlocking-go-slice-performance-navigating-sync-pool-for-enhanced-efficiency-7cb63b0b453e - wasVisiblePtr := l.slicePool.Get().(*[]itemAndID) + wasVisiblePtr := l.slicePool.Get().(*[]listItemAndID) wasVisible := (*wasVisiblePtr)[:0] wasVisible = append(wasVisible, l.visible...) @@ -687,7 +687,7 @@ func (l *listLayout) updateList(newOnly bool) { c.Resize(size) y += itemHeight + separatorThickness - l.visible = append(l.visible, itemAndID{id: row, item: c}) + l.visible = append(l.visible, listItemAndID{id: row, item: c}) l.children = append(l.children, c) } l.nilOldSliceData(l.children, len(l.children), oldChildrenLen) @@ -710,7 +710,7 @@ func (l *listLayout) updateList(newOnly bool) { // make a local deep copy of l.visible since rest of this function is unlocked // and cannot safely access l.visible - visiblePtr := l.slicePool.Get().(*[]itemAndID) + visiblePtr := l.slicePool.Get().(*[]listItemAndID) visible := (*visiblePtr)[:0] visible = append(visible, l.visible...) l.renderLock.Unlock() // user code should not be locked @@ -766,7 +766,7 @@ func (l *listLayout) updateSeparators() { } // invariant: visible is in ascending order of IDs -func (l *listLayout) searchVisible(visible []itemAndID, id ListItemID) (*listItem, bool) { +func (l *listLayout) searchVisible(visible []listItemAndID, id ListItemID) (*listItem, bool) { ln := len(visible) idx := sort.Search(ln, func(i int) bool { return visible[i].id >= id }) if idx < ln && visible[idx].id == id { @@ -784,7 +784,7 @@ func (l *listLayout) nilOldSliceData(objs []fyne.CanvasObject, len, oldLen int) } } -func (l *listLayout) nilOldVisibleSliceData(objs []itemAndID, len, oldLen int) { +func (l *listLayout) nilOldVisibleSliceData(objs []listItemAndID, len, oldLen int) { if oldLen > len { objs = objs[:oldLen] // gain view into old data for i := len; i < oldLen; i++ { From 48e9e6f3f45c871e0ef8528fef6f227dc94d6927 Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 6 Dec 2023 22:16:33 +0100 Subject: [PATCH 142/248] Reduce string allocations in mimetype code The code handling mimetypes was using strings.Split() to split the string and that allocates. We can use strings.IndexByte() to get an index and subslice instead. I also refactored some code to avoid duplicating mimetype split logic. The new internal/repository/mime package exists to avoid cycling imports. NOTE: The split logic is slightly different because a second / would be includes as part of the subtype now but as far as I can see from reading the spec (https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.21.html) it should not be a problem as the format is "mainType/subType;weight" so there should not be any more separators. --- internal/repository/mime/mime.go | 18 ++++++++++++++ internal/repository/mime/mime_test.go | 21 ++++++++++++++++ storage/filter.go | 35 ++++++++++----------------- storage/repository/uri.go | 8 ++++-- widget/fileicon.go | 14 +++-------- 5 files changed, 61 insertions(+), 35 deletions(-) create mode 100644 internal/repository/mime/mime.go create mode 100644 internal/repository/mime/mime_test.go diff --git a/internal/repository/mime/mime.go b/internal/repository/mime/mime.go new file mode 100644 index 0000000000..198698aaf7 --- /dev/null +++ b/internal/repository/mime/mime.go @@ -0,0 +1,18 @@ +package mime + +import ( + "strings" +) + +// Split spits the mimetype into its main type and subtype. +func Split(mimeTypeFull string) (mimeType, mimeSubType string) { + // Replace with strings.Cut() when Go 1.18 is our new base version. + separatorIndex := strings.IndexByte(mimeTypeFull, '/') + if separatorIndex == -1 || mimeTypeFull[separatorIndex+1:] == "" { + return "", "" // Empty or only one part. Ignore. + } + + mimeType = mimeTypeFull[:separatorIndex] + mimeSubType = mimeTypeFull[separatorIndex+1:] + return +} diff --git a/internal/repository/mime/mime_test.go b/internal/repository/mime/mime_test.go new file mode 100644 index 0000000000..5cedb2034a --- /dev/null +++ b/internal/repository/mime/mime_test.go @@ -0,0 +1,21 @@ +package mime + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSplitMimeType(t *testing.T) { + main, sub := Split("text/plain") + assert.Equal(t, "text", main) + assert.Equal(t, "plain", sub) + + main, sub = Split("text/") + assert.Empty(t, main) + assert.Empty(t, sub) + + main, sub = Split("") + assert.Empty(t, main) + assert.Empty(t, sub) +} diff --git a/storage/filter.go b/storage/filter.go index c6bec67c42..bcc9adac05 100644 --- a/storage/filter.go +++ b/storage/filter.go @@ -4,6 +4,7 @@ import ( "strings" "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/repository/mime" ) // FileFilter is an interface that can be implemented to provide a filter to a file dialog. @@ -42,18 +43,21 @@ func NewExtensionFileFilter(extensions []string) FileFilter { // Matches returns true if a file URI has one of the filtered mimetypes. func (mt *MimeTypeFileFilter) Matches(uri fyne.URI) bool { - mimeType, mimeSubType := splitMimeType(uri) + mimeType, mimeSubType := mime.Split(uri.MimeType()) for _, mimeTypeFull := range mt.MimeTypes { - mimeTypeSplit := strings.Split(mimeTypeFull, "/") - if len(mimeTypeSplit) <= 1 { + mType, mSubType := mime.Split(mimeTypeFull) + if mType == "" || mSubType == "" { continue } - mType := mimeTypeSplit[0] - mSubType := strings.Split(mimeTypeSplit[1], ";")[0] - if mType == mimeType { - if mSubType == mimeSubType || mSubType == "*" { - return true - } + + // Replace with strings.Cut() when Go 1.18 is our new base version. + subTypeSeparatorIndex := strings.IndexByte(mSubType, ';') + if subTypeSeparatorIndex != -1 { + mSubType = mSubType[:subTypeSeparatorIndex] + } + + if mType == mimeType && (mSubType == mimeSubType || mSubType == "*") { + return true } } return false @@ -64,16 +68,3 @@ func (mt *MimeTypeFileFilter) Matches(uri fyne.URI) bool { func NewMimeTypeFileFilter(mimeTypes []string) FileFilter { return &MimeTypeFileFilter{MimeTypes: mimeTypes} } - -func splitMimeType(uri fyne.URI) (mimeType, mimeSubType string) { - mimeTypeFull := uri.MimeType() - mimeTypeSplit := strings.Split(mimeTypeFull, "/") - if len(mimeTypeSplit) <= 1 { - mimeType, mimeSubType = "", "" - return - } - mimeType = mimeTypeSplit[0] - mimeSubType = mimeTypeSplit[1] - - return -} diff --git a/storage/repository/uri.go b/storage/repository/uri.go index bb07544dfb..44a5416b19 100644 --- a/storage/repository/uri.go +++ b/storage/repository/uri.go @@ -30,7 +30,6 @@ func (u *uri) Name() string { } func (u *uri) MimeType() string { - mimeTypeFull := mime.TypeByExtension(u.Extension()) if mimeTypeFull == "" { mimeTypeFull = "text/plain" @@ -50,7 +49,12 @@ func (u *uri) MimeType() string { } } - return strings.Split(mimeTypeFull, ";")[0] + // Replace with strings.Cut() when Go 1.18 is our new base version. + semicolonIndex := strings.IndexByte(mimeTypeFull, ';') + if semicolonIndex == -1 { + return mimeTypeFull + } + return mimeTypeFull[:semicolonIndex] } func (u *uri) Scheme() string { diff --git a/widget/fileicon.go b/widget/fileicon.go index 60041e481a..0ea2ea1833 100644 --- a/widget/fileicon.go +++ b/widget/fileicon.go @@ -1,10 +1,9 @@ package widget import ( - "strings" - "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/internal/repository/mime" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/storage" "fyne.io/fyne/v2/theme" @@ -99,7 +98,8 @@ func (i *FileIcon) lookupIcon(uri fyne.URI) fyne.Resource { return theme.FolderIcon() } - switch splitMimeType(uri) { + mainMimeType, _ := mime.Split(uri.MimeType()) + switch mainMimeType { case "application": return theme.FileApplicationIcon() case "audio": @@ -201,11 +201,3 @@ func trimmedExtension(uri fyne.URI) string { } return ext } - -func splitMimeType(uri fyne.URI) string { - mimeTypeSplit := strings.Split(uri.MimeType(), "/") - if len(mimeTypeSplit) <= 1 { - return "" - } - return mimeTypeSplit[0] -} From 1f3d1c1cfd30fea9e9e7861b4c9a540cd647d8af Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 6 Dec 2023 22:18:23 +0100 Subject: [PATCH 143/248] Remove unnecessary verbose import --- internal/repository/mime/mime.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/repository/mime/mime.go b/internal/repository/mime/mime.go index 198698aaf7..ef39897531 100644 --- a/internal/repository/mime/mime.go +++ b/internal/repository/mime/mime.go @@ -1,8 +1,6 @@ package mime -import ( - "strings" -) +import "strings" // Split spits the mimetype into its main type and subtype. func Split(mimeTypeFull string) (mimeType, mimeSubType string) { From 612eeb39ec279dbb450e422bcfa3d8a11d276434 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 5 Dec 2023 01:52:18 +0100 Subject: [PATCH 144/248] driver/glfw: Avoid calling slow functions twice in a row This avoids various cases where we were calling "slow" (C-calls for glfw or locking mutexes) functions multiple times in a row. Lets save the value and use it instead. --- internal/driver/glfw/canvas.go | 3 ++- internal/driver/glfw/window.go | 33 +++++++++++++++----------- internal/driver/glfw/window_desktop.go | 2 +- internal/driver/mobile/window.go | 3 ++- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/internal/driver/glfw/canvas.go b/internal/driver/glfw/canvas.go index fbd294de54..d866245ba9 100644 --- a/internal/driver/glfw/canvas.go +++ b/internal/driver/glfw/canvas.go @@ -95,8 +95,9 @@ func (c *glCanvas) Padded() bool { func (c *glCanvas) PixelCoordinateForPosition(pos fyne.Position) (int, int) { c.RLock() texScale := c.texScale + scale := c.scale c.RUnlock() - multiple := c.Scale() * texScale + multiple := scale * texScale scaleInt := func(x float32) int { return int(math.Round(float64(x * multiple))) } diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 540caf3fca..4c40388c6d 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -119,8 +119,9 @@ func (w *window) calculatedScale() float32 { } func (w *window) detectTextureScale() float32 { - winWidth, _ := w.view().GetSize() - texWidth, _ := w.view().GetFramebufferSize() + view := w.view() + winWidth, _ := view.GetSize() + texWidth, _ := view.GetFramebufferSize() return float32(texWidth) / float32(winWidth) } @@ -149,15 +150,16 @@ func (w *window) doShow() { w.viewLock.Lock() w.visible = true w.viewLock.Unlock() - w.view().SetTitle(w.title) + view := w.view() + view.SetTitle(w.title) if w.centered { w.doCenterOnScreen() // lastly center if that was requested } - w.view().Show() + view.Show() // save coordinates - w.xpos, w.ypos = w.view().GetPos() + w.xpos, w.ypos = view.GetPos() if w.fullScreen { // this does not work if called before viewport.Show() go func() { @@ -168,8 +170,8 @@ func (w *window) doShow() { }) // show top canvas element - if w.canvas.Content() != nil { - w.canvas.Content().Show() + if content := w.canvas.Content(); content != nil { + content.Show() runOnDraw(w, func() { w.driver.repaintWindow(w) @@ -192,8 +194,8 @@ func (w *window) Hide() { v.Hide() // hide top canvas element - if w.canvas.Content() != nil { - w.canvas.Content().Hide() + if content := w.canvas.Content(); content != nil { + content.Hide() } }) } @@ -214,8 +216,10 @@ func (w *window) Close() { w.closing = true w.viewLock.Unlock() w.viewport.SetShouldClose(true) + + painter := w.canvas.Painter() cache.RangeTexturesFor(w.canvas, func(obj fyne.CanvasObject) { - w.canvas.Painter().Free(obj) + painter.Free(obj) }) }) @@ -973,12 +977,13 @@ func (w *window) doShowAgain() { runOnMain(func() { // show top canvas element - if w.canvas.Content() != nil { - w.canvas.Content().Show() + if content := w.canvas.Content(); content != nil { + content.Show() } - w.view().SetPos(w.xpos, w.ypos) - w.view().Show() + view := w.view() + view.SetPos(w.xpos, w.ypos) + view.Show() w.viewLock.Lock() w.visible = true w.viewLock.Unlock() diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index d04fccd421..ae4dc2b899 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -279,7 +279,7 @@ func (w *window) getMonitorForWindow() *glfw.Monitor { if x > xOff || y > yOff { continue } - if x+monitor.GetVideoMode().Width <= xOff || y+monitor.GetVideoMode().Height <= yOff { + if videoMode := monitor.GetVideoMode(); x+videoMode.Width <= xOff || y+videoMode.Height <= yOff { continue } diff --git a/internal/driver/mobile/window.go b/internal/driver/mobile/window.go index 7d3128f251..4227f97374 100644 --- a/internal/driver/mobile/window.go +++ b/internal/driver/mobile/window.go @@ -161,8 +161,9 @@ func (w *window) Close() { d.windows = append(d.windows[:pos], d.windows[pos+1:]...) } + painter := w.canvas.Painter() cache.RangeTexturesFor(w.canvas, func(obj fyne.CanvasObject) { - w.canvas.Painter().Free(obj) + painter.Free(obj) }) w.canvas.WalkTrees(nil, func(node *common.RenderCacheNode, _ fyne.Position) { From 119a6ea4ff11719ca0965a35d4908af8ec604d77 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 5 Dec 2023 01:56:03 +0100 Subject: [PATCH 145/248] Pass function directly instead --- internal/driver/glfw/window.go | 5 +---- internal/driver/mobile/window.go | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 4c40388c6d..17e4bb340d 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -217,10 +217,7 @@ func (w *window) Close() { w.viewLock.Unlock() w.viewport.SetShouldClose(true) - painter := w.canvas.Painter() - cache.RangeTexturesFor(w.canvas, func(obj fyne.CanvasObject) { - painter.Free(obj) - }) + cache.RangeTexturesFor(w.canvas, w.canvas.Painter().Free) }) w.canvas.WalkTrees(nil, func(node *common.RenderCacheNode, _ fyne.Position) { diff --git a/internal/driver/mobile/window.go b/internal/driver/mobile/window.go index 4227f97374..c3ad9d03b2 100644 --- a/internal/driver/mobile/window.go +++ b/internal/driver/mobile/window.go @@ -161,10 +161,7 @@ func (w *window) Close() { d.windows = append(d.windows[:pos], d.windows[pos+1:]...) } - painter := w.canvas.Painter() - cache.RangeTexturesFor(w.canvas, func(obj fyne.CanvasObject) { - painter.Free(obj) - }) + cache.RangeTexturesFor(w.canvas, w.canvas.Painter().Free) w.canvas.WalkTrees(nil, func(node *common.RenderCacheNode, _ fyne.Position) { if wid, ok := node.Obj().(fyne.Widget); ok { From 0afc194e17ecef1359adca44328386630297b3f3 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 5 Dec 2023 02:00:40 +0100 Subject: [PATCH 146/248] driver/common: Hoist nil check out of loop and pass function directly --- internal/driver/common/canvas.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/internal/driver/common/canvas.go b/internal/driver/common/canvas.go index ef22c29ee6..c70c0f13ff 100644 --- a/internal/driver/common/canvas.go +++ b/internal/driver/common/canvas.go @@ -283,11 +283,9 @@ func (c *Canvas) FreeDirtyTextures() (freed uint64) { } } - cache.RangeExpiredTexturesFor(c.impl, func(obj fyne.CanvasObject) { - if c.painter != nil { - c.painter.Free(obj) - } - }) + if c.painter != nil { + cache.RangeExpiredTexturesFor(c.impl, c.painter.Free) + } return } From eab2b94bca4e9b2232c12782c814063b22d7cad6 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 23:20:43 +0100 Subject: [PATCH 147/248] Fix *BSD systems using the wrong (and slow) window resize --- internal/driver/glfw/{window_notlinux.go => window_notxdg.go} | 4 ++-- internal/driver/glfw/{window_linux.go => window_xdg.go} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename internal/driver/glfw/{window_notlinux.go => window_notxdg.go} (81%) rename internal/driver/glfw/{window_linux.go => window_xdg.go} (100%) diff --git a/internal/driver/glfw/window_notlinux.go b/internal/driver/glfw/window_notxdg.go similarity index 81% rename from internal/driver/glfw/window_notlinux.go rename to internal/driver/glfw/window_notxdg.go index ed30559c3b..6c693bf2ef 100644 --- a/internal/driver/glfw/window_notlinux.go +++ b/internal/driver/glfw/window_notxdg.go @@ -1,5 +1,5 @@ -//go:build !linux -// +build !linux +//go:build !linux && !freebsd && !openbsd && !netbsd +// +build !linux,!freebsd,!openbsd,!netbsd package glfw diff --git a/internal/driver/glfw/window_linux.go b/internal/driver/glfw/window_xdg.go similarity index 100% rename from internal/driver/glfw/window_linux.go rename to internal/driver/glfw/window_xdg.go From 425c30e04fea330f9081dd697e6f8a28dc538dfe Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 21 Nov 2023 23:36:08 +0100 Subject: [PATCH 148/248] Try to make the buildtag work on not unix --- internal/driver/glfw/window_xdg.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/driver/glfw/window_xdg.go b/internal/driver/glfw/window_xdg.go index 9d56dd06a4..a8f4331a8a 100644 --- a/internal/driver/glfw/window_xdg.go +++ b/internal/driver/glfw/window_xdg.go @@ -1,3 +1,6 @@ +//go:build linux || freebsd || openbsd || netbsd +// +build linux freebsd openbsd netbsd + package glfw import "fyne.io/fyne/v2" From 14d724787c0d65cd6bf41784f39f97f50337e8bf Mon Sep 17 00:00:00 2001 From: Nikola Ubavic <53820106+ubavic@users.noreply.github.com> Date: Sat, 18 Nov 2023 18:10:03 +0100 Subject: [PATCH 149/248] Fix comment on theme variants --- theme/theme.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/theme.go b/theme/theme.go index 0d7af723b9..6f8ed78745 100644 --- a/theme/theme.go +++ b/theme/theme.go @@ -10,12 +10,12 @@ import ( ) const ( - // VariantDark is the version of a theme that satisfies a user preference for a light look. + // VariantDark is the version of a theme that satisfies a user preference for a dark look. // // Since: 2.0 VariantDark fyne.ThemeVariant = 0 - // VariantLight is the version of a theme that satisfies a user preference for a dark look. + // VariantLight is the version of a theme that satisfies a user preference for a light look. // // Since: 2.0 VariantLight fyne.ThemeVariant = 1 From f83e221075e2cdce356714ea3f5919e24350217c Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 18 Nov 2023 17:30:13 +0100 Subject: [PATCH 150/248] Cache some sizes to local variables in internal/painter --- internal/painter/draw.go | 23 +++++++++++++---------- internal/painter/image.go | 9 +++++---- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/internal/painter/draw.go b/internal/painter/draw.go index 127ee57737..e1d30b8c19 100644 --- a/internal/painter/draw.go +++ b/internal/painter/draw.go @@ -46,20 +46,22 @@ func DrawCircle(circle *canvas.Circle, vectorPad float32, scale func(float32) fl // The scale function is used to understand how many pixels are required per unit of size. func DrawLine(line *canvas.Line, vectorPad float32, scale func(float32) float32) *image.RGBA { col := line.StrokeColor - width := int(scale(line.Size().Width + vectorPad*2)) - height := int(scale(line.Size().Height + vectorPad*2)) + size := line.Size() + width := int(scale(size.Width + vectorPad*2)) + height := int(scale(size.Height + vectorPad*2)) stroke := scale(line.StrokeWidth) if stroke < 1 { // software painter doesn't fade lines to compensate stroke = 1 } raw := image.NewRGBA(image.Rect(0, 0, width, height)) - scanner := rasterx.NewScannerGV(int(line.Size().Width), int(line.Size().Height), raw, raw.Bounds()) + scanner := rasterx.NewScannerGV(int(size.Width), int(size.Height), raw, raw.Bounds()) dasher := rasterx.NewDasher(width, height, scanner) dasher.SetColor(col) dasher.SetStroke(fixed.Int26_6(float64(stroke)*64), 0, nil, nil, nil, 0, nil, 0) - p1x, p1y := scale(line.Position1.X-line.Position().X+vectorPad), scale(line.Position1.Y-line.Position().Y+vectorPad) - p2x, p2y := scale(line.Position2.X-line.Position().X+vectorPad), scale(line.Position2.Y-line.Position().Y+vectorPad) + positon := line.Position() + p1x, p1y := scale(line.Position1.X-positon.X+vectorPad), scale(line.Position1.Y-positon.Y+vectorPad) + p2x, p2y := scale(line.Position2.X-positon.X+vectorPad), scale(line.Position2.Y-positon.Y+vectorPad) if stroke <= 1.5 { // adjust to support 1px if p1x == p2x { @@ -84,17 +86,18 @@ func DrawLine(line *canvas.Line, vectorPad float32, scale func(float32) float32) // The bounds of the output image will be increased by vectorPad to allow for stroke overflow at the edges. // The scale function is used to understand how many pixels are required per unit of size. func DrawRectangle(rect *canvas.Rectangle, vectorPad float32, scale func(float32) float32) *image.RGBA { - width := int(scale(rect.Size().Width + vectorPad*2)) - height := int(scale(rect.Size().Height + vectorPad*2)) + size := rect.Size() + width := int(scale(size.Width + vectorPad*2)) + height := int(scale(size.Height + vectorPad*2)) stroke := scale(rect.StrokeWidth) raw := image.NewRGBA(image.Rect(0, 0, width, height)) - scanner := rasterx.NewScannerGV(int(rect.Size().Width), int(rect.Size().Height), raw, raw.Bounds()) + scanner := rasterx.NewScannerGV(int(size.Width), int(size.Height), raw, raw.Bounds()) scaledPad := scale(vectorPad) p1x, p1y := scaledPad, scaledPad - p2x, p2y := scale(rect.Size().Width)+scaledPad, scaledPad - p3x, p3y := scale(rect.Size().Width)+scaledPad, scale(rect.Size().Height)+scaledPad + p2x, p2y := scale(size.Width)+scaledPad, scaledPad + p3x, p3y := scale(size.Width)+scaledPad, scale(size.Height)+scaledPad p4x, p4y := scaledPad, scale(rect.Size().Height)+scaledPad if rect.FillColor != nil { diff --git a/internal/painter/image.go b/internal/painter/image.go index 13b81bc6e8..a9e2a8adb9 100644 --- a/internal/painter/image.go +++ b/internal/painter/image.go @@ -50,18 +50,19 @@ func scaleImage(pixels image.Image, scaledW, scaledH int, scale canvas.ImageScal return pixels } - pixW := int(fyne.Min(float32(scaledW), float32(pixels.Bounds().Dx()))) // don't push more pixels than we have to - pixH := int(fyne.Min(float32(scaledH), float32(pixels.Bounds().Dy()))) // the GL calls will scale this up on GPU. + bounds := pixels.Bounds() + pixW := int(fyne.Min(float32(scaledW), float32(bounds.Dx()))) // don't push more pixels than we have to + pixH := int(fyne.Min(float32(scaledH), float32(bounds.Dy()))) // the GL calls will scale this up on GPU. scaledBounds := image.Rect(0, 0, pixW, pixH) tex := image.NewNRGBA(scaledBounds) switch scale { case canvas.ImageScalePixels: - draw.NearestNeighbor.Scale(tex, scaledBounds, pixels, pixels.Bounds(), draw.Over, nil) + draw.NearestNeighbor.Scale(tex, scaledBounds, pixels, bounds, draw.Over, nil) default: if scale != canvas.ImageScaleSmooth { fyne.LogError("Invalid canvas.ImageScale value, using canvas.ImageScaleSmooth", nil) } - draw.CatmullRom.Scale(tex, scaledBounds, pixels, pixels.Bounds(), draw.Over, nil) + draw.CatmullRom.Scale(tex, scaledBounds, pixels, bounds, draw.Over, nil) } return tex } From 03e6d10af97554897d97e5ae770a5599bdfb04fc Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 18 Dec 2023 11:02:07 +0000 Subject: [PATCH 151/248] Prepping v2.4.3 --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 952c7d8323..41286ffbc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,17 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). -## 2.4.3 - Ongoing +## 2.4.3 - 22 December 2023 -### Fixes +### Fixed * Fix OpenGL init for arm64 desktop devices * System tray icon on Mac is showing the app ID (#4416) +* Failure with fyne release -os android/arm (#4174) +* Android GoBack with forcefully close the app even if the keyboard is up (#4257) +* *BSD systems using the wrong (and slow) window resize +* Optimisations to reduce memory allocations in List, GridWrap and mime type handling +* Reduce calls to C and repeated size checks in painter and driver code ## 2.4.2 - 21 November 2023 From fa3e65c403f69b7010e8788566f0c8b3076a023e Mon Sep 17 00:00:00 2001 From: Jacalz Date: Wed, 23 Aug 2023 13:38:07 +0200 Subject: [PATCH 152/248] Don't allocate a slice of windows 60 times per second We were allocating and appending to a slice 60 times per second to modify the window list if windows were supposed to close. This updates the runloop to keep track of how many windows need to be closed and only allocate a slice when we need to. Updates #2506 --- internal/driver/glfw/loop.go | 45 ++++++++++++++++++++-------------- internal/driver/glfw/window.go | 2 +- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/internal/driver/glfw/loop.go b/internal/driver/glfw/loop.go index 9098f39d01..bf16f98b6e 100644 --- a/internal/driver/glfw/loop.go +++ b/internal/driver/glfw/loop.go @@ -139,8 +139,7 @@ func (d *gLDriver) runGL() { } case <-eventTick.C: d.tryPollEvents() - newWindows := []fyne.Window{} - reassign := false + windowsToRemove := 0 for _, win := range d.windowList() { w := win.(*window) if w.viewport == nil { @@ -148,15 +147,7 @@ func (d *gLDriver) runGL() { } if w.viewport.ShouldClose() { - reassign = true - w.viewLock.Lock() - w.visible = false - v := w.viewport - w.viewLock.Unlock() - - // remove window from window list - v.Destroy() - w.destroy(d) + windowsToRemove++ continue } @@ -177,20 +168,38 @@ func (d *gLDriver) runGL() { } } - newWindows = append(newWindows, win) - if drawOnMainThread { d.drawSingleFrame() } } - if reassign { + if windowsToRemove > 0 { + oldWindows := d.windowList() + newWindows := make([]fyne.Window, 0, len(oldWindows)-windowsToRemove) + + for _, win := range oldWindows { + w := win.(*window) + if w.viewport == nil { + continue + } + + if w.viewport.ShouldClose() { + w.viewLock.Lock() + w.visible = false + v := w.viewport + w.viewLock.Unlock() + + // remove window from window list + v.Destroy() + w.destroy(d) + continue + } + + newWindows = append(newWindows, win) + } + d.windowLock.Lock() d.windows = newWindows d.windowLock.Unlock() - - if len(newWindows) == 0 { - d.Quit() - } } } } diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 17e4bb340d..111a15f293 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -284,7 +284,7 @@ func (w *window) destroy(d *gLDriver) { w.DestroyEventQueue() cache.CleanCanvas(w.canvas) - if w.master { + if w.master || len(w.driver.windowList()) == 1 { d.Quit() } else if runtime.GOOS == "darwin" { go d.focusPreviousWindow() From 6a9b848954d3c8c1a4f0a8c36131261c68e13368 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Thu, 14 Sep 2023 20:13:01 +0200 Subject: [PATCH 153/248] Restore old location for quit with no windows left --- internal/driver/glfw/loop.go | 4 ++++ internal/driver/glfw/window.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/driver/glfw/loop.go b/internal/driver/glfw/loop.go index bf16f98b6e..d7049ba2c0 100644 --- a/internal/driver/glfw/loop.go +++ b/internal/driver/glfw/loop.go @@ -200,6 +200,10 @@ func (d *gLDriver) runGL() { d.windowLock.Lock() d.windows = newWindows d.windowLock.Unlock() + + if len(newWindows) == 0 { + d.Quit() + } } } } diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 111a15f293..17e4bb340d 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -284,7 +284,7 @@ func (w *window) destroy(d *gLDriver) { w.DestroyEventQueue() cache.CleanCanvas(w.canvas) - if w.master || len(w.driver.windowList()) == 1 { + if w.master { d.Quit() } else if runtime.GOOS == "darwin" { go d.focusPreviousWindow() From d754ae1d9c1308f9001a19386e26de4d41a4ec6e Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Tue, 19 Dec 2023 10:45:41 +0000 Subject: [PATCH 154/248] Note more optimisations --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41286ffbc9..2420bb4b02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ More detailed release notes can be found on the [releases page](https://github.c * Failure with fyne release -os android/arm (#4174) * Android GoBack with forcefully close the app even if the keyboard is up (#4257) * *BSD systems using the wrong (and slow) window resize -* Optimisations to reduce memory allocations in List, GridWrap and mime type handling +* Optimisations to reduce memory allocations in List, GridWrap, driver and mime type handling * Reduce calls to C and repeated size checks in painter and driver code From f97c331d1ee622bf665c760ce81f4f88c5524097 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 20 Dec 2023 17:22:22 +0000 Subject: [PATCH 155/248] Add SetContent to InnerWindow --- container/innerwindow.go | 10 ++++++++-- container/innerwindow_test.go | 10 ++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/container/innerwindow.go b/container/innerwindow.go index ee522aa08b..639d940028 100644 --- a/container/innerwindow.go +++ b/container/innerwindow.go @@ -25,7 +25,7 @@ type InnerWindow struct { Icon fyne.Resource title string - content fyne.CanvasObject + content *fyne.Container } // NewInnerWindow creates a new window border around the given `content`, displaying the `title` along the top. @@ -33,7 +33,7 @@ type InnerWindow struct { // // Since: 2.5 func NewInnerWindow(title string, content fyne.CanvasObject) *InnerWindow { - w := &InnerWindow{title: title, content: content} + w := &InnerWindow{title: title, content: NewStack(content)} w.ExtendBaseWidget(w) return w } @@ -88,6 +88,12 @@ func (w *InnerWindow) CreateRenderer() fyne.WidgetRenderer { win: w, bar: bar, bg: bg, corner: corner, contentBG: contentBG} } +func (w *InnerWindow) SetContent(obj fyne.CanvasObject) { + w.content.Objects[0] = obj + + w.content.Refresh() +} + func (w *InnerWindow) SetTitle(title string) { w.title = title w.Refresh() diff --git a/container/innerwindow_test.go b/container/innerwindow_test.go index 51e87e6a5d..d9ae5033de 100644 --- a/container/innerwindow_test.go +++ b/container/innerwindow_test.go @@ -50,6 +50,16 @@ func TestInnerWindow_MinSize(t *testing.T) { assert.Equal(t, winMin, w2.MinSize()) } +func TestInnerWindow_SetContent(t *testing.T) { + w := NewInnerWindow("Title", widget.NewLabel("Content")) + r := cache.Renderer(w).(*innerWindowRenderer) + title := r.Objects()[4].(*fyne.Container) + assert.Equal(t, "Content", title.Objects[0].(*widget.Label).Text) + + w.SetContent(widget.NewLabel("Content2")) + assert.Equal(t, "Content2", title.Objects[0].(*widget.Label).Text) +} + func TestInnerWindow_SetTitle(t *testing.T) { w := NewInnerWindow("Title1", widget.NewLabel("Content")) r := cache.Renderer(w).(*innerWindowRenderer) From 14c4cf4ccccd17fc8d81ead7024beb3fc781e6a1 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 20 Dec 2023 18:02:19 +0000 Subject: [PATCH 156/248] Add padding to inner window by default, but allow it to be turned off like regular Window --- container/innerwindow.go | 12 +++++++++++- container/innerwindow_test.go | 15 +++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/container/innerwindow.go b/container/innerwindow.go index 639d940028..a72d07fe09 100644 --- a/container/innerwindow.go +++ b/container/innerwindow.go @@ -6,6 +6,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" intWidget "fyne.io/fyne/v2/internal/widget" + "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -33,7 +34,7 @@ type InnerWindow struct { // // Since: 2.5 func NewInnerWindow(title string, content fyne.CanvasObject) *InnerWindow { - w := &InnerWindow{title: title, content: NewStack(content)} + w := &InnerWindow{title: title, content: NewPadded(content)} w.ExtendBaseWidget(w) return w } @@ -94,6 +95,15 @@ func (w *InnerWindow) SetContent(obj fyne.CanvasObject) { w.content.Refresh() } +func (w *InnerWindow) SetPadded(pad bool) { + if pad { + w.content.Layout = layout.NewPaddedLayout() + } else { + w.content.Layout = layout.NewStackLayout() + } + w.content.Refresh() +} + func (w *InnerWindow) SetTitle(title string) { w.title = title w.Refresh() diff --git a/container/innerwindow_test.go b/container/innerwindow_test.go index d9ae5033de..463844f2fa 100644 --- a/container/innerwindow_test.go +++ b/container/innerwindow_test.go @@ -43,8 +43,8 @@ func TestInnerWindow_MinSize(t *testing.T) { labelMin := widget.NewLabel("Inner").MinSize() winMin := w.MinSize() - assert.Equal(t, btnMin.Height+labelMin.Height+theme.Padding()*2, winMin.Height) - assert.Greater(t, winMin.Width, btnMin.Width*3+theme.Padding()*3) + assert.Equal(t, btnMin.Height+labelMin.Height+theme.Padding()*4, winMin.Height) + assert.Greater(t, winMin.Width, btnMin.Width*3+theme.Padding()*5) w2 := NewInnerWindow("Much longer title that will truncate", widget.NewLabel("Content")) assert.Equal(t, winMin, w2.MinSize()) @@ -60,6 +60,17 @@ func TestInnerWindow_SetContent(t *testing.T) { assert.Equal(t, "Content2", title.Objects[0].(*widget.Label).Text) } +func TestInnerWindow_SetPadded(t *testing.T) { + w := NewInnerWindow("Title", widget.NewLabel("Content")) + minPadded := w.MinSize() + + w.SetPadded(false) + assert.Less(t, w.MinSize().Height, minPadded.Height) + + w.SetPadded(true) + assert.Equal(t, minPadded, w.MinSize()) +} + func TestInnerWindow_SetTitle(t *testing.T) { w := NewInnerWindow("Title1", widget.NewLabel("Content")) r := cache.Renderer(w).(*innerWindowRenderer) From 8cfd1ba92cfdfcbb154f0950c36ba08a549c2d0f Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 20 Dec 2023 18:03:10 +0000 Subject: [PATCH 157/248] Allow the `OnResized` to be updated after window creation... --- container/innerwindow.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/container/innerwindow.go b/container/innerwindow.go index a72d07fe09..1a028c8357 100644 --- a/container/innerwindow.go +++ b/container/innerwindow.go @@ -82,7 +82,7 @@ func (w *InnerWindow) CreateRenderer() fyne.WidgetRenderer { bar := NewBorder(nil, nil, buttons, icon, title) bg := canvas.NewRectangle(theme.OverlayBackgroundColor()) contentBG := canvas.NewRectangle(theme.BackgroundColor()) - corner := newDraggableCorner(w.OnResized) + corner := newDraggableCorner(w) objects := []fyne.CanvasObject{bg, contentBG, bar, corner, w.content} return &innerWindowRenderer{ShadowingRenderer: intWidget.NewShadowingRenderer(objects, intWidget.DialogLevel), @@ -197,11 +197,11 @@ func (d *draggableLabel) Tapped(ev *fyne.PointEvent) { type draggableCorner struct { widget.BaseWidget - drag func(*fyne.DragEvent) + win *InnerWindow } -func newDraggableCorner(fn func(*fyne.DragEvent)) *draggableCorner { - d := &draggableCorner{drag: fn} +func newDraggableCorner(w *InnerWindow) *draggableCorner { + d := &draggableCorner{win: w} d.ExtendBaseWidget(d) return d } @@ -213,8 +213,8 @@ func (c *draggableCorner) CreateRenderer() fyne.WidgetRenderer { } func (c *draggableCorner) Dragged(ev *fyne.DragEvent) { - if f := c.drag; f != nil { - c.drag(ev) + if f := c.win.OnResized; f != nil { + c.win.OnResized(ev) } } From cd66e3f65b8227a8fe37b9cf1622015e54bd7eff Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Thu, 21 Dec 2023 12:25:54 +0000 Subject: [PATCH 158/248] Add an icon to inner window corner that indicates it can be dragged. I did not add a new "theme.XxxIcon()" function as we are tending toward "theme.Current().Icon(Yyy)" for the 2.5 API --- container/innerwindow.go | 10 ++++------ theme/bundled-icons.go | 5 +++++ theme/gen.go | 2 ++ theme/icons.go | 7 +++++++ theme/icons/drag-corner-indicator.svg | 11 +++++++++++ 5 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 theme/icons/drag-corner-indicator.svg diff --git a/container/innerwindow.go b/container/innerwindow.go index 1a028c8357..19fec83d3d 100644 --- a/container/innerwindow.go +++ b/container/innerwindow.go @@ -1,8 +1,6 @@ package container import ( - "image/color" - "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" intWidget "fyne.io/fyne/v2/internal/widget" @@ -84,7 +82,7 @@ func (w *InnerWindow) CreateRenderer() fyne.WidgetRenderer { contentBG := canvas.NewRectangle(theme.BackgroundColor()) corner := newDraggableCorner(w) - objects := []fyne.CanvasObject{bg, contentBG, bar, corner, w.content} + objects := []fyne.CanvasObject{bg, contentBG, bar, w.content, corner} return &innerWindowRenderer{ShadowingRenderer: intWidget.NewShadowingRenderer(objects, intWidget.DialogLevel), win: w, bar: bar, bg: bg, corner: corner, contentBG: contentBG} } @@ -141,7 +139,7 @@ func (i *innerWindowRenderer) Layout(size fyne.Size) { i.win.content.Resize(innerSize) cornerSize := i.corner.MinSize() - i.corner.Move(pos.Add(size).Subtract(cornerSize)) + i.corner.Move(pos.Add(size).Subtract(cornerSize).AddXY(1, 1)) i.corner.Resize(cornerSize) } @@ -207,8 +205,8 @@ func newDraggableCorner(w *InnerWindow) *draggableCorner { } func (c *draggableCorner) CreateRenderer() fyne.WidgetRenderer { - prop := canvas.NewRectangle(color.Transparent) - prop.SetMinSize(fyne.NewSquareSize(20)) + prop := canvas.NewImageFromResource(fyne.CurrentApp().Settings().Theme().Icon(theme.IconNameDragCornerIndicator)) + prop.SetMinSize(fyne.NewSquareSize(16)) return widget.NewSimpleRenderer(prop) } diff --git a/theme/bundled-icons.go b/theme/bundled-icons.go index 71b4afd105..b4bf56f18f 100644 --- a/theme/bundled-icons.go +++ b/theme/bundled-icons.go @@ -145,6 +145,11 @@ var documentsaveIconRes = &fyne.StaticResource{ StaticContent: []byte(""), } +var dragcornerindicatorIconRes = &fyne.StaticResource{ + StaticName: "drag-corner-indicator.svg", + StaticContent: []byte("\n\n \n \n\n"), +} + var morehorizontalIconRes = &fyne.StaticResource{ StaticName: "more-horizontal.svg", StaticContent: []byte("\n \n"), diff --git a/theme/gen.go b/theme/gen.go index 45d3fab3d7..11a2cb50ba 100644 --- a/theme/gen.go +++ b/theme/gen.go @@ -122,6 +122,8 @@ func main() { bundleIcon("document-print", f) bundleIcon("document-save", f) + bundleIcon("drag-corner-indicator", f) + bundleIcon("more-horizontal", f) bundleIcon("more-vertical", f) diff --git a/theme/icons.go b/theme/icons.go index a7d17ec50a..cce59dfa70 100644 --- a/theme/icons.go +++ b/theme/icons.go @@ -161,6 +161,11 @@ const ( // Since: 2.0 IconNameDocumentSave fyne.ThemeIconName = "documentSave" + // IconNameDragCornerIndicator is the name of the icon used in inner windows to indicate a draggable corner. + // + // Since: 2.5 + IconNameDragCornerIndicator fyne.ThemeIconName = "dragCornerIndicator" + // IconNameMoreHorizontal is the name of theme lookup for horizontal more. // // Since 2.0 @@ -507,6 +512,8 @@ var ( IconNameDocumentPrint: NewThemedResource(documentprintIconRes), IconNameDocumentSave: NewThemedResource(documentsaveIconRes), + IconNameDragCornerIndicator: NewThemedResource(dragcornerindicatorIconRes), + IconNameMoreHorizontal: NewThemedResource(morehorizontalIconRes), IconNameMoreVertical: NewThemedResource(moreverticalIconRes), diff --git a/theme/icons/drag-corner-indicator.svg b/theme/icons/drag-corner-indicator.svg new file mode 100644 index 0000000000..11e8b56684 --- /dev/null +++ b/theme/icons/drag-corner-indicator.svg @@ -0,0 +1,11 @@ + + + + + From 28c057c46abaee090057011e0d24fbf46369365a Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 22 Dec 2023 15:57:51 +0000 Subject: [PATCH 159/248] Fix MinSize calculations in Form layout Fixes #4471 --- layout/formlayout.go | 3 ++- layout/formlayout_test.go | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/layout/formlayout.go b/layout/formlayout.go index 553b1164e1..280564fb43 100644 --- a/layout/formlayout.go +++ b/layout/formlayout.go @@ -42,6 +42,7 @@ func (f *formLayout) tableCellsSize(objects []fyne.CanvasObject, containerWidth } padding := theme.Padding() + innerPadding := theme.InnerPadding() lowBound := 0 highBound := 2 labelCellMaxWidth := float32(0) @@ -56,7 +57,7 @@ func (f *formLayout) tableCellsSize(objects []fyne.CanvasObject, containerWidth labelCell := currentRow[0].MinSize() if _, ok := currentRow[0].(*canvas.Text); ok { - labelCell.Width += padding * 4 + labelCell.Width += innerPadding * 2 } labelCellMaxWidth = fyne.Max(labelCellMaxWidth, labelCell.Width) diff --git a/layout/formlayout_test.go b/layout/formlayout_test.go index 5e8fbec78a..87570fd637 100644 --- a/layout/formlayout_test.go +++ b/layout/formlayout_test.go @@ -8,6 +8,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/theme" + "fyne.io/fyne/v2/widget" "github.com/stretchr/testify/assert" ) @@ -106,6 +107,13 @@ func TestFormLayout_MinSize(t *testing.T) { expectedRowWidth := 70 + 120 + theme.Padding() expectedRowHeight := 100 + 80 + theme.Padding() assert.Equal(t, fyne.NewSize(expectedRowWidth, expectedRowHeight), layoutMin) + + text := canvas.NewText("Text", color.Black) + value := widget.NewLabel("Text") + l = layout.NewFormLayout() + layoutMin = l.MinSize([]fyne.CanvasObject{text, value}) + // check that the text minsize is padded to match a label + assert.Equal(t, value.MinSize().Width*2+theme.Padding(), layoutMin.Width) } func TestFormLayout_MinSize_Hidden(t *testing.T) { From d88c07fece60c3185a05cced520ebbf6a0fb33cb Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 18 Oct 2023 20:36:07 +0200 Subject: [PATCH 160/248] Update to Go 1.19 as base and 1.21 as upper test version --- .github/workflows/mobile_tests.yml | 2 +- .github/workflows/platform_tests.yml | 2 +- .github/workflows/web_tests.yml | 2 +- go.mod | 2 +- go.sum | 42 ---------------------------- 5 files changed, 4 insertions(+), 46 deletions(-) diff --git a/.github/workflows/mobile_tests.yml b/.github/workflows/mobile_tests.yml index 0fce72d32e..0ad354fd77 100644 --- a/.github/workflows/mobile_tests.yml +++ b/.github/workflows/mobile_tests.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: ['1.17.x', '1.21.x'] + go-version: ['1.19.x', '1.21.x'] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/platform_tests.yml b/.github/workflows/platform_tests.yml index 0bd37d22ed..22ec944794 100644 --- a/.github/workflows/platform_tests.yml +++ b/.github/workflows/platform_tests.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: ['1.17.x', '1.21.x'] + go-version: ['1.19.x', '1.21.x'] os: [ubuntu-latest, windows-latest, macos-latest] include: - os: ubuntu-latest diff --git a/.github/workflows/web_tests.yml b/.github/workflows/web_tests.yml index 2f2e8f74dc..1de7dd832d 100644 --- a/.github/workflows/web_tests.yml +++ b/.github/workflows/web_tests.yml @@ -15,7 +15,7 @@ jobs: persist-credentials: false - uses: WillAbides/setup-go-faster@v1.8.0 with: - go-version: '1.17.x' + go-version: '1.19.x' - name: Get dependencies run: sudo apt-get update && sudo apt-get install gcc libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libx11-dev xorg-dev diff --git a/go.mod b/go.mod index dea38c8b9e..96ba346b4b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module fyne.io/fyne/v2 -go 1.17 +go 1.19 require ( fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e diff --git a/go.sum b/go.sum index b227b22fea..3e993faab9 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,7 +15,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -38,7 +36,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e h1:Hvs+kW2VwCzNToF3FmnIAzmivNgrclwPgoUdVSrjkP8= fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e/go.mod h1:oM2AQqGJ1AMo4nNqZFYU8xYygSBZkW2hmdJ7n4yjedE= @@ -94,7 +91,6 @@ github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2/go.mod h1:eO7W361vml github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 h1:zDw5v7qm4yH7N8C8uWd+8Ii9rROdgWxQuGoJ9WDXxfk= github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -108,7 +104,6 @@ github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8/go.mod h1:h29xCucjN github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a h1:VjN8ttdfklC0dnAdKbZqGNESdERUxtE3l8a/4Grgarc= github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a/go.mod h1:evDBbvNR/KaVFZ2ZlDSOWWXIUKq0wCOEtzLxRM8SG3k= github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22 h1:LBQTFxP2MfsyEDqSKmUBZaDuDHN1vpqDyOZjcqS7MYI= -github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -171,14 +166,12 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20211219123610-ec9572f70e60/go.mod h1:cz9oNYuRUWGdHmLF2IodMLkAhcPtXeULvcBNagUrxTI= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= @@ -253,9 +246,7 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -273,11 +264,9 @@ github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxr github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -285,12 +274,10 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= -github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -335,12 +322,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -354,8 +337,6 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.3.0/go.mod h1:fXd9211C/0VTlYuAcOhW8dY/RtEJqODXOWBDpmYBf+A= golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo= golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -420,19 +401,13 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -459,10 +434,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -477,7 +450,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -500,14 +472,12 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -517,18 +487,11 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -538,9 +501,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= @@ -596,7 +557,6 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -673,9 +633,7 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= From 142a9deeb4ad9ce1b9f4caec0efdbe629fcbe6c2 Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 18 Oct 2023 20:58:45 +0200 Subject: [PATCH 161/248] Update fredbi/uri to v1.1.0 for improved performance Requires Go 1.19 --- go.mod | 2 +- go.sum | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 96ba346b4b..5f953b9fc4 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e github.com/BurntSushi/toml v1.3.2 github.com/fogleman/gg v1.3.0 - github.com/fredbi/uri v1.0.0 + github.com/fredbi/uri v1.1.0 github.com/fsnotify/fsnotify v1.7.0 github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 diff --git a/go.sum b/go.sum index 3e993faab9..a620103eb4 100644 --- a/go.sum +++ b/go.sum @@ -75,10 +75,11 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fredbi/uri v1.0.0 h1:s4QwUAZ8fz+mbTsukND+4V5f+mJ/wjaTokwstGUAemg= -github.com/fredbi/uri v1.0.0/go.mod h1:1xC40RnIOGCaQzswaOvrzvG/3M3F0hyDVb3aO/1iGy0= +github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8= +github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= @@ -168,6 +169,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -246,6 +248,7 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -277,7 +280,6 @@ github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -285,7 +287,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -485,7 +486,6 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From edddb742796f4f9157cd75b2afb9c560379ef5fc Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 18 Oct 2023 21:10:36 +0200 Subject: [PATCH 162/248] Apply gofmt with Go 1.19 rules --- data/binding/gen.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/data/binding/gen.go b/data/binding/gen.go index 8e56d0c215..6b444a8ad6 100644 --- a/data/binding/gen.go +++ b/data/binding/gen.go @@ -1052,14 +1052,14 @@ import ( list := template.Must(template.New("list").Parse(listBindTemplate)) tree := template.Must(template.New("tree").Parse(treeBindTemplate)) binds := []bindValues{ - bindValues{Name: "Bool", Type: "bool", Default: "false", Format: "%t", SupportsPreferences: true}, - bindValues{Name: "Bytes", Type: "[]byte", Default: "nil", Since: "2.2", Comparator: "bytes.Equal"}, - bindValues{Name: "Float", Type: "float64", Default: "0.0", Format: "%f", SupportsPreferences: true}, - bindValues{Name: "Int", Type: "int", Default: "0", Format: "%d", SupportsPreferences: true}, - bindValues{Name: "Rune", Type: "rune", Default: "rune(0)"}, - bindValues{Name: "String", Type: "string", Default: "\"\"", SupportsPreferences: true}, - bindValues{Name: "Untyped", Type: "interface{}", Default: "nil", Since: "2.1"}, - bindValues{Name: "URI", Type: "fyne.URI", Default: "fyne.URI(nil)", Since: "2.1", + {Name: "Bool", Type: "bool", Default: "false", Format: "%t", SupportsPreferences: true}, + {Name: "Bytes", Type: "[]byte", Default: "nil", Since: "2.2", Comparator: "bytes.Equal"}, + {Name: "Float", Type: "float64", Default: "0.0", Format: "%f", SupportsPreferences: true}, + {Name: "Int", Type: "int", Default: "0", Format: "%d", SupportsPreferences: true}, + {Name: "Rune", Type: "rune", Default: "rune(0)"}, + {Name: "String", Type: "string", Default: "\"\"", SupportsPreferences: true}, + {Name: "Untyped", Type: "interface{}", Default: "nil", Since: "2.1"}, + {Name: "URI", Type: "fyne.URI", Default: "fyne.URI(nil)", Since: "2.1", FromString: "uriFromString", ToString: "uriToString", Comparator: "compareURI"}, } for _, b := range binds { From c7ce1125414e8d02323e03241c2be86db872a374 Mon Sep 17 00:00:00 2001 From: Jacob Date: Wed, 18 Oct 2023 21:16:55 +0200 Subject: [PATCH 163/248] Kill GopherJS from our tests --- .github/workflows/web_tests.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/web_tests.yml b/.github/workflows/web_tests.yml index 1de7dd832d..3a313606fb 100644 --- a/.github/workflows/web_tests.yml +++ b/.github/workflows/web_tests.yml @@ -27,8 +27,7 @@ jobs: working-directory: cmd/fyne_demo run: go build - - name: Build GopherJS and Wasm full website + - name: Build WASM full website run: | - go install github.com/gopherjs/gopherjs@latest go install ./cmd/fyne - cd cmd/fyne_demo && fyne package --target=web + cd cmd/fyne_demo && fyne package --target=wasm From eb7b0e4415dee1f69e3f13d0a6aaf9a3e9cf12da Mon Sep 17 00:00:00 2001 From: Jacalz Date: Sat, 23 Dec 2023 09:29:32 +0100 Subject: [PATCH 164/248] Run web tests on latest version as well --- .github/workflows/web_tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/web_tests.yml b/.github/workflows/web_tests.yml index 3a313606fb..2c04aebbbb 100644 --- a/.github/workflows/web_tests.yml +++ b/.github/workflows/web_tests.yml @@ -6,8 +6,11 @@ permissions: jobs: web_tests: runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false + matrix: + go-version: ['1.19.x', '1.21.x'] steps: - uses: actions/checkout@v3 @@ -15,7 +18,7 @@ jobs: persist-credentials: false - uses: WillAbides/setup-go-faster@v1.8.0 with: - go-version: '1.19.x' + go-version: ${{ matrix.go-version }} - name: Get dependencies run: sudo apt-get update && sudo apt-get install gcc libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libx11-dev xorg-dev From 000bc6ea30a18d4e4e4c46c2e7b6771e9b1370b7 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sat, 23 Dec 2023 16:00:56 +0000 Subject: [PATCH 165/248] Fix the date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2420bb4b02..88e625a8a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ This file lists the main changes with each version of the Fyne toolkit. More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases). -## 2.4.3 - 22 December 2023 +## 2.4.3 - 23 December 2023 ### Fixed From eb0c18e203fbb2c22c9442bb509727e73c987770 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sat, 23 Dec 2023 16:44:30 +0000 Subject: [PATCH 166/248] Fix naming --- cmd/fyne_demo/main.go | 4 ++-- cmd/fyne_demo/theme.go | 4 ++-- cmd/fyne_demo/theme_test.go | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cmd/fyne_demo/main.go b/cmd/fyne_demo/main.go index 4c91df8dac..e8fa759647 100644 --- a/cmd/fyne_demo/main.go +++ b/cmd/fyne_demo/main.go @@ -238,10 +238,10 @@ func makeNav(setTutorial func(tutorial tutorials.Tutorial), loadPrevious bool) f themes := container.NewGridWithColumns(2, widget.NewButton("Dark", func() { - a.Settings().SetTheme(&forceVariantTheme{Theme: theme.DefaultTheme(), variant: theme.VariantDark}) + a.Settings().SetTheme(&forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantDark}) }), widget.NewButton("Light", func() { - a.Settings().SetTheme(&forceVariantTheme{Theme: theme.DefaultTheme(), variant: theme.VariantLight}) + a.Settings().SetTheme(&forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantLight}) }), ) diff --git a/cmd/fyne_demo/theme.go b/cmd/fyne_demo/theme.go index 30ca28e0af..1e3241ca5e 100644 --- a/cmd/fyne_demo/theme.go +++ b/cmd/fyne_demo/theme.go @@ -6,12 +6,12 @@ import ( "fyne.io/fyne/v2" ) -type forceVariantTheme struct { +type forcedVariant struct { fyne.Theme variant fyne.ThemeVariant } -func (f *forceVariantTheme) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color { +func (f *forcedVariant) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color { return f.Theme.Color(name, f.variant) } diff --git a/cmd/fyne_demo/theme_test.go b/cmd/fyne_demo/theme_test.go index 9702db2407..24dd999cf9 100644 --- a/cmd/fyne_demo/theme_test.go +++ b/cmd/fyne_demo/theme_test.go @@ -3,14 +3,15 @@ package main import ( "testing" + "github.com/stretchr/testify/assert" + "fyne.io/fyne/v2" "fyne.io/fyne/v2/theme" - "github.com/stretchr/testify/assert" ) func TestForceVariantTheme_Color(t *testing.T) { - dark := &forceVariantTheme{Theme: theme.DefaultTheme(), variant: theme.VariantDark} - light := &forceVariantTheme{Theme: theme.DefaultTheme(), variant: theme.VariantLight} + dark := &forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantDark} + light := &forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantLight} unspecified := fyne.ThemeVariant(99) assert.Equal(t, theme.DefaultTheme().Color(theme.ColorNameForeground, theme.VariantDark), dark.Color(theme.ColorNameForeground, unspecified)) From 5680ae707f7f1e85e5e7171d7e2ba6ae44a8dc16 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Sat, 23 Dec 2023 22:51:48 +0100 Subject: [PATCH 167/248] Update glfw to 3.3.9 for many bug fixes and improved Wayland support --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dea38c8b9e..1ffd1738ae 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 - github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231124074035-2de0cf0c80af + github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7 github.com/go-ole/go-ole v1.2.6 github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a diff --git a/go.sum b/go.sum index b227b22fea..0d9a06ff7c 100644 --- a/go.sum +++ b/go.sum @@ -99,8 +99,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231124074035-2de0cf0c80af h1:zclgNFqP+NXDgGX2BiDvIonxKIom8j65wQlOyFtyujc= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231124074035-2de0cf0c80af/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7 h1:7tf/0aw5DxRQjr7WaNqgtjidub6v21L2cogKIbMcTYw= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 h1:VkKnvzbvHqgEfm351rfr8Uclu5fnwq8HP2ximUzJsBM= From 1d2c0c9d2f5c3301a05d018a1d1ab4c2ca90af27 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Sat, 23 Dec 2023 22:56:01 +0100 Subject: [PATCH 168/248] Drop various unsupported glfw calls on Wayland --- internal/driver/glfw/window.go | 11 +++++-- internal/driver/glfw/window_desktop.go | 40 ++++++++++++++++---------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index 427528fbbd..2fb7267a6e 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -10,6 +10,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/internal/app" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/driver" "fyne.io/fyne/v2/internal/driver/common" @@ -148,13 +149,15 @@ func (w *window) doShow() { view := w.view() view.SetTitle(w.title) - if w.centered { + if !build.IsWayland && w.centered { w.doCenterOnScreen() // lastly center if that was requested } view.Show() // save coordinates - w.xpos, w.ypos = view.GetPos() + if !build.IsWayland { + w.xpos, w.ypos = view.GetPos() + } if w.fullScreen { // this does not work if called before viewport.Show() go func() { @@ -973,7 +976,9 @@ func (w *window) doShowAgain() { } view := w.view() - view.SetPos(w.xpos, w.ypos) + if !build.IsWayland { + view.SetPos(w.xpos, w.ypos) + } view.Show() w.viewLock.Lock() w.visible = true diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index 5ee94ccdde..32779275e3 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -134,6 +134,10 @@ func (w *window) SetFullScreen(full bool) { } func (w *window) CenterOnScreen() { + if build.IsWayland { + return + } + w.centered = true if w.view() != nil { @@ -192,6 +196,10 @@ func (w *window) RequestFocus() { func (w *window) SetIcon(icon fyne.Resource) { w.icon = icon + if build.IsWayland { + return + } + if icon == nil { appIcon := fyne.CurrentApp().Icon() if appIcon != nil { @@ -265,24 +273,26 @@ func (w *window) fitContent() { } func (w *window) getMonitorForWindow() *glfw.Monitor { - x, y := w.xpos, w.ypos - if w.fullScreen { - x, y = w.viewport.GetPos() - } - xOff := x + (w.width / 2) - yOff := y + (w.height / 2) + if !build.IsWayland { + x, y := w.xpos, w.ypos + if w.fullScreen { + x, y = w.viewport.GetPos() + } + xOff := x + (w.width / 2) + yOff := y + (w.height / 2) - for _, monitor := range glfw.GetMonitors() { - x, y := monitor.GetPos() + for _, monitor := range glfw.GetMonitors() { + x, y := monitor.GetPos() - if x > xOff || y > yOff { - continue - } - if videoMode := monitor.GetVideoMode(); x+videoMode.Width <= xOff || y+videoMode.Height <= yOff { - continue - } + if x > xOff || y > yOff { + continue + } + if videoMode := monitor.GetVideoMode(); x+videoMode.Width <= xOff || y+videoMode.Height <= yOff { + continue + } - return monitor + return monitor + } } // try built-in function to detect monitor if above logic didn't succeed From e435f184c8cfbb820c21f4d14c06e4b5610bc437 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Sat, 23 Dec 2023 23:02:58 +0100 Subject: [PATCH 169/248] Remove glfw workarounds fixed in 3.3.9 --- internal/driver/glfw/window_desktop.go | 4 ---- internal/driver/glfw/window_goxjs.go | 4 ---- 2 files changed, 8 deletions(-) diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index 32779275e3..a4ec260645 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -592,10 +592,6 @@ func keyCodeToKeyName(code string) fyne.KeyName { } func keyToName(code glfw.Key, scancode int) fyne.KeyName { - if runtime.GOOS == "darwin" && scancode == 0x69 { // TODO remove once fixed upstream glfw/glfw#1786 - code = glfw.KeyPrintScreen - } - ret := glfwKeyToKeyName(code) if ret != fyne.KeyUnknown { return ret diff --git a/internal/driver/glfw/window_goxjs.go b/internal/driver/glfw/window_goxjs.go index a10d6be0b8..ebb8de7856 100644 --- a/internal/driver/glfw/window_goxjs.go +++ b/internal/driver/glfw/window_goxjs.go @@ -394,10 +394,6 @@ func keyCodeToKeyName(code string) fyne.KeyName { } func keyToName(code glfw.Key, scancode int) fyne.KeyName { - if runtime.GOOS == "darwin" && scancode == 0x69 { // TODO remove once fixed upstream glfw/glfw#1786 - code = glfw.KeyPrintScreen - } - ret := glfwKeyToKeyName(code) if ret != fyne.KeyUnknown { return ret From 3600f77ea8ef14c9eaf934a6000604b78026b54f Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 23 Dec 2023 15:40:44 -0800 Subject: [PATCH 170/248] make slider disableable --- cmd/fyne_demo/tutorials/widget.go | 5 ++- widget/slider.go | 64 ++++++++++++++++++++++++++++--- widget/slider_test.go | 23 +++++++++++ 3 files changed, 86 insertions(+), 6 deletions(-) diff --git a/cmd/fyne_demo/tutorials/widget.go b/cmd/fyne_demo/tutorials/widget.go index 3d58bbc9c7..d40738ece0 100644 --- a/cmd/fyne_demo/tutorials/widget.go +++ b/cmd/fyne_demo/tutorials/widget.go @@ -351,6 +351,8 @@ func makeInputTab(_ fyne.Window) fyne.CanvasObject { disabledRadio := widget.NewRadioGroup([]string{"Disabled radio"}, func(string) {}) disabledRadio.Disable() + disabledSlider := widget.NewSlider(0, 1000) + disabledSlider.Disable() return container.NewVBox( widget.NewSelect([]string{"Option 1", "Option 2", "Option 3"}, func(s string) { fmt.Println("selected", s) }), selectEntry, @@ -359,7 +361,8 @@ func makeInputTab(_ fyne.Window) fyne.CanvasObject { checkGroup, radio, disabledRadio, - widget.NewSlider(0, 1000), + container.NewBorder(nil, nil, widget.NewLabel("Slider"), nil, widget.NewSlider(0, 1000)), + container.NewBorder(nil, nil, widget.NewLabel("Disabled slider"), nil, disabledSlider), ) } diff --git a/widget/slider.go b/widget/slider.go index d799c253a9..0918be700d 100644 --- a/widget/slider.go +++ b/widget/slider.go @@ -26,6 +26,7 @@ var _ fyne.Draggable = (*Slider)(nil) var _ fyne.Focusable = (*Slider)(nil) var _ desktop.Hoverable = (*Slider)(nil) var _ fyne.Tappable = (*Slider)(nil) +var _ fyne.Disableable = (*Slider)(nil) // Slider is a widget that can slide between two fixed values. type Slider struct { @@ -45,6 +46,7 @@ type Slider struct { binder basicBinder hovered bool focused bool + disabled bool // don't use DisableableWidget so we can put Since comments on funcs pendingChange bool // true if value changed since last OnChangeEnded } @@ -87,11 +89,16 @@ func (s *Slider) Bind(data binding.Float) { // DragEnd is called when the drag ends. func (s *Slider) DragEnd() { - s.fireChangeEnded() + if !s.disabled { + s.fireChangeEnded() + } } // DragEnd is called when a drag event occurs. func (s *Slider) Dragged(e *fyne.DragEvent) { + if s.disabled { + return + } ratio := s.getRatio(&e.PointEvent) lastValue := s.Value @@ -147,6 +154,9 @@ func (s *Slider) fireChangeEnded() { // // Since: 2.4 func (s *Slider) FocusGained() { + if s.disabled { + return + } s.focused = true s.Refresh() } @@ -155,6 +165,9 @@ func (s *Slider) FocusGained() { // // Since: 2.4 func (s *Slider) FocusLost() { + if s.disabled { + return + } s.focused = false s.Refresh() } @@ -163,6 +176,9 @@ func (s *Slider) FocusLost() { // // Since: 2.4 func (s *Slider) MouseIn(_ *desktop.MouseEvent) { + if s.disabled { + return + } s.hovered = true s.Refresh() } @@ -177,6 +193,9 @@ func (s *Slider) MouseMoved(_ *desktop.MouseEvent) { // // Since: 2.4 func (s *Slider) MouseOut() { + if s.disabled { + return + } s.hovered = false s.Refresh() } @@ -185,6 +204,9 @@ func (s *Slider) MouseOut() { // // Since: 2.4 func (s *Slider) TypedKey(key *fyne.KeyEvent) { + if s.disabled { + return + } if s.Orientation == Vertical { switch key.Name { case fyne.KeyUp: @@ -293,6 +315,33 @@ func (s *Slider) MinSize() fyne.Size { return s.BaseWidget.MinSize() } +// Disable disables the slider +// +// Since: 2.5 +func (s *Slider) Disable() { + if !s.disabled { + defer s.Refresh() + } + s.disabled = true +} + +// Enable enables the slider +// +// Since: 2.5 +func (s *Slider) Enable() { + if s.disabled { + defer s.Refresh() + } + s.disabled = false +} + +// Disabled returns true if the slider is currently disabled +// +// Since: 2.5 +func (s *Slider) Disabled() bool { + return s.disabled +} + // CreateRenderer links this widget to its renderer. func (s *Slider) CreateRenderer() fyne.WidgetRenderer { s.ExtendBaseWidget(s) @@ -373,12 +422,17 @@ type sliderRenderer struct { // Refresh updates the widget state for drawing. func (s *sliderRenderer) Refresh() { s.track.FillColor = theme.InputBackgroundColor() - s.thumb.FillColor = theme.ForegroundColor() - s.active.FillColor = theme.ForegroundColor() + if s.slider.disabled { + s.thumb.FillColor = theme.DisabledColor() + s.active.FillColor = theme.DisabledColor() + } else { + s.thumb.FillColor = theme.ForegroundColor() + s.active.FillColor = theme.ForegroundColor() + } - if s.slider.focused { + if s.slider.focused && !s.slider.disabled { s.focusIndicator.FillColor = theme.FocusColor() - } else if s.slider.hovered { + } else if s.slider.hovered && !s.slider.disabled { s.focusIndicator.FillColor = theme.HoverColor() } else { s.focusIndicator.FillColor = color.Transparent diff --git a/widget/slider_test.go b/widget/slider_test.go index faf24a1b48..6a4bc26b29 100644 --- a/widget/slider_test.go +++ b/widget/slider_test.go @@ -310,3 +310,26 @@ func TestSlider_Focus(t *testing.T) { slider.TypedKey(down) assert.Equal(t, slider.Min, slider.Value) } + +func TestSlider_Disabled(t *testing.T) { + slider := NewSlider(0, 5) + slider.Disable() + + changes := 0 + slider.OnChanged = func(_ float64) { + changes++ + } + + drag := &fyne.DragEvent{} + drag.PointEvent.Position = fyne.NewPos(25, 2) + slider.Dragged(drag) + assert.Equal(t, 0, changes) + + slider.TypedKey(&fyne.KeyEvent{Name: fyne.KeyRight}) + assert.Equal(t, 0, changes) + + slider.Enable() + + slider.Dragged(drag) + assert.Equal(t, 1, changes) +} From 95ef04e9c7b3b087fbf419fa815d44401bb648f8 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 23 Dec 2023 16:52:27 -0800 Subject: [PATCH 171/248] still keep track of mouse/focus state when disabled but no refresh --- widget/slider.go | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/widget/slider.go b/widget/slider.go index 0918be700d..680d8f4c04 100644 --- a/widget/slider.go +++ b/widget/slider.go @@ -154,33 +154,30 @@ func (s *Slider) fireChangeEnded() { // // Since: 2.4 func (s *Slider) FocusGained() { - if s.disabled { - return - } s.focused = true - s.Refresh() + if !s.disabled { + s.Refresh() + } } // FocusLost is called when this item lost the focus. // // Since: 2.4 func (s *Slider) FocusLost() { - if s.disabled { - return - } s.focused = false - s.Refresh() + if !s.disabled { + s.Refresh() + } } // MouseIn is called when a desktop pointer enters the widget. // // Since: 2.4 func (s *Slider) MouseIn(_ *desktop.MouseEvent) { - if s.disabled { - return - } s.hovered = true - s.Refresh() + if !s.disabled { + s.Refresh() + } } // MouseMoved is called when a desktop pointer hovers over the widget. @@ -193,11 +190,10 @@ func (s *Slider) MouseMoved(_ *desktop.MouseEvent) { // // Since: 2.4 func (s *Slider) MouseOut() { - if s.disabled { - return - } s.hovered = false - s.Refresh() + if !s.disabled { + s.Refresh() + } } // TypedKey is called when this item receives a key event. From 20ef8cd45d9264554655a719f1ef1d98dee8a496 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 23 Dec 2023 17:01:07 -0800 Subject: [PATCH 172/248] don't respond to tapped when disabled --- widget/slider.go | 4 ++++ widget/slider_test.go | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/widget/slider.go b/widget/slider.go index 680d8f4c04..07c5685123 100644 --- a/widget/slider.go +++ b/widget/slider.go @@ -110,6 +110,10 @@ func (s *Slider) Dragged(e *fyne.DragEvent) { // // Since: 2.4 func (s *Slider) Tapped(e *fyne.PointEvent) { + if s.disabled { + return + } + driver := fyne.CurrentApp().Driver() if !s.focused && !driver.Device().IsMobile() { impl := s.super() diff --git a/widget/slider_test.go b/widget/slider_test.go index 6a4bc26b29..740255044b 100644 --- a/widget/slider_test.go +++ b/widget/slider_test.go @@ -320,6 +320,11 @@ func TestSlider_Disabled(t *testing.T) { changes++ } + tap := &fyne.PointEvent{} + tap.Position = fyne.NewPos(30, 2) + slider.Tapped(tap) + assert.Equal(t, 0, changes) + drag := &fyne.DragEvent{} drag.PointEvent.Position = fyne.NewPos(25, 2) slider.Dragged(drag) From 7f1274fc96e2b3b4c4e96658ba3facef9bfcba17 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 24 Dec 2023 14:56:11 +0000 Subject: [PATCH 173/248] Fix the refreshing of the other two callbacks on InnerWindow --- container/innerwindow.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/container/innerwindow.go b/container/innerwindow.go index 19fec83d3d..b21f458dad 100644 --- a/container/innerwindow.go +++ b/container/innerwindow.go @@ -74,7 +74,7 @@ func (w *InnerWindow) CreateRenderer() fyne.WidgetRenderer { icon.(*widget.Button).Disable() } } - title := newDraggableLabel(w.title, w.OnDragged, w.OnTappedBar) + title := newDraggableLabel(w.title, w) title.Truncation = fyne.TextTruncateEllipsis bar := NewBorder(nil, nil, buttons, icon, title) @@ -167,20 +167,19 @@ func (i *innerWindowRenderer) Refresh() { type draggableLabel struct { widget.Label - drag func(*fyne.DragEvent) - tap func() + win *InnerWindow } -func newDraggableLabel(title string, fn func(*fyne.DragEvent), tap func()) *draggableLabel { - d := &draggableLabel{drag: fn, tap: tap} +func newDraggableLabel(title string, win *InnerWindow) *draggableLabel { + d := &draggableLabel{win: win} d.ExtendBaseWidget(d) d.Text = title return d } func (d *draggableLabel) Dragged(ev *fyne.DragEvent) { - if f := d.drag; f != nil { - d.drag(ev) + if f := d.win.OnDragged; f != nil { + f(ev) } } @@ -188,8 +187,8 @@ func (d *draggableLabel) DragEnd() { } func (d *draggableLabel) Tapped(ev *fyne.PointEvent) { - if f := d.tap; f != nil { - d.tap() + if f := d.win.OnTappedBar; f != nil { + f() } } From 4104079d809a8bea45ba81e2ad3d359564742b97 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 24 Dec 2023 15:18:43 +0000 Subject: [PATCH 174/248] Don't allow apps in a web browser to quit --- internal/driver/glfw/menu.go | 29 ------------------------ internal/driver/glfw/menu_notweb.go | 35 +++++++++++++++++++++++++++++ internal/driver/glfw/menu_web.go | 11 +++++++++ 3 files changed, 46 insertions(+), 29 deletions(-) create mode 100644 internal/driver/glfw/menu_notweb.go create mode 100644 internal/driver/glfw/menu_web.go diff --git a/internal/driver/glfw/menu.go b/internal/driver/glfw/menu.go index f469451750..9c1008cae2 100644 --- a/internal/driver/glfw/menu.go +++ b/internal/driver/glfw/menu.go @@ -13,32 +13,3 @@ func buildMenuOverlay(menus *fyne.MainMenu, w *window) fyne.CanvasObject { menus = addMissingQuitForMainMenu(menus, w) return NewMenuBar(menus, w.canvas) } - -func addMissingQuitForMainMenu(menus *fyne.MainMenu, w *window) *fyne.MainMenu { - var lastItem *fyne.MenuItem - if len(menus.Items[0].Items) > 0 { - lastItem = menus.Items[0].Items[len(menus.Items[0].Items)-1] - if lastItem.Label == "Quit" { - lastItem.IsQuit = true - } - } - if lastItem == nil || !lastItem.IsQuit { // make sure the first menu always has a quit option - quitItem := fyne.NewMenuItem("Quit", nil) - quitItem.IsQuit = true - menus.Items[0].Items = append(menus.Items[0].Items, fyne.NewMenuItemSeparator(), quitItem) - } - for _, item := range menus.Items[0].Items { - if item.IsQuit && item.Action == nil { - item.Action = func() { - for _, win := range w.driver.AllWindows() { - if glWin, ok := win.(*window); ok { - glWin.closed(glWin.view()) - } else { - win.Close() // for test windows - } - } - } - } - } - return menus -} diff --git a/internal/driver/glfw/menu_notweb.go b/internal/driver/glfw/menu_notweb.go new file mode 100644 index 0000000000..ca9ae0ead2 --- /dev/null +++ b/internal/driver/glfw/menu_notweb.go @@ -0,0 +1,35 @@ +//go:build !js && !wasm && !test_web_driver +// +build !js,!wasm,!test_web_driver + +package glfw + +import "fyne.io/fyne/v2" + +func addMissingQuitForMainMenu(menus *fyne.MainMenu, w *window) *fyne.MainMenu { + var lastItem *fyne.MenuItem + if len(menus.Items[0].Items) > 0 { + lastItem = menus.Items[0].Items[len(menus.Items[0].Items)-1] + if lastItem.Label == "Quit" { + lastItem.IsQuit = true + } + } + if lastItem == nil || !lastItem.IsQuit { // make sure the first menu always has a quit option + quitItem := fyne.NewMenuItem("Quit", nil) + quitItem.IsQuit = true + menus.Items[0].Items = append(menus.Items[0].Items, fyne.NewMenuItemSeparator(), quitItem) + } + for _, item := range menus.Items[0].Items { + if item.IsQuit && item.Action == nil { + item.Action = func() { + for _, win := range w.driver.AllWindows() { + if glWin, ok := win.(*window); ok { + glWin.closed(glWin.view()) + } else { + win.Close() // for test windows + } + } + } + } + } + return menus +} diff --git a/internal/driver/glfw/menu_web.go b/internal/driver/glfw/menu_web.go new file mode 100644 index 0000000000..0ceaa3c121 --- /dev/null +++ b/internal/driver/glfw/menu_web.go @@ -0,0 +1,11 @@ +//go:build js || wasm || test_web_driver +// +build js wasm test_web_driver + +package glfw + +import "fyne.io/fyne/v2" + +func addMissingQuitForMainMenu(menus *fyne.MainMenu, w *window) *fyne.MainMenu { + // no-op for a web browser + return menus +} From 8e20b6cf1ae56b9d382722967692eafb0f801c4d Mon Sep 17 00:00:00 2001 From: Jacalz Date: Mon, 25 Dec 2023 10:44:46 +0100 Subject: [PATCH 175/248] Try to simply revert back web test workflow --- .github/workflows/web_tests.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/web_tests.yml b/.github/workflows/web_tests.yml index 2c04aebbbb..d47da136aa 100644 --- a/.github/workflows/web_tests.yml +++ b/.github/workflows/web_tests.yml @@ -6,11 +6,8 @@ permissions: jobs: web_tests: runs-on: ubuntu-latest - runs-on: ${{ matrix.os }} strategy: fail-fast: false - matrix: - go-version: ['1.19.x', '1.21.x'] steps: - uses: actions/checkout@v3 @@ -18,7 +15,7 @@ jobs: persist-credentials: false - uses: WillAbides/setup-go-faster@v1.8.0 with: - go-version: ${{ matrix.go-version }} + go-version: '1.17.x' - name: Get dependencies run: sudo apt-get update && sudo apt-get install gcc libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libx11-dev xorg-dev @@ -30,7 +27,8 @@ jobs: working-directory: cmd/fyne_demo run: go build - - name: Build WASM full website + - name: Build GopherJS and Wasm full website run: | + go install github.com/gopherjs/gopherjs@latest go install ./cmd/fyne - cd cmd/fyne_demo && fyne package --target=wasm + cd cmd/fyne_demo && fyne package --target=web \ No newline at end of file From 85cd02ff124bf80de86b53e22b774aabc9cb9c29 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Mon, 25 Dec 2023 10:46:52 +0100 Subject: [PATCH 176/248] Downgrade to uri 1.0.0 for now --- go.mod | 2 +- go.sum | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 5f953b9fc4..96ba346b4b 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e github.com/BurntSushi/toml v1.3.2 github.com/fogleman/gg v1.3.0 - github.com/fredbi/uri v1.1.0 + github.com/fredbi/uri v1.0.0 github.com/fsnotify/fsnotify v1.7.0 github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 diff --git a/go.sum b/go.sum index a620103eb4..4f6b0d0221 100644 --- a/go.sum +++ b/go.sum @@ -75,11 +75,10 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8= -github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4= +github.com/fredbi/uri v1.0.0 h1:s4QwUAZ8fz+mbTsukND+4V5f+mJ/wjaTokwstGUAemg= +github.com/fredbi/uri v1.0.0/go.mod h1:1xC40RnIOGCaQzswaOvrzvG/3M3F0hyDVb3aO/1iGy0= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= @@ -169,7 +168,6 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -248,7 +246,6 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -280,6 +277,7 @@ github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -287,6 +285,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= From 671b657ba490fcea6ac5114ffca042d690a24ac2 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 11:45:59 +0100 Subject: [PATCH 177/248] workflows: Update to new checkout and Go setup --- .github/workflows/license_check.yml | 4 ++-- .github/workflows/mobile_tests.yml | 4 ++-- .github/workflows/platform_tests.yml | 4 ++-- .github/workflows/static_analysis.yml | 4 ++-- .github/workflows/web_tests.yml | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/license_check.yml b/.github/workflows/license_check.yml index 95108fda9f..d41c3a6449 100644 --- a/.github/workflows/license_check.yml +++ b/.github/workflows/license_check.yml @@ -7,10 +7,10 @@ jobs: licenses: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: persist-credentials: false - - uses: WillAbides/setup-go-faster@v1.8.0 + - uses: WillAbides/setup-go-faster@v1.13.0 with: go-version: '1.21.x' diff --git a/.github/workflows/mobile_tests.yml b/.github/workflows/mobile_tests.yml index 0ad354fd77..4919d08d18 100644 --- a/.github/workflows/mobile_tests.yml +++ b/.github/workflows/mobile_tests.yml @@ -12,10 +12,10 @@ jobs: go-version: ['1.19.x', '1.21.x'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: persist-credentials: false - - uses: WillAbides/setup-go-faster@v1.8.0 + - uses: WillAbides/setup-go-faster@v1.13.0 with: go-version: ${{ matrix.go-version }} diff --git a/.github/workflows/platform_tests.yml b/.github/workflows/platform_tests.yml index 22ec944794..26a31f4291 100644 --- a/.github/workflows/platform_tests.yml +++ b/.github/workflows/platform_tests.yml @@ -20,10 +20,10 @@ jobs: tags: no_glfw steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: persist-credentials: false - - uses: WillAbides/setup-go-faster@v1.8.0 + - uses: WillAbides/setup-go-faster@v1.13.0 with: go-version: ${{ matrix.go-version }} diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 97d47d8070..489c47a755 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -10,10 +10,10 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: persist-credentials: false - - uses: WillAbides/setup-go-faster@v1.8.0 + - uses: WillAbides/setup-go-faster@v1.13.0 with: go-version: '1.21.x' diff --git a/.github/workflows/web_tests.yml b/.github/workflows/web_tests.yml index d47da136aa..cd1dfb2ea4 100644 --- a/.github/workflows/web_tests.yml +++ b/.github/workflows/web_tests.yml @@ -10,10 +10,10 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: persist-credentials: false - - uses: WillAbides/setup-go-faster@v1.8.0 + - uses: WillAbides/setup-go-faster@v1.13.0 with: go-version: '1.17.x' From cce6cfdb5f0f23ad04fb81fef4e012e7b3939f30 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 11:53:52 +0100 Subject: [PATCH 178/248] workflows: Separate Windows tests for now to avoid compile issues on Go < 1.19 --- .github/workflows/platform_tests.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/platform_tests.yml b/.github/workflows/platform_tests.yml index 26a31f4291..37d6bd9839 100644 --- a/.github/workflows/platform_tests.yml +++ b/.github/workflows/platform_tests.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: go-version: ['1.19.x', '1.21.x'] - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest, macos-latest] include: - os: ubuntu-latest runner: xvfb-run @@ -47,3 +47,20 @@ jobs: - name: Wayland Tests run: go test -tags no_glfw,ci,wayland ./... if: ${{ runner.os == 'Linux' }} + + windows_tests: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + go-version: ['1.20.x', '1.21.x'] + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: WillAbides/setup-go-faster@v1.13.0 + with: + go-version: ${{ matrix.go-version }} + + - name: Tests + run: ${{ matrix.runner }} go test "-test.benchtime" 10ms -tags no_glfw ./... From 6bed780aa9920ca46b79aeb7f1801c75f86ef275 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 11:57:53 +0100 Subject: [PATCH 179/248] workflows: Fix YAML syntax issue --- .github/workflows/platform_tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/platform_tests.yml b/.github/workflows/platform_tests.yml index 37d6bd9839..104bb9ffc5 100644 --- a/.github/workflows/platform_tests.yml +++ b/.github/workflows/platform_tests.yml @@ -47,7 +47,7 @@ jobs: - name: Wayland Tests run: go test -tags no_glfw,ci,wayland ./... if: ${{ runner.os == 'Linux' }} - + windows_tests: runs-on: windows-latest strategy: @@ -62,5 +62,5 @@ jobs: with: go-version: ${{ matrix.go-version }} - - name: Tests - run: ${{ matrix.runner }} go test "-test.benchtime" 10ms -tags no_glfw ./... + - name: Tests + run: ${{ matrix.runner }} go test "-test.benchtime" 10ms -tags no_glfw ./... From 084c1bc62f6621b396f194f25e6637bb0161f7ff Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 11:59:35 +0100 Subject: [PATCH 180/248] Try to fix Windows workflows --- .github/workflows/platform_tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/platform_tests.yml b/.github/workflows/platform_tests.yml index 104bb9ffc5..c56cb7c0a6 100644 --- a/.github/workflows/platform_tests.yml +++ b/.github/workflows/platform_tests.yml @@ -14,8 +14,6 @@ jobs: include: - os: ubuntu-latest runner: xvfb-run - - os: windows-latest - tags: no_glfw - os: macos-latest tags: no_glfw From 02c42f776fb858b583e061184c05731da64ac3fa Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 30 Dec 2023 13:58:13 +0100 Subject: [PATCH 181/248] Minor cleanup of hyperlink code --- widget/hyperlink.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/widget/hyperlink.go b/widget/hyperlink.go index cded064c34..7aa4aba736 100644 --- a/widget/hyperlink.go +++ b/widget/hyperlink.go @@ -218,10 +218,11 @@ func (r *hyperlinkRenderer) Destroy() { func (r *hyperlinkRenderer) Layout(s fyne.Size) { r.hl.provider.Resize(s) - r.focus.Move(fyne.NewPos(theme.InnerPadding()/2, theme.InnerPadding()/2)) - r.focus.Resize(fyne.NewSize(s.Width-theme.InnerPadding(), s.Height-theme.InnerPadding())) - r.under.Move(fyne.NewPos(theme.InnerPadding(), s.Height-theme.InnerPadding())) - r.under.Resize(fyne.NewSize(s.Width-theme.InnerPadding()*2, 1)) + innerPadding := theme.InnerPadding() + r.focus.Move(fyne.NewSquareOffsetPos(innerPadding / 2)) + r.focus.Resize(s.SubtractWidthHeight(innerPadding, innerPadding)) + r.under.Move(fyne.NewPos(innerPadding, s.Height-innerPadding)) + r.under.Resize(fyne.NewSize(s.Width-innerPadding*2, 1)) } func (r *hyperlinkRenderer) MinSize() fyne.Size { From 2cde868904092382ca5f645802ee9d444d8ae6e8 Mon Sep 17 00:00:00 2001 From: Jacob Date: Fri, 29 Dec 2023 23:44:21 +0100 Subject: [PATCH 182/248] Separate box layouts into two empty types Each boxlayout object is now essentially allocation free and the layout/minsize calls branch less. A bit more code duplication but I think the logic is more readable and probably easier to optimize in the future. --- layout/boxlayout.go | 174 ++++++++++++++++++++++++++++---------------- 1 file changed, 110 insertions(+), 64 deletions(-) diff --git a/layout/boxlayout.go b/layout/boxlayout.go index 248505b745..d6ab3a2e30 100644 --- a/layout/boxlayout.go +++ b/layout/boxlayout.go @@ -5,11 +5,12 @@ import ( "fyne.io/fyne/v2/theme" ) -// Declare conformity with Layout interface -var _ fyne.Layout = (*boxLayout)(nil) - -type boxLayout struct { - horizontal bool +// NewVBoxLayout returns a vertical box layout for stacking a number of child +// canvas objects or widgets top to bottom. The objects are always displayed +// at their vertical MinSize. Use a different layout if the objects are intended +// to be larger then their vertical MinSize. +func NewVBoxLayout() fyne.Layout { + return vBoxLayout{} } // NewHBoxLayout returns a horizontal box layout for stacking a number of child @@ -17,39 +18,100 @@ type boxLayout struct { // at their horizontal MinSize. Use a different layout if the objects are intended // to be larger then their horizontal MinSize. func NewHBoxLayout() fyne.Layout { - return &boxLayout{true} + return hBoxLayout{} } -// NewVBoxLayout returns a vertical box layout for stacking a number of child -// canvas objects or widgets top to bottom. The objects are always displayed -// at their vertical MinSize. Use a different layout if the objects are intended -// to be larger then their vertical MinSize. -func NewVBoxLayout() fyne.Layout { - return &boxLayout{false} -} +// Declare conformity with Layout interface +var _ fyne.Layout = (*vBoxLayout)(nil) -func (g *boxLayout) isSpacer(obj fyne.CanvasObject) bool { - if !obj.Visible() { - return false // invisible spacers don't impact layout +type vBoxLayout struct{} + +// Layout is called to pack all child objects into a specified size. +// This will pack objects into a single column where each item +// is full width but the height is the minimum required. +// Any spacers added will pad the view, sharing the space if there are two or more. +func (v vBoxLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { + spacers := 0 + visibleObjects := 0 + // Size taken up by visible objects + total := float32(0) + + for _, child := range objects { + if !child.Visible() { + continue + } + + if isVerticalSpacer(child) { + spacers++ + continue + } + + visibleObjects++ + total += child.MinSize().Height } - spacer, ok := obj.(SpacerObject) - if !ok { - return false + padding := theme.Padding() + + // Amount of space not taken up by visible objects and inter-object padding + extra := size.Height - total - (padding * float32(visibleObjects-1)) + + // Spacers split extra space equally + spacerSize := float32(0) + if spacers > 0 { + spacerSize = extra / float32(spacers) } - if g.horizontal { - return spacer.ExpandHorizontal() + x, y := float32(0), float32(0) + for _, child := range objects { + if !child.Visible() { + continue + } + + if isVerticalSpacer(child) { + y += spacerSize + continue + } + child.Move(fyne.NewPos(x, y)) + + height := child.MinSize().Height + y += padding + height + child.Resize(fyne.NewSize(size.Width, height)) } +} + +// MinSize finds the smallest size that satisfies all the child objects. +// For a BoxLayout this is the width of the widest item and the height is +// the sum of of all children combined with padding between each. +func (v vBoxLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { + minSize := fyne.NewSize(0, 0) + addPadding := false + padding := theme.Padding() + for _, child := range objects { + if !child.Visible() || isVerticalSpacer(child) { + continue + } - return spacer.ExpandVertical() + childMin := child.MinSize() + minSize.Width = fyne.Max(childMin.Width, minSize.Width) + minSize.Height += childMin.Height + if addPadding { + minSize.Height += padding + } + addPadding = true + } + return minSize } +// Declare conformity with Layout interface +var _ fyne.Layout = (*hBoxLayout)(nil) + +type hBoxLayout struct{} + // Layout is called to pack all child objects into a specified size. // For a VBoxLayout this will pack objects into a single column where each item // is full width but the height is the minimum required. // Any spacers added will pad the view, sharing the space if there are two or more. -func (g *boxLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { +func (g hBoxLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { spacers := 0 visibleObjects := 0 // Size taken up by visible objects @@ -59,28 +121,20 @@ func (g *boxLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { if !child.Visible() { continue } - if g.isSpacer(child) { + + if isHorizontalSpacer(child) { spacers++ continue } visibleObjects++ - if g.horizontal { - total += child.MinSize().Width - } else { - total += child.MinSize().Height - } + total += child.MinSize().Width } padding := theme.Padding() // Amount of space not taken up by visible objects and inter-object padding - var extra float32 - if g.horizontal { - extra = size.Width - total - (padding * float32(visibleObjects-1)) - } else { - extra = size.Height - total - (padding * float32(visibleObjects-1)) - } + extra := size.Width - total - (padding * float32(visibleObjects-1)) // Spacers split extra space equally spacerSize := float32(0) @@ -94,55 +148,47 @@ func (g *boxLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { continue } - if g.isSpacer(child) { - if g.horizontal { - x += spacerSize - } else { - y += spacerSize - } + if isHorizontalSpacer(child) { + x += spacerSize continue } child.Move(fyne.NewPos(x, y)) - if g.horizontal { - width := child.MinSize().Width - x += padding + width - child.Resize(fyne.NewSize(width, size.Height)) - } else { - height := child.MinSize().Height - y += padding + height - child.Resize(fyne.NewSize(size.Width, height)) - } + width := child.MinSize().Width + x += padding + width + child.Resize(fyne.NewSize(width, size.Height)) } } // MinSize finds the smallest size that satisfies all the child objects. // For a BoxLayout this is the width of the widest item and the height is // the sum of of all children combined with padding between each. -func (g *boxLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { +func (g hBoxLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { minSize := fyne.NewSize(0, 0) addPadding := false padding := theme.Padding() for _, child := range objects { - if !child.Visible() || g.isSpacer(child) { + if !child.Visible() || isHorizontalSpacer(child) { continue } childMin := child.MinSize() - if g.horizontal { - minSize.Height = fyne.Max(childMin.Height, minSize.Height) - minSize.Width += childMin.Width - if addPadding { - minSize.Width += padding - } - } else { - minSize.Width = fyne.Max(childMin.Width, minSize.Width) - minSize.Height += childMin.Height - if addPadding { - minSize.Height += padding - } + minSize.Height = fyne.Max(childMin.Height, minSize.Height) + minSize.Width += childMin.Width + if addPadding { + minSize.Width += padding } addPadding = true } return minSize } + +func isVerticalSpacer(obj fyne.CanvasObject) bool { + spacer, ok := obj.(SpacerObject) + return ok && spacer.ExpandVertical() +} + +func isHorizontalSpacer(obj fyne.CanvasObject) bool { + spacer, ok := obj.(SpacerObject) + return ok && spacer.ExpandHorizontal() +} From 34ce2b0a9c4e683a0292858389d2e2c2c6e71215 Mon Sep 17 00:00:00 2001 From: Jacob Date: Fri, 29 Dec 2023 23:52:26 +0100 Subject: [PATCH 183/248] Optimize MinSize for gridlayout --- layout/gridlayout.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/layout/gridlayout.go b/layout/gridlayout.go index f0a64a8e62..e5e99946c8 100644 --- a/layout/gridlayout.go +++ b/layout/gridlayout.go @@ -62,7 +62,6 @@ func (g *gridLayout) countRows(objects []fyne.CanvasObject) int { // size is the ideal cell size and the offset is which col or row its on. func getLeading(size float64, offset int) float32 { ret := (size + float64(theme.Padding())) * float64(offset) - return float32(ret) } @@ -139,11 +138,19 @@ func (g *gridLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { minSize = minSize.Max(child.MinSize()) } + padding := theme.Padding() if g.horizontal() { minContentSize := fyne.NewSize(minSize.Width*float32(g.Cols), minSize.Height*float32(rows)) - return minContentSize.Add(fyne.NewSize(theme.Padding()*fyne.Max(float32(g.Cols-1), 0), theme.Padding()*fyne.Max(float32(rows-1), 0))) + if rows == 0 { + return minContentSize + } + + return minContentSize.Add(fyne.NewSize(padding*float32(g.Cols-1), padding*float32(rows-1))) } minContentSize := fyne.NewSize(minSize.Width*float32(rows), minSize.Height*float32(g.Cols)) - return minContentSize.Add(fyne.NewSize(theme.Padding()*fyne.Max(float32(rows-1), 0), theme.Padding()*fyne.Max(float32(g.Cols-1), 0))) + if rows == 0 { + return minContentSize + } + return minContentSize.Add(fyne.NewSize(padding*float32(rows-1), padding*float32(g.Cols-1))) } From c2d6fc39bf53dbc63ec3e1e04bd1557682662238 Mon Sep 17 00:00:00 2001 From: Jacob Date: Fri, 29 Dec 2023 23:54:41 +0100 Subject: [PATCH 184/248] Stacklayout does not need to be a reference --- layout/stacklayout.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/layout/stacklayout.go b/layout/stacklayout.go index 81e09a535b..7874fbde15 100644 --- a/layout/stacklayout.go +++ b/layout/stacklayout.go @@ -16,7 +16,7 @@ type stackLayout struct { // // Since: 2.4 func NewStackLayout() fyne.Layout { - return &stackLayout{} + return stackLayout{} } // NewMaxLayout creates a new MaxLayout instance @@ -28,7 +28,7 @@ func NewMaxLayout() fyne.Layout { // Layout is called to pack all child objects into a specified size. // For StackLayout this sets all children to the full size passed. -func (m *stackLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { +func (m stackLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { topLeft := fyne.NewPos(0, 0) for _, child := range objects { child.Resize(size) @@ -38,7 +38,7 @@ func (m *stackLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { // MinSize finds the smallest size that satisfies all the child objects. // For StackLayout this is determined simply as the MinSize of the largest child. -func (m *stackLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { +func (m stackLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { minSize := fyne.NewSize(0, 0) for _, child := range objects { if !child.Visible() { From 77e9a4a6838386d734b7a20279c95e2b17cec4fa Mon Sep 17 00:00:00 2001 From: Jacob Date: Fri, 29 Dec 2023 23:59:03 +0100 Subject: [PATCH 185/248] Minor cleanup of padded layout --- layout/paddedlayout.go | 11 +++++------ layout/stacklayout.go | 3 +-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/layout/paddedlayout.go b/layout/paddedlayout.go index 5e6776d018..c260841819 100644 --- a/layout/paddedlayout.go +++ b/layout/paddedlayout.go @@ -8,14 +8,13 @@ import ( // Declare conformity with Layout interface var _ fyne.Layout = (*paddedLayout)(nil) -type paddedLayout struct { -} +type paddedLayout struct{} // Layout is called to pack all child objects into a specified size. // For PaddedLayout this sets all children to the full size passed minus padding all around. -func (l *paddedLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { +func (l paddedLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { padding := theme.Padding() - pos := fyne.NewPos(padding, padding) + pos := fyne.NewSquareOffsetPos(padding) siz := fyne.NewSize(size.Width-2*padding, size.Height-2*padding) for _, child := range objects { child.Resize(siz) @@ -25,7 +24,7 @@ func (l *paddedLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { // MinSize finds the smallest size that satisfies all the child objects. // For PaddedLayout this is determined simply as the MinSize of the largest child plus padding all around. -func (l *paddedLayout) MinSize(objects []fyne.CanvasObject) (min fyne.Size) { +func (l paddedLayout) MinSize(objects []fyne.CanvasObject) (min fyne.Size) { for _, child := range objects { if !child.Visible() { continue @@ -41,5 +40,5 @@ func (l *paddedLayout) MinSize(objects []fyne.CanvasObject) (min fyne.Size) { // // Since: 1.4 func NewPaddedLayout() fyne.Layout { - return &paddedLayout{} + return paddedLayout{} } diff --git a/layout/stacklayout.go b/layout/stacklayout.go index 7874fbde15..a8f896ab1a 100644 --- a/layout/stacklayout.go +++ b/layout/stacklayout.go @@ -6,8 +6,7 @@ import "fyne.io/fyne/v2" // Declare conformity with Layout interface var _ fyne.Layout = (*stackLayout)(nil) -type stackLayout struct { -} +type stackLayout struct{} // NewStackLayout returns a new StackLayout instance. Objects are stacked // on top of each other with later objects on top of those before. From da7b797429a8ea465ba01320e2bb62d009e4be27 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 30 Dec 2023 00:10:34 +0100 Subject: [PATCH 186/248] Remove code duplication in grid minsize --- layout/gridlayout.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/layout/gridlayout.go b/layout/gridlayout.go index e5e99946c8..a67be66965 100644 --- a/layout/gridlayout.go +++ b/layout/gridlayout.go @@ -139,18 +139,23 @@ func (g *gridLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { } padding := theme.Padding() + var primaryObjects, secondaryObjects int if g.horizontal() { - minContentSize := fyne.NewSize(minSize.Width*float32(g.Cols), minSize.Height*float32(rows)) - if rows == 0 { - return minContentSize - } - - return minContentSize.Add(fyne.NewSize(padding*float32(g.Cols-1), padding*float32(rows-1))) + primaryObjects = g.Cols + secondaryObjects = rows + } else { + primaryObjects = rows + secondaryObjects = g.Cols } - minContentSize := fyne.NewSize(minSize.Width*float32(rows), minSize.Height*float32(g.Cols)) + width := minSize.Width * float32(primaryObjects) + height := minSize.Height * float32(secondaryObjects) + xpad := padding * float32(primaryObjects-1) + ypad := padding * float32(secondaryObjects-1) + + minContentSize := fyne.NewSize(width, height) if rows == 0 { return minContentSize } - return minContentSize.Add(fyne.NewSize(padding*float32(rows-1), padding*float32(g.Cols-1))) + return minContentSize.Add(fyne.NewSize(xpad, ypad)) } From 99fa7e3a7dc83dd273ad366cc7d336a1e1cee5f6 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 30 Dec 2023 00:18:27 +0100 Subject: [PATCH 187/248] More cleanup of gridlayout code --- layout/gridlayout.go | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/layout/gridlayout.go b/layout/gridlayout.go index a67be66965..2d83fd59c7 100644 --- a/layout/gridlayout.go +++ b/layout/gridlayout.go @@ -78,17 +78,18 @@ func (g *gridLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { rows := g.countRows(objects) padding := theme.Padding() - padWidth := float32(g.Cols-1) * padding - padHeight := float32(rows-1) * padding - cellWidth := float64(size.Width-padWidth) / float64(g.Cols) - cellHeight := float64(size.Height-padHeight) / float64(rows) - - if !g.horizontal() { - padWidth, padHeight = padHeight, padWidth - cellWidth = float64(size.Width-padWidth) / float64(rows) - cellHeight = float64(size.Height-padHeight) / float64(g.Cols) + + primaryObjects := rows + secondaryObjects := g.Cols + if g.horizontal() { + primaryObjects, secondaryObjects = secondaryObjects, primaryObjects } + padWidth := float32(primaryObjects-1) * padding + padHeight := float32(secondaryObjects-1) * padding + cellWidth := float64(size.Width-padWidth) / float64(primaryObjects) + cellHeight := float64(size.Height-padHeight) / float64(secondaryObjects) + row, col := 0, 0 i := 0 for _, child := range objects { @@ -139,13 +140,11 @@ func (g *gridLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { } padding := theme.Padding() - var primaryObjects, secondaryObjects int + + primaryObjects := rows + secondaryObjects := g.Cols if g.horizontal() { - primaryObjects = g.Cols - secondaryObjects = rows - } else { - primaryObjects = rows - secondaryObjects = g.Cols + primaryObjects, secondaryObjects = secondaryObjects, primaryObjects } width := minSize.Width * float32(primaryObjects) From 4ea8a5762f1744401ede9f7bd35b3b75890f925e Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 30 Dec 2023 12:45:20 +0100 Subject: [PATCH 188/248] Fix a bug in the gridLayout minSize cleanup --- layout/gridlayout.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/layout/gridlayout.go b/layout/gridlayout.go index 2d83fd59c7..316b2ed8d7 100644 --- a/layout/gridlayout.go +++ b/layout/gridlayout.go @@ -149,12 +149,8 @@ func (g *gridLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { width := minSize.Width * float32(primaryObjects) height := minSize.Height * float32(secondaryObjects) - xpad := padding * float32(primaryObjects-1) - ypad := padding * float32(secondaryObjects-1) + xpad := padding * fyne.Max(float32(primaryObjects-1), 0) + ypad := padding * fyne.Max(float32(secondaryObjects-1), 0) - minContentSize := fyne.NewSize(width, height) - if rows == 0 { - return minContentSize - } - return minContentSize.Add(fyne.NewSize(xpad, ypad)) + return fyne.NewSize(width+xpad, height+ypad) } From f71623c91f05666acc4eeed21c2c007acecc151e Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 11:40:45 +0100 Subject: [PATCH 189/248] Remove support for GopherJS to unblock newer Go versions The leaves the GopherJS support in cmd/fyne intact given that the plan is to move that tool out of the repository for this release. --- .github/workflows/web_tests.yml | 8 +------- app/app_openurl_js.go | 20 ------------------- app/app_theme_js.go | 29 ---------------------------- go.mod | 4 ++-- go.sum | 2 -- internal/driver/glfw/shortcuts_js.go | 15 -------------- internal/driver/glfw/window_js.go | 11 ----------- 7 files changed, 3 insertions(+), 86 deletions(-) delete mode 100644 app/app_openurl_js.go delete mode 100644 app/app_theme_js.go delete mode 100644 internal/driver/glfw/shortcuts_js.go delete mode 100644 internal/driver/glfw/window_js.go diff --git a/.github/workflows/web_tests.yml b/.github/workflows/web_tests.yml index cd1dfb2ea4..dea71861ae 100644 --- a/.github/workflows/web_tests.yml +++ b/.github/workflows/web_tests.yml @@ -15,7 +15,7 @@ jobs: persist-credentials: false - uses: WillAbides/setup-go-faster@v1.13.0 with: - go-version: '1.17.x' + go-version: '1.19.x' - name: Get dependencies run: sudo apt-get update && sudo apt-get install gcc libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libx11-dev xorg-dev @@ -26,9 +26,3 @@ jobs: GOARCH: wasm working-directory: cmd/fyne_demo run: go build - - - name: Build GopherJS and Wasm full website - run: | - go install github.com/gopherjs/gopherjs@latest - go install ./cmd/fyne - cd cmd/fyne_demo && fyne package --target=web \ No newline at end of file diff --git a/app/app_openurl_js.go b/app/app_openurl_js.go deleted file mode 100644 index 35af69b0a9..0000000000 --- a/app/app_openurl_js.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build !ci && js && !wasm -// +build !ci,js,!wasm - -package app - -import ( - "fmt" - "net/url" - - "honnef.co/go/js/dom" -) - -func (app *fyneApp) OpenURL(url *url.URL) error { - window := dom.GetWindow().Open(url.String(), "_blank", "") - if window == nil { - return fmt.Errorf("Unable to open a new window/tab for URL: %v.", url) - } - window.Focus() - return nil -} diff --git a/app/app_theme_js.go b/app/app_theme_js.go deleted file mode 100644 index 479cb9f425..0000000000 --- a/app/app_theme_js.go +++ /dev/null @@ -1,29 +0,0 @@ -//go:build !ci && js && !wasm -// +build !ci,js,!wasm - -package app - -import ( - "fyne.io/fyne/v2" - "fyne.io/fyne/v2/theme" - - "github.com/gopherjs/gopherjs/js" -) - -func defaultVariant() fyne.ThemeVariant { - if matchMedia := js.Global.Call("matchMedia", "(prefers-color-scheme: dark)"); matchMedia != js.Undefined { - if matches := matchMedia.Get("matches"); matches != js.Undefined && matches.Bool() { - return theme.VariantDark - } - return theme.VariantLight - } - return theme.VariantDark -} - -func init() { - if matchMedia := js.Global.Call("matchMedia", "(prefers-color-scheme: dark)"); matchMedia != js.Undefined { - matchMedia.Call("addEventListener", "change", func(o *js.Object) { - fyne.CurrentApp().Settings().(*settings).setupTheme() - }) - } -} diff --git a/go.mod b/go.mod index 7ec8fd9500..c590cf6416 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a github.com/godbus/dbus/v5 v5.1.0 - github.com/gopherjs/gopherjs v1.17.2 github.com/jackmordaunt/icns/v2 v2.2.6 github.com/josephspurrier/goversioninfo v1.4.0 github.com/lucor/goinfo v0.9.0 @@ -34,7 +33,6 @@ require ( golang.org/x/mod v0.12.0 golang.org/x/sys v0.13.0 golang.org/x/tools v0.12.0 - honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 ) require ( @@ -42,6 +40,7 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -49,4 +48,5 @@ require ( golang.org/x/net v0.17.0 // indirect golang.org/x/text v0.13.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect ) diff --git a/go.sum b/go.sum index f070772353..7041263d55 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,6 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe h1:A/wiwvQ0CAjPkuJytaD+SsXkPU0asQ+guQEIg1BJGX4= github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe/go.mod h1:d4clgH0/GrRwWjRzJJQXxT/h1TyuNSfF/X64zb/3Ggg= -github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 h1:+31CdF/okdokeFNoy9L/2PccG3JFidQT3ev64/r4pYU= -github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504/go.mod h1:gLRWYfYnMA9TONeppRSikMdXlHQ97xVsPojddUv3b/E= github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33 h1:0Ayg0/do/sqX2R7NonoLZvWxGrd9utTVf3A0QvCbC88= github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33/go.mod h1:gLRWYfYnMA9TONeppRSikMdXlHQ97xVsPojddUv3b/E= github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 h1:hnLq+55b7Zh7/2IRzWCpiTcAvjv/P8ERF+N7+xXbZhk= diff --git a/internal/driver/glfw/shortcuts_js.go b/internal/driver/glfw/shortcuts_js.go deleted file mode 100644 index cc18b8b9d9..0000000000 --- a/internal/driver/glfw/shortcuts_js.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:build js && !wasm -// +build js,!wasm - -package glfw - -import ( - "strings" - - "github.com/gopherjs/gopherjs/js" -) - -// Checks if running on Mac OSX -func isMacOSRuntime() bool { - return strings.Contains(strings.ToLower(js.Global.Get("window").Get("navigator").Get("platform").String()), "mac") -} diff --git a/internal/driver/glfw/window_js.go b/internal/driver/glfw/window_js.go deleted file mode 100644 index c1516d57f7..0000000000 --- a/internal/driver/glfw/window_js.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build js && !wasm && !test_web_driver -// +build js,!wasm,!test_web_driver - -package glfw - -import "math" - -func (w *window) scaleInput(in float64) float64 { - return math.Ceil(in * float64(w.canvas.Scale())) - -} From 89736e433c2117b575084de9fcde0f1114f8ec28 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 16:49:33 +0100 Subject: [PATCH 190/248] Remove the pure struct queue for gopherjs --- internal/async/gen.go | 50 ----------------------- internal/async/queue_pure_canvasobject.go | 41 ------------------- 2 files changed, 91 deletions(-) delete mode 100755 internal/async/queue_pure_canvasobject.go diff --git a/internal/async/gen.go b/internal/async/gen.go index 1dd1c333b5..e920284304 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -69,15 +69,6 @@ func main() { )`, }, }, - queuePureStructImpl: { - "queue_pure_canvasobject.go": { - Type: "fyne.CanvasObject", - Name: "CanvasObject", - Imports: `import ( - "fyne.io/fyne/v2" - )`, - }, - }, } for tmpl, types := range codes { @@ -201,47 +192,6 @@ func (ch *Unbounded{{.Name}}Chan) closed() { } `)) -var queuePureStructImpl = template.Must(template.New("queue").Parse(`// Code generated by go run gen.go; DO NOT EDIT. -//go:build js -// +build js - -package async - -{{.Imports}} - -// {{.Name}}Queue implements lock-free FIFO freelist based queue. -// -// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 -type {{.Name}}Queue struct { - head *item{{.Name}} - tail *item{{.Name}} - len uint64 -} - -// New{{.Name}}Queue returns a queue for caching values. -func New{{.Name}}Queue() *{{.Name}}Queue { - head := &item{{.Name}}{next: nil, v: nil} - return &{{.Name}}Queue{ - tail: head, - head: head, - } -} - -type item{{.Name}} struct { - next *item{{.Name}} - v {{.Type}} -} - -func load{{.Name}}Item(p **item{{.Name}}) *item{{.Name}} { - return *p -} - -func cas{{.Name}}Item(p **item{{.Name}}, _, new *item{{.Name}}) bool { - *p = new - return true -} -`)) - var queueUnsafeStructImpl = template.Must(template.New("queue").Parse(`// Code generated by go run gen.go; DO NOT EDIT. //go:build !js // +build !js diff --git a/internal/async/queue_pure_canvasobject.go b/internal/async/queue_pure_canvasobject.go deleted file mode 100755 index 3cd7ef2ea2..0000000000 --- a/internal/async/queue_pure_canvasobject.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by go run gen.go; DO NOT EDIT. -//go:build js -// +build js - -package async - -import ( - "fyne.io/fyne/v2" -) - -// CanvasObjectQueue implements lock-free FIFO freelist based queue. -// -// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 -type CanvasObjectQueue struct { - head *itemCanvasObject - tail *itemCanvasObject - len uint64 -} - -// NewCanvasObjectQueue returns a queue for caching values. -func NewCanvasObjectQueue() *CanvasObjectQueue { - head := &itemCanvasObject{next: nil, v: nil} - return &CanvasObjectQueue{ - tail: head, - head: head, - } -} - -type itemCanvasObject struct { - next *itemCanvasObject - v fyne.CanvasObject -} - -func loadCanvasObjectItem(p **itemCanvasObject) *itemCanvasObject { - return *p -} - -func casCanvasObjectItem(p **itemCanvasObject, _, new *itemCanvasObject) bool { - *p = new - return true -} From b4f8d6410edb63c093eb1a4cdf2a03af911c2d3b Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 30 Dec 2023 22:34:26 +0100 Subject: [PATCH 191/248] Fix build tags to unbreak WASM --- internal/async/gen.go | 2 -- internal/async/queue_unsafe_canvasobject.go | 2 -- 2 files changed, 4 deletions(-) diff --git a/internal/async/gen.go b/internal/async/gen.go index e920284304..fb95af7c83 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -193,8 +193,6 @@ func (ch *Unbounded{{.Name}}Chan) closed() { `)) var queueUnsafeStructImpl = template.Must(template.New("queue").Parse(`// Code generated by go run gen.go; DO NOT EDIT. -//go:build !js -// +build !js package async diff --git a/internal/async/queue_unsafe_canvasobject.go b/internal/async/queue_unsafe_canvasobject.go index 7a315d8418..c78247ddcc 100755 --- a/internal/async/queue_unsafe_canvasobject.go +++ b/internal/async/queue_unsafe_canvasobject.go @@ -1,6 +1,4 @@ // Code generated by go run gen.go; DO NOT EDIT. -//go:build !js -// +build !js package async From 02495a1a178d145014726ed7a6c630a2813eac94 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 31 Dec 2023 14:29:27 +0100 Subject: [PATCH 192/248] cmd/fyne: Initial migration to fyne.io/tools --- cmd/fyne/main.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/fyne/main.go b/cmd/fyne/main.go index f6b1ae78de..15a8efedc0 100644 --- a/cmd/fyne/main.go +++ b/cmd/fyne/main.go @@ -1,4 +1,6 @@ // Run a command line helper for various Fyne tools. +// +// Deprecated: Install fyne.io/tools/cmd/fyne for latest version. package main import ( @@ -11,6 +13,8 @@ import ( ) func main() { + fmt.Println("NOTE: This tool is deprecated. Install fyne.io/tools/cmd/fyne for the latest version.") + app := &cli.App{ Name: "fyne", Usage: "A command line helper for various Fyne tools.", From d557b97a6a7d341112361d0e9235d381bb077a66 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 31 Dec 2023 15:08:14 +0100 Subject: [PATCH 193/248] Mention how to install new tool --- cmd/fyne/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/fyne/main.go b/cmd/fyne/main.go index 15a8efedc0..faeb414d9e 100644 --- a/cmd/fyne/main.go +++ b/cmd/fyne/main.go @@ -13,7 +13,8 @@ import ( ) func main() { - fmt.Println("NOTE: This tool is deprecated. Install fyne.io/tools/cmd/fyne for the latest version.") + fmt.Println("NOTE: This tool is deprecated and has migrated to fyne.io/tools/cmd/fyne.") + fmt.Println("The new tool can be installed by running the following command:\n\tgo install fyne.io/tools/cmd/fyne@latest") app := &cli.App{ Name: "fyne", From dfef916668527e61d286e1124189e04a28b59982 Mon Sep 17 00:00:00 2001 From: Jacob Date: Mon, 1 Jan 2024 23:08:39 +0100 Subject: [PATCH 194/248] Only use wasm build tag and not js --- app/app_darwin.go | 4 ++-- app/app_desktop_darwin.go | 4 ++-- app/app_goxjs.go | 4 ++-- app/app_notlegacy_darwin.go | 4 ++-- app/app_openurl_web.go | 4 ++-- app/app_other.go | 4 ++-- app/app_theme_web.go | 4 ++-- app/app_windows.go | 4 ++-- app/app_xdg.go | 3 +-- app/settings_desktop.go | 4 ++-- app/settings_file.go | 4 ++-- app/settings_goxjs.go | 4 ++-- internal/cache/texture_desktop.go | 4 ++-- internal/cache/texture_goxjs.go | 4 ++-- internal/driver/glfw/clipboard.go | 4 ++-- internal/driver/glfw/clipboard_goxjs.go | 4 ++-- internal/driver/glfw/device_desktop.go | 4 ++-- internal/driver/glfw/device_goxjs.go | 4 ++-- internal/driver/glfw/device_test.go | 4 ++-- internal/driver/glfw/driver_desktop.go | 4 ++-- internal/driver/glfw/driver_goxjs.go | 4 ++-- internal/driver/glfw/driver_web.go | 4 ++-- internal/driver/glfw/glfw_core.go | 3 +-- internal/driver/glfw/glfw_es.go | 3 +-- internal/driver/glfw/glfw_goxjs.go | 4 ++-- internal/driver/glfw/loop_desktop.go | 4 ++-- internal/driver/glfw/loop_goxjs.go | 4 ++-- internal/driver/glfw/menu_darwin.go | 4 ++-- internal/driver/glfw/menu_notweb.go | 4 ++-- internal/driver/glfw/menu_other.go | 4 ++-- internal/driver/glfw/menu_web.go | 4 ++-- internal/driver/glfw/shortcuts_other.go | 4 ++-- internal/driver/glfw/shortcuts_wasm.go | 4 ++-- internal/driver/glfw/window_desktop.go | 4 ++-- internal/driver/glfw/window_desktop_test.go | 4 ++-- internal/driver/glfw/window_goxjs.go | 4 ++-- internal/driver/glfw/window_x11.go | 3 +-- internal/painter/gl/gl_core.go | 4 ++-- internal/painter/gl/gl_es.go | 3 +-- internal/painter/gl/gl_gomobile.go | 4 ++-- internal/painter/gl/gl_goxjs.go | 4 ++-- 41 files changed, 77 insertions(+), 82 deletions(-) diff --git a/app/app_darwin.go b/app/app_darwin.go index 9ee2a3140a..8e6e08668f 100644 --- a/app/app_darwin.go +++ b/app/app_darwin.go @@ -1,5 +1,5 @@ -//go:build !ci && !js && !wasm && !test_web_driver -// +build !ci,!js,!wasm,!test_web_driver +//go:build !ci && !wasm && !test_web_driver +// +build !ci,!wasm,!test_web_driver package app diff --git a/app/app_desktop_darwin.go b/app/app_desktop_darwin.go index 5b494e473a..eb93777e8b 100644 --- a/app/app_desktop_darwin.go +++ b/app/app_desktop_darwin.go @@ -1,5 +1,5 @@ -//go:build !ci && !ios && !js && !wasm && !test_web_driver -// +build !ci,!ios,!js,!wasm,!test_web_driver +//go:build !ci && !ios && !wasm && !test_web_driver +// +build !ci,!ios,!wasm,!test_web_driver package app diff --git a/app/app_goxjs.go b/app/app_goxjs.go index c9ffe05369..2392408875 100644 --- a/app/app_goxjs.go +++ b/app/app_goxjs.go @@ -1,7 +1,7 @@ -//go:build !ci && (!android || !ios || !mobile) && (js || wasm || test_web_driver) +//go:build !ci && (!android || !ios || !mobile) && (wasm || test_web_driver) // +build !ci // +build !android !ios !mobile -// +build js wasm test_web_driver +// +build wasm test_web_driver package app diff --git a/app/app_notlegacy_darwin.go b/app/app_notlegacy_darwin.go index 7a72bb2aca..01153c93b2 100644 --- a/app/app_notlegacy_darwin.go +++ b/app/app_notlegacy_darwin.go @@ -1,5 +1,5 @@ -//go:build !ci && !legacy && !js && !wasm && !test_web_driver -// +build !ci,!legacy,!js,!wasm,!test_web_driver +//go:build !ci && !legacy && !wasm && !test_web_driver +// +build !ci,!legacy,!wasm,!test_web_driver package app diff --git a/app/app_openurl_web.go b/app/app_openurl_web.go index 234a834fdb..9b039938ed 100644 --- a/app/app_openurl_web.go +++ b/app/app_openurl_web.go @@ -1,5 +1,5 @@ -//go:build !ci && !js && !wasm && test_web_driver -// +build !ci,!js,!wasm,test_web_driver +//go:build !ci && !wasm && test_web_driver +// +build !ci,!wasm,test_web_driver package app diff --git a/app/app_other.go b/app/app_other.go index 3d8fed6f29..d74089e59d 100644 --- a/app/app_other.go +++ b/app/app_other.go @@ -1,5 +1,5 @@ -//go:build ci || (!linux && !darwin && !windows && !freebsd && !openbsd && !netbsd && !js && !wasm && !test_web_driver) -// +build ci !linux,!darwin,!windows,!freebsd,!openbsd,!netbsd,!js,!wasm,!test_web_driver +//go:build ci || (!linux && !darwin && !windows && !freebsd && !openbsd && !netbsd && !wasm && !test_web_driver) +// +build ci !linux,!darwin,!windows,!freebsd,!openbsd,!netbsd,!wasm,!test_web_driver package app diff --git a/app/app_theme_web.go b/app/app_theme_web.go index de6c1e2a96..48ad5ef8c4 100644 --- a/app/app_theme_web.go +++ b/app/app_theme_web.go @@ -1,5 +1,5 @@ -//go:build !ci && !js && !wasm && test_web_driver -// +build !ci,!js,!wasm,test_web_driver +//go:build !ci && !wasm && test_web_driver +// +build !ci,!wasm,test_web_driver package app diff --git a/app/app_windows.go b/app/app_windows.go index fcb53e0232..60d9b0a166 100644 --- a/app/app_windows.go +++ b/app/app_windows.go @@ -1,5 +1,5 @@ -//go:build !ci && !js && !android && !ios && !wasm && !test_web_driver -// +build !ci,!js,!android,!ios,!wasm,!test_web_driver +//go:build !ci && !android && !ios && !wasm && !test_web_driver +// +build !ci,!android,!ios,!wasm,!test_web_driver package app diff --git a/app/app_xdg.go b/app/app_xdg.go index cfbd95b4b5..de39cecead 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -1,6 +1,5 @@ -//go:build !ci && !js && !wasm && !test_web_driver && (linux || openbsd || freebsd || netbsd) && !android +//go:build !ci && !wasm && !test_web_driver && (linux || openbsd || freebsd || netbsd) && !android // +build !ci -// +build !js // +build !wasm // +build !test_web_driver // +build linux openbsd freebsd netbsd diff --git a/app/settings_desktop.go b/app/settings_desktop.go index dae958ba21..7832835a1c 100644 --- a/app/settings_desktop.go +++ b/app/settings_desktop.go @@ -1,5 +1,5 @@ -//go:build !android && !ios && !mobile && !js && !wasm && !test_web_driver -// +build !android,!ios,!mobile,!js,!wasm,!test_web_driver +//go:build !android && !ios && !mobile && !wasm && !test_web_driver +// +build !android,!ios,!mobile,!wasm,!test_web_driver package app diff --git a/app/settings_file.go b/app/settings_file.go index ed276da75c..eb0426f672 100644 --- a/app/settings_file.go +++ b/app/settings_file.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm && !test_web_driver -// +build !js,!wasm,!test_web_driver +//go:build !wasm && !test_web_driver +// +build !wasm,!test_web_driver package app diff --git a/app/settings_goxjs.go b/app/settings_goxjs.go index c27fab8019..2acf5bfeb9 100644 --- a/app/settings_goxjs.go +++ b/app/settings_goxjs.go @@ -1,5 +1,5 @@ -//go:build js || wasm || test_web_driver -// +build js wasm test_web_driver +//go:build wasm || test_web_driver +// +build wasm test_web_driver package app diff --git a/internal/cache/texture_desktop.go b/internal/cache/texture_desktop.go index f37e750844..e1f826694c 100644 --- a/internal/cache/texture_desktop.go +++ b/internal/cache/texture_desktop.go @@ -1,5 +1,5 @@ -//go:build !android && !ios && !mobile && !js && !wasm && !test_web_driver -// +build !android,!ios,!mobile,!js,!wasm,!test_web_driver +//go:build !android && !ios && !mobile && !wasm && !test_web_driver +// +build !android,!ios,!mobile,!wasm,!test_web_driver package cache diff --git a/internal/cache/texture_goxjs.go b/internal/cache/texture_goxjs.go index ce75c10be5..c686e1f3d7 100644 --- a/internal/cache/texture_goxjs.go +++ b/internal/cache/texture_goxjs.go @@ -1,5 +1,5 @@ -//go:build js || wasm || test_web_driver -// +build js wasm test_web_driver +//go:build wasm || test_web_driver +// +build wasm test_web_driver package cache diff --git a/internal/driver/glfw/clipboard.go b/internal/driver/glfw/clipboard.go index 41fb2edd07..db5b82d2ff 100644 --- a/internal/driver/glfw/clipboard.go +++ b/internal/driver/glfw/clipboard.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm && !test_web_driver -// +build !js,!wasm,!test_web_driver +//go:build !wasm && !test_web_driver +// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/clipboard_goxjs.go b/internal/driver/glfw/clipboard_goxjs.go index b809359ad9..7928831baa 100644 --- a/internal/driver/glfw/clipboard_goxjs.go +++ b/internal/driver/glfw/clipboard_goxjs.go @@ -1,5 +1,5 @@ -//go:build js || wasm || test_web_driver -// +build js wasm test_web_driver +//go:build wasm || test_web_driver +// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/device_desktop.go b/internal/driver/glfw/device_desktop.go index 5d34ed7c76..8685cb46d0 100644 --- a/internal/driver/glfw/device_desktop.go +++ b/internal/driver/glfw/device_desktop.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm -// +build !js,!wasm +//go:build !wasm +// +build !wasm package glfw diff --git a/internal/driver/glfw/device_goxjs.go b/internal/driver/glfw/device_goxjs.go index 1782820546..dba18461e9 100644 --- a/internal/driver/glfw/device_goxjs.go +++ b/internal/driver/glfw/device_goxjs.go @@ -1,5 +1,5 @@ -//go:build js || wasm -// +build js wasm +//go:build wasm +// +build wasm package glfw diff --git a/internal/driver/glfw/device_test.go b/internal/driver/glfw/device_test.go index 0aa2aebce8..3cc253dcee 100644 --- a/internal/driver/glfw/device_test.go +++ b/internal/driver/glfw/device_test.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm -// +build !js,!wasm +//go:build !wasm +// +build !wasm package glfw diff --git a/internal/driver/glfw/driver_desktop.go b/internal/driver/glfw/driver_desktop.go index b317bc35c0..10f145a6f6 100644 --- a/internal/driver/glfw/driver_desktop.go +++ b/internal/driver/glfw/driver_desktop.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm && !test_web_driver -// +build !js,!wasm,!test_web_driver +//go:build !wasm && !test_web_driver +// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/driver_goxjs.go b/internal/driver/glfw/driver_goxjs.go index f1cfa3b166..564bdb6d10 100644 --- a/internal/driver/glfw/driver_goxjs.go +++ b/internal/driver/glfw/driver_goxjs.go @@ -1,5 +1,5 @@ -//go:build js -// +build js +//go:build wasm +// +build wasm package glfw diff --git a/internal/driver/glfw/driver_web.go b/internal/driver/glfw/driver_web.go index 1ecc09da62..5b12e53251 100644 --- a/internal/driver/glfw/driver_web.go +++ b/internal/driver/glfw/driver_web.go @@ -1,5 +1,5 @@ -//go:build js || wasm || test_web_driver -// +build js wasm test_web_driver +//go:build wasm || test_web_driver +// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/glfw_core.go b/internal/driver/glfw/glfw_core.go index 7026d449eb..ea06527b3a 100644 --- a/internal/driver/glfw/glfw_core.go +++ b/internal/driver/glfw/glfw_core.go @@ -1,6 +1,5 @@ -//go:build ((!gles && !arm && !arm64) || darwin) && !js && !wasm && !test_web_driver +//go:build ((!gles && !arm && !arm64) || darwin) && !wasm && !test_web_driver // +build !gles,!arm,!arm64 darwin -// +build !js // +build !wasm // +build !test_web_driver diff --git a/internal/driver/glfw/glfw_es.go b/internal/driver/glfw/glfw_es.go index 2dd30cf459..34f4a6cd73 100644 --- a/internal/driver/glfw/glfw_es.go +++ b/internal/driver/glfw/glfw_es.go @@ -1,7 +1,6 @@ -//go:build (gles || arm || arm64) && !darwin && !js && !wasm && !test_web_driver +//go:build (gles || arm || arm64) && !darwin && !wasm && !test_web_driver // +build gles arm arm64 // +build !darwin -// +build !js // +build !wasm // +build !test_web_driver diff --git a/internal/driver/glfw/glfw_goxjs.go b/internal/driver/glfw/glfw_goxjs.go index 645a856b54..89de5aa178 100644 --- a/internal/driver/glfw/glfw_goxjs.go +++ b/internal/driver/glfw/glfw_goxjs.go @@ -1,5 +1,5 @@ -//go:build js || wasm || test_web_driver -// +build js wasm test_web_driver +//go:build wasm || test_web_driver +// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/loop_desktop.go b/internal/driver/glfw/loop_desktop.go index 988cbd5bf5..d89aa2d3a5 100644 --- a/internal/driver/glfw/loop_desktop.go +++ b/internal/driver/glfw/loop_desktop.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm && !test_web_driver -// +build !js,!wasm,!test_web_driver +//go:build !wasm && !test_web_driver +// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/loop_goxjs.go b/internal/driver/glfw/loop_goxjs.go index baa46fac3c..c99f9a7d65 100644 --- a/internal/driver/glfw/loop_goxjs.go +++ b/internal/driver/glfw/loop_goxjs.go @@ -1,5 +1,5 @@ -//go:build js || wasm || test_web_driver -// +build js wasm test_web_driver +//go:build wasm || test_web_driver +// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/menu_darwin.go b/internal/driver/glfw/menu_darwin.go index e8da989022..be5899d644 100644 --- a/internal/driver/glfw/menu_darwin.go +++ b/internal/driver/glfw/menu_darwin.go @@ -1,5 +1,5 @@ -//go:build !no_native_menus && !js && !wasm && !test_web_driver -// +build !no_native_menus,!js,!wasm,!test_web_driver +//go:build !no_native_menus && !wasm && !test_web_driver +// +build !no_native_menus,!wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/menu_notweb.go b/internal/driver/glfw/menu_notweb.go index ca9ae0ead2..3547a46a04 100644 --- a/internal/driver/glfw/menu_notweb.go +++ b/internal/driver/glfw/menu_notweb.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm && !test_web_driver -// +build !js,!wasm,!test_web_driver +//go:build !wasm && !test_web_driver +// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/menu_other.go b/internal/driver/glfw/menu_other.go index 260217e9ea..d4f7b0d918 100644 --- a/internal/driver/glfw/menu_other.go +++ b/internal/driver/glfw/menu_other.go @@ -1,5 +1,5 @@ -//go:build !darwin || js || wasm || test_web_driver || no_native_menus -// +build !darwin js wasm test_web_driver no_native_menus +//go:build !darwin || wasm || test_web_driver || no_native_menus +// +build !darwin wasm test_web_driver no_native_menus package glfw diff --git a/internal/driver/glfw/menu_web.go b/internal/driver/glfw/menu_web.go index 0ceaa3c121..78f75ae54d 100644 --- a/internal/driver/glfw/menu_web.go +++ b/internal/driver/glfw/menu_web.go @@ -1,5 +1,5 @@ -//go:build js || wasm || test_web_driver -// +build js wasm test_web_driver +//go:build wasm || test_web_driver +// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/shortcuts_other.go b/internal/driver/glfw/shortcuts_other.go index d672aa6906..549b21c4e9 100644 --- a/internal/driver/glfw/shortcuts_other.go +++ b/internal/driver/glfw/shortcuts_other.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm -// +build !js,!wasm +//go:build !wasm +// +build !wasm package glfw diff --git a/internal/driver/glfw/shortcuts_wasm.go b/internal/driver/glfw/shortcuts_wasm.go index 21cac3b4c0..bb1055101e 100644 --- a/internal/driver/glfw/shortcuts_wasm.go +++ b/internal/driver/glfw/shortcuts_wasm.go @@ -1,5 +1,5 @@ -//go:build js && wasm -// +build js,wasm +//go:build wasm +// +build wasm package glfw diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index a4ec260645..ba509b7ab5 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm && !test_web_driver -// +build !js,!wasm,!test_web_driver +//go:build !wasm && !test_web_driver +// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/window_desktop_test.go b/internal/driver/glfw/window_desktop_test.go index 7c6a20cf29..3cba4c5202 100644 --- a/internal/driver/glfw/window_desktop_test.go +++ b/internal/driver/glfw/window_desktop_test.go @@ -1,5 +1,5 @@ -//go:build !js && !wasm && !test_web_driver -// +build !js,!wasm,!test_web_driver +//go:build !wasm && !test_web_driver +// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/window_goxjs.go b/internal/driver/glfw/window_goxjs.go index ebb8de7856..ef6fea7afe 100644 --- a/internal/driver/glfw/window_goxjs.go +++ b/internal/driver/glfw/window_goxjs.go @@ -1,5 +1,5 @@ -//go:build js || wasm || test_web_driver -// +build js wasm test_web_driver +//go:build wasm || test_web_driver +// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/window_x11.go b/internal/driver/glfw/window_x11.go index 99efc4b4de..bc8da918c5 100644 --- a/internal/driver/glfw/window_x11.go +++ b/internal/driver/glfw/window_x11.go @@ -1,7 +1,6 @@ -//go:build !wayland && (linux || freebsd || openbsd || netbsd) && !js && !wasm && !test_web_driver +//go:build !wayland && (linux || freebsd || openbsd || netbsd) && !wasm && !test_web_driver // +build !wayland // +build linux freebsd openbsd netbsd -// +build !js // +build !wasm // +build !test_web_driver diff --git a/internal/painter/gl/gl_core.go b/internal/painter/gl/gl_core.go index 2b9f45b5ee..5e4d25bc54 100644 --- a/internal/painter/gl/gl_core.go +++ b/internal/painter/gl/gl_core.go @@ -1,5 +1,5 @@ -//go:build (!gles && !arm && !arm64 && !android && !ios && !mobile && !js && !test_web_driver && !wasm) || (darwin && !mobile && !ios && !js && !wasm && !test_web_driver) -// +build !gles,!arm,!arm64,!android,!ios,!mobile,!js,!test_web_driver,!wasm darwin,!mobile,!ios,!js,!wasm,!test_web_driver +//go:build (!gles && !arm && !arm64 && !android && !ios && !mobile && !test_web_driver && !wasm) || (darwin && !mobile && !ios && !wasm && !test_web_driver) +// +build !gles,!arm,!arm64,!android,!ios,!mobile,!test_web_driver,!wasm darwin,!mobile,!ios,!wasm,!test_web_driver package gl diff --git a/internal/painter/gl/gl_es.go b/internal/painter/gl/gl_es.go index e89dc75955..c810eefbc6 100644 --- a/internal/painter/gl/gl_es.go +++ b/internal/painter/gl/gl_es.go @@ -1,10 +1,9 @@ -//go:build (gles || arm || arm64) && !android && !ios && !mobile && !darwin && !js && !wasm && !test_web_driver +//go:build (gles || arm || arm64) && !android && !ios && !mobile && !darwin && !wasm && !test_web_driver // +build gles arm arm64 // +build !android // +build !ios // +build !mobile // +build !darwin -// +build !js // +build !wasm // +build !test_web_driver diff --git a/internal/painter/gl/gl_gomobile.go b/internal/painter/gl/gl_gomobile.go index 4fe04f9ffa..a0d76182e5 100644 --- a/internal/painter/gl/gl_gomobile.go +++ b/internal/painter/gl/gl_gomobile.go @@ -1,6 +1,6 @@ -//go:build (android || ios || mobile) && (!js || !wasm || !test_web_driver) +//go:build (android || ios || mobile) && (!wasm || !test_web_driver) // +build android ios mobile -// +build !js !wasm !test_web_driver +// +build !wasm !test_web_driver package gl diff --git a/internal/painter/gl/gl_goxjs.go b/internal/painter/gl/gl_goxjs.go index 4ee75b574c..6d0c5121f6 100644 --- a/internal/painter/gl/gl_goxjs.go +++ b/internal/painter/gl/gl_goxjs.go @@ -1,5 +1,5 @@ -//go:build js || wasm || test_web_driver -// +build js wasm test_web_driver +//go:build wasm || test_web_driver +// +build wasm test_web_driver package gl From 84c727bda67c343b82d3e2c548f692d420d85f8f Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 12:01:21 +0100 Subject: [PATCH 195/248] Use the new math.MaxInt contant in table --- widget/table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/table.go b/widget/table.go index d492487fa3..85333506cb 100644 --- a/widget/table.go +++ b/widget/table.go @@ -13,7 +13,7 @@ import ( "fyne.io/fyne/v2/theme" ) -const noCellMatch = math.MaxInt32 // TODO make this MaxInt once we move to newer Go version +const noCellMatch = math.MaxInt // allTableCellsID represents all table cells when refreshing requested cells var allTableCellsID = TableCellID{-1, -1} From b323f49abb67381e245b6b3ff4254ce8d39aa756 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 12:13:07 +0100 Subject: [PATCH 196/248] Replace some usages of IndexByte with strings.Cut --- internal/repository/mime/mime.go | 11 ++++------- storage/filter.go | 7 +------ storage/repository/parse.go | 8 +++----- storage/repository/uri.go | 8 ++------ 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/internal/repository/mime/mime.go b/internal/repository/mime/mime.go index ef39897531..e3281d6301 100644 --- a/internal/repository/mime/mime.go +++ b/internal/repository/mime/mime.go @@ -4,13 +4,10 @@ import "strings" // Split spits the mimetype into its main type and subtype. func Split(mimeTypeFull string) (mimeType, mimeSubType string) { - // Replace with strings.Cut() when Go 1.18 is our new base version. - separatorIndex := strings.IndexByte(mimeTypeFull, '/') - if separatorIndex == -1 || mimeTypeFull[separatorIndex+1:] == "" { - return "", "" // Empty or only one part. Ignore. + mimeType, mimeSubType, ok := strings.Cut(mimeTypeFull, "/") + if !ok || mimeSubType == "" { + return "", "" } - mimeType = mimeTypeFull[:separatorIndex] - mimeSubType = mimeTypeFull[separatorIndex+1:] - return + return mimeType, mimeSubType } diff --git a/storage/filter.go b/storage/filter.go index bcc9adac05..3476bd49c1 100644 --- a/storage/filter.go +++ b/storage/filter.go @@ -50,12 +50,7 @@ func (mt *MimeTypeFileFilter) Matches(uri fyne.URI) bool { continue } - // Replace with strings.Cut() when Go 1.18 is our new base version. - subTypeSeparatorIndex := strings.IndexByte(mSubType, ';') - if subTypeSeparatorIndex != -1 { - mSubType = mSubType[:subTypeSeparatorIndex] - } - + mSubType, _, _ = strings.Cut(mSubType, ";") if mType == mimeType && (mSubType == mimeSubType || mSubType == "*") { return true } diff --git a/storage/repository/parse.go b/storage/repository/parse.go index db4e25962e..6da6e9d4ab 100644 --- a/storage/repository/parse.go +++ b/storage/repository/parse.go @@ -40,14 +40,12 @@ func NewFileURI(path string) fyne.URI { // Since: 2.0 func ParseURI(s string) (fyne.URI, error) { // Extract the scheme. - colonIndex := strings.IndexByte(s, ':') - if colonIndex <= 0 { + scheme, _, ok := strings.Cut(s, ":") + if !ok { return nil, errors.New("invalid URI, scheme must be present") } - scheme := strings.ToLower(s[:colonIndex]) - - if scheme == "file" { + if strings.EqualFold(scheme, "file") { // Does this really deserve to be special? In principle, the // purpose of this check is to pass it to NewFileURI, which // allows platform path seps in the URI (against the RFC, but diff --git a/storage/repository/uri.go b/storage/repository/uri.go index 44a5416b19..c687302181 100644 --- a/storage/repository/uri.go +++ b/storage/repository/uri.go @@ -49,12 +49,8 @@ func (u *uri) MimeType() string { } } - // Replace with strings.Cut() when Go 1.18 is our new base version. - semicolonIndex := strings.IndexByte(mimeTypeFull, ';') - if semicolonIndex == -1 { - return mimeTypeFull - } - return mimeTypeFull[:semicolonIndex] + mimeType, _, _ := strings.Cut(mimeTypeFull, ";") + return mimeType } func (u *uri) Scheme() string { From 5af278bdf664324c0b277ba3399ac97ce1bab5f2 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 12:58:39 +0100 Subject: [PATCH 197/248] Start using new Go 1.19 atomic APIs --- app.go | 6 ++-- dialog/color_channel.go | 8 +++--- internal/animation/animation.go | 6 ++-- internal/app/lifecycle.go | 47 ++++++++++++++++++-------------- internal/cache/base.go | 7 +++-- internal/driver/common/canvas.go | 6 ++-- internal/driver/glfw/driver.go | 6 ++-- internal/driver/glfw/loop.go | 6 ++-- internal/driver/mobile/driver.go | 4 +-- 9 files changed, 51 insertions(+), 45 deletions(-) diff --git a/app.go b/app.go index d36d326cf4..bffcf9c1ff 100644 --- a/app.go +++ b/app.go @@ -83,7 +83,7 @@ type App interface { // app contains an App variable, but due to atomic.Value restrictions on // interfaces we need to use an indirect type, i.e. appContainer. -var app atomic.Value // appContainer +var app atomic.Pointer[appContainer] // appContainer // appContainer is a dummy container that holds an App instance. This // struct exists to guarantee that atomic.Value can store objects with @@ -94,7 +94,7 @@ type appContainer struct { // SetCurrentApp is an internal function to set the app instance currently running. func SetCurrentApp(current App) { - app.Store(appContainer{current}) + app.Store(&appContainer{current}) } // CurrentApp returns the current application, for which there is only 1 per process. @@ -104,7 +104,7 @@ func CurrentApp() App { LogError("Attempt to access current Fyne app when none is started", nil) return nil } - return (val).(appContainer).current + return val.current } // AppMetadata captures the build metadata for an application. diff --git a/dialog/color_channel.go b/dialog/color_channel.go index 4f5d9f6e3c..839feb191f 100644 --- a/dialog/color_channel.go +++ b/dialog/color_channel.go @@ -152,7 +152,7 @@ func (e *colorChannelEntry) MinSize() fyne.Size { type userChangeEntry struct { widget.Entry - userTyped uint32 // atomic, 0 == false, 1 == true + userTyped atomic.Bool } func newUserChangeEntry(text string) *userChangeEntry { @@ -164,7 +164,7 @@ func newUserChangeEntry(text string) *userChangeEntry { func (e *userChangeEntry) setOnChanged(onChanged func(s string)) { e.Entry.OnChanged = func(text string) { - if !atomic.CompareAndSwapUint32(&e.userTyped, 1, 0) { + if !e.userTyped.CompareAndSwap(true, false) { return } if onChanged != nil { @@ -175,11 +175,11 @@ func (e *userChangeEntry) setOnChanged(onChanged func(s string)) { } func (e *userChangeEntry) TypedRune(r rune) { - atomic.StoreUint32(&e.userTyped, 1) + e.userTyped.Store(true) e.Entry.TypedRune(r) } func (e *userChangeEntry) TypedKey(ev *fyne.KeyEvent) { - atomic.StoreUint32(&e.userTyped, 1) + e.userTyped.Store(true) e.Entry.TypedKey(ev) } diff --git a/internal/animation/animation.go b/internal/animation/animation.go index 68eccec1d9..6d3a1712e1 100644 --- a/internal/animation/animation.go +++ b/internal/animation/animation.go @@ -14,7 +14,7 @@ type anim struct { reverse bool start time.Time total int64 - stopped uint32 // atomic, 0 == false 1 == true + stopped atomic.Bool } func newAnim(a *fyne.Animation) *anim { @@ -25,9 +25,9 @@ func newAnim(a *fyne.Animation) *anim { } func (a *anim) setStopped() { - atomic.StoreUint32(&a.stopped, 1) + a.stopped.Store(true) } func (a *anim) isStopped() bool { - return atomic.LoadUint32(&a.stopped) == 1 + return a.stopped.Load() } diff --git a/internal/app/lifecycle.go b/internal/app/lifecycle.go index b8b6fe70a9..71c826d93a 100644 --- a/internal/app/lifecycle.go +++ b/internal/app/lifecycle.go @@ -12,10 +12,10 @@ var _ fyne.Lifecycle = (*Lifecycle)(nil) // // Since: 2.1 type Lifecycle struct { - onForeground atomic.Value // func() - onBackground atomic.Value // func() - onStarted atomic.Value // func() - onStopped atomic.Value // func() + onForeground atomic.Pointer[func()] + onBackground atomic.Pointer[func()] + onStarted atomic.Pointer[func()] + onStopped atomic.Pointer[func()] onStoppedHookExecuted func() } @@ -28,57 +28,64 @@ func (l *Lifecycle) SetOnStoppedHookExecuted(f func()) { // SetOnEnteredForeground hooks into the the app becoming foreground. func (l *Lifecycle) SetOnEnteredForeground(f func()) { - l.onForeground.Store(f) + l.onForeground.Store(&f) } // SetOnExitedForeground hooks into the app having moved to the background. // Depending on the platform it may still be visible but will not receive keyboard events. // On some systems hover or desktop mouse move events may still occur. func (l *Lifecycle) SetOnExitedForeground(f func()) { - l.onBackground.Store(f) + l.onBackground.Store(&f) } // SetOnStarted hooks into an event that says the app is now running. func (l *Lifecycle) SetOnStarted(f func()) { - l.onStarted.Store(f) + l.onStarted.Store(&f) } // SetOnStopped hooks into an event that says the app is no longer running. func (l *Lifecycle) SetOnStopped(f func()) { - l.onStopped.Store(f) + l.onStopped.Store(&f) } // TriggerEnteredForeground will call the focus gained hook, if one is registered. func (l *Lifecycle) TriggerEnteredForeground() { - f := l.onForeground.Load() - if ff, ok := f.(func()); ok && ff != nil { - ff() + f := *l.onForeground.Load() + if f == nil { + return } + + f() } // TriggerExitedForeground will call the focus lost hook, if one is registered. func (l *Lifecycle) TriggerExitedForeground() { - f := l.onBackground.Load() - if ff, ok := f.(func()); ok && ff != nil { - ff() + f := *l.onBackground.Load() + if f == nil { + return } + + f() } // TriggerStarted will call the started hook, if one is registered. func (l *Lifecycle) TriggerStarted() { - f := l.onStarted.Load() - if ff, ok := f.(func()); ok && ff != nil { - ff() + f := *l.onStarted.Load() + if f == nil { + return } + + f() } // TriggerStopped will call the stopped hook, if one is registered, // and an internal stopped hook after that. func (l *Lifecycle) TriggerStopped() { - f := l.onStopped.Load() - if ff, ok := f.(func()); ok && ff != nil { - ff() + f := *l.onStopped.Load() + if f != nil { + f() } + if l.onStoppedHookExecuted != nil { l.onStoppedHookExecuted() } diff --git a/internal/cache/base.go b/internal/cache/base.go index 422a08503d..21dc8f70dd 100644 --- a/internal/cache/base.go +++ b/internal/cache/base.go @@ -215,7 +215,7 @@ func matchesACanvas(cinfo *canvasInfo, canvases []fyne.Canvas) bool { } type expiringCache struct { - expires atomic.Value // time.Time + expires atomic.Pointer[time.Time] } // isExpired check if the cache data is expired. @@ -224,12 +224,13 @@ func (c *expiringCache) isExpired(now time.Time) bool { if t == nil { return (time.Time{}).Before(now) } - return t.(time.Time).Before(now) + return t.Before(now) } // setAlive updates expiration time. func (c *expiringCache) setAlive() { - c.expires.Store(timeNow().Add(cacheDuration)) + expirationTIme := timeNow().Add(cacheDuration) + c.expires.Store(&expirationTIme) } type expiringCacheNoLock struct { diff --git a/internal/driver/common/canvas.go b/internal/driver/common/canvas.go index c70c0f13ff..594a436718 100644 --- a/internal/driver/common/canvas.go +++ b/internal/driver/common/canvas.go @@ -49,7 +49,7 @@ type Canvas struct { // the refreshQueue is an unbounded queue which is bale to cache // arbitrary number of fyne.CanvasObject for the rendering. refreshQueue *async.CanvasObjectQueue - dirty uint32 // atomic + dirty atomic.Bool mWindowHeadTree, contentTree, menuTree *renderCacheTree } @@ -380,12 +380,12 @@ func (c *Canvas) SetContentTreeAndFocusMgr(content fyne.CanvasObject) { // CheckDirtyAndClear returns true if the canvas is dirty and // clears the dirty state atomically. func (c *Canvas) CheckDirtyAndClear() bool { - return atomic.SwapUint32(&c.dirty, 0) != 0 + return c.dirty.Swap(false) } // SetDirty sets canvas dirty flag atomically. func (c *Canvas) SetDirty() { - atomic.AddUint32(&c.dirty, 1) + c.dirty.Store(true) } // SetMenuTreeAndFocusMgr sets menu tree and focus manager. diff --git a/internal/driver/glfw/driver.go b/internal/driver/glfw/driver.go index 6a44a1c45d..7c68ff7486 100644 --- a/internal/driver/glfw/driver.go +++ b/internal/driver/glfw/driver.go @@ -8,7 +8,6 @@ import ( "os" "runtime" "sync" - "sync/atomic" "time" "github.com/fyne-io/image/ico" @@ -109,7 +108,7 @@ func (d *gLDriver) Quit() { } // Only call close once to avoid panic. - if atomic.CompareAndSwapUint32(&running, 1, 0) { + if running.CompareAndSwap(true, false) { close(d.done) } } @@ -154,8 +153,7 @@ func (d *gLDriver) windowList() []fyne.Window { func (d *gLDriver) initFailed(msg string, err error) { logError(msg, err) - onMain := atomic.LoadUint32(&running) == 0 - if onMain { + if !running.Load() { d.Quit() } else { os.Exit(1) diff --git a/internal/driver/glfw/loop.go b/internal/driver/glfw/loop.go index 7d2fab3228..6bfdf41caa 100644 --- a/internal/driver/glfw/loop.go +++ b/internal/driver/glfw/loop.go @@ -28,7 +28,7 @@ type drawData struct { // channel for queuing functions on the main thread var funcQueue = make(chan funcData) var drawFuncQueue = make(chan drawData) -var running uint32 // atomic bool, 0 or 1 +var running atomic.Bool var initOnce = &sync.Once{} // Arrange that main.main runs on main thread. @@ -41,7 +41,7 @@ func init() { func runOnMain(f func()) { // If we are on main just execute - otherwise add it to the main queue and wait. // The "running" variable is normally false when we are on the main thread. - if onMain := atomic.LoadUint32(&running) == 0; onMain { + if !running.Load() { f() return } @@ -105,7 +105,7 @@ func (d *gLDriver) drawSingleFrame() { } func (d *gLDriver) runGL() { - if !atomic.CompareAndSwapUint32(&running, 0, 1) { + if !running.CompareAndSwap(false, true) { return // Run was called twice. } close(d.waitForStart) // Signal that execution can continue. diff --git a/internal/driver/mobile/driver.go b/internal/driver/mobile/driver.go index 4173cd3ad2..1629894ab6 100644 --- a/internal/driver/mobile/driver.go +++ b/internal/driver/mobile/driver.go @@ -57,7 +57,7 @@ type mobileDriver struct { theme fyne.ThemeVariant onConfigChanged func(*Configuration) painting bool - running uint32 // atomic, 1 == running, 0 == stopped + running atomic.Bool } // Declare conformity with Driver @@ -141,7 +141,7 @@ func (d *mobileDriver) Quit() { } func (d *mobileDriver) Run() { - if !atomic.CompareAndSwapUint32(&d.running, 0, 1) { + if !d.running.CompareAndSwap(false, true) { return // Run was called twice. } From 2334c7485a30a7cade0c950818e21fbbb5cd7e68 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 12:59:52 +0100 Subject: [PATCH 198/248] Fix scheme not being lowercase --- storage/repository/parse.go | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/repository/parse.go b/storage/repository/parse.go index 6da6e9d4ab..33ff36cd5e 100644 --- a/storage/repository/parse.go +++ b/storage/repository/parse.go @@ -65,6 +65,7 @@ func ParseURI(s string) (fyne.URI, error) { return NewFileURI(path), nil } + scheme = strings.ToLower(scheme) repo, err := ForScheme(scheme) if err == nil { // If the repository registered for this scheme implements a parser From dd7943c9711e2d4786096603104aa6ceb0e567b4 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:14:15 +0100 Subject: [PATCH 199/248] Avoid copy of lock --- internal/cache/base.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cache/base.go b/internal/cache/base.go index 21dc8f70dd..8f9f7cb3ab 100644 --- a/internal/cache/base.go +++ b/internal/cache/base.go @@ -215,7 +215,7 @@ func matchesACanvas(cinfo *canvasInfo, canvases []fyne.Canvas) bool { } type expiringCache struct { - expires atomic.Pointer[time.Time] + expires atomic.Value // time.time } // isExpired check if the cache data is expired. @@ -224,7 +224,7 @@ func (c *expiringCache) isExpired(now time.Time) bool { if t == nil { return (time.Time{}).Before(now) } - return t.Before(now) + return t.(time.Time).Before(now) } // setAlive updates expiration time. From 580e8e27709351db24a0b48912f14d22db473db9 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:22:26 +0100 Subject: [PATCH 200/248] More usages of new atomic APIs --- internal/async/gen.go | 9 ++--- internal/async/queue_canvasobject.go | 7 ++-- internal/async/queue_pure_canvasobject.go | 41 +++++++++++++++++++++ internal/async/queue_unsafe_canvasobject.go | 2 +- internal/driver/glfw/window_test.go | 12 +++--- widget/bind_helper.go | 12 +++--- 6 files changed, 62 insertions(+), 21 deletions(-) create mode 100755 internal/async/queue_pure_canvasobject.go diff --git a/internal/async/gen.go b/internal/async/gen.go index fb95af7c83..b31a3a68a9 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -51,7 +51,6 @@ func main() { Name: "CanvasObject", Imports: `import ( "sync" - "sync/atomic" "fyne.io/fyne/v2" )`, @@ -204,7 +203,7 @@ package async type {{.Name}}Queue struct { head unsafe.Pointer tail unsafe.Pointer - len uint64 + len atomic.Uint64 } // New{{.Name}}Queue returns a queue for caching values. @@ -254,7 +253,7 @@ func (q *{{.Name}}Queue) In(v {{.Type}}) { if lastnext == nil { if cas{{.Name}}Item(&last.next, lastnext, i) { cas{{.Name}}Item(&q.tail, last, i) - atomic.AddUint64(&q.len, 1) + q.len.Add(1) return } } else { @@ -281,7 +280,7 @@ func (q *{{.Name}}Queue) Out() {{.Type}} { } else { v := firstnext.v if cas{{.Name}}Item(&q.head, first, firstnext) { - atomic.AddUint64(&q.len, ^uint64(0)) + q.len.Add(^uint64(0)) item{{.Name}}Pool.Put(first) return v } @@ -292,6 +291,6 @@ func (q *{{.Name}}Queue) Out() {{.Type}} { // Len returns the length of the queue. func (q *{{.Name}}Queue) Len() uint64 { - return atomic.LoadUint64(&q.len) + return q.len.Load() } `)) diff --git a/internal/async/queue_canvasobject.go b/internal/async/queue_canvasobject.go index c0acb5c718..1af42f28df 100755 --- a/internal/async/queue_canvasobject.go +++ b/internal/async/queue_canvasobject.go @@ -4,7 +4,6 @@ package async import ( "sync" - "sync/atomic" "fyne.io/fyne/v2" ) @@ -27,7 +26,7 @@ func (q *CanvasObjectQueue) In(v fyne.CanvasObject) { if lastnext == nil { if casCanvasObjectItem(&last.next, lastnext, i) { casCanvasObjectItem(&q.tail, last, i) - atomic.AddUint64(&q.len, 1) + q.len.Add(1) return } } else { @@ -54,7 +53,7 @@ func (q *CanvasObjectQueue) Out() fyne.CanvasObject { } else { v := firstnext.v if casCanvasObjectItem(&q.head, first, firstnext) { - atomic.AddUint64(&q.len, ^uint64(0)) + q.len.Add(^uint64(0)) itemCanvasObjectPool.Put(first) return v } @@ -65,5 +64,5 @@ func (q *CanvasObjectQueue) Out() fyne.CanvasObject { // Len returns the length of the queue. func (q *CanvasObjectQueue) Len() uint64 { - return atomic.LoadUint64(&q.len) + return q.len.Load() } diff --git a/internal/async/queue_pure_canvasobject.go b/internal/async/queue_pure_canvasobject.go new file mode 100755 index 0000000000..05bd739014 --- /dev/null +++ b/internal/async/queue_pure_canvasobject.go @@ -0,0 +1,41 @@ +// Code generated by go run gen.go; DO NOT EDIT. +//go:build js +// +build js + +package async + +import ( + "fyne.io/fyne/v2" +) + +// CanvasObjectQueue implements lock-free FIFO freelist based queue. +// +// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 +type CanvasObjectQueue struct { + head *itemCanvasObject + tail *itemCanvasObject + len atomic.Uint64 +} + +// NewCanvasObjectQueue returns a queue for caching values. +func NewCanvasObjectQueue() *CanvasObjectQueue { + head := &itemCanvasObject{next: nil, v: nil} + return &CanvasObjectQueue{ + tail: head, + head: head, + } +} + +type itemCanvasObject struct { + next *itemCanvasObject + v fyne.CanvasObject +} + +func loadCanvasObjectItem(p **itemCanvasObject) *itemCanvasObject { + return *p +} + +func casCanvasObjectItem(p **itemCanvasObject, _, new *itemCanvasObject) bool { + *p = new + return true +} diff --git a/internal/async/queue_unsafe_canvasobject.go b/internal/async/queue_unsafe_canvasobject.go index c78247ddcc..5fbb99d26a 100755 --- a/internal/async/queue_unsafe_canvasobject.go +++ b/internal/async/queue_unsafe_canvasobject.go @@ -15,7 +15,7 @@ import ( type CanvasObjectQueue struct { head unsafe.Pointer tail unsafe.Pointer - len uint64 + len atomic.Uint64 } // NewCanvasObjectQueue returns a queue for caching values. diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index c0e8718ed5..15ebd22273 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -1220,14 +1220,14 @@ func TestWindow_TappedAndDoubleTapped(t *testing.T) { w := createWindow("Test").(*window) waitSingleTapped := make(chan struct{}) waitDoubleTapped := make(chan struct{}) - tapped := int32(0) // atomic + tapped := atomic.Int32{} but := newDoubleTappableButton() but.OnTapped = func() { - atomic.StoreInt32(&tapped, 1) + tapped.Store(1) waitSingleTapped <- struct{}{} } but.onDoubleTap = func() { - atomic.StoreInt32(&tapped, 2) + tapped.Store(2) waitDoubleTapped <- struct{}{} } w.SetContent(container.NewBorder(nil, nil, nil, nil, but)) @@ -1240,8 +1240,8 @@ func TestWindow_TappedAndDoubleTapped(t *testing.T) { w.WaitForEvents() time.Sleep(500 * time.Millisecond) - assert.Equal(t, int32(1), atomic.LoadInt32(&tapped), "Single tap should have fired") - atomic.StoreInt32(&tapped, 0) + assert.Equal(t, int32(1), tapped.Load(), "Single tap should have fired") + tapped.Store(0) w.mouseClicked(w.viewport, glfw.MouseButton1, glfw.Press, 0) w.mouseClicked(w.viewport, glfw.MouseButton1, glfw.Release, 0) @@ -1252,7 +1252,7 @@ func TestWindow_TappedAndDoubleTapped(t *testing.T) { w.WaitForEvents() time.Sleep(500 * time.Millisecond) - assert.Equal(t, int32(2), atomic.LoadInt32(&tapped), "Double tap should have fired") + assert.Equal(t, int32(2), tapped.Load(), "Double tap should have fired") } func TestWindow_MouseEventContainsModifierKeys(t *testing.T) { diff --git a/widget/bind_helper.go b/widget/bind_helper.go index 9f02fc273a..069c5ed0cf 100644 --- a/widget/bind_helper.go +++ b/widget/bind_helper.go @@ -10,7 +10,7 @@ import ( // basicBinder stores a DataItem and a function to be called when it changes. // It provides a convenient way to replace data and callback independently. type basicBinder struct { - callback atomic.Value // func(binding.DataItem) + callback atomic.Pointer[func(binding.DataItem)] dataListenerPairLock sync.RWMutex dataListenerPair annotatedListener // access guarded by dataListenerPairLock @@ -19,10 +19,12 @@ type basicBinder struct { // Bind replaces the data item whose changes are tracked by the callback function. func (binder *basicBinder) Bind(data binding.DataItem) { listener := binding.NewDataListener(func() { // NB: listener captures `data` but always calls the up-to-date callback - f := binder.callback.Load() - if fn, ok := f.(func(binding.DataItem)); ok && fn != nil { - fn(data) + f := *binder.callback.Load() + if f == nil { + return } + + f(data) }) data.AddListener(listener) listenerInfo := annotatedListener{ @@ -47,7 +49,7 @@ func (binder *basicBinder) CallWithData(f func(data binding.DataItem)) { // SetCallback replaces the function to be called when the data changes. func (binder *basicBinder) SetCallback(f func(data binding.DataItem)) { - binder.callback.Store(f) + binder.callback.Store(&f) } // Unbind requests the callback to be no longer called when the previously bound From f0aae53b4867efe53fb950dc5cc87112ca1e7e35 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:30:32 +0100 Subject: [PATCH 201/248] Fix a bad revert --- internal/cache/base.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/cache/base.go b/internal/cache/base.go index 8f9f7cb3ab..204e8f4604 100644 --- a/internal/cache/base.go +++ b/internal/cache/base.go @@ -229,8 +229,7 @@ func (c *expiringCache) isExpired(now time.Time) bool { // setAlive updates expiration time. func (c *expiringCache) setAlive() { - expirationTIme := timeNow().Add(cacheDuration) - c.expires.Store(&expirationTIme) + c.expires.Store(timeNow().Add(cacheDuration)) } type expiringCacheNoLock struct { From 5eb3608bf16c100c627b617301e51bea68b376d7 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:35:49 +0100 Subject: [PATCH 202/248] No need to use execabs any more --- app/app_darwin.go | 4 ++-- app/app_desktop_darwin.go | 5 ++--- app/app_windows.go | 6 +++--- app/app_xdg.go | 4 ++-- dialog/file_xdg.go | 7 +++---- theme/gen.go | 5 ++--- 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/app/app_darwin.go b/app/app_darwin.go index 8e6e08668f..0feabf3feb 100644 --- a/app/app_darwin.go +++ b/app/app_darwin.go @@ -16,11 +16,11 @@ void sendNotification(char *title, char *content); import "C" import ( "fmt" + "os/exec" "strings" "unsafe" "fyne.io/fyne/v2" - "golang.org/x/sys/execabs" ) func (a *fyneApp) SendNotification(n *fyne.Notification) { @@ -53,7 +53,7 @@ func fallbackNotification(title, content string) { template := `display notification "%s" with title "%s"` script := fmt.Sprintf(template, escapeNotificationString(content), escapeNotificationString(title)) - err := execabs.Command("osascript", "-e", script).Start() + err := exec.Command("osascript", "-e", script).Start() if err != nil { fyne.LogError("Failed to launch darwin notify script", err) } diff --git a/app/app_desktop_darwin.go b/app/app_desktop_darwin.go index eb93777e8b..7305e95996 100644 --- a/app/app_desktop_darwin.go +++ b/app/app_desktop_darwin.go @@ -17,10 +17,9 @@ import "C" import ( "net/url" "os" + "os/exec" "path/filepath" - "golang.org/x/sys/execabs" - "fyne.io/fyne/v2" "fyne.io/fyne/v2/theme" ) @@ -54,7 +53,7 @@ func rootConfigDir() string { } func (a *fyneApp) OpenURL(url *url.URL) error { - cmd := execabs.Command("open", url.String()) + cmd := exec.Command("open", url.String()) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr return cmd.Run() } diff --git a/app/app_windows.go b/app/app_windows.go index 60d9b0a166..718cb6f348 100644 --- a/app/app_windows.go +++ b/app/app_windows.go @@ -7,11 +7,11 @@ import ( "fmt" "net/url" "os" + "os/exec" "path/filepath" "strings" "syscall" - "golang.org/x/sys/execabs" "golang.org/x/sys/windows/registry" "fyne.io/fyne/v2" @@ -62,7 +62,7 @@ func rootConfigDir() string { } func (a *fyneApp) OpenURL(url *url.URL) error { - cmd := execabs.Command("rundll32", "url.dll,FileProtocolHandler", url.String()) + cmd := exec.Command("rundll32", "url.dll,FileProtocolHandler", url.String()) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr return cmd.Run() } @@ -112,7 +112,7 @@ func runScript(name, script string) { defer os.Remove(tmpFilePath) launch := "(Get-Content -Encoding UTF8 -Path " + tmpFilePath + " -Raw) | Invoke-Expression" - cmd := execabs.Command("PowerShell", "-ExecutionPolicy", "Bypass", launch) + cmd := exec.Command("PowerShell", "-ExecutionPolicy", "Bypass", launch) cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} err = cmd.Run() if err != nil { diff --git a/app/app_xdg.go b/app/app_xdg.go index de39cecead..6d31a996a3 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -10,13 +10,13 @@ package app import ( "net/url" "os" + "os/exec" "path/filepath" "sync" "github.com/godbus/dbus/v5" "github.com/rymdport/portal/notification" "github.com/rymdport/portal/openuri" - "golang.org/x/sys/execabs" "fyne.io/fyne/v2" "fyne.io/fyne/v2/internal/build" @@ -38,7 +38,7 @@ func (a *fyneApp) OpenURL(url *url.URL) error { return err } - cmd := execabs.Command("xdg-open", url.String()) + cmd := exec.Command("xdg-open", url.String()) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr return cmd.Start() } diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 824aa1bce3..d73b6f781f 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -9,20 +9,19 @@ package dialog import ( "fmt" "os" + "os/exec" "fyne.io/fyne/v2" "fyne.io/fyne/v2/storage" - - "golang.org/x/sys/execabs" ) func getFavoriteLocation(homeURI fyne.URI, name, fallbackName string) (fyne.URI, error) { cmdName := "xdg-user-dir" - if _, err := execabs.LookPath(cmdName); err != nil { + if _, err := exec.LookPath(cmdName); err != nil { return storage.Child(homeURI, fallbackName) // no lookup possible } - cmd := execabs.Command(cmdName, name) + cmd := exec.Command(cmdName, name) loc, err := cmd.Output() if err != nil { return storage.Child(homeURI, fallbackName) diff --git a/theme/gen.go b/theme/gen.go index 11a2cb50ba..e4a86ae23f 100644 --- a/theme/gen.go +++ b/theme/gen.go @@ -9,13 +9,12 @@ import ( "go/format" "io" "os" + "os/exec" "path" "path/filepath" "runtime" "strings" - "golang.org/x/sys/execabs" - "fyne.io/fyne/v2" ) @@ -245,7 +244,7 @@ func createFontByStripping(newFontFile, fontFile string, runes []rune) error { for _, r := range runes { unicodes = append(unicodes, fmt.Sprintf(`%04X`, r)) } - cmd := execabs.Command( + cmd := exec.Command( "pyftsubset", fontPath(fontFile), "--output-file="+fontPath(newFontFile), From dff4cd7b930015b7f826dc92bf19240dc75dfe46 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 13:39:59 +0100 Subject: [PATCH 203/248] Fix some crashes for atomic function references --- internal/app/lifecycle.go | 16 ++++++++-------- widget/bind_helper.go | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/app/lifecycle.go b/internal/app/lifecycle.go index 71c826d93a..169bdcb9f6 100644 --- a/internal/app/lifecycle.go +++ b/internal/app/lifecycle.go @@ -50,40 +50,40 @@ func (l *Lifecycle) SetOnStopped(f func()) { // TriggerEnteredForeground will call the focus gained hook, if one is registered. func (l *Lifecycle) TriggerEnteredForeground() { - f := *l.onForeground.Load() + f := l.onForeground.Load() if f == nil { return } - f() + (*f)() } // TriggerExitedForeground will call the focus lost hook, if one is registered. func (l *Lifecycle) TriggerExitedForeground() { - f := *l.onBackground.Load() + f := l.onBackground.Load() if f == nil { return } - f() + (*f)() } // TriggerStarted will call the started hook, if one is registered. func (l *Lifecycle) TriggerStarted() { - f := *l.onStarted.Load() + f := l.onStarted.Load() if f == nil { return } - f() + (*f)() } // TriggerStopped will call the stopped hook, if one is registered, // and an internal stopped hook after that. func (l *Lifecycle) TriggerStopped() { - f := *l.onStopped.Load() + f := l.onStopped.Load() if f != nil { - f() + (*f)() } if l.onStoppedHookExecuted != nil { diff --git a/widget/bind_helper.go b/widget/bind_helper.go index 069c5ed0cf..019424b5da 100644 --- a/widget/bind_helper.go +++ b/widget/bind_helper.go @@ -19,12 +19,12 @@ type basicBinder struct { // Bind replaces the data item whose changes are tracked by the callback function. func (binder *basicBinder) Bind(data binding.DataItem) { listener := binding.NewDataListener(func() { // NB: listener captures `data` but always calls the up-to-date callback - f := *binder.callback.Load() + f := binder.callback.Load() if f == nil { return } - f(data) + (*f)(data) }) data.AddListener(listener) listenerInfo := annotatedListener{ From 77fe5c6cfebb16dc571c145994fb318704e24fbb Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 14:14:19 +0100 Subject: [PATCH 204/248] Fix incorrect generation of async queue --- internal/async/queue_pure_canvasobject.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/async/queue_pure_canvasobject.go b/internal/async/queue_pure_canvasobject.go index 05bd739014..e2f44fc10c 100755 --- a/internal/async/queue_pure_canvasobject.go +++ b/internal/async/queue_pure_canvasobject.go @@ -5,6 +5,8 @@ package async import ( + "sync/atomic" + "fyne.io/fyne/v2" ) From e015a117bac6a3b6e725ebe9a64c943e54a0353f Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 14:34:41 +0100 Subject: [PATCH 205/248] Update uri to v1.1.0 for faster performance --- go.mod | 2 +- go.sum | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index c590cf6416..88d4b1ac6d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e github.com/BurntSushi/toml v1.3.2 github.com/fogleman/gg v1.3.0 - github.com/fredbi/uri v1.0.0 + github.com/fredbi/uri v1.1.0 github.com/fsnotify/fsnotify v1.7.0 github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33 diff --git a/go.sum b/go.sum index 7041263d55..488bf10414 100644 --- a/go.sum +++ b/go.sum @@ -75,10 +75,11 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fredbi/uri v1.0.0 h1:s4QwUAZ8fz+mbTsukND+4V5f+mJ/wjaTokwstGUAemg= -github.com/fredbi/uri v1.0.0/go.mod h1:1xC40RnIOGCaQzswaOvrzvG/3M3F0hyDVb3aO/1iGy0= +github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8= +github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= @@ -168,6 +169,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -246,6 +248,7 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -277,7 +280,6 @@ github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -285,7 +287,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= From 53eceaeb56c1c2d5932a62c2f0186e700856c0e2 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 14:41:14 +0100 Subject: [PATCH 206/248] Update golang.org/x/image for various improvements --- go.mod | 4 ++-- go.sum | 26 ++++---------------------- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 88d4b1ac6d..b920644851 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.4.0 github.com/yuin/goldmark v1.5.5 - golang.org/x/image v0.11.0 + golang.org/x/image v0.14.0 golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda golang.org/x/mod v0.12.0 golang.org/x/sys v0.13.0 @@ -46,7 +46,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/tevino/abool v1.2.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect ) diff --git a/go.sum b/go.sum index 488bf10414..df68a95768 100644 --- a/go.sum +++ b/go.sum @@ -300,7 +300,6 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.5.5 h1:IJznPe8wOzfIKETmMkd06F8nXkmlhaHqFRM9l1hAGsU= github.com/yuin/goldmark v1.5.5/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -324,7 +323,6 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -338,8 +336,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo= -golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8= +golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= +golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -366,8 +364,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -407,8 +403,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -434,8 +428,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -483,15 +475,10 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -500,11 +487,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -561,8 +545,6 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From f68f986f2de7f7efd592c440827f1931ebc473e1 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 15:03:12 +0100 Subject: [PATCH 207/248] Update other golang.org/x deps for Go 1.18 base --- go.mod | 10 +++++----- go.sum | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index b920644851..4f60e2a5e1 100644 --- a/go.mod +++ b/go.mod @@ -29,10 +29,10 @@ require ( github.com/urfave/cli/v2 v2.4.0 github.com/yuin/goldmark v1.5.5 golang.org/x/image v0.14.0 - golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda - golang.org/x/mod v0.12.0 - golang.org/x/sys v0.13.0 - golang.org/x/tools v0.12.0 + golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a + golang.org/x/mod v0.14.0 + golang.org/x/sys v0.15.0 + golang.org/x/tools v0.16.1 ) require ( @@ -45,7 +45,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/tevino/abool v1.2.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect diff --git a/go.sum b/go.sum index df68a95768..925005bb9b 100644 --- a/go.sum +++ b/go.sum @@ -353,8 +353,8 @@ golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= -golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda h1:O+EUvnBNPwI4eLthn8W5K+cS8zQZfgTABPLNm6Bna34= -golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY= +golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a h1:sYbmY3FwUWCBTodZL1S3JUuOvaW6kM2o+clDzzDNBWg= +golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a/go.mod h1:Ede7gF0KGoHlj822RtphAHK1jLdrcuRBZg0sF1Q+SPc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= @@ -364,8 +364,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -403,8 +403,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -428,7 +428,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -476,8 +476,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -545,8 +545,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 50a1ab42a926bdc867b4251415771776cd1b3581 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 16:47:26 +0100 Subject: [PATCH 208/248] Rework async queue to not use unsafe --- internal/async/gen.go | 127 -------------------- internal/async/queue_canvasobject.go | 55 ++++++--- internal/async/queue_pure_canvasobject.go | 43 ------- internal/async/queue_unsafe_canvasobject.go | 41 ------- 4 files changed, 39 insertions(+), 227 deletions(-) delete mode 100755 internal/async/queue_pure_canvasobject.go delete mode 100755 internal/async/queue_unsafe_canvasobject.go diff --git a/internal/async/gen.go b/internal/async/gen.go index b31a3a68a9..2ff74fa252 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -45,29 +45,6 @@ func main() { Imports: "", }, }, - queueImpl: { - "queue_canvasobject.go": { - Type: "fyne.CanvasObject", - Name: "CanvasObject", - Imports: `import ( - "sync" - - "fyne.io/fyne/v2" - )`, - }, - }, - queueUnsafeStructImpl: { - "queue_unsafe_canvasobject.go": { - Type: "fyne.CanvasObject", - Name: "CanvasObject", - Imports: `import ( - "sync/atomic" - "unsafe" - - "fyne.io/fyne/v2" - )`, - }, - }, } for tmpl, types := range codes { @@ -190,107 +167,3 @@ func (ch *Unbounded{{.Name}}Chan) closed() { close(ch.close) } `)) - -var queueUnsafeStructImpl = template.Must(template.New("queue").Parse(`// Code generated by go run gen.go; DO NOT EDIT. - -package async - -{{.Imports}} - -// {{.Name}}Queue implements lock-free FIFO freelist based queue. -// -// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 -type {{.Name}}Queue struct { - head unsafe.Pointer - tail unsafe.Pointer - len atomic.Uint64 -} - -// New{{.Name}}Queue returns a queue for caching values. -func New{{.Name}}Queue() *{{.Name}}Queue { - head := &item{{.Name}}{next: nil, v: nil} - return &{{.Name}}Queue{ - tail: unsafe.Pointer(head), - head: unsafe.Pointer(head), - } -} - -type item{{.Name}} struct { - next unsafe.Pointer - v {{.Type}} -} - -func load{{.Name}}Item(p *unsafe.Pointer) *item{{.Name}} { - return (*item{{.Name}})(atomic.LoadPointer(p)) -} - -func cas{{.Name}}Item(p *unsafe.Pointer, old, new *item{{.Name}}) bool { - return atomic.CompareAndSwapPointer(p, unsafe.Pointer(old), unsafe.Pointer(new)) -} -`)) - -var queueImpl = template.Must(template.New("queue").Parse(`// Code generated by go run gen.go; DO NOT EDIT. - -package async - -{{.Imports}} - -var item{{.Name}}Pool = sync.Pool{ - New: func() interface{} { return &item{{.Name}}{next: nil, v: nil} }, -} - -// In puts the given value at the tail of the queue. -func (q *{{.Name}}Queue) In(v {{.Type}}) { - i := item{{.Name}}Pool.Get().(*item{{.Name}}) - i.next = nil - i.v = v - - var last, lastnext *item{{.Name}} - for { - last = load{{.Name}}Item(&q.tail) - lastnext = load{{.Name}}Item(&last.next) - if load{{.Name}}Item(&q.tail) == last { - if lastnext == nil { - if cas{{.Name}}Item(&last.next, lastnext, i) { - cas{{.Name}}Item(&q.tail, last, i) - q.len.Add(1) - return - } - } else { - cas{{.Name}}Item(&q.tail, last, lastnext) - } - } - } -} - -// Out removes and returns the value at the head of the queue. -// It returns nil if the queue is empty. -func (q *{{.Name}}Queue) Out() {{.Type}} { - var first, last, firstnext *item{{.Name}} - for { - first = load{{.Name}}Item(&q.head) - last = load{{.Name}}Item(&q.tail) - firstnext = load{{.Name}}Item(&first.next) - if first == load{{.Name}}Item(&q.head) { - if first == last { - if firstnext == nil { - return nil - } - cas{{.Name}}Item(&q.tail, last, firstnext) - } else { - v := firstnext.v - if cas{{.Name}}Item(&q.head, first, firstnext) { - q.len.Add(^uint64(0)) - item{{.Name}}Pool.Put(first) - return v - } - } - } - } -} - -// Len returns the length of the queue. -func (q *{{.Name}}Queue) Len() uint64 { - return q.len.Load() -} -`)) diff --git a/internal/async/queue_canvasobject.go b/internal/async/queue_canvasobject.go index 1af42f28df..5ccd42bf6e 100755 --- a/internal/async/queue_canvasobject.go +++ b/internal/async/queue_canvasobject.go @@ -1,36 +1,58 @@ -// Code generated by go run gen.go; DO NOT EDIT. - package async import ( "sync" + "sync/atomic" "fyne.io/fyne/v2" ) +// CanvasObjectQueue implements lock-free FIFO freelist based queue. +// +// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 +type CanvasObjectQueue struct { + head atomic.Pointer[itemCanvasObject] + tail atomic.Pointer[itemCanvasObject] + len atomic.Uint64 +} + +// NewCanvasObjectQueue returns a queue for caching values. +func NewCanvasObjectQueue() *CanvasObjectQueue { + head := &itemCanvasObject{} + queue := &CanvasObjectQueue{} + queue.head.Store(head) + queue.tail.Store(head) + return queue +} + +type itemCanvasObject struct { + next atomic.Pointer[itemCanvasObject] + v fyne.CanvasObject +} + var itemCanvasObjectPool = sync.Pool{ - New: func() interface{} { return &itemCanvasObject{next: nil, v: nil} }, + New: func() interface{} { return &itemCanvasObject{} }, } // In puts the given value at the tail of the queue. func (q *CanvasObjectQueue) In(v fyne.CanvasObject) { i := itemCanvasObjectPool.Get().(*itemCanvasObject) - i.next = nil + i.next.Store(nil) i.v = v var last, lastnext *itemCanvasObject for { - last = loadCanvasObjectItem(&q.tail) - lastnext = loadCanvasObjectItem(&last.next) - if loadCanvasObjectItem(&q.tail) == last { + last = q.tail.Load() + lastnext = last.next.Load() + if q.tail.Load() == last { if lastnext == nil { - if casCanvasObjectItem(&last.next, lastnext, i) { - casCanvasObjectItem(&q.tail, last, i) + if last.next.CompareAndSwap(lastnext, i) { + q.tail.CompareAndSwap(last, i) q.len.Add(1) return } } else { - casCanvasObjectItem(&q.tail, last, lastnext) + q.tail.CompareAndSwap(last, lastnext) } } } @@ -41,18 +63,19 @@ func (q *CanvasObjectQueue) In(v fyne.CanvasObject) { func (q *CanvasObjectQueue) Out() fyne.CanvasObject { var first, last, firstnext *itemCanvasObject for { - first = loadCanvasObjectItem(&q.head) - last = loadCanvasObjectItem(&q.tail) - firstnext = loadCanvasObjectItem(&first.next) - if first == loadCanvasObjectItem(&q.head) { + first = q.head.Load() + last = q.tail.Load() + firstnext = first.next.Load() + if first == q.head.Load() { if first == last { if firstnext == nil { return nil } - casCanvasObjectItem(&q.tail, last, firstnext) + + q.tail.CompareAndSwap(last, firstnext) } else { v := firstnext.v - if casCanvasObjectItem(&q.head, first, firstnext) { + if q.head.CompareAndSwap(first, firstnext) { q.len.Add(^uint64(0)) itemCanvasObjectPool.Put(first) return v diff --git a/internal/async/queue_pure_canvasobject.go b/internal/async/queue_pure_canvasobject.go deleted file mode 100755 index e2f44fc10c..0000000000 --- a/internal/async/queue_pure_canvasobject.go +++ /dev/null @@ -1,43 +0,0 @@ -// Code generated by go run gen.go; DO NOT EDIT. -//go:build js -// +build js - -package async - -import ( - "sync/atomic" - - "fyne.io/fyne/v2" -) - -// CanvasObjectQueue implements lock-free FIFO freelist based queue. -// -// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 -type CanvasObjectQueue struct { - head *itemCanvasObject - tail *itemCanvasObject - len atomic.Uint64 -} - -// NewCanvasObjectQueue returns a queue for caching values. -func NewCanvasObjectQueue() *CanvasObjectQueue { - head := &itemCanvasObject{next: nil, v: nil} - return &CanvasObjectQueue{ - tail: head, - head: head, - } -} - -type itemCanvasObject struct { - next *itemCanvasObject - v fyne.CanvasObject -} - -func loadCanvasObjectItem(p **itemCanvasObject) *itemCanvasObject { - return *p -} - -func casCanvasObjectItem(p **itemCanvasObject, _, new *itemCanvasObject) bool { - *p = new - return true -} diff --git a/internal/async/queue_unsafe_canvasobject.go b/internal/async/queue_unsafe_canvasobject.go deleted file mode 100755 index 5fbb99d26a..0000000000 --- a/internal/async/queue_unsafe_canvasobject.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by go run gen.go; DO NOT EDIT. - -package async - -import ( - "sync/atomic" - "unsafe" - - "fyne.io/fyne/v2" -) - -// CanvasObjectQueue implements lock-free FIFO freelist based queue. -// -// Reference: https://dl.acm.org/citation.cfm?doid=248052.248106 -type CanvasObjectQueue struct { - head unsafe.Pointer - tail unsafe.Pointer - len atomic.Uint64 -} - -// NewCanvasObjectQueue returns a queue for caching values. -func NewCanvasObjectQueue() *CanvasObjectQueue { - head := &itemCanvasObject{next: nil, v: nil} - return &CanvasObjectQueue{ - tail: unsafe.Pointer(head), - head: unsafe.Pointer(head), - } -} - -type itemCanvasObject struct { - next unsafe.Pointer - v fyne.CanvasObject -} - -func loadCanvasObjectItem(p *unsafe.Pointer) *itemCanvasObject { - return (*itemCanvasObject)(atomic.LoadPointer(p)) -} - -func casCanvasObjectItem(p *unsafe.Pointer, old, new *itemCanvasObject) bool { - return atomic.CompareAndSwapPointer(p, unsafe.Pointer(old), unsafe.Pointer(new)) -} From c8bbbfd1326ac4bd91a17374781b32d1ada38172 Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 16:59:56 +0100 Subject: [PATCH 209/248] More atomic.Value cleanups --- app.go | 15 +++------------ internal/cache/base.go | 9 +++++---- internal/cache/text.go | 4 ++-- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/app.go b/app.go index bffcf9c1ff..74ac0bf89a 100644 --- a/app.go +++ b/app.go @@ -81,20 +81,11 @@ type App interface { SetCloudProvider(CloudProvider) // configure cloud for this app } -// app contains an App variable, but due to atomic.Value restrictions on -// interfaces we need to use an indirect type, i.e. appContainer. -var app atomic.Pointer[appContainer] // appContainer - -// appContainer is a dummy container that holds an App instance. This -// struct exists to guarantee that atomic.Value can store objects with -// same type. -type appContainer struct { - current App -} +var app atomic.Pointer[App] // SetCurrentApp is an internal function to set the app instance currently running. func SetCurrentApp(current App) { - app.Store(&appContainer{current}) + app.Store(¤t) } // CurrentApp returns the current application, for which there is only 1 per process. @@ -104,7 +95,7 @@ func CurrentApp() App { LogError("Attempt to access current Fyne app when none is started", nil) return nil } - return val.current + return *val } // AppMetadata captures the build metadata for an application. diff --git a/internal/cache/base.go b/internal/cache/base.go index 204e8f4604..92b0167e11 100644 --- a/internal/cache/base.go +++ b/internal/cache/base.go @@ -155,7 +155,7 @@ func ResetThemeCaches() { }) fontSizeLock.Lock() - fontSizeCache = map[fontSizeEntry]fontMetric{} + fontSizeCache = map[fontSizeEntry]*fontMetric{} fontSizeLock.Unlock() } @@ -215,7 +215,7 @@ func matchesACanvas(cinfo *canvasInfo, canvases []fyne.Canvas) bool { } type expiringCache struct { - expires atomic.Value // time.time + expires atomic.Pointer[time.Time] } // isExpired check if the cache data is expired. @@ -224,12 +224,13 @@ func (c *expiringCache) isExpired(now time.Time) bool { if t == nil { return (time.Time{}).Before(now) } - return t.(time.Time).Before(now) + return (*t).Before(now) } // setAlive updates expiration time. func (c *expiringCache) setAlive() { - c.expires.Store(timeNow().Add(cacheDuration)) + time := timeNow().Add(cacheDuration) + c.expires.Store(&time) } type expiringCacheNoLock struct { diff --git a/internal/cache/text.go b/internal/cache/text.go index 13ab450577..465caec5bf 100644 --- a/internal/cache/text.go +++ b/internal/cache/text.go @@ -8,7 +8,7 @@ import ( ) var ( - fontSizeCache = map[fontSizeEntry]fontMetric{} + fontSizeCache = map[fontSizeEntry]*fontMetric{} fontSizeLock = sync.RWMutex{} ) @@ -40,7 +40,7 @@ func GetFontMetrics(text string, fontSize float32, style fyne.TextStyle) (size f // SetFontMetrics stores a calculated font size and baseline for parameters that were missing from the cache. func SetFontMetrics(text string, fontSize float32, style fyne.TextStyle, size fyne.Size, base float32) { ent := fontSizeEntry{text, fontSize, style} - metric := fontMetric{size: size, baseLine: base} + metric := &fontMetric{size: size, baseLine: base} metric.setAlive() fontSizeLock.Lock() fontSizeCache[ent] = metric From 325103a98fb3ae8f46bbf7eb726c1fc347dec31e Mon Sep 17 00:00:00 2001 From: Jacalz Date: Tue, 26 Dec 2023 17:04:39 +0100 Subject: [PATCH 210/248] Use atomic.Pointer for preference bindings --- data/binding/gen.go | 11 ++++------ data/binding/preference.go | 44 ++++++++++++++------------------------ 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/data/binding/gen.go b/data/binding/gen.go index 6b444a8ad6..ec6afd3868 100644 --- a/data/binding/gen.go +++ b/data/binding/gen.go @@ -122,7 +122,7 @@ type prefBound{{ .Name }} struct { base key string p fyne.Preferences - cache atomic.Value // {{ .Type }} + cache atomic.Pointer[{{ .Type }}] } // BindPreference{{ .Name }} returns a bindable {{ .Type }} value that is managed by the application preferences. @@ -148,7 +148,7 @@ func BindPreference{{ .Name }}(key string, p fyne.Preferences) {{ .Name }} { func (b *prefBound{{ .Name }}) Get() ({{ .Type }}, error) { cache := b.p.{{ .Name }}(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -163,11 +163,8 @@ func (b *prefBound{{ .Name }}) Set(v {{ .Type }}) error { func (b *prefBound{{ .Name }}) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.({{ .Type }}) - if b.p.{{ .Name }}(b.key) == cache { - return - } + if val != nil && b.p.{{ .Name }}(b.key) == *val { + return } b.trigger() } diff --git a/data/binding/preference.go b/data/binding/preference.go index 27dc3d9448..81b0b7c1be 100644 --- a/data/binding/preference.go +++ b/data/binding/preference.go @@ -15,7 +15,7 @@ type prefBoundBool struct { base key string p fyne.Preferences - cache atomic.Value // bool + cache atomic.Pointer[bool] } // BindPreferenceBool returns a bindable bool value that is managed by the application preferences. @@ -41,7 +41,7 @@ func BindPreferenceBool(key string, p fyne.Preferences) Bool { func (b *prefBoundBool) Get() (bool, error) { cache := b.p.Bool(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -56,11 +56,8 @@ func (b *prefBoundBool) Set(v bool) error { func (b *prefBoundBool) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.(bool) - if b.p.Bool(b.key) == cache { - return - } + if val != nil && b.p.Bool(b.key) == *val { + return } b.trigger() } @@ -73,7 +70,7 @@ type prefBoundFloat struct { base key string p fyne.Preferences - cache atomic.Value // float64 + cache atomic.Pointer[float64] } // BindPreferenceFloat returns a bindable float64 value that is managed by the application preferences. @@ -99,7 +96,7 @@ func BindPreferenceFloat(key string, p fyne.Preferences) Float { func (b *prefBoundFloat) Get() (float64, error) { cache := b.p.Float(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -114,11 +111,8 @@ func (b *prefBoundFloat) Set(v float64) error { func (b *prefBoundFloat) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.(float64) - if b.p.Float(b.key) == cache { - return - } + if val != nil && b.p.Float(b.key) == *val { + return } b.trigger() } @@ -131,7 +125,7 @@ type prefBoundInt struct { base key string p fyne.Preferences - cache atomic.Value // int + cache atomic.Pointer[int] } // BindPreferenceInt returns a bindable int value that is managed by the application preferences. @@ -157,7 +151,7 @@ func BindPreferenceInt(key string, p fyne.Preferences) Int { func (b *prefBoundInt) Get() (int, error) { cache := b.p.Int(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -172,11 +166,8 @@ func (b *prefBoundInt) Set(v int) error { func (b *prefBoundInt) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.(int) - if b.p.Int(b.key) == cache { - return - } + if val != nil && b.p.Int(b.key) == *val { + return } b.trigger() } @@ -189,7 +180,7 @@ type prefBoundString struct { base key string p fyne.Preferences - cache atomic.Value // string + cache atomic.Pointer[string] } // BindPreferenceString returns a bindable string value that is managed by the application preferences. @@ -215,7 +206,7 @@ func BindPreferenceString(key string, p fyne.Preferences) String { func (b *prefBoundString) Get() (string, error) { cache := b.p.String(b.key) - b.cache.Store(cache) + b.cache.Store(&cache) return cache, nil } @@ -230,11 +221,8 @@ func (b *prefBoundString) Set(v string) error { func (b *prefBoundString) checkForChange() { val := b.cache.Load() - if val != nil { - cache := val.(string) - if b.p.String(b.key) == cache { - return - } + if val != nil && b.p.String(b.key) == *val { + return } b.trigger() } From b25a148187564771e7a1e78e6cf0607453c051ad Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 28 Dec 2023 22:13:31 +0100 Subject: [PATCH 211/248] internal/async: Add a generic unbound channel Requires Go 1.21 for the clear() builtin but will allow us to cut down on generation scripts later on. --- internal/async/chan_canvasobject.go | 4 +- internal/async/chan_func.go | 4 +- internal/async/chan_go1.21.go | 124 ++++++++++++++++++++++++++++ internal/async/chan_interface.go | 4 +- internal/async/gen.go | 2 +- 5 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 internal/async/chan_go1.21.go diff --git a/internal/async/chan_canvasobject.go b/internal/async/chan_canvasobject.go index 69ca5d7afb..7a88a68368 100755 --- a/internal/async/chan_canvasobject.go +++ b/internal/async/chan_canvasobject.go @@ -1,5 +1,7 @@ -// Code generated by go run gen.go; DO NOT EDIT. +//go:build !go1.21 +// Code generated by go run gen.go; DO NOT EDIT. +// package async import "fyne.io/fyne/v2" diff --git a/internal/async/chan_func.go b/internal/async/chan_func.go index ccf4ad9b31..5c58619343 100755 --- a/internal/async/chan_func.go +++ b/internal/async/chan_func.go @@ -1,5 +1,7 @@ -// Code generated by go run gen.go; DO NOT EDIT. +//go:build !go1.21 +// Code generated by go run gen.go; DO NOT EDIT. +// package async // UnboundedFuncChan is a channel with an unbounded buffer for caching diff --git a/internal/async/chan_go1.21.go b/internal/async/chan_go1.21.go new file mode 100644 index 0000000000..7353d7caa9 --- /dev/null +++ b/internal/async/chan_go1.21.go @@ -0,0 +1,124 @@ +//go:build go1.21 + +package async + +import "fyne.io/fyne/v2" + +// UnboundedFuncChan is a channel with an unbounded buffer for caching +// Func objects. A channel must be closed via Close method. +type UnboundedChan[T any] struct { + in, out chan T + close chan struct{} + q []T +} + +// NewUnboundedFuncChan returns a unbounded channel with unlimited capacity. +func NewUnboundedChan[T any]() *UnboundedChan[T] { + ch := &UnboundedChan[T]{ + // The size of Func is less than 16 bytes, we use 16 to fit + // a CPU cache line (L2, 256 Bytes), which may reduce cache misses. + in: make(chan T, 16), + out: make(chan T, 16), + close: make(chan struct{}), + } + go ch.processing() + return ch +} + +// In returns the send channel of the given channel, which can be used to +// send values to the channel. +func (ch *UnboundedChan[T]) In() chan<- T { return ch.in } + +// Out returns the receive channel of the given channel, which can be used +// to receive values from the channel. +func (ch *UnboundedChan[T]) Out() <-chan T { return ch.out } + +// Close closes the channel. +func (ch *UnboundedChan[T]) Close() { ch.close <- struct{}{} } + +func (ch *UnboundedChan[T]) processing() { + // This is a preallocation of the internal unbounded buffer. + // The size is randomly picked. But if one changes the size, the + // reallocation size at the subsequent for loop should also be + // changed too. Furthermore, there is no memory leak since the + // queue is garbage collected. + ch.q = make([]T, 0, 1<<10) + for { + select { + case e, ok := <-ch.in: + if !ok { + // We don't want the input channel be accidentally closed + // via close() instead of Close(). If that happens, it is + // a misuse, do a panic as warning. + panic("async: misuse of unbounded channel, In() was closed") + } + ch.q = append(ch.q, e) + case <-ch.close: + ch.closed() + return + } + for len(ch.q) > 0 { + select { + case ch.out <- ch.q[0]: + clear(ch.q[:1]) // de-reference earlier to help GC + ch.q = ch.q[1:] + case e, ok := <-ch.in: + if !ok { + // We don't want the input channel be accidentally closed + // via close() instead of Close(). If that happens, it is + // a misuse, do a panic as warning. + panic("async: misuse of unbounded channel, In() was closed") + } + ch.q = append(ch.q, e) + case <-ch.close: + ch.closed() + return + } + } + // If the remaining capacity is too small, we prefer to + // reallocate the entire buffer. + if cap(ch.q) < 1<<5 { + ch.q = make([]T, 0, 1<<10) + } + } +} + +func (ch *UnboundedChan[T]) closed() { + close(ch.in) + for e := range ch.in { + ch.q = append(ch.q, e) + } + for len(ch.q) > 0 { + select { + case ch.out <- ch.q[0]: + clear(ch.q[:1]) // de-reference earlier to help GC + ch.q = ch.q[1:] + default: + } + } + close(ch.out) + close(ch.close) +} + +// UnboundedFuncChan is a channel with an unbounded buffer for caching +// Func objects. A channel must be closed via Close method +type UnboundedFuncChan = UnboundedChan[func()] + +// NewUnboundedInterfaceChan returns a unbounded channel, of func(), with unlimited capacity. +func NewUnboundedFuncChan() *UnboundedChan[func()] { + return NewUnboundedChan[func()]() +} + +// UnboundedInterfaceChan is a channel with an unbounded buffer for caching +// Interface objects. A channel must be closed via Close method. +type UnboundedInterfaceChan = UnboundedChan[any] + +// NewUnboundedInterfaceChan returns a unbounded channel, of any type, with unlimited capacity. +func NewUnboundedInterfaceChan() *UnboundedChan[any] { + return NewUnboundedChan[any]() +} + +// NewUnboundedCanvasObjectChan returns a unbounded channel, of canvas objects, with unlimited capacity. +func NewUnboundedCanvasObjectChan() *UnboundedChan[fyne.CanvasObject] { + return NewUnboundedChan[fyne.CanvasObject]() +} diff --git a/internal/async/chan_interface.go b/internal/async/chan_interface.go index 9c39f6f605..ec7533c0d2 100755 --- a/internal/async/chan_interface.go +++ b/internal/async/chan_interface.go @@ -1,5 +1,7 @@ -// Code generated by go run gen.go; DO NOT EDIT. +//go:build !go1.21 +// Code generated by go run gen.go; DO NOT EDIT. +// package async // UnboundedInterfaceChan is a channel with an unbounded buffer for caching diff --git a/internal/async/gen.go b/internal/async/gen.go index 2ff74fa252..c52b265a0c 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -66,7 +66,7 @@ func main() { } var chanImpl = template.Must(template.New("async").Parse(`// Code generated by go run gen.go; DO NOT EDIT. - +//go:build !go1.21 package async {{.Imports}} From 317df119fd38828f514d94e8d6fe140bbf8f0d94 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 28 Dec 2023 22:22:35 +0100 Subject: [PATCH 212/248] Reorder fields to the top --- internal/async/chan_go1.21.go | 50 +++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/internal/async/chan_go1.21.go b/internal/async/chan_go1.21.go index 7353d7caa9..d04bb7e3af 100644 --- a/internal/async/chan_go1.21.go +++ b/internal/async/chan_go1.21.go @@ -4,6 +4,33 @@ package async import "fyne.io/fyne/v2" +// UnboundedFuncChan is a channel with an unbounded buffer for caching +// Func objects. A channel must be closed via Close method +type UnboundedFuncChan = UnboundedChan[func()] + +// NewUnboundedInterfaceChan returns a unbounded channel, of func(), with unlimited capacity. +func NewUnboundedFuncChan() *UnboundedFuncChan { + return NewUnboundedChan[func()]() +} + +// UnboundedInterfaceChan is a channel with an unbounded buffer for caching +// Interface objects. A channel must be closed via Close method. +type UnboundedInterfaceChan = UnboundedChan[any] + +// NewUnboundedInterfaceChan returns a unbounded channel, of any type, with unlimited capacity. +func NewUnboundedInterfaceChan() *UnboundedInterfaceChan { + return NewUnboundedChan[any]() +} + +// UnboundedCanvasObjectChan is a channel with an unbounded buffer for caching +// CanvasObject objects. A channel must be closed via Close method. +type UnboundedCanvasObjectChan = UnboundedChan[fyne.CanvasObject] + +// NewUnboundedCanvasObjectChan returns a unbounded channel, of canvas objects, with unlimited capacity. +func NewUnboundedCanvasObjectChan() *UnboundedChan[fyne.CanvasObject] { + return NewUnboundedChan[fyne.CanvasObject]() +} + // UnboundedFuncChan is a channel with an unbounded buffer for caching // Func objects. A channel must be closed via Close method. type UnboundedChan[T any] struct { @@ -99,26 +126,3 @@ func (ch *UnboundedChan[T]) closed() { close(ch.out) close(ch.close) } - -// UnboundedFuncChan is a channel with an unbounded buffer for caching -// Func objects. A channel must be closed via Close method -type UnboundedFuncChan = UnboundedChan[func()] - -// NewUnboundedInterfaceChan returns a unbounded channel, of func(), with unlimited capacity. -func NewUnboundedFuncChan() *UnboundedChan[func()] { - return NewUnboundedChan[func()]() -} - -// UnboundedInterfaceChan is a channel with an unbounded buffer for caching -// Interface objects. A channel must be closed via Close method. -type UnboundedInterfaceChan = UnboundedChan[any] - -// NewUnboundedInterfaceChan returns a unbounded channel, of any type, with unlimited capacity. -func NewUnboundedInterfaceChan() *UnboundedChan[any] { - return NewUnboundedChan[any]() -} - -// NewUnboundedCanvasObjectChan returns a unbounded channel, of canvas objects, with unlimited capacity. -func NewUnboundedCanvasObjectChan() *UnboundedChan[fyne.CanvasObject] { - return NewUnboundedChan[fyne.CanvasObject]() -} From 89db36b298106598a0a69b6a7252810a360a75ae Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 28 Dec 2023 22:29:45 +0100 Subject: [PATCH 213/248] Update an out of date comment --- internal/async/chan_go1.21.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/async/chan_go1.21.go b/internal/async/chan_go1.21.go index d04bb7e3af..7b0407c94e 100644 --- a/internal/async/chan_go1.21.go +++ b/internal/async/chan_go1.21.go @@ -42,7 +42,7 @@ type UnboundedChan[T any] struct { // NewUnboundedFuncChan returns a unbounded channel with unlimited capacity. func NewUnboundedChan[T any]() *UnboundedChan[T] { ch := &UnboundedChan[T]{ - // The size of Func is less than 16 bytes, we use 16 to fit + // The size of Func, Interface, and CanvasObject are all less than 16 bytes, we use 16 to fit // a CPU cache line (L2, 256 Bytes), which may reduce cache misses. in: make(chan T, 16), out: make(chan T, 16), From 74ae818080f734cf76e40796c02ffc7801b5606b Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 28 Dec 2023 22:38:48 +0100 Subject: [PATCH 214/248] Make goimports happier --- internal/async/chan_canvasobject.go | 1 - internal/async/chan_func.go | 1 - internal/async/chan_interface.go | 1 - internal/async/gen.go | 5 +++-- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/internal/async/chan_canvasobject.go b/internal/async/chan_canvasobject.go index 7a88a68368..6af88ba323 100755 --- a/internal/async/chan_canvasobject.go +++ b/internal/async/chan_canvasobject.go @@ -1,7 +1,6 @@ //go:build !go1.21 // Code generated by go run gen.go; DO NOT EDIT. -// package async import "fyne.io/fyne/v2" diff --git a/internal/async/chan_func.go b/internal/async/chan_func.go index 5c58619343..26e2e926f9 100755 --- a/internal/async/chan_func.go +++ b/internal/async/chan_func.go @@ -1,7 +1,6 @@ //go:build !go1.21 // Code generated by go run gen.go; DO NOT EDIT. -// package async // UnboundedFuncChan is a channel with an unbounded buffer for caching diff --git a/internal/async/chan_interface.go b/internal/async/chan_interface.go index ec7533c0d2..89e065ce5c 100755 --- a/internal/async/chan_interface.go +++ b/internal/async/chan_interface.go @@ -1,7 +1,6 @@ //go:build !go1.21 // Code generated by go run gen.go; DO NOT EDIT. -// package async // UnboundedInterfaceChan is a channel with an unbounded buffer for caching diff --git a/internal/async/gen.go b/internal/async/gen.go index c52b265a0c..846ff3f9a9 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -65,8 +65,9 @@ func main() { } } -var chanImpl = template.Must(template.New("async").Parse(`// Code generated by go run gen.go; DO NOT EDIT. -//go:build !go1.21 +var chanImpl = template.Must(template.New("async").Parse(`//go:build !go1.21 + +// Code generated by go run gen.go; DO NOT EDIT. package async {{.Imports}} From 049f4e410b98f9c81b59ac5ba921041dc381b02e Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 30 Dec 2023 21:55:41 +0100 Subject: [PATCH 215/248] Update systray to Go 1.19 version --- go.mod | 3 +-- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 4f60e2a5e1..3ae5699b13 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module fyne.io/fyne/v2 go 1.19 require ( - fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e + fyne.io/systray v1.10.1-0.20231230205326-d160fd363db9 github.com/BurntSushi/toml v1.3.2 github.com/fogleman/gg v1.3.0 github.com/fredbi/uri v1.1.0 @@ -44,7 +44,6 @@ require ( github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/tevino/abool v1.2.0 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 925005bb9b..13bbed2896 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e h1:Hvs+kW2VwCzNToF3FmnIAzmivNgrclwPgoUdVSrjkP8= -fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e/go.mod h1:oM2AQqGJ1AMo4nNqZFYU8xYygSBZkW2hmdJ7n4yjedE= +fyne.io/systray v1.10.1-0.20231230205326-d160fd363db9 h1:E/gHmMVyk8TuI6JIgNIv/Qu1JABMVFBIkQ8lYRa5gkQ= +fyne.io/systray v1.10.1-0.20231230205326-d160fd363db9/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -290,8 +290,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA= -github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg= github.com/urfave/cli/v2 v2.4.0 h1:m2pxjjDFgDxSPtO8WSdbndj17Wu2y8vOT86wE/tjr+I= github.com/urfave/cli/v2 v2.4.0/go.mod h1:NX9W0zmTvedE5oDoOMs2RTC8RvdK98NTYZE5LbaEYPg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= From 081664a96fe236fa09f2943366f96ba775069a2f Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 2 Jan 2024 11:46:17 +0100 Subject: [PATCH 216/248] Update to glfw-js without GopherJS support --- go.mod | 3 +-- go.sum | 8 ++------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 3ae5699b13..e93f68042d 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/fredbi/uri v1.1.0 github.com/fsnotify/fsnotify v1.7.0 github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe - github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33 + github.com/fyne-io/glfw-js v0.0.0-20240101223322-6e1efdc71b7a github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7 @@ -47,5 +47,4 @@ require ( golang.org/x/net v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect ) diff --git a/go.sum b/go.sum index 13bbed2896..70e172995a 100644 --- a/go.sum +++ b/go.sum @@ -85,8 +85,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe h1:A/wiwvQ0CAjPkuJytaD+SsXkPU0asQ+guQEIg1BJGX4= github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe/go.mod h1:d4clgH0/GrRwWjRzJJQXxT/h1TyuNSfF/X64zb/3Ggg= -github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33 h1:0Ayg0/do/sqX2R7NonoLZvWxGrd9utTVf3A0QvCbC88= -github.com/fyne-io/glfw-js v0.0.0-20220517201726-bebc2019cd33/go.mod h1:gLRWYfYnMA9TONeppRSikMdXlHQ97xVsPojddUv3b/E= +github.com/fyne-io/glfw-js v0.0.0-20240101223322-6e1efdc71b7a h1:ybgRdYvAHTn93HW79bLiBiJwVL4jVeyGQRZMgImoeWs= +github.com/fyne-io/glfw-js v0.0.0-20240101223322-6e1efdc71b7a/go.mod h1:gsGA2dotD4v0SR6PmPCYvS9JuOeMwAtmfvDE7mbYXMY= github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 h1:hnLq+55b7Zh7/2IRzWCpiTcAvjv/P8ERF+N7+xXbZhk= github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2/go.mod h1:eO7W361vmlPOrykIg+Rsh1SZ3tQBaOsfzZhsIOb/Lm0= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -95,7 +95,6 @@ github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVin github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7 h1:7tf/0aw5DxRQjr7WaNqgtjidub6v21L2cogKIbMcTYw= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -179,7 +178,6 @@ github.com/gopherjs/gopherjs v0.0.0-20211219123610-ec9572f70e60/go.mod h1:cz9oNY github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/goxjs/gl v0.0.0-20210104184919-e3fafc6f8f2a/go.mod h1:dy/f2gjY09hwVfIyATps4G2ai7/hLwLkc5TrPqONuXY= -github.com/goxjs/glfw v0.0.0-20191126052801-d2efb5f20838/go.mod h1:oS8P8gVOT4ywTcjV6wZlOU4GuVFQ8F5328KY3MJ79CY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -664,8 +662,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 h1:oomkgU6VaQDsV6qZby2uz1Lap0eXmku8+2em3A/l700= -honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2/go.mod h1:sUMDUKNB2ZcVjt92UnLy3cdGs+wDAcrPdV3JP6sVgA4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 32bc3d709addc80ec060e3e23d52e667c813de3f Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 2 Jan 2024 12:18:41 +0100 Subject: [PATCH 217/248] Switch from +build to go:build --- app/app_darwin.go | 1 - app/app_darwin.m | 1 - app/app_darwin_test.go | 1 - app/app_desktop_darwin.go | 1 - app/app_desktop_darwin.m | 1 - app/app_gl.go | 1 - app/app_goxjs.go | 3 --- app/app_mobile.go | 2 -- app/app_mobile_and.c | 1 - app/app_mobile_and.go | 1 - app/app_mobile_and_test.go | 1 - app/app_mobile_ios.go | 1 - app/app_mobile_ios.m | 1 - app/app_notlegacy_darwin.go | 1 - app/app_openurl_wasm.go | 1 - app/app_openurl_web.go | 1 - app/app_other.go | 1 - app/app_software.go | 1 - app/app_theme_wasm.go | 1 - app/app_theme_web.go | 1 - app/app_windows.go | 1 - app/app_windows_test.go | 1 - app/app_xdg.go | 5 ----- app/preferences_android.go | 1 - app/preferences_ios.go | 1 - app/preferences_mobile.go | 1 - app/preferences_other.go | 1 - app/settings_desktop.go | 1 - app/settings_desktop_test.go | 1 - app/settings_file.go | 1 - app/settings_goxjs.go | 1 - app/settings_mobile.go | 1 - app/settings_noanimation.go | 1 - cmd/fyne/internal/commands/install_other.go | 1 - cmd/fyne/internal/mobile/binres/genarsc.go | 1 - cmd/fyne/internal/mobile/gendex/gendex.go | 1 - container/apptabs_desktop_test.go | 1 - container/apptabs_mobile_test.go | 1 - container/doctabs_desktop_test.go | 1 - container/doctabs_mobile_test.go | 1 - data/binding/gen.go | 1 - dialog/file_darwin.go | 1 - dialog/file_goxjs.go | 1 - dialog/file_mobile.go | 1 - dialog/file_other_test.go | 1 - dialog/file_unix.go | 1 - dialog/file_xdg.go | 4 ---- dialog/file_xdg_flatpak.go | 1 - dialog/file_xdg_notflatpak.go | 1 - dialog/file_xdg_test.go | 2 -- driver/native_android.go | 1 - driver/native_other.go | 1 - internal/animation/animation_test.go | 1 - internal/async/gen.go | 1 - internal/build/driver_flatpak.go | 1 - internal/build/driver_notflatpak.go | 1 - internal/build/driver_notwayland.go | 1 - internal/build/driver_wayland.go | 1 - internal/build/hints_disabled.go | 1 - internal/build/hints_enabled.go | 1 - internal/build/mode_debug.go | 1 - internal/build/mode_release.go | 1 - internal/build/mode_standard.go | 1 - internal/cache/texture_desktop.go | 1 - internal/cache/texture_desktop_test.go | 1 - internal/cache/texture_gomobile.go | 1 - internal/cache/texture_gomobile_test.go | 1 - internal/cache/texture_goxjs.go | 1 - internal/driver/glfw/canvas_other_test.go | 3 --- internal/driver/glfw/canvas_test.go | 1 - internal/driver/glfw/clipboard.go | 1 - internal/driver/glfw/clipboard_goxjs.go | 1 - internal/driver/glfw/device_desktop.go | 1 - internal/driver/glfw/device_goxjs.go | 1 - internal/driver/glfw/device_test.go | 1 - internal/driver/glfw/driver_desktop.go | 1 - internal/driver/glfw/driver_goxjs.go | 1 - internal/driver/glfw/driver_notwindows.go | 1 - internal/driver/glfw/driver_test.go | 1 - internal/driver/glfw/driver_web.go | 1 - internal/driver/glfw/glfw_core.go | 3 --- internal/driver/glfw/glfw_es.go | 4 ---- internal/driver/glfw/glfw_goxjs.go | 1 - internal/driver/glfw/glfw_test.go | 1 - internal/driver/glfw/loop_desktop.go | 1 - internal/driver/glfw/loop_goxjs.go | 1 - internal/driver/glfw/loop_test.go | 1 - internal/driver/glfw/menu_bar_test.go | 2 -- internal/driver/glfw/menu_darwin.go | 1 - internal/driver/glfw/menu_darwin.m | 1 - internal/driver/glfw/menu_darwin_test.go | 1 - internal/driver/glfw/menu_notweb.go | 1 - internal/driver/glfw/menu_other.go | 1 - internal/driver/glfw/menu_other_test.go | 3 --- internal/driver/glfw/menu_test.go | 1 - internal/driver/glfw/menu_web.go | 1 - internal/driver/glfw/scale_test.go | 1 - internal/driver/glfw/scroll_speed_darwin.go | 1 - internal/driver/glfw/scroll_speed_default.go | 1 - internal/driver/glfw/shortcuts_other.go | 1 - internal/driver/glfw/shortcuts_wasm.go | 1 - internal/driver/glfw/window_desktop.go | 1 - internal/driver/glfw/window_desktop_test.go | 1 - internal/driver/glfw/window_goxjs.go | 1 - internal/driver/glfw/window_notwindows.go | 1 - internal/driver/glfw/window_notxdg.go | 1 - internal/driver/glfw/window_test.go | 1 - internal/driver/glfw/window_wasm.go | 1 - internal/driver/glfw/window_wayland.go | 2 -- internal/driver/glfw/window_x11.go | 4 ---- internal/driver/glfw/window_xdg.go | 1 - internal/driver/mobile/android.c | 1 - internal/driver/mobile/app/android.c | 2 +- internal/driver/mobile/app/android.go | 1 - internal/driver/mobile/app/app.go | 1 - internal/driver/mobile/app/callfn/callfn.go | 2 -- internal/driver/mobile/app/darwin_desktop.go | 1 - internal/driver/mobile/app/darwin_desktop.m | 3 +-- internal/driver/mobile/app/darwin_ios.go | 1 - internal/driver/mobile/app/darwin_ios.m | 1 - internal/driver/mobile/app/shiny.go | 1 - internal/driver/mobile/app/x11.c | 1 - internal/driver/mobile/app/x11.go | 1 - internal/driver/mobile/canvas_test.go | 1 - internal/driver/mobile/clipboard_android.go | 1 - internal/driver/mobile/clipboard_desktop.go | 1 - internal/driver/mobile/clipboard_ios.go | 1 - internal/driver/mobile/clipboard_ios.m | 1 - internal/driver/mobile/device_android.go | 1 - internal/driver/mobile/device_desktop.go | 1 - internal/driver/mobile/device_ios.go | 1 - internal/driver/mobile/device_wayland.go | 1 - internal/driver/mobile/file_android.go | 1 - internal/driver/mobile/file_desktop.go | 1 - internal/driver/mobile/file_ios.go | 1 - internal/driver/mobile/file_ios.m | 1 - internal/driver/mobile/folder_android.go | 1 - internal/driver/mobile/folder_desktop.go | 1 - internal/driver/mobile/folder_ios.go | 1 - internal/driver/mobile/folder_ios.m | 1 - internal/driver/mobile/gl/gl.go | 1 - internal/driver/mobile/gl/types.go | 1 - internal/driver/mobile/gl/work.c | 1 - internal/driver/mobile/gl/work.go | 1 - internal/driver/mobile/gl/work_other.go | 2 -- internal/driver/mobile/menu_test.go | 1 - internal/driver/mobile/mobileinit/mobileinit_ios.go | 2 -- internal/driver/mobile/mobileinit/mobileinit_ios.m | 2 -- internal/driver/mobile/uri.go | 1 - internal/driver/mobile/uri_android.go | 1 - internal/hints_disabled.go | 1 - internal/hints_enabled.go | 1 - internal/painter/gl/draw_test.go | 1 - internal/painter/gl/gl_core.go | 1 - internal/painter/gl/gl_es.go | 7 ------- internal/painter/gl/gl_gomobile.go | 2 -- internal/painter/gl/gl_goxjs.go | 1 - internal/painter/gl/gl_test.go | 1 - key_other.go | 1 - test/device_mobile.go | 1 - test/device_other.go | 1 - theme/bundled-emoji.go | 1 - theme/gen.go | 3 +-- theme/theme_hints.go | 1 - theme/theme_other.go | 1 - theme/unbundled-emoji.go | 1 - widget/fileicon_internal_test.go | 1 - widget/menu_desktop_test.go | 1 - widget/menu_internal_desktop_test.go | 1 - widget/menu_internal_mobile_test.go | 1 - widget/menu_item_other.go | 1 - widget/menu_mobile_test.go | 1 - widget/popup_menu_desktop_test.go | 1 - widget/table_desktop_test.go | 1 - 174 files changed, 3 insertions(+), 212 deletions(-) diff --git a/app/app_darwin.go b/app/app_darwin.go index 8e6e08668f..54087b71d1 100644 --- a/app/app_darwin.go +++ b/app/app_darwin.go @@ -1,5 +1,4 @@ //go:build !ci && !wasm && !test_web_driver -// +build !ci,!wasm,!test_web_driver package app diff --git a/app/app_darwin.m b/app/app_darwin.m index e5d0718f4e..5afb52bc56 100644 --- a/app/app_darwin.m +++ b/app/app_darwin.m @@ -1,5 +1,4 @@ //go:build !ci -// +build !ci #import #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 diff --git a/app/app_darwin_test.go b/app/app_darwin_test.go index 960b22ce8d..ec65428fa7 100644 --- a/app/app_darwin_test.go +++ b/app/app_darwin_test.go @@ -1,5 +1,4 @@ //go:build !ci && !ios -// +build !ci,!ios package app diff --git a/app/app_desktop_darwin.go b/app/app_desktop_darwin.go index eb93777e8b..33adb3fb20 100644 --- a/app/app_desktop_darwin.go +++ b/app/app_desktop_darwin.go @@ -1,5 +1,4 @@ //go:build !ci && !ios && !wasm && !test_web_driver -// +build !ci,!ios,!wasm,!test_web_driver package app diff --git a/app/app_desktop_darwin.m b/app/app_desktop_darwin.m index b28a3ee71b..a571f6642a 100644 --- a/app/app_desktop_darwin.m +++ b/app/app_desktop_darwin.m @@ -1,5 +1,4 @@ //go:build !ci && !ios -// +build !ci,!ios extern void themeChanged(); diff --git a/app/app_gl.go b/app/app_gl.go index 511f6e26fe..1f34caaa2f 100644 --- a/app/app_gl.go +++ b/app/app_gl.go @@ -1,5 +1,4 @@ //go:build !ci && !android && !ios && !mobile -// +build !ci,!android,!ios,!mobile package app diff --git a/app/app_goxjs.go b/app/app_goxjs.go index 2392408875..e003518ea6 100644 --- a/app/app_goxjs.go +++ b/app/app_goxjs.go @@ -1,7 +1,4 @@ //go:build !ci && (!android || !ios || !mobile) && (wasm || test_web_driver) -// +build !ci -// +build !android !ios !mobile -// +build wasm test_web_driver package app diff --git a/app/app_mobile.go b/app/app_mobile.go index 1dbcdd4e07..9976bb0d88 100644 --- a/app/app_mobile.go +++ b/app/app_mobile.go @@ -1,6 +1,4 @@ //go:build !ci && (android || ios || mobile) -// +build !ci -// +build android ios mobile package app diff --git a/app/app_mobile_and.c b/app/app_mobile_and.c index cbe6dc2336..a21e330ec0 100644 --- a/app/app_mobile_and.c +++ b/app/app_mobile_and.c @@ -1,5 +1,4 @@ //go:build !ci && android -// +build !ci,android #include #include diff --git a/app/app_mobile_and.go b/app/app_mobile_and.go index 64f07c4dfa..35baf26e14 100644 --- a/app/app_mobile_and.go +++ b/app/app_mobile_and.go @@ -1,5 +1,4 @@ //go:build !ci && android -// +build !ci,android package app diff --git a/app/app_mobile_and_test.go b/app/app_mobile_and_test.go index e82dd81ffa..da0244cb1f 100644 --- a/app/app_mobile_and_test.go +++ b/app/app_mobile_and_test.go @@ -1,5 +1,4 @@ //go:build !ci && android -// +build !ci,android package app diff --git a/app/app_mobile_ios.go b/app/app_mobile_ios.go index c479e099b7..fb79323d91 100644 --- a/app/app_mobile_ios.go +++ b/app/app_mobile_ios.go @@ -1,5 +1,4 @@ //go:build !ci && ios -// +build !ci,ios package app diff --git a/app/app_mobile_ios.m b/app/app_mobile_ios.m index c0f60c1e97..d1e6ab48b6 100644 --- a/app/app_mobile_ios.m +++ b/app/app_mobile_ios.m @@ -1,5 +1,4 @@ //go:build !ci && ios -// +build !ci,ios #import diff --git a/app/app_notlegacy_darwin.go b/app/app_notlegacy_darwin.go index 01153c93b2..f1c065ebbb 100644 --- a/app/app_notlegacy_darwin.go +++ b/app/app_notlegacy_darwin.go @@ -1,5 +1,4 @@ //go:build !ci && !legacy && !wasm && !test_web_driver -// +build !ci,!legacy,!wasm,!test_web_driver package app diff --git a/app/app_openurl_wasm.go b/app/app_openurl_wasm.go index 82f851aa4a..75397fe655 100644 --- a/app/app_openurl_wasm.go +++ b/app/app_openurl_wasm.go @@ -1,5 +1,4 @@ //go:build !ci && wasm -// +build !ci,wasm package app diff --git a/app/app_openurl_web.go b/app/app_openurl_web.go index 9b039938ed..b03d040281 100644 --- a/app/app_openurl_web.go +++ b/app/app_openurl_web.go @@ -1,5 +1,4 @@ //go:build !ci && !wasm && test_web_driver -// +build !ci,!wasm,test_web_driver package app diff --git a/app/app_other.go b/app/app_other.go index d74089e59d..d20799ba7f 100644 --- a/app/app_other.go +++ b/app/app_other.go @@ -1,5 +1,4 @@ //go:build ci || (!linux && !darwin && !windows && !freebsd && !openbsd && !netbsd && !wasm && !test_web_driver) -// +build ci !linux,!darwin,!windows,!freebsd,!openbsd,!netbsd,!wasm,!test_web_driver package app diff --git a/app/app_software.go b/app/app_software.go index fbded3d26c..ccdcb097cf 100644 --- a/app/app_software.go +++ b/app/app_software.go @@ -1,5 +1,4 @@ //go:build ci -// +build ci package app diff --git a/app/app_theme_wasm.go b/app/app_theme_wasm.go index a67a820b23..66f141e338 100644 --- a/app/app_theme_wasm.go +++ b/app/app_theme_wasm.go @@ -1,5 +1,4 @@ //go:build !ci && wasm -// +build !ci,wasm package app diff --git a/app/app_theme_web.go b/app/app_theme_web.go index 48ad5ef8c4..df16339216 100644 --- a/app/app_theme_web.go +++ b/app/app_theme_web.go @@ -1,5 +1,4 @@ //go:build !ci && !wasm && test_web_driver -// +build !ci,!wasm,test_web_driver package app diff --git a/app/app_windows.go b/app/app_windows.go index 60d9b0a166..3b6ea44681 100644 --- a/app/app_windows.go +++ b/app/app_windows.go @@ -1,5 +1,4 @@ //go:build !ci && !android && !ios && !wasm && !test_web_driver -// +build !ci,!android,!ios,!wasm,!test_web_driver package app diff --git a/app/app_windows_test.go b/app/app_windows_test.go index 0a607522ce..ebf36f1136 100644 --- a/app/app_windows_test.go +++ b/app/app_windows_test.go @@ -1,5 +1,4 @@ //go:build !ci && !android && !ios -// +build !ci,!android,!ios package app diff --git a/app/app_xdg.go b/app/app_xdg.go index de39cecead..c6ae218c4b 100644 --- a/app/app_xdg.go +++ b/app/app_xdg.go @@ -1,9 +1,4 @@ //go:build !ci && !wasm && !test_web_driver && (linux || openbsd || freebsd || netbsd) && !android -// +build !ci -// +build !wasm -// +build !test_web_driver -// +build linux openbsd freebsd netbsd -// +build !android package app diff --git a/app/preferences_android.go b/app/preferences_android.go index d51353098c..a2e7e47fbf 100644 --- a/app/preferences_android.go +++ b/app/preferences_android.go @@ -1,5 +1,4 @@ //go:build android -// +build android package app diff --git a/app/preferences_ios.go b/app/preferences_ios.go index 6e0ddf7bfa..8720dcf331 100644 --- a/app/preferences_ios.go +++ b/app/preferences_ios.go @@ -1,5 +1,4 @@ //go:build ios -// +build ios package app diff --git a/app/preferences_mobile.go b/app/preferences_mobile.go index 72f601c5bf..0faa122672 100644 --- a/app/preferences_mobile.go +++ b/app/preferences_mobile.go @@ -1,5 +1,4 @@ //go:build mobile -// +build mobile package app diff --git a/app/preferences_other.go b/app/preferences_other.go index 6304676d8f..4b997dcfd2 100644 --- a/app/preferences_other.go +++ b/app/preferences_other.go @@ -1,5 +1,4 @@ //go:build !ios && !android && !mobile -// +build !ios,!android,!mobile package app diff --git a/app/settings_desktop.go b/app/settings_desktop.go index 7832835a1c..c3de2120f1 100644 --- a/app/settings_desktop.go +++ b/app/settings_desktop.go @@ -1,5 +1,4 @@ //go:build !android && !ios && !mobile && !wasm && !test_web_driver -// +build !android,!ios,!mobile,!wasm,!test_web_driver package app diff --git a/app/settings_desktop_test.go b/app/settings_desktop_test.go index 0ffcd93bea..ea9f5c7c0d 100644 --- a/app/settings_desktop_test.go +++ b/app/settings_desktop_test.go @@ -1,5 +1,4 @@ //go:build !android && !ios && !mobile -// +build !android,!ios,!mobile package app diff --git a/app/settings_file.go b/app/settings_file.go index eb0426f672..a8bc94b2f2 100644 --- a/app/settings_file.go +++ b/app/settings_file.go @@ -1,5 +1,4 @@ //go:build !wasm && !test_web_driver -// +build !wasm,!test_web_driver package app diff --git a/app/settings_goxjs.go b/app/settings_goxjs.go index 2acf5bfeb9..b17aac0adf 100644 --- a/app/settings_goxjs.go +++ b/app/settings_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package app diff --git a/app/settings_mobile.go b/app/settings_mobile.go index 01a5f91765..642a7e7a01 100644 --- a/app/settings_mobile.go +++ b/app/settings_mobile.go @@ -1,5 +1,4 @@ //go:build android || ios || mobile -// +build android ios mobile package app diff --git a/app/settings_noanimation.go b/app/settings_noanimation.go index b7b3527ed6..7d808d8dcb 100644 --- a/app/settings_noanimation.go +++ b/app/settings_noanimation.go @@ -1,5 +1,4 @@ //go:build no_animations -// +build no_animations package app diff --git a/cmd/fyne/internal/commands/install_other.go b/cmd/fyne/internal/commands/install_other.go index 886ec869e6..8d8046972d 100644 --- a/cmd/fyne/internal/commands/install_other.go +++ b/cmd/fyne/internal/commands/install_other.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package commands diff --git a/cmd/fyne/internal/mobile/binres/genarsc.go b/cmd/fyne/internal/mobile/binres/genarsc.go index db8706d99a..536e4f7161 100644 --- a/cmd/fyne/internal/mobile/binres/genarsc.go +++ b/cmd/fyne/internal/mobile/binres/genarsc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Genarsc generates stripped down version of android.jar resources used // for validation of manifest entries. diff --git a/cmd/fyne/internal/mobile/gendex/gendex.go b/cmd/fyne/internal/mobile/gendex/gendex.go index 4bfb50f38d..be78637e67 100644 --- a/cmd/fyne/internal/mobile/gendex/gendex.go +++ b/cmd/fyne/internal/mobile/gendex/gendex.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gendex -// +build gendex // Gendex generates a dex file used by Go apps created with gomobile. // diff --git a/container/apptabs_desktop_test.go b/container/apptabs_desktop_test.go index aca2bc3e34..642e8ae7b9 100644 --- a/container/apptabs_desktop_test.go +++ b/container/apptabs_desktop_test.go @@ -1,5 +1,4 @@ //go:build !mobile -// +build !mobile package container_test diff --git a/container/apptabs_mobile_test.go b/container/apptabs_mobile_test.go index f22c20db7a..ffae2fff77 100644 --- a/container/apptabs_mobile_test.go +++ b/container/apptabs_mobile_test.go @@ -1,5 +1,4 @@ //go:build mobile -// +build mobile package container_test diff --git a/container/doctabs_desktop_test.go b/container/doctabs_desktop_test.go index 80641d7ca9..dc2949de02 100644 --- a/container/doctabs_desktop_test.go +++ b/container/doctabs_desktop_test.go @@ -1,5 +1,4 @@ //go:build !mobile -// +build !mobile package container_test diff --git a/container/doctabs_mobile_test.go b/container/doctabs_mobile_test.go index 034c3ed9cf..730e21430d 100644 --- a/container/doctabs_mobile_test.go +++ b/container/doctabs_mobile_test.go @@ -1,5 +1,4 @@ //go:build mobile -// +build mobile package container_test diff --git a/data/binding/gen.go b/data/binding/gen.go index 6b444a8ad6..d2788e81af 100644 --- a/data/binding/gen.go +++ b/data/binding/gen.go @@ -1,5 +1,4 @@ //go:build ignore -// +build ignore package main diff --git a/dialog/file_darwin.go b/dialog/file_darwin.go index 9d7f756ca7..991aaa16f6 100644 --- a/dialog/file_darwin.go +++ b/dialog/file_darwin.go @@ -1,5 +1,4 @@ //go:build !ios && !android && !wasm && !js -// +build !ios,!android,!wasm,!js package dialog diff --git a/dialog/file_goxjs.go b/dialog/file_goxjs.go index 2dafd38ddc..d311ec6b62 100644 --- a/dialog/file_goxjs.go +++ b/dialog/file_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm || js -// +build wasm js package dialog diff --git a/dialog/file_mobile.go b/dialog/file_mobile.go index f3a7f0fe41..1d2aa0259a 100644 --- a/dialog/file_mobile.go +++ b/dialog/file_mobile.go @@ -1,5 +1,4 @@ //go:build ios || android -// +build ios android package dialog diff --git a/dialog/file_other_test.go b/dialog/file_other_test.go index 3dd0d70999..c026a36917 100644 --- a/dialog/file_other_test.go +++ b/dialog/file_other_test.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package dialog diff --git a/dialog/file_unix.go b/dialog/file_unix.go index dea11fbe4a..ce3743b378 100644 --- a/dialog/file_unix.go +++ b/dialog/file_unix.go @@ -1,5 +1,4 @@ //go:build !windows && !android && !ios && !wasm && !js -// +build !windows,!android,!ios,!wasm,!js package dialog diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 824aa1bce3..627268daf3 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -1,8 +1,4 @@ //go:build (linux || openbsd || freebsd || netbsd) && !android && !wasm && !js -// +build linux openbsd freebsd netbsd -// +build !android -// +build !wasm -// +build !js package dialog diff --git a/dialog/file_xdg_flatpak.go b/dialog/file_xdg_flatpak.go index c69c9fdf5b..8d7972131d 100644 --- a/dialog/file_xdg_flatpak.go +++ b/dialog/file_xdg_flatpak.go @@ -1,5 +1,4 @@ //go:build flatpak && !windows && !android && !ios && !wasm && !js -// +build flatpak,!windows,!android,!ios,!wasm,!js package dialog diff --git a/dialog/file_xdg_notflatpak.go b/dialog/file_xdg_notflatpak.go index 5531a6476a..4494e18b7f 100644 --- a/dialog/file_xdg_notflatpak.go +++ b/dialog/file_xdg_notflatpak.go @@ -1,5 +1,4 @@ //go:build !flatpak && !windows && !android && !ios && !wasm && !js -// +build !flatpak,!windows,!android,!ios,!wasm,!js package dialog diff --git a/dialog/file_xdg_test.go b/dialog/file_xdg_test.go index d198fee186..1d7887e245 100644 --- a/dialog/file_xdg_test.go +++ b/dialog/file_xdg_test.go @@ -1,6 +1,4 @@ //go:build (linux || openbsd || freebsd || netbsd) && !android -// +build linux openbsd freebsd netbsd -// +build !android package dialog diff --git a/driver/native_android.go b/driver/native_android.go index bd7f383b96..98e179a060 100644 --- a/driver/native_android.go +++ b/driver/native_android.go @@ -1,5 +1,4 @@ //go:build android -// +build android package driver diff --git a/driver/native_other.go b/driver/native_other.go index 8dac0d8d5c..6b2518eeab 100644 --- a/driver/native_other.go +++ b/driver/native_other.go @@ -1,5 +1,4 @@ //go:build !android -// +build !android package driver diff --git a/internal/animation/animation_test.go b/internal/animation/animation_test.go index cb5b173170..96b5f3300a 100644 --- a/internal/animation/animation_test.go +++ b/internal/animation/animation_test.go @@ -1,5 +1,4 @@ //go:build !ci || !darwin -// +build !ci !darwin package animation diff --git a/internal/async/gen.go b/internal/async/gen.go index fb95af7c83..50e8fc3d30 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -1,5 +1,4 @@ //go:build ignore -// +build ignore package main diff --git a/internal/build/driver_flatpak.go b/internal/build/driver_flatpak.go index 96f3315a4e..0261f7b93e 100644 --- a/internal/build/driver_flatpak.go +++ b/internal/build/driver_flatpak.go @@ -1,5 +1,4 @@ //go:build flatpak -// +build flatpak package build diff --git a/internal/build/driver_notflatpak.go b/internal/build/driver_notflatpak.go index d2f79cdc46..2f891ba76f 100644 --- a/internal/build/driver_notflatpak.go +++ b/internal/build/driver_notflatpak.go @@ -1,5 +1,4 @@ //go:build !flatpak -// +build !flatpak package build diff --git a/internal/build/driver_notwayland.go b/internal/build/driver_notwayland.go index dbe88559c7..ba398c2041 100644 --- a/internal/build/driver_notwayland.go +++ b/internal/build/driver_notwayland.go @@ -1,5 +1,4 @@ //go:build !wayland -// +build !wayland package build diff --git a/internal/build/driver_wayland.go b/internal/build/driver_wayland.go index eaa86cf1c1..d48bb5150c 100644 --- a/internal/build/driver_wayland.go +++ b/internal/build/driver_wayland.go @@ -1,5 +1,4 @@ //go:build wayland -// +build wayland package build diff --git a/internal/build/hints_disabled.go b/internal/build/hints_disabled.go index 42274ae37f..f8919d0f40 100644 --- a/internal/build/hints_disabled.go +++ b/internal/build/hints_disabled.go @@ -1,5 +1,4 @@ //go:build !hints -// +build !hints package build diff --git a/internal/build/hints_enabled.go b/internal/build/hints_enabled.go index 041dd985d7..db627a3878 100644 --- a/internal/build/hints_enabled.go +++ b/internal/build/hints_enabled.go @@ -1,5 +1,4 @@ //go:build hints -// +build hints package build diff --git a/internal/build/mode_debug.go b/internal/build/mode_debug.go index e89ac6c13a..9658ddcb6f 100644 --- a/internal/build/mode_debug.go +++ b/internal/build/mode_debug.go @@ -1,5 +1,4 @@ //go:build debug -// +build debug package build diff --git a/internal/build/mode_release.go b/internal/build/mode_release.go index 8c4f6604f6..3b6937e905 100644 --- a/internal/build/mode_release.go +++ b/internal/build/mode_release.go @@ -1,5 +1,4 @@ //go:build release -// +build release package build diff --git a/internal/build/mode_standard.go b/internal/build/mode_standard.go index c46dac9992..7565646eab 100644 --- a/internal/build/mode_standard.go +++ b/internal/build/mode_standard.go @@ -1,5 +1,4 @@ //go:build !debug && !release -// +build !debug,!release package build diff --git a/internal/cache/texture_desktop.go b/internal/cache/texture_desktop.go index e1f826694c..26062eb7e5 100644 --- a/internal/cache/texture_desktop.go +++ b/internal/cache/texture_desktop.go @@ -1,5 +1,4 @@ //go:build !android && !ios && !mobile && !wasm && !test_web_driver -// +build !android,!ios,!mobile,!wasm,!test_web_driver package cache diff --git a/internal/cache/texture_desktop_test.go b/internal/cache/texture_desktop_test.go index ce9232bb9b..518b1fa4d6 100644 --- a/internal/cache/texture_desktop_test.go +++ b/internal/cache/texture_desktop_test.go @@ -1,5 +1,4 @@ //go:build !android && !ios && !mobile -// +build !android,!ios,!mobile package cache_test diff --git a/internal/cache/texture_gomobile.go b/internal/cache/texture_gomobile.go index a259963e4d..4b0d89cfd7 100644 --- a/internal/cache/texture_gomobile.go +++ b/internal/cache/texture_gomobile.go @@ -1,5 +1,4 @@ //go:build android || ios || mobile -// +build android ios mobile package cache diff --git a/internal/cache/texture_gomobile_test.go b/internal/cache/texture_gomobile_test.go index 62dbbdb7fc..7e962ed998 100644 --- a/internal/cache/texture_gomobile_test.go +++ b/internal/cache/texture_gomobile_test.go @@ -1,5 +1,4 @@ //go:build android || ios || mobile -// +build android ios mobile package cache_test diff --git a/internal/cache/texture_goxjs.go b/internal/cache/texture_goxjs.go index c686e1f3d7..17669ea596 100644 --- a/internal/cache/texture_goxjs.go +++ b/internal/cache/texture_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package cache diff --git a/internal/driver/glfw/canvas_other_test.go b/internal/driver/glfw/canvas_other_test.go index 17e7694a65..8a7f04ac85 100644 --- a/internal/driver/glfw/canvas_other_test.go +++ b/internal/driver/glfw/canvas_other_test.go @@ -1,7 +1,4 @@ //go:build !no_glfw && !mobile && (!darwin || no_native_menus) -// +build !no_glfw -// +build !mobile -// +build !darwin no_native_menus package glfw diff --git a/internal/driver/glfw/canvas_test.go b/internal/driver/glfw/canvas_test.go index 57a8845857..fce55e7c3f 100644 --- a/internal/driver/glfw/canvas_test.go +++ b/internal/driver/glfw/canvas_test.go @@ -1,5 +1,4 @@ //go:build !no_glfw && !mobile -// +build !no_glfw,!mobile package glfw diff --git a/internal/driver/glfw/clipboard.go b/internal/driver/glfw/clipboard.go index db5b82d2ff..d0aac66d1a 100644 --- a/internal/driver/glfw/clipboard.go +++ b/internal/driver/glfw/clipboard.go @@ -1,5 +1,4 @@ //go:build !wasm && !test_web_driver -// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/clipboard_goxjs.go b/internal/driver/glfw/clipboard_goxjs.go index 7928831baa..239158f746 100644 --- a/internal/driver/glfw/clipboard_goxjs.go +++ b/internal/driver/glfw/clipboard_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/device_desktop.go b/internal/driver/glfw/device_desktop.go index 8685cb46d0..b56ee294d7 100644 --- a/internal/driver/glfw/device_desktop.go +++ b/internal/driver/glfw/device_desktop.go @@ -1,5 +1,4 @@ //go:build !wasm -// +build !wasm package glfw diff --git a/internal/driver/glfw/device_goxjs.go b/internal/driver/glfw/device_goxjs.go index dba18461e9..bca9de6942 100644 --- a/internal/driver/glfw/device_goxjs.go +++ b/internal/driver/glfw/device_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm -// +build wasm package glfw diff --git a/internal/driver/glfw/device_test.go b/internal/driver/glfw/device_test.go index 3cc253dcee..11e3cb2049 100644 --- a/internal/driver/glfw/device_test.go +++ b/internal/driver/glfw/device_test.go @@ -1,5 +1,4 @@ //go:build !wasm -// +build !wasm package glfw diff --git a/internal/driver/glfw/driver_desktop.go b/internal/driver/glfw/driver_desktop.go index 10f145a6f6..62cff6d106 100644 --- a/internal/driver/glfw/driver_desktop.go +++ b/internal/driver/glfw/driver_desktop.go @@ -1,5 +1,4 @@ //go:build !wasm && !test_web_driver -// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/driver_goxjs.go b/internal/driver/glfw/driver_goxjs.go index 564bdb6d10..036de76820 100644 --- a/internal/driver/glfw/driver_goxjs.go +++ b/internal/driver/glfw/driver_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm -// +build wasm package glfw diff --git a/internal/driver/glfw/driver_notwindows.go b/internal/driver/glfw/driver_notwindows.go index 4fd0ef432c..fad4b39f90 100644 --- a/internal/driver/glfw/driver_notwindows.go +++ b/internal/driver/glfw/driver_notwindows.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package glfw diff --git a/internal/driver/glfw/driver_test.go b/internal/driver/glfw/driver_test.go index 080d683862..01910c3a7e 100644 --- a/internal/driver/glfw/driver_test.go +++ b/internal/driver/glfw/driver_test.go @@ -1,5 +1,4 @@ //go:build !no_glfw && !mobile -// +build !no_glfw,!mobile package glfw diff --git a/internal/driver/glfw/driver_web.go b/internal/driver/glfw/driver_web.go index 5b12e53251..973dda9c5a 100644 --- a/internal/driver/glfw/driver_web.go +++ b/internal/driver/glfw/driver_web.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/glfw_core.go b/internal/driver/glfw/glfw_core.go index ea06527b3a..4a0b1a1f72 100644 --- a/internal/driver/glfw/glfw_core.go +++ b/internal/driver/glfw/glfw_core.go @@ -1,7 +1,4 @@ //go:build ((!gles && !arm && !arm64) || darwin) && !wasm && !test_web_driver -// +build !gles,!arm,!arm64 darwin -// +build !wasm -// +build !test_web_driver package glfw diff --git a/internal/driver/glfw/glfw_es.go b/internal/driver/glfw/glfw_es.go index 34f4a6cd73..d3a7b1186d 100644 --- a/internal/driver/glfw/glfw_es.go +++ b/internal/driver/glfw/glfw_es.go @@ -1,8 +1,4 @@ //go:build (gles || arm || arm64) && !darwin && !wasm && !test_web_driver -// +build gles arm arm64 -// +build !darwin -// +build !wasm -// +build !test_web_driver package glfw diff --git a/internal/driver/glfw/glfw_goxjs.go b/internal/driver/glfw/glfw_goxjs.go index 89de5aa178..9236608a91 100644 --- a/internal/driver/glfw/glfw_goxjs.go +++ b/internal/driver/glfw/glfw_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/glfw_test.go b/internal/driver/glfw/glfw_test.go index a4004c80e5..90613703c8 100644 --- a/internal/driver/glfw/glfw_test.go +++ b/internal/driver/glfw/glfw_test.go @@ -1,5 +1,4 @@ //go:build !no_glfw && !mobile -// +build !no_glfw,!mobile package glfw diff --git a/internal/driver/glfw/loop_desktop.go b/internal/driver/glfw/loop_desktop.go index d89aa2d3a5..f522a42fc7 100644 --- a/internal/driver/glfw/loop_desktop.go +++ b/internal/driver/glfw/loop_desktop.go @@ -1,5 +1,4 @@ //go:build !wasm && !test_web_driver -// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/loop_goxjs.go b/internal/driver/glfw/loop_goxjs.go index c99f9a7d65..d45c691d5b 100644 --- a/internal/driver/glfw/loop_goxjs.go +++ b/internal/driver/glfw/loop_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/loop_test.go b/internal/driver/glfw/loop_test.go index 05ba2c3403..20807a7ff6 100644 --- a/internal/driver/glfw/loop_test.go +++ b/internal/driver/glfw/loop_test.go @@ -1,5 +1,4 @@ //go:build !no_glfw && !mobile -// +build !no_glfw,!mobile package glfw diff --git a/internal/driver/glfw/menu_bar_test.go b/internal/driver/glfw/menu_bar_test.go index bb07e1d7fa..64b3729fa0 100644 --- a/internal/driver/glfw/menu_bar_test.go +++ b/internal/driver/glfw/menu_bar_test.go @@ -1,6 +1,4 @@ //go:build !mobile && (!no_glfw || !windows) -// +build !mobile -// +build !no_glfw !windows package glfw_test diff --git a/internal/driver/glfw/menu_darwin.go b/internal/driver/glfw/menu_darwin.go index be5899d644..7b2629edbb 100644 --- a/internal/driver/glfw/menu_darwin.go +++ b/internal/driver/glfw/menu_darwin.go @@ -1,5 +1,4 @@ //go:build !no_native_menus && !wasm && !test_web_driver -// +build !no_native_menus,!wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/menu_darwin.m b/internal/driver/glfw/menu_darwin.m index e9038c7a27..458c5ab269 100644 --- a/internal/driver/glfw/menu_darwin.m +++ b/internal/driver/glfw/menu_darwin.m @@ -1,5 +1,4 @@ //go:build !no_native_menus -// +build !no_native_menus #import #import diff --git a/internal/driver/glfw/menu_darwin_test.go b/internal/driver/glfw/menu_darwin_test.go index 9ddc72012f..d2ee99dac1 100644 --- a/internal/driver/glfw/menu_darwin_test.go +++ b/internal/driver/glfw/menu_darwin_test.go @@ -1,5 +1,4 @@ //go:build !no_glfw && !no_native_menus && !mobile -// +build !no_glfw,!no_native_menus,!mobile package glfw diff --git a/internal/driver/glfw/menu_notweb.go b/internal/driver/glfw/menu_notweb.go index 3547a46a04..3cd7a6f515 100644 --- a/internal/driver/glfw/menu_notweb.go +++ b/internal/driver/glfw/menu_notweb.go @@ -1,5 +1,4 @@ //go:build !wasm && !test_web_driver -// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/menu_other.go b/internal/driver/glfw/menu_other.go index d4f7b0d918..9eeacc8e94 100644 --- a/internal/driver/glfw/menu_other.go +++ b/internal/driver/glfw/menu_other.go @@ -1,5 +1,4 @@ //go:build !darwin || wasm || test_web_driver || no_native_menus -// +build !darwin wasm test_web_driver no_native_menus package glfw diff --git a/internal/driver/glfw/menu_other_test.go b/internal/driver/glfw/menu_other_test.go index 673b49b329..3eb1a43e15 100644 --- a/internal/driver/glfw/menu_other_test.go +++ b/internal/driver/glfw/menu_other_test.go @@ -1,7 +1,4 @@ //go:build !no_glfw && (!darwin || no_native_menus) && !mobile -// +build !no_glfw -// +build !darwin no_native_menus -// +build !mobile package glfw diff --git a/internal/driver/glfw/menu_test.go b/internal/driver/glfw/menu_test.go index cb3b341861..40e35ec836 100644 --- a/internal/driver/glfw/menu_test.go +++ b/internal/driver/glfw/menu_test.go @@ -1,5 +1,4 @@ //go:build !no_glfw && !mobile -// +build !no_glfw,!mobile package glfw diff --git a/internal/driver/glfw/menu_web.go b/internal/driver/glfw/menu_web.go index 78f75ae54d..215937bb46 100644 --- a/internal/driver/glfw/menu_web.go +++ b/internal/driver/glfw/menu_web.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/scale_test.go b/internal/driver/glfw/scale_test.go index f1035e8fba..081693521b 100644 --- a/internal/driver/glfw/scale_test.go +++ b/internal/driver/glfw/scale_test.go @@ -1,5 +1,4 @@ //go:build !mobile -// +build !mobile package glfw diff --git a/internal/driver/glfw/scroll_speed_darwin.go b/internal/driver/glfw/scroll_speed_darwin.go index b018f5da9e..4434a717c1 100644 --- a/internal/driver/glfw/scroll_speed_darwin.go +++ b/internal/driver/glfw/scroll_speed_darwin.go @@ -1,5 +1,4 @@ //go:build darwin -// +build darwin package glfw diff --git a/internal/driver/glfw/scroll_speed_default.go b/internal/driver/glfw/scroll_speed_default.go index 70265378f8..401b5fa4aa 100644 --- a/internal/driver/glfw/scroll_speed_default.go +++ b/internal/driver/glfw/scroll_speed_default.go @@ -1,5 +1,4 @@ //go:build !darwin -// +build !darwin package glfw diff --git a/internal/driver/glfw/shortcuts_other.go b/internal/driver/glfw/shortcuts_other.go index 549b21c4e9..2214079968 100644 --- a/internal/driver/glfw/shortcuts_other.go +++ b/internal/driver/glfw/shortcuts_other.go @@ -1,5 +1,4 @@ //go:build !wasm -// +build !wasm package glfw diff --git a/internal/driver/glfw/shortcuts_wasm.go b/internal/driver/glfw/shortcuts_wasm.go index bb1055101e..042b563566 100644 --- a/internal/driver/glfw/shortcuts_wasm.go +++ b/internal/driver/glfw/shortcuts_wasm.go @@ -1,5 +1,4 @@ //go:build wasm -// +build wasm package glfw diff --git a/internal/driver/glfw/window_desktop.go b/internal/driver/glfw/window_desktop.go index ba509b7ab5..a3acbc0c1f 100644 --- a/internal/driver/glfw/window_desktop.go +++ b/internal/driver/glfw/window_desktop.go @@ -1,5 +1,4 @@ //go:build !wasm && !test_web_driver -// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/window_desktop_test.go b/internal/driver/glfw/window_desktop_test.go index 3cba4c5202..7d98da578d 100644 --- a/internal/driver/glfw/window_desktop_test.go +++ b/internal/driver/glfw/window_desktop_test.go @@ -1,5 +1,4 @@ //go:build !wasm && !test_web_driver -// +build !wasm,!test_web_driver package glfw diff --git a/internal/driver/glfw/window_goxjs.go b/internal/driver/glfw/window_goxjs.go index ef6fea7afe..b8dde32648 100644 --- a/internal/driver/glfw/window_goxjs.go +++ b/internal/driver/glfw/window_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/window_notwindows.go b/internal/driver/glfw/window_notwindows.go index 169e2cefa1..03108435c9 100644 --- a/internal/driver/glfw/window_notwindows.go +++ b/internal/driver/glfw/window_notwindows.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package glfw diff --git a/internal/driver/glfw/window_notxdg.go b/internal/driver/glfw/window_notxdg.go index 34e34a879f..76a0a9ee72 100644 --- a/internal/driver/glfw/window_notxdg.go +++ b/internal/driver/glfw/window_notxdg.go @@ -1,5 +1,4 @@ //go:build !linux && !freebsd && !openbsd && !netbsd -// +build !linux,!freebsd,!openbsd,!netbsd package glfw diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index c0e8718ed5..e9babc98ef 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -1,5 +1,4 @@ //go:build !no_glfw && !mobile -// +build !no_glfw,!mobile package glfw diff --git a/internal/driver/glfw/window_wasm.go b/internal/driver/glfw/window_wasm.go index 8a5c99b238..83fcdfcdf1 100644 --- a/internal/driver/glfw/window_wasm.go +++ b/internal/driver/glfw/window_wasm.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package glfw diff --git a/internal/driver/glfw/window_wayland.go b/internal/driver/glfw/window_wayland.go index 84909d9310..ea6b84f0bb 100644 --- a/internal/driver/glfw/window_wayland.go +++ b/internal/driver/glfw/window_wayland.go @@ -1,6 +1,4 @@ //go:build wayland && (linux || freebsd || openbsd || netbsd) -// +build wayland -// +build linux freebsd openbsd netbsd package glfw diff --git a/internal/driver/glfw/window_x11.go b/internal/driver/glfw/window_x11.go index bc8da918c5..13ed9b010f 100644 --- a/internal/driver/glfw/window_x11.go +++ b/internal/driver/glfw/window_x11.go @@ -1,8 +1,4 @@ //go:build !wayland && (linux || freebsd || openbsd || netbsd) && !wasm && !test_web_driver -// +build !wayland -// +build linux freebsd openbsd netbsd -// +build !wasm -// +build !test_web_driver package glfw diff --git a/internal/driver/glfw/window_xdg.go b/internal/driver/glfw/window_xdg.go index a8f4331a8a..1c5c7200a1 100644 --- a/internal/driver/glfw/window_xdg.go +++ b/internal/driver/glfw/window_xdg.go @@ -1,5 +1,4 @@ //go:build linux || freebsd || openbsd || netbsd -// +build linux freebsd openbsd netbsd package glfw diff --git a/internal/driver/mobile/android.c b/internal/driver/mobile/android.c index f1c5bcc620..afc898dbe0 100644 --- a/internal/driver/mobile/android.c +++ b/internal/driver/mobile/android.c @@ -1,5 +1,4 @@ //go:build android -// +build android #include #include diff --git a/internal/driver/mobile/app/android.c b/internal/driver/mobile/app/android.c index efe35195ae..56c759a2aa 100644 --- a/internal/driver/mobile/app/android.c +++ b/internal/driver/mobile/app/android.c @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build android +//go:build android #include #include diff --git a/internal/driver/mobile/app/android.go b/internal/driver/mobile/app/android.go index dc874199db..824900f8d9 100644 --- a/internal/driver/mobile/app/android.go +++ b/internal/driver/mobile/app/android.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build android -// +build android /* Android Apps are built with -buildmode=c-shared. They are loaded by a diff --git a/internal/driver/mobile/app/app.go b/internal/driver/mobile/app/app.go index de56614499..bbff34948e 100644 --- a/internal/driver/mobile/app/app.go +++ b/internal/driver/mobile/app/app.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd || linux || darwin || windows || openbsd -// +build freebsd linux darwin windows openbsd package app diff --git a/internal/driver/mobile/app/callfn/callfn.go b/internal/driver/mobile/app/callfn/callfn.go index 7a3d0506e6..ecc3d456f5 100644 --- a/internal/driver/mobile/app/callfn/callfn.go +++ b/internal/driver/mobile/app/callfn/callfn.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build android && (arm || 386 || amd64 || arm64) -// +build android -// +build arm 386 amd64 arm64 // Package callfn provides an android entry point. // diff --git a/internal/driver/mobile/app/darwin_desktop.go b/internal/driver/mobile/app/darwin_desktop.go index 5b7041f465..2a7801bbc7 100644 --- a/internal/driver/mobile/app/darwin_desktop.go +++ b/internal/driver/mobile/app/darwin_desktop.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios package app diff --git a/internal/driver/mobile/app/darwin_desktop.m b/internal/driver/mobile/app/darwin_desktop.m index 0a77b72a25..7d2c3dc48c 100644 --- a/internal/driver/mobile/app/darwin_desktop.m +++ b/internal/driver/mobile/app/darwin_desktop.m @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin -// +build !ios +//go:build darwin || !ios #include "_cgo_export.h" #include diff --git a/internal/driver/mobile/app/darwin_ios.go b/internal/driver/mobile/app/darwin_ios.go index d40ec5a29e..b0c68babf7 100644 --- a/internal/driver/mobile/app/darwin_ios.go +++ b/internal/driver/mobile/app/darwin_ios.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && ios -// +build darwin,ios package app diff --git a/internal/driver/mobile/app/darwin_ios.m b/internal/driver/mobile/app/darwin_ios.m index 6cce1d07a3..c3db9775d0 100644 --- a/internal/driver/mobile/app/darwin_ios.m +++ b/internal/driver/mobile/app/darwin_ios.m @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && ios -// +build darwin,ios #include "_cgo_export.h" #include diff --git a/internal/driver/mobile/app/shiny.go b/internal/driver/mobile/app/shiny.go index 8784215080..0ebf488dfb 100644 --- a/internal/driver/mobile/app/shiny.go +++ b/internal/driver/mobile/app/shiny.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package app diff --git a/internal/driver/mobile/app/x11.c b/internal/driver/mobile/app/x11.c index c0c86ade4f..c83b2fd9c4 100644 --- a/internal/driver/mobile/app/x11.c +++ b/internal/driver/mobile/app/x11.c @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux && !android) || freebsd || openbsd -// +build linux,!android freebsd openbsd #include "_cgo_export.h" #include diff --git a/internal/driver/mobile/app/x11.go b/internal/driver/mobile/app/x11.go index c9e2d524cd..da42a69421 100644 --- a/internal/driver/mobile/app/x11.go +++ b/internal/driver/mobile/app/x11.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux && !android) || freebsd || openbsd -// +build linux,!android freebsd openbsd package app diff --git a/internal/driver/mobile/canvas_test.go b/internal/driver/mobile/canvas_test.go index 68468ea6ae..9e15882318 100644 --- a/internal/driver/mobile/canvas_test.go +++ b/internal/driver/mobile/canvas_test.go @@ -1,5 +1,4 @@ //go:build !windows || !ci -// +build !windows !ci package mobile diff --git a/internal/driver/mobile/clipboard_android.go b/internal/driver/mobile/clipboard_android.go index 8a99a939a6..a15cd72196 100644 --- a/internal/driver/mobile/clipboard_android.go +++ b/internal/driver/mobile/clipboard_android.go @@ -1,5 +1,4 @@ //go:build android -// +build android package mobile diff --git a/internal/driver/mobile/clipboard_desktop.go b/internal/driver/mobile/clipboard_desktop.go index 895545da3c..3860d388cd 100644 --- a/internal/driver/mobile/clipboard_desktop.go +++ b/internal/driver/mobile/clipboard_desktop.go @@ -1,5 +1,4 @@ //go:build !ios && !android -// +build !ios,!android package mobile diff --git a/internal/driver/mobile/clipboard_ios.go b/internal/driver/mobile/clipboard_ios.go index 5b4a88422a..7ac97efd86 100644 --- a/internal/driver/mobile/clipboard_ios.go +++ b/internal/driver/mobile/clipboard_ios.go @@ -1,5 +1,4 @@ //go:build ios -// +build ios package mobile diff --git a/internal/driver/mobile/clipboard_ios.m b/internal/driver/mobile/clipboard_ios.m index c6c0758082..4298523284 100644 --- a/internal/driver/mobile/clipboard_ios.m +++ b/internal/driver/mobile/clipboard_ios.m @@ -1,5 +1,4 @@ //go:build ios -// +build ios #import #import diff --git a/internal/driver/mobile/device_android.go b/internal/driver/mobile/device_android.go index 76ffec8b38..6952e22eea 100644 --- a/internal/driver/mobile/device_android.go +++ b/internal/driver/mobile/device_android.go @@ -1,5 +1,4 @@ //go:build android -// +build android package mobile diff --git a/internal/driver/mobile/device_desktop.go b/internal/driver/mobile/device_desktop.go index dcabdb0925..006e71cfec 100644 --- a/internal/driver/mobile/device_desktop.go +++ b/internal/driver/mobile/device_desktop.go @@ -1,5 +1,4 @@ //go:build !ios && !android && !wayland -// +build !ios,!android,!wayland package mobile diff --git a/internal/driver/mobile/device_ios.go b/internal/driver/mobile/device_ios.go index 8a27c544d0..a69bcbf164 100644 --- a/internal/driver/mobile/device_ios.go +++ b/internal/driver/mobile/device_ios.go @@ -1,5 +1,4 @@ //go:build ios -// +build ios package mobile diff --git a/internal/driver/mobile/device_wayland.go b/internal/driver/mobile/device_wayland.go index dd7051376c..30f3ee8fd9 100644 --- a/internal/driver/mobile/device_wayland.go +++ b/internal/driver/mobile/device_wayland.go @@ -1,5 +1,4 @@ //go:build wayland -// +build wayland package mobile diff --git a/internal/driver/mobile/file_android.go b/internal/driver/mobile/file_android.go index 32e37ae09e..929fdc6367 100644 --- a/internal/driver/mobile/file_android.go +++ b/internal/driver/mobile/file_android.go @@ -1,5 +1,4 @@ //go:build android -// +build android package mobile diff --git a/internal/driver/mobile/file_desktop.go b/internal/driver/mobile/file_desktop.go index f5a0607fcb..b87e4dce95 100644 --- a/internal/driver/mobile/file_desktop.go +++ b/internal/driver/mobile/file_desktop.go @@ -1,5 +1,4 @@ //go:build !ios && !android -// +build !ios,!android package mobile diff --git a/internal/driver/mobile/file_ios.go b/internal/driver/mobile/file_ios.go index 02de4cf1ac..0a5e4224c0 100644 --- a/internal/driver/mobile/file_ios.go +++ b/internal/driver/mobile/file_ios.go @@ -1,5 +1,4 @@ //go:build ios -// +build ios package mobile diff --git a/internal/driver/mobile/file_ios.m b/internal/driver/mobile/file_ios.m index e7474d2614..5722198350 100644 --- a/internal/driver/mobile/file_ios.m +++ b/internal/driver/mobile/file_ios.m @@ -1,5 +1,4 @@ //go:build ios -// +build ios #import diff --git a/internal/driver/mobile/folder_android.go b/internal/driver/mobile/folder_android.go index 39525a259e..3d789eb953 100644 --- a/internal/driver/mobile/folder_android.go +++ b/internal/driver/mobile/folder_android.go @@ -1,5 +1,4 @@ //go:build android -// +build android package mobile diff --git a/internal/driver/mobile/folder_desktop.go b/internal/driver/mobile/folder_desktop.go index 4828fd58e1..33badb1e03 100644 --- a/internal/driver/mobile/folder_desktop.go +++ b/internal/driver/mobile/folder_desktop.go @@ -1,5 +1,4 @@ //go:build !ios && !android -// +build !ios,!android package mobile diff --git a/internal/driver/mobile/folder_ios.go b/internal/driver/mobile/folder_ios.go index d8dccbcc19..daa192c851 100644 --- a/internal/driver/mobile/folder_ios.go +++ b/internal/driver/mobile/folder_ios.go @@ -1,5 +1,4 @@ //go:build ios -// +build ios package mobile diff --git a/internal/driver/mobile/folder_ios.m b/internal/driver/mobile/folder_ios.m index f895dad14f..a18a536525 100644 --- a/internal/driver/mobile/folder_ios.m +++ b/internal/driver/mobile/folder_ios.m @@ -1,5 +1,4 @@ //go:build ios -// +build ios #import diff --git a/internal/driver/mobile/gl/gl.go b/internal/driver/mobile/gl/gl.go index 7d3cf2cdf1..2ed5ccd178 100644 --- a/internal/driver/mobile/gl/gl.go +++ b/internal/driver/mobile/gl/gl.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || linux || openbsd || freebsd || windows -// +build darwin linux openbsd freebsd windows package gl diff --git a/internal/driver/mobile/gl/types.go b/internal/driver/mobile/gl/types.go index 79f498ba25..7ac387226e 100644 --- a/internal/driver/mobile/gl/types.go +++ b/internal/driver/mobile/gl/types.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || linux || openbsd || freebsd || windows -// +build darwin linux openbsd freebsd windows package gl diff --git a/internal/driver/mobile/gl/work.c b/internal/driver/mobile/gl/work.c index b00dd3510e..4ed4a25568 100644 --- a/internal/driver/mobile/gl/work.c +++ b/internal/driver/mobile/gl/work.c @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || linux || openbsd || freebsd -// +build darwin linux openbsd freebsd #include #include "_cgo_export.h" diff --git a/internal/driver/mobile/gl/work.go b/internal/driver/mobile/gl/work.go index 53d9d39615..6233077453 100644 --- a/internal/driver/mobile/gl/work.go +++ b/internal/driver/mobile/gl/work.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || linux || openbsd || freebsd -// +build darwin linux openbsd freebsd package gl diff --git a/internal/driver/mobile/gl/work_other.go b/internal/driver/mobile/gl/work_other.go index 8e554365c9..5168f0ea0c 100644 --- a/internal/driver/mobile/gl/work_other.go +++ b/internal/driver/mobile/gl/work_other.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (!cgo || (!darwin && !linux && !openbsd && !freebsd)) && !windows -// +build !cgo !darwin,!linux,!openbsd,!freebsd -// +build !windows package gl diff --git a/internal/driver/mobile/menu_test.go b/internal/driver/mobile/menu_test.go index 8581330ebb..c5b9cef7f4 100644 --- a/internal/driver/mobile/menu_test.go +++ b/internal/driver/mobile/menu_test.go @@ -1,5 +1,4 @@ //go:build !windows || !ci -// +build !windows !ci package mobile diff --git a/internal/driver/mobile/mobileinit/mobileinit_ios.go b/internal/driver/mobile/mobileinit/mobileinit_ios.go index 8e16f3f34c..ae33c12e9b 100644 --- a/internal/driver/mobile/mobileinit/mobileinit_ios.go +++ b/internal/driver/mobile/mobileinit/mobileinit_ios.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && (arm || arm64) -// +build darwin -// +build arm arm64 package mobileinit diff --git a/internal/driver/mobile/mobileinit/mobileinit_ios.m b/internal/driver/mobile/mobileinit/mobileinit_ios.m index d8562c776b..84ab98dcab 100644 --- a/internal/driver/mobile/mobileinit/mobileinit_ios.m +++ b/internal/driver/mobile/mobileinit/mobileinit_ios.m @@ -1,6 +1,4 @@ //go:build darwin && (arm || arm64) -// +build darwin -// +build arm arm64 #import diff --git a/internal/driver/mobile/uri.go b/internal/driver/mobile/uri.go index 2ad6ad5942..8b2d05d927 100644 --- a/internal/driver/mobile/uri.go +++ b/internal/driver/mobile/uri.go @@ -1,5 +1,4 @@ //go:build !android -// +build !android package mobile diff --git a/internal/driver/mobile/uri_android.go b/internal/driver/mobile/uri_android.go index f7cebc39ee..82d0ea3bd8 100644 --- a/internal/driver/mobile/uri_android.go +++ b/internal/driver/mobile/uri_android.go @@ -1,5 +1,4 @@ //go:build android -// +build android package mobile diff --git a/internal/hints_disabled.go b/internal/hints_disabled.go index b7b0432bb7..280952430a 100644 --- a/internal/hints_disabled.go +++ b/internal/hints_disabled.go @@ -1,5 +1,4 @@ //go:build !hints -// +build !hints package internal diff --git a/internal/hints_enabled.go b/internal/hints_enabled.go index 5f1038ed8f..3e4935ab9b 100644 --- a/internal/hints_enabled.go +++ b/internal/hints_enabled.go @@ -1,5 +1,4 @@ //go:build hints -// +build hints package internal diff --git a/internal/painter/gl/draw_test.go b/internal/painter/gl/draw_test.go index 10846eb809..99827d28a8 100644 --- a/internal/painter/gl/draw_test.go +++ b/internal/painter/gl/draw_test.go @@ -1,5 +1,4 @@ //go:build !windows || !ci -// +build !windows !ci package gl diff --git a/internal/painter/gl/gl_core.go b/internal/painter/gl/gl_core.go index 5e4d25bc54..895ea720d8 100644 --- a/internal/painter/gl/gl_core.go +++ b/internal/painter/gl/gl_core.go @@ -1,5 +1,4 @@ //go:build (!gles && !arm && !arm64 && !android && !ios && !mobile && !test_web_driver && !wasm) || (darwin && !mobile && !ios && !wasm && !test_web_driver) -// +build !gles,!arm,!arm64,!android,!ios,!mobile,!test_web_driver,!wasm darwin,!mobile,!ios,!wasm,!test_web_driver package gl diff --git a/internal/painter/gl/gl_es.go b/internal/painter/gl/gl_es.go index c810eefbc6..d0c196551d 100644 --- a/internal/painter/gl/gl_es.go +++ b/internal/painter/gl/gl_es.go @@ -1,11 +1,4 @@ //go:build (gles || arm || arm64) && !android && !ios && !mobile && !darwin && !wasm && !test_web_driver -// +build gles arm arm64 -// +build !android -// +build !ios -// +build !mobile -// +build !darwin -// +build !wasm -// +build !test_web_driver package gl diff --git a/internal/painter/gl/gl_gomobile.go b/internal/painter/gl/gl_gomobile.go index a0d76182e5..eb84dadeba 100644 --- a/internal/painter/gl/gl_gomobile.go +++ b/internal/painter/gl/gl_gomobile.go @@ -1,6 +1,4 @@ //go:build (android || ios || mobile) && (!wasm || !test_web_driver) -// +build android ios mobile -// +build !wasm !test_web_driver package gl diff --git a/internal/painter/gl/gl_goxjs.go b/internal/painter/gl/gl_goxjs.go index 6d0c5121f6..44c002df33 100644 --- a/internal/painter/gl/gl_goxjs.go +++ b/internal/painter/gl/gl_goxjs.go @@ -1,5 +1,4 @@ //go:build wasm || test_web_driver -// +build wasm test_web_driver package gl diff --git a/internal/painter/gl/gl_test.go b/internal/painter/gl/gl_test.go index 51e0df0c12..f2b89f877d 100644 --- a/internal/painter/gl/gl_test.go +++ b/internal/painter/gl/gl_test.go @@ -1,5 +1,4 @@ //go:build !ci -// +build !ci package gl diff --git a/key_other.go b/key_other.go index dcdf882a63..f5fdd0d4a2 100644 --- a/key_other.go +++ b/key_other.go @@ -1,5 +1,4 @@ //go:build !darwin -// +build !darwin package fyne diff --git a/test/device_mobile.go b/test/device_mobile.go index 5702237931..781f0f7883 100644 --- a/test/device_mobile.go +++ b/test/device_mobile.go @@ -1,5 +1,4 @@ //go:build mobile -// +build mobile package test diff --git a/test/device_other.go b/test/device_other.go index 0c0275ba8c..23b80f736c 100644 --- a/test/device_other.go +++ b/test/device_other.go @@ -1,5 +1,4 @@ //go:build !mobile -// +build !mobile package test diff --git a/theme/bundled-emoji.go b/theme/bundled-emoji.go index 1096ecc463..d8cf5ad6e9 100644 --- a/theme/bundled-emoji.go +++ b/theme/bundled-emoji.go @@ -1,7 +1,6 @@ // auto-generated // Code generated by '$ fyne bundle'. DO NOT EDIT.//go:build !no_emoji //go:build !no_emoji -// +build !no_emoji package theme diff --git a/theme/gen.go b/theme/gen.go index 11a2cb50ba..5033d6a785 100644 --- a/theme/gen.go +++ b/theme/gen.go @@ -1,5 +1,4 @@ //go:build ignore -// +build ignore package main @@ -75,7 +74,7 @@ func main() { fmt.Println("Bundle emoji…") f = &bytes.Buffer{} - f.WriteString(fileHeader + "//go:build !no_emoji\n// +build !no_emoji\n\n\npackage theme\n\nimport \"fyne.io/fyne/v2\"\n\n") + f.WriteString(fileHeader + "//go:build !no_emoji\n\n\npackage theme\n\nimport \"fyne.io/fyne/v2\"\n\n") bundleFont("EmojiOneColor.otf", "emoji", f) err = writeFile("bundled-emoji.go", f.Bytes()) diff --git a/theme/theme_hints.go b/theme/theme_hints.go index f346c39bc0..58d9d367f5 100644 --- a/theme/theme_hints.go +++ b/theme/theme_hints.go @@ -1,5 +1,4 @@ //go:build hints -// +build hints package theme diff --git a/theme/theme_other.go b/theme/theme_other.go index 6c35e1fadc..e12d351014 100644 --- a/theme/theme_other.go +++ b/theme/theme_other.go @@ -1,5 +1,4 @@ //go:build !hints -// +build !hints package theme diff --git a/theme/unbundled-emoji.go b/theme/unbundled-emoji.go index 3d3197915d..99665e7024 100644 --- a/theme/unbundled-emoji.go +++ b/theme/unbundled-emoji.go @@ -1,5 +1,4 @@ //go:build no_emoji -// +build no_emoji package theme diff --git a/widget/fileicon_internal_test.go b/widget/fileicon_internal_test.go index ef290de1f8..ae522265a9 100644 --- a/widget/fileicon_internal_test.go +++ b/widget/fileicon_internal_test.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package widget diff --git a/widget/menu_desktop_test.go b/widget/menu_desktop_test.go index ac449476e2..4d4f5743a2 100644 --- a/widget/menu_desktop_test.go +++ b/widget/menu_desktop_test.go @@ -1,5 +1,4 @@ //go:build !mobile -// +build !mobile package widget_test diff --git a/widget/menu_internal_desktop_test.go b/widget/menu_internal_desktop_test.go index 51e4ff9e92..051aa419d8 100644 --- a/widget/menu_internal_desktop_test.go +++ b/widget/menu_internal_desktop_test.go @@ -1,5 +1,4 @@ //go:build !mobile -// +build !mobile package widget diff --git a/widget/menu_internal_mobile_test.go b/widget/menu_internal_mobile_test.go index 839ed26d37..b363ef6277 100644 --- a/widget/menu_internal_mobile_test.go +++ b/widget/menu_internal_mobile_test.go @@ -1,5 +1,4 @@ //go:build mobile -// +build mobile package widget diff --git a/widget/menu_item_other.go b/widget/menu_item_other.go index e4122fee59..6c8f55220e 100644 --- a/widget/menu_item_other.go +++ b/widget/menu_item_other.go @@ -1,5 +1,4 @@ //go:build !darwin -// +build !darwin package widget diff --git a/widget/menu_mobile_test.go b/widget/menu_mobile_test.go index 178780eb61..9c81ed0381 100644 --- a/widget/menu_mobile_test.go +++ b/widget/menu_mobile_test.go @@ -1,5 +1,4 @@ //go:build mobile -// +build mobile package widget_test diff --git a/widget/popup_menu_desktop_test.go b/widget/popup_menu_desktop_test.go index b4dea0117e..beddddfebe 100644 --- a/widget/popup_menu_desktop_test.go +++ b/widget/popup_menu_desktop_test.go @@ -1,5 +1,4 @@ //go:build !mobile -// +build !mobile package widget_test diff --git a/widget/table_desktop_test.go b/widget/table_desktop_test.go index 881abf6d2c..e06990b227 100644 --- a/widget/table_desktop_test.go +++ b/widget/table_desktop_test.go @@ -1,5 +1,4 @@ //go:build !mobile -// +build !mobile package widget From 6d2290114fd68b49b98197cae26a0bba5367fd62 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 2 Jan 2024 12:34:01 +0100 Subject: [PATCH 218/248] Fix the build tag that I broke --- internal/driver/mobile/app/darwin_desktop.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/driver/mobile/app/darwin_desktop.m b/internal/driver/mobile/app/darwin_desktop.m index 7d2c3dc48c..b1b5c2bd36 100644 --- a/internal/driver/mobile/app/darwin_desktop.m +++ b/internal/driver/mobile/app/darwin_desktop.m @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin || !ios +//go:build darwin && !ios #include "_cgo_export.h" #include From 8fdc9b4cdd16ec8fe006bee8e50f48909585acbc Mon Sep 17 00:00:00 2001 From: Jesse Donat Date: Tue, 2 Jan 2024 11:56:58 -0600 Subject: [PATCH 219/248] Upgrade go-text/typesetting to v0.1.0 --- go.mod | 2 +- go.sum | 6 +++--- internal/painter/font.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index c590cf6416..e524d55cec 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7 github.com/go-ole/go-ole v1.2.6 github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 - github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a + github.com/go-text/typesetting v0.1.0 github.com/godbus/dbus/v5 v5.1.0 github.com/jackmordaunt/icns/v2 v2.2.6 github.com/josephspurrier/goversioninfo v1.4.0 diff --git a/go.sum b/go.sum index 7041263d55..f85a802a93 100644 --- a/go.sum +++ b/go.sum @@ -101,9 +101,9 @@ github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 h1:VkKnvzbvHqgEfm351rfr8Uclu5fnwq8HP2ximUzJsBM= github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8/go.mod h1:h29xCucjNsDcYb7+0rJokxVwYAq+9kQ19WiFuBKkYtc= -github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a h1:VjN8ttdfklC0dnAdKbZqGNESdERUxtE3l8a/4Grgarc= -github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a/go.mod h1:evDBbvNR/KaVFZ2ZlDSOWWXIUKq0wCOEtzLxRM8SG3k= -github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22 h1:LBQTFxP2MfsyEDqSKmUBZaDuDHN1vpqDyOZjcqS7MYI= +github.com/go-text/typesetting v0.1.0 h1:vioSaLPYcHwPEPLT7gsjCGDCoYSbljxoHJzMnKwVvHw= +github.com/go-text/typesetting v0.1.0/go.mod h1:d22AnmeKq/on0HNv73UFriMKc4Ez6EqZAofLhAzpSzI= +github.com/go-text/typesetting-utils v0.0.0-20231211103740-d9332ae51f04 h1:zBx+p/W2aQYtNuyZNcTfinWvXBQwYtDfme051PR/lAY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= diff --git a/internal/painter/font.go b/internal/painter/font.go index 937bad4a3b..9ce954b9c7 100644 --- a/internal/painter/font.go +++ b/internal/painter/font.go @@ -206,7 +206,7 @@ func walkString(faces []font.Face, s string, textSize fixed.Int26_6, tabWidth in } *advance = x - return fyne.NewSize(*advance, fixed266ToFloat32(out.LineBounds.LineHeight())), + return fyne.NewSize(*advance, fixed266ToFloat32(out.LineBounds.LineThickness())), fixed266ToFloat32(out.LineBounds.Ascent) } From f6be177627fad3dc74e65df777ac7b89051f9bd4 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Wed, 3 Jan 2024 18:20:29 +0000 Subject: [PATCH 220/248] Strip space when no params are added on Linux --- cmd/fyne/internal/templates/bundled.go | 2 +- cmd/fyne/internal/templates/data/app.desktop | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/fyne/internal/templates/bundled.go b/cmd/fyne/internal/templates/bundled.go index 97e86e5cb1..71dff47380 100644 --- a/cmd/fyne/internal/templates/bundled.go +++ b/cmd/fyne/internal/templates/bundled.go @@ -23,7 +23,7 @@ var resourceMakefile = &fyne.StaticResource{ var resourceAppDesktop = &fyne.StaticResource{ StaticName: "app.desktop", StaticContent: []byte( - "[Desktop Entry]\nType=Application\nName={{.Name}}\n{{- if ne .GenericName \"\"}}\nGenericName={{.GenericName}}{{end}}\nExec={{.Exec}} {{.ExecParams}}\nIcon={{.Name}}\n{{- if ne .Comment \"\"}}\nComment={{.Comment}}{{end}}\n{{- if ne .Categories \"\"}}\nCategories={{.Categories}}{{end}}\n{{if ne .Keywords \"\"}}Keywords={{.Keywords}}{{else}}Keywords=fyne;{{end}}"), + "[Desktop Entry]\nType=Application\nName={{.Name}}\n{{- if ne .GenericName \"\"}}\nGenericName={{.GenericName}}{{end}}\nExec={{.Exec}} {{- .ExecParams}}\nIcon={{.Name}}\n{{- if ne .Comment \"\"}}\nComment={{.Comment}}{{end}}\n{{- if ne .Categories \"\"}}\nCategories={{.Categories}}{{end}}\n{{if ne .Keywords \"\"}}Keywords={{.Keywords}}{{else}}Keywords=fyne;{{end}}"), } var resourceAppManifest = &fyne.StaticResource{ StaticName: "app.manifest", diff --git a/cmd/fyne/internal/templates/data/app.desktop b/cmd/fyne/internal/templates/data/app.desktop index a74aea5aa5..a8ae72d8a7 100644 --- a/cmd/fyne/internal/templates/data/app.desktop +++ b/cmd/fyne/internal/templates/data/app.desktop @@ -3,7 +3,7 @@ Type=Application Name={{.Name}} {{- if ne .GenericName ""}} GenericName={{.GenericName}}{{end}} -Exec={{.Exec}} {{.ExecParams}} +Exec={{.Exec}} {{- .ExecParams}} Icon={{.Name}} {{- if ne .Comment ""}} Comment={{.Comment}}{{end}} From 56079a9ebea1316c29699a2ef1d36a2fb88745f9 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Thu, 4 Jan 2024 09:53:29 -0800 Subject: [PATCH 221/248] don't test Cursor with hyperlink --- internal/driver/glfw/window_test.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index f0b8ebfe48..002bf32e1d 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -246,9 +246,13 @@ func TestWindow_Cursor(t *testing.T) { textCursor := desktop.TextCursor assert.Equal(t, textCursor, w.cursor) - w.mouseMoved(w.viewport, float64(h.Position().X+10), float64(h.Position().Y+10)) - pointerCursor := desktop.PointerCursor - assert.Equal(t, pointerCursor, w.cursor) + /* + // See fyne-io/fyne/issues/4513 - Hyperlink doesn't update its cursor type until + // mouse moves are processed in the event queue + w.mouseMoved(w.viewport, float64(h.Position().X+10), float64(h.Position().Y+10)) + pointerCursor := desktop.PointerCursor + assert.Equal(t, pointerCursor, w.cursor) + */ w.mouseMoved(w.viewport, 10, float64(b.Position().Y+10)) defaultCursor := desktop.DefaultCursor From 13894d7c3518bfda83ab3aa0e775387fcea3ecf7 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 5 Jan 2024 19:34:34 +0000 Subject: [PATCH 222/248] Move fileicon public tests to the right file --- widget/fileicon_internal_test.go | 49 -------------------------- widget/fileicon_test.go | 60 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 49 deletions(-) create mode 100644 widget/fileicon_test.go diff --git a/widget/fileicon_internal_test.go b/widget/fileicon_internal_test.go index ef290de1f8..1c2ef7fef2 100644 --- a/widget/fileicon_internal_test.go +++ b/widget/fileicon_internal_test.go @@ -12,7 +12,6 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/storage" - "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" ) @@ -80,54 +79,6 @@ func TestFileIcon_NewURI_WithFolder(t *testing.T) { assert.Equal(t, theme.FolderIcon(), item.resource) } -func TestFileIcon_NewFileIcon_Rendered(t *testing.T) { - test.NewApp() - defer test.NewApp() - - workingDir, err := os.Getwd() - if err != nil { - fyne.LogError("Could not get current working directory", err) - t.FailNow() - } - - icon := NewFileIcon(nil) - - w := test.NewWindow(icon) - w.Resize(fyne.NewSize(150, 150)) - - test.AssertImageMatches(t, "fileicon/fileicon_nil.png", w.Canvas().Capture()) - - text := filepath.Join(workingDir, "testdata/text") - icon2 := NewFileIcon(storage.NewFileURI(text)) - - w.SetContent(icon2) - w.Resize(fyne.NewSize(150, 150)) - test.AssertImageMatches(t, "fileicon/fileicon_text.png", w.Canvas().Capture()) - - text += ".txt" - icon3 := NewFileIcon(storage.NewFileURI(text)) - - w.SetContent(icon3) - w.Resize(fyne.NewSize(150, 150)) - test.AssertImageMatches(t, "fileicon/fileicon_text_txt.png", w.Canvas().Capture()) - - bin := filepath.Join(workingDir, "testdata/bin") - icon4 := NewFileIcon(storage.NewFileURI(bin)) - - w.SetContent(icon4) - w.Resize(fyne.NewSize(150, 150)) - test.AssertImageMatches(t, "fileicon/fileicon_bin.png", w.Canvas().Capture()) - - dir := filepath.Join(workingDir, "testdata") - icon5 := NewFileIcon(storage.NewFileURI(dir)) - - w.SetContent(icon5) - w.Resize(fyne.NewSize(150, 150)) - test.AssertImageMatches(t, "fileicon/fileicon_folder.png", w.Canvas().Capture()) - - w.Close() -} - func TestFileIcon_SetURI(t *testing.T) { item := newRenderedFileIcon(storage.NewFileURI("/path/to/filename.zip")) assert.Equal(t, ".zip", item.extension) diff --git a/widget/fileicon_test.go b/widget/fileicon_test.go new file mode 100644 index 0000000000..d3bf285212 --- /dev/null +++ b/widget/fileicon_test.go @@ -0,0 +1,60 @@ +package widget_test + +import ( + "os" + "path/filepath" + "testing" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/storage" + "fyne.io/fyne/v2/test" + "fyne.io/fyne/v2/widget" +) + +func TestFileIcon_NewFileIcon_Rendered(t *testing.T) { + test.NewApp() + defer test.NewApp() + + workingDir, err := os.Getwd() + if err != nil { + fyne.LogError("Could not get current working directory", err) + t.FailNow() + } + + icon := widget.NewFileIcon(nil) + + w := test.NewWindow(icon) + w.Resize(fyne.NewSize(150, 150)) + + test.AssertImageMatches(t, "fileicon/fileicon_nil.png", w.Canvas().Capture()) + + text := filepath.Join(workingDir, "testdata/text") + icon2 := widget.NewFileIcon(storage.NewFileURI(text)) + + w.SetContent(icon2) + w.Resize(fyne.NewSize(150, 150)) + test.AssertImageMatches(t, "fileicon/fileicon_text.png", w.Canvas().Capture()) + + text += ".txt" + icon3 := widget.NewFileIcon(storage.NewFileURI(text)) + + w.SetContent(icon3) + w.Resize(fyne.NewSize(150, 150)) + test.AssertImageMatches(t, "fileicon/fileicon_text_txt.png", w.Canvas().Capture()) + + bin := filepath.Join(workingDir, "testdata/bin") + icon4 := widget.NewFileIcon(storage.NewFileURI(bin)) + + w.SetContent(icon4) + w.Resize(fyne.NewSize(150, 150)) + test.AssertImageMatches(t, "fileicon/fileicon_bin.png", w.Canvas().Capture()) + + dir := filepath.Join(workingDir, "testdata") + icon5 := widget.NewFileIcon(storage.NewFileURI(dir)) + + w.SetContent(icon5) + w.Resize(fyne.NewSize(150, 150)) + test.AssertImageMatches(t, "fileicon/fileicon_folder.png", w.Canvas().Capture()) + + w.Close() +} From 1a45243c46dbc8769cfd7413b36980a1bd2ed56c Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 5 Jan 2024 19:47:45 +0000 Subject: [PATCH 223/248] Support custom icons in a FileIcon Use a new URIWithIcon type to do this --- uri.go | 9 +++++++++ widget/fileicon.go | 4 ++++ widget/fileicon_test.go | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/uri.go b/uri.go index 3bab3532ff..4cde1a1e04 100644 --- a/uri.go +++ b/uri.go @@ -91,3 +91,12 @@ type ListableURI interface { // List returns a list of child URIs of this URI. List() ([]URI, error) } + +// URIWithIcon describes a URI that should be rendered with a certain icon in file browsers. +// +// Since: 2.5 +type URIWithIcon interface { + URI + + Icon() Resource +} diff --git a/widget/fileicon.go b/widget/fileicon.go index 0ea2ea1833..a2f0b86b51 100644 --- a/widget/fileicon.go +++ b/widget/fileicon.go @@ -94,6 +94,9 @@ func (i *FileIcon) SetSelected(selected bool) { } func (i *FileIcon) lookupIcon(uri fyne.URI) fyne.Resource { + if icon, ok := uri.(fyne.URIWithIcon); ok { + return icon.Icon() + } if i.isDir(uri) { return theme.FolderIcon() } @@ -190,6 +193,7 @@ func (s *fileIconRenderer) Refresh() { } } + s.img.Refresh() canvas.Refresh(s.file.super()) canvas.Refresh(s.ext) } diff --git a/widget/fileicon_test.go b/widget/fileicon_test.go index d3bf285212..a655e39e41 100644 --- a/widget/fileicon_test.go +++ b/widget/fileicon_test.go @@ -5,9 +5,13 @@ import ( "path/filepath" "testing" + "github.com/stretchr/testify/assert" + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/driver/software" "fyne.io/fyne/v2/storage" "fyne.io/fyne/v2/test" + "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -58,3 +62,36 @@ func TestFileIcon_NewFileIcon_Rendered(t *testing.T) { w.Close() } + +func TestFileIcon_Icon(t *testing.T) { + data, _ := filepath.Abs("testdata") + dir := storage.NewFileURI(data) + + icon1 := widget.NewFileIcon(dir) + trash := &customURI{URI: dir, icon: theme.DeleteIcon()} + icon2 := widget.NewFileIcon(trash) + + // test icon change + icon1Img := software.Render(icon1, test.Theme()) + icon2Img := software.Render(icon2, test.Theme()) + assert.NotEqual(t, icon1Img, icon2Img) +} + +type customURI struct { + fyne.URI + + name string + icon fyne.Resource +} + +func (c *customURI) Icon() fyne.Resource { + return c.icon +} + +func (c *customURI) Name() string { + if c.name != "" { + return c.name + } + + return c.URI.Name() +} From ed315852c49e9a28dc7061ecc64f221301a59e57 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 6 Jan 2024 11:00:00 +0100 Subject: [PATCH 224/248] Minor optimization to widget.Entry --- widget/entry.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/widget/entry.go b/widget/entry.go index e943a8fe52..2f7475613e 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -1864,8 +1864,9 @@ func (r *entryContentRenderer) Refresh() { r.moveCursor() for _, selection := range selections { - selection.(*canvas.Rectangle).Hidden = !r.content.entry.focused - selection.(*canvas.Rectangle).FillColor = theme.SelectionColor() + rect := selection.(*canvas.Rectangle) + rect.Hidden = !r.content.entry.focused + rect.FillColor = theme.SelectionColor() } canvas.Refresh(r.content) From 792b8de6bb4e57c2cabbb757eefb12c0dea8b31b Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 6 Jan 2024 17:39:40 +0100 Subject: [PATCH 225/248] Move color out of loop and fix race condition --- widget/entry.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/widget/entry.go b/widget/entry.go index 2f7475613e..422b331a37 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -1841,7 +1841,8 @@ func (r *entryContentRenderer) Refresh() { r.content.entry.propertyLock.RLock() provider := r.content.entry.textProvider() placeholder := r.content.entry.placeholderProvider() - focusedAppearance := r.content.entry.focused && !r.content.entry.disabled + focused := r.content.entry.focused + focusedAppearance := focused && !r.content.entry.disabled selections := r.selection r.updateScrollDirections() r.content.entry.propertyLock.RUnlock() @@ -1863,10 +1864,11 @@ func (r *entryContentRenderer) Refresh() { } r.moveCursor() + selectionColor := theme.SelectionColor() for _, selection := range selections { rect := selection.(*canvas.Rectangle) - rect.Hidden = !r.content.entry.focused - rect.FillColor = theme.SelectionColor() + rect.Hidden = !focused + rect.FillColor = selectionColor } canvas.Refresh(r.content) From ca81ae5d0249a42fa5e2a74fad27ba6d5cdffb25 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 2 Jan 2024 12:24:20 +0100 Subject: [PATCH 226/248] Replace empty interface with any type --- app/app_theme_wasm.go | 2 +- app/preferences.go | 8 +-- app/preferences_test.go | 8 +-- app/settings.go | 6 +- app/settings_desktop_test.go | 4 +- .../internal/commands/mock_runner_test.go | 2 +- cmd/fyne/internal/commands/release.go | 2 +- cmd/fyne/internal/mobile/build.go | 2 +- cmd/fyne_demo/tutorials/widget.go | 4 +- data/binding/binding.go | 28 ++++---- data/binding/binding_test.go | 2 +- data/binding/binditems_test.go | 2 +- data/binding/bindlists.go | 60 ++++++++--------- data/binding/bindtrees.go | 52 +++++++-------- data/binding/gen.go | 6 +- data/binding/mapbinding.go | 66 +++++++++---------- data/binding/mapbinding_test.go | 16 ++--- data/binding/pref_helper.go | 2 +- data/binding/preference_test.go | 2 +- data/binding/sprintf.go | 4 +- dialog/file.go | 2 +- driver/native_android.go | 2 +- driver/native_other.go | 2 +- driver/native_test.go | 2 +- internal/async/chan_interface.go | 16 ++--- internal/async/chan_test.go | 4 +- internal/async/gen.go | 2 +- internal/async/queue_canvasobject.go | 2 +- internal/cache/base.go | 2 +- internal/cache/base_test.go | 2 +- internal/cache/svg.go | 2 +- internal/cache/svg_test.go | 2 +- internal/cache/texture_common.go | 4 +- internal/driver/common/canvas.go | 2 +- internal/driver/common/window.go | 2 +- internal/driver/context.go | 2 +- internal/driver/glfw/canvas_test.go | 4 +- internal/driver/glfw/window.go | 4 +- internal/driver/glfw/window_test.go | 38 +++++------ internal/driver/mobile/app/app.go | 20 +++--- internal/driver/mobile/app/doc.go | 4 +- .../mobile/event/lifecycle/lifecycle.go | 2 +- internal/driver/mobile/window.go | 2 +- internal/preferences.go | 12 ++-- internal/preferences_test.go | 14 ++-- internal/test/util.go | 2 +- shortcut_test.go | 2 +- test/test.go | 14 ++-- widget/entry_test.go | 2 +- widget/gridwrap.go | 2 +- widget/list.go | 2 +- 51 files changed, 226 insertions(+), 226 deletions(-) diff --git a/app/app_theme_wasm.go b/app/app_theme_wasm.go index 66f141e338..e95d683ea0 100644 --- a/app/app_theme_wasm.go +++ b/app/app_theme_wasm.go @@ -22,7 +22,7 @@ func defaultVariant() fyne.ThemeVariant { func init() { if matchMedia := js.Global().Call("matchMedia", "(prefers-color-scheme: dark)"); matchMedia.Truthy() { - matchMedia.Call("addEventListener", "change", js.FuncOf(func(this js.Value, args []js.Value) interface{} { + matchMedia.Call("addEventListener", "change", js.FuncOf(func(this js.Value, args []js.Value) any { fyne.CurrentApp().Settings().(*settings).setupTheme() return nil })) diff --git a/app/preferences.go b/app/preferences.go index 9ada3f675c..33ff6bfe4d 100644 --- a/app/preferences.go +++ b/app/preferences.go @@ -80,7 +80,7 @@ func (p *preferences) saveToFile(path string) error { defer file.Close() encode := json.NewEncoder(file) - p.InMemoryPreferences.ReadValues(func(values map[string]interface{}) { + p.InMemoryPreferences.ReadValues(func(values map[string]any) { err = encode.Encode(&values) }) @@ -120,7 +120,7 @@ func (p *preferences) loadFromFile(path string) (err error) { p.loadingInProgress = true p.prefLock.Unlock() - p.InMemoryPreferences.WriteValues(func(values map[string]interface{}) { + p.InMemoryPreferences.WriteValues(func(values map[string]any) { err = decode.Decode(&values) if err != nil { return @@ -170,9 +170,9 @@ func newPreferences(app *fyneApp) *preferences { return p } -func convertLists(values map[string]interface{}) { +func convertLists(values map[string]any) { for k, v := range values { - if items, ok := v.([]interface{}); ok { + if items, ok := v.([]any); ok { if len(items) == 0 { continue } diff --git a/app/preferences_test.go b/app/preferences_test.go index 7a189aacfb..9f0de61e2c 100644 --- a/app/preferences_test.go +++ b/app/preferences_test.go @@ -17,7 +17,7 @@ func loadPreferences(id string) *preferences { func TestPreferences_Remove(t *testing.T) { p := loadPreferences("dummy") - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["keyString"] = "value" val["keyInt"] = 4 }) @@ -34,7 +34,7 @@ func TestPreferences_Remove(t *testing.T) { func TestPreferences_Save(t *testing.T) { p := loadPreferences("dummy") - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["keyString"] = "value" val["keyStringList"] = []string{"1", "2", "3"} val["keyInt"] = 4 @@ -68,7 +68,7 @@ func TestPreferences_Save(t *testing.T) { func TestPreferences_Save_OverwriteFast(t *testing.T) { p := loadPreferences("dummy2") - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["key"] = "value" }) @@ -76,7 +76,7 @@ func TestPreferences_Save_OverwriteFast(t *testing.T) { defer os.Remove(path) p.saveToFile(path) - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["key2"] = "value2" }) p.saveToFile(path) diff --git a/app/settings.go b/app/settings.go index cc0d32ed42..bac0469530 100644 --- a/app/settings.go +++ b/app/settings.go @@ -38,8 +38,8 @@ type settings struct { themeSpecified bool variant fyne.ThemeVariant - changeListeners sync.Map // map[chan fyne.Settings]bool - watcher interface{} // normally *fsnotify.Watcher or nil - avoid import in this file + changeListeners sync.Map // map[chan fyne.Settings]bool + watcher any // normally *fsnotify.Watcher or nil - avoid import in this file schema SettingsSchema } @@ -104,7 +104,7 @@ func (s *settings) AddChangeListener(listener chan fyne.Settings) { } func (s *settings) apply() { - s.changeListeners.Range(func(key, _ interface{}) bool { + s.changeListeners.Range(func(key, _ any) bool { listener := key.(chan fyne.Settings) select { case listener <- s: diff --git a/app/settings_desktop_test.go b/app/settings_desktop_test.go index ea9f5c7c0d..e550bec810 100644 --- a/app/settings_desktop_test.go +++ b/app/settings_desktop_test.go @@ -44,7 +44,7 @@ func TestWatchFile(t *testing.T) { f.Close() defer os.Remove(path) - called := make(chan interface{}, 1) + called := make(chan any, 1) watchFile(path, func() { called <- true }) @@ -65,7 +65,7 @@ func TestFileWatcher_FileDeleted(t *testing.T) { f.Close() defer os.Remove(path) - called := make(chan interface{}, 1) + called := make(chan any, 1) watcher := watchFile(path, func() { called <- true }) diff --git a/cmd/fyne/internal/commands/mock_runner_test.go b/cmd/fyne/internal/commands/mock_runner_test.go index 21dfa0e46d..c22f0e75fe 100644 --- a/cmd/fyne/internal/commands/mock_runner_test.go +++ b/cmd/fyne/internal/commands/mock_runner_test.go @@ -10,7 +10,7 @@ import ( ) type expectedValue struct { - dir interface{} + dir any env []string osEnv bool args []string diff --git a/cmd/fyne/internal/commands/release.go b/cmd/fyne/internal/commands/release.go index 43fe05cf67..6110da3f0d 100644 --- a/cmd/fyne/internal/commands/release.go +++ b/cmd/fyne/internal/commands/release.go @@ -499,7 +499,7 @@ func (r *Releaser) validate() error { return nil } -func (r *Releaser) writeEntitlements(tmpl *template.Template, entitlementData interface{}) (cleanup func(), err error) { +func (r *Releaser) writeEntitlements(tmpl *template.Template, entitlementData any) (cleanup func(), err error) { entitlementPath := filepath.Join(r.dir, "entitlements.plist") entitlements, err := os.Create(entitlementPath) if err != nil { diff --git a/cmd/fyne/internal/mobile/build.go b/cmd/fyne/internal/mobile/build.go index db3100d43c..39c591fbd6 100644 --- a/cmd/fyne/internal/mobile/build.go +++ b/cmd/fyne/internal/mobile/build.go @@ -232,7 +232,7 @@ func extractPkgs(nm string, path string) (map[string]bool, error) { var xout io.Writer = os.Stderr -func printcmd(format string, args ...interface{}) { +func printcmd(format string, args ...any) { cmd := fmt.Sprintf(format+"\n", args...) if tmpdir != "" { cmd = strings.Replace(cmd, tmpdir, "$WORK", -1) diff --git a/cmd/fyne_demo/tutorials/widget.go b/cmd/fyne_demo/tutorials/widget.go index d40738ece0..2eb45b4f30 100644 --- a/cmd/fyne_demo/tutorials/widget.go +++ b/cmd/fyne_demo/tutorials/widget.go @@ -35,7 +35,7 @@ var ( progress *widget.ProgressBar fprogress *widget.ProgressBar infProgress *widget.ProgressBarInfinite - endProgress chan interface{} + endProgress chan any ) func makeAccordionTab(_ fyne.Window) fyne.CanvasObject { @@ -377,7 +377,7 @@ func makeProgressTab(_ fyne.Window) fyne.CanvasObject { } infProgress = widget.NewProgressBarInfinite() - endProgress = make(chan interface{}, 1) + endProgress = make(chan any, 1) startProgress() return container.NewVBox( diff --git a/data/binding/binding.go b/data/binding/binding.go index 2034217b33..8183f7b7c8 100644 --- a/data/binding/binding.go +++ b/data/binding/binding.go @@ -74,26 +74,26 @@ func (b *base) RemoveListener(l DataListener) { } func (b *base) trigger() { - b.listeners.Range(func(key, _ interface{}) bool { + b.listeners.Range(func(key, _ any) bool { queueItem(key.(DataListener).DataChanged) return true }) } -// Untyped supports binding a interface{} value. +// Untyped supports binding a any value. // // Since: 2.1 type Untyped interface { DataItem - Get() (interface{}, error) - Set(interface{}) error + Get() (any, error) + Set(any) error } -// NewUntyped returns a bindable interface{} value that is managed internally. +// NewUntyped returns a bindable any value that is managed internally. // // Since: 2.1 func NewUntyped() Untyped { - var blank interface{} = nil + var blank any = nil v := &blank return &boundUntyped{val: reflect.ValueOf(v).Elem()} } @@ -104,14 +104,14 @@ type boundUntyped struct { val reflect.Value } -func (b *boundUntyped) Get() (interface{}, error) { +func (b *boundUntyped) Get() (any, error) { b.lock.RLock() defer b.lock.RUnlock() return b.val.Interface(), nil } -func (b *boundUntyped) Set(val interface{}) error { +func (b *boundUntyped) Set(val any) error { b.lock.Lock() defer b.lock.Unlock() if b.val.Interface() == val { @@ -124,7 +124,7 @@ func (b *boundUntyped) Set(val interface{}) error { return nil } -// ExternalUntyped supports binding a interface{} value to an external value. +// ExternalUntyped supports binding a any value to an external value. // // Since: 2.1 type ExternalUntyped interface { @@ -132,11 +132,11 @@ type ExternalUntyped interface { Reload() error } -// BindUntyped returns a bindable interface{} value that is bound to an external type. +// BindUntyped returns a bindable any value that is bound to an external type. // The parameter must be a pointer to the type you wish to bind. // // Since: 2.1 -func BindUntyped(v interface{}) ExternalUntyped { +func BindUntyped(v any) ExternalUntyped { t := reflect.TypeOf(v) if t.Kind() != reflect.Ptr { fyne.LogError("Invalid type passed to BindUntyped, must be a pointer", nil) @@ -144,7 +144,7 @@ func BindUntyped(v interface{}) ExternalUntyped { } if v == nil { - var blank interface{} + var blank any v = &blank // never allow a nil value pointer } @@ -157,10 +157,10 @@ func BindUntyped(v interface{}) ExternalUntyped { type boundExternalUntyped struct { boundUntyped - old interface{} + old any } -func (b *boundExternalUntyped) Set(val interface{}) error { +func (b *boundExternalUntyped) Set(val any) error { b.lock.Lock() defer b.lock.Unlock() if b.old == val { diff --git a/data/binding/binding_test.go b/data/binding/binding_test.go index 7191bab1df..a9e2d5394b 100644 --- a/data/binding/binding_test.go +++ b/data/binding/binding_test.go @@ -8,7 +8,7 @@ import ( ) func syncMapLen(m *sync.Map) (n int) { - m.Range(func(_, _ interface{}) bool { + m.Range(func(_, _ any) bool { n++ return true }) diff --git a/data/binding/binditems_test.go b/data/binding/binditems_test.go index 0bd517e978..3ed9847beb 100644 --- a/data/binding/binditems_test.go +++ b/data/binding/binditems_test.go @@ -41,7 +41,7 @@ func TestBindFloat(t *testing.T) { } func TestBindUntyped(t *testing.T) { - var val interface{} + var val any val = 0.5 f := BindUntyped(&val) v, err := f.Get() diff --git a/data/binding/bindlists.go b/data/binding/bindlists.go index 9b2430f4f7..5aa8c9ae68 100644 --- a/data/binding/bindlists.go +++ b/data/binding/bindlists.go @@ -1545,22 +1545,22 @@ func (b *boundExternalStringListItem) setIfChanged(val string) error { return nil } -// UntypedList supports binding a list of interface{} values. +// UntypedList supports binding a list of any values. // // Since: 2.1 type UntypedList interface { DataList - Append(value interface{}) error - Get() ([]interface{}, error) - GetValue(index int) (interface{}, error) - Prepend(value interface{}) error - Remove(value interface{}) error - Set(list []interface{}) error - SetValue(index int, value interface{}) error + Append(value any) error + Get() ([]any, error) + GetValue(index int) (any, error) + Prepend(value any) error + Remove(value any) error + Set(list []any) error + SetValue(index int, value any) error } -// ExternalUntypedList supports binding a list of interface{} values from an external variable. +// ExternalUntypedList supports binding a list of any values from an external variable. // // Since: 2.1 type ExternalUntypedList interface { @@ -1569,18 +1569,18 @@ type ExternalUntypedList interface { Reload() error } -// NewUntypedList returns a bindable list of interface{} values. +// NewUntypedList returns a bindable list of any values. // // Since: 2.1 func NewUntypedList() UntypedList { - return &boundUntypedList{val: &[]interface{}{}} + return &boundUntypedList{val: &[]any{}} } -// BindUntypedList returns a bound list of interface{} values, based on the contents of the passed slice. +// BindUntypedList returns a bound list of any values, based on the contents of the passed slice. // If your code changes the content of the slice this refers to you should call Reload() to inform the bindings. // // Since: 2.1 -func BindUntypedList(v *[]interface{}) ExternalUntypedList { +func BindUntypedList(v *[]any) ExternalUntypedList { if v == nil { return NewUntypedList().(ExternalUntypedList) } @@ -1598,10 +1598,10 @@ type boundUntypedList struct { listBase updateExternal bool - val *[]interface{} + val *[]any } -func (l *boundUntypedList) Append(val interface{}) error { +func (l *boundUntypedList) Append(val any) error { l.lock.Lock() defer l.lock.Unlock() @@ -1610,14 +1610,14 @@ func (l *boundUntypedList) Append(val interface{}) error { return l.doReload() } -func (l *boundUntypedList) Get() ([]interface{}, error) { +func (l *boundUntypedList) Get() ([]any, error) { l.lock.RLock() defer l.lock.RUnlock() return *l.val, nil } -func (l *boundUntypedList) GetValue(i int) (interface{}, error) { +func (l *boundUntypedList) GetValue(i int) (any, error) { l.lock.RLock() defer l.lock.RUnlock() @@ -1628,10 +1628,10 @@ func (l *boundUntypedList) GetValue(i int) (interface{}, error) { return (*l.val)[i], nil } -func (l *boundUntypedList) Prepend(val interface{}) error { +func (l *boundUntypedList) Prepend(val any) error { l.lock.Lock() defer l.lock.Unlock() - *l.val = append([]interface{}{val}, *l.val...) + *l.val = append([]any{val}, *l.val...) return l.doReload() } @@ -1643,10 +1643,10 @@ func (l *boundUntypedList) Reload() error { return l.doReload() } -// Remove takes the specified interface{} out of the list. +// Remove takes the specified any out of the list. // // Since: 2.5 -func (l *boundUntypedList) Remove(val interface{}) error { +func (l *boundUntypedList) Remove(val any) error { l.lock.Lock() defer l.lock.Unlock() @@ -1676,7 +1676,7 @@ func (l *boundUntypedList) Remove(val interface{}) error { return l.doReload() } -func (l *boundUntypedList) Set(v []interface{}) error { +func (l *boundUntypedList) Set(v []any) error { l.lock.Lock() defer l.lock.Unlock() *l.val = v @@ -1721,7 +1721,7 @@ func (l *boundUntypedList) doReload() (retErr error) { return } -func (l *boundUntypedList) SetValue(i int, v interface{}) error { +func (l *boundUntypedList) SetValue(i int, v any) error { l.lock.RLock() len := l.Length() l.lock.RUnlock() @@ -1741,7 +1741,7 @@ func (l *boundUntypedList) SetValue(i int, v interface{}) error { return item.(Untyped).Set(v) } -func bindUntypedListItem(v *[]interface{}, i int, external bool) Untyped { +func bindUntypedListItem(v *[]any, i int, external bool) Untyped { if external { ret := &boundExternalUntypedListItem{old: (*v)[i]} ret.val = v @@ -1755,11 +1755,11 @@ func bindUntypedListItem(v *[]interface{}, i int, external bool) Untyped { type boundUntypedListItem struct { base - val *[]interface{} + val *[]any index int } -func (b *boundUntypedListItem) Get() (interface{}, error) { +func (b *boundUntypedListItem) Get() (any, error) { b.lock.Lock() defer b.lock.Unlock() @@ -1770,14 +1770,14 @@ func (b *boundUntypedListItem) Get() (interface{}, error) { return (*b.val)[b.index], nil } -func (b *boundUntypedListItem) Set(val interface{}) error { +func (b *boundUntypedListItem) Set(val any) error { b.lock.Lock() defer b.lock.Unlock() return b.doSet(val) } -func (b *boundUntypedListItem) doSet(val interface{}) error { +func (b *boundUntypedListItem) doSet(val any) error { (*b.val)[b.index] = val b.trigger() @@ -1787,10 +1787,10 @@ func (b *boundUntypedListItem) doSet(val interface{}) error { type boundExternalUntypedListItem struct { boundUntypedListItem - old interface{} + old any } -func (b *boundExternalUntypedListItem) setIfChanged(val interface{}) error { +func (b *boundExternalUntypedListItem) setIfChanged(val any) error { if val == b.old { return nil } diff --git a/data/binding/bindtrees.go b/data/binding/bindtrees.go index d7f39e1d82..daf686bb30 100644 --- a/data/binding/bindtrees.go +++ b/data/binding/bindtrees.go @@ -1719,22 +1719,22 @@ func (t *boundExternalStringTreeItem) setIfChanged(val string) error { return nil } -// UntypedTree supports binding a tree of interface{} values. +// UntypedTree supports binding a tree of any values. // // Since: 2.4 type UntypedTree interface { DataTree - Append(parent, id string, value interface{}) error - Get() (map[string][]string, map[string]interface{}, error) - GetValue(id string) (interface{}, error) - Prepend(parent, id string, value interface{}) error + Append(parent, id string, value any) error + Get() (map[string][]string, map[string]any, error) + GetValue(id string) (any, error) + Prepend(parent, id string, value any) error Remove(id string) error - Set(ids map[string][]string, values map[string]interface{}) error - SetValue(id string, value interface{}) error + Set(ids map[string][]string, values map[string]any) error + SetValue(id string, value any) error } -// ExternalUntypedTree supports binding a tree of interface{} values from an external variable. +// ExternalUntypedTree supports binding a tree of any values from an external variable. // // Since: 2.4 type ExternalUntypedTree interface { @@ -1743,22 +1743,22 @@ type ExternalUntypedTree interface { Reload() error } -// NewUntypedTree returns a bindable tree of interface{} values. +// NewUntypedTree returns a bindable tree of any values. // // Since: 2.4 func NewUntypedTree() UntypedTree { - t := &boundUntypedTree{val: &map[string]interface{}{}} + t := &boundUntypedTree{val: &map[string]any{}} t.ids = make(map[string][]string) t.items = make(map[string]DataItem) return t } -// BindUntypedTree returns a bound tree of interface{} values, based on the contents of the passed values. +// BindUntypedTree returns a bound tree of any values, based on the contents of the passed values. // The ids map specifies how each item relates to its parent (with id ""), with the values being in the v map. // If your code changes the content of the maps this refers to you should call Reload() to inform the bindings. // // Since: 2.4 -func BindUntypedTree(ids *map[string][]string, v *map[string]interface{}) ExternalUntypedTree { +func BindUntypedTree(ids *map[string][]string, v *map[string]any) ExternalUntypedTree { if v == nil { return NewUntypedTree().(ExternalUntypedTree) } @@ -1780,10 +1780,10 @@ type boundUntypedTree struct { treeBase updateExternal bool - val *map[string]interface{} + val *map[string]any } -func (t *boundUntypedTree) Append(parent, id string, val interface{}) error { +func (t *boundUntypedTree) Append(parent, id string, val any) error { t.lock.Lock() defer t.lock.Unlock() ids, ok := t.ids[parent] @@ -1798,14 +1798,14 @@ func (t *boundUntypedTree) Append(parent, id string, val interface{}) error { return t.doReload() } -func (t *boundUntypedTree) Get() (map[string][]string, map[string]interface{}, error) { +func (t *boundUntypedTree) Get() (map[string][]string, map[string]any, error) { t.lock.RLock() defer t.lock.RUnlock() return t.ids, *t.val, nil } -func (t *boundUntypedTree) GetValue(id string) (interface{}, error) { +func (t *boundUntypedTree) GetValue(id string) (any, error) { t.lock.RLock() defer t.lock.RUnlock() @@ -1816,7 +1816,7 @@ func (t *boundUntypedTree) GetValue(id string) (interface{}, error) { return nil, errOutOfBounds } -func (t *boundUntypedTree) Prepend(parent, id string, val interface{}) error { +func (t *boundUntypedTree) Prepend(parent, id string, val any) error { t.lock.Lock() defer t.lock.Unlock() ids, ok := t.ids[parent] @@ -1864,7 +1864,7 @@ func (t *boundUntypedTree) Reload() error { return t.doReload() } -func (t *boundUntypedTree) Set(ids map[string][]string, v map[string]interface{}) error { +func (t *boundUntypedTree) Set(ids map[string][]string, v map[string]any) error { t.lock.Lock() defer t.lock.Unlock() t.ids = ids @@ -1931,7 +1931,7 @@ func (t *boundUntypedTree) doReload() (retErr error) { return } -func (t *boundUntypedTree) SetValue(id string, v interface{}) error { +func (t *boundUntypedTree) SetValue(id string, v any) error { t.lock.Lock() (*t.val)[id] = v t.lock.Unlock() @@ -1943,7 +1943,7 @@ func (t *boundUntypedTree) SetValue(id string, v interface{}) error { return item.(Untyped).Set(v) } -func bindUntypedTreeItem(v *map[string]interface{}, id string, external bool) Untyped { +func bindUntypedTreeItem(v *map[string]any, id string, external bool) Untyped { if external { ret := &boundExternalUntypedTreeItem{old: (*v)[id]} ret.val = v @@ -1957,11 +1957,11 @@ func bindUntypedTreeItem(v *map[string]interface{}, id string, external bool) Un type boundUntypedTreeItem struct { base - val *map[string]interface{} + val *map[string]any id string } -func (t *boundUntypedTreeItem) Get() (interface{}, error) { +func (t *boundUntypedTreeItem) Get() (any, error) { t.lock.Lock() defer t.lock.Unlock() @@ -1973,14 +1973,14 @@ func (t *boundUntypedTreeItem) Get() (interface{}, error) { return nil, errOutOfBounds } -func (t *boundUntypedTreeItem) Set(val interface{}) error { +func (t *boundUntypedTreeItem) Set(val any) error { t.lock.Lock() defer t.lock.Unlock() return t.doSet(val) } -func (t *boundUntypedTreeItem) doSet(val interface{}) error { +func (t *boundUntypedTreeItem) doSet(val any) error { (*t.val)[t.id] = val t.trigger() @@ -1990,10 +1990,10 @@ func (t *boundUntypedTreeItem) doSet(val interface{}) error { type boundExternalUntypedTreeItem struct { boundUntypedTreeItem - old interface{} + old any } -func (t *boundExternalUntypedTreeItem) setIfChanged(val interface{}) error { +func (t *boundExternalUntypedTreeItem) setIfChanged(val any) error { if val == t.old { return nil } diff --git a/data/binding/gen.go b/data/binding/gen.go index 1db3cb0bc1..eab9dcc935 100644 --- a/data/binding/gen.go +++ b/data/binding/gen.go @@ -969,7 +969,7 @@ package binding return f, nil } -func writeFile(f *os.File, t *template.Template, d interface{}) { +func writeFile(f *os.File, t *template.Template, d any) { if err := t.Execute(f, d); err != nil { fyne.LogError("Unable to write file "+f.Name(), err) } @@ -1054,7 +1054,7 @@ import ( {Name: "Int", Type: "int", Default: "0", Format: "%d", SupportsPreferences: true}, {Name: "Rune", Type: "rune", Default: "rune(0)"}, {Name: "String", Type: "string", Default: "\"\"", SupportsPreferences: true}, - {Name: "Untyped", Type: "interface{}", Default: "nil", Since: "2.1"}, + {Name: "Untyped", Type: "any", Default: "nil", Since: "2.1"}, {Name: "URI", Type: "fyne.URI", Default: "fyne.URI(nil)", Since: "2.1", FromString: "uriFromString", ToString: "uriToString", Comparator: "compareURI"}, } @@ -1066,7 +1066,7 @@ import ( writeFile(listFile, list, b) writeFile(treeFile, tree, b) if b.Name == "Untyped" { - continue // interface{} is special, we have it in binding.go instead + continue // any is special, we have it in binding.go instead } writeFile(itemFile, item, b) diff --git a/data/binding/mapbinding.go b/data/binding/mapbinding.go index f6ec68cfbc..cfc2468075 100644 --- a/data/binding/mapbinding.go +++ b/data/binding/mapbinding.go @@ -16,7 +16,7 @@ type DataMap interface { Keys() []string } -// ExternalUntypedMap is a map data binding with all values untyped (interface{}), connected to an external data source. +// ExternalUntypedMap is a map data binding with all values untyped (any), connected to an external data source. // // Since: 2.0 type ExternalUntypedMap interface { @@ -24,30 +24,30 @@ type ExternalUntypedMap interface { Reload() error } -// UntypedMap is a map data binding with all values Untyped (interface{}). +// UntypedMap is a map data binding with all values Untyped (any). // // Since: 2.0 type UntypedMap interface { DataMap Delete(string) - Get() (map[string]interface{}, error) - GetValue(string) (interface{}, error) - Set(map[string]interface{}) error - SetValue(string, interface{}) error + Get() (map[string]any, error) + GetValue(string) (any, error) + Set(map[string]any) error + SetValue(string, any) error } -// NewUntypedMap creates a new, empty map binding of string to interface{}. +// NewUntypedMap creates a new, empty map binding of string to any. // // Since: 2.0 func NewUntypedMap() UntypedMap { - return &mapBase{items: make(map[string]reflectUntyped), val: &map[string]interface{}{}} + return &mapBase{items: make(map[string]reflectUntyped), val: &map[string]any{}} } -// BindUntypedMap creates a new map binding of string to interface{} based on the data passed. +// BindUntypedMap creates a new map binding of string to any based on the data passed. // If your code changes the content of the map this refers to you should call Reload() to inform the bindings. // // Since: 2.0 -func BindUntypedMap(d *map[string]interface{}) ExternalUntypedMap { +func BindUntypedMap(d *map[string]any) ExternalUntypedMap { if d == nil { return NewUntypedMap().(ExternalUntypedMap) } @@ -65,17 +65,17 @@ func BindUntypedMap(d *map[string]interface{}) ExternalUntypedMap { // Since: 2.0 type Struct interface { DataMap - GetValue(string) (interface{}, error) - SetValue(string, interface{}) error + GetValue(string) (any, error) + SetValue(string, any) error Reload() error } -// BindStruct creates a new map binding of string to interface{} using the struct passed as data. -// The key for each item is a string representation of each exported field with the value set as an interface{}. +// BindStruct creates a new map binding of string to any using the struct passed as data. +// The key for each item is a string representation of each exported field with the value set as an any. // Only exported fields are included. // // Since: 2.0 -func BindStruct(i interface{}) Struct { +func BindStruct(i any) Struct { if i == nil { return NewUntypedMap().(Struct) } @@ -88,7 +88,7 @@ func BindStruct(i interface{}) Struct { s := &boundStruct{orig: i} s.items = make(map[string]reflectUntyped) - s.val = &map[string]interface{}{} + s.val = &map[string]any{} s.updateExternal = true v := reflect.ValueOf(i).Elem() @@ -109,8 +109,8 @@ func BindStruct(i interface{}) Struct { type reflectUntyped interface { DataItem - get() (interface{}, error) - set(interface{}) error + get() (any, error) + set(any) error } type mapBase struct { @@ -118,7 +118,7 @@ type mapBase struct { updateExternal bool items map[string]reflectUntyped - val *map[string]interface{} + val *map[string]any } func (b *mapBase) GetItem(key string) (DataItem, error) { @@ -155,18 +155,18 @@ func (b *mapBase) Delete(key string) { b.trigger() } -func (b *mapBase) Get() (map[string]interface{}, error) { +func (b *mapBase) Get() (map[string]any, error) { b.lock.RLock() defer b.lock.RUnlock() if b.val == nil { - return map[string]interface{}{}, nil + return map[string]any{}, nil } return *b.val, nil } -func (b *mapBase) GetValue(key string) (interface{}, error) { +func (b *mapBase) GetValue(key string) (any, error) { b.lock.RLock() defer b.lock.RUnlock() @@ -184,7 +184,7 @@ func (b *mapBase) Reload() error { return b.doReload() } -func (b *mapBase) Set(v map[string]interface{}) error { +func (b *mapBase) Set(v map[string]any) error { b.lock.Lock() defer b.lock.Unlock() @@ -198,7 +198,7 @@ func (b *mapBase) Set(v map[string]interface{}) error { return b.doReload() } -func (b *mapBase) SetValue(key string, d interface{}) error { +func (b *mapBase) SetValue(key string, d any) error { b.lock.Lock() defer b.lock.Unlock() @@ -260,7 +260,7 @@ func (b *mapBase) setItem(key string, d reflectUntyped) { type boundStruct struct { mapBase - orig interface{} + orig any } func (b *boundStruct) Reload() (retErr error) { @@ -305,7 +305,7 @@ func (b *boundStruct) Reload() (retErr error) { return } -func bindUntypedMapValue(m *map[string]interface{}, k string, external bool) reflectUntyped { +func bindUntypedMapValue(m *map[string]any, k string, external bool) reflectUntyped { if external { ret := &boundExternalMapValue{old: (*m)[k]} ret.val = m @@ -319,11 +319,11 @@ func bindUntypedMapValue(m *map[string]interface{}, k string, external bool) ref type boundMapValue struct { base - val *map[string]interface{} + val *map[string]any key string } -func (b *boundMapValue) get() (interface{}, error) { +func (b *boundMapValue) get() (any, error) { if v, ok := (*b.val)[b.key]; ok { return v, nil } @@ -331,7 +331,7 @@ func (b *boundMapValue) get() (interface{}, error) { return nil, errKeyNotFound } -func (b *boundMapValue) set(val interface{}) error { +func (b *boundMapValue) set(val any) error { (*b.val)[b.key] = val b.trigger() @@ -341,10 +341,10 @@ func (b *boundMapValue) set(val interface{}) error { type boundExternalMapValue struct { boundMapValue - old interface{} + old any } -func (b *boundExternalMapValue) setIfChanged(val interface{}) error { +func (b *boundExternalMapValue) setIfChanged(val any) error { if val == b.old { return nil } @@ -359,11 +359,11 @@ type boundReflect struct { val reflect.Value } -func (b *boundReflect) get() (interface{}, error) { +func (b *boundReflect) get() (any, error) { return b.val.Interface(), nil } -func (b *boundReflect) set(val interface{}) (err error) { +func (b *boundReflect) set(val any) (err error) { defer func() { if r := recover(); r != nil { err = errors.New("unable to set bool in data binding") diff --git a/data/binding/mapbinding_test.go b/data/binding/mapbinding_test.go index ffdb1fe83c..fb33aab0f5 100644 --- a/data/binding/mapbinding_test.go +++ b/data/binding/mapbinding_test.go @@ -138,7 +138,7 @@ func TestBindStruct_Reload(t *testing.T) { } func TestBindUntypedMap(t *testing.T) { - m := map[string]interface{}{ + m := map[string]any{ "foo": "bar", "val": 5, "bas": 0.2, @@ -168,7 +168,7 @@ func TestBindUntypedMap(t *testing.T) { } func TestExternalUntypedMap_Reload(t *testing.T) { - m := map[string]interface{}{ + m := map[string]any{ "foo": "bar", "val": 5, "bas": 0.2, @@ -207,7 +207,7 @@ func TestExternalUntypedMap_Reload(t *testing.T) { assert.True(t, calledChild) calledMap, calledChild = false, false - m = map[string]interface{}{ + m = map[string]any{ "foo": "bar", "val": 5, } @@ -220,7 +220,7 @@ func TestExternalUntypedMap_Reload(t *testing.T) { assert.True(t, calledChild) calledMap, calledChild = false, false - m = map[string]interface{}{ + m = map[string]any{ "foo": "bar", "val": 5, "new": "longer", @@ -235,7 +235,7 @@ func TestExternalUntypedMap_Reload(t *testing.T) { } func TestUntypedMap_Delete(t *testing.T) { - m := map[string]interface{}{ + m := map[string]any{ "foo": "bar", "val": 5, } @@ -261,7 +261,7 @@ func TestUntypedMap_Delete(t *testing.T) { } func TestUntypedMap_Set(t *testing.T) { - m := map[string]interface{}{ + m := map[string]any{ "foo": "bar", "val": 5, } @@ -279,7 +279,7 @@ func TestUntypedMap_Set(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 5, v) - m = map[string]interface{}{ + m = map[string]any{ "foo": "new", "bas": "another", "val": 7, @@ -295,7 +295,7 @@ func TestUntypedMap_Set(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 7, v) - m = map[string]interface{}{ + m = map[string]any{ "val": 9, } err = b.Set(m) diff --git a/data/binding/pref_helper.go b/data/binding/pref_helper.go index 5ee5b4eece..e37c367d3a 100644 --- a/data/binding/pref_helper.go +++ b/data/binding/pref_helper.go @@ -24,7 +24,7 @@ func (b *preferenceBindings) getItem(key string) preferenceItem { func (b *preferenceBindings) list() []preferenceItem { ret := []preferenceItem{} - b.items.Range(func(_, val interface{}) bool { + b.items.Range(func(_, val any) bool { ret = append(ret, val.(preferenceItem)) return true }) diff --git a/data/binding/preference_test.go b/data/binding/preference_test.go index ba511f2283..49852d5c14 100644 --- a/data/binding/preference_test.go +++ b/data/binding/preference_test.go @@ -142,7 +142,7 @@ func TestPreferenceBindingTriggers(t *testing.T) { bind1 := BindPreferenceString(key, p) bind2 := BindPreferenceString(key, p) - ch := make(chan interface{}, 2) + ch := make(chan any, 2) bind1.AddListener(NewDataListener(func() { ch <- struct{}{} })) diff --git a/data/binding/sprintf.go b/data/binding/sprintf.go index 3389cf9c54..faa39b5f64 100644 --- a/data/binding/sprintf.go +++ b/data/binding/sprintf.go @@ -35,7 +35,7 @@ func NewSprintf(format string, b ...DataItem) String { } func (s *sprintfString) DataChanged() { - data := make([]interface{}, 0, len(s.source)) + data := make([]any, 0, len(s.source)) s.err = nil for _, value := range s.source { @@ -112,7 +112,7 @@ func (s *sprintfString) Get() (string, error) { } func (s *sprintfString) Set(str string) error { - data := make([]interface{}, 0, len(s.source)) + data := make([]any, 0, len(s.source)) s.err = nil for _, value := range s.source { diff --git a/dialog/file.go b/dialog/file.go index 64ac9f3382..05c8648caf 100644 --- a/dialog/file.go +++ b/dialog/file.go @@ -71,7 +71,7 @@ type fileDialog struct { // FileDialog is a dialog containing a file picker for use in opening or saving files. type FileDialog struct { - callback interface{} + callback any onClosedCallback func(bool) parent fyne.Window dialog *fileDialog diff --git a/driver/native_android.go b/driver/native_android.go index 98e179a060..64cae3311a 100644 --- a/driver/native_android.go +++ b/driver/native_android.go @@ -8,7 +8,7 @@ import "fyne.io/fyne/v2/internal/driver/mobile/app" // On Android this provides the JVM pointers required to execute various NDK calls or use JNI APIs. // // Since: 2.3 -func RunNative(fn func(interface{}) error) error { +func RunNative(fn func(any) error) error { return app.RunOnJVM(func(vm, env, ctx uintptr) error { data := &AndroidContext{VM: vm, Env: env, Ctx: ctx} return fn(data) diff --git a/driver/native_other.go b/driver/native_other.go index 6b2518eeab..0f61efb9ac 100644 --- a/driver/native_other.go +++ b/driver/native_other.go @@ -7,6 +7,6 @@ package driver // The call for most platforms will just execute passing an `UnknownContext` and returning any error reported. // // Since: 2.3 -func RunNative(fn func(interface{}) error) error { +func RunNative(fn func(any) error) error { return fn(&UnknownContext{}) } diff --git a/driver/native_test.go b/driver/native_test.go index e8d6affd12..d1be55131c 100644 --- a/driver/native_test.go +++ b/driver/native_test.go @@ -7,7 +7,7 @@ import ( ) func TestRunNative(t *testing.T) { - err := RunNative(func(i interface{}) error { + err := RunNative(func(i any) error { native, ok := i.(*UnknownContext) assert.True(t, ok) diff --git a/internal/async/chan_interface.go b/internal/async/chan_interface.go index 89e065ce5c..85af28b10c 100755 --- a/internal/async/chan_interface.go +++ b/internal/async/chan_interface.go @@ -6,9 +6,9 @@ package async // UnboundedInterfaceChan is a channel with an unbounded buffer for caching // Interface objects. A channel must be closed via Close method. type UnboundedInterfaceChan struct { - in, out chan interface{} + in, out chan any close chan struct{} - q []interface{} + q []any } // NewUnboundedInterfaceChan returns a unbounded channel with unlimited capacity. @@ -16,8 +16,8 @@ func NewUnboundedInterfaceChan() *UnboundedInterfaceChan { ch := &UnboundedInterfaceChan{ // The size of Interface is less than 16 bytes, we use 16 to fit // a CPU cache line (L2, 256 Bytes), which may reduce cache misses. - in: make(chan interface{}, 16), - out: make(chan interface{}, 16), + in: make(chan any, 16), + out: make(chan any, 16), close: make(chan struct{}), } go ch.processing() @@ -26,11 +26,11 @@ func NewUnboundedInterfaceChan() *UnboundedInterfaceChan { // In returns the send channel of the given channel, which can be used to // send values to the channel. -func (ch *UnboundedInterfaceChan) In() chan<- interface{} { return ch.in } +func (ch *UnboundedInterfaceChan) In() chan<- any { return ch.in } // Out returns the receive channel of the given channel, which can be used // to receive values from the channel. -func (ch *UnboundedInterfaceChan) Out() <-chan interface{} { return ch.out } +func (ch *UnboundedInterfaceChan) Out() <-chan any { return ch.out } // Close closes the channel. func (ch *UnboundedInterfaceChan) Close() { ch.close <- struct{}{} } @@ -41,7 +41,7 @@ func (ch *UnboundedInterfaceChan) processing() { // reallocation size at the subsequent for loop should also be // changed too. Furthermore, there is no memory leak since the // queue is garbage collected. - ch.q = make([]interface{}, 0, 1<<10) + ch.q = make([]any, 0, 1<<10) for { select { case e, ok := <-ch.in: @@ -77,7 +77,7 @@ func (ch *UnboundedInterfaceChan) processing() { // If the remaining capacity is too small, we prefer to // reallocate the entire buffer. if cap(ch.q) < 1<<5 { - ch.q = make([]interface{}, 0, 1<<10) + ch.q = make([]any, 0, 1<<10) } } } diff --git a/internal/async/chan_test.go b/internal/async/chan_test.go index 5996a746a2..3b9dfbb2e8 100644 --- a/internal/async/chan_test.go +++ b/internal/async/chan_test.go @@ -16,7 +16,7 @@ func TestUnboundedChann(t *testing.T) { wg := sync.WaitGroup{} for i := 0; i < N; i++ { - t.Run("interface{}", func(t *testing.T) { + t.Run("any", func(t *testing.T) { t.Run("send", func(t *testing.T) { // Ensure send to an unbounded channel does not block. c := async.NewUnboundedInterfaceChan() @@ -175,7 +175,7 @@ func TestUnboundedChann(t *testing.T) { } func BenchmarkUnboundedChann(b *testing.B) { - b.Run("interface{}", func(b *testing.B) { + b.Run("any", func(b *testing.B) { b.Run("sync", func(b *testing.B) { c := async.NewUnboundedInterfaceChan() b.ResetTimer() diff --git a/internal/async/gen.go b/internal/async/gen.go index f6e7ffdc81..48d2701e4f 100644 --- a/internal/async/gen.go +++ b/internal/async/gen.go @@ -39,7 +39,7 @@ func main() { Imports: "", }, "chan_interface.go": { - Type: "interface{}", + Type: "any", Name: "Interface", Imports: "", }, diff --git a/internal/async/queue_canvasobject.go b/internal/async/queue_canvasobject.go index 5ccd42bf6e..5f4da2b41d 100755 --- a/internal/async/queue_canvasobject.go +++ b/internal/async/queue_canvasobject.go @@ -31,7 +31,7 @@ type itemCanvasObject struct { } var itemCanvasObjectPool = sync.Pool{ - New: func() interface{} { return &itemCanvasObject{} }, + New: func() any { return &itemCanvasObject{} }, } // In puts the given value at the tail of the queue. diff --git a/internal/cache/base.go b/internal/cache/base.go index 92b0167e11..097cedfa48 100644 --- a/internal/cache/base.go +++ b/internal/cache/base.go @@ -149,7 +149,7 @@ func CleanCanvases(refreshingCanvases []fyne.Canvas) { // ResetThemeCaches clears all the svg and text size cache maps func ResetThemeCaches() { - svgs.Range(func(key, value interface{}) bool { + svgs.Range(func(key, value any) bool { svgs.Delete(key) return true }) diff --git a/internal/cache/base_test.go b/internal/cache/base_test.go index b85177b6df..72ae9c1892 100644 --- a/internal/cache/base_test.go +++ b/internal/cache/base_test.go @@ -267,7 +267,7 @@ func testClearAll() { expiredObjects = make([]fyne.CanvasObject, 0, 50) skippedCleanWithCanvasRefresh = false canvases = make(map[fyne.CanvasObject]*canvasInfo, 1024) - svgs.Range(func(key, _ interface{}) bool { + svgs.Range(func(key, _ any) bool { svgs.Delete(key) return true }) diff --git a/internal/cache/svg.go b/internal/cache/svg.go index 0a10771386..20b17038ff 100644 --- a/internal/cache/svg.go +++ b/internal/cache/svg.go @@ -45,7 +45,7 @@ type svgInfo struct { // destroyExpiredSvgs destroys expired svgs cache data. func destroyExpiredSvgs(now time.Time) { expiredSvgs := make([]string, 0, 20) - svgs.Range(func(key, value interface{}) bool { + svgs.Range(func(key, value any) bool { s, sinfo := key.(string), value.(*svgInfo) if sinfo.isExpired(now) { expiredSvgs = append(expiredSvgs, s) diff --git a/internal/cache/svg_test.go b/internal/cache/svg_test.go index 6a06fc6892..3f0899e27b 100644 --- a/internal/cache/svg_test.go +++ b/internal/cache/svg_test.go @@ -10,7 +10,7 @@ import ( ) func syncMapLen(m *sync.Map) (n int) { - m.Range(func(_, _ interface{}) bool { + m.Range(func(_, _ any) bool { n++ return true }) diff --git a/internal/cache/texture_common.go b/internal/cache/texture_common.go index 97576d8ebd..abfd54f644 100644 --- a/internal/cache/texture_common.go +++ b/internal/cache/texture_common.go @@ -30,7 +30,7 @@ func GetTexture(obj fyne.CanvasObject) (TextureType, bool) { // gl context to ensure textures are deleted from gl. func RangeExpiredTexturesFor(canvas fyne.Canvas, f func(fyne.CanvasObject)) { now := timeNow() - textures.Range(func(key, value interface{}) bool { + textures.Range(func(key, value any) bool { obj, tinfo := key.(fyne.CanvasObject), value.(*textureInfo) if tinfo.isExpired(now) && tinfo.canvas == canvas { f(obj) @@ -44,7 +44,7 @@ func RangeExpiredTexturesFor(canvas fyne.Canvas, f func(fyne.CanvasObject)) { // Note: If this is used to free textures, then it should be called inside a current // gl context to ensure textures are deleted from gl. func RangeTexturesFor(canvas fyne.Canvas, f func(fyne.CanvasObject)) { - textures.Range(func(key, value interface{}) bool { + textures.Range(func(key, value any) bool { obj, tinfo := key.(fyne.CanvasObject), value.(*textureInfo) if tinfo.canvas == canvas { f(obj) diff --git a/internal/driver/common/canvas.go b/internal/driver/common/canvas.go index 594a436718..26e1d3ee0a 100644 --- a/internal/driver/common/canvas.go +++ b/internal/driver/common/canvas.go @@ -537,7 +537,7 @@ type RenderCacheNode struct { // it may for instance point to a GL texture // it should free all associated resources when released // i.e. it should not simply be a texture reference integer - painterData interface{} + painterData any } // Obj returns the node object. diff --git a/internal/driver/common/window.go b/internal/driver/common/window.go index eb518bf9a5..0a3c1f0c83 100644 --- a/internal/driver/common/window.go +++ b/internal/driver/common/window.go @@ -46,7 +46,7 @@ func (w *Window) WaitForEvents() { } var DonePool = sync.Pool{ - New: func() interface{} { + New: func() any { return make(chan struct{}) }, } diff --git a/internal/driver/context.go b/internal/driver/context.go index 162a15a417..925eabb0e7 100644 --- a/internal/driver/context.go +++ b/internal/driver/context.go @@ -5,5 +5,5 @@ package driver type WithContext interface { RunWithContext(f func()) RescaleContext() - Context() interface{} + Context() any } diff --git a/internal/driver/glfw/canvas_test.go b/internal/driver/glfw/canvas_test.go index fce55e7c3f..3394a45dbc 100644 --- a/internal/driver/glfw/canvas_test.go +++ b/internal/driver/glfw/canvas_test.go @@ -555,7 +555,7 @@ func TestGlCanvas_SetContent(t *testing.T) { var _ fyne.Layout = (*recordingLayout)(nil) type recordingLayout struct { - layoutEvents []interface{} + layoutEvents []any } func (l *recordingLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { @@ -566,7 +566,7 @@ func (l *recordingLayout) MinSize([]fyne.CanvasObject) fyne.Size { return fyne.NewSize(6, 9) } -func (l *recordingLayout) popLayoutEvent() (e interface{}) { +func (l *recordingLayout) popLayoutEvent() (e any) { e, l.layoutEvents = pop(l.layoutEvents) return } diff --git a/internal/driver/glfw/window.go b/internal/driver/glfw/window.go index a491722dc2..34a99d21dd 100644 --- a/internal/driver/glfw/window.go +++ b/internal/driver/glfw/window.go @@ -457,7 +457,7 @@ func (w *window) processMouseMoved(xpos float64, ypos float64) { } } -func (w *window) objIsDragged(obj interface{}) bool { +func (w *window) objIsDragged(obj any) bool { if w.mouseDragged != nil && obj != nil { draggedObj, _ := obj.(fyne.Draggable) return draggedObj == w.mouseDragged @@ -926,7 +926,7 @@ func (w *window) RescaleContext() { runOnMain(w.rescaleOnMain) } -func (w *window) Context() interface{} { +func (w *window) Context() any { return nil } diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index caa10cf03b..5e677ce8cf 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -1813,9 +1813,9 @@ type hoverableObject struct { var _ desktop.Hoverable = (*hoverable)(nil) type hoverable struct { - mouseInEvents []interface{} - mouseOutEvents []interface{} - mouseMovedEvents []interface{} + mouseInEvents []any + mouseOutEvents []any + mouseMovedEvents []any } func (h *hoverable) MouseIn(e *desktop.MouseEvent) { @@ -1830,17 +1830,17 @@ func (h *hoverable) MouseOut() { h.mouseOutEvents = append(h.mouseOutEvents, true) } -func (h *hoverable) popMouseInEvent() (e interface{}) { +func (h *hoverable) popMouseInEvent() (e any) { e, h.mouseInEvents = pop(h.mouseInEvents) return } -func (h *hoverable) popMouseMovedEvent() (e interface{}) { +func (h *hoverable) popMouseMovedEvent() (e any) { e, h.mouseMovedEvents = pop(h.mouseMovedEvents) return } -func (h *hoverable) popMouseOutEvent() (e interface{}) { +func (h *hoverable) popMouseOutEvent() (e any) { e, h.mouseOutEvents = pop(h.mouseOutEvents) return } @@ -1853,8 +1853,8 @@ type draggableObject struct { var _ fyne.Draggable = (*draggable)(nil) type draggable struct { - events []interface{} - endEvents []interface{} + events []any + endEvents []any } func (d *draggable) Dragged(e *fyne.DragEvent) { @@ -1865,12 +1865,12 @@ func (d *draggable) DragEnd() { d.endEvents = append(d.endEvents, true) } -func (d *draggable) popDragEvent() (e interface{}) { +func (d *draggable) popDragEvent() (e any) { e, d.events = pop(d.events) return } -func (d *draggable) popDragEndEvent() (e interface{}) { +func (d *draggable) popDragEndEvent() (e any) { e, d.endEvents = pop(d.endEvents) return } @@ -1889,7 +1889,7 @@ type mouseableObject struct { var _ desktop.Mouseable = (*mouseable)(nil) type mouseable struct { - mouseEvents []interface{} + mouseEvents []any } func (m *mouseable) MouseDown(e *desktop.MouseEvent) { @@ -1900,7 +1900,7 @@ func (m *mouseable) MouseUp(e *desktop.MouseEvent) { m.mouseEvents = append(m.mouseEvents, e) } -func (m *mouseable) popMouseEvent() (e interface{}) { +func (m *mouseable) popMouseEvent() (e any) { e, m.mouseEvents = pop(m.mouseEvents) return } @@ -1919,8 +1919,8 @@ type tappableObject struct { var _ fyne.Tappable = (*tappable)(nil) type tappable struct { - tapEvents []interface{} - secondaryTapEvents []interface{} + tapEvents []any + secondaryTapEvents []any } func (t *tappable) Tapped(e *fyne.PointEvent) { @@ -1931,12 +1931,12 @@ func (t *tappable) TappedSecondary(e *fyne.PointEvent) { t.secondaryTapEvents = append(t.secondaryTapEvents, e) } -func (t *tappable) popTapEvent() (e interface{}) { +func (t *tappable) popTapEvent() (e any) { e, t.tapEvents = pop(t.tapEvents) return } -func (t *tappable) popSecondaryTapEvent() (e interface{}) { +func (t *tappable) popSecondaryTapEvent() (e any) { e, t.secondaryTapEvents = pop(t.secondaryTapEvents) return } @@ -2007,14 +2007,14 @@ var _ fyne.Scrollable = (*scrollable)(nil) type scrollable struct { *canvas.Rectangle - events []interface{} + events []any } func (s *scrollable) Scrolled(e *fyne.ScrollEvent) { s.events = append(s.events, e) } -func (s *scrollable) popScrollEvent() (e interface{}) { +func (s *scrollable) popScrollEvent() (e any) { e, s.events = pop(s.events) return } @@ -2023,7 +2023,7 @@ func (s *scrollable) popScrollEvent() (e interface{}) { // Test helper // -func pop(s []interface{}) (interface{}, []interface{}) { +func pop(s []any) (any, []any) { if len(s) == 0 { return nil, s } diff --git a/internal/driver/mobile/app/app.go b/internal/driver/mobile/app/app.go index bbff34948e..dc057ecc23 100644 --- a/internal/driver/mobile/app/app.go +++ b/internal/driver/mobile/app/app.go @@ -35,10 +35,10 @@ type App interface { // - touch.Event // from the golang.org/x/mobile/event/etc packages. Other packages may // define other event types that are carried on this channel. - Events() <-chan interface{} + Events() <-chan any // Send sends an event on the events channel. It does not block. - Send(event interface{}) + Send(event any) // Publish flushes any pending drawing commands, such as OpenGL calls, and // swaps the back buffer to the screen. @@ -47,13 +47,13 @@ type App interface { // TODO: replace filters (and the Events channel) with a NextEvent method? // Filter calls each registered event filter function in sequence. - Filter(event interface{}) interface{} + Filter(event any) any // RegisterFilter registers a event filter function to be called by Filter. The // function can return a different event, or return nil to consume the event, // but the function can also return its argument unchanged, where its purpose // is to trigger a side effect rather than modify the event. - RegisterFilter(f func(interface{}) interface{}) + RegisterFilter(f func(any) any) ShowVirtualKeyboard(KeyboardType) HideVirtualKeyboard() @@ -98,7 +98,7 @@ func (a *app) sendLifecycle(to lifecycle.Stage) { } type app struct { - filters []func(interface{}) interface{} + filters []func(any) any events *async.UnboundedInterfaceChan lifecycleStage lifecycle.Stage @@ -109,11 +109,11 @@ type app struct { worker gl.Worker } -func (a *app) Events() <-chan interface{} { +func (a *app) Events() <-chan any { return a.events.Out() } -func (a *app) Send(event interface{}) { +func (a *app) Send(event any) { a.events.In() <- event } @@ -130,14 +130,14 @@ func (a *app) Publish() PublishResult { return <-a.publishResult } -func (a *app) Filter(event interface{}) interface{} { +func (a *app) Filter(event any) any { for _, f := range a.filters { event = f(event) } return event } -func (a *app) RegisterFilter(f func(interface{}) interface{}) { +func (a *app) RegisterFilter(f func(any) any) { a.filters = append(a.filters, f) } @@ -162,7 +162,7 @@ func (a *app) ShowFileSavePicker(callback func(string, func()), filter *FileFilt // TODO: does Android need this?? It seems to work without it (Nexus 7, // KitKat). If only x11 needs this, should we move this to x11.go?? func (a *app) registerGLViewportFilter() { - a.RegisterFilter(func(e interface{}) interface{} { + a.RegisterFilter(func(e any) any { if e, ok := e.(size.Event); ok { a.glctx.Viewport(0, 0, e.WidthPx, e.HeightPx) } diff --git a/internal/driver/mobile/app/doc.go b/internal/driver/mobile/app/doc.go index 47fc6ade95..3ee21814e4 100644 --- a/internal/driver/mobile/app/doc.go +++ b/internal/driver/mobile/app/doc.go @@ -66,8 +66,8 @@ goroutine as other code that calls OpenGL. }) } -An event is represented by the empty interface type interface{}. Any value can -be an event. Commonly used types include Event types defined by the following +An event is represented by the any type, so any value can be an event. +Commonly used types include Event types defined by the following packages: - golang.org/x/mobile/event/lifecycle - golang.org/x/mobile/event/mouse diff --git a/internal/driver/mobile/event/lifecycle/lifecycle.go b/internal/driver/mobile/event/lifecycle/lifecycle.go index c755bf6665..7bd394585f 100644 --- a/internal/driver/mobile/event/lifecycle/lifecycle.go +++ b/internal/driver/mobile/event/lifecycle/lifecycle.go @@ -52,7 +52,7 @@ type Event struct { // For OpenGL apps, a non-nil DrawContext is a gl.Context. // // TODO: make this an App method if we move away from an event channel? - DrawContext interface{} + DrawContext any } func (e Event) String() string { diff --git a/internal/driver/mobile/window.go b/internal/driver/mobile/window.go index c3ad9d03b2..3c044b9768 100644 --- a/internal/driver/mobile/window.go +++ b/internal/driver/mobile/window.go @@ -218,6 +218,6 @@ func (w *window) RescaleContext() { // TODO } -func (w *window) Context() interface{} { +func (w *window) Context() any { return fyne.CurrentApp().Driver().(*mobileDriver).glctx } diff --git a/internal/preferences.go b/internal/preferences.go index c49ca720b9..d61d19fc4f 100644 --- a/internal/preferences.go +++ b/internal/preferences.go @@ -9,7 +9,7 @@ import ( // InMemoryPreferences provides an implementation of the fyne.Preferences API that is stored in memory. type InMemoryPreferences struct { - values map[string]interface{} + values map[string]any lock sync.RWMutex changeListeners []func() } @@ -161,7 +161,7 @@ func (p *InMemoryPreferences) IntWithFallback(key string, fallback int) int { // ReadValues provides read access to the underlying value map - for internal use only... // You should not retain a reference to the map nor write to the values in the callback function -func (p *InMemoryPreferences) ReadValues(fn func(map[string]interface{})) { +func (p *InMemoryPreferences) ReadValues(fn func(map[string]any)) { p.lock.RLock() fn(p.values) p.lock.RUnlock() @@ -244,7 +244,7 @@ func (p *InMemoryPreferences) StringWithFallback(key, fallback string) string { // WriteValues provides write access to the underlying value map - for internal use only... // You should not retain a reference to the map passed to the callback function -func (p *InMemoryPreferences) WriteValues(fn func(map[string]interface{})) { +func (p *InMemoryPreferences) WriteValues(fn func(map[string]any)) { p.lock.Lock() fn(p.values) p.lock.Unlock() @@ -254,7 +254,7 @@ func (p *InMemoryPreferences) WriteValues(fn func(map[string]interface{})) { // NewInMemoryPreferences creates a new preferences implementation stored in memory func NewInMemoryPreferences() *InMemoryPreferences { - return &InMemoryPreferences{values: make(map[string]interface{})} + return &InMemoryPreferences{values: make(map[string]any)} } func (p *InMemoryPreferences) fireChange() { @@ -275,7 +275,7 @@ func (p *InMemoryPreferences) fireChange() { wg.Wait() } -func (p *InMemoryPreferences) get(key string) (interface{}, bool) { +func (p *InMemoryPreferences) get(key string) (any, bool) { p.lock.RLock() defer p.lock.RUnlock() @@ -291,7 +291,7 @@ func (p *InMemoryPreferences) remove(key string) { p.fireChange() } -func (p *InMemoryPreferences) set(key string, value interface{}) { +func (p *InMemoryPreferences) set(key string, value any) { p.lock.Lock() if reflect.TypeOf(value).Kind() == reflect.Slice { diff --git a/internal/preferences_test.go b/internal/preferences_test.go index 89e0b4c355..968c2b8453 100644 --- a/internal/preferences_test.go +++ b/internal/preferences_test.go @@ -16,7 +16,7 @@ func TestPrefs_SetBool(t *testing.T) { func TestPrefs_Bool(t *testing.T) { p := NewInMemoryPreferences() - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["testBool"] = true }) @@ -62,7 +62,7 @@ func TestPrefs_SetFloat(t *testing.T) { func TestPrefs_Float(t *testing.T) { p := NewInMemoryPreferences() - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["testFloat"] = 1.2 }) @@ -73,7 +73,7 @@ func TestPrefs_FloatWithFallback(t *testing.T) { p := NewInMemoryPreferences() assert.Equal(t, 1.0, p.FloatWithFallback("testFloat", 1.0)) - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["testFloat"] = 1.2 }) assert.Equal(t, 1.2, p.FloatWithFallback("testFloat", 1.0)) @@ -99,7 +99,7 @@ func TestPrefs_SetInt(t *testing.T) { func TestPrefs_Int(t *testing.T) { p := NewInMemoryPreferences() - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["testInt"] = 5 }) assert.Equal(t, 5, p.Int("testInt")) @@ -109,7 +109,7 @@ func TestPrefs_IntWithFallback(t *testing.T) { p := NewInMemoryPreferences() assert.Equal(t, 2, p.IntWithFallback("testInt", 2)) - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["testInt"] = 5 }) assert.Equal(t, 5, p.IntWithFallback("testInt", 2)) @@ -136,7 +136,7 @@ func TestPrefs_SetString(t *testing.T) { func TestPrefs_String(t *testing.T) { p := NewInMemoryPreferences() - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["test"] = "value" }) @@ -147,7 +147,7 @@ func TestPrefs_StringWithFallback(t *testing.T) { p := NewInMemoryPreferences() assert.Equal(t, "default", p.StringWithFallback("test", "default")) - p.WriteValues(func(val map[string]interface{}) { + p.WriteValues(func(val map[string]any) { val["test"] = "value" }) assert.Equal(t, "value", p.StringWithFallback("test", "default")) diff --git a/internal/test/util.go b/internal/test/util.go index 0829fbddf8..2f0631356d 100644 --- a/internal/test/util.go +++ b/internal/test/util.go @@ -19,7 +19,7 @@ import ( // The test `t` fails if the given image is not equal to the loaded master image. // In this case the given image is written into a file in `testdata/failed/` (relative to the test). // This path is also reported, thus the file can be used as new master. -func AssertImageMatches(t *testing.T, masterFilename string, img image.Image, msgAndArgs ...interface{}) bool { +func AssertImageMatches(t *testing.T, masterFilename string, img image.Image, msgAndArgs ...any) bool { wd, err := os.Getwd() require.NoError(t, err) masterPath := filepath.Join(wd, "testdata", masterFilename) diff --git a/shortcut_test.go b/shortcut_test.go index cb29428b87..4a6c03e4f2 100644 --- a/shortcut_test.go +++ b/shortcut_test.go @@ -8,7 +8,7 @@ import ( ) func syncMapLen(m *sync.Map) (n int) { - m.Range(func(_, _ interface{}) bool { + m.Range(func(_, _ any) bool { n++ return true }) diff --git a/test/test.go b/test/test.go index c675ad08b1..53c568d9d9 100644 --- a/test/test.go +++ b/test/test.go @@ -37,7 +37,7 @@ func AssertCanvasTappableAt(t *testing.T, c fyne.Canvas, pos fyne.Position) bool // This path is also reported, thus the file can be used as new master. // // Since 2.3 -func AssertObjectRendersToImage(t *testing.T, masterFilename string, o fyne.CanvasObject, msgAndArgs ...interface{}) bool { +func AssertObjectRendersToImage(t *testing.T, masterFilename string, o fyne.CanvasObject, msgAndArgs ...any) bool { c := NewCanvasWithPainter(software.NewPainter()) c.SetPadded(false) size := o.MinSize().Max(o.Size()) @@ -59,7 +59,7 @@ func AssertObjectRendersToImage(t *testing.T, masterFilename string, o fyne.Canv // The only exception to this are text elements which do not contain line breaks unless the text includes them. // // Since 2.3 -func AssertObjectRendersToMarkup(t *testing.T, masterFilename string, o fyne.CanvasObject, msgAndArgs ...interface{}) bool { +func AssertObjectRendersToMarkup(t *testing.T, masterFilename string, o fyne.CanvasObject, msgAndArgs ...any) bool { c := NewCanvas() c.SetPadded(false) size := o.MinSize().Max(o.Size()) @@ -74,7 +74,7 @@ func AssertObjectRendersToMarkup(t *testing.T, masterFilename string, o fyne.Can // The test `t` fails if the given image is not equal to the loaded master image. // In this case the given image is written into a file in `testdata/failed/` (relative to the test). // This path is also reported, thus the file can be used as new master. -func AssertImageMatches(t *testing.T, masterFilename string, img image.Image, msgAndArgs ...interface{}) bool { +func AssertImageMatches(t *testing.T, masterFilename string, img image.Image, msgAndArgs ...any) bool { return test.AssertImageMatches(t, masterFilename, img, msgAndArgs...) } @@ -85,7 +85,7 @@ func AssertImageMatches(t *testing.T, masterFilename string, img image.Image, ms // This path is also reported, thus the file can be used as new master. // // Since 2.3 -func AssertRendersToImage(t *testing.T, masterFilename string, c fyne.Canvas, msgAndArgs ...interface{}) bool { +func AssertRendersToImage(t *testing.T, masterFilename string, c fyne.Canvas, msgAndArgs ...any) bool { return test.AssertImageMatches(t, masterFilename, c.Capture(), msgAndArgs...) } @@ -101,7 +101,7 @@ func AssertRendersToImage(t *testing.T, masterFilename string, c fyne.Canvas, ms // The only exception to this are text elements which do not contain line breaks unless the text includes them. // // Since: 2.0 -func AssertRendersToMarkup(t *testing.T, masterFilename string, c fyne.Canvas, msgAndArgs ...interface{}) bool { +func AssertRendersToMarkup(t *testing.T, masterFilename string, c fyne.Canvas, msgAndArgs ...any) bool { wd, err := os.Getwd() require.NoError(t, err) @@ -323,7 +323,7 @@ func findTappable(c fyne.Canvas, pos fyne.Position) (o fyne.CanvasObject, p fyne return } -func prepareTap(obj interface{}, pos fyne.Position) (*fyne.PointEvent, fyne.Canvas) { +func prepareTap(obj any, pos fyne.Position) (*fyne.PointEvent, fyne.Canvas) { d := fyne.CurrentApp().Driver() ev := &fyne.PointEvent{Position: pos} var c fyne.Canvas @@ -339,7 +339,7 @@ func tap(c fyne.Canvas, obj fyne.Tappable, ev *fyne.PointEvent) { obj.Tapped(ev) } -func handleFocusOnTap(c fyne.Canvas, obj interface{}) { +func handleFocusOnTap(c fyne.Canvas, obj any) { if c == nil { return } diff --git a/widget/entry_test.go b/widget/entry_test.go index 0c9eb5d3ab..ca0d9eff26 100644 --- a/widget/entry_test.go +++ b/widget/entry_test.go @@ -2161,7 +2161,7 @@ func clickPrimary(c fyne.Canvas, obj desktop.Mouseable, ev *fyne.PointEvent) { } } -func handleFocusOnTap(c fyne.Canvas, obj interface{}) { +func handleFocusOnTap(c fyne.Canvas, obj any) { if c == nil { return } diff --git a/widget/gridwrap.go b/widget/gridwrap.go index 0221c9bb08..0b600089f0 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -480,7 +480,7 @@ type gridWrapLayout struct { func newGridWrapLayout(list *GridWrap) fyne.Layout { l := &gridWrapLayout{list: list} - l.slicePool.New = func() interface{} { + l.slicePool.New = func() any { s := make([]gridItemAndID, 0) return &s } diff --git a/widget/list.go b/widget/list.go index 23636edbb2..53bca499b1 100644 --- a/widget/list.go +++ b/widget/list.go @@ -545,7 +545,7 @@ type listLayout struct { func newListLayout(list *List) fyne.Layout { l := &listLayout{list: list} - l.slicePool.New = func() interface{} { + l.slicePool.New = func() any { s := make([]listItemAndID, 0) return &s } From fb3cefde24aaa2e98a54fda4d64eaccd18357017 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 6 Jan 2024 23:11:20 +0100 Subject: [PATCH 227/248] Minor driver cleanup --- internal/driver/glfw/driver.go | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/internal/driver/glfw/driver.go b/internal/driver/glfw/driver.go index 7c68ff7486..30ef0e0f15 100644 --- a/internal/driver/glfw/driver.go +++ b/internal/driver/glfw/driver.go @@ -41,12 +41,12 @@ const doubleTapDelay = 300 * time.Millisecond type gLDriver struct { windowLock sync.RWMutex windows []fyne.Window - device *glDevice + device glDevice done chan struct{} drawDone chan struct{} waitForStart chan struct{} - animation *animation.Runner + animation animation.Runner currentKeyModifiers fyne.KeyModifier // desktop driver only @@ -91,11 +91,7 @@ func (d *gLDriver) AbsolutePositionForObject(co fyne.CanvasObject) fyne.Position } func (d *gLDriver) Device() fyne.Device { - if d.device == nil { - d.device = &glDevice{} - } - - return d.device + return &d.device } func (d *gLDriver) Quit() { @@ -127,18 +123,19 @@ func (d *gLDriver) focusPreviousWindow() { wins := d.windows d.windowLock.RUnlock() - var chosen fyne.Window + var chosen *window for _, w := range wins { - if !w.(*window).visible { + win := w.(*window) + if !win.visible { continue } - chosen = w - if w.(*window).master { + chosen = win + if win.master { break } } - if chosen == nil || chosen.(*window).view() == nil { + if chosen == nil || chosen.view() == nil { return } chosen.RequestFocus() @@ -181,6 +178,5 @@ func NewGLDriver() *gLDriver { done: make(chan struct{}), drawDone: make(chan struct{}), waitForStart: make(chan struct{}), - animation: &animation.Runner{}, } } From 81bf6b8f9f2ed654711842931aab2d902e8a939b Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 6 Jan 2024 23:21:39 +0100 Subject: [PATCH 228/248] We don't actually have to keep track of glDevice --- internal/driver/glfw/driver.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/driver/glfw/driver.go b/internal/driver/glfw/driver.go index 30ef0e0f15..26755572cf 100644 --- a/internal/driver/glfw/driver.go +++ b/internal/driver/glfw/driver.go @@ -41,7 +41,6 @@ const doubleTapDelay = 300 * time.Millisecond type gLDriver struct { windowLock sync.RWMutex windows []fyne.Window - device glDevice done chan struct{} drawDone chan struct{} waitForStart chan struct{} @@ -91,7 +90,7 @@ func (d *gLDriver) AbsolutePositionForObject(co fyne.CanvasObject) fyne.Position } func (d *gLDriver) Device() fyne.Device { - return &d.device + return &glDevice{} } func (d *gLDriver) Quit() { From 36947b26325ffb46c2588aa517432ae35bc7800d Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 6 Jan 2024 23:25:21 +0100 Subject: [PATCH 229/248] Apply the same idea to mobile driver --- internal/driver/mobile/driver.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/internal/driver/mobile/driver.go b/internal/driver/mobile/driver.go index 1629894ab6..242a82e29a 100644 --- a/internal/driver/mobile/driver.go +++ b/internal/driver/mobile/driver.go @@ -50,8 +50,8 @@ type mobileDriver struct { glctx gl.Context windows []fyne.Window - device *device - animation *animation.Runner + device device + animation animation.Runner currentSize size.Event theme fyne.ThemeVariant @@ -540,11 +540,7 @@ func (d *mobileDriver) typeUpCanvas(_ *mobileCanvas, _ rune, _ key.Code, _ key.M } func (d *mobileDriver) Device() fyne.Device { - if d.device == nil { - d.device = &device{} - } - - return d.device + return &d.device } func (d *mobileDriver) SetOnConfigurationChanged(f func(*Configuration)) { @@ -559,8 +555,7 @@ func (d *mobileDriver) DoubleTapDelay() time.Duration { // Mobile extension and OpenGL bindings. func NewGoMobileDriver() fyne.Driver { d := &mobileDriver{ - theme: fyne.ThemeVariant(2), // unspecified - animation: &animation.Runner{}, + theme: fyne.ThemeVariant(2), // unspecified } registerRepository(d) From ea6e92e13347e12beacce180d8d6d586602b69c2 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 7 Jan 2024 15:28:03 +0100 Subject: [PATCH 230/248] Make staticcheck checks more agressive Poorly choosen indentifiers, consistent receiver names in struct methods, and exported APIs should have comments beginning with type name. --- dialog/file_test.go | 12 ++++++------ internal/async/chan_go1.21.go | 6 +++--- staticcheck.conf | 2 +- widget/entry.go | 2 +- widget/slider.go | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dialog/file_test.go b/dialog/file_test.go index 16ea1eb656..88f4d39466 100644 --- a/dialog/file_test.go +++ b/dialog/file_test.go @@ -653,21 +653,21 @@ func TestCreateNewFolderInDir(t *testing.T) { defer win.Canvas().Overlays().Remove(inputPopup) assert.NotNil(t, inputPopup) - folderNameInputUi := inputPopup.Content.(*fyne.Container) + folderNameInputUI := inputPopup.Content.(*fyne.Container) - folderNameInputTitle := folderNameInputUi.Objects[4].(*widget.Label) + folderNameInputTitle := folderNameInputUI.Objects[4].(*widget.Label) assert.Equal(t, "New Folder", folderNameInputTitle.Text) - folderNameInputLabel := folderNameInputUi.Objects[2].(*widget.Form).Items[0].Text + folderNameInputLabel := folderNameInputUI.Objects[2].(*widget.Form).Items[0].Text assert.Equal(t, "Name", folderNameInputLabel) - folderNameInputEntry := folderNameInputUi.Objects[2].(*widget.Form).Items[0].Widget.(*widget.Entry) + folderNameInputEntry := folderNameInputUI.Objects[2].(*widget.Form).Items[0].Widget.(*widget.Entry) assert.Equal(t, "", folderNameInputEntry.Text) - folderNameInputCancel := folderNameInputUi.Objects[3].(*fyne.Container).Objects[0].(*widget.Button) + folderNameInputCancel := folderNameInputUI.Objects[3].(*fyne.Container).Objects[0].(*widget.Button) assert.Equal(t, "Cancel", folderNameInputCancel.Text) assert.Equal(t, theme.CancelIcon(), folderNameInputCancel.Icon) - folderNameInputCreate := folderNameInputUi.Objects[3].(*fyne.Container).Objects[1].(*widget.Button) + folderNameInputCreate := folderNameInputUI.Objects[3].(*fyne.Container).Objects[1].(*widget.Button) assert.Equal(t, theme.ConfirmIcon(), folderNameInputCreate.Icon) } diff --git a/internal/async/chan_go1.21.go b/internal/async/chan_go1.21.go index 7b0407c94e..5e912b124d 100644 --- a/internal/async/chan_go1.21.go +++ b/internal/async/chan_go1.21.go @@ -8,7 +8,7 @@ import "fyne.io/fyne/v2" // Func objects. A channel must be closed via Close method type UnboundedFuncChan = UnboundedChan[func()] -// NewUnboundedInterfaceChan returns a unbounded channel, of func(), with unlimited capacity. +// NewUnboundedFuncChan returns a unbounded channel, of func(), with unlimited capacity. func NewUnboundedFuncChan() *UnboundedFuncChan { return NewUnboundedChan[func()]() } @@ -31,7 +31,7 @@ func NewUnboundedCanvasObjectChan() *UnboundedChan[fyne.CanvasObject] { return NewUnboundedChan[fyne.CanvasObject]() } -// UnboundedFuncChan is a channel with an unbounded buffer for caching +// UnboundedChan is a channel with an unbounded buffer for caching // Func objects. A channel must be closed via Close method. type UnboundedChan[T any] struct { in, out chan T @@ -39,7 +39,7 @@ type UnboundedChan[T any] struct { q []T } -// NewUnboundedFuncChan returns a unbounded channel with unlimited capacity. +// NewUnboundedChan returns a unbounded channel with unlimited capacity. func NewUnboundedChan[T any]() *UnboundedChan[T] { ch := &UnboundedChan[T]{ // The size of Func, Interface, and CanvasObject are all less than 16 bytes, we use 16 to fit diff --git a/staticcheck.conf b/staticcheck.conf index 2e9a224ab9..7cbfa2195b 100644 --- a/staticcheck.conf +++ b/staticcheck.conf @@ -1 +1 @@ -checks = ["inherit", "-SA1019"] +checks = ["inherit", "-SA1019", "ST1003", "ST1016", "ST1020", "ST1021", "ST1022"] diff --git a/widget/entry.go b/widget/entry.go index 422b331a37..1b22117a50 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -524,7 +524,7 @@ func (e *Entry) SetText(text string) { e.propertyLock.Unlock() } -// Appends the text to the end of the entry +// Append appends the text to the end of the entry. // // Since: 2.4 func (e *Entry) Append(text string) { diff --git a/widget/slider.go b/widget/slider.go index 07c5685123..c6621180ae 100644 --- a/widget/slider.go +++ b/widget/slider.go @@ -94,7 +94,7 @@ func (s *Slider) DragEnd() { } } -// DragEnd is called when a drag event occurs. +// Dragged is called when a drag event occurs. func (s *Slider) Dragged(e *fyne.DragEvent) { if s.disabled { return From 8ec37b300f721d23f8e23e8630cfb9d61be0e317 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 7 Jan 2024 17:23:32 +0100 Subject: [PATCH 231/248] Fix possible crash in atomic function pointers --- internal/app/lifecycle.go | 8 ++++---- widget/bind_helper.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/app/lifecycle.go b/internal/app/lifecycle.go index 169bdcb9f6..dc79bea20f 100644 --- a/internal/app/lifecycle.go +++ b/internal/app/lifecycle.go @@ -51,7 +51,7 @@ func (l *Lifecycle) SetOnStopped(f func()) { // TriggerEnteredForeground will call the focus gained hook, if one is registered. func (l *Lifecycle) TriggerEnteredForeground() { f := l.onForeground.Load() - if f == nil { + if f == nil || *f == nil { return } @@ -61,7 +61,7 @@ func (l *Lifecycle) TriggerEnteredForeground() { // TriggerExitedForeground will call the focus lost hook, if one is registered. func (l *Lifecycle) TriggerExitedForeground() { f := l.onBackground.Load() - if f == nil { + if f == nil || *f == nil { return } @@ -71,7 +71,7 @@ func (l *Lifecycle) TriggerExitedForeground() { // TriggerStarted will call the started hook, if one is registered. func (l *Lifecycle) TriggerStarted() { f := l.onStarted.Load() - if f == nil { + if f == nil || *f == nil { return } @@ -82,7 +82,7 @@ func (l *Lifecycle) TriggerStarted() { // and an internal stopped hook after that. func (l *Lifecycle) TriggerStopped() { f := l.onStopped.Load() - if f != nil { + if f != nil && *f != nil { (*f)() } diff --git a/widget/bind_helper.go b/widget/bind_helper.go index 019424b5da..4d2d4654b4 100644 --- a/widget/bind_helper.go +++ b/widget/bind_helper.go @@ -20,7 +20,7 @@ type basicBinder struct { func (binder *basicBinder) Bind(data binding.DataItem) { listener := binding.NewDataListener(func() { // NB: listener captures `data` but always calls the up-to-date callback f := binder.callback.Load() - if f == nil { + if f == nil || *f == nil { return } From 2968c874a1950013475f30a3adb56bb4df628e76 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 7 Jan 2024 17:32:39 +0100 Subject: [PATCH 232/248] Apply something similar for application lifecycle --- app/app.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/app.go b/app/app.go index 545b94b492..56872403d6 100644 --- a/app/app.go +++ b/app/app.go @@ -24,7 +24,7 @@ type fyneApp struct { uniqueID string cloud fyne.CloudProvider - lifecycle fyne.Lifecycle + lifecycle app.Lifecycle settings *settings storage fyne.Storage prefs fyne.Preferences @@ -97,7 +97,7 @@ func (a *fyneApp) Preferences() fyne.Preferences { } func (a *fyneApp) Lifecycle() fyne.Lifecycle { - return a.lifecycle + return &a.lifecycle } func (a *fyneApp) newDefaultPreferences() *preferences { @@ -131,11 +131,11 @@ func makeStoreDocs(id string, s *store) *internal.Docs { } func newAppWithDriver(d fyne.Driver, id string) fyne.App { - newApp := &fyneApp{uniqueID: id, driver: d, lifecycle: &app.Lifecycle{}} + newApp := &fyneApp{uniqueID: id, driver: d} fyne.SetCurrentApp(newApp) newApp.prefs = newApp.newDefaultPreferences() - newApp.lifecycle.(*app.Lifecycle).SetOnStoppedHookExecuted(func() { + newApp.lifecycle.SetOnStoppedHookExecuted(func() { if prefs, ok := newApp.prefs.(*preferences); ok { prefs.forceImmediateSave() } From 907af949576cb22079e8f0e3936444cf2bfe0ecc Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 7 Jan 2024 17:42:59 +0100 Subject: [PATCH 233/248] Add a test for app.Lifecycle --- internal/app/lifecycle_test.go | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 internal/app/lifecycle_test.go diff --git a/internal/app/lifecycle_test.go b/internal/app/lifecycle_test.go new file mode 100644 index 0000000000..cefb591fcd --- /dev/null +++ b/internal/app/lifecycle_test.go @@ -0,0 +1,51 @@ +package app + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLifecycle(t *testing.T) { + life := &Lifecycle{} + + // Not setting anything should not panic. + assert.NotPanics(t, life.TriggerEnteredForeground) + assert.NotPanics(t, life.TriggerExitedForeground) + assert.NotPanics(t, life.TriggerStarted) + assert.NotPanics(t, life.TriggerStopped) + + var entered, exited, start, stop, hookedStop bool + life.SetOnEnteredForeground(func() { entered = true }) + life.TriggerEnteredForeground() + assert.True(t, entered) + + life.SetOnExitedForeground(func() { exited = true }) + life.TriggerExitedForeground() + assert.True(t, exited) + + life.SetOnStarted(func() { start = true }) + life.TriggerStarted() + assert.True(t, start) + + life.SetOnStopped(func() { stop = true }) + life.TriggerStopped() + assert.True(t, stop) + + stop = false + life.SetOnStoppedHookExecuted(func() { hookedStop = true }) + life.TriggerStopped() + assert.True(t, stop && hookedStop) + + // Setting back to nil should not panic. + life.SetOnEnteredForeground(nil) + life.SetOnExitedForeground(nil) + life.SetOnStarted(nil) + life.SetOnStopped(nil) + life.SetOnStoppedHookExecuted(nil) + + assert.NotPanics(t, life.TriggerEnteredForeground) + assert.NotPanics(t, life.TriggerExitedForeground) + assert.NotPanics(t, life.TriggerStarted) + assert.NotPanics(t, life.TriggerStopped) +} From 33b88efe41c400f82a17e736f790fcab98591186 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 7 Jan 2024 09:13:39 -0800 Subject: [PATCH 234/248] reorder functions in check.go --- widget/check.go | 236 ++++++++++++++++++++++++------------------------ 1 file changed, 118 insertions(+), 118 deletions(-) diff --git a/widget/check.go b/widget/check.go index 19d7dbced4..7aff91ba4a 100644 --- a/widget/check.go +++ b/widget/check.go @@ -12,103 +12,6 @@ import ( "fyne.io/fyne/v2/theme" ) -type checkRenderer struct { - widget.BaseRenderer - bg, icon *canvas.Image - label *canvas.Text - focusIndicator *canvas.Circle - check *Check -} - -// MinSize calculates the minimum size of a check. -// This is based on the contained text, the check icon and a standard amount of padding added. -func (c *checkRenderer) MinSize() fyne.Size { - pad4 := theme.InnerPadding() * 2 - min := c.label.MinSize().Add(fyne.NewSize(theme.IconInlineSize()+pad4, pad4)) - if c.check.Text != "" { - min.Add(fyne.NewSize(theme.Padding(), 0)) - } - - return min -} - -// Layout the components of the check widget -func (c *checkRenderer) Layout(size fyne.Size) { - focusIndicatorSize := fyne.NewSquareSize(theme.IconInlineSize() + theme.InnerPadding()) - c.focusIndicator.Resize(focusIndicatorSize) - c.focusIndicator.Move(fyne.NewPos(theme.InputBorderSize(), (size.Height-focusIndicatorSize.Height)/2)) - - xOff := focusIndicatorSize.Width + theme.InputBorderSize()*2 - labelSize := size.SubtractWidthHeight(xOff, 0) - c.label.Resize(labelSize) - c.label.Move(fyne.NewPos(xOff, 0)) - - iconPos := fyne.NewPos(theme.InnerPadding()/2+theme.InputBorderSize(), (size.Height-theme.IconInlineSize())/2) - iconSize := fyne.NewSquareSize(theme.IconInlineSize()) - c.bg.Move(iconPos) - c.bg.Resize(iconSize) - c.icon.Resize(iconSize) - c.icon.Move(iconPos) -} - -// applyTheme updates this Check to the current theme -func (c *checkRenderer) applyTheme() { - c.label.Color = theme.ForegroundColor() - c.label.TextSize = theme.TextSize() - if c.check.disabled { - c.label.Color = theme.DisabledColor() - } -} - -func (c *checkRenderer) Refresh() { - c.check.propertyLock.RLock() - c.applyTheme() - c.updateLabel() - c.updateResource() - c.updateFocusIndicator() - c.check.propertyLock.RUnlock() - canvas.Refresh(c.check.super()) -} - -func (c *checkRenderer) updateLabel() { - c.label.Text = c.check.Text -} - -func (c *checkRenderer) updateResource() { - res := theme.NewThemedResource(theme.CheckButtonIcon()) - res.ColorName = theme.ColorNameInputBorder - // TODO move to `theme.CheckButtonFillIcon()` when we add it in 2.4 - bgRes := theme.NewThemedResource(fyne.CurrentApp().Settings().Theme().Icon("iconNameCheckButtonFill")) - bgRes.ColorName = theme.ColorNameInputBackground - - if c.check.Checked { - res = theme.NewThemedResource(theme.CheckButtonCheckedIcon()) - res.ColorName = theme.ColorNamePrimary - bgRes.ColorName = theme.ColorNameBackground - } - if c.check.disabled { - if c.check.Checked { - res = theme.NewThemedResource(theme.CheckButtonCheckedIcon()) - } - res.ColorName = theme.ColorNameDisabled - bgRes.ColorName = theme.ColorNameBackground - } - c.icon.Resource = res - c.bg.Resource = bgRes -} - -func (c *checkRenderer) updateFocusIndicator() { - if c.check.disabled { - c.focusIndicator.FillColor = color.Transparent - } else if c.check.focused { - c.focusIndicator.FillColor = theme.FocusColor() - } else if c.check.hovered { - c.focusIndicator.FillColor = theme.HoverColor() - } else { - c.focusIndicator.FillColor = color.Transparent - } -} - // Check widget has a text label and a checked (or unchecked) icon and triggers an event func when toggled type Check struct { DisableableWidget @@ -123,6 +26,27 @@ type Check struct { binder basicBinder } +// NewCheck creates a new check widget with the set label and change handler +func NewCheck(label string, changed func(bool)) *Check { + c := &Check{ + Text: label, + OnChanged: changed, + } + + c.ExtendBaseWidget(c) + return c +} + +// NewCheckWithData returns a check widget connected with the specified data source. +// +// Since: 2.0 +func NewCheckWithData(label string, data binding.Bool) *Check { + check := NewCheck(label, nil) + check.Bind(data) + + return check +} + // Bind connects the specified data source to this Check. // The current value will be displayed and any changes in the data will cause the widget to update. // User interactions with this Check will set the value into the data source. @@ -233,27 +157,6 @@ func (c *Check) CreateRenderer() fyne.WidgetRenderer { return r } -// NewCheck creates a new check widget with the set label and change handler -func NewCheck(label string, changed func(bool)) *Check { - c := &Check{ - Text: label, - OnChanged: changed, - } - - c.ExtendBaseWidget(c) - return c -} - -// NewCheckWithData returns a check widget connected with the specified data source. -// -// Since: 2.0 -func NewCheckWithData(label string, data binding.Bool) *Check { - check := NewCheck(label, nil) - check.Bind(data) - - return check -} - // FocusGained is called when the Check has been given focus. func (c *Check) FocusGained() { if c.Disabled() { @@ -336,3 +239,100 @@ func (c *Check) writeData(data binding.DataItem) { } } } + +type checkRenderer struct { + widget.BaseRenderer + bg, icon *canvas.Image + label *canvas.Text + focusIndicator *canvas.Circle + check *Check +} + +// MinSize calculates the minimum size of a check. +// This is based on the contained text, the check icon and a standard amount of padding added. +func (c *checkRenderer) MinSize() fyne.Size { + pad4 := theme.InnerPadding() * 2 + min := c.label.MinSize().Add(fyne.NewSize(theme.IconInlineSize()+pad4, pad4)) + if c.check.Text != "" { + min.Add(fyne.NewSize(theme.Padding(), 0)) + } + + return min +} + +// Layout the components of the check widget +func (c *checkRenderer) Layout(size fyne.Size) { + focusIndicatorSize := fyne.NewSquareSize(theme.IconInlineSize() + theme.InnerPadding()) + c.focusIndicator.Resize(focusIndicatorSize) + c.focusIndicator.Move(fyne.NewPos(theme.InputBorderSize(), (size.Height-focusIndicatorSize.Height)/2)) + + xOff := focusIndicatorSize.Width + theme.InputBorderSize()*2 + labelSize := size.SubtractWidthHeight(xOff, 0) + c.label.Resize(labelSize) + c.label.Move(fyne.NewPos(xOff, 0)) + + iconPos := fyne.NewPos(theme.InnerPadding()/2+theme.InputBorderSize(), (size.Height-theme.IconInlineSize())/2) + iconSize := fyne.NewSquareSize(theme.IconInlineSize()) + c.bg.Move(iconPos) + c.bg.Resize(iconSize) + c.icon.Resize(iconSize) + c.icon.Move(iconPos) +} + +// applyTheme updates this Check to the current theme +func (c *checkRenderer) applyTheme() { + c.label.Color = theme.ForegroundColor() + c.label.TextSize = theme.TextSize() + if c.check.disabled { + c.label.Color = theme.DisabledColor() + } +} + +func (c *checkRenderer) Refresh() { + c.check.propertyLock.RLock() + c.applyTheme() + c.updateLabel() + c.updateResource() + c.updateFocusIndicator() + c.check.propertyLock.RUnlock() + canvas.Refresh(c.check.super()) +} + +func (c *checkRenderer) updateLabel() { + c.label.Text = c.check.Text +} + +func (c *checkRenderer) updateResource() { + res := theme.NewThemedResource(theme.CheckButtonIcon()) + res.ColorName = theme.ColorNameInputBorder + // TODO move to `theme.CheckButtonFillIcon()` when we add it in 2.4 + bgRes := theme.NewThemedResource(fyne.CurrentApp().Settings().Theme().Icon("iconNameCheckButtonFill")) + bgRes.ColorName = theme.ColorNameInputBackground + + if c.check.Checked { + res = theme.NewThemedResource(theme.CheckButtonCheckedIcon()) + res.ColorName = theme.ColorNamePrimary + bgRes.ColorName = theme.ColorNameBackground + } + if c.check.disabled { + if c.check.Checked { + res = theme.NewThemedResource(theme.CheckButtonCheckedIcon()) + } + res.ColorName = theme.ColorNameDisabled + bgRes.ColorName = theme.ColorNameBackground + } + c.icon.Resource = res + c.bg.Resource = bgRes +} + +func (c *checkRenderer) updateFocusIndicator() { + if c.check.disabled { + c.focusIndicator.FillColor = color.Transparent + } else if c.check.focused { + c.focusIndicator.FillColor = theme.FocusColor() + } else if c.check.hovered { + c.focusIndicator.FillColor = theme.HoverColor() + } else { + c.focusIndicator.FillColor = color.Transparent + } +} From d84159b9b2b44c4c5bbafab6a1f1cf4100e1c6cb Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 7 Jan 2024 09:16:16 -0800 Subject: [PATCH 235/248] Check: only respond to hover/tap inside active area of the widget --- widget/check.go | 53 ++++++++++++++++++++++++++--------- widget/check_internal_test.go | 32 +++++++++++++++++++++ 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/widget/check.go b/widget/check.go index 7aff91ba4a..5c4c7bf1c9 100644 --- a/widget/check.go +++ b/widget/check.go @@ -24,6 +24,8 @@ type Check struct { hovered bool binder basicBinder + + minSize fyne.Size // cached for hover/tap position calculations } // NewCheck creates a new check widget with the set label and change handler @@ -91,26 +93,50 @@ func (c *Check) Hide() { } // MouseIn is called when a desktop pointer enters the widget -func (c *Check) MouseIn(*desktop.MouseEvent) { - if c.Disabled() { - return - } - c.hovered = true - c.Refresh() +func (c *Check) MouseIn(me *desktop.MouseEvent) { + c.MouseMoved(me) } // MouseOut is called when a desktop pointer exits the widget func (c *Check) MouseOut() { - c.hovered = false - c.Refresh() + if c.hovered { + c.hovered = false + c.Refresh() + } } // MouseMoved is called when a desktop pointer hovers over the widget -func (c *Check) MouseMoved(*desktop.MouseEvent) { +func (c *Check) MouseMoved(me *desktop.MouseEvent) { + if c.Disabled() { + return + } + + oldHovered := c.hovered + if c.minSize.Width == 0 && c.minSize.Height == 0 { + c.hovered = true + } else if me.Position.X <= c.minSize.Width && me.Position.Y <= c.minSize.Height { + c.hovered = true + } else { + // mouse outside the active area of the widget + c.hovered = false + } + + if oldHovered != c.hovered { + c.Refresh() + } } // Tapped is called when a pointer tapped event is captured and triggers any change handler -func (c *Check) Tapped(*fyne.PointEvent) { +func (c *Check) Tapped(pe *fyne.PointEvent) { + if c.Disabled() { + return + } + if c.minSize.Height > 0 && c.minSize.Width > 0 && + (pe.Position.X > c.minSize.Width || pe.Position.Y > c.minSize.Height) { + // tapped outside the active area of the widget + return + } + if !c.focused && !fyne.CurrentDevice().IsMobile() { impl := c.super() @@ -118,15 +144,14 @@ func (c *Check) Tapped(*fyne.PointEvent) { c.Focus(impl.(fyne.Focusable)) } } - if !c.Disabled() { - c.SetChecked(!c.Checked) - } + c.SetChecked(!c.Checked) } // MinSize returns the size that this widget should not shrink below func (c *Check) MinSize() fyne.Size { c.ExtendBaseWidget(c) - return c.BaseWidget.MinSize() + c.minSize = c.BaseWidget.MinSize() + return c.minSize } // CreateRenderer is a private method to Fyne which links this widget to its renderer diff --git a/widget/check_internal_test.go b/widget/check_internal_test.go index 6047db9ac1..7e07dccd97 100644 --- a/widget/check_internal_test.go +++ b/widget/check_internal_test.go @@ -210,6 +210,38 @@ func TestCheck_Hovered(t *testing.T) { assert.Equal(t, color.Transparent, render.focusIndicator.FillColor) } +func TestCheck_HoveredOutsideActiveArea(t *testing.T) { + check := NewCheck("Test", func(on bool) {}) + w := test.NewWindow(check) + defer w.Close() + render := test.WidgetRenderer(check).(*checkRenderer) + + check.SetChecked(true) + assert.False(t, check.hovered) + assert.Equal(t, color.Transparent, render.focusIndicator.FillColor) + + ms := check.MinSize() + check.MouseIn(&desktop.MouseEvent{PointEvent: fyne.PointEvent{ + Position: fyne.NewPos(ms.Width+2, 1), + }}) + assert.False(t, check.hovered) + assert.Equal(t, color.Transparent, render.focusIndicator.FillColor) +} + +func TestCheck_TappedOutsideActiveArea(t *testing.T) { + check := NewCheck("Test", func(on bool) {}) + w := test.NewWindow(check) + defer w.Close() + + check.SetChecked(true) + + ms := check.MinSize() + check.Tapped(&fyne.PointEvent{ + Position: fyne.NewPos(ms.Width+2, 1), + }) + assert.True(t, check.Checked) +} + func TestCheck_TypedRune(t *testing.T) { check := NewCheck("Test", func(on bool) {}) w := test.NewWindow(check) From 4a3cbbf6a42954330fff4e1bcd7d40dbab93b927 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 7 Jan 2024 20:36:42 +0000 Subject: [PATCH 236/248] Fix the theme of hidden tabs if it changes Fixes #4344 --- container/apptabs.go | 1 + container/doctabs.go | 2 ++ container/tabs.go | 6 ++++++ container/tabs_test.go | 27 ++++++++++++++++++++++++++- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/container/apptabs.go b/container/apptabs.go index b02300e59a..f7b7c8bf25 100644 --- a/container/apptabs.go +++ b/container/apptabs.go @@ -57,6 +57,7 @@ func (t *AppTabs) CreateRenderer() fyne.WidgetRenderer { appTabs: t, } r.action = r.buildOverflowTabsButton() + r.tabs = t // Initially setup the tab bar to only show one tab, all others will be in overflow. // When the widget is laid out, and we know the size, the tab bar will be updated to show as many as can fit. diff --git a/container/doctabs.go b/container/doctabs.go index b1bcf468e3..55d55af00d 100644 --- a/container/doctabs.go +++ b/container/doctabs.go @@ -67,6 +67,8 @@ func (t *DocTabs) CreateRenderer() fyne.WidgetRenderer { } r.action = r.buildAllTabsButton() r.create = r.buildCreateTabsButton() + r.tabs = t + r.box = NewHBox(r.create, r.action) r.scroller.OnScrolled = func(offset fyne.Position) { r.updateIndicator(false) diff --git a/container/tabs.go b/container/tabs.go index 4d60d82c56..cc20f99fc4 100644 --- a/container/tabs.go +++ b/container/tabs.go @@ -293,6 +293,8 @@ type baseTabsRenderer struct { action *widget.Button bar *fyne.Container divider, indicator *canvas.Rectangle + + tabs baseTabs } func (r *baseTabsRenderer) Destroy() { @@ -305,6 +307,10 @@ func (r *baseTabsRenderer) applyTheme(t baseTabs) { r.divider.FillColor = theme.ShadowColor() r.indicator.FillColor = theme.PrimaryColor() r.indicator.CornerRadius = theme.SelectionRadiusSize() + + for _, tab := range r.tabs.items() { + tab.Content.Refresh() + } } func (r *baseTabsRenderer) layout(t baseTabs, size fyne.Size) { diff --git a/container/tabs_test.go b/container/tabs_test.go index 7149cb8f00..bf486949b9 100644 --- a/container/tabs_test.go +++ b/container/tabs_test.go @@ -3,10 +3,13 @@ package container import ( "testing" + "github.com/stretchr/testify/assert" + "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/internal/cache" + "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" - "github.com/stretchr/testify/assert" + "fyne.io/fyne/v2/widget" ) func TestTabButton_Icon_Change(t *testing.T) { @@ -19,3 +22,25 @@ func TestTabButton_Icon_Change(t *testing.T) { b.Refresh() assert.NotEqual(t, oldResource, icon.Resource) } + +func TestTab_ThemeChange(t *testing.T) { + a := test.NewApp() + defer test.NewApp() + a.Settings().SetTheme(theme.LightTheme()) + + tabs := NewAppTabs( + NewTabItem("a", widget.NewLabel("a")), + NewTabItem("b", widget.NewLabel("b"))) + w := test.NewWindow(tabs) + + initial := w.Canvas().Capture() + + a.Settings().SetTheme(theme.DarkTheme()) + tabs.SelectIndex(1) + second := w.Canvas().Capture() + assert.NotEqual(t, initial, second) + + a.Settings().SetTheme(theme.LightTheme()) + tabs.SelectIndex(0) + assert.Equal(t, initial, w.Canvas().Capture()) +} From 8c5f1737b19160e1b42ce9d9f886a66b5574bca3 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 7 Jan 2024 20:41:46 +0000 Subject: [PATCH 237/248] Fix possible issue with mobile test being too small --- container/tabs_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/container/tabs_test.go b/container/tabs_test.go index bf486949b9..be00624bdd 100644 --- a/container/tabs_test.go +++ b/container/tabs_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" + "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/test" @@ -32,6 +33,7 @@ func TestTab_ThemeChange(t *testing.T) { NewTabItem("a", widget.NewLabel("a")), NewTabItem("b", widget.NewLabel("b"))) w := test.NewWindow(tabs) + w.Resize(fyne.NewSquareSize(100)) initial := w.Canvas().Capture() From f0f2623df4b0c236b19843d5bd6d7c286308939f Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 7 Jan 2024 21:20:20 +0000 Subject: [PATCH 238/248] Use the test theme more might stabilise test breaks --- container/tabs_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/container/tabs_test.go b/container/tabs_test.go index be00624bdd..e6b11d2f1c 100644 --- a/container/tabs_test.go +++ b/container/tabs_test.go @@ -27,13 +27,13 @@ func TestTabButton_Icon_Change(t *testing.T) { func TestTab_ThemeChange(t *testing.T) { a := test.NewApp() defer test.NewApp() - a.Settings().SetTheme(theme.LightTheme()) + a.Settings().SetTheme(test.Theme()) tabs := NewAppTabs( NewTabItem("a", widget.NewLabel("a")), NewTabItem("b", widget.NewLabel("b"))) w := test.NewWindow(tabs) - w.Resize(fyne.NewSquareSize(100)) + w.Resize(fyne.NewSquareSize(150)) initial := w.Canvas().Capture() @@ -42,7 +42,7 @@ func TestTab_ThemeChange(t *testing.T) { second := w.Canvas().Capture() assert.NotEqual(t, initial, second) - a.Settings().SetTheme(theme.LightTheme()) + a.Settings().SetTheme(test.Theme()) tabs.SelectIndex(0) assert.Equal(t, initial, w.Canvas().Capture()) } From 61ebf5b96eea8238997dd9f7f12d9cf58be45f0e Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Sun, 7 Jan 2024 21:28:30 +0000 Subject: [PATCH 239/248] Move the forced theme variant to internal test and use --- cmd/fyne_demo/main.go | 5 ++-- cmd/fyne_demo/theme.go | 17 ------------ container/tabs_test.go | 3 ++- internal/test/theme.go | 26 +++++++++++++++++++ .../fyne_demo => internal/test}/theme_test.go | 2 +- 5 files changed, 32 insertions(+), 21 deletions(-) delete mode 100644 cmd/fyne_demo/theme.go create mode 100644 internal/test/theme.go rename {cmd/fyne_demo => internal/test}/theme_test.go (98%) diff --git a/cmd/fyne_demo/main.go b/cmd/fyne_demo/main.go index e8fa759647..b7e5f56c9b 100644 --- a/cmd/fyne_demo/main.go +++ b/cmd/fyne_demo/main.go @@ -13,6 +13,7 @@ import ( "fyne.io/fyne/v2/cmd/fyne_settings/settings" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -238,10 +239,10 @@ func makeNav(setTutorial func(tutorial tutorials.Tutorial), loadPrevious bool) f themes := container.NewGridWithColumns(2, widget.NewButton("Dark", func() { - a.Settings().SetTheme(&forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantDark}) + a.Settings().SetTheme(test.DarkTheme()) }), widget.NewButton("Light", func() { - a.Settings().SetTheme(&forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantLight}) + a.Settings().SetTheme(test.LightTheme()) }), ) diff --git a/cmd/fyne_demo/theme.go b/cmd/fyne_demo/theme.go deleted file mode 100644 index 1e3241ca5e..0000000000 --- a/cmd/fyne_demo/theme.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "image/color" - - "fyne.io/fyne/v2" -) - -type forcedVariant struct { - fyne.Theme - - variant fyne.ThemeVariant -} - -func (f *forcedVariant) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color { - return f.Theme.Color(name, f.variant) -} diff --git a/container/tabs_test.go b/container/tabs_test.go index e6b11d2f1c..3cba18aa40 100644 --- a/container/tabs_test.go +++ b/container/tabs_test.go @@ -8,6 +8,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/internal/cache" + intTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -37,7 +38,7 @@ func TestTab_ThemeChange(t *testing.T) { initial := w.Canvas().Capture() - a.Settings().SetTheme(theme.DarkTheme()) + a.Settings().SetTheme(intTest.DarkTheme()) tabs.SelectIndex(1) second := w.Canvas().Capture() assert.NotEqual(t, initial, second) diff --git a/internal/test/theme.go b/internal/test/theme.go new file mode 100644 index 0000000000..627b1d1875 --- /dev/null +++ b/internal/test/theme.go @@ -0,0 +1,26 @@ +package test + +import ( + "image/color" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/theme" +) + +func DarkTheme() fyne.Theme { + return &forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantDark} +} + +func LightTheme() fyne.Theme { + return &forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantLight} +} + +type forcedVariant struct { + fyne.Theme + + variant fyne.ThemeVariant +} + +func (f *forcedVariant) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color { + return f.Theme.Color(name, f.variant) +} diff --git a/cmd/fyne_demo/theme_test.go b/internal/test/theme_test.go similarity index 98% rename from cmd/fyne_demo/theme_test.go rename to internal/test/theme_test.go index 24dd999cf9..c8320b607b 100644 --- a/cmd/fyne_demo/theme_test.go +++ b/internal/test/theme_test.go @@ -1,4 +1,4 @@ -package main +package test import ( "testing" From c3815fb0d6fb2d455a69ccf14d1b085311fd76d0 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 8 Jan 2024 10:20:08 +0000 Subject: [PATCH 240/248] Make a copy of theme variant back into demo --- cmd/fyne_demo/main.go | 5 ++--- cmd/fyne_demo/theme.go | 17 +++++++++++++++++ {internal/test => cmd/fyne_demo}/theme_test.go | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 cmd/fyne_demo/theme.go rename {internal/test => cmd/fyne_demo}/theme_test.go (98%) diff --git a/cmd/fyne_demo/main.go b/cmd/fyne_demo/main.go index b7e5f56c9b..e8fa759647 100644 --- a/cmd/fyne_demo/main.go +++ b/cmd/fyne_demo/main.go @@ -13,7 +13,6 @@ import ( "fyne.io/fyne/v2/cmd/fyne_settings/settings" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/driver/desktop" - "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -239,10 +238,10 @@ func makeNav(setTutorial func(tutorial tutorials.Tutorial), loadPrevious bool) f themes := container.NewGridWithColumns(2, widget.NewButton("Dark", func() { - a.Settings().SetTheme(test.DarkTheme()) + a.Settings().SetTheme(&forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantDark}) }), widget.NewButton("Light", func() { - a.Settings().SetTheme(test.LightTheme()) + a.Settings().SetTheme(&forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantLight}) }), ) diff --git a/cmd/fyne_demo/theme.go b/cmd/fyne_demo/theme.go new file mode 100644 index 0000000000..1e3241ca5e --- /dev/null +++ b/cmd/fyne_demo/theme.go @@ -0,0 +1,17 @@ +package main + +import ( + "image/color" + + "fyne.io/fyne/v2" +) + +type forcedVariant struct { + fyne.Theme + + variant fyne.ThemeVariant +} + +func (f *forcedVariant) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color { + return f.Theme.Color(name, f.variant) +} diff --git a/internal/test/theme_test.go b/cmd/fyne_demo/theme_test.go similarity index 98% rename from internal/test/theme_test.go rename to cmd/fyne_demo/theme_test.go index c8320b607b..24dd999cf9 100644 --- a/internal/test/theme_test.go +++ b/cmd/fyne_demo/theme_test.go @@ -1,4 +1,4 @@ -package test +package main import ( "testing" From ef3ce038dfbf260473ceab8138b936b354b9cb74 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 8 Jan 2024 10:23:19 +0000 Subject: [PATCH 241/248] Ensure an app is available in tester --- cmd/fyne_demo/theme_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/fyne_demo/theme_test.go b/cmd/fyne_demo/theme_test.go index 24dd999cf9..c77a70139a 100644 --- a/cmd/fyne_demo/theme_test.go +++ b/cmd/fyne_demo/theme_test.go @@ -6,10 +6,12 @@ import ( "github.com/stretchr/testify/assert" "fyne.io/fyne/v2" + "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" ) func TestForceVariantTheme_Color(t *testing.T) { + test.NewApp() dark := &forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantDark} light := &forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantLight} unspecified := fyne.ThemeVariant(99) From ebe5c56c5f9380e4a1aefd5a252a1c328daed23d Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 8 Jan 2024 10:29:54 +0000 Subject: [PATCH 242/248] Remove import loop --- container/tabs_test.go | 2 +- internal/test/theme.go | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/container/tabs_test.go b/container/tabs_test.go index 3cba18aa40..46de24afef 100644 --- a/container/tabs_test.go +++ b/container/tabs_test.go @@ -38,7 +38,7 @@ func TestTab_ThemeChange(t *testing.T) { initial := w.Canvas().Capture() - a.Settings().SetTheme(intTest.DarkTheme()) + a.Settings().SetTheme(intTest.DarkTheme(theme.DefaultTheme())) tabs.SelectIndex(1) second := w.Canvas().Capture() assert.NotEqual(t, initial, second) diff --git a/internal/test/theme.go b/internal/test/theme.go index 627b1d1875..33bd9c54a1 100644 --- a/internal/test/theme.go +++ b/internal/test/theme.go @@ -4,15 +4,14 @@ import ( "image/color" "fyne.io/fyne/v2" - "fyne.io/fyne/v2/theme" ) -func DarkTheme() fyne.Theme { - return &forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantDark} +func DarkTheme(fallback fyne.Theme) fyne.Theme { + return &forcedVariant{Theme: fallback, variant: 0} // avoid import loops } -func LightTheme() fyne.Theme { - return &forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantLight} +func LightTheme(fallback fyne.Theme) fyne.Theme { + return &forcedVariant{Theme: fallback, variant: 1} // avoid import loops } type forcedVariant struct { From aa90f759b660bd7d1a5327d5ae2f03b8a1e0e0bc Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Mon, 8 Jan 2024 10:42:09 +0000 Subject: [PATCH 243/248] Debugging CI theme issues --- container/tabs_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/container/tabs_test.go b/container/tabs_test.go index 46de24afef..6f7de44a4c 100644 --- a/container/tabs_test.go +++ b/container/tabs_test.go @@ -28,7 +28,7 @@ func TestTabButton_Icon_Change(t *testing.T) { func TestTab_ThemeChange(t *testing.T) { a := test.NewApp() defer test.NewApp() - a.Settings().SetTheme(test.Theme()) + firstTheme := a.Settings().Theme() tabs := NewAppTabs( NewTabItem("a", widget.NewLabel("a")), @@ -43,7 +43,7 @@ func TestTab_ThemeChange(t *testing.T) { second := w.Canvas().Capture() assert.NotEqual(t, initial, second) - a.Settings().SetTheme(test.Theme()) + a.Settings().SetTheme(firstTheme) tabs.SelectIndex(0) assert.Equal(t, initial, w.Canvas().Capture()) } From c630423c5d4e76d679f45c363aae6513aa135ea8 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Mon, 8 Jan 2024 08:02:40 -0800 Subject: [PATCH 244/248] simplify MouseMoved --- widget/check.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/widget/check.go b/widget/check.go index 5c4c7bf1c9..ee50f80056 100644 --- a/widget/check.go +++ b/widget/check.go @@ -112,14 +112,11 @@ func (c *Check) MouseMoved(me *desktop.MouseEvent) { } oldHovered := c.hovered - if c.minSize.Width == 0 && c.minSize.Height == 0 { - c.hovered = true - } else if me.Position.X <= c.minSize.Width && me.Position.Y <= c.minSize.Height { - c.hovered = true - } else { - // mouse outside the active area of the widget - c.hovered = false - } + + // only hovered if cached minSize has not been initialized (test code) + // or the pointer is within the "active" area of the widget (its minSize) + c.hovered = c.minSize.IsZero() || + (me.Position.X <= c.minSize.Width && me.Position.Y <= c.minSize.Height) if oldHovered != c.hovered { c.Refresh() @@ -131,7 +128,7 @@ func (c *Check) Tapped(pe *fyne.PointEvent) { if c.Disabled() { return } - if c.minSize.Height > 0 && c.minSize.Width > 0 && + if !c.minSize.IsZero() && (pe.Position.X > c.minSize.Width || pe.Position.Y > c.minSize.Height) { // tapped outside the active area of the widget return From b2f5f121e38b24c8320b55325abcb664ca5eb313 Mon Sep 17 00:00:00 2001 From: Jesse Donat Date: Mon, 8 Jan 2024 10:11:02 -0600 Subject: [PATCH 245/248] Apply fixes for updated typesetting --- widget/richtext.go | 4 ++-- widget/select_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/widget/richtext.go b/widget/richtext.go index 6b14fb9f71..e9fbd921c6 100644 --- a/widget/richtext.go +++ b/widget/richtext.go @@ -1089,9 +1089,9 @@ func truncateLimit(s string, text *canvas.Text, limit int, ellipsis []rune) (int out := shaper.Shape(in) l.Prepare(conf, runes, shaping.NewSliceIterator([]shaping.Output{out})) - finalLine, _, done := l.WrapNextLine(limit) + wrapped, done := l.WrapNextLine(limit) - count := finalLine[0].Runes.Count + count := wrapped.Line[0].Runes.Count full := done && count == len(runes) if !full && len(ellipsis) > 0 { count-- diff --git a/widget/select_test.go b/widget/select_test.go index 57e8621a29..ac97654d09 100644 --- a/widget/select_test.go +++ b/widget/select_test.go @@ -100,7 +100,7 @@ func TestSelect_ClipValue(t *testing.T) { r2 := cache.Renderer(text) assert.Equal(t, 1, len(r2.Objects())) - assert.Equal(t, "som…", r2.Objects()[0].(*canvas.Text).Text) + assert.Equal(t, "some…", r2.Objects()[0].(*canvas.Text).Text) } func TestSelect_Disable(t *testing.T) { From e97aa9a684f07872b9e1fc5f5ad86393e4afe14a Mon Sep 17 00:00:00 2001 From: Jacob Date: Mon, 8 Jan 2024 21:51:52 +0100 Subject: [PATCH 246/248] Fix usage of deprecated theme APIs --- app/settings_test.go | 7 ++++--- cmd/fyne_demo/tutorials/container.go | 3 +-- cmd/fyne_demo/tutorials/theme.go | 2 +- container/apptabs_mobile_test.go | 2 +- container/doctabs_mobile_test.go | 2 +- dialog/form_test.go | 4 +++- driver/software/render_test.go | 20 +++++++++++--------- internal/driver/glfw/canvas_test.go | 3 ++- internal/driver/glfw/window_test.go | 7 ++++--- staticcheck.conf | 2 +- test/markup_renderer.go | 2 +- test/testapp.go | 3 ++- tools/playground/playground.go | 5 +++-- widget/button_test.go | 7 ++++--- widget/entry_validation_test.go | 3 ++- widget/form_test.go | 15 ++++++++------- widget/hyperlink_test.go | 3 ++- widget/label_test.go | 3 ++- widget/slider_test.go | 5 +++-- widget/table_test.go | 7 ++++--- widget/tree_test.go | 3 ++- widget/widget_test.go | 5 +++-- 22 files changed, 65 insertions(+), 48 deletions(-) diff --git a/app/settings_test.go b/app/settings_test.go index 68f954b9a7..65745df0f6 100644 --- a/app/settings_test.go +++ b/app/settings_test.go @@ -6,11 +6,12 @@ import ( "testing" "fyne.io/fyne/v2" - "github.com/stretchr/testify/assert" - "fyne.io/fyne/v2/internal/build" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" + + "github.com/stretchr/testify/assert" ) func TestSettingsBuildType(t *testing.T) { @@ -100,7 +101,7 @@ func TestCustomTheme(t *testing.T) { fyne.Theme } set := &settings{} - ctheme := &customTheme{theme.LightTheme()} + ctheme := &customTheme{internalTest.LightTheme(theme.DefaultTheme())} set.SetTheme(ctheme) set.setupTheme() diff --git a/cmd/fyne_demo/tutorials/container.go b/cmd/fyne_demo/tutorials/container.go index 098a04c58d..6ec57b415f 100644 --- a/cmd/fyne_demo/tutorials/container.go +++ b/cmd/fyne_demo/tutorials/container.go @@ -9,7 +9,6 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/cmd/fyne_demo/data" "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -115,7 +114,7 @@ func makeInnerWindowTab(_ fyne.Window) fyne.CanvasObject { widget.NewButton("Tap Me", func() { label.SetText("Tapped") }))) - win1.Icon = theme.FyneLogo() + win1.Icon = data.FyneLogo win2 := container.NewInnerWindow("Inner2", widget.NewLabel("Win 2")) diff --git a/cmd/fyne_demo/tutorials/theme.go b/cmd/fyne_demo/tutorials/theme.go index 9f87253d54..071979fa3c 100644 --- a/cmd/fyne_demo/tutorials/theme.go +++ b/cmd/fyne_demo/tutorials/theme.go @@ -35,7 +35,7 @@ func (customTheme) Color(c fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color } func (customTheme) Font(style fyne.TextStyle) fyne.Resource { - return theme.DarkTheme().Font(style) + return theme.DefaultTheme().Font(style) } func (customTheme) Icon(n fyne.ThemeIconName) fyne.Resource { diff --git a/container/apptabs_mobile_test.go b/container/apptabs_mobile_test.go index ffae2fff77..5f9ca9c90e 100644 --- a/container/apptabs_mobile_test.go +++ b/container/apptabs_mobile_test.go @@ -160,7 +160,7 @@ func TestAppTabs_DynamicTabs(t *testing.T) { func TestAppTabs_HoverButtons(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) item1 := &container.TabItem{Text: "Test1", Content: widget.NewLabel("Text1")} item2 := &container.TabItem{Text: "Test2", Content: widget.NewLabel("Text2")} diff --git a/container/doctabs_mobile_test.go b/container/doctabs_mobile_test.go index 730e21430d..7f3495643b 100644 --- a/container/doctabs_mobile_test.go +++ b/container/doctabs_mobile_test.go @@ -160,7 +160,7 @@ func TestDocTabs_DynamicTabs(t *testing.T) { func TestDocTabs_HoverButtons(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) item1 := &container.TabItem{Text: "Test1", Content: widget.NewLabel("Text1")} item2 := &container.TabItem{Text: "Test2", Content: widget.NewLabel("Text2")} diff --git a/dialog/form_test.go b/dialog/form_test.go index 70d96c2855..5c7074319f 100644 --- a/dialog/form_test.go +++ b/dialog/form_test.go @@ -5,9 +5,11 @@ import ( "testing" "fyne.io/fyne/v2" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -87,7 +89,7 @@ func TestFormDialog_Hints(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) w := test.NewWindow(nil) w.SetFullScreen(true) diff --git a/driver/software/render_test.go b/driver/software/render_test.go index aa10608990..4a979adfe2 100644 --- a/driver/software/render_test.go +++ b/driver/software/render_test.go @@ -7,32 +7,34 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" + "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) func TestRender(t *testing.T) { obj := widget.NewLabel("Hi") - test.AssertImageMatches(t, "label_dark.png", Render(obj, theme.DarkTheme())) - test.AssertImageMatches(t, "label_light.png", Render(obj, theme.LightTheme())) + test.AssertImageMatches(t, "label_dark.png", Render(obj, internalTest.DarkTheme(theme.DefaultTheme()))) + test.AssertImageMatches(t, "label_light.png", Render(obj, internalTest.LightTheme(theme.DefaultTheme()))) } func TestRender_State(t *testing.T) { obj := widget.NewButtonWithIcon("Cancel", theme.CancelIcon(), func() {}) - test.AssertImageMatches(t, "button.png", Render(obj, theme.DarkTheme())) + test.AssertImageMatches(t, "button.png", Render(obj, internalTest.DarkTheme(theme.DefaultTheme()))) obj.Importance = widget.HighImportance obj.Refresh() - test.AssertImageMatches(t, "button_important.png", Render(obj, theme.DarkTheme())) + test.AssertImageMatches(t, "button_important.png", Render(obj, internalTest.DarkTheme(theme.DefaultTheme()))) } func TestRender_Focus(t *testing.T) { obj := widget.NewEntry() - test.AssertImageMatches(t, "entry.png", Render(obj, theme.DarkTheme())) + test.AssertImageMatches(t, "entry.png", Render(obj, internalTest.DarkTheme(theme.DefaultTheme()))) obj.FocusGained() - test.AssertImageMatches(t, "entry_focus.png", Render(obj, theme.DarkTheme())) + test.AssertImageMatches(t, "entry_focus.png", Render(obj, internalTest.DarkTheme(theme.DefaultTheme()))) } func TestRenderCanvas(t *testing.T) { @@ -46,9 +48,9 @@ func TestRenderCanvas(t *testing.T) { c.SetContent(obj) if fyne.CurrentDevice().IsMobile() { - test.AssertImageMatches(t, "canvas_mobile.png", RenderCanvas(c, theme.LightTheme())) + test.AssertImageMatches(t, "canvas_mobile.png", RenderCanvas(c, internalTest.LightTheme(theme.DefaultTheme()))) } else { - test.AssertImageMatches(t, "canvas.png", RenderCanvas(c, theme.LightTheme())) + test.AssertImageMatches(t, "canvas.png", RenderCanvas(c, internalTest.LightTheme(theme.DefaultTheme()))) } } @@ -61,5 +63,5 @@ func TestRender_ImageSize(t *testing.T) { c := container.NewStack(image, bg) - test.AssertImageMatches(t, "image_size.png", Render(c, theme.LightTheme())) + test.AssertImageMatches(t, "image_size.png", Render(c, internalTest.LightTheme(theme.DefaultTheme()))) } diff --git a/internal/driver/glfw/canvas_test.go b/internal/driver/glfw/canvas_test.go index 3394a45dbc..2bdc66a27d 100644 --- a/internal/driver/glfw/canvas_test.go +++ b/internal/driver/glfw/canvas_test.go @@ -9,6 +9,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -509,7 +510,7 @@ func TestGlCanvas_Scale(t *testing.T) { } func TestGlCanvas_SetContent(t *testing.T) { - fyne.CurrentApp().Settings().SetTheme(theme.DarkTheme()) + fyne.CurrentApp().Settings().SetTheme(internalTest.DarkTheme(theme.DefaultTheme())) var menuHeight float32 if hasNativeMenu() { menuHeight = 0 diff --git a/internal/driver/glfw/window_test.go b/internal/driver/glfw/window_test.go index 5e677ce8cf..00c5e13222 100644 --- a/internal/driver/glfw/window_test.go +++ b/internal/driver/glfw/window_test.go @@ -16,6 +16,7 @@ import ( "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/internal/scale" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" @@ -305,7 +306,7 @@ func TestWindow_HandleHoverable(t *testing.T) { func TestWindow_HandleOutsideHoverableObject(t *testing.T) { w := createWindow("Test").(*window) - test.ApplyTheme(t, theme.DarkTheme()) + test.ApplyTheme(t, internalTest.DarkTheme(theme.DefaultTheme())) l := widget.NewList( func() int { return 2 }, func() fyne.CanvasObject { return widget.NewEntry() }, @@ -1152,7 +1153,7 @@ func TestWindow_TappedSecondary_OnPrimaryOnlyTarget(t *testing.T) { func TestWindow_TappedIgnoresScrollerClip(t *testing.T) { w := createWindow("Test").(*window) - fyne.CurrentApp().Settings().SetTheme(theme.DarkTheme()) + fyne.CurrentApp().Settings().SetTheme(internalTest.DarkTheme(theme.DefaultTheme())) rect := canvas.NewRectangle(color.White) rect.SetMinSize(fyne.NewSize(100, 100)) tapped := false @@ -1435,7 +1436,7 @@ func TestWindow_SetPadded(t *testing.T) { } else { menuHeight = canvas.NewText("", color.Black).MinSize().Height + theme.Padding()*2 } - fyne.CurrentApp().Settings().SetTheme(theme.DarkTheme()) + fyne.CurrentApp().Settings().SetTheme(internalTest.DarkTheme(theme.DefaultTheme())) tests := []struct { name string padding bool diff --git a/staticcheck.conf b/staticcheck.conf index 7cbfa2195b..2817485420 100644 --- a/staticcheck.conf +++ b/staticcheck.conf @@ -1 +1 @@ -checks = ["inherit", "-SA1019", "ST1003", "ST1016", "ST1020", "ST1021", "ST1022"] +checks = ["inherit", "ST1003", "ST1016", "ST1020", "ST1021", "ST1022"] diff --git a/test/markup_renderer.go b/test/markup_renderer.go index 74d0752964..9a7c770a38 100644 --- a/test/markup_renderer.go +++ b/test/markup_renderer.go @@ -444,7 +444,7 @@ func knownResource(rsc fyne.Resource) string { theme.FolderIcon(): "folderIcon", theme.FolderNewIcon(): "folderNewIcon", theme.FolderOpenIcon(): "folderOpenIcon", - theme.FyneLogo(): "fyneLogo", + theme.FyneLogo(): "fyneLogo", //lint:ignore SA1019 This needs to stay until the API is removed. theme.HelpIcon(): "helpIcon", theme.HistoryIcon(): "historyIcon", theme.HomeIcon(): "homeIcon", diff --git a/test/testapp.go b/test/testapp.go index ed2382a172..6c54eee35d 100644 --- a/test/testapp.go +++ b/test/testapp.go @@ -10,6 +10,7 @@ import ( "fyne.io/fyne/v2/internal/app" "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/painter" + "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/theme" ) @@ -216,7 +217,7 @@ func (s *testSettings) Theme() fyne.Theme { defer s.propertyLock.RUnlock() if s.theme == nil { - return theme.DarkTheme() + return test.DarkTheme(theme.DefaultTheme()) } return s.theme diff --git a/tools/playground/playground.go b/tools/playground/playground.go index 2eabe8038e..8dfb852dda 100644 --- a/tools/playground/playground.go +++ b/tools/playground/playground.go @@ -10,6 +10,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/driver/software" + "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/theme" ) @@ -27,7 +28,7 @@ func imageToPlayground(img image.Image) { // RenderCanvas takes a canvas and converts it into an inline image for showing in the playground func RenderCanvas(c fyne.Canvas) { - imageToPlayground(software.RenderCanvas(c, theme.DarkTheme())) + imageToPlayground(software.RenderCanvas(c, test.DarkTheme(theme.DefaultTheme()))) } // RenderWindow takes a window and converts it's canvas into an inline image for showing in the playground @@ -37,5 +38,5 @@ func RenderWindow(w fyne.Window) { // Render takes a canvasobject and converts it into an inline image for showing in the playground func Render(obj fyne.CanvasObject) { - imageToPlayground(software.Render(obj, theme.DarkTheme())) + imageToPlayground(software.Render(obj, test.DarkTheme(theme.DefaultTheme()))) } diff --git a/widget/button_test.go b/widget/button_test.go index 45e98b2ba9..c13b2a841f 100644 --- a/widget/button_test.go +++ b/widget/button_test.go @@ -6,6 +6,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/driver/desktop" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -67,7 +68,7 @@ func TestButton_Tapped(t *testing.T) { func TestButton_Disable(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) tapped := false button := widget.NewButtonWithIcon("Test", theme.HomeIcon(), func() { @@ -138,7 +139,7 @@ func TestButton_LowImportance(t *testing.T) { func TestButton_Hover(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) b := widget.NewButtonWithIcon("Test", theme.HomeIcon(), func() {}) w := test.NewWindow(b) @@ -324,7 +325,7 @@ func TestButtonCompatImportance(t *testing.T) { func TestButtonSuccess(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) b := widget.NewButtonWithIcon("Test", theme.HomeIcon(), func() {}) w := test.NewWindow(b) diff --git a/widget/entry_validation_test.go b/widget/entry_validation_test.go index 1a54a7e793..b8f4aa1509 100644 --- a/widget/entry_validation_test.go +++ b/widget/entry_validation_test.go @@ -5,6 +5,7 @@ import ( "testing" "fyne.io/fyne/v2/data/validation" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -88,7 +89,7 @@ func TestEntry_NotEmptyValidator(t *testing.T) { func TestEntry_SetValidationError(t *testing.T) { entry, window := setupImageTest(t, false) - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) defer teardownImageTest(window) c := window.Canvas() diff --git a/widget/form_test.go b/widget/form_test.go index ffc1f2f3b4..efa32a0e07 100644 --- a/widget/form_test.go +++ b/widget/form_test.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/data/validation" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" @@ -150,7 +151,7 @@ func TestForm_ChangeTheme(t *testing.T) { func TestForm_Disabled(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) disabled := NewEntry() disabled.Disable() @@ -167,7 +168,7 @@ func TestForm_Disabled(t *testing.T) { func TestForm_Hints(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) entry1 := &Entry{} entry2 := &Entry{Validator: validation.NewRegexp(`^\w{3}-\w{5}$`, "Input is not valid"), Text: "wrong"} @@ -192,7 +193,7 @@ func TestForm_Hints(t *testing.T) { func TestForm_Validation(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) entry1 := &Entry{Validator: validation.NewRegexp(`^\d{2}-\w{4}$`, "Input is not valid"), Text: "15-true"} entry2 := &Entry{Validator: validation.NewRegexp(`^\w{3}-\w{5}$`, "Input is not valid"), Text: "wrong"} @@ -224,7 +225,7 @@ func TestForm_Validation(t *testing.T) { func TestForm_EntryValidation_FirstTypeValid(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) notEmptyValidator := func(s string) error { if s == "" { @@ -264,7 +265,7 @@ func TestForm_EntryValidation_FirstTypeValid(t *testing.T) { func TestForm_DisableEnable(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) form := &Form{ Items: []*FormItem{ @@ -300,7 +301,7 @@ func TestForm_DisableEnable(t *testing.T) { func TestForm_Disable_Validation(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) entry := &Entry{Validator: validation.NewRegexp(`^\d{2}-\w{4}$`, "Input is not valid"), Text: "wrong"} @@ -332,7 +333,7 @@ func TestForm_Disable_Validation(t *testing.T) { func TestForm_HintsRendered(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) f := NewForm() diff --git a/widget/hyperlink_test.go b/widget/hyperlink_test.go index 21ba205427..178b2c7df0 100644 --- a/widget/hyperlink_test.go +++ b/widget/hyperlink_test.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/driver/desktop" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" @@ -69,7 +70,7 @@ func TestHyperlink_Hide(t *testing.T) { func TestHyperlink_Focus(t *testing.T) { app := test.NewApp() defer test.NewApp() - app.Settings().SetTheme(theme.LightTheme()) + app.Settings().SetTheme(internalTest.LightTheme(theme.DefaultTheme())) hyperlink := &Hyperlink{Text: "Test"} w := test.NewWindow(hyperlink) diff --git a/widget/label_test.go b/widget/label_test.go index bcc737a49e..bc4441ef55 100644 --- a/widget/label_test.go +++ b/widget/label_test.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/internal/painter/software" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" @@ -208,7 +209,7 @@ func TestNewLabelWithData(t *testing.T) { func TestLabelImportance(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) lbl := NewLabel("hello, fyne") w := test.NewWindow(lbl) diff --git a/widget/slider_test.go b/widget/slider_test.go index 740255044b..b225eea892 100644 --- a/widget/slider_test.go +++ b/widget/slider_test.go @@ -5,6 +5,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/data/binding" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" @@ -54,7 +55,7 @@ func TestSlider_Binding(t *testing.T) { func TestSlider_HorizontalLayout(t *testing.T) { app := test.NewApp() defer test.NewApp() - app.Settings().SetTheme(theme.LightTheme()) + app.Settings().SetTheme(internalTest.LightTheme(theme.DefaultTheme())) slider := NewSlider(0, 1) slider.Resize(fyne.NewSize(100, 10)) @@ -89,7 +90,7 @@ func TestSlider_OutOfRange(t *testing.T) { func TestSlider_VerticalLayout(t *testing.T) { app := test.NewApp() defer test.NewApp() - app.Settings().SetTheme(theme.LightTheme()) + app.Settings().SetTheme(internalTest.LightTheme(theme.DefaultTheme())) slider := NewSlider(0, 1) slider.Orientation = Vertical diff --git a/widget/table_test.go b/widget/table_test.go index 8ed6eb5cae..b634f532a8 100644 --- a/widget/table_test.go +++ b/widget/table_test.go @@ -8,6 +8,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/driver/desktop" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" @@ -86,7 +87,7 @@ func TestTable_ChangeTheme(t *testing.T) { func TestTable_Filled(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) table := NewTable( func() (int, int) { return 5, 5 }, @@ -717,7 +718,7 @@ func TestTable_Select(t *testing.T) { func TestTable_SetColumnWidth(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) table := NewTable( func() (int, int) { return 5, 5 }, @@ -797,7 +798,7 @@ func TestTable_SetColumnWidth_Dragged(t *testing.T) { func TestTable_SetRowHeight(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) table := NewTable( func() (int, int) { return 5, 5 }, diff --git a/widget/tree_test.go b/widget/tree_test.go index eea8e07ac1..d53b3fc5cf 100644 --- a/widget/tree_test.go +++ b/widget/tree_test.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/data/binding" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -329,7 +330,7 @@ func TestTree_Move(t *testing.T) { func TestTree_Refresh(t *testing.T) { test.NewApp() defer test.NewApp() - test.ApplyTheme(t, theme.LightTheme()) + test.ApplyTheme(t, internalTest.LightTheme(theme.DefaultTheme())) value := "Foo Leaf" tree := widget.NewTreeWithStrings(treeData) diff --git a/widget/widget_test.go b/widget/widget_test.go index 28b429406b..4fd7d19544 100644 --- a/widget/widget_test.go +++ b/widget/widget_test.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" + internalTest "fyne.io/fyne/v2/internal/test" internalWidget "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/test" @@ -33,7 +34,7 @@ func TestApplyThemeCalled(t *testing.T) { widget := &myWidget{refreshed: make(chan bool)} window := test.NewWindow(widget) - fyne.CurrentApp().Settings().SetTheme(theme.LightTheme()) + fyne.CurrentApp().Settings().SetTheme(internalTest.LightTheme(theme.DefaultTheme())) func() { select { @@ -51,7 +52,7 @@ func TestApplyThemeCalledChild(t *testing.T) { parent := &fyne.Container{Layout: layout.NewVBoxLayout(), Objects: []fyne.CanvasObject{child}} window := test.NewWindow(parent) - fyne.CurrentApp().Settings().SetTheme(theme.LightTheme()) + fyne.CurrentApp().Settings().SetTheme(internalTest.LightTheme(theme.DefaultTheme())) func() { select { case <-child.refreshed: From b614c91907de9257113b0de3a8d7142f9d7c4f80 Mon Sep 17 00:00:00 2001 From: Jacob Date: Mon, 8 Jan 2024 22:02:16 +0100 Subject: [PATCH 247/248] Fix last batch of deprecation warnings --- cmd/fyne/internal/commands/bundle.go | 2 +- cmd/fyne/internal/mobile/build_androidapp.go | 2 +- cmd/fyne/internal/mobile/build_iosapp.go | 2 +- cmd/fyne/main.go | 2 +- widget/entry.go | 12 ++++++------ widget/entry_password_extend_test.go | 2 +- widget/entry_test.go | 6 +++--- widget/label_test.go | 2 +- widget/richtext.go | 2 +- widget/richtext_benchmark_test.go | 2 +- widget/richtext_test.go | 18 +++++++++--------- widget/select_entry.go | 2 +- 12 files changed, 27 insertions(+), 27 deletions(-) diff --git a/cmd/fyne/internal/commands/bundle.go b/cmd/fyne/internal/commands/bundle.go index 0c2feddabe..5b8b8f3268 100644 --- a/cmd/fyne/internal/commands/bundle.go +++ b/cmd/fyne/internal/commands/bundle.go @@ -243,7 +243,7 @@ func openOutputFile(filePath string, noheader bool) (file *os.File, close func() } func sanitiseName(file, prefix string) string { - titled := strings.Title(file) + titled := strings.Title(file) //lint:ignore SA1019 This is fine for our use case. name := filenameRegex.ReplaceAllString(titled, "") return prefix + name diff --git a/cmd/fyne/internal/mobile/build_androidapp.go b/cmd/fyne/internal/mobile/build_androidapp.go index 1d2373dca3..62762336ef 100644 --- a/cmd/fyne/internal/mobile/build_androidapp.go +++ b/cmd/fyne/internal/mobile/build_androidapp.go @@ -58,7 +58,7 @@ func goAndroidBuild(pkg *packages.Package, bundleID string, androidArchs []strin buf.WriteString(``) err := templates.ManifestAndroid.Execute(buf, manifestTmplData{ JavaPkgPath: bundleID, - Name: strings.Title(appName), + Name: strings.Title(appName), //lint:ignore SA1019 This is fine for our use case. Debug: !buildRelease, LibName: libName, Version: version, diff --git a/cmd/fyne/internal/mobile/build_iosapp.go b/cmd/fyne/internal/mobile/build_iosapp.go index 09fb668af6..6712116847 100644 --- a/cmd/fyne/internal/mobile/build_iosapp.go +++ b/cmd/fyne/internal/mobile/build_iosapp.go @@ -51,7 +51,7 @@ func goIOSBuild(pkg *packages.Package, bundleID string, archs []string, infoplist := new(bytes.Buffer) if err := infoplistTmpl.Execute(infoplist, infoplistTmplData{ BundleID: bundleID, - Name: strings.Title(appName), + Name: strings.Title(appName), //lint:ignore SA1019 This is fine for our use case. Version: version, Build: build, Legacy: len(allArchs["ios"]) > 2, diff --git a/cmd/fyne/main.go b/cmd/fyne/main.go index faeb414d9e..f24860689e 100644 --- a/cmd/fyne/main.go +++ b/cmd/fyne/main.go @@ -32,7 +32,7 @@ func main() { commands.Build(), // Deprecated: Use "go mod vendor" instead. - commands.Vendor(), + commands.Vendor(), //lint:ignore SA1019 This whole tool is deprecated. }, } diff --git a/widget/entry.go b/widget/entry.go index 1b22117a50..927b2781bf 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -109,7 +109,7 @@ type Entry struct { // NewEntry creates a new single line entry widget. func NewEntry() *Entry { - e := &Entry{Wrapping: fyne.TextTruncate} + e := &Entry{Wrapping: fyne.TextWrap(fyne.TextTruncateClip)} e.ExtendBaseWidget(e) return e } @@ -126,14 +126,14 @@ func NewEntryWithData(data binding.String) *Entry { // NewMultiLineEntry creates a new entry that allows multiple lines func NewMultiLineEntry() *Entry { - e := &Entry{MultiLine: true, Wrapping: fyne.TextTruncate} + e := &Entry{MultiLine: true, Wrapping: fyne.TextWrap(fyne.TextTruncateClip)} e.ExtendBaseWidget(e) return e } // NewPasswordEntry creates a new entry password widget func NewPasswordEntry() *Entry { - e := &Entry{Password: true, Wrapping: fyne.TextTruncate} + e := &Entry{Password: true, Wrapping: fyne.TextWrap(fyne.TextTruncateClip)} e.ExtendBaseWidget(e) e.ActionItem = newPasswordRevealer(e) return e @@ -1356,13 +1356,13 @@ func (e *Entry) textProvider() *RichText { // textWrap calculates the wrapping that we should apply. func (e *Entry) textWrap() fyne.TextWrap { - if e.Wrapping == fyne.TextTruncate { // this is now the default - but we scroll around this large content + if e.Wrapping == fyne.TextWrap(fyne.TextTruncateClip) { // this is now the default - but we scroll around this large content return fyne.TextWrapOff } if !e.MultiLine && (e.Wrapping == fyne.TextWrapBreak || e.Wrapping == fyne.TextWrapWord) { fyne.LogError("Entry cannot wrap single line", nil) - e.Wrapping = fyne.TextTruncate + e.Wrapping = fyne.TextWrap(fyne.TextTruncateClip) return fyne.TextWrapOff } return e.Wrapping @@ -2026,7 +2026,7 @@ func (r *entryContentRenderer) updateScrollDirections() { switch r.content.entry.Wrapping { case fyne.TextWrapOff: r.content.scroll.Direction = r.content.entry.Scroll - case fyne.TextTruncate: // this is now the default - but we scroll + case fyne.TextWrap(fyne.TextTruncateClip): // this is now the default - but we scroll r.content.scroll.Direction = widget.ScrollBoth default: // fyne.TextWrapBreak, fyne.TextWrapWord r.content.scroll.Direction = widget.ScrollVerticalOnly diff --git a/widget/entry_password_extend_test.go b/widget/entry_password_extend_test.go index 5494bc1bb6..71f4011413 100644 --- a/widget/entry_password_extend_test.go +++ b/widget/entry_password_extend_test.go @@ -21,7 +21,7 @@ func TestEntry_Password_Extended_CreateRenderer(t *testing.T) { entry := &extendEntry{} entry.ExtendBaseWidget(entry) entry.Password = true - entry.Wrapping = fyne.TextTruncate + entry.Wrapping = fyne.TextWrap(fyne.TextTruncateClip) assert.NotNil(t, test.WidgetRenderer(entry)) r := test.WidgetRenderer(entry).(*entryRenderer).scroll.Content.(*entryContent) p := test.WidgetRenderer(r).(*entryContentRenderer).provider diff --git a/widget/entry_test.go b/widget/entry_test.go index ca0d9eff26..1f4f83be73 100644 --- a/widget/entry_test.go +++ b/widget/entry_test.go @@ -1686,7 +1686,7 @@ func TestEntry_TextWrap(t *testing.T) { want: "entry/wrap_single_line_off.xml", }, "single line Truncate": { - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: "entry/wrap_single_line_truncate.xml", }, "single line Scroll": { @@ -1712,7 +1712,7 @@ func TestEntry_TextWrap(t *testing.T) { // Disallowed - fallback to TextWrapOff "multi line Truncate": { multiLine: true, - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: "entry/wrap_multi_line_truncate.xml", }, "multi line WrapBreak": { @@ -1755,7 +1755,7 @@ func TestEntry_TextWrap_Changed(t *testing.T) { e.SetText("Testing Wrapping") test.AssertRendersToMarkup(t, "entry/wrap_single_line_off.xml", c) - e.Wrapping = fyne.TextTruncate + e.Wrapping = fyne.TextWrap(fyne.TextTruncateClip) e.Refresh() test.AssertRendersToMarkup(t, "entry/wrap_single_line_truncate.xml", c) diff --git a/widget/label_test.go b/widget/label_test.go index bc4441ef55..2eea912c08 100644 --- a/widget/label_test.go +++ b/widget/label_test.go @@ -192,7 +192,7 @@ func TestLabel_ChangeTruncate(t *testing.T) { truncSize := text.MinSize().Subtract(fyne.NewSize(10, 0)) text.Resize(truncSize) - text.Wrapping = fyne.TextTruncate + text.Truncation = fyne.TextTruncateClip text.Refresh() test.AssertRendersToMarkup(t, "label/truncate.xml", c) } diff --git a/widget/richtext.go b/widget/richtext.go index 6b14fb9f71..8279575d90 100644 --- a/widget/richtext.go +++ b/widget/richtext.go @@ -897,7 +897,7 @@ func float32ToFixed266(f float32) fixed.Int26_6 { func lineBounds(seg *TextSegment, wrap fyne.TextWrap, trunc fyne.TextTruncation, firstWidth float32, max fyne.Size, measurer func([]rune) fyne.Size) ([]rowBoundary, float32) { lines := splitLines(seg) - if wrap == fyne.TextTruncate { + if wrap == fyne.TextWrap(fyne.TextTruncateClip) { if trunc == fyne.TextTruncateOff { trunc = fyne.TextTruncateClip } diff --git a/widget/richtext_benchmark_test.go b/widget/richtext_benchmark_test.go index 583a0ba9b7..96e358af44 100644 --- a/widget/richtext_benchmark_test.go +++ b/widget/richtext_benchmark_test.go @@ -49,7 +49,7 @@ func BenchmarkText_lineBounds_WrapOff(b *testing.B) { } func BenchmarkText_lineBounds_Truncate(b *testing.B) { - benchmarkTextLineBounds(fyne.TextTruncate, b) + benchmarkTextLineBounds(fyne.TextWrap(fyne.TextTruncateClip), b) } func BenchmarkText_lineBounds_WrapBreak(b *testing.B) { diff --git a/widget/richtext_test.go b/widget/richtext_test.go index 136ae13411..ea4fbfe8d3 100644 --- a/widget/richtext_test.go +++ b/widget/richtext_test.go @@ -461,7 +461,7 @@ func TestText_lineBounds(t *testing.T) { { name: "Empty_Truncate", text: "", - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: [][2]int{ {0, 0}, }, @@ -501,7 +501,7 @@ func TestText_lineBounds(t *testing.T) { { name: "Single_Short_Truncate", text: "foobar", - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: [][2]int{ {0, 6}, }, @@ -550,7 +550,7 @@ func TestText_lineBounds(t *testing.T) { { name: "Single_Long_Truncate", text: "foobar foobar", - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: [][2]int{ {0, 10}, }, @@ -602,7 +602,7 @@ func TestText_lineBounds(t *testing.T) { { name: "Multiple_Short_Truncate", text: "foo\nbar", - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: [][2]int{ {0, 3}, {4, 7}, @@ -658,7 +658,7 @@ func TestText_lineBounds(t *testing.T) { { name: "Multiple_Long_Truncate", text: "foobar\nfoobar foobar foobar\nfoobar foobar", - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: [][2]int{ {0, 6}, {7, 17}, @@ -725,7 +725,7 @@ func TestText_lineBounds(t *testing.T) { { name: "Multiple_Contiguous_Long_Truncate", text: "foobar\nfoobarfoobarfoobar\nfoobarfoobar\n", - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: [][2]int{ {0, 6}, {7, 17}, @@ -795,7 +795,7 @@ func TestText_lineBounds(t *testing.T) { { name: "Multiple_Trailing_Short_Truncate", text: "foo\nbar\n", - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: [][2]int{ {0, 3}, {4, 7}, @@ -877,7 +877,7 @@ func TestText_lineBounds(t *testing.T) { { name: "Multiple_Trailing_Long_Truncate", text: "foobar\nfoobar foobar foobar\nfoobar foobar\n", - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: [][2]int{ {0, 6}, {7, 17}, @@ -1016,7 +1016,7 @@ func TestText_lineBounds_variable_char_width(t *testing.T) { { name: "IM_Truncate", text: "iiiiiiiiiimmmmmmmmmm", - wrap: fyne.TextTruncate, + wrap: fyne.TextWrap(fyne.TextTruncateClip), want: [][2]int{ {0, 12}, }, diff --git a/widget/select_entry.go b/widget/select_entry.go index b2900e7f19..4c2bedaf59 100644 --- a/widget/select_entry.go +++ b/widget/select_entry.go @@ -17,7 +17,7 @@ type SelectEntry struct { func NewSelectEntry(options []string) *SelectEntry { e := &SelectEntry{options: options} e.ExtendBaseWidget(e) - e.Wrapping = fyne.TextTruncate + e.Wrapping = fyne.TextWrap(fyne.TextTruncateClip) return e } From 751df8ccb81b4984a200dc3876204ed61623180a Mon Sep 17 00:00:00 2001 From: Jacob Date: Mon, 8 Jan 2024 22:08:00 +0100 Subject: [PATCH 248/248] Fix mobile tests --- container/apptabs_mobile_test.go | 2 ++ container/doctabs_mobile_test.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/container/apptabs_mobile_test.go b/container/apptabs_mobile_test.go index 5f9ca9c90e..fea05dbd07 100644 --- a/container/apptabs_mobile_test.go +++ b/container/apptabs_mobile_test.go @@ -8,9 +8,11 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/container/doctabs_mobile_test.go b/container/doctabs_mobile_test.go index 7f3495643b..6dd788404c 100644 --- a/container/doctabs_mobile_test.go +++ b/container/doctabs_mobile_test.go @@ -8,9 +8,11 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" + internalTest "fyne.io/fyne/v2/internal/test" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" )