mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
Added monitor cache and scale cache (#731)
This commit is contained in:
parent
b396b4f88a
commit
5e70fce639
@ -19,11 +19,14 @@
|
||||
package devicescale
|
||||
|
||||
import (
|
||||
"math"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
type desktop int
|
||||
@ -37,6 +40,29 @@ const (
|
||||
desktopXfce
|
||||
)
|
||||
|
||||
var (
|
||||
cachedScale uint64 // use atomic to read/write as multiple goroutines touch it.
|
||||
cacheUpdateWait = time.Millisecond * 100
|
||||
)
|
||||
|
||||
func init() {
|
||||
go scaleUpdater()
|
||||
}
|
||||
|
||||
func impl(x, y int) float64 {
|
||||
return math.Float64frombits(atomic.LoadUint64(&cachedScale))
|
||||
}
|
||||
|
||||
// run as goroutine. Will keep the desktop scale up to date.
|
||||
// This can be removed once the scale change event is implemented in GLFW 3.3
|
||||
func scaleUpdater() {
|
||||
for {
|
||||
s := getscale(0, 0)
|
||||
atomic.StoreUint64(&cachedScale, math.Float64bits(s))
|
||||
time.Sleep(cacheUpdateWait)
|
||||
}
|
||||
}
|
||||
|
||||
func currentDesktop() desktop {
|
||||
tokens := strings.Split(os.Getenv("XDG_CURRENT_DESKTOP"), ":")
|
||||
switch tokens[len(tokens)-1] {
|
||||
@ -95,30 +121,24 @@ func cinnamonScale() float64 {
|
||||
return float64(s)
|
||||
}
|
||||
|
||||
func impl(x, y int) float64 {
|
||||
// TODO: Can Linux has different scales for multiple monitors?
|
||||
func getscale(x, y int) float64 {
|
||||
s := -1.0
|
||||
switch currentDesktop() {
|
||||
case desktopGnome:
|
||||
s := gnomeScale()
|
||||
if s <= 0 {
|
||||
return 1
|
||||
}
|
||||
return s
|
||||
// TODO: Support wayland and per-monitor scaling https://wiki.gnome.org/HowDoI/HiDpi
|
||||
s = gnomeScale()
|
||||
case desktopCinnamon:
|
||||
s := cinnamonScale()
|
||||
if s <= 0 {
|
||||
return 1
|
||||
}
|
||||
return s
|
||||
s = cinnamonScale()
|
||||
case desktopUnity:
|
||||
// TODO: Implement
|
||||
return 1
|
||||
// TODO: Implement, supports per-monitor scaling
|
||||
case desktopKDE:
|
||||
// TODO: Implement
|
||||
return 1
|
||||
// TODO: Implement, appears to support per-monitor scaling
|
||||
case desktopXfce:
|
||||
// TODO: Implement
|
||||
return 1
|
||||
}
|
||||
return 1
|
||||
if s <= 0 {
|
||||
s = 1
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
@ -76,6 +76,10 @@ func init() {
|
||||
if err := initialize(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
glfw.SetMonitorCallback(func(monitor *glfw.Monitor, event glfw.MonitorEvent) {
|
||||
cacheMonitors()
|
||||
})
|
||||
cacheMonitors()
|
||||
}
|
||||
|
||||
func initialize() error {
|
||||
@ -117,6 +121,44 @@ func initialize() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type cachedMonitor struct {
|
||||
m *glfw.Monitor
|
||||
vm *glfw.VidMode
|
||||
// Pos of monitor in virtual coords
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
// monitors is the monitor list cache for desktop glfw compile targets.
|
||||
// populated by 'cacheMonitors' which is called on init and every
|
||||
// monitor config change event.
|
||||
var monitors []*cachedMonitor
|
||||
|
||||
func cacheMonitors() {
|
||||
monitors = make([]*cachedMonitor, 0, 3)
|
||||
ms := glfw.GetMonitors()
|
||||
for _, m := range ms {
|
||||
x, y := m.GetPos()
|
||||
monitors = append(monitors, &cachedMonitor{
|
||||
m: m,
|
||||
vm: m.GetVideoMode(),
|
||||
x: x,
|
||||
y: y,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// getCachedMonitor returns a monitor for the given window x/y
|
||||
// returns false if monitor is not found.
|
||||
func getCachedMonitor(wx, wy int) (*cachedMonitor, bool) {
|
||||
for _, m := range monitors {
|
||||
if m.x <= wx && wx < m.x+m.vm.Width && m.y <= wy && wy < m.y+m.vm.Height {
|
||||
return m, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func Loop(ch <-chan error) error {
|
||||
currentUI.setRunning(true)
|
||||
if err := mainthread.Loop(ch); err != nil {
|
||||
@ -552,6 +594,10 @@ func (u *userInterface) getScale() float64 {
|
||||
|
||||
// actualScreenScale must be called from the main thread.
|
||||
func (u *userInterface) actualScreenScale() float64 {
|
||||
// Avoid calling monitor.GetPos if we have the monitor position cached already.
|
||||
if cm, ok := getCachedMonitor(u.window.GetPos()); ok {
|
||||
return u.getScale() * devicescale.GetAt(cm.x, cm.y)
|
||||
}
|
||||
return u.getScale() * devicescale.GetAt(u.currentMonitor().GetPos())
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,11 @@ import (
|
||||
|
||||
func glfwScale() float64 {
|
||||
// This function must be called on the main thread.
|
||||
return devicescale.GetAt(currentUI.currentMonitor().GetPos())
|
||||
cm, ok := getCachedMonitor(currentUI.window.GetPos())
|
||||
if !ok {
|
||||
return devicescale.GetAt(currentUI.currentMonitor().GetPos())
|
||||
}
|
||||
return devicescale.GetAt(cm.x, cm.y)
|
||||
}
|
||||
|
||||
func adjustWindowPosition(x, y int) (int, int) {
|
||||
@ -35,14 +39,8 @@ func adjustWindowPosition(x, y int) (int, int) {
|
||||
|
||||
func (u *userInterface) currentMonitorImpl() *glfw.Monitor {
|
||||
// TODO: Return more appropriate display.
|
||||
w := u.window
|
||||
wx, wy := w.GetPos()
|
||||
for _, m := range glfw.GetMonitors() {
|
||||
mx, my := m.GetPos()
|
||||
v := m.GetVideoMode()
|
||||
if mx <= wx && wx < mx+v.Width && my <= wy && wy < my+v.Height {
|
||||
return m
|
||||
}
|
||||
if cm, ok := getCachedMonitor(u.window.GetPos()); ok {
|
||||
return cm.m
|
||||
}
|
||||
return glfw.GetPrimaryMonitor()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user