internal/ui: refactoring: replace *glfw.Monitor with *Monitor

This commit is contained in:
Hajime Hoshi 2023-09-24 02:05:42 +09:00
parent f72b8a4ced
commit 5d5e3c7c0b
6 changed files with 94 additions and 131 deletions

View File

@ -26,13 +26,14 @@ import (
// Monitor is a wrapper around glfw.Monitor. // Monitor is a wrapper around glfw.Monitor.
type Monitor struct { type Monitor struct {
m *glfw.Monitor m *glfw.Monitor
vm *glfw.VidMode videoMode *glfw.VidMode
id int id int
name string name string
x int x int
y int y int
videoModeScale float64
} }
// Name returns the monitor's name. // Name returns the monitor's name.
@ -90,12 +91,13 @@ func (m *monitors) update() {
for i, m := range glfwMonitors { for i, m := range glfwMonitors {
x, y := m.GetPos() x, y := m.GetPos()
newMonitors = append(newMonitors, &Monitor{ newMonitors = append(newMonitors, &Monitor{
m: m, m: m,
vm: m.GetVideoMode(), videoMode: m.GetVideoMode(),
id: i, id: i,
name: m.GetName(), name: m.GetName(),
x: x, x: x,
y: y, y: y,
videoModeScale: videoModeScale(m),
}) })
} }
@ -103,7 +105,6 @@ func (m *monitors) update() {
m.monitors = newMonitors m.monitors = newMonitors
m.m.Unlock() m.m.Unlock()
clearVideoModeScaleCache()
devicescale.ClearCache() devicescale.ClearCache()
atomic.StoreInt32(&m.updateCalled, 1) atomic.StoreInt32(&m.updateCalled, 1)

View File

@ -179,7 +179,7 @@ func initialize() error {
return err return err
} }
if m == nil { if m == nil {
m = glfw.GetPrimaryMonitor() m = theMonitors.monitorFromGLFWMonitor(glfw.GetPrimaryMonitor())
} }
// GetPrimaryMonitor might return nil in theory (#1887). // GetPrimaryMonitor might return nil in theory (#1887).
@ -187,7 +187,7 @@ func initialize() error {
return errors.New("ui: no monitor was found at initialize") return errors.New("ui: no monitor was found at initialize")
} }
theUI.setInitMonitor(theMonitors.monitorFromGLFWMonitor(m)) theUI.setInitMonitor(m)
// Create system cursors. These cursors are destroyed at glfw.Terminate(). // Create system cursors. These cursors are destroyed at glfw.Terminate().
glfwSystemCursors[CursorShapeDefault] = nil glfwSystemCursors[CursorShapeDefault] = nil
@ -211,10 +211,10 @@ func (u *userInterfaceImpl) setInitMonitor(m *Monitor) {
u.initMonitor = m u.initMonitor = m
// TODO: Remove these members. These can be calculated anytime from initMonitor. // TODO: Remove these members. These can be calculated anytime from initMonitor.
u.initDeviceScaleFactor = u.deviceScaleFactor(m.m) u.initDeviceScaleFactor = u.deviceScaleFactor(m)
v := m.vm v := m.videoMode
u.initFullscreenWidthInDIP = int(u.dipFromGLFWMonitorPixel(float64(v.Width), m.m)) u.initFullscreenWidthInDIP = int(u.dipFromGLFWMonitorPixel(float64(v.Width), m))
u.initFullscreenHeightInDIP = int(u.dipFromGLFWMonitorPixel(float64(v.Height), m.m)) u.initFullscreenHeightInDIP = int(u.dipFromGLFWMonitorPixel(float64(v.Height), m))
} }
// AppendMonitors appends the current monitors to the passed in mons slice and returns it. // AppendMonitors appends the current monitors to the passed in mons slice and returns it.
@ -232,11 +232,7 @@ func (u *userInterfaceImpl) Monitor() *Monitor {
if u.isTerminated() { if u.isTerminated() {
return return
} }
glfwMonitor := u.currentMonitor() monitor = u.currentMonitor()
if glfwMonitor == nil {
return
}
monitor = theMonitors.monitorFromGLFWMonitor(glfwMonitor)
}) })
return monitor return monitor
} }
@ -249,7 +245,7 @@ func getMonitorFromPosition(wx, wy int) *Monitor {
for _, m := range theMonitors.append(nil) { for _, m := range theMonitors.append(nil) {
// TODO: Fix incorrectness in the cases of https://github.com/glfw/glfw/issues/1961. // TODO: Fix incorrectness in the cases of https://github.com/glfw/glfw/issues/1961.
// See also internal/devicescale/impl_desktop.go for a maybe better way of doing this. // See also internal/devicescale/impl_desktop.go for a maybe better way of doing this.
if m.x <= wx && wx < m.x+m.vm.Width && m.y <= wy && wy < m.y+m.vm.Height { if m.x <= wx && wx < m.x+m.videoMode.Width && m.y <= wy && wy < m.y+m.videoMode.Height {
return m return m
} }
} }
@ -283,7 +279,7 @@ func (u *userInterfaceImpl) setWindowMonitor(monitor *Monitor) {
} }
// Ignore if it is the same monitor. // Ignore if it is the same monitor.
if monitor.m == u.currentMonitor() { if monitor == u.currentMonitor() {
return return
} }
@ -304,15 +300,14 @@ func (u *userInterfaceImpl) setWindowMonitor(monitor *Monitor) {
} }
} }
w := u.dipToGLFWPixel(float64(ww), monitor.m) w := u.dipToGLFWPixel(float64(ww), monitor)
h := u.dipToGLFWPixel(float64(wh), monitor.m) h := u.dipToGLFWPixel(float64(wh), monitor)
x, y := monitor.x, monitor.y mw := u.dipFromGLFWMonitorPixel(float64(monitor.videoMode.Width), monitor)
mw := u.dipFromGLFWMonitorPixel(float64(monitor.vm.Width), monitor.m) mh := u.dipFromGLFWMonitorPixel(float64(monitor.videoMode.Height), monitor)
mh := u.dipFromGLFWMonitorPixel(float64(monitor.vm.Height), monitor.m) mw = u.dipToGLFWPixel(mw, monitor)
mw = u.dipToGLFWPixel(mw, monitor.m) mh = u.dipToGLFWPixel(mh, monitor)
mh = u.dipToGLFWPixel(mh, monitor.m)
px, py := InitialWindowPosition(int(mw), int(mh), int(w), int(h)) px, py := InitialWindowPosition(int(mw), int(mh), int(w), int(h))
u.window.SetPos(x+px, y+py) u.window.SetPos(monitor.x+px, monitor.y+py)
if fullscreen { if fullscreen {
// Calling setFullscreen immediately might not work well, especially on Linux (#2778). // Calling setFullscreen immediately might not work well, especially on Linux (#2778).
@ -559,9 +554,9 @@ func (u *userInterfaceImpl) ScreenSizeInFullscreen() (int, int) {
if m == nil { if m == nil {
return return
} }
v := m.GetVideoMode() vm := m.videoMode
w = int(u.dipFromGLFWMonitorPixel(float64(v.Width), m)) w = int(u.dipFromGLFWMonitorPixel(float64(vm.Width), m))
h = int(u.dipFromGLFWMonitorPixel(float64(v.Height), m)) h = int(u.dipFromGLFWMonitorPixel(float64(vm.Height), m))
}) })
return w, h return w, h
} }
@ -765,15 +760,14 @@ func (u *userInterfaceImpl) DeviceScaleFactor() float64 {
} }
// deviceScaleFactor must be called from the main thread. // deviceScaleFactor must be called from the main thread.
func (u *userInterfaceImpl) deviceScaleFactor(monitor *glfw.Monitor) float64 { func (u *userInterfaceImpl) deviceScaleFactor(monitor *Monitor) float64 {
// It is rare, but monitor can be nil when glfw.GetPrimaryMonitor returns nil. // It is rare, but monitor can be nil when glfw.GetPrimaryMonitor returns nil.
// In this case, return 1 as a tentative scale (#1878). // In this case, return 1 as a tentative scale (#1878).
if monitor == nil { if monitor == nil {
return 1 return 1
} }
mx, my := monitor.GetPos() return devicescale.GetAt(monitor.x, monitor.y)
return devicescale.GetAt(mx, my)
} }
func init() { func init() {
@ -788,7 +782,7 @@ func init() {
// createWindow must be called from the main thread. // createWindow must be called from the main thread.
// //
// createWindow does not set the position or size so far. // createWindow does not set the position or size so far.
func (u *userInterfaceImpl) createWindow(width, height int, monitor *glfw.Monitor) error { func (u *userInterfaceImpl) createWindow(width, height int, monitor *Monitor) error {
if u.window != nil { if u.window != nil {
panic("ui: u.window must not exist at createWindow") panic("ui: u.window must not exist at createWindow")
} }
@ -800,14 +794,13 @@ func (u *userInterfaceImpl) createWindow(width, height int, monitor *glfw.Monito
} }
// Set our target monitor if provided. This is required to prevent an initial window flash on the default monitor. // Set our target monitor if provided. This is required to prevent an initial window flash on the default monitor.
x, y := monitor.GetPos() vm := monitor.videoMode
vm := monitor.GetVideoMode()
mw := u.dipFromGLFWMonitorPixel(float64(vm.Width), monitor) mw := u.dipFromGLFWMonitorPixel(float64(vm.Width), monitor)
mh := u.dipFromGLFWMonitorPixel(float64(vm.Height), monitor) mh := u.dipFromGLFWMonitorPixel(float64(vm.Height), monitor)
mw = u.dipToGLFWPixel(mw, monitor) mw = u.dipToGLFWPixel(mw, monitor)
mh = u.dipToGLFWPixel(mh, monitor) mh = u.dipToGLFWPixel(mh, monitor)
px, py := InitialWindowPosition(int(mw), int(mh), width, height) px, py := InitialWindowPosition(int(mw), int(mh), width, height)
window.SetPos(x+px, y+py) window.SetPos(monitor.x+px, monitor.y+py)
initializeWindowAfterCreation(window) initializeWindowAfterCreation(window)
@ -1003,9 +996,9 @@ func (u *userInterfaceImpl) initOnMainThread(options *RunOptions) error {
} }
ww, wh := u.getInitWindowSizeInDIP() ww, wh := u.getInitWindowSizeInDIP()
initW := int(u.dipToGLFWPixel(float64(ww), u.initMonitor.m)) initW := int(u.dipToGLFWPixel(float64(ww), u.initMonitor))
initH := int(u.dipToGLFWPixel(float64(wh), u.initMonitor.m)) initH := int(u.dipToGLFWPixel(float64(wh), u.initMonitor))
if err := u.createWindow(initW, initH, u.initMonitor.m); err != nil { if err := u.createWindow(initW, initH, u.initMonitor); err != nil {
return err return err
} }
@ -1026,7 +1019,7 @@ func (u *userInterfaceImpl) initOnMainThread(options *RunOptions) error {
if max := u.initFullscreenHeightInDIP - wh; wy >= max { if max := u.initFullscreenHeightInDIP - wh; wy >= max {
wy = max wy = max
} }
u.setWindowPositionInDIP(wx, wy, u.initMonitor.m) u.setWindowPositionInDIP(wx, wy, u.initMonitor)
u.setWindowSizeInDIP(ww, wh, true) u.setWindowSizeInDIP(ww, wh, true)
// Maximizing a window requires a proper size and position. Call Maximize here (#1117). // Maximizing a window requires a proper size and position. Call Maximize here (#1117).
@ -1070,8 +1063,8 @@ func (u *userInterfaceImpl) outsideSize() (float64, float64) {
// reflecting the adjustment of the view size (#1745). // reflecting the adjustment of the view size (#1745).
var w, h float64 var w, h float64
if m := u.currentMonitor(); m != nil { if m := u.currentMonitor(); m != nil {
v := m.GetVideoMode() vm := m.videoMode
ww, wh := v.Width, v.Height ww, wh := vm.Width, vm.Height
w = u.dipFromGLFWMonitorPixel(float64(ww), m) w = u.dipFromGLFWMonitorPixel(float64(ww), m)
h = u.dipFromGLFWMonitorPixel(float64(wh), m) h = u.dipFromGLFWMonitorPixel(float64(wh), m)
} }
@ -1434,8 +1427,8 @@ func (u *userInterfaceImpl) setFullscreen(fullscreen bool) {
return return
} }
v := m.GetVideoMode() vm := m.videoMode
u.window.SetMonitor(m, 0, 0, v.Width, v.Height, v.RefreshRate) u.window.SetMonitor(m.m, 0, 0, vm.Width, vm.Height, vm.RefreshRate)
} }
u.adjustViewSizeAfterFullscreen() u.adjustViewSizeAfterFullscreen()
return return
@ -1519,20 +1512,20 @@ func (u *userInterfaceImpl) updateVsyncOnRenderThread() {
// currentMonitor returns the current active monitor. // currentMonitor returns the current active monitor.
// //
// currentMonitor must be called on the main thread. // currentMonitor must be called on the main thread.
func (u *userInterfaceImpl) currentMonitor() *glfw.Monitor { func (u *userInterfaceImpl) currentMonitor() *Monitor {
if u.window == nil { if u.window == nil {
return u.initMonitor.m return u.initMonitor
} }
if m := monitorFromWindow(u.window); m != nil { if m := monitorFromWindow(u.window); m != nil {
return m return m
} }
return glfw.GetPrimaryMonitor() return theMonitors.monitorFromGLFWMonitor(glfw.GetPrimaryMonitor())
} }
// monitorFromWindow returns the monitor from the given window. // monitorFromWindow returns the monitor from the given window.
// //
// monitorFromWindow must be called on the main thread. // monitorFromWindow must be called on the main thread.
func monitorFromWindow(window *glfw.Window) *glfw.Monitor { func monitorFromWindow(window *glfw.Window) *Monitor {
// Getting a monitor from a window position is not reliable in general (e.g., when a window is put across // Getting a monitor from a window position is not reliable in general (e.g., when a window is put across
// multiple monitors, or, before SetWindowPosition is called.). // multiple monitors, or, before SetWindowPosition is called.).
// Get the monitor which the current window belongs to. This requires OS API. // Get the monitor which the current window belongs to. This requires OS API.
@ -1542,7 +1535,7 @@ func monitorFromWindow(window *glfw.Window) *glfw.Monitor {
// As the fallback, detect the monitor from the window. // As the fallback, detect the monitor from the window.
if m := getMonitorFromPosition(window.GetPos()); m != nil { if m := getMonitorFromPosition(window.GetPos()); m != nil {
return m.m return m
} }
return nil return nil
@ -1669,13 +1662,13 @@ func (u *userInterfaceImpl) setWindowResizingMode(mode WindowResizingMode) {
// x and y are the position in device-independent pixels. // x and y are the position in device-independent pixels.
// //
// setWindowPositionInDIP must be called from the main thread. // setWindowPositionInDIP must be called from the main thread.
func (u *userInterfaceImpl) setWindowPositionInDIP(x, y int, monitor *glfw.Monitor) { func (u *userInterfaceImpl) setWindowPositionInDIP(x, y int, monitor *Monitor) {
if microsoftgdk.IsXbox() { if microsoftgdk.IsXbox() {
// Do nothing. The position is always fixed. // Do nothing. The position is always fixed.
return return
} }
mx, my := monitor.GetPos() mx, my := monitor.x, monitor.y
xf := u.dipToGLFWPixel(float64(x), monitor) xf := u.dipToGLFWPixel(float64(x), monitor)
yf := u.dipToGLFWPixel(float64(y), monitor) yf := u.dipToGLFWPixel(float64(y), monitor)
if x, y := u.adjustWindowPosition(mx+int(xf), my+int(yf), monitor); u.isFullscreen() { if x, y := u.adjustWindowPosition(mx+int(xf), my+int(yf), monitor); u.isFullscreen() {

View File

@ -184,16 +184,16 @@ func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
return metal.NewGraphics() return metal.NewGraphics()
} }
// clearVideoModeScaleCache must be called from the main thread. // videoModeScale must be called from the main thread.
func clearVideoModeScaleCache() {} func videoModeScale(monitor *glfw.Monitor) float64 {
return 1
}
// dipFromGLFWMonitorPixel must be called from the main thread. func (u *userInterfaceImpl) dipFromGLFWMonitorPixel(x float64, monitor *Monitor) float64 {
func (u *userInterfaceImpl) dipFromGLFWMonitorPixel(x float64, monitor *glfw.Monitor) float64 {
return x return x
} }
// dipFromGLFWPixel must be called from the main thread. func (u *userInterfaceImpl) dipFromGLFWPixel(x float64, monitor *Monitor) float64 {
func (u *userInterfaceImpl) dipFromGLFWPixel(x float64, monitor *glfw.Monitor) float64 {
// NOTE: On macOS, GLFW exposes the device independent coordinate system. // NOTE: On macOS, GLFW exposes the device independent coordinate system.
// Thus, the conversion functions are unnecessary, // Thus, the conversion functions are unnecessary,
// however we still need the deviceScaleFactor internally // however we still need the deviceScaleFactor internally
@ -201,12 +201,11 @@ func (u *userInterfaceImpl) dipFromGLFWPixel(x float64, monitor *glfw.Monitor) f
return x return x
} }
// dipToGLFWPixel must be called from the main thread. func (u *userInterfaceImpl) dipToGLFWPixel(x float64, monitor *Monitor) float64 {
func (u *userInterfaceImpl) dipToGLFWPixel(x float64, monitor *glfw.Monitor) float64 {
return x return x
} }
func (u *userInterfaceImpl) adjustWindowPosition(x, y int, monitor *glfw.Monitor) (int, int) { func (u *userInterfaceImpl) adjustWindowPosition(x, y int, monitor *Monitor) (int, int) {
return x, y return x, y
} }
@ -254,21 +253,21 @@ func currentMouseLocation() (x, y int) {
return int(point.X), int(point.Y) return int(point.X), int(point.Y)
} }
func initialMonitorByOS() (*glfw.Monitor, error) { func initialMonitorByOS() (*Monitor, error) {
x, y := currentMouseLocation() x, y := currentMouseLocation()
// Find the monitor including the cursor. // Find the monitor including the cursor.
for _, m := range theMonitors.append(nil) { for _, m := range theMonitors.append(nil) {
w, h := m.vm.Width, m.vm.Height w, h := m.videoMode.Width, m.videoMode.Height
if x >= m.x && x < m.x+w && y >= m.y && y < m.y+h { if x >= m.x && x < m.x+w && y >= m.y && y < m.y+h {
return m.m, nil return m, nil
} }
} }
return nil, nil return nil, nil
} }
func monitorFromWindowByOS(w *glfw.Window) *glfw.Monitor { func monitorFromWindowByOS(w *glfw.Window) *Monitor {
window := cocoa.NSWindow{ID: objc.ID(w.GetCocoaWindow())} window := cocoa.NSWindow{ID: objc.ID(w.GetCocoaWindow())}
pool := cocoa.NSAutoreleasePool_new() pool := cocoa.NSAutoreleasePool_new()
screen := cocoa.NSScreen_mainScreen() screen := cocoa.NSScreen_mainScreen()
@ -283,7 +282,7 @@ func monitorFromWindowByOS(w *glfw.Window) *glfw.Monitor {
pool.Release() pool.Release()
for _, m := range theMonitors.append(nil) { for _, m := range theMonitors.append(nil) {
if m.m.GetCocoaMonitor() == aID { if m.m.GetCocoaMonitor() == aID {
return m.m return m
} }
} }
return nil return nil

View File

@ -51,39 +51,8 @@ func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
return nil, nil return nil, nil
} }
type videoModeScaleCacheKey struct{ X, Y int }
var videoModeScaleCache = map[videoModeScaleCacheKey]float64{}
// clearVideoModeScaleCache must be called from the main thread.
func clearVideoModeScaleCache() {
for k := range videoModeScaleCache {
delete(videoModeScaleCache, k)
}
}
// videoModeScale must be called from the main thread. // videoModeScale must be called from the main thread.
func videoModeScale(m *glfw.Monitor) float64 { func videoModeScale(m *glfw.Monitor) float64 {
if m == nil {
return 1
}
// Caching wrapper for videoModeScaleUncached as
// videoModeScaleUncached may be expensive (uses blocking calls on X connection)
// and public ScreenSizeInFullscreen API needs the videoModeScale.
monitorX, monitorY := m.GetPos()
cacheKey := videoModeScaleCacheKey{X: monitorX, Y: monitorY}
if cached, ok := videoModeScaleCache[cacheKey]; ok {
return cached
}
scale := videoModeScaleUncached(m)
videoModeScaleCache[cacheKey] = scale
return scale
}
// videoModeScaleUncached must be called from the main thread.
func videoModeScaleUncached(m *glfw.Monitor) float64 {
// TODO: if glfw/glfw#1961 gets fixed, this function may need revising. // TODO: if glfw/glfw#1961 gets fixed, this function may need revising.
// In case GLFW decides to switch to returning logical pixels, we can just return 1. // In case GLFW decides to switch to returning logical pixels, we can just return 1.
@ -142,25 +111,25 @@ func videoModeScaleUncached(m *glfw.Monitor) float64 {
} }
// dipFromGLFWMonitorPixel must be called from the main thread. // dipFromGLFWMonitorPixel must be called from the main thread.
func (u *userInterfaceImpl) dipFromGLFWMonitorPixel(x float64, monitor *glfw.Monitor) float64 { func (u *userInterfaceImpl) dipFromGLFWMonitorPixel(x float64, monitor *Monitor) float64 {
return x / (videoModeScale(monitor) * u.deviceScaleFactor(monitor)) return x / (monitor.videoModeScale * u.deviceScaleFactor(monitor))
} }
// dipFromGLFWPixel must be called from the main thread. // dipFromGLFWPixel must be called from the main thread.
func (u *userInterfaceImpl) dipFromGLFWPixel(x float64, monitor *glfw.Monitor) float64 { func (u *userInterfaceImpl) dipFromGLFWPixel(x float64, monitor *Monitor) float64 {
return x / u.deviceScaleFactor(monitor) return x / u.deviceScaleFactor(monitor)
} }
// dipToGLFWPixel must be called from the main thread. // dipToGLFWPixel must be called from the main thread.
func (u *userInterfaceImpl) dipToGLFWPixel(x float64, monitor *glfw.Monitor) float64 { func (u *userInterfaceImpl) dipToGLFWPixel(x float64, monitor *Monitor) float64 {
return x * u.deviceScaleFactor(monitor) return x * u.deviceScaleFactor(monitor)
} }
func (u *userInterfaceImpl) adjustWindowPosition(x, y int, monitor *glfw.Monitor) (int, int) { func (u *userInterfaceImpl) adjustWindowPosition(x, y int, monitor *Monitor) (int, int) {
return x, y return x, y
} }
func initialMonitorByOS() (*glfw.Monitor, error) { func initialMonitorByOS() (*Monitor, error) {
xconn, err := xgb.NewConn() xconn, err := xgb.NewConn()
if err != nil { if err != nil {
// Assume we're on pure Wayland then. // Assume we're on pure Wayland then.
@ -177,16 +146,16 @@ func initialMonitorByOS() (*glfw.Monitor, error) {
// Find the monitor including the cursor. // Find the monitor including the cursor.
for _, m := range theMonitors.append(nil) { for _, m := range theMonitors.append(nil) {
w, h := m.vm.Width, m.vm.Height w, h := m.videoMode.Width, m.videoMode.Height
if x >= m.x && x < m.x+w && y >= m.y && y < m.y+h { if x >= m.x && x < m.x+w && y >= m.y && y < m.y+h {
return m.m, nil return m, nil
} }
} }
return nil, nil return nil, nil
} }
func monitorFromWindowByOS(_ *glfw.Window) *glfw.Monitor { func monitorFromWindowByOS(_ *glfw.Window) *Monitor {
// TODO: Implement this correctly. (#1119). // TODO: Implement this correctly. (#1119).
return nil return nil
} }

View File

@ -86,30 +86,32 @@ func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
return nil, nil return nil, nil
} }
// clearVideoModeScaleCache must be called from the main thread. // videoModeScale must be called from the main thread.
func clearVideoModeScaleCache() {} func videoModeScale(monitor *glfw.Monitor) float64 {
return 1
}
// dipFromGLFWMonitorPixel must be called from the main thread. // dipFromGLFWMonitorPixel must be called from the main thread.
func (u *userInterfaceImpl) dipFromGLFWMonitorPixel(x float64, monitor *glfw.Monitor) float64 { func (u *userInterfaceImpl) dipFromGLFWMonitorPixel(x float64, monitor *Monitor) float64 {
return x / u.deviceScaleFactor(monitor) return x / u.deviceScaleFactor(monitor)
} }
// dipFromGLFWPixel must be called from the main thread. // dipFromGLFWPixel must be called from the main thread.
func (u *userInterfaceImpl) dipFromGLFWPixel(x float64, monitor *glfw.Monitor) float64 { func (u *userInterfaceImpl) dipFromGLFWPixel(x float64, monitor *Monitor) float64 {
return x / u.deviceScaleFactor(monitor) return x / u.deviceScaleFactor(monitor)
} }
// dipToGLFWPixel must be called from the main thread. // dipToGLFWPixel must be called from the main thread.
func (u *userInterfaceImpl) dipToGLFWPixel(x float64, monitor *glfw.Monitor) float64 { func (u *userInterfaceImpl) dipToGLFWPixel(x float64, monitor *Monitor) float64 {
return x * u.deviceScaleFactor(monitor) return x * u.deviceScaleFactor(monitor)
} }
func (u *userInterfaceImpl) adjustWindowPosition(x, y int, monitor *glfw.Monitor) (int, int) { func (u *userInterfaceImpl) adjustWindowPosition(x, y int, monitor *Monitor) (int, int) {
if microsoftgdk.IsXbox() { if microsoftgdk.IsXbox() {
return x, y return x, y
} }
mx, my := monitor.GetPos() mx, my := monitor.x, monitor.y
// As the video width/height might be wrong, // As the video width/height might be wrong,
// adjust x/y at least to enable to handle the window (#328) // adjust x/y at least to enable to handle the window (#328)
if x < mx { if x < mx {
@ -125,9 +127,9 @@ func (u *userInterfaceImpl) adjustWindowPosition(x, y int, monitor *glfw.Monitor
return x, y return x, y
} }
func initialMonitorByOS() (*glfw.Monitor, error) { func initialMonitorByOS() (*Monitor, error) {
if microsoftgdk.IsXbox() { if microsoftgdk.IsXbox() {
return glfw.GetPrimaryMonitor(), nil return theMonitors.monitorFromGLFWMonitor(glfw.GetPrimaryMonitor()), nil
} }
px, py, err := _GetCursorPos() px, py, err := _GetCursorPos()
@ -141,23 +143,23 @@ func initialMonitorByOS() (*glfw.Monitor, error) {
// Find the monitor including the cursor. // Find the monitor including the cursor.
for _, m := range theMonitors.append(nil) { for _, m := range theMonitors.append(nil) {
w, h := m.vm.Width, m.vm.Height w, h := m.videoMode.Width, m.videoMode.Height
if x >= m.x && x < m.x+w && y >= m.y && y < m.y+h { if x >= m.x && x < m.x+w && y >= m.y && y < m.y+h {
return m.m, nil return m, nil
} }
} }
return nil, nil return nil, nil
} }
func monitorFromWindowByOS(w *glfw.Window) *glfw.Monitor { func monitorFromWindowByOS(w *glfw.Window) *Monitor {
if microsoftgdk.IsXbox() { if microsoftgdk.IsXbox() {
return glfw.GetPrimaryMonitor() return theMonitors.monitorFromGLFWMonitor(glfw.GetPrimaryMonitor())
} }
return monitorFromWin32Window(windows.HWND(w.GetWin32Window())) return monitorFromWin32Window(windows.HWND(w.GetWin32Window()))
} }
func monitorFromWin32Window(w windows.HWND) *glfw.Monitor { func monitorFromWin32Window(w windows.HWND) *Monitor {
// Get the current monitor by the window handle instead of the window position. It is because the window // Get the current monitor by the window handle instead of the window position. It is because the window
// position is not reliable in some cases e.g. when the window is put across multiple monitors. // position is not reliable in some cases e.g. when the window is put across multiple monitors.
@ -175,7 +177,7 @@ func monitorFromWin32Window(w windows.HWND) *glfw.Monitor {
x, y := int(mi.rcMonitor.left), int(mi.rcMonitor.top) x, y := int(mi.rcMonitor.left), int(mi.rcMonitor.top)
for _, m := range theMonitors.append(nil) { for _, m := range theMonitors.append(nil) {
if m.x == x && m.y == y { if m.x == x && m.y == y {
return m.m return m
} }
} }
return nil return nil

View File

@ -264,9 +264,8 @@ func (w *glfwWindow) Position() (int, int) {
wx, wy = w.ui.window.GetPos() wx, wy = w.ui.window.GetPos()
} }
m := w.ui.currentMonitor() m := w.ui.currentMonitor()
mx, my := m.GetPos() wx -= m.x
wx -= mx wy -= m.y
wy -= my
xf := w.ui.dipFromGLFWPixel(float64(wx), m) xf := w.ui.dipFromGLFWPixel(float64(wx), m)
yf := w.ui.dipFromGLFWPixel(float64(wy), m) yf := w.ui.dipFromGLFWPixel(float64(wy), m)
x, y = int(xf), int(yf) x, y = int(xf), int(yf)