From 602d54dc5ef72ff66eba2b2a38da2ba7c9be4d17 Mon Sep 17 00:00:00 2001 From: Larry Clapp Date: Wed, 17 Jun 2020 09:10:48 -0400 Subject: [PATCH] app,app/internal/window: [macOS] add app.Window.Close for closing a window Recently support was added for multiple top-level windows. Add support for closing those windows. macOS only; all others stubbed out. Signed-off-by: Larry Clapp --- app/internal/window/os_android.go | 3 +++ app/internal/window/os_ios.go | 3 +++ app/internal/window/os_js.go | 3 +++ app/internal/window/os_macos.go | 12 ++++++++++++ app/internal/window/os_macos.m | 5 +++++ app/internal/window/os_wayland.go | 3 +++ app/internal/window/os_windows.go | 3 +++ app/internal/window/os_x11.go | 3 +++ app/internal/window/window.go | 3 +++ app/window.go | 11 +++++++++++ 10 files changed, 49 insertions(+) diff --git a/app/internal/window/os_android.go b/app/internal/window/os_android.go index 347c8785..3458b261 100644 --- a/app/internal/window/os_android.go +++ b/app/internal/window/os_android.go @@ -650,6 +650,9 @@ func (w *window) ReadClipboard() { }) } +// Close the window. Not implemented for Android. +func (w *window) Close() {} + // RunOnMain is the exported version of runOnMain without a JNI // environement. func RunOnMain(f func()) { diff --git a/app/internal/window/os_ios.go b/app/internal/window/os_ios.go index 10971892..67bcdde1 100644 --- a/app/internal/window/os_ios.go +++ b/app/internal/window/os_ios.go @@ -299,6 +299,9 @@ func (w *window) ShowTextInput(show bool) { }) } +// Close the window. Not implemented for iOS. +func (w *window) Close() {} + func NewWindow(win Callbacks, opts *Options) error { mainWindow.in <- windowAndOptions{win, opts} return <-mainWindow.errs diff --git a/app/internal/window/os_js.go b/app/internal/window/os_js.go index 3f383256..30255f22 100644 --- a/app/internal/window/os_js.go +++ b/app/internal/window/os_js.go @@ -406,6 +406,9 @@ func (w *window) ShowTextInput(show bool) { }() } +// Close the window. Not implemented for js. +func (w *window) Close() {} + func (w *window) draw(sync bool) { width, height, scale, cfg := w.config() if cfg == (unit.Metric{}) || width == 0 || height == 0 { diff --git a/app/internal/window/os_macos.go b/app/internal/window/os_macos.go index 2378cdb0..df4ca981 100644 --- a/app/internal/window/os_macos.go +++ b/app/internal/window/os_macos.go @@ -44,6 +44,7 @@ __attribute__ ((visibility ("hidden"))) void gio_appTerminate(void); __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createWindow(CFTypeRef viewRef, const char *title, CGFloat width, CGFloat height); __attribute__ ((visibility ("hidden"))) void gio_makeKeyAndOrderFront(CFTypeRef windowRef); __attribute__ ((visibility ("hidden"))) NSPoint gio_cascadeTopLeftFromPoint(CFTypeRef windowRef, NSPoint topLeft); +__attribute__ ((visibility ("hidden"))) void gio_close(CFTypeRef windowRef); */ import "C" @@ -132,6 +133,17 @@ func (w *window) SetAnimating(anim bool) { } } +// Close the window. Only implemented for macOS. +func (w *window) Close() { + runOnMain(func() { + // Make sure the view is still valid. The window might've been closed + // during the switch to the main thread. + if w.view != 0 { + C.gio_close(w.window) + } + }) +} + func (w *window) setStage(stage system.Stage) { if stage == w.stage { return diff --git a/app/internal/window/os_macos.m b/app/internal/window/os_macos.m index 9ff15408..bd7ce288 100644 --- a/app/internal/window/os_macos.m +++ b/app/internal/window/os_macos.m @@ -153,6 +153,11 @@ void gio_appTerminate(void) { } } +void gio_close(CFTypeRef windowRef) { + NSWindow* window = (__bridge NSWindow *)windowRef; + [window performClose:nil]; +} + @implementation GioAppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)]; diff --git a/app/internal/window/os_wayland.go b/app/internal/window/os_wayland.go index c85f177f..50e8aa79 100644 --- a/app/internal/window/os_wayland.go +++ b/app/internal/window/os_wayland.go @@ -1426,6 +1426,9 @@ func (w *window) surface() (*C.struct_wl_surface, int, int) { func (w *window) ShowTextInput(show bool) {} +// Close the window. Not implemented for Wayland. +func (w *window) Close() {} + // detectUIScale reports the system UI scale, or 1.0 if it fails. func detectUIScale() float32 { // TODO: What about other window environments? diff --git a/app/internal/window/os_windows.go b/app/internal/window/os_windows.go index 1279a155..c008f4b4 100644 --- a/app/internal/window/os_windows.go +++ b/app/internal/window/os_windows.go @@ -501,6 +501,9 @@ func (w *window) HWND() (syscall.Handle, int, int) { return w.hwnd, w.width, w.height } +// Close the window. Not implemented for Windows. +func (w *window) Close() {} + func convertKeyCode(code uintptr) (string, bool) { if '0' <= code && code <= '9' || 'A' <= code && code <= 'Z' { return string(rune(code)), true diff --git a/app/internal/window/os_x11.go b/app/internal/window/os_x11.go index fdf7d3a3..4f6706af 100644 --- a/app/internal/window/os_x11.go +++ b/app/internal/window/os_x11.go @@ -110,6 +110,9 @@ func (w *x11Window) WriteClipboard(s string) { func (w *x11Window) ShowTextInput(show bool) {} +// Close the window. Not implemented for X11. +func (w *x11Window) Close() {} + var x11OneByte = make([]byte, 1) func (w *x11Window) wakeup() { diff --git a/app/internal/window/window.go b/app/internal/window/window.go index f4fa7eca..1191d1e2 100644 --- a/app/internal/window/window.go +++ b/app/internal/window/window.go @@ -57,6 +57,9 @@ type Driver interface { ReadClipboard() // WriteClipboard requests a clipboard write. WriteClipboard(s string) + + // Close the window. + Close() } type windowRendezvous struct { diff --git a/app/window.go b/app/window.go index 482e2332..633ea747 100644 --- a/app/window.go +++ b/app/window.go @@ -208,6 +208,17 @@ func (w *Window) WriteClipboard(s string) { }) } +// Close the window. The window's event loop should exit when it receives +// system.DestroyEvent. +// +// Currently, only the macOS driver implements this functionality, all others +// are stubbed. +func (w *Window) Close() { + w.driverDo(func() { + w.driver.Close() + }) +} + // driverDo calls f as soon as the window has a valid driver attached, // or does nothing if the window is destroyed while waiting. func (w *Window) driverDo(f func()) {