Skip to content

Commit

Permalink
Merge branch 'release/v2.4.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
andydotxyz committed Feb 13, 2024
2 parents 0ace386 + 9073c1b commit e332a5e
Show file tree
Hide file tree
Showing 44 changed files with 610 additions and 245 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,27 @@
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.4 - 13 February 2024

### Fixed

* Spaces could be appended to linux Exec command during packaging
* Secondary mobile windows would not size correctly when padded
* Setting Icon.Resource to nil will not clear rendering
* Dismiss iOS keyboard if "Done" is tapped
* Large speed improvement in Entry and GridWrap widgets
* tests fail with macOS Assertion failure in NSMenu (#4572)
* Fix image test failures on Apple Silicon
* High CPU use when showing CustomDialogs (#4574)
* Entry does not show the last (few) changes when updating a binding.String in a fast succession (#4082)
* Calling Entry.SetText and then Entry.Bind immediately will ignore the bound value (#4235)
* Changing theme while application is running doesn't change some parameters on some widgets (#4344)
* Check widget: hovering/tapping to the right of the label area should not activate widget (#4527)
* Calling entry.SetPlaceHolder inside of OnChanged callback freezes app (#4516)
* Hyperlink enhancement: underline and tappable area shouldn't be wider than the text label (#3528)
* Fix possible compile error from go-text/typesetting


## 2.4.3 - 23 December 2023

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion cmd/fyne/internal/templates/bundled.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cmd/fyne/internal/templates/data/app.desktop
Expand Up @@ -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}}
Expand Down
4 changes: 2 additions & 2 deletions container.go
Expand Up @@ -129,12 +129,12 @@ func (c *Container) Refresh() {
// This method is not intended to be used inside a loop, to remove all the elements.
// It is much more efficient to call RemoveAll() instead.
func (c *Container) Remove(rem CanvasObject) {
c.lock.Lock()
defer c.lock.Unlock()
if len(c.Objects) == 0 {
return
}

c.lock.Lock()
defer c.lock.Unlock()
for i, o := range c.Objects {
if o != rem {
continue
Expand Down
1 change: 1 addition & 0 deletions container/apptabs.go
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions container/doctabs.go
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions container/tabs.go
Expand Up @@ -292,6 +292,8 @@ type baseTabsRenderer struct {
action *widget.Button
bar *fyne.Container
divider, indicator *canvas.Rectangle

tabs baseTabs
}

func (r *baseTabsRenderer) Destroy() {
Expand All @@ -304,6 +306,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) {
Expand Down
29 changes: 28 additions & 1 deletion container/tabs_test.go
Expand Up @@ -3,10 +3,14 @@ package container
import (
"testing"

"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"
"fyne.io/fyne/v2/theme"
"github.com/stretchr/testify/assert"
"fyne.io/fyne/v2/widget"
)

func TestTabButton_Icon_Change(t *testing.T) {
Expand All @@ -19,3 +23,26 @@ 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)
w.Resize(fyne.NewSize(180, 120))

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())
}
10 changes: 9 additions & 1 deletion dialog/base.go
Expand Up @@ -8,6 +8,7 @@ import (
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
col "fyne.io/fyne/v2/internal/color"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
Expand Down Expand Up @@ -108,8 +109,15 @@ func (d *dialog) hideWithResponse(resp bool) {
func (d *dialog) create(buttons fyne.CanvasObject) {
label := widget.NewLabelWithStyle(d.title, fyne.TextAlignLeading, fyne.TextStyle{Bold: true})

var image fyne.CanvasObject
if d.icon != nil {
image = &canvas.Image{Resource: d.icon}
} else {
image = &layout.Spacer{}
}

content := container.New(&dialogLayout{d: d},
&canvas.Image{Resource: d.icon},
image,
newThemedBackground(),
d.content,
buttons,
Expand Down
2 changes: 1 addition & 1 deletion dialog/file.go
Expand Up @@ -689,7 +689,7 @@ func (f *FileDialog) SetDismissText(label string) {
f.dialog.win.Refresh()
}

// SetLocation tells this FileDirectory which location to display.
// SetLocation tells this FileDialog which location to display.
// This is normally called before the dialog is shown.
//
// Since: 1.4
Expand Down
2 changes: 1 addition & 1 deletion dialog/testdata/dialog-custom-custom-buttons.xml
Expand Up @@ -17,7 +17,7 @@
<rectangle fillColor="shadow" size="200x300"/>
<rectangle fillColor="overlayBackground" pos="19,74" size="161x150"/>
<container pos="23,78" size="153x142">
<image pos="59,-4" size="98x98"/>
<spacer pos="59,-4" size="98x98"/>
<widget size="153x142" type="*dialog.themedBackground">
<rectangle fillColor="rgba(34,34,34,230)" size="153x142"/>
</widget>
Expand Down
2 changes: 1 addition & 1 deletion dialog/testdata/dialog-custom-no-buttons.xml
Expand Up @@ -17,7 +17,7 @@
<rectangle fillColor="shadow" size="200x300"/>
<rectangle fillColor="overlayBackground" pos="19,92" size="161x114"/>
<container pos="23,96" size="153x106">
<image pos="59,-4" size="98x98"/>
<spacer pos="59,-4" size="98x98"/>
<widget size="153x106" type="*dialog.themedBackground">
<rectangle fillColor="rgba(34,34,34,230)" size="153x106"/>
</widget>
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -15,7 +15,7 @@ require (
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b
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/gopherjs/gopherjs v1.17.2
github.com/jackmordaunt/icns/v2 v2.2.6
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Expand Up @@ -105,10 +105,12 @@ 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-20230616150549-2a7df14b6a22/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
github.com/go-text/typesetting-utils v0.0.0-20231211103740-d9332ae51f04 h1:zBx+p/W2aQYtNuyZNcTfinWvXBQwYtDfme051PR/lAY=
github.com/go-text/typesetting-utils v0.0.0-20231211103740-d9332ae51f04/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=
Expand Down
Binary file modified img/hello-dark.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/hello-light.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/widgets-dark.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/widgets-light.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/widgets-mobile-light.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion internal/driver/glfw/glfw_test.go
Expand Up @@ -24,7 +24,7 @@ func assertCanvasSize(t *testing.T, w *window, size fyne.Size) {
}

func ensureCanvasSize(t *testing.T, w *window, size fyne.Size) {
if runtime.GOOS == "linux" {
if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
// TODO: find the root cause for these problems and solve them without additional repaint
// fixes issues where the window does not have the correct size
waitForCanvasSize(t, w, size, true)
Expand Down
16 changes: 12 additions & 4 deletions internal/driver/glfw/menu_darwin_test.go
Expand Up @@ -17,7 +17,9 @@ func TestDarwinMenu(t *testing.T) {
setExceptionCallback(func(msg string) { t.Error("Obj-C exception:", msg) })
defer setExceptionCallback(nil)

resetMainMenu()
runOnMain(func() {
resetMainMenu()
})

w := createWindow("Test").(*window)

Expand Down Expand Up @@ -59,7 +61,9 @@ func TestDarwinMenu(t *testing.T) {
menuSettings := fyne.NewMenu("Settings", itemSettings, fyne.NewMenuItemSeparator(), itemMoreSetings)

mainMenu := fyne.NewMainMenu(menuEdit, menuHelp, menuMore, menuSettings)
setupNativeMenu(w, mainMenu)
runOnMain(func() {
setupNativeMenu(w, mainMenu)
})

mm := testDarwinMainMenu()
// The custom “Preferences” menu should be moved to the system app menu completely.
Expand Down Expand Up @@ -247,13 +251,17 @@ func TestDarwinMenu_specialKeyShortcuts(t *testing.T) {
},
} {
t.Run(name, func(t *testing.T) {
resetMainMenu()
runOnMain(func() {
resetMainMenu()
})
w := createWindow("Test").(*window)
item := fyne.NewMenuItem("Special", func() {})
item.Shortcut = &desktop.CustomShortcut{KeyName: tt.key, Modifier: fyne.KeyModifierShortcutDefault}
menu := fyne.NewMenu("Special", item)
mainMenu := fyne.NewMainMenu(menu)
setupNativeMenu(w, mainMenu)
runOnMain(func() {
setupNativeMenu(w, mainMenu)
})

mm := testDarwinMainMenu()
m := testNSMenuItemSubmenu(testNSMenuItemAtIndex(mm, 1))
Expand Down
10 changes: 7 additions & 3 deletions internal/driver/glfw/window_test.go
Expand Up @@ -245,9 +245,13 @@ 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))
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
Expand Down
13 changes: 13 additions & 0 deletions internal/driver/mobile/app/darwin_ios.m
Expand Up @@ -214,6 +214,19 @@ -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange
return NO;
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if ([self returnKeyType] != UIReturnKeyDone) {
keyboardTyped("\n");
return YES;
}

dispatch_async(dispatch_get_main_queue(), ^{
[self resignFirstResponder];
});

return NO;
}

@end

void runApp(void) {
Expand Down
6 changes: 5 additions & 1 deletion internal/driver/mobile/canvas.go
Expand Up @@ -196,7 +196,11 @@ func (c *mobileCanvas) sizeContent(size fyne.Size) {
if c.windowHead != nil {
topHeight := c.windowHead.MinSize().Height

if len(c.windowHead.(*fyne.Container).Objects) > 1 {
chromeBox := c.windowHead.(*fyne.Container)
if c.padded {
chromeBox = chromeBox.Objects[0].(*fyne.Container) // the padded container
}
if len(chromeBox.Objects) > 1 {
c.windowHead.Resize(fyne.NewSize(areaSize.Width, topHeight))
offset = fyne.NewPos(0, topHeight)
areaSize = areaSize.Subtract(offset)
Expand Down
2 changes: 1 addition & 1 deletion internal/painter/font.go
Expand Up @@ -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)
}

Expand Down
37 changes: 36 additions & 1 deletion internal/test/util.go
Expand Up @@ -8,6 +8,7 @@ import (
"math"
"os"
"path/filepath"
"runtime"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -40,6 +41,13 @@ func AssertImageMatches(t *testing.T, masterFilename string, img image.Image, ms
masterPix := pixelsForImage(t, raw) // let's just compare the pixels directly
capturePix := pixelsForImage(t, img)

// On darwin/arm64, there are slight differences in the rendering.
// Use a slower, more lenient comparison. If that fails,
// fall back to the strict comparison for a more detailed error message.
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" && pixCloseEnough(masterPix, capturePix) {
return true
}

var msg string
if len(msgAndArgs) > 0 {
msg = fmt.Sprintf(msgAndArgs[0].(string)+"\n", msgAndArgs[1:]...)
Expand All @@ -51,6 +59,33 @@ func AssertImageMatches(t *testing.T, masterFilename string, img image.Image, ms
return true
}

// pixCloseEnough reports whether a and b are mostly the same.
func pixCloseEnough(a, b []uint8) bool {
if len(a) != len(b) {
return false
}
mismatches := 0

for i, v := range a {
w := b[i]
if v == w {
continue
}
// Allow a small delta for rendering variation.
delta := int(v) - int(w) // use int to avoid overflow
if delta < 0 {
delta *= -1
}
if delta > 4 {
return false
}
mismatches++
}

// Allow up to 1% of pixels to mismatch.
return mismatches < len(a)/100
}

// NewCheckedImage returns a new black/white checked image with the specified size
// and the specified amount of horizontal and vertical tiles.
func NewCheckedImage(w, h, hTiles, vTiles int) image.Image {
Expand Down Expand Up @@ -83,7 +118,7 @@ func pixelsForImage(t *testing.T, img image.Image) []uint8 {
}

func writeImage(path string, img image.Image) error {
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return err
}
f, err := os.Create(path)
Expand Down

0 comments on commit e332a5e

Please sign in to comment.