1
1
package flutter
2
2
3
3
import (
4
+ "encoding/json"
4
5
"fmt"
6
+ "runtime"
7
+ "sync"
5
8
"unsafe"
6
9
7
10
"github.com/go-flutter-desktop/go-flutter/embedder"
@@ -26,6 +29,9 @@ type windowManager struct {
26
29
27
30
// caching of ppsc to avoid re-calculating every event
28
31
pixelsPerScreenCoordinate float64
32
+
33
+ // sync.Once to limit pixelRatio warning messages.
34
+ oncePrintPixelRatioLimit sync.Once
29
35
}
30
36
31
37
func newWindowManager (forcedPixelRatio float64 ) * windowManager {
@@ -202,8 +208,11 @@ func (m *windowManager) glfwRefreshCallback(window *glfw.Window) {
202
208
if m .forcedPixelRatio != 0 {
203
209
pixelRatio = m .forcedPixelRatio
204
210
} else {
205
- xscale , _ := window .GetContentScale ()
206
- pixelRatio = float64 (xscale )
211
+ if runtime .GOOS == "linux" {
212
+ pixelRatio = m .getPixelRatioLinux (window )
213
+ } else {
214
+ pixelRatio = m .getPixelRatioOther (window )
215
+ }
207
216
}
208
217
209
218
event := embedder.WindowMetricsEvent {
@@ -217,3 +226,81 @@ func (m *windowManager) glfwRefreshCallback(window *glfw.Window) {
217
226
218
227
flutterEngine .SendWindowMetricsEvent (event )
219
228
}
229
+
230
+ // getPixelRatioOther, getPixelRatioLinux isn't well working on other platform.
231
+ // GLFW window.GetContentScale() works better:
232
+ // https://github.com/go-flutter-desktop/go-flutter/pull/458
233
+ func (m * windowManager ) getPixelRatioOther (window * glfw.Window ) float64 {
234
+ xscale , _ := window .GetContentScale ()
235
+ return float64 (xscale )
236
+ }
237
+
238
+ // getPixelRatioLinux returns the Flutter pixel_ratio is defined as DPI/dp
239
+ // given framebuffer size and the current window information.
240
+ // Same as defined in the official LINUX embedder:
241
+ // https://github.com/flutter/engine/blob/master/shell/platform/glfw/flutter_glfw.cc
242
+ // Fallback to getPixelRatioOther if error occur.
243
+ func (m * windowManager ) getPixelRatioLinux (window * glfw.Window ) float64 {
244
+ widthPx , heightPx := window .GetFramebufferSize ()
245
+ width , _ := window .GetSize ()
246
+
247
+ var selectedMonitor * glfw.Monitor
248
+ winX , winY := window .GetPos ()
249
+ winCenterX , winCenterY := winX + widthPx / 2 , winY + heightPx / 2
250
+
251
+ monitors := glfw .GetMonitors ()
252
+ for _ , monitor := range monitors {
253
+ monX1 , monY1 := monitor .GetPos ()
254
+ monMode := monitor .GetVideoMode ()
255
+ if monMode == nil {
256
+ continue
257
+ }
258
+ monX2 , monY2 := monX1 + monMode .Width , monY1 + monMode .Height
259
+ if (monX1 <= winCenterX && winCenterX <= monX2 ) &&
260
+ (monY1 <= winCenterY && winCenterY <= monY2 ) {
261
+ selectedMonitor = monitor
262
+ break
263
+ }
264
+ }
265
+
266
+ if selectedMonitor == nil {
267
+ // when no monitor was selected, try fallback to primary monitor
268
+ // TODO: ? perhaps select monitor that is "closest" to the window ?
269
+ selectedMonitor = glfw .GetPrimaryMonitor ()
270
+ }
271
+ if selectedMonitor == nil {
272
+ return m .getPixelRatioOther (window )
273
+ }
274
+ selectedMonitorMode := selectedMonitor .GetVideoMode ()
275
+ if selectedMonitorMode == nil {
276
+ return m .getPixelRatioOther (window )
277
+ }
278
+ selectedMonitorWidthMM , _ := selectedMonitor .GetPhysicalSize ()
279
+ if selectedMonitorWidthMM == 0 {
280
+ return m .getPixelRatioOther (window )
281
+ }
282
+ monitorScreenCoordinatesPerInch := float64 (selectedMonitorMode .Width ) / (float64 (selectedMonitorWidthMM ) / 25.4 )
283
+
284
+ dpi := m .pixelsPerScreenCoordinate * monitorScreenCoordinatesPerInch
285
+ pixelRatio := dpi / dpPerInch
286
+
287
+ // Limit the ratio to 1 to avoid rendering a smaller UI in standard resolution monitors.
288
+ if pixelRatio < 1.0 {
289
+ m .oncePrintPixelRatioLimit .Do (func () {
290
+ metrics := map [string ]interface {}{
291
+ "ppsc" : m .pixelsPerScreenCoordinate ,
292
+ "windowWidthPx" : widthPx ,
293
+ "windowWidthSc" : width ,
294
+ "mscpi" : monitorScreenCoordinatesPerInch ,
295
+ "dpi" : dpi ,
296
+ "pixelRatio" : pixelRatio ,
297
+ "monitorWidthMm" : selectedMonitorWidthMM ,
298
+ "monitorWidthSc" : selectedMonitorMode .Width ,
299
+ }
300
+ metricsBytes , _ := json .Marshal (metrics )
301
+ fmt .Println ("go-flutter: calculated pixelRatio limited to a minimum of 1.0. metrics: " + string (metricsBytes ))
302
+ })
303
+ pixelRatio = 1.0
304
+ }
305
+ return pixelRatio
306
+ }
0 commit comments