mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +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)
|
ScreenSizeInFullscreen() (int, int)
|
||||||
WindowPosition() (int, int)
|
WindowPosition() (int, int)
|
||||||
IsScreenTransparent() bool
|
IsScreenTransparent() bool
|
||||||
|
MonitorPosition() (int, int)
|
||||||
CanHaveWindow() bool // TODO: Create a 'Widnow' interface.
|
CanHaveWindow() bool // TODO: Create a 'Widnow' interface.
|
||||||
|
|
||||||
SetCursorMode(mode CursorMode)
|
SetCursorMode(mode CursorMode)
|
||||||
|
@ -129,14 +129,12 @@ func initialize() error {
|
|||||||
panic("glfw: glfw.CreateWindow must not return nil")
|
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.window = w
|
||||||
theUI.initMonitor = theUI.currentMonitor()
|
theUI.initMonitor = theUI.currentMonitor()
|
||||||
v := theUI.initMonitor.GetVideoMode()
|
v := theUI.initMonitor.GetVideoMode()
|
||||||
theUI.initFullscreenWidthInDP = int(theUI.toDeviceIndependentPixel(float64(v.Width)))
|
theUI.initFullscreenWidthInDP = int(theUI.toDeviceIndependentPixel(float64(v.Width)))
|
||||||
theUI.initFullscreenHeightInDP = int(theUI.toDeviceIndependentPixel(float64(v.Height)))
|
theUI.initFullscreenHeightInDP = int(theUI.toDeviceIndependentPixel(float64(v.Height)))
|
||||||
theUI.window.Destroy()
|
|
||||||
theUI.window = nil
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -568,7 +566,7 @@ func (u *UserInterface) Run(width, height int, scale float64, title string, uico
|
|||||||
go func() {
|
go func() {
|
||||||
defer cancel()
|
defer cancel()
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
if err := u.run(width, height, scale, title, uicontext); err != nil {
|
if err := u.run(title, uicontext); err != nil {
|
||||||
ch <- err
|
ch <- err
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -632,15 +630,12 @@ func (u *UserInterface) createWindow() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) run(width, height int, scale float64, title string, context driver.UIContext) error {
|
func (u *UserInterface) run(title string, context driver.UIContext) error {
|
||||||
var (
|
|
||||||
m *glfw.Monitor
|
|
||||||
mx, my int
|
|
||||||
v *glfw.VidMode
|
|
||||||
ww, wh int
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := u.t.Call(func() error {
|
if err := u.t.Call(func() error {
|
||||||
|
// The window is created at initialize().
|
||||||
|
u.window.Destroy()
|
||||||
|
u.window = nil
|
||||||
|
|
||||||
if u.graphics.IsGL() {
|
if u.graphics.IsGL() {
|
||||||
glfw.WindowHint(glfw.ContextVersionMajor, 2)
|
glfw.WindowHint(glfw.ContextVersionMajor, 2)
|
||||||
glfw.WindowHint(glfw.ContextVersionMinor, 1)
|
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 {
|
if i := u.getInitIconImages(); i != nil {
|
||||||
u.window.SetIcon(i)
|
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
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// The game is in window mode (not fullscreen mode) at the first state.
|
u.SetWindowPosition(u.getInitWindowPosition())
|
||||||
// Don't refer u.initFullscreen here to avoid some GLFW problems.
|
|
||||||
u.setWindowSize(ww, wh, false, u.vsync)
|
|
||||||
|
|
||||||
_ = u.t.Call(func() error {
|
_ = 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.title = title
|
||||||
u.window.SetTitle(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()
|
u.window.Show()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -1042,9 +1000,11 @@ func (u *UserInterface) setWindowSize(width, height int, fullscreen bool, vsync
|
|||||||
//
|
//
|
||||||
// currentMonitor must be called on the main thread.
|
// currentMonitor must be called on the main thread.
|
||||||
func (u *UserInterface) currentMonitor() *glfw.Monitor {
|
func (u *UserInterface) currentMonitor() *glfw.Monitor {
|
||||||
w := u.window
|
if w := u.window; w != nil {
|
||||||
if m := w.GetMonitor(); m != nil {
|
// TODO: When is the monitor nil?
|
||||||
return m
|
if m := w.GetMonitor(); m != nil {
|
||||||
|
return m
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Get the monitor which the current window belongs to. This requires OS API.
|
// Get the monitor which the current window belongs to. This requires OS API.
|
||||||
return u.currentMonitorFromPosition()
|
return u.currentMonitorFromPosition()
|
||||||
@ -1058,10 +1018,11 @@ func (u *UserInterface) SetWindowPosition(x, y int) {
|
|||||||
_ = u.t.Call(func() error {
|
_ = u.t.Call(func() error {
|
||||||
xf := u.toDeviceDependentPixel(float64(x))
|
xf := u.toDeviceDependentPixel(float64(x))
|
||||||
yf := u.toDeviceDependentPixel(float64(y))
|
yf := u.toDeviceDependentPixel(float64(y))
|
||||||
|
x, y := adjustWindowPosition(int(xf), int(yf))
|
||||||
if u.isFullscreen() {
|
if u.isFullscreen() {
|
||||||
u.origPosX, u.origPosY = int(xf), int(yf)
|
u.origPosX, u.origPosY = x, y
|
||||||
} else {
|
} else {
|
||||||
u.window.SetPos(int(xf), int(yf))
|
u.window.SetPos(x, y)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -1116,6 +1077,23 @@ func (u *UserInterface) SetWindowSize(width, height int) {
|
|||||||
u.setWindowSize(w, h, u.isFullscreen(), u.vsync)
|
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 {
|
func (u *UserInterface) CanHaveWindow() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -59,12 +59,14 @@ func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
|
|||||||
x := C.int(0)
|
x := C.int(0)
|
||||||
y := C.int(0)
|
y := C.int(0)
|
||||||
// Note: [NSApp mainWindow] is nil when it doesn't have its border. Use u.window here.
|
// Note: [NSApp mainWindow] is nil when it doesn't have its border. Use u.window here.
|
||||||
win := u.window.GetCocoaWindow()
|
if u.window != nil {
|
||||||
C.currentMonitorPos(win, &x, &y)
|
win := u.window.GetCocoaWindow()
|
||||||
for _, m := range glfw.GetMonitors() {
|
C.currentMonitorPos(win, &x, &y)
|
||||||
mx, my := m.GetPos()
|
for _, m := range glfw.GetMonitors() {
|
||||||
if int(x) == mx && int(y) == my {
|
mx, my := m.GetPos()
|
||||||
return m
|
if int(x) == mx && int(y) == my {
|
||||||
|
return m
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return glfw.GetPrimaryMonitor()
|
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)
|
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 := uiDriver().Run(width, height, scale, title, theUIContext, graphicsDriver()); err != nil {
|
||||||
if err == driver.RegularTermination {
|
if err == driver.RegularTermination {
|
||||||
return nil
|
return nil
|
||||||
|
65
window.go
65
window.go
@ -16,6 +16,13 @@ package ebiten
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxInt = int(^uint(0) >> 1)
|
||||||
|
minInt = -maxInt - 1
|
||||||
|
invalidPos = minInt
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetWindowDecorated sets the state if the window is decorated.
|
// SetWindowDecorated sets the state if the window is decorated.
|
||||||
@ -105,6 +112,9 @@ func SetWindowIcon(iconImages []image.Image) {
|
|||||||
//
|
//
|
||||||
// WindowPosition is concurrent-safe.
|
// WindowPosition is concurrent-safe.
|
||||||
func WindowPosition() (x, y int) {
|
func WindowPosition() (x, y int) {
|
||||||
|
if x, y, ok := initWindowPosition(); ok {
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
return uiDriver().WindowPosition()
|
return uiDriver().WindowPosition()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,5 +128,60 @@ func WindowPosition() (x, y int) {
|
|||||||
//
|
//
|
||||||
// SetWindowPosition is concurrent-safe.
|
// SetWindowPosition is concurrent-safe.
|
||||||
func SetWindowPosition(x, y int) {
|
func SetWindowPosition(x, y int) {
|
||||||
|
if setInitWindowPosition(x, y) {
|
||||||
|
return
|
||||||
|
}
|
||||||
uiDriver().SetWindowPosition(x, y)
|
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