mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
uidriver: Remove width/height/scale arguments from run
The initial window position is determined on ebiten package side. Updates #943
This commit is contained in:
parent
d07028735f
commit
dabaf66b81
@ -44,6 +44,7 @@ type UI interface {
|
||||
ScreenSizeInFullscreen() (int, int)
|
||||
WindowPosition() (int, int)
|
||||
IsScreenTransparent() bool
|
||||
MonitorPosition() (int, int)
|
||||
CanHaveWindow() bool // TODO: Create a 'Widnow' interface.
|
||||
|
||||
SetCursorMode(mode CursorMode)
|
||||
|
@ -129,14 +129,12 @@ func initialize() error {
|
||||
panic("glfw: glfw.CreateWindow must not return nil")
|
||||
}
|
||||
|
||||
// TODO: Fix this hack. currentMonitor now requires u.window on POSIX.
|
||||
// Create a window and leave it as it is: this affects the result of currentMonitorFromPosition.
|
||||
theUI.window = w
|
||||
theUI.initMonitor = theUI.currentMonitor()
|
||||
v := theUI.initMonitor.GetVideoMode()
|
||||
theUI.initFullscreenWidthInDP = int(theUI.toDeviceIndependentPixel(float64(v.Width)))
|
||||
theUI.initFullscreenHeightInDP = int(theUI.toDeviceIndependentPixel(float64(v.Height)))
|
||||
theUI.window.Destroy()
|
||||
theUI.window = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -568,7 +566,7 @@ func (u *UserInterface) Run(width, height int, scale float64, title string, uico
|
||||
go func() {
|
||||
defer cancel()
|
||||
defer close(ch)
|
||||
if err := u.run(width, height, scale, title, uicontext); err != nil {
|
||||
if err := u.run(title, uicontext); err != nil {
|
||||
ch <- err
|
||||
}
|
||||
}()
|
||||
@ -632,15 +630,12 @@ func (u *UserInterface) createWindow() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) run(width, height int, scale float64, title string, context driver.UIContext) error {
|
||||
var (
|
||||
m *glfw.Monitor
|
||||
mx, my int
|
||||
v *glfw.VidMode
|
||||
ww, wh int
|
||||
)
|
||||
|
||||
func (u *UserInterface) run(title string, context driver.UIContext) error {
|
||||
if err := u.t.Call(func() error {
|
||||
// The window is created at initialize().
|
||||
u.window.Destroy()
|
||||
u.window = nil
|
||||
|
||||
if u.graphics.IsGL() {
|
||||
glfw.WindowHint(glfw.ContextVersionMajor, 2)
|
||||
glfw.WindowHint(glfw.ContextVersionMinor, 1)
|
||||
@ -679,53 +674,16 @@ func (u *UserInterface) run(width, height int, scale float64, title string, cont
|
||||
if i := u.getInitIconImages(); i != nil {
|
||||
u.window.SetIcon(i)
|
||||
}
|
||||
|
||||
// Get the monitor before showing the window.
|
||||
//
|
||||
// On Windows, there are two types of windows:
|
||||
//
|
||||
// active window: The window that has input-focus and attached to the calling thread.
|
||||
// foreground window: The window that has input-focus: this can be in another process
|
||||
//
|
||||
// currentMonitor returns the monitor for the active window when possible and then the monitor for
|
||||
// the foreground window as fallback. In the current situation, the current window is hidden and
|
||||
// there is not the active window but the foreground window. After showing the current window, the
|
||||
// current window will be the active window. Thus, currentMonitor result varies before and after
|
||||
// showing the window.
|
||||
m = u.currentMonitor()
|
||||
mx, my = m.GetPos()
|
||||
v = m.GetVideoMode()
|
||||
|
||||
ww = int(u.toDeviceDependentPixel(float64(width) * scale))
|
||||
wh = int(u.toDeviceDependentPixel(float64(height) * scale))
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The game is in window mode (not fullscreen mode) at the first state.
|
||||
// Don't refer u.initFullscreen here to avoid some GLFW problems.
|
||||
u.setWindowSize(ww, wh, false, u.vsync)
|
||||
u.SetWindowPosition(u.getInitWindowPosition())
|
||||
|
||||
_ = u.t.Call(func() error {
|
||||
// Get the window size before showing it. Showing the window might change the current monitor which
|
||||
// affects deviceDependentWindowSize result.
|
||||
w, h := u.window.GetSize()
|
||||
|
||||
u.title = title
|
||||
u.window.SetTitle(title)
|
||||
|
||||
x, y := u.getInitWindowPosition()
|
||||
if x == invalidPos || y == invalidPos {
|
||||
x = mx + (v.Width-w)/2
|
||||
y = my + (v.Height-h)/3
|
||||
}
|
||||
// Adjusting the position is needed only when the monitor is primary. (#829)
|
||||
if mx == 0 && my == 0 {
|
||||
x, y = adjustWindowPosition(x, y)
|
||||
}
|
||||
u.window.SetPos(x, y)
|
||||
u.window.Show()
|
||||
|
||||
return nil
|
||||
@ -1042,10 +1000,12 @@ func (u *UserInterface) setWindowSize(width, height int, fullscreen bool, vsync
|
||||
//
|
||||
// currentMonitor must be called on the main thread.
|
||||
func (u *UserInterface) currentMonitor() *glfw.Monitor {
|
||||
w := u.window
|
||||
if w := u.window; w != nil {
|
||||
// TODO: When is the monitor nil?
|
||||
if m := w.GetMonitor(); m != nil {
|
||||
return m
|
||||
}
|
||||
}
|
||||
// Get the monitor which the current window belongs to. This requires OS API.
|
||||
return u.currentMonitorFromPosition()
|
||||
}
|
||||
@ -1058,10 +1018,11 @@ func (u *UserInterface) SetWindowPosition(x, y int) {
|
||||
_ = u.t.Call(func() error {
|
||||
xf := u.toDeviceDependentPixel(float64(x))
|
||||
yf := u.toDeviceDependentPixel(float64(y))
|
||||
x, y := adjustWindowPosition(int(xf), int(yf))
|
||||
if u.isFullscreen() {
|
||||
u.origPosX, u.origPosY = int(xf), int(yf)
|
||||
u.origPosX, u.origPosY = x, y
|
||||
} else {
|
||||
u.window.SetPos(int(xf), int(yf))
|
||||
u.window.SetPos(x, y)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@ -1116,6 +1077,23 @@ func (u *UserInterface) SetWindowSize(width, height int) {
|
||||
u.setWindowSize(w, h, u.isFullscreen(), u.vsync)
|
||||
}
|
||||
|
||||
func (u *UserInterface) MonitorPosition() (int, int) {
|
||||
if !u.isRunning() {
|
||||
return u.monitorPosition()
|
||||
}
|
||||
var mx, my int
|
||||
_ = u.t.Call(func() error {
|
||||
mx, my = u.monitorPosition()
|
||||
return nil
|
||||
})
|
||||
return mx, my
|
||||
}
|
||||
|
||||
func (u *UserInterface) monitorPosition() (int, int) {
|
||||
// TODO: toDeviceIndependentPixel might be required.
|
||||
return u.currentMonitor().GetPos()
|
||||
}
|
||||
|
||||
func (u *UserInterface) CanHaveWindow() bool {
|
||||
return true
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
|
||||
x := C.int(0)
|
||||
y := C.int(0)
|
||||
// Note: [NSApp mainWindow] is nil when it doesn't have its border. Use u.window here.
|
||||
if u.window != nil {
|
||||
win := u.window.GetCocoaWindow()
|
||||
C.currentMonitorPos(win, &x, &y)
|
||||
for _, m := range glfw.GetMonitors() {
|
||||
@ -67,6 +68,7 @@ func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
|
||||
return m
|
||||
}
|
||||
}
|
||||
}
|
||||
return glfw.GetPrimaryMonitor()
|
||||
}
|
||||
|
||||
|
1
run.go
1
run.go
@ -156,6 +156,7 @@ func Run(f func(*Image) error, width, height int, scale float64, title string) e
|
||||
}
|
||||
|
||||
theUIContext = newUIContext(game, scale)
|
||||
fixWindowPosition(int(float64(width)*scale), int(float64(height)*scale))
|
||||
if err := uiDriver().Run(width, height, scale, title, theUIContext, graphicsDriver()); err != nil {
|
||||
if err == driver.RegularTermination {
|
||||
return nil
|
||||
|
65
window.go
65
window.go
@ -16,6 +16,13 @@ package ebiten
|
||||
|
||||
import (
|
||||
"image"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
maxInt = int(^uint(0) >> 1)
|
||||
minInt = -maxInt - 1
|
||||
invalidPos = minInt
|
||||
)
|
||||
|
||||
// SetWindowDecorated sets the state if the window is decorated.
|
||||
@ -105,6 +112,9 @@ func SetWindowIcon(iconImages []image.Image) {
|
||||
//
|
||||
// WindowPosition is concurrent-safe.
|
||||
func WindowPosition() (x, y int) {
|
||||
if x, y, ok := initWindowPosition(); ok {
|
||||
return x, y
|
||||
}
|
||||
return uiDriver().WindowPosition()
|
||||
}
|
||||
|
||||
@ -118,5 +128,60 @@ func WindowPosition() (x, y int) {
|
||||
//
|
||||
// SetWindowPosition is concurrent-safe.
|
||||
func SetWindowPosition(x, y int) {
|
||||
if setInitWindowPosition(x, y) {
|
||||
return
|
||||
}
|
||||
uiDriver().SetWindowPosition(x, y)
|
||||
}
|
||||
|
||||
var (
|
||||
windowM sync.Mutex
|
||||
mainLoopStarted bool
|
||||
initWindowPositionX = invalidPos
|
||||
initWindowPositionY = invalidPos
|
||||
)
|
||||
|
||||
func initWindowPosition() (x, y int, ok bool) {
|
||||
windowM.Lock()
|
||||
defer windowM.Unlock()
|
||||
if mainLoopStarted {
|
||||
return 0, 0, false
|
||||
}
|
||||
if initWindowPositionX == invalidPos || initWindowPositionY == invalidPos {
|
||||
return 0, 0, false
|
||||
}
|
||||
return initWindowPositionX, initWindowPositionY, true
|
||||
}
|
||||
|
||||
func setInitWindowPosition(x, y int) bool {
|
||||
windowM.Lock()
|
||||
defer windowM.Unlock()
|
||||
if mainLoopStarted {
|
||||
return false
|
||||
}
|
||||
initWindowPositionX, initWindowPositionY = x, y
|
||||
return true
|
||||
}
|
||||
|
||||
func fixWindowPosition(width, height int) {
|
||||
windowM.Lock()
|
||||
defer windowM.Unlock()
|
||||
|
||||
defer func() {
|
||||
mainLoopStarted = true
|
||||
}()
|
||||
|
||||
if !uiDriver().CanHaveWindow() {
|
||||
return
|
||||
}
|
||||
|
||||
if initWindowPositionX == invalidPos || initWindowPositionY == invalidPos {
|
||||
mx, my := uiDriver().MonitorPosition()
|
||||
sw, sh := uiDriver().ScreenSizeInFullscreen()
|
||||
x := mx + (sw-width)/2
|
||||
y := my + (sh-height)/3
|
||||
uiDriver().SetWindowPosition(x, y)
|
||||
} else {
|
||||
uiDriver().SetWindowPosition(initWindowPositionX, initWindowPositionY)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user