diff --git a/internal/ui/ui_glfw.go b/internal/ui/ui_glfw.go index 5799e8966..7a8356f40 100644 --- a/internal/ui/ui_glfw.go +++ b/internal/ui/ui_glfw.go @@ -170,8 +170,12 @@ func initialize() error { glfw.WindowHint(glfw.ClientAPI, glfw.NoAPI) var m *glfw.Monitor - if runtime.GOOS == "darwin" { - m = initialMonitorByOS() + if runtime.GOOS == "darwin" || runtime.GOOS == "windows" { + var err error + m, err = initialMonitorByOS() + if err != nil { + return err + } if m == nil { m = glfw.GetPrimaryMonitor() } @@ -189,7 +193,10 @@ func initialize() error { defer w.Destroy() initializeWindowAfterCreation(w) theUI.waitForFramebufferSizeCallback(w, nil) - m = initialMonitorByOS() + m, err = initialMonitorByOS() + if err != nil { + return err + } if m == nil { m = currentMonitorImpl(w) } diff --git a/internal/ui/ui_glfw_darwin.go b/internal/ui/ui_glfw_darwin.go index 8cece67e8..400d74b88 100644 --- a/internal/ui/ui_glfw_darwin.go +++ b/internal/ui/ui_glfw_darwin.go @@ -158,7 +158,7 @@ func (u *UserInterface) adjustWindowPosition(x, y int) (int, int) { return x, y } -func initialMonitorByOS() *glfw.Monitor { +func initialMonitorByOS() (*glfw.Monitor, error) { var cx, cy C.int C.currentMouseLocation(&cx, &cy) x, y := int(cx), int(cy) @@ -176,11 +176,11 @@ func initialMonitorByOS() *glfw.Monitor { for _, m := range ensureMonitors() { w, h := m.vm.Width, m.vm.Height if x >= m.x && x < m.x+w && y >= m.y && y < m.y+h { - return m.m + return m.m, nil } } - return nil + return nil, nil } func currentMonitorByOS(w *glfw.Window) *glfw.Monitor { diff --git a/internal/ui/ui_glfw_unix.go b/internal/ui/ui_glfw_unix.go index d62d932be..01c4ded63 100644 --- a/internal/ui/ui_glfw_unix.go +++ b/internal/ui/ui_glfw_unix.go @@ -133,8 +133,8 @@ func (u *UserInterface) adjustWindowPosition(x, y int) (int, int) { return x, y } -func initialMonitorByOS() *glfw.Monitor { - return nil +func initialMonitorByOS() (*glfw.Monitor, error) { + return nil, nil } func currentMonitorByOS(_ *glfw.Window) *glfw.Monitor { diff --git a/internal/ui/ui_glfw_windows.go b/internal/ui/ui_glfw_windows.go index 90f709ec7..72f40db12 100644 --- a/internal/ui/ui_glfw_windows.go +++ b/internal/ui/ui_glfw_windows.go @@ -46,12 +46,17 @@ type monitorInfo struct { dwFlags uint32 } +type point struct { + x int32 + y int32 +} + var ( // user32 is defined at hideconsole_windows.go - procGetSystemMetrics = user32.NewProc("GetSystemMetrics") - procGetForegroundWindow = user32.NewProc("GetForegroundWindow") - procMonitorFromWindow = user32.NewProc("MonitorFromWindow") - procGetMonitorInfoW = user32.NewProc("GetMonitorInfoW") + procGetSystemMetrics = user32.NewProc("GetSystemMetrics") + procMonitorFromWindow = user32.NewProc("MonitorFromWindow") + procGetMonitorInfoW = user32.NewProc("GetMonitorInfoW") + procGetCursorPos = user32.NewProc("GetCursorPos") ) func getSystemMetrics(nIndex int) (int32, error) { @@ -64,11 +69,6 @@ func getSystemMetrics(nIndex int) (int32, error) { return int32(r), nil } -func getForegroundWindow() windows.HWND { - r, _, _ := procGetForegroundWindow.Call() - return windows.HWND(r) -} - func monitorFromWindow(hwnd windows.HWND, dwFlags uint32) uintptr { r, _, _ := procMonitorFromWindow.Call(uintptr(hwnd), uintptr(dwFlags)) return r @@ -85,6 +85,18 @@ func getMonitorInfoW(hMonitor uintptr, lpmi *monitorInfo) error { return nil } +func getCursorPos() (int32, int32, error) { + var pt point + r, _, e := procGetCursorPos.Call(uintptr(unsafe.Pointer(&pt))) + if r == 0 { + if e != nil && e != windows.ERROR_SUCCESS { + return 0, 0, fmt.Errorf("ui: GetCursorPos failed: error code: %w", e) + } + return 0, 0, fmt.Errorf("ui: GetCursorPos failed: returned 0") + } + return pt.x, pt.y, nil +} + // clearVideoModeScaleCache must be called from the main thread. func clearVideoModeScaleCache() {} @@ -120,14 +132,22 @@ func (u *UserInterface) adjustWindowPosition(x, y int) (int, int) { return x, y } -func initialMonitorByOS() *glfw.Monitor { - // Get the foreground window, that is common among multiple processes. - w := getForegroundWindow() - if w == 0 { - // GetForegroundWindow can return null according to the document. - return nil +func initialMonitorByOS() (*glfw.Monitor, error) { + px, py, err := getCursorPos() + if err != nil { + return nil, err } - return monitorFromWin32Window(w) + x, y := int(px), int(py) + + // Find the monitor including the cursor. + for _, m := range ensureMonitors() { + w, h := m.vm.Width, m.vm.Height + if x >= m.x && x < m.x+w && y >= m.y && y < m.y+h { + return m.m, nil + } + } + + return nil, nil } func currentMonitorByOS(w *glfw.Window) *glfw.Monitor {