mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 11:48:55 +01:00
ebiten: add (*Monitor).Size() to replace ScreenSizeInFullscreen()
Also, this change fixes redundant checks the case when a monitor does not exist. Now Ebitengine checks a monitor existence at the initialization. Closes #2145 Closes #2795
This commit is contained in:
parent
230619a036
commit
f4029aaa77
@ -85,7 +85,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||||||
op.Filter = ebiten.FilterLinear
|
op.Filter = ebiten.FilterLinear
|
||||||
screen.DrawImage(gophersImage, op)
|
screen.DrawImage(gophersImage, op)
|
||||||
|
|
||||||
fw, fh := ebiten.ScreenSizeInFullscreen()
|
fw, fh := ebiten.Monitor().Size()
|
||||||
msg := "This is an example of the finest fullscreen.\n"
|
msg := "This is an example of the finest fullscreen.\n"
|
||||||
if runtime.GOOS == "js" {
|
if runtime.GOOS == "js" {
|
||||||
msg += "Press F or touch the screen to enter fullscreen (again).\n"
|
msg += "Press F or touch the screen to enter fullscreen (again).\n"
|
||||||
|
@ -80,7 +80,7 @@ func (m *mascot) Layout(outsideWidth, outsideHeight int) (int, int) {
|
|||||||
func (m *mascot) Update() error {
|
func (m *mascot) Update() error {
|
||||||
m.count++
|
m.count++
|
||||||
|
|
||||||
sw, sh := ebiten.ScreenSizeInFullscreen()
|
sw, sh := ebiten.Monitor().Size()
|
||||||
ebiten.SetWindowPosition(m.x16/16, m.y16/16+sh-height)
|
ebiten.SetWindowPosition(m.x16/16, m.y16/16+sh-height)
|
||||||
|
|
||||||
if m.vx16 == 0 {
|
if m.vx16 == 0 {
|
||||||
|
@ -401,7 +401,7 @@ func parseWindowPosition() (int, int, bool) {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Printf("Device scale factor: %0.2f\n", ebiten.Monitor().DeviceScaleFactor())
|
fmt.Printf("Device scale factor: %0.2f\n", ebiten.Monitor().DeviceScaleFactor())
|
||||||
w, h := ebiten.ScreenSizeInFullscreen()
|
w, h := ebiten.Monitor().Size()
|
||||||
fmt.Printf("Screen size in fullscreen: %d, %d\n", w, h)
|
fmt.Printf("Screen size in fullscreen: %d, %d\n", w, h)
|
||||||
|
|
||||||
// Decode an image from the image file's byte slice.
|
// Decode an image from the image file's byte slice.
|
||||||
|
@ -42,14 +42,15 @@ func (m *Monitor) Name() string {
|
|||||||
|
|
||||||
// DeviceScaleFactor is concurrent-safe as contentScale is immutable.
|
// DeviceScaleFactor is concurrent-safe as contentScale is immutable.
|
||||||
func (m *Monitor) DeviceScaleFactor() float64 {
|
func (m *Monitor) DeviceScaleFactor() float64 {
|
||||||
// It is rare, but monitor can be nil when glfw.GetPrimaryMonitor returns nil.
|
|
||||||
// In this case, return 1 as a tentative scale (#1878).
|
|
||||||
if m == nil {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return m.contentScale
|
return m.contentScale
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size returns the size of the monitor in device-independent pixels.
|
||||||
|
func (m *Monitor) Size() (int, int) {
|
||||||
|
w, h := m.sizeInDIP()
|
||||||
|
return int(w), int(h)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Monitor) sizeInDIP() (float64, float64) {
|
func (m *Monitor) sizeInDIP() (float64, float64) {
|
||||||
w, h := m.boundsInGLFWPixels.Dx(), m.boundsInGLFWPixels.Dy()
|
w, h := m.boundsInGLFWPixels.Dx(), m.boundsInGLFWPixels.Dy()
|
||||||
s := m.DeviceScaleFactor()
|
s := m.DeviceScaleFactor()
|
||||||
@ -88,6 +89,11 @@ func (m *monitors) primaryMonitor() *Monitor {
|
|||||||
m.m.Lock()
|
m.m.Lock()
|
||||||
defer m.m.Unlock()
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
// GetMonitors might return nil in theory (#1878, #1887).
|
||||||
|
// primaryMonitor can be called at the initialization, so monitors can be nil.
|
||||||
|
if len(m.monitors) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return m.monitors[0]
|
return m.monitors[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
internal/ui/screensizeinfullscreen_js.go
Normal file
20
internal/ui/screensizeinfullscreen_js.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2024 The Ebitengine Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
|
||||||
|
// On browsers, ScreenSizeInFullscreen returns the 'window' (global object) size, not 'screen' size for backward compatibility (#2145).
|
||||||
|
return window.Get("width").Int(), window.Get("height").Int()
|
||||||
|
}
|
21
internal/ui/screensizeinfullscreen_notjs.go
Normal file
21
internal/ui/screensizeinfullscreen_notjs.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2024 The Ebitengine Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//go:build !js
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
|
||||||
|
return u.Monitor().Size()
|
||||||
|
}
|
@ -178,9 +178,9 @@ func (u *UserInterface) initializeGLFW() error {
|
|||||||
m = theMonitors.primaryMonitor()
|
m = theMonitors.primaryMonitor()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrimaryMonitor might return nil in theory (#1887).
|
// GetMonitors might return nil in theory (#1878, #1887).
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return errors.New("ui: no monitor was found at initialize")
|
return errors.New("ui: no monitor was found at initializeGLFW")
|
||||||
}
|
}
|
||||||
|
|
||||||
u.setInitMonitor(m)
|
u.setInitMonitor(m)
|
||||||
@ -265,7 +265,7 @@ func (u *UserInterface) AppendMonitors(monitors []*Monitor) []*Monitor {
|
|||||||
// Monitor returns the window's current monitor. Returns nil if there is no current monitor yet.
|
// Monitor returns the window's current monitor. Returns nil if there is no current monitor yet.
|
||||||
func (u *UserInterface) Monitor() *Monitor {
|
func (u *UserInterface) Monitor() *Monitor {
|
||||||
if !u.isRunning() {
|
if !u.isRunning() {
|
||||||
return nil
|
return u.getInitMonitor()
|
||||||
}
|
}
|
||||||
var monitor *Monitor
|
var monitor *Monitor
|
||||||
u.mainThread.Call(func() {
|
u.mainThread.Call(func() {
|
||||||
@ -571,36 +571,6 @@ func (u *UserInterface) setWindowClosingHandled(handled bool) {
|
|||||||
u.m.Unlock()
|
u.m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
|
|
||||||
if u.isTerminated() {
|
|
||||||
return 0, 0
|
|
||||||
}
|
|
||||||
if !u.isRunning() {
|
|
||||||
m := u.getInitMonitor()
|
|
||||||
w, h := m.sizeInDIP()
|
|
||||||
return int(w), int(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
var w, h int
|
|
||||||
u.mainThread.Call(func() {
|
|
||||||
if u.isTerminated() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m, err := u.currentMonitor()
|
|
||||||
if err != nil {
|
|
||||||
u.setError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if m == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
wf, hf := m.sizeInDIP()
|
|
||||||
w = int(wf)
|
|
||||||
h = int(hf)
|
|
||||||
})
|
|
||||||
return w, h
|
|
||||||
}
|
|
||||||
|
|
||||||
// isFullscreen must be called from the main thread.
|
// isFullscreen must be called from the main thread.
|
||||||
func (u *UserInterface) isFullscreen() (bool, error) {
|
func (u *UserInterface) isFullscreen() (bool, error) {
|
||||||
if !u.isRunning() {
|
if !u.isRunning() {
|
||||||
|
@ -121,6 +121,7 @@ type userInterfaceImpl struct {
|
|||||||
var (
|
var (
|
||||||
window = js.Global().Get("window")
|
window = js.Global().Get("window")
|
||||||
document = js.Global().Get("document")
|
document = js.Global().Get("document")
|
||||||
|
screen = js.Global().Get("screen")
|
||||||
canvas js.Value
|
canvas js.Value
|
||||||
requestAnimationFrame = js.Global().Get("requestAnimationFrame")
|
requestAnimationFrame = js.Global().Get("requestAnimationFrame")
|
||||||
setTimeout = js.Global().Get("setTimeout")
|
setTimeout = js.Global().Get("setTimeout")
|
||||||
@ -131,10 +132,6 @@ var (
|
|||||||
documentHidden = js.Global().Get("Object").Call("getOwnPropertyDescriptor", js.Global().Get("Document").Get("prototype"), "hidden").Get("get").Call("bind", document)
|
documentHidden = js.Global().Get("Object").Call("getOwnPropertyDescriptor", js.Global().Get("Document").Get("prototype"), "hidden").Get("get").Call("bind", document)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
|
|
||||||
return window.Get("innerWidth").Int(), window.Get("innerHeight").Int()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UserInterface) SetFullscreen(fullscreen bool) {
|
func (u *UserInterface) SetFullscreen(fullscreen bool) {
|
||||||
if !canvas.Truthy() {
|
if !canvas.Truthy() {
|
||||||
return
|
return
|
||||||
@ -796,6 +793,10 @@ func (m *Monitor) DeviceScaleFactor() float64 {
|
|||||||
return m.deviceScaleFactor
|
return m.deviceScaleFactor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Monitor) Size() (int, int) {
|
||||||
|
return screen.Get("width").Int(), screen.Get("height").Int()
|
||||||
|
}
|
||||||
|
|
||||||
func (u *UserInterface) AppendMonitors(mons []*Monitor) []*Monitor {
|
func (u *UserInterface) AppendMonitors(mons []*Monitor) []*Monitor {
|
||||||
return append(mons, theMonitor)
|
return append(mons, theMonitor)
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ func glfwMonitorSizeInGLFWPixels(m *glfw.Monitor) (int, int, error) {
|
|||||||
|
|
||||||
// Note: GLFW currently returns physical pixel sizes,
|
// Note: GLFW currently returns physical pixel sizes,
|
||||||
// but we need to predict the window system-side size of the fullscreen window
|
// but we need to predict the window system-side size of the fullscreen window
|
||||||
// for Ebitengine's `ScreenSizeInFullscreen` public API.
|
// for Ebitengine's `(*Monitor).Size()` public API.
|
||||||
// Also at the moment we need this prior to switching to fullscreen, but that might be replaceable.
|
// Also at the moment we need this prior to switching to fullscreen, but that might be replaceable.
|
||||||
// So this function computes the ratio of physical per logical pixels.
|
// So this function computes the ratio of physical per logical pixels.
|
||||||
xconn, err := xgb.NewConn()
|
xconn, err := xgb.NewConn()
|
||||||
|
@ -183,12 +183,6 @@ func (u *UserInterface) update() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
|
|
||||||
// TODO: This function should return gbuildWidthPx, gbuildHeightPx,
|
|
||||||
// but these values are not initialized until the main loop starts.
|
|
||||||
return 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOutsideSize is called from mobile/ebitenmobileview.
|
// SetOutsideSize is called from mobile/ebitenmobileview.
|
||||||
//
|
//
|
||||||
// SetOutsideSize is concurrent safe.
|
// SetOutsideSize is concurrent safe.
|
||||||
@ -289,6 +283,11 @@ func (m *Monitor) DeviceScaleFactor() float64 {
|
|||||||
return m.deviceScaleFactor
|
return m.deviceScaleFactor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Monitor) Size() (int, int) {
|
||||||
|
// TODO: Return a valid value.
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
func (u *UserInterface) AppendMonitors(mons []*Monitor) []*Monitor {
|
func (u *UserInterface) AppendMonitors(mons []*Monitor) []*Monitor {
|
||||||
return append(mons, theMonitor)
|
return append(mons, theMonitor)
|
||||||
}
|
}
|
||||||
|
@ -102,10 +102,6 @@ func (*UserInterface) IsFocused() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*UserInterface) ScreenSizeInFullscreen() (int, int) {
|
|
||||||
return 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UserInterface) readInputState(inputState *InputState) {
|
func (u *UserInterface) readInputState(inputState *InputState) {
|
||||||
u.m.Lock()
|
u.m.Lock()
|
||||||
defer u.m.Unlock()
|
defer u.m.Unlock()
|
||||||
@ -170,6 +166,10 @@ func (m *Monitor) DeviceScaleFactor() float64 {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Monitor) Size() (int, int) {
|
||||||
|
return int(C.kScreenWidth), int(C.kScreenHeight)
|
||||||
|
}
|
||||||
|
|
||||||
func (u *UserInterface) AppendMonitors(mons []*Monitor) []*Monitor {
|
func (u *UserInterface) AppendMonitors(mons []*Monitor) []*Monitor {
|
||||||
return append(mons, theMonitor)
|
return append(mons, theMonitor)
|
||||||
}
|
}
|
||||||
|
@ -92,10 +92,6 @@ func (*UserInterface) IsFocused() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*UserInterface) ScreenSizeInFullscreen() (int, int) {
|
|
||||||
return 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UserInterface) readInputState(inputState *InputState) {
|
func (u *UserInterface) readInputState(inputState *InputState) {
|
||||||
// TODO: Implement this.
|
// TODO: Implement this.
|
||||||
}
|
}
|
||||||
@ -163,6 +159,10 @@ func (m *Monitor) DeviceScaleFactor() float64 {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Monitor) Size() (int, int) {
|
||||||
|
return screenWidth, screenHeight
|
||||||
|
}
|
||||||
|
|
||||||
func (u *UserInterface) AppendMonitors(mons []*Monitor) []*Monitor {
|
func (u *UserInterface) AppendMonitors(mons []*Monitor) []*Monitor {
|
||||||
return append(mons, theMonitor)
|
return append(mons, theMonitor)
|
||||||
}
|
}
|
||||||
|
16
monitor.go
16
monitor.go
@ -34,13 +34,23 @@ func (m *MonitorType) Name() string {
|
|||||||
//
|
//
|
||||||
// DeviceScaleFactor might panic on init function on some devices like Android.
|
// DeviceScaleFactor might panic on init function on some devices like Android.
|
||||||
// Then, it is not recommended to call DeviceScaleFactor from init functions.
|
// Then, it is not recommended to call DeviceScaleFactor from init functions.
|
||||||
//
|
|
||||||
// DeviceScaleFactor must be called on the main thread before the main loop,
|
|
||||||
// and is concurrent-safe after the main loop.
|
|
||||||
func (m *MonitorType) DeviceScaleFactor() float64 {
|
func (m *MonitorType) DeviceScaleFactor() float64 {
|
||||||
return (*ui.Monitor)(m).DeviceScaleFactor()
|
return (*ui.Monitor)(m).DeviceScaleFactor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size returns the size of the monitor in device-independent pixels.
|
||||||
|
// This is the same as the screen size in fullscreen mode.
|
||||||
|
// The returned value can be given to SetSize function if the perfectly fit fullscreen is needed.
|
||||||
|
//
|
||||||
|
// On mobiles, Size returns (0, 0) so far.
|
||||||
|
//
|
||||||
|
// Size's use cases are limited. If you are making a fullscreen application, you can use RunGame and
|
||||||
|
// the Game interface's Layout function instead. If you are making a not-fullscreen application but the application's
|
||||||
|
// behavior depends on the monitor size, Size is useful.
|
||||||
|
func (m *MonitorType) Size() (int, int) {
|
||||||
|
return (*ui.Monitor)(m).Size()
|
||||||
|
}
|
||||||
|
|
||||||
// Monitor returns the current monitor.
|
// Monitor returns the current monitor.
|
||||||
func Monitor() *MonitorType {
|
func Monitor() *MonitorType {
|
||||||
m := ui.Get().Monitor()
|
m := ui.Get().Monitor()
|
||||||
|
2
run.go
2
run.go
@ -352,6 +352,8 @@ func isRunGameEnded() bool {
|
|||||||
//
|
//
|
||||||
// ScreenSizeInFullscreen must be called on the main thread before ebiten.RunGame, and is concurrent-safe after
|
// ScreenSizeInFullscreen must be called on the main thread before ebiten.RunGame, and is concurrent-safe after
|
||||||
// ebiten.RunGame.
|
// ebiten.RunGame.
|
||||||
|
//
|
||||||
|
// Deprecated: as of v2.6. Use Monitor().Size() instead.
|
||||||
func ScreenSizeInFullscreen() (int, int) {
|
func ScreenSizeInFullscreen() (int, int) {
|
||||||
return ui.Get().ScreenSizeInFullscreen()
|
return ui.Get().ScreenSizeInFullscreen()
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ var (
|
|||||||
|
|
||||||
func initializeWindowPositionIfNeeded(width, height int) {
|
func initializeWindowPositionIfNeeded(width, height int) {
|
||||||
if atomic.LoadUint32(&windowPositionSetExplicitly) == 0 {
|
if atomic.LoadUint32(&windowPositionSetExplicitly) == 0 {
|
||||||
sw, sh := ui.Get().ScreenSizeInFullscreen()
|
sw, sh := ui.Get().Monitor().Size()
|
||||||
x, y := ui.InitialWindowPosition(sw, sh, width, height)
|
x, y := ui.InitialWindowPosition(sw, sh, width, height)
|
||||||
ui.Get().Window().SetPosition(x, y)
|
ui.Get().Window().SetPosition(x, y)
|
||||||
}
|
}
|
||||||
@ -175,7 +175,7 @@ func initializeWindowPositionIfNeeded(width, height int) {
|
|||||||
// WindowSize returns (0, 0) on other environments.
|
// WindowSize returns (0, 0) on other environments.
|
||||||
//
|
//
|
||||||
// Even if the application is in fullscreen mode, WindowSize returns the original window size
|
// Even if the application is in fullscreen mode, WindowSize returns the original window size
|
||||||
// If you need the fullscreen dimensions, see ScreenSizeInFullscreen instead.
|
// If you need the fullscreen dimensions, see Monitor().Size() instead.
|
||||||
//
|
//
|
||||||
// WindowSize is concurrent-safe.
|
// WindowSize is concurrent-safe.
|
||||||
func WindowSize() (int, int) {
|
func WindowSize() (int, int) {
|
||||||
|
Loading…
Reference in New Issue
Block a user