Skip to content

Commit 20288d0

Browse files
authored
Merge pull request #201 from go-flutter-desktop/feature/multi-monitor-dpi
Implement basic multi-monitor DPI support
2 parents 5b6cd49 + f320f78 commit 20288d0

File tree

2 files changed

+48
-20
lines changed

2 files changed

+48
-20
lines changed

application.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ func (a *Application) Run() error {
235235

236236
m.glfwRefreshCallback(a.window)
237237
a.window.SetRefreshCallback(m.glfwRefreshCallback)
238+
a.window.SetPosCallback(m.glfwPosCallback)
238239

239240
a.window.SetKeyCallback(
240241
func(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {

glfw.go

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ func (m *windowManager) glfwScrollCallback(window *glfw.Window, xoff float64, yo
170170
m.sendPointerEventScroll(window, xoff*scrollModifier, yoff*scrollModifier)
171171
}
172172

173+
// glfwPosCallback is called when the window is moved, this directly calls
174+
// glfwRefreshCallback in order to recalculate DPI.
175+
func (m *windowManager) glfwPosCallback(window *glfw.Window, xpos int, ypos int) {
176+
m.glfwRefreshCallback(window)
177+
}
178+
173179
// glfwRefreshCallback is called when the window needs a reresh, this
174180
// can occur when the window is resized, was covered by another window, etc.
175181
// When forcedPixelratio is zero, the forcedPixelratio communicated to the
@@ -188,45 +194,66 @@ func (m *windowManager) glfwRefreshCallback(window *glfw.Window) {
188194
if m.forcedPixelRatio != 0 {
189195
pixelRatio = m.forcedPixelRatio
190196
} else {
191-
// TODO(#74): multi-monitor support
192-
primaryMonitor := glfw.GetPrimaryMonitor()
193-
if primaryMonitor == nil {
197+
var selectedMonitor *glfw.Monitor
198+
winX, winY := window.GetPos()
199+
winCenterX, winCenterY := winX+widthPx/2, winY+heightPx/2
200+
201+
monitors := glfw.GetMonitors()
202+
for _, monitor := range monitors {
203+
monX1, monY1 := monitor.GetPos()
204+
monMode := monitor.GetVideoMode()
205+
if monMode == nil {
206+
continue
207+
}
208+
monX2, monY2 := monX1+monMode.Width, monY1+monMode.Height
209+
if (monX1 <= winCenterX && winCenterX <= monX2) &&
210+
(monY1 <= winCenterY && winCenterY <= monY2) {
211+
selectedMonitor = monitor
212+
break
213+
}
214+
}
215+
216+
if selectedMonitor == nil {
217+
// when no monitor was selected, try fallback to primary monitor
218+
// TODO: ? perhaps select monitor that is "closest" to the window ?
219+
selectedMonitor = glfw.GetPrimaryMonitor()
220+
}
221+
if selectedMonitor == nil {
194222
pixelRatio = 1.0
195223
goto SendWindowMetricsEvent
196224
}
197-
primaryMonitorMode := primaryMonitor.GetVideoMode()
198-
primaryMonitor.GetVideoModes()
199-
if primaryMonitorMode == nil {
225+
selectedMonitorMode := selectedMonitor.GetVideoMode()
226+
if selectedMonitorMode == nil {
200227
pixelRatio = 1.0
201228
goto SendWindowMetricsEvent
202229
}
203-
primaryMonitorWidthMM, _ := primaryMonitor.GetPhysicalSize()
204-
if primaryMonitorWidthMM == 0 {
230+
selectedMonitorWidthMM, _ := selectedMonitor.GetPhysicalSize()
231+
if selectedMonitorWidthMM == 0 {
205232
pixelRatio = 1.0
206233
goto SendWindowMetricsEvent
207234
}
208-
monitorScreenCoordinatesPerInch := float64(primaryMonitorMode.Width) / (float64(primaryMonitorWidthMM) / 25.4)
235+
monitorScreenCoordinatesPerInch := float64(selectedMonitorMode.Width) / (float64(selectedMonitorWidthMM) / 25.4)
209236

210237
dpi := m.pixelsPerScreenCoordinate * monitorScreenCoordinatesPerInch
211238
pixelRatio = dpi / dpPerInch
212239

213240
// Limit the ratio to 1 to avoid rendering a smaller UI in standard resolution monitors.
214241
if pixelRatio < 1.0 {
215-
metrics := map[string]interface{}{
216-
"ppsc": m.pixelsPerScreenCoordinate,
217-
"windowWidthPx": widthPx,
218-
"windowWidthSc": width,
219-
"mscpi": monitorScreenCoordinatesPerInch,
220-
"dpi": dpi,
221-
"pixelRatio": pixelRatio,
222-
"monitorWidthMm": primaryMonitorWidthMM,
223-
"monitorWidthSc": primaryMonitorMode.Width,
224-
}
225-
pixelRatio = 1.0
226242
m.oncePrintPixelRatioLimit.Do(func() {
243+
metrics := map[string]interface{}{
244+
"ppsc": m.pixelsPerScreenCoordinate,
245+
"windowWidthPx": widthPx,
246+
"windowWidthSc": width,
247+
"mscpi": monitorScreenCoordinatesPerInch,
248+
"dpi": dpi,
249+
"pixelRatio": pixelRatio,
250+
"monitorWidthMm": selectedMonitorWidthMM,
251+
"monitorWidthSc": selectedMonitorMode.Width,
252+
}
227253
metricsBytes, _ := json.Marshal(metrics)
228254
fmt.Println("go-flutter: calculated pixelRatio limited to a minimum of 1.0. metrics: " + string(metricsBytes))
229255
})
256+
pixelRatio = 1.0
230257
}
231258
}
232259

0 commit comments

Comments
 (0)