[v3 windows] Refactor events + mappings. Fix app.Quit(). Make systray example work slightly better

This commit is contained in:
Lea Anthony 2023-07-05 20:35:45 +10:00
commit f0bf8cd827
No known key found for this signature in database
GPG key ID: 33DAF7BB90A58405
10 changed files with 188 additions and 71 deletions

View file

@ -6,6 +6,7 @@ import (
"github.com/wailsapp/wails/v3/pkg/icons"
"log"
"runtime"
"time"
"github.com/wailsapp/wails/v3/pkg/application"
)
@ -31,12 +32,15 @@ func main() {
},
})
var justClosed bool
window.On(events.Common.WindowLostFocus, func(ctx *application.WindowEventContext) {
window.Hide()
})
app.On(events.Mac.ApplicationDidResignActiveNotification, func() {
window.Hide()
justClosed = true
go func() {
time.Sleep(200 * time.Millisecond)
justClosed = false
}()
})
systemTray := app.NewSystemTray()
@ -79,15 +83,10 @@ func main() {
}
showWindow := func() {
if window.IsVisible() {
window.Hide()
return
}
err := systemTray.PositionWindow(window, 5)
if err != nil {
application.InfoDialog().SetTitle("Error").SetMessage(err.Error()).Show()
if justClosed {
return
}
_ = systemTray.PositionWindow(window, 5)
window.Show().Focus()
}
systemTray.OnClick(showWindow)

View file

@ -534,28 +534,21 @@ func (a *App) CurrentWindow() *WebviewWindow {
}
func (a *App) Quit() {
var wg sync.WaitGroup
wg.Add(2)
go func() {
invokeSync(func() {
a.windowsLock.Lock()
for _, window := range a.windows {
window.Destroy()
}
a.windowsLock.Unlock()
wg.Done()
}()
go func() {
a.systemTraysLock.Lock()
for _, systray := range a.systemTrays {
systray.Destroy()
}
a.systemTraysLock.Unlock()
wg.Done()
}()
wg.Wait()
if a.impl != nil {
a.impl.destroy()
}
if a.impl != nil {
a.impl.destroy()
}
})
}
func (a *App) SetMenu(menu *Menu) {

View file

@ -182,7 +182,8 @@ func (m *windowsApp) run() error {
}
func (m *windowsApp) destroy() {
//C.destroyApp()
// Post a quit message to the main thread
w32.PostQuitMessage(0)
}
func (m *windowsApp) init() {

View file

@ -1,5 +1,7 @@
package application
import "github.com/wailsapp/wails/v3/pkg/events"
type ActivationPolicy int
const (
@ -48,6 +50,8 @@ type MacWindow struct {
TitleBar MacTitleBar
Appearance MacAppearanceType
InvisibleTitleBarHeight int
// Maps events from platform specific to the event name
EventMapping map[events.WindowEventType]events.WindowEventType
}
// MacTitleBar contains options for the Mac titlebar

View file

@ -1,5 +1,7 @@
package application
import "github.com/wailsapp/wails/v3/pkg/events"
type WindowsApplicationOptions struct {
// WndProcInterceptor is a function that will be called for every message sent in the application.
// Use this to hook into the main message loop. This is useful for handling custom window messages.
@ -55,6 +57,9 @@ type WindowsWindow struct {
// Disable the menu bar for this window
DisableMenu bool
// Event mapping for the window
EventMapping map[events.WindowEventType]events.WindowEventType
}
type Theme int

View file

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"github.com/samber/lo"
"runtime"
"strings"
"sync"
"time"
@ -109,6 +110,30 @@ func (w *WebviewWindow) onApplicationEvent(eventType events.ApplicationEventType
w.addCancellationFunction(cancelFn)
}
func (w *WebviewWindow) setupEventMapping() {
var mapping map[events.WindowEventType]events.WindowEventType
switch runtime.GOOS {
case "darwin":
mapping = w.options.Mac.EventMapping
case "windows":
mapping = w.options.Windows.EventMapping
case "linux":
// TBD
}
if mapping == nil {
mapping = events.DefaultWindowEventMapping()
}
for source, target := range mapping {
source := source
target := target
w.On(source, func(ctx *WindowEventContext) {
w.emit(target)
})
}
}
// NewWindow creates a new window with the given options
func NewWindow(options WebviewWindowOptions) *WebviewWindow {
if options.Width == 0 {
@ -128,6 +153,8 @@ func NewWindow(options WebviewWindowOptions) *WebviewWindow {
contextMenus: make(map[string]*Menu),
}
result.setupEventMapping()
// Listen for window closing events and de
result.On(events.Common.WindowClosing, func(ctx *WindowEventContext) {
shouldClose := true

View file

@ -368,8 +368,7 @@ func (w *windowsWebviewWindow) relativePosition() (int, int) {
}
func (w *windowsWebviewWindow) destroy() {
//TODO implement me
panic("implement me")
// Not sure if we have anything to destroy...
}
func (w *windowsWebviewWindow) reload() {
@ -740,11 +739,15 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp
switch msg {
case w32.WM_ACTIVATE:
if int(wparam&0xffff) == w32.WA_INACTIVE {
w.parent.emit(events.Common.WindowLostFocus)
w.parent.emit(events.Windows.WindowInactive)
}
if wparam == w32.WA_ACTIVE || wparam == w32.WA_CLICKACTIVE {
if wparam == w32.WA_ACTIVE {
getNativeApplication().currentWindowID = w.parent.id
w.parent.emit(events.Common.WindowFocus)
w.parent.emit(events.Windows.WindowActive)
}
if wparam == w32.WA_CLICKACTIVE {
getNativeApplication().currentWindowID = w.parent.id
w.parent.emit(events.Windows.WindowClickActive)
}
// If we want to have a frameless window but with the default frame decorations, extend the DWM client area.
// This Option is not affected by returning 0 in WM_NCCALCSIZE.
@ -754,15 +757,15 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp
w32.ExtendFrameIntoClientArea(w.hwnd, true)
}
case w32.WM_CLOSE:
w.parent.emit(events.Common.WindowClosing)
w.parent.emit(events.Windows.WindowClose)
return 0
case w32.WM_KILLFOCUS:
if w.focusingChromium {
return 0
}
w.parent.emit(events.Common.WindowLostFocus)
w.parent.emit(events.Windows.WindowKillFocus)
case w32.WM_SETFOCUS:
w.parent.emit(events.Common.WindowFocus)
w.parent.emit(events.Windows.WindowSetFocus)
case w32.WM_NCLBUTTONDOWN:
w32.SetFocus(w.hwnd)
case w32.WM_MOVE, w32.WM_MOVING:
@ -770,11 +773,11 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp
case w32.WM_SIZE:
switch wparam {
case w32.SIZE_MAXIMIZED:
w.parent.emit(events.Common.WindowMaximise)
w.parent.emit(events.Windows.WindowMaximise)
case w32.SIZE_RESTORED:
w.parent.emit(events.Common.WindowRestore)
w.parent.emit(events.Windows.WindowRestore)
case w32.SIZE_MINIMIZED:
w.parent.emit(events.Common.WindowMinimise)
w.parent.emit(events.Windows.WindowMinimise)
}
if w.parent.options.Frameless && wparam == w32.SIZE_MINIMIZED {
// If the window is frameless, and we are minimizing, then we need to suppress the Resize on the

33
v3/pkg/events/defaults.go Normal file
View file

@ -0,0 +1,33 @@
package events
import "runtime"
var defaultWindowEventMapping = map[string]map[WindowEventType]WindowEventType{
"windows": {
Windows.WindowInactive: Common.WindowLostFocus,
Windows.WindowClickActive: Common.WindowFocus,
Windows.WindowActive: Common.WindowFocus,
Windows.WindowMaximise: Common.WindowMaximise,
Windows.WindowMinimise: Common.WindowMinimise,
Windows.WindowRestore: Common.WindowRestore,
Windows.WindowUnMaximise: Common.WindowUnMaximise,
Windows.WindowUnMinimise: Common.WindowUnMinimise,
Windows.WindowFullscreen: Common.WindowFullscreen,
Windows.WindowUnFullscreen: Common.WindowUnFullscreen,
},
"darwin": {
Mac.WindowDidResignKey: Common.WindowLostFocus,
Mac.WindowDidResignKey: Common.WindowLostFocus,
Mac.WindowDidBecomeKey: Common.WindowFocus,
Mac.WindowDidMiniaturize: Common.WindowMinimise,
Mac.WindowDidDeminiaturize: Common.WindowUnMinimise,
Mac.WindowDidEnterFullScreen: Common.WindowFullscreen,
Mac.WindowDidExitFullScreen: Common.WindowUnFullscreen,
},
"linux": {},
}
func DefaultWindowEventMapping() map[WindowEventType]WindowEventType {
platform := runtime.GOOS
return defaultWindowEventMapping[platform]
}

View file

@ -32,24 +32,24 @@ type commonEvents struct {
func newCommonEvents() commonEvents {
return commonEvents{
ApplicationStarted: 1153,
WindowMaximise: 1154,
WindowUnMaximise: 1155,
WindowFullscreen: 1156,
WindowUnFullscreen: 1157,
WindowRestore: 1158,
WindowMinimise: 1159,
WindowUnMinimise: 1160,
WindowClosing: 1161,
WindowZoom: 1162,
WindowZoomIn: 1163,
WindowZoomOut: 1164,
WindowZoomReset: 1165,
WindowFocus: 1166,
WindowLostFocus: 1167,
WindowShow: 1168,
WindowHide: 1169,
WindowDPIChanged: 1170,
ApplicationStarted: 1166,
WindowMaximise: 1167,
WindowUnMaximise: 1168,
WindowFullscreen: 1169,
WindowUnFullscreen: 1170,
WindowRestore: 1171,
WindowMinimise: 1172,
WindowUnMinimise: 1173,
WindowClosing: 1174,
WindowZoom: 1175,
WindowZoomIn: 1176,
WindowZoomOut: 1177,
WindowZoomReset: 1178,
WindowFocus: 1179,
WindowLostFocus: 1180,
WindowShow: 1181,
WindowHide: 1182,
WindowDPIChanged: 1183,
}
}
@ -317,6 +317,19 @@ type windowsEvents struct {
APMResumeSuspend ApplicationEventType
APMPowerSettingChange ApplicationEventType
WebViewNavigationCompleted WindowEventType
WindowInactive WindowEventType
WindowActive WindowEventType
WindowClickActive WindowEventType
WindowMaximise WindowEventType
WindowUnMaximise WindowEventType
WindowFullscreen WindowEventType
WindowUnFullscreen WindowEventType
WindowRestore WindowEventType
WindowMinimise WindowEventType
WindowUnMinimise WindowEventType
WindowClose WindowEventType
WindowSetFocus WindowEventType
WindowKillFocus WindowEventType
}
func newWindowsEvents() windowsEvents {
@ -328,6 +341,19 @@ func newWindowsEvents() windowsEvents {
APMResumeSuspend: 1150,
APMPowerSettingChange: 1151,
WebViewNavigationCompleted: 1152,
WindowInactive: 1153,
WindowActive: 1154,
WindowClickActive: 1155,
WindowMaximise: 1156,
WindowUnMaximise: 1157,
WindowFullscreen: 1158,
WindowUnFullscreen: 1159,
WindowRestore: 1160,
WindowMinimise: 1161,
WindowUnMinimise: 1162,
WindowClose: 1163,
WindowSetFocus: 1164,
WindowKillFocus: 1165,
}
}
@ -465,22 +491,35 @@ var eventToJS = map[uint]string{
1150: "windows:APMResumeSuspend",
1151: "windows:APMPowerSettingChange",
1152: "windows:WebViewNavigationCompleted",
1153: "common:ApplicationStarted",
1154: "common:WindowMaximise",
1155: "common:WindowUnMaximise",
1156: "common:WindowFullscreen",
1157: "common:WindowUnFullscreen",
1158: "common:WindowRestore",
1159: "common:WindowMinimise",
1160: "common:WindowUnMinimise",
1161: "common:WindowClosing",
1162: "common:WindowZoom",
1163: "common:WindowZoomIn",
1164: "common:WindowZoomOut",
1165: "common:WindowZoomReset",
1166: "common:WindowFocus",
1167: "common:WindowLostFocus",
1168: "common:WindowShow",
1169: "common:WindowHide",
1170: "common:WindowDPIChanged",
1153: "windows:WindowInactive",
1154: "windows:WindowActive",
1155: "windows:WindowClickActive",
1156: "windows:WindowMaximise",
1157: "windows:WindowUnMaximise",
1158: "windows:WindowFullscreen",
1159: "windows:WindowUnFullscreen",
1160: "windows:WindowRestore",
1161: "windows:WindowMinimise",
1162: "windows:WindowUnMinimise",
1163: "windows:WindowClose",
1164: "windows:WindowSetFocus",
1165: "windows:WindowKillFocus",
1166: "common:ApplicationStarted",
1167: "common:WindowMaximise",
1168: "common:WindowUnMaximise",
1169: "common:WindowFullscreen",
1170: "common:WindowUnFullscreen",
1171: "common:WindowRestore",
1172: "common:WindowMinimise",
1173: "common:WindowUnMinimise",
1174: "common:WindowClosing",
1175: "common:WindowZoom",
1176: "common:WindowZoomIn",
1177: "common:WindowZoomOut",
1178: "common:WindowZoomReset",
1179: "common:WindowFocus",
1180: "common:WindowLostFocus",
1181: "common:WindowShow",
1182: "common:WindowHide",
1183: "common:WindowDPIChanged",
}

View file

@ -127,6 +127,19 @@ windows:APMResumeAutomatic
windows:APMResumeSuspend
windows:APMPowerSettingChange
windows:WebViewNavigationCompleted
windows:WindowInactive
windows:WindowActive
windows:WindowClickActive
windows:WindowMaximise
windows:WindowUnMaximise
windows:WindowFullscreen
windows:WindowUnFullscreen
windows:WindowRestore
windows:WindowMinimise
windows:WindowUnMinimise
windows:WindowClose
windows:WindowSetFocus
windows:WindowKillFocus
common:ApplicationStarted
common:WindowMaximise
common:WindowUnMaximise