diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 9f17be321..60ebc1ab5 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -3,12 +3,13 @@ package main import ( _ "embed" "log" + "math/rand" "strconv" + "time" "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" ) func main() { @@ -27,40 +28,78 @@ func main() { // Let's make a "Demo" menu myMenu := menu.AddSubmenu("New") - myMenu.Add("New Blank Window").OnClick(func(ctx *application.Context) { - app.NewWindow().SetTitle("Window " + strconv.Itoa(windowCounter)).Run() - windowCounter++ - }) - myMenu.Add("New Window").OnClick(func(ctx *application.Context) { - app.NewWindow(). - SetTitle("Window " + strconv.Itoa(windowCounter)). - SetBackgroundColour(&options.RGBA{ - Red: 255, - Green: 0, - Blue: 0, - Alpha: 0, - }). - Run() - windowCounter++ - }) - myMenu.Add("New Webview").OnClick(func(ctx *application.Context) { - app.NewWindow(). - SetTitle("Webview " + strconv.Itoa(windowCounter)). - SetURL("https://wails.app"). - Run() - windowCounter++ - }) + + myMenu.Add("New Window"). + SetAccelerator("CmdOrCtrl+N"). + OnClick(func(ctx *application.Context) { + app.NewWindow(). + SetTitle("Window "+strconv.Itoa(windowCounter)). + SetPosition(rand.Intn(1000), rand.Intn(800)). + SetURL("https://wails.io"). + Run() + windowCounter++ + }) // Disabled menu item adjustMenu := menu.AddSubmenu("Adjust") adjustMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { - app.CurrentWindow().SetPosition(0, 0) - windowCounter++ + w := app.CurrentWindow() + if w != nil { + w.SetPosition(0, 0) + } }) + adjustMenu.Add("Set Position (Random)").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + 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 { + w.SetSize(800, 600) + } + }) + adjustMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.SetSize(rand.Intn(800)+200, rand.Intn(600)+200) + } + }) + adjustMenu.Add("Center").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.Center() + } + }) + adjustMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.Minimise() + time.Sleep(2 * time.Second) + w.Restore() + } + }) + adjustMenu.Add("Maximise").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.Maximise() + } + }) + adjustMenu.Add("Restore").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.Restore() + } + }) + + app.NewWindow() + app.SetMenu(menu) err := app.Run() if err != nil { log.Fatal(err) } + } diff --git a/exp/pkg/application/menu_darwin.go b/exp/pkg/application/menu_darwin.go index fccf85559..b14be232a 100644 --- a/exp/pkg/application/menu_darwin.go +++ b/exp/pkg/application/menu_darwin.go @@ -24,6 +24,7 @@ void* createNSMenu(char* label) { menu.title = [NSString stringWithUTF8String:label]; free(label); } + [menu setAutoenablesItems:NO]; return (void*)menu; } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index a7ca3bfc7..4a8d613b5 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -18,8 +18,6 @@ type ( setMinSize(width, height int) setMaxSize(width, height int) execJS(js string) - setMaximised() - setMinimised() setFullscreen() isMinimised() bool isMaximised() bool @@ -46,6 +44,10 @@ type ( setHTML(html string) setPosition(x int, y int) on(eventID uint) + minimise() + maximise() + unminimise() + unmaximise() } ) @@ -179,26 +181,12 @@ func (w *Window) ExecJS(js string) { w.impl.execJS(js) } -func (w *Window) SetMaximized() *Window { - w.options.StartState = options.WindowStateMaximised - if w.impl != nil { - w.impl.setMaximised() - } - return w -} - -// Set Minimized -func (w *Window) SetMinimized() *Window { - w.options.StartState = options.WindowStateMinimised - if w.impl == nil { - w.impl.setMinimised() - } - return w -} - func (w *Window) SetFullscreen() *Window { - w.options.StartState = options.WindowStateFullscreen if w.impl == nil { + w.options.StartState = options.WindowStateFullscreen + return w + } + if !w.IsFullscreen() { w.impl.setFullscreen() } return w @@ -396,3 +384,38 @@ func (w *Window) SetPosition(x, y int) *Window { } return w } + +func (w *Window) Minimise() *Window { + if w.impl == nil { + w.options.StartState = options.WindowStateMinimised + return w + } + if !w.IsMinimised() { + w.impl.minimise() + } + return w +} + +func (w *Window) Maximise() *Window { + if w.impl == nil { + w.options.StartState = options.WindowStateMaximised + return w + } + if !w.IsMaximised() { + w.impl.maximise() + } + return w +} + +func (w *Window) Restore() { + if w.impl == nil { + return + } + if w.IsMinimised() { + w.impl.unminimise() + } else if w.IsMaximised() { + w.impl.unmaximise() + } else if w.IsFullscreen() { + w.impl.toggleFullscreen() + } +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 011846d0a..c2e307dab 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -121,7 +121,7 @@ void windowSetSize(void* nsWindow, int width, int height) { NSRect frame = [(NSWindow*)nsWindow frame]; frame.size.width = width; frame.size.height = height; - [(NSWindow*)nsWindow setFrame:frame display:YES]; + [(NSWindow*)nsWindow setFrame:frame display:YES animate:YES]; }); } @@ -332,14 +332,6 @@ void windowSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) { }); } -// Set Window maximised -void windowSetMaximised(void* nsWindow) { - // Set window maximized on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow zoom:nil]; - }); -} - // toggle fullscreen void windowToggleFullscreen(void* nsWindow) { // Toggle fullscreen on main thread @@ -356,18 +348,6 @@ void windowSetFullscreen(void* nsWindow) { }); } -// Set Window Minimised -void windowSetMinimised(void* nsWindow) { - // Set window minimised on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - // Get screen that the window is on - NSScreen* screen = [(NSWindow*)nsWindow screen]; - NSRect screenRect = [screen frame]; - // Set window to top left corner - [(NSWindow*)nsWindow setFrame:NSMakeRect(0, screenRect.size.height, 0, 0) display:YES]; - }); -} - // restore window to normal size void windowRestore(void* nsWindow) { // Set window normal on main thread @@ -610,14 +590,6 @@ static void windowMiniaturize(void *window) { }); } -// zoom maximizes the window to the screen dimensions -static void windowMaximize(void *window) { - dispatch_async(dispatch_get_main_queue(), ^{ - // maximize window - [(NSWindow*)window zoom:nil]; - }); -} - // webviewRenderHTML renders the given HTML static void windowRenderHTML(void *window, const char *html) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -642,6 +614,55 @@ static void windowInjectCSS(void *window, const char *css) { }); } +static void windowMinimise(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // minimize window + [(NSWindow*)window miniaturize:nil]; + }); +} + +// zoom maximizes the window to the screen dimensions +static void windowMaximise(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // maximize window + [(NSWindow*)window zoom:nil]; + }); +} + +static bool isFullScreen(void *window) { + // get main window + NSWindow* nsWindow = (NSWindow*)window; + long mask = [nsWindow styleMask]; + return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen; +} + +// windowSetFullScreen +static void windowSetFullScreen(void *window, bool fullscreen) { + if (isFullScreen(window)) { + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ + NSWindow* nsWindow = (NSWindow*)window; + [nsWindow toggleFullScreen:nil]; + }); +} + +// windowUnminimise +static void windowUnminimise(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // unminimize window + [(NSWindow*)window deminiaturize:nil]; + }); +} + +// windowUnmaximise +static void windowUnmaximise(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // unmaximize window + [(NSWindow*)window zoom:nil]; + }); +} + */ import "C" import ( @@ -660,6 +681,22 @@ type macosWindow struct { parent *Window } +func (w *macosWindow) unminimise() { + C.windowUnminimise(w.nsWindow) +} + +func (w *macosWindow) unmaximise() { + C.windowUnmaximise(w.nsWindow) +} + +func (w *macosWindow) maximise() { + C.windowMaximise(w.nsWindow) +} + +func (w *macosWindow) minimise() { + C.windowMinimise(w.nsWindow) +} + func (w *macosWindow) on(eventID uint) { C.registerListener(C.uint(eventID)) } @@ -716,19 +753,19 @@ func (w *macosWindow) center() { func (w *macosWindow) isMinimised() bool { return w.syncMainThreadReturningBool(func() bool { - return C.windowIsMinimised(w.nsWindow) == C.bool(true) + return bool(C.windowIsMinimised(w.nsWindow)) }) } func (w *macosWindow) isMaximised() bool { return w.syncMainThreadReturningBool(func() bool { - return C.windowIsMaximised(w.nsWindow) == C.bool(true) + return bool(C.windowIsMaximised(w.nsWindow)) }) } func (w *macosWindow) isFullscreen() bool { return w.syncMainThreadReturningBool(func() bool { - return C.windowIsFullscreen(w.nsWindow) == C.bool(true) + return bool(C.windowIsFullscreen(w.nsWindow)) }) } @@ -749,14 +786,6 @@ func (w *macosWindow) restore() { C.windowRestore(w.nsWindow) } -func (w *macosWindow) setMaximised() { - C.windowSetMaximised(w.nsWindow) -} - -func (w *macosWindow) setMinimised() { - C.windowSetMinimised(w.nsWindow) -} - func (w *macosWindow) setFullscreen() { C.windowSetFullscreen(w.nsWindow) } @@ -898,9 +927,9 @@ func (w *macosWindow) run() { switch w.parent.options.StartState { case options.WindowStateMaximised: - w.setMaximised() + w.maximise() case options.WindowStateMinimised: - w.setMinimised() + w.minimise() case options.WindowStateFullscreen: w.setFullscreen()