mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-11 19:48:54 +01:00
Added monitor cache and scale cache (#731)
This commit is contained in:
parent
b396b4f88a
commit
5e70fce639
@ -19,11 +19,14 @@
|
|||||||
package devicescale
|
package devicescale
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type desktop int
|
type desktop int
|
||||||
@ -37,6 +40,29 @@ const (
|
|||||||
desktopXfce
|
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 {
|
func currentDesktop() desktop {
|
||||||
tokens := strings.Split(os.Getenv("XDG_CURRENT_DESKTOP"), ":")
|
tokens := strings.Split(os.Getenv("XDG_CURRENT_DESKTOP"), ":")
|
||||||
switch tokens[len(tokens)-1] {
|
switch tokens[len(tokens)-1] {
|
||||||
@ -95,30 +121,24 @@ func cinnamonScale() float64 {
|
|||||||
return float64(s)
|
return float64(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func impl(x, y int) float64 {
|
func getscale(x, y int) float64 {
|
||||||
// TODO: Can Linux has different scales for multiple monitors?
|
s := -1.0
|
||||||
switch currentDesktop() {
|
switch currentDesktop() {
|
||||||
case desktopGnome:
|
case desktopGnome:
|
||||||
s := gnomeScale()
|
// TODO: Support wayland and per-monitor scaling https://wiki.gnome.org/HowDoI/HiDpi
|
||||||
if s <= 0 {
|
s = gnomeScale()
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
case desktopCinnamon:
|
case desktopCinnamon:
|
||||||
s := cinnamonScale()
|
s = cinnamonScale()
|
||||||
if s <= 0 {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
case desktopUnity:
|
case desktopUnity:
|
||||||
// TODO: Implement
|
// TODO: Implement, supports per-monitor scaling
|
||||||
return 1
|
|
||||||
case desktopKDE:
|
case desktopKDE:
|
||||||
// TODO: Implement
|
// TODO: Implement, appears to support per-monitor scaling
|
||||||
return 1
|
|
||||||
case desktopXfce:
|
case desktopXfce:
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
return 1
|
if s <= 0 {
|
||||||
|
s = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,10 @@ func init() {
|
|||||||
if err := initialize(); err != nil {
|
if err := initialize(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
glfw.SetMonitorCallback(func(monitor *glfw.Monitor, event glfw.MonitorEvent) {
|
||||||
|
cacheMonitors()
|
||||||
|
})
|
||||||
|
cacheMonitors()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initialize() error {
|
func initialize() error {
|
||||||
@ -117,6 +121,44 @@ func initialize() error {
|
|||||||
return nil
|
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 {
|
func Loop(ch <-chan error) error {
|
||||||
currentUI.setRunning(true)
|
currentUI.setRunning(true)
|
||||||
if err := mainthread.Loop(ch); err != nil {
|
if err := mainthread.Loop(ch); err != nil {
|
||||||
@ -552,6 +594,10 @@ func (u *userInterface) getScale() float64 {
|
|||||||
|
|
||||||
// actualScreenScale must be called from the main thread.
|
// actualScreenScale must be called from the main thread.
|
||||||
func (u *userInterface) actualScreenScale() float64 {
|
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())
|
return u.getScale() * devicescale.GetAt(u.currentMonitor().GetPos())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,11 @@ import (
|
|||||||
|
|
||||||
func glfwScale() float64 {
|
func glfwScale() float64 {
|
||||||
// This function must be called on the main thread.
|
// This function must be called on the main thread.
|
||||||
|
cm, ok := getCachedMonitor(currentUI.window.GetPos())
|
||||||
|
if !ok {
|
||||||
return devicescale.GetAt(currentUI.currentMonitor().GetPos())
|
return devicescale.GetAt(currentUI.currentMonitor().GetPos())
|
||||||
|
}
|
||||||
|
return devicescale.GetAt(cm.x, cm.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adjustWindowPosition(x, y int) (int, int) {
|
func adjustWindowPosition(x, y int) (int, int) {
|
||||||
@ -35,14 +39,8 @@ func adjustWindowPosition(x, y int) (int, int) {
|
|||||||
|
|
||||||
func (u *userInterface) currentMonitorImpl() *glfw.Monitor {
|
func (u *userInterface) currentMonitorImpl() *glfw.Monitor {
|
||||||
// TODO: Return more appropriate display.
|
// TODO: Return more appropriate display.
|
||||||
w := u.window
|
if cm, ok := getCachedMonitor(u.window.GetPos()); ok {
|
||||||
wx, wy := w.GetPos()
|
return cm.m
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return glfw.GetPrimaryMonitor()
|
return glfw.GetPrimaryMonitor()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user