Skip to content

Commit d8e9fe0

Browse files
committed
Merge branch 'release/v2.4.x'
2 parents 6b2c99e + 32c0f15 commit d8e9fe0

32 files changed

+311
-121
lines changed

CHANGELOG.md

+20
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,26 @@
33
This file lists the main changes with each version of the Fyne toolkit.
44
More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases).
55

6+
## 2.4.5 - 15 April 2024
7+
8+
### Fixed
9+
10+
* iOS files write would fail when over 16KB
11+
* storage.Delete not supported on Android/iOS (#2120)
12+
* layout.formLayout do not handle canvas.Text well in second column (#4665)
13+
* Fix building with ios17.4 (#4741)
14+
* Support template icon for system tray menu icons
15+
* Fix recognition of missing XDG user directories (#4650)
16+
* FileDialog.SetOnClosed not always working (#4651)
17+
* Upgrade GLFW for performance improvements and bug fixes
18+
* Multiple select popups can crash during background operations (#4730)
19+
* Controlling a negative slider with the left arrow key blocks after 8 steps (#4736)
20+
* cmd/fyne: command "get" is broken with Go 1.22 (#4684)
21+
* Race condition during system tray menu refresh (#4697)
22+
* Fyne release on Linux does not set Metadata().Release to true (#4711)
23+
* RichText leaks memory when replacing segments (#4723)
24+
25+
626
## 2.4.4 - 13 February 2024
727

828
### Fixed

cmd/fyne/internal/commands/get.go

+24-16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import (
1010

1111
"github.com/urfave/cli/v2"
1212
"golang.org/x/sys/execabs"
13+
14+
//lint:ignore SA1019 The recommended replacement does not solve the use-case
15+
"golang.org/x/tools/go/vcs"
1316
)
1417

1518
// Get returns the command which downloads and installs fyne applications.
@@ -57,20 +60,37 @@ func NewGetter() *Getter {
5760

5861
// Get automates the download and install of a named GUI app package.
5962
func (g *Getter) Get(pkg string) error {
60-
cmd := execabs.Command("go", "get", "-u", "-d", pkg)
61-
cmd.Env = append(os.Environ(), "GO111MODULE=off") // cache the downloaded code
63+
name := filepath.Base(pkg)
64+
path, err := os.MkdirTemp("", fmt.Sprintf("fyne-get-%s-*", name))
65+
if err != nil {
66+
return err
67+
}
68+
defer os.RemoveAll(path)
69+
70+
repo, err := vcs.RepoRootForImportPath(pkg, false)
71+
if err != nil {
72+
return fmt.Errorf("failed to look up source control for package: %w", err)
73+
}
74+
if repo.VCS.Name != "Git" {
75+
return errors.New("unsupported VCS: " + repo.VCS.Name)
76+
}
77+
cmd := execabs.Command("git", "clone", repo.Repo, "--depth=1", path)
6278
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
6379

64-
err := cmd.Run()
80+
err = cmd.Run()
6581
if err != nil {
6682
return err
6783
}
6884

69-
path := filepath.Join(goPath(), "src", pkg)
7085
if !util.Exists(path) { // the error above may be ignorable, unless the path was not found
7186
return err
7287
}
7388

89+
if repo.Root != pkg {
90+
dir := strings.Replace(pkg, repo.Root, "", 1)
91+
path = filepath.Join(path, dir)
92+
}
93+
7494
install := &Installer{appData: g.appData, srcDir: path, release: true}
7595
if err := install.validate(); err != nil {
7696
return fmt.Errorf("failed to set up installer: %w", err)
@@ -121,15 +141,3 @@ func (g *Getter) Run(args []string) {
121141
os.Exit(1)
122142
}
123143
}
124-
125-
func goPath() string {
126-
cmd := execabs.Command("go", "env", "GOPATH")
127-
out, err := cmd.CombinedOutput()
128-
129-
if err != nil {
130-
home, _ := os.UserHomeDir()
131-
return filepath.Join(home, "go")
132-
}
133-
134-
return strings.TrimSpace(string(out[0 : len(out)-1]))
135-
}

cmd/fyne/internal/commands/package.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ func (p *Packager) validate() (err error) {
375375
os.Chdir(p.srcDir)
376376

377377
p.appData.CustomMetadata = p.customMetadata.m
378+
p.appData.Release = p.release
378379

379380
data, err := metadata.LoadStandard(p.srcDir)
380381
if err == nil {
@@ -383,7 +384,6 @@ func (p *Packager) validate() (err error) {
383384
data.Details.Icon = util.MakePathRelativeTo(p.srcDir, data.Details.Icon)
384385
}
385386

386-
p.appData.Release = p.release
387387
p.appData.mergeMetadata(data)
388388
p.linuxAndBSDMetadata = data.LinuxAndBSD
389389
}

cmd/fyne/internal/commands/release.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,14 @@ func (r *Releaser) PrintHelp(indent string) {
188188
//
189189
// Deprecated: A better version will be exposed in the future.
190190
func (r *Releaser) Run(params []string) {
191+
r.Packager.distribution = true
192+
r.Packager.release = true
193+
191194
if err := r.validate(); err != nil {
192195
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
193196
return
194197
}
195198

196-
r.Packager.distribution = true
197-
r.Packager.release = true
198-
199199
if err := r.beforePackage(); err != nil {
200200
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
201201
return
@@ -207,13 +207,13 @@ func (r *Releaser) Run(params []string) {
207207
}
208208

209209
func (r *Releaser) releaseAction(_ *cli.Context) error {
210+
r.Packager.distribution = true
211+
r.Packager.release = true
212+
210213
if err := r.validate(); err != nil {
211214
return err
212215
}
213216

214-
r.Packager.distribution = true
215-
r.Packager.release = true
216-
217217
if err := r.beforePackage(); err != nil {
218218
return err
219219
}

cmd/fyne/internal/mobile/build_iosapp.go

+2
Original file line numberDiff line numberDiff line change
@@ -523,11 +523,13 @@ var projPbxprojTmpl = template.Must(template.New("projPbxproj").Parse(`// !$*UTF
523523
GCC_WARN_UNUSED_FUNCTION = YES;
524524
GCC_WARN_UNUSED_VARIABLE = YES;
525525
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
526+
OS_ACTIVITY_MODE = "disabled";
526527
MTL_ENABLE_DEBUG_INFO = {{if .Debug}}YES{{else}}NO{{end}};
527528
PRODUCT_BUNDLE_IDENTIFIER = {{.BundleID}};
528529
PROVISIONING_PROFILE_SPECIFIER = "{{.Profile}}";
529530
SDKROOT = iphoneos;
530531
TARGETED_DEVICE_FAMILY = "1,2";
532+
OS_ACTIVITY_MODE = "disable";
531533
VALIDATE_PRODUCT = YES;
532534
{{if not .BitcodeEnabled}}ENABLE_BITCODE = NO;{{end}}
533535
};

dialog/file.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -703,13 +703,13 @@ func (f *FileDialog) SetLocation(u fyne.ListableURI) {
703703
// SetOnClosed sets a callback function that is called when
704704
// the dialog is closed.
705705
func (f *FileDialog) SetOnClosed(closed func()) {
706-
if f.dialog == nil {
707-
return
708-
}
709706
// If there is already a callback set, remember it and call both.
710707
originalCallback := f.onClosedCallback
711708

712709
f.onClosedCallback = func(response bool) {
710+
if f.dialog == nil {
711+
return
712+
}
713713
closed()
714714
if originalCallback != nil {
715715
originalCallback(response)

dialog/file_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,13 @@ func TestCreateNewFolderInDir(t *testing.T) {
630630
folderNameInputCreate := folderNameInputUi.Objects[3].(*fyne.Container).Objects[1].(*widget.Button)
631631
assert.Equal(t, theme.ConfirmIcon(), folderNameInputCreate.Icon)
632632
}
633+
634+
func TestSetOnClosedBeforeShow(t *testing.T) {
635+
win := test.NewWindow(widget.NewLabel("Content"))
636+
d := NewFileSave(func(fyne.URIWriteCloser, error) {}, win)
637+
onClosedCalled := false
638+
d.SetOnClosed(func() { onClosedCalled = true })
639+
d.Show()
640+
d.Hide()
641+
assert.True(t, onClosedCalled)
642+
}

dialog/file_xdg.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package dialog
99
import (
1010
"fmt"
1111
"os"
12+
"strings"
1213

1314
"fyne.io/fyne/v2"
1415
"fyne.io/fyne/v2/storage"
@@ -32,7 +33,7 @@ func getFavoriteLocation(homeURI fyne.URI, name, fallbackName string) (fyne.URI,
3233
loc = loc[:len(loc)-1]
3334
locURI := storage.NewFileURI(string(loc))
3435

35-
if locURI.String() == homeURI.String() {
36+
if strings.TrimRight(locURI.String(), "/") == strings.TrimRight(homeURI.String(), "/") {
3637
fallback, _ := storage.Child(homeURI, fallbackName)
3738
return fallback, fmt.Errorf("this computer does not define a %s folder", name)
3839
}
@@ -63,6 +64,9 @@ func getFavoriteLocations() (map[string]fyne.ListableURI, error) {
6364
for _, favName := range favoriteNames {
6465
var uri fyne.URI
6566
uri, err = getFavoriteLocation(homeURI, arguments[favName], favName)
67+
if err != nil {
68+
continue
69+
}
6670

6771
listURI, err1 := storage.ListerForURI(uri)
6872
if err1 != nil {

go.mod

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ require (
1212
github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504
1313
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2
1414
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6
15-
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b
15+
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240306074159-ea2d69986ecb
1616
github.com/go-ole/go-ole v1.2.6
17-
github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8
17+
github.com/go-text/render v0.1.0
1818
github.com/go-text/typesetting v0.1.0
1919
github.com/godbus/dbus/v5 v5.1.0
2020
github.com/gopherjs/gopherjs v1.17.2
@@ -33,6 +33,7 @@ require (
3333
golang.org/x/mod v0.12.0
3434
golang.org/x/sys v0.13.0
3535
golang.org/x/tools v0.12.0
36+
golang.org/x/tools/go/vcs v0.1.0-deprecated
3637
honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2
3738
)
3839

go.sum

+9-7
Original file line numberDiff line numberDiff line change
@@ -99,18 +99,17 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
9999
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
100100
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
101101
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
102-
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b h1:GgabKamyOYguHqHjSkDACcgoPIz3w0Dis/zJ1wyHHHU=
103-
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
102+
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240306074159-ea2d69986ecb h1:S9I8pIVT5JHKDvmI1vQ0qs5fqxzUfhcZm/YbUC/8k1k=
103+
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240306074159-ea2d69986ecb/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
104104
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
105105
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
106-
github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 h1:VkKnvzbvHqgEfm351rfr8Uclu5fnwq8HP2ximUzJsBM=
107-
github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8/go.mod h1:h29xCucjNsDcYb7+0rJokxVwYAq+9kQ19WiFuBKkYtc=
108-
github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a/go.mod h1:evDBbvNR/KaVFZ2ZlDSOWWXIUKq0wCOEtzLxRM8SG3k=
106+
github.com/go-text/render v0.1.0 h1:osrmVDZNHuP1RSu3pNG7Z77Sd2xSbcb/xWytAj9kyVs=
107+
github.com/go-text/render v0.1.0/go.mod h1:jqEuNMenrmj6QRnkdpeaP0oKGFLDNhDkVKwGjsWWYU4=
109108
github.com/go-text/typesetting v0.1.0 h1:vioSaLPYcHwPEPLT7gsjCGDCoYSbljxoHJzMnKwVvHw=
110109
github.com/go-text/typesetting v0.1.0/go.mod h1:d22AnmeKq/on0HNv73UFriMKc4Ez6EqZAofLhAzpSzI=
111-
github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
112-
github.com/go-text/typesetting-utils v0.0.0-20231211103740-d9332ae51f04 h1:zBx+p/W2aQYtNuyZNcTfinWvXBQwYtDfme051PR/lAY=
113110
github.com/go-text/typesetting-utils v0.0.0-20231211103740-d9332ae51f04/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
111+
github.com/go-text/typesetting-utils v0.0.0-20240329101916-eee87fb235a3 h1:levTnuLLUmpavLGbJYLJA7fQnKeS7P1eCdAlM+vReXk=
112+
github.com/go-text/typesetting-utils v0.0.0-20240329101916-eee87fb235a3/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
114113
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
115114
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
116115
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -519,6 +518,7 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
519518
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
520519
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
521520
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
521+
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
522522
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
523523
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
524524
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -605,6 +605,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
605605
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
606606
golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
607607
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
608+
golang.org/x/tools/go/vcs v0.1.0-deprecated h1:cOIJqWBl99H1dH5LWizPa+0ImeeJq3t3cJjaeOWUAL4=
609+
golang.org/x/tools/go/vcs v0.1.0-deprecated/go.mod h1:zUrvATBAvEI9535oC0yWYsLsHIV4Z7g63sNPVMtuBy8=
608610
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
609611
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
610612
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

internal/driver/glfw/driver.go

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ type gLDriver struct {
4848

4949
trayStart, trayStop func() // shut down the system tray, if used
5050
systrayMenu *fyne.Menu // cache the menu set so we know when to refresh
51+
systrayLock sync.Mutex
5152
}
5253

5354
func toOSIcon(icon []byte) ([]byte, error) {

internal/driver/glfw/driver_desktop.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,20 @@ func itemForMenuItem(i *fyne.MenuItem, parent *systray.MenuItem) *systray.MenuIt
121121
if err != nil {
122122
fyne.LogError("Failed to convert systray icon", err)
123123
} else {
124-
item.SetIcon(img)
124+
if _, ok := i.Icon.(*theme.ThemedResource); ok {
125+
item.SetTemplateIcon(img, img)
126+
} else {
127+
item.SetIcon(img)
128+
}
125129
}
126130
}
127131
return item
128132
}
129133

130134
func (d *gLDriver) refreshSystray(m *fyne.Menu) {
135+
d.systrayLock.Lock()
136+
defer d.systrayLock.Unlock()
137+
131138
d.systrayMenu = m
132139
systray.ResetMenu()
133140
d.refreshSystrayMenu(m, nil)

internal/driver/glfw/loop.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ func (d *gLDriver) runGL() {
138138
f.done <- struct{}{}
139139
}
140140
case <-eventTick.C:
141-
d.tryPollEvents()
141+
d.pollEvents()
142142
windowsToRemove := 0
143143
for _, win := range d.windowList() {
144144
w := win.(*window)

internal/driver/glfw/loop_desktop.go

+1-9
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
package glfw
55

66
import (
7-
"fmt"
8-
97
"fyne.io/fyne/v2"
108

119
"github.com/go-gl/glfw/v3.3/glfw"
@@ -24,13 +22,7 @@ func (d *gLDriver) initGLFW() {
2422
})
2523
}
2624

27-
func (d *gLDriver) tryPollEvents() {
28-
defer func() {
29-
if r := recover(); r != nil {
30-
fyne.LogError(fmt.Sprint("GLFW poll event error: ", r), nil)
31-
}
32-
}()
33-
25+
func (d *gLDriver) pollEvents() {
3426
glfw.PollEvents() // This call blocks while window is being resized, which prevents freeDirtyTextures from being called
3527
}
3628

internal/driver/glfw/loop_goxjs.go

+3-11
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44
package glfw
55

66
import (
7-
"fmt"
8-
97
"fyne.io/fyne/v2"
108

11-
gl "github.com/fyne-io/gl-js"
12-
glfw "github.com/fyne-io/glfw-js"
9+
"github.com/fyne-io/gl-js"
10+
"github.com/fyne-io/glfw-js"
1311
)
1412

1513
func (d *gLDriver) initGLFW() {
@@ -24,13 +22,7 @@ func (d *gLDriver) initGLFW() {
2422
})
2523
}
2624

27-
func (d *gLDriver) tryPollEvents() {
28-
defer func() {
29-
if r := recover(); r != nil {
30-
fyne.LogError(fmt.Sprint("GLFW poll event error: ", r), nil)
31-
}
32-
}()
33-
25+
func (d *gLDriver) pollEvents() {
3426
glfw.PollEvents() // This call blocks while window is being resized, which prevents freeDirtyTextures from being called
3527
}
3628

internal/driver/glfw/window_desktop.go

-4
Original file line numberDiff line numberDiff line change
@@ -583,10 +583,6 @@ func keyCodeToKeyName(code string) fyne.KeyName {
583583
}
584584

585585
func keyToName(code glfw.Key, scancode int) fyne.KeyName {
586-
if runtime.GOOS == "darwin" && scancode == 0x69 { // TODO remove once fixed upstream glfw/glfw#1786
587-
code = glfw.KeyPrintScreen
588-
}
589-
590586
ret := glfwKeyToKeyName(code)
591587
if ret != fyne.KeyUnknown {
592588
return ret

internal/driver/glfw/window_goxjs.go

-4
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,6 @@ func keyCodeToKeyName(code string) fyne.KeyName {
394394
}
395395

396396
func keyToName(code glfw.Key, scancode int) fyne.KeyName {
397-
if runtime.GOOS == "darwin" && scancode == 0x69 { // TODO remove once fixed upstream glfw/glfw#1786
398-
code = glfw.KeyPrintScreen
399-
}
400-
401397
ret := glfwKeyToKeyName(code)
402398
if ret != fyne.KeyUnknown {
403399
return ret

0 commit comments

Comments
 (0)