Merge pull request #878 from dweymouth/mac-dock-reopen

Handle click on dock icon to reopen app for Mac
This commit is contained in:
Drew Weymouth
2026-03-30 19:03:47 -07:00
committed by GitHub
4 changed files with 107 additions and 2 deletions
+40
View File
@@ -0,0 +1,40 @@
//go:build darwin
package ui
/*
void installReopenDelegate();
*/
import "C"
import "fyne.io/fyne/v2"
var darwinAppDelegateReopenWindow fyne.Window
// darwinQuitting is set to true when applicationShouldTerminate: fires so
// the close intercept knows to actually close instead of hide.
var darwinQuitting bool
func isRealQuit() bool {
return darwinQuitting
}
func installReopenHandler(w fyne.Window) {
darwinAppDelegateReopenWindow = w
C.installReopenDelegate()
}
//export appReopened
func appReopened() {
if darwinAppDelegateReopenWindow == nil {
return
}
go func() {
fyne.Do(darwinAppDelegateReopenWindow.Show)
}()
}
//export appShouldTerminate
func appShouldTerminate() {
darwinQuitting = true
}
+52
View File
@@ -0,0 +1,52 @@
//go:build darwin
#import <AppKit/AppKit.h>
extern void appReopened(void);
extern void appShouldTerminate(void);
@interface ReopenDelegate : NSObject<NSApplicationDelegate>
@property (nonatomic, strong) id<NSApplicationDelegate> wrapped;
@end
@implementation ReopenDelegate
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
// Set the quitting flag before GLFW's delegate fires close requests for
// each window, so our close intercept knows to close rather than hide.
appShouldTerminate();
if ([self.wrapped respondsToSelector:_cmd]) {
return [self.wrapped applicationShouldTerminate:sender];
}
return NSTerminateNow;
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)app
hasVisibleWindows:(BOOL)hasVisible {
if (!hasVisible) {
appReopened();
}
if ([self.wrapped respondsToSelector:_cmd]) {
return [self.wrapped applicationShouldHandleReopen:app
hasVisibleWindows:hasVisible];
}
return YES;
}
- (BOOL)respondsToSelector:(SEL)sel {
return [super respondsToSelector:sel] ||
[self.wrapped respondsToSelector:sel];
}
- (id)forwardingTargetForSelector:(SEL)sel {
return [self.wrapped respondsToSelector:sel] ? self.wrapped : nil;
}
@end
void installReopenDelegate(void) {
ReopenDelegate *d = [ReopenDelegate new];
d.wrapped = [NSApp delegate];
[NSApp setDelegate:d];
}
+12
View File
@@ -0,0 +1,12 @@
//go:build !darwin
package ui
import "fyne.io/fyne/v2"
func installReopenHandler(w fyne.Window) {
}
func isRealQuit() bool {
return false
}
+3 -2
View File
@@ -61,6 +61,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
Window: fyneApp.NewWindow(displayAppName),
theme: myTheme.NewMyTheme(&app.Config.Theme, app.ThemesDir()),
}
installReopenHandler(m.Window)
fynetooltip.SetToolTipTextSizeName(myTheme.SizeNameSubText)
m.theme.NormalFont = app.Config.Application.FontNormalTTF
@@ -184,7 +185,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
m.Window.SetCloseIntercept(func() {
m.SaveWindowSettings()
if app.Config.Application.CloseToSystemTray && m.HaveSystemTray() {
if (runtime.GOOS == "darwin" && !isRealQuit()) || (app.Config.Application.CloseToSystemTray && m.HaveSystemTray()) {
m.Window.Hide()
} else {
m.Window.Close()
@@ -514,7 +515,7 @@ func (m *MainWindow) addShortcuts() {
m.Controller.SelectAll()
})
m.Canvas().AddShortcut(&shortcuts.ShortcutCloseWindow, func(_ fyne.Shortcut) {
if m.App.Config.Application.CloseToSystemTray && m.HaveSystemTray() {
if runtime.GOOS == "darwin" || (m.App.Config.Application.CloseToSystemTray && m.HaveSystemTray()) {
m.Window.Hide()
}
})