diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 60ebc1ab5..83fcff7ee 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -20,6 +20,14 @@ func main() { log.Println("ApplicationDidFinishLaunching") }) + currentWindow := func(fn func(window *application.Window)) { + if app.CurrentWindow() != nil { + fn(app.CurrentWindow()) + } else { + println("Current Window is nil") + } + } + // Create a custom menu menu := app.NewMenu() menu.AddRole(application.AppMenu) @@ -43,54 +51,73 @@ func main() { // Disabled menu item adjustMenu := menu.AddSubmenu("Adjust") adjustMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.SetPosition(0, 0) - } + }) }) adjustMenu.Add("Set Position (Random)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.SetPosition(rand.Intn(1000), rand.Intn(800)) - } + }) }) adjustMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.SetSize(800, 600) - } + }) }) + adjustMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.SetSize(rand.Intn(800)+200, rand.Intn(600)+200) - } + }) + }) + adjustMenu.Add("Set Min Size (200,200)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetMinSize(200, 200) + }) + }) + adjustMenu.Add("Set Max Size (600,600)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetMaxSize(600, 600) + }) + }) + adjustMenu.Add("Reset Min Size").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetMinSize(0, 0) + }) + }) + + adjustMenu.Add("Reset Max Size").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetMaxSize(0, 0) + }) }) adjustMenu.Add("Center").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.Center() - } + }) }) adjustMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.Minimise() time.Sleep(2 * time.Second) w.Restore() - } + }) }) adjustMenu.Add("Maximise").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.Maximise() - } + }) + }) + adjustMenu.Add("Fullscreen").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.Fullscreen() + }) }) adjustMenu.Add("Restore").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.Restore() - } + }) }) app.NewWindow() diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 4a8d613b5..6a90dc2d8 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -18,10 +18,6 @@ type ( setMinSize(width, height int) setMaxSize(width, height int) execJS(js string) - setFullscreen() - isMinimised() bool - isMaximised() bool - isFullscreen() bool restore() setBackgroundColour(color *options.RGBA) run() @@ -45,9 +41,15 @@ type ( setPosition(x int, y int) on(eventID uint) minimise() - maximise() unminimise() + maximise() unmaximise() + fullscreen() + unfullscreen() + isMinimised() bool + isMaximised() bool + isFullscreen() bool + disableSizeConstraints() } ) @@ -96,6 +98,10 @@ func (w *Window) SetTitle(title string) *Window { } func (w *Window) SetSize(width, height int) *Window { + // Don't set size if fullscreen + if w.IsFullscreen() { + return w + } w.options.Width = width w.options.Height = height if w.impl != nil { @@ -144,31 +150,53 @@ func (w *Window) Resizable() bool { func (w *Window) SetMinSize(minWidth, minHeight int) *Window { w.options.MinWidth = minWidth - if w.options.Width < minWidth { - w.options.Width = minWidth - } w.options.MinHeight = minHeight - if w.options.Height < minHeight { - w.options.Height = minHeight + + currentWidth, currentHeight := w.Size() + newWidth, newHeight := currentWidth, currentHeight + + var newSize bool + if minHeight != 0 && currentHeight < minHeight { + newHeight = minHeight + w.options.Height = newHeight + newSize = true + } + if minWidth != 0 && currentWidth < minWidth { + newWidth = minWidth + w.options.Width = newWidth + newSize = true } if w.impl != nil { - w.impl.setSize(w.options.Width, w.options.Height) + if newSize { + w.impl.setSize(newWidth, newHeight) + } w.impl.setMinSize(minWidth, minHeight) } return w } func (w *Window) SetMaxSize(maxWidth, maxHeight int) *Window { - w.options.MinWidth = maxWidth - if w.options.Width > maxWidth { - w.options.Width = maxWidth - } - w.options.MinHeight = maxHeight - if w.options.Height > maxHeight { + w.options.MaxWidth = maxWidth + w.options.MaxHeight = maxHeight + + currentWidth, currentHeight := w.Size() + newWidth, newHeight := currentWidth, currentHeight + + var newSize bool + if maxHeight != 0 && currentHeight > maxHeight { + newHeight = maxHeight w.options.Height = maxHeight + newSize = true + } + if maxWidth != 0 && currentWidth > maxWidth { + newWidth = maxWidth + w.options.Width = maxWidth + newSize = true } if w.impl != nil { - w.impl.setSize(w.options.Width, w.options.Height) + if newSize { + w.impl.setSize(newWidth, newHeight) + } w.impl.setMaxSize(maxWidth, maxHeight) } return w @@ -181,13 +209,14 @@ func (w *Window) ExecJS(js string) { w.impl.execJS(js) } -func (w *Window) SetFullscreen() *Window { +func (w *Window) Fullscreen() *Window { if w.impl == nil { w.options.StartState = options.WindowStateFullscreen return w } if !w.IsFullscreen() { - w.impl.setFullscreen() + w.disableSizeConstraints() + w.impl.fullscreen() } return w } @@ -208,8 +237,8 @@ func (w *Window) IsMaximised() bool { return w.impl.isMaximised() } -// Size returns the current size of the window -func (w *Window) Size() (int, int) { +// Size returns the size of the window +func (w *Window) Size() (width int, height int) { if w.impl == nil { return 0, 0 } @@ -407,15 +436,53 @@ func (w *Window) Maximise() *Window { return w } +func (w *Window) UnMinimise() { + if w.impl == nil { + return + } + w.impl.unminimise() +} + +func (w *Window) UnMaximise() { + if w.impl == nil { + return + } + w.enableConstraints() + w.impl.unmaximise() +} + +func (w *Window) UnFullscreen() { + if w.impl == nil { + return + } + w.enableConstraints() + w.impl.unfullscreen() +} + func (w *Window) Restore() { if w.impl == nil { return } if w.IsMinimised() { - w.impl.unminimise() + w.UnMinimise() } else if w.IsMaximised() { - w.impl.unmaximise() + w.UnMaximise() } else if w.IsFullscreen() { - w.impl.toggleFullscreen() + w.UnFullscreen() } } + +func (w *Window) disableSizeConstraints() { + if w.impl == nil { + return + } + w.impl.disableSizeConstraints() +} + +func (w *Window) enableConstraints() { + if w.impl == nil { + return + } + w.SetMinSize(w.options.MinWidth, w.options.MinHeight) + w.SetMaxSize(w.options.MaxWidth, w.options.MaxHeight) +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index c2e307dab..b0bc30fa4 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -117,13 +117,11 @@ void windowSetTitle(void* nsWindow, char* title) { void windowSetSize(void* nsWindow, int width, int height) { // Set window size on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentSize:NSMakeSize(width, height)]; - NSRect frame = [(NSWindow*)nsWindow frame]; - frame.size.width = width; - frame.size.height = height; - [(NSWindow*)nsWindow setFrame:frame display:YES animate:YES]; + NSWindow* window = (NSWindow*)nsWindow; + NSSize contentSize = [window contentRectForFrameRect:NSMakeRect(0, 0, width, height)].size; + [window setContentSize:contentSize]; + [window setFrame:NSMakeRect(window.frame.origin.x, window.frame.origin.y, width, height) display:YES animate:YES]; }); - } // Show the NSWindow @@ -178,7 +176,11 @@ void windowSetResizable(void* nsWindow, bool resizable) { void windowSetMinSize(void* nsWindow, int width, int height) { // Set window min size on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentMinSize:NSMakeSize(width, height)]; + NSWindow* window = (NSWindow*)nsWindow; + NSSize contentSize = [window contentRectForFrameRect:NSMakeRect(0, 0, width, height)].size; + [window setContentMinSize:contentSize]; + NSSize size = { width, height }; + [window setMinSize:size]; }); } @@ -186,22 +188,13 @@ void windowSetMinSize(void* nsWindow, int width, int height) { void windowSetMaxSize(void* nsWindow, int width, int height) { // Set window max size on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentMaxSize:NSMakeSize(width, height)]; - }); -} - -// Reset NSWindow min and max size -void windowResetMinSize(void* nsWindow) { - // Reset window min size on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentMinSize:NSMakeSize(0, 0)]; - }); -} - -void windowResetMaxSize(void* nsWindow) { - // Reset window max size on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentMaxSize:NSMakeSize(0, 0)]; + NSSize size = { FLT_MAX, FLT_MAX }; + size.width = width > 0 ? width : FLT_MAX; + size.height = height > 0 ? height : FLT_MAX; + NSWindow* window = (NSWindow*)nsWindow; + NSSize contentSize = [window contentRectForFrameRect:NSMakeRect(0, 0, size.width, size.height)].size; + [window setContentMaxSize:contentSize]; + [window setMaxSize:size]; }); } @@ -332,6 +325,18 @@ void windowSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) { }); } +bool windowIsMaximised(void* nsWindow) { + return [(NSWindow*)nsWindow isZoomed]; +} + +bool windowIsFullscreen(void* nsWindow) { + return [(NSWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen; +} + +bool windowIsMinimised(void* nsWindow) { + return [(NSWindow*)nsWindow isMiniaturized]; +} + // toggle fullscreen void windowToggleFullscreen(void* nsWindow) { // Toggle fullscreen on main thread @@ -341,8 +346,17 @@ void windowToggleFullscreen(void* nsWindow) { } // Set Window fullscreen -void windowSetFullscreen(void* nsWindow) { - // Set window fullscreen on main thread +void windowFullscreen(void* nsWindow) { + if( windowIsFullscreen(nsWindow) ) { + return; + } + windowToggleFullscreen(nsWindow); +} + +void windowUnFullscreen(void* nsWindow) { + if( !windowIsFullscreen(nsWindow) ) { + return; + } dispatch_async(dispatch_get_main_queue(), ^{ [(NSWindow*)nsWindow toggleFullScreen:nil]; }); @@ -367,18 +381,6 @@ void windowRestore(void* nsWindow) { }); } -bool windowIsMaximised(void* nsWindow) { - return [(NSWindow*)nsWindow isZoomed]; -} - -bool windowIsFullscreen(void* nsWindow) { - return [(NSWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen; -} - -bool windowIsMinimised(void* nsWindow) { - return [(NSWindow*)nsWindow isMiniaturized]; -} - // Set the titlebar style void windowSetTitleBarAppearsTransparent(void* nsWindow, bool transparent) { // Set window titlebar style on main thread @@ -663,6 +665,16 @@ static void windowUnmaximise(void *window) { }); } +static void windowDisableSizeConstraints(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* nsWindow = (NSWindow*)window; + // disable size constraints + [nsWindow setContentMinSize:CGSizeZero]; + [nsWindow setContentMaxSize:CGSizeZero]; + }); +} + */ import "C" import ( @@ -681,6 +693,18 @@ type macosWindow struct { parent *Window } +func (w *macosWindow) disableSizeConstraints() { + C.windowDisableSizeConstraints(w.nsWindow) +} + +func (w *macosWindow) unfullscreen() { + C.windowUnFullscreen(w.nsWindow) +} + +func (w *macosWindow) fullscreen() { + C.windowFullscreen(w.nsWindow) +} + func (w *macosWindow) unminimise() { C.windowUnminimise(w.nsWindow) } @@ -786,10 +810,6 @@ func (w *macosWindow) restore() { C.windowRestore(w.nsWindow) } -func (w *macosWindow) setFullscreen() { - C.windowSetFullscreen(w.nsWindow) -} - func (w *macosWindow) restoreWindow() { C.windowRestore(w.nsWindow) } @@ -931,7 +951,7 @@ func (w *macosWindow) run() { case options.WindowStateMinimised: w.minimise() case options.WindowStateFullscreen: - w.setFullscreen() + w.fullscreen() } C.windowCenter(w.nsWindow)