internal/ui: bug fix: wrong monitor initialization on macOS

This change fixes these issues:

* `currentMouseLocation()` returned a position in the macOS native
coordinate. This means the Y axis is upward, while the Y axis is
downward in the GLFW coordinate. This change adjusts the Y position.
* `(*monitors).monitorFromGLFWMonitor` always returned nil at least
on macOS. This change replaces this with a new method
`(*monitors).primaryMonitor`.

Updates #807
Closes #2794
This commit is contained in:
Hajime Hoshi 2023-09-29 12:20:07 +09:00
parent 4ca3fa5e57
commit 0bcee31a6f
3 changed files with 20 additions and 12 deletions

View File

@ -79,16 +79,15 @@ func (m *monitors) append(ms []*Monitor) []*Monitor {
return append(ms, m.monitors...) return append(ms, m.monitors...)
} }
func (m *monitors) monitorFromGLFWMonitor(glfwMonitor *glfw.Monitor) *Monitor { func (m *monitors) primaryMonitor() *Monitor {
if atomic.LoadInt32(&m.updateCalled) == 0 {
panic("ui: (*monitors).primaryMonitor must be called before (*monitors).append is called")
}
m.m.Lock() m.m.Lock()
defer m.m.Unlock() defer m.m.Unlock()
for _, m := range m.monitors { return m.monitors[0]
if m.m == glfwMonitor {
return m
}
}
return nil
} }
func (m *monitors) monitorFromID(id int) *Monitor { func (m *monitors) monitorFromID(id int) *Monitor {

View File

@ -172,7 +172,7 @@ func initialize() error {
return err return err
} }
if m == nil { if m == nil {
m = theMonitors.monitorFromGLFWMonitor(glfw.GetPrimaryMonitor()) m = theMonitors.primaryMonitor()
} }
// GetPrimaryMonitor might return nil in theory (#1887). // GetPrimaryMonitor might return nil in theory (#1887).
@ -1479,7 +1479,7 @@ func (u *userInterfaceImpl) currentMonitor() *Monitor {
return m return m
} }
return theMonitors.monitorFromGLFWMonitor(glfw.GetPrimaryMonitor()) return theMonitors.primaryMonitor()
} }
func (u *userInterfaceImpl) readInputState(inputState *InputState) { func (u *userInterfaceImpl) readInputState(inputState *InputState) {

View File

@ -239,7 +239,7 @@ var (
sel_windowWillExitFullScreen = objc.RegisterName("windowWillExitFullScreen:") sel_windowWillExitFullScreen = objc.RegisterName("windowWillExitFullScreen:")
) )
func currentMouseLocation() (x, y int) { func currentMouseLocationInDIP() (x, y int) {
sig := cocoa.NSMethodSignature_signatureWithObjCTypes("{NSPoint=dd}@:") sig := cocoa.NSMethodSignature_signatureWithObjCTypes("{NSPoint=dd}@:")
inv := cocoa.NSInvocation_invocationWithMethodSignature(sig) inv := cocoa.NSInvocation_invocationWithMethodSignature(sig)
inv.SetTarget(objc.ID(class_NSEvent)) inv.SetTarget(objc.ID(class_NSEvent))
@ -247,11 +247,20 @@ func currentMouseLocation() (x, y int) {
inv.Invoke() inv.Invoke()
var point cocoa.NSPoint var point cocoa.NSPoint
inv.GetReturnValue(unsafe.Pointer(&point)) inv.GetReturnValue(unsafe.Pointer(&point))
return int(point.X), int(point.Y)
// On macOS, the unit of GLFW (OS-native) pixels' scale and device-independent pixels's scale are the same.
// The monitor sizes' scales are also the same.
x, y = int(point.X), int(point.Y)
// On macOS, the Y axis is upward. Adjust the Y position (#807, #2794).
y = -y
m := theMonitors.primaryMonitor()
y += m.videoMode.Height
return x, y
} }
func initialMonitorByOS() (*Monitor, error) { func initialMonitorByOS() (*Monitor, error) {
x, y := currentMouseLocation() x, y := currentMouseLocationInDIP()
// Find the monitor including the cursor. // Find the monitor including the cursor.
for _, m := range theMonitors.append(nil) { for _, m := range theMonitors.append(nil) {