mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
ui: Bug fix: wrong scaling when a window move across monitors
Fixes #701
This commit is contained in:
parent
0e7dab3707
commit
e0d2d5e753
@ -24,7 +24,6 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
logPixelsX = 88
|
logPixelsX = 88
|
||||||
monitorDefaultToNull = 0
|
|
||||||
monitorDefaultToNearest = 2
|
monitorDefaultToNearest = 2
|
||||||
mdtEffectiveDpi = 0
|
mdtEffectiveDpi = 0
|
||||||
)
|
)
|
||||||
@ -178,7 +177,7 @@ func impl(x, y int) float64 {
|
|||||||
|
|
||||||
// MonitorFromPoint requires to pass a POINT value, and there seems no portable way to
|
// MonitorFromPoint requires to pass a POINT value, and there seems no portable way to
|
||||||
// do this with Cgo. Use MonitorFromRect instead.
|
// do this with Cgo. Use MonitorFromRect instead.
|
||||||
m, err := monitorFromRect(uintptr(unsafe.Pointer(&lprc)), monitorDefaultToNull)
|
m, err := monitorFromRect(uintptr(unsafe.Pointer(&lprc)), monitorDefaultToNearest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -774,14 +774,6 @@ func (u *userInterface) currentMonitor() *glfw.Monitor {
|
|||||||
if m := w.GetMonitor(); m != nil {
|
if m := w.GetMonitor(); m != nil {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
// Get the monitor which the current window belongs to. This requires OS API.
|
||||||
wx, wy := w.GetPos()
|
return currentMonitor()
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,25 @@
|
|||||||
|
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
|
// #cgo CFLAGS: -x objective-c
|
||||||
|
// #cgo LDFLAGS: -framework AppKit
|
||||||
|
//
|
||||||
|
// #import <AppKit/AppKit.h>
|
||||||
|
//
|
||||||
|
// static void currentMonitorPos(int* x, int* y) {
|
||||||
|
// NSDictionary* screenDictionary = [[NSScreen mainScreen] deviceDescription];
|
||||||
|
// NSNumber* screenID = [screenDictionary objectForKey:@"NSScreenNumber"];
|
||||||
|
// CGDirectDisplayID aID = [screenID unsignedIntValue];
|
||||||
|
// const CGRect bounds = CGDisplayBounds(aID);
|
||||||
|
// *x = bounds.origin.x;
|
||||||
|
// *y = bounds.origin.y;
|
||||||
|
// }
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-gl/glfw/v3.2/glfw"
|
||||||
|
)
|
||||||
|
|
||||||
func glfwScale() float64 {
|
func glfwScale() float64 {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@ -25,3 +44,16 @@ func glfwScale() float64 {
|
|||||||
func adjustWindowPosition(x, y int) (int, int) {
|
func adjustWindowPosition(x, y int) (int, int) {
|
||||||
return x, y
|
return x, y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func currentMonitor() *glfw.Monitor {
|
||||||
|
x := C.int(0)
|
||||||
|
y := C.int(0)
|
||||||
|
C.currentMonitorPos(&x, &y)
|
||||||
|
for _, m := range glfw.GetMonitors() {
|
||||||
|
mx, my := m.GetPos()
|
||||||
|
if int(x) == mx && int(y) == my {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-gl/glfw/v3.2/glfw"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,3 +32,17 @@ func glfwScale() float64 {
|
|||||||
func adjustWindowPosition(x, y int) (int, int) {
|
func adjustWindowPosition(x, y int) (int, int) {
|
||||||
return x, y
|
return x, y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func currentMonitor() *glfw.Monitor {
|
||||||
|
// TODO: Return more appropriate display.
|
||||||
|
w := glfw.GetCurrentContext()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -16,21 +16,81 @@
|
|||||||
|
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
// TODO: Use golang.org/x/sys/windows (NewLazyDLL) instead of cgo.
|
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lgdi32
|
|
||||||
//
|
|
||||||
// #include <windows.h>
|
|
||||||
//
|
|
||||||
// static int getCaptionHeight() {
|
|
||||||
// return GetSystemMetrics(SM_CYCAPTION);
|
|
||||||
// }
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/go-gl/glfw/v3.2/glfw"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
smCyCaption = 4
|
||||||
|
monitorDefaultToNearest = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type rect struct {
|
||||||
|
left int32
|
||||||
|
top int32
|
||||||
|
right int32
|
||||||
|
bottom int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type monitorInfo struct {
|
||||||
|
cbSize uint32
|
||||||
|
rcMonitor rect
|
||||||
|
rcWork rect
|
||||||
|
dwFlags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// user32 is defined at hideconsole_windows.go
|
||||||
|
procGetSystemMetrics = user32.NewProc("GetSystemMetrics")
|
||||||
|
procGetActiveWindow = user32.NewProc("GetActiveWindow")
|
||||||
|
procMonitorFromWindow = user32.NewProc("MonitorFromWindow")
|
||||||
|
procGetMonitorInfoW = user32.NewProc("GetMonitorInfoW")
|
||||||
|
)
|
||||||
|
|
||||||
|
func getSystemMetrics(nIndex int) (int, error) {
|
||||||
|
r, _, e := syscall.Syscall(procGetSystemMetrics.Addr(), 1, uintptr(nIndex), 0, 0)
|
||||||
|
if e != 0 {
|
||||||
|
return 0, fmt.Errorf("ui: GetSystemMetrics failed: error code: %d", e)
|
||||||
|
}
|
||||||
|
return int(r), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getActiveWindow() (uintptr, error) {
|
||||||
|
r, _, e := syscall.Syscall(procGetActiveWindow.Addr(), 0, 0, 0, 0)
|
||||||
|
if e != 0 {
|
||||||
|
return 0, fmt.Errorf("ui: GetActiveWindow failed: error code: %d", e)
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func monitorFromWindow(hwnd uintptr, dwFlags uint32) (uintptr, error) {
|
||||||
|
r, _, e := syscall.Syscall(procMonitorFromWindow.Addr(), 2, hwnd, uintptr(dwFlags), 0)
|
||||||
|
if e != 0 {
|
||||||
|
return 0, fmt.Errorf("ui: MonitorFromWindow failed: error code: %d", e)
|
||||||
|
}
|
||||||
|
if r == 0 {
|
||||||
|
return 0, fmt.Errorf("ui: MonitorFromWindow failed: returned value: %d", r)
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMonitorInfoW(hMonitor uintptr, lpmi *monitorInfo) error {
|
||||||
|
r, _, e := syscall.Syscall(procGetMonitorInfoW.Addr(), 2, hMonitor, uintptr(unsafe.Pointer(lpmi)), 0)
|
||||||
|
if e != 0 {
|
||||||
|
return fmt.Errorf("ui: GetMonitorInfoW failed: error code: %d", e)
|
||||||
|
}
|
||||||
|
if r == 0 {
|
||||||
|
return fmt.Errorf("ui: GetMonitorInfoW failed: returned value: %d", r)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func glfwScale() float64 {
|
func glfwScale() float64 {
|
||||||
// This function must be called on the main thread.
|
// This function must be called on the main thread.
|
||||||
return devicescale.GetAt(currentUI.currentMonitor().GetPos())
|
return devicescale.GetAt(currentUI.currentMonitor().GetPos())
|
||||||
@ -42,9 +102,43 @@ func adjustWindowPosition(x, y int) (int, int) {
|
|||||||
if x < 0 {
|
if x < 0 {
|
||||||
x = 0
|
x = 0
|
||||||
}
|
}
|
||||||
t := int(C.getCaptionHeight())
|
t, err := getSystemMetrics(smCyCaption)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
if y < t {
|
if y < t {
|
||||||
y = t
|
y = t
|
||||||
}
|
}
|
||||||
return x, y
|
return x, y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func currentMonitor() *glfw.Monitor {
|
||||||
|
w, err := getActiveWindow()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if w == 0 {
|
||||||
|
// There is no window at launching.
|
||||||
|
return glfw.GetPrimaryMonitor()
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := monitorFromWindow(w, monitorDefaultToNearest)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mi := monitorInfo{}
|
||||||
|
mi.cbSize = uint32(unsafe.Sizeof(mi))
|
||||||
|
if err := getMonitorInfoW(m, &mi); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
x, y := int(mi.rcMonitor.left), int(mi.rcMonitor.top)
|
||||||
|
for _, m := range glfw.GetMonitors() {
|
||||||
|
mx, my := m.GetPos()
|
||||||
|
if mx == x && my == y {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user