2019-11-26 16:29:30 +01:00
|
|
|
// Copyright 2019 The Ebiten 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 ebiten
|
|
|
|
|
|
|
|
import (
|
|
|
|
"image"
|
2021-04-17 10:19:36 +02:00
|
|
|
"sync/atomic"
|
2019-12-17 04:28:52 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
maxInt = int(^uint(0) >> 1)
|
|
|
|
minInt = -maxInt - 1
|
|
|
|
invalidPos = minInt
|
2019-11-26 16:29:30 +01:00
|
|
|
)
|
|
|
|
|
2020-03-20 13:46:23 +01:00
|
|
|
// IsWindowDecorated reports whether the window is decorated.
|
|
|
|
//
|
|
|
|
// IsWindowDecorated is concurrent-safe.
|
|
|
|
func IsWindowDecorated() bool {
|
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
return w.IsDecorated()
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-11-26 16:29:30 +01:00
|
|
|
// SetWindowDecorated sets the state if the window is decorated.
|
|
|
|
//
|
|
|
|
// The window is decorated by default.
|
|
|
|
//
|
|
|
|
// SetWindowDecorated works only on desktops.
|
|
|
|
// SetWindowDecorated does nothing on other platforms.
|
|
|
|
//
|
2021-04-18 10:35:46 +02:00
|
|
|
// SetWindowDecorated does nothing on macOS when the window is fullscreened natively by the macOS desktop
|
|
|
|
// instead of SetFullscreen(true).
|
|
|
|
//
|
2019-11-26 16:29:30 +01:00
|
|
|
// SetWindowDecorated is concurrent-safe.
|
|
|
|
func SetWindowDecorated(decorated bool) {
|
2019-12-24 16:05:56 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.SetDecorated(decorated)
|
|
|
|
}
|
2019-11-26 16:29:30 +01:00
|
|
|
}
|
|
|
|
|
2019-12-22 10:08:02 +01:00
|
|
|
// IsWindowResizable reports whether the window is resizable by the user's dragging on desktops.
|
|
|
|
// On the other environments, IsWindowResizable always returns false.
|
2019-11-26 16:29:30 +01:00
|
|
|
//
|
|
|
|
// IsWindowResizable is concurrent-safe.
|
|
|
|
func IsWindowResizable() bool {
|
2019-12-24 16:05:56 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
return w.IsResizable()
|
|
|
|
}
|
|
|
|
return false
|
2019-11-26 16:29:30 +01:00
|
|
|
}
|
|
|
|
|
2019-12-22 10:08:02 +01:00
|
|
|
// SetWindowResizable sets whether the window is resizable by the user's dragging on desktops.
|
|
|
|
// On the other environments, SetWindowResizable does nothing.
|
|
|
|
//
|
2020-02-12 12:58:23 +01:00
|
|
|
// The window is not resizable by default.
|
|
|
|
//
|
2019-12-22 10:08:02 +01:00
|
|
|
// If SetWindowResizable is called with true and Run is used, SetWindowResizable panics. Use RunGame instead.
|
|
|
|
//
|
2021-04-18 10:35:46 +02:00
|
|
|
// SetWindowResizable does nothing on macOS when the window is fullscreened natively by the macOS desktop
|
|
|
|
// instead of SetFullscreen(true).
|
|
|
|
//
|
2019-12-22 10:08:02 +01:00
|
|
|
// SetWindowResizable is concurrent-safe.
|
|
|
|
func SetWindowResizable(resizable bool) {
|
|
|
|
theUIContext.setWindowResizable(resizable)
|
|
|
|
}
|
|
|
|
|
2019-11-26 16:29:30 +01:00
|
|
|
// SetWindowTitle sets the title of the window.
|
|
|
|
//
|
2020-10-04 19:00:50 +02:00
|
|
|
// SetWindowTitle does nothing on browsers or mobiles.
|
2019-11-26 16:29:30 +01:00
|
|
|
//
|
|
|
|
// SetWindowTitle is concurrent-safe.
|
|
|
|
func SetWindowTitle(title string) {
|
2019-12-24 16:05:56 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.SetTitle(title)
|
|
|
|
}
|
2019-11-26 16:29:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetWindowIcon sets the icon of the game window.
|
|
|
|
//
|
|
|
|
// If len(iconImages) is 0, SetWindowIcon reverts the icon to the default one.
|
|
|
|
//
|
|
|
|
// For desktops, see the document of glfwSetWindowIcon of GLFW 3.2:
|
|
|
|
//
|
|
|
|
// This function sets the icon of the specified window.
|
|
|
|
// If passed an array of candidate images, those of or closest to the sizes
|
|
|
|
// desired by the system are selected.
|
|
|
|
// If no images are specified, the window reverts to its default icon.
|
|
|
|
//
|
|
|
|
// The desired image sizes varies depending on platform and system settings.
|
|
|
|
// The selected images will be rescaled as needed.
|
|
|
|
// Good sizes include 16x16, 32x32 and 48x48.
|
|
|
|
//
|
|
|
|
// As macOS windows don't have icons, SetWindowIcon doesn't work on macOS.
|
|
|
|
//
|
|
|
|
// SetWindowIcon doesn't work on browsers or mobiles.
|
|
|
|
//
|
|
|
|
// SetWindowIcon is concurrent-safe.
|
|
|
|
func SetWindowIcon(iconImages []image.Image) {
|
2019-12-24 16:05:56 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.SetIcon(iconImages)
|
|
|
|
}
|
2019-11-26 16:29:30 +01:00
|
|
|
}
|
2019-11-30 14:37:53 +01:00
|
|
|
|
|
|
|
// WindowPosition returns the window position.
|
2020-03-28 11:51:44 +01:00
|
|
|
// The origin position is the left-upper corner of the current monitor.
|
|
|
|
// The unit is device-independent pixels.
|
2019-11-30 14:37:53 +01:00
|
|
|
//
|
2019-12-16 02:52:53 +01:00
|
|
|
// WindowPosition panics if the main loop does not start yet.
|
2019-11-30 14:37:53 +01:00
|
|
|
//
|
2021-04-21 15:50:00 +02:00
|
|
|
// WindowPosition returns the last window position in fullscreen mode.
|
2019-11-30 16:39:04 +01:00
|
|
|
//
|
2019-11-30 14:37:53 +01:00
|
|
|
// WindowPosition returns (0, 0) on browsers and mobiles.
|
2019-11-30 16:11:46 +01:00
|
|
|
//
|
|
|
|
// WindowPosition is concurrent-safe.
|
2019-11-30 15:22:23 +01:00
|
|
|
func WindowPosition() (x, y int) {
|
2019-12-24 16:05:56 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
return w.Position()
|
|
|
|
}
|
|
|
|
return 0, 0
|
2019-11-30 14:37:53 +01:00
|
|
|
}
|
2019-11-30 15:22:23 +01:00
|
|
|
|
|
|
|
// SetWindowPosition sets the window position.
|
2020-03-28 11:51:44 +01:00
|
|
|
// The origin position is the left-upper corner of the current monitor.
|
|
|
|
// The unit is device-independent pixels.
|
2019-11-30 15:22:23 +01:00
|
|
|
//
|
2021-04-21 15:50:00 +02:00
|
|
|
// SetWindowPosition does nothing in fullscreen mode.
|
2019-11-30 16:39:04 +01:00
|
|
|
//
|
2019-11-30 15:22:23 +01:00
|
|
|
// SetWindowPosition does nothing on browsers and mobiles.
|
2019-11-30 16:11:46 +01:00
|
|
|
//
|
|
|
|
// SetWindowPosition is concurrent-safe.
|
2019-11-30 15:22:23 +01:00
|
|
|
func SetWindowPosition(x, y int) {
|
2021-04-17 10:19:36 +02:00
|
|
|
atomic.StoreUint32(&windowPositionSetExplicitly, 1)
|
2019-12-24 16:05:56 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.SetPosition(x, y)
|
|
|
|
}
|
2019-11-30 15:22:23 +01:00
|
|
|
}
|
2019-12-17 04:28:52 +01:00
|
|
|
|
|
|
|
var (
|
2021-04-17 10:19:36 +02:00
|
|
|
windowPositionSetExplicitly uint32
|
2019-12-17 04:28:52 +01:00
|
|
|
)
|
|
|
|
|
2021-04-17 10:30:48 +02:00
|
|
|
func initializeWindowPositionIfNeeded(width, height int) {
|
2019-12-24 16:05:56 +01:00
|
|
|
w := uiDriver().Window()
|
|
|
|
if w == nil {
|
2019-12-17 04:28:52 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-04-17 10:19:36 +02:00
|
|
|
if atomic.LoadUint32(&windowPositionSetExplicitly) == 0 {
|
2019-12-17 04:28:52 +01:00
|
|
|
sw, sh := uiDriver().ScreenSizeInFullscreen()
|
2020-03-28 11:51:44 +01:00
|
|
|
x := (sw - width) / 2
|
|
|
|
y := (sh - height) / 3
|
2019-12-24 16:05:56 +01:00
|
|
|
w.SetPosition(x, y)
|
2019-12-17 04:28:52 +01:00
|
|
|
}
|
|
|
|
}
|
2019-12-16 02:52:53 +01:00
|
|
|
|
2019-12-22 04:52:50 +01:00
|
|
|
// WindowSize returns the window size on desktops.
|
|
|
|
// WindowSize returns (0, 0) on other environments.
|
|
|
|
//
|
2021-04-21 15:50:00 +02:00
|
|
|
// In fullscreen mode, WindowSize returns the original window size.
|
2019-12-16 02:52:53 +01:00
|
|
|
//
|
|
|
|
// WindowSize is concurrent-safe.
|
|
|
|
func WindowSize() (int, int) {
|
2019-12-24 16:05:56 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
return w.Size()
|
|
|
|
}
|
|
|
|
return 0, 0
|
2019-12-16 02:52:53 +01:00
|
|
|
}
|
|
|
|
|
2019-12-22 04:52:50 +01:00
|
|
|
// SetWindowSize sets the window size on desktops.
|
|
|
|
// SetWindowSize does nothing on other environments.
|
|
|
|
//
|
2021-04-21 15:50:00 +02:00
|
|
|
// In fullscreen mode, SetWindowSize sets the original window size.
|
2019-12-16 02:52:53 +01:00
|
|
|
//
|
2019-12-22 04:46:57 +01:00
|
|
|
// SetWindowSize panics if width or height is not a positive number.
|
|
|
|
//
|
2019-12-16 02:52:53 +01:00
|
|
|
// SetWindowSize is concurrent-safe.
|
|
|
|
func SetWindowSize(width, height int) {
|
2019-12-22 04:46:57 +01:00
|
|
|
if width <= 0 || height <= 0 {
|
|
|
|
panic("ebiten: width and height must be positive")
|
|
|
|
}
|
2019-12-24 16:05:56 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.SetSize(width, height)
|
|
|
|
}
|
2019-12-16 02:52:53 +01:00
|
|
|
}
|
2020-03-20 13:46:23 +01:00
|
|
|
|
2021-04-16 19:27:04 +02:00
|
|
|
// WindowSizeLimist returns the limitation of the window size on desktops.
|
|
|
|
// A negative value indicates the size is not limited.
|
|
|
|
//
|
|
|
|
// WindowMaxSize is concurrent-safe.
|
|
|
|
func WindowSizeLimits() (minw, minh, maxw, maxh int) {
|
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
return w.SizeLimits()
|
|
|
|
}
|
|
|
|
return -1, -1, -1, -1
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetWindowSizeLimits sets the limitation of the window size on desktops.
|
|
|
|
// A negative value indicates the size is not limited.
|
|
|
|
//
|
|
|
|
// SetWindowMaxSize is concurrent-safe.
|
|
|
|
func SetWindowSizeLimits(minw, minh, maxw, maxh int) {
|
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.SetSizeLimits(minw, minh, maxw, maxh)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-20 13:46:23 +01:00
|
|
|
// IsWindowFloating reports whether the window is always shown above all the other windows.
|
|
|
|
//
|
2020-03-21 11:26:28 +01:00
|
|
|
// IsWindowFloating returns false on browsers and mobiles.
|
|
|
|
//
|
2020-03-20 13:46:23 +01:00
|
|
|
// IsWindowFloating is concurrent-safe.
|
|
|
|
func IsWindowFloating() bool {
|
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
return w.IsFloating()
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetWindowFloating sets the state whether the window is always shown above all the other windows.
|
|
|
|
//
|
2020-03-21 11:26:28 +01:00
|
|
|
// SetWindowFloating does nothing on browsers or mobiles.
|
|
|
|
//
|
2021-04-18 10:35:46 +02:00
|
|
|
// SetWindowFloating does nothing on macOS when the window is fullscreened natively by the macOS desktop
|
|
|
|
// instead of SetFullscreen(true).
|
|
|
|
//
|
2020-03-20 13:46:23 +01:00
|
|
|
// SetWindowFloating is concurrent-safe.
|
|
|
|
func SetWindowFloating(float bool) {
|
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.SetFloating(float)
|
|
|
|
}
|
|
|
|
}
|
2020-03-21 11:26:28 +01:00
|
|
|
|
|
|
|
// MaximizeWindow maximizes the window.
|
|
|
|
//
|
2020-03-28 14:00:40 +01:00
|
|
|
// MaximizeWindow panics when the window is not resizable.
|
2020-03-21 11:26:28 +01:00
|
|
|
//
|
|
|
|
// MaximizeWindow does nothing on browsers or mobiles.
|
|
|
|
//
|
|
|
|
// MaximizeWindow is concurrent-safe.
|
|
|
|
func MaximizeWindow() {
|
2020-03-28 14:00:40 +01:00
|
|
|
if !IsWindowResizable() {
|
|
|
|
panic("ebiten: a window to maximize must be resizable")
|
|
|
|
}
|
2020-03-21 11:26:28 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.Maximize()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsWindowMaximized reports whether the window is maximized or not.
|
|
|
|
//
|
2020-03-30 19:48:19 +02:00
|
|
|
// IsWindowMaximized returns false when the window is not resizable.
|
|
|
|
//
|
2020-03-21 11:26:28 +01:00
|
|
|
// IsWindowMaximized always returns false on browsers and mobiles.
|
|
|
|
//
|
|
|
|
// IsWindowMaximized is concurrent-safe.
|
|
|
|
func IsWindowMaximized() bool {
|
2020-03-30 19:48:19 +02:00
|
|
|
if !IsWindowResizable() {
|
|
|
|
return false
|
|
|
|
}
|
2020-03-21 11:26:28 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
return w.IsMaximized()
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// MinimizeWindow minimizes the window.
|
|
|
|
//
|
|
|
|
// If the main loop does not start yet, MinimizeWindow does nothing.
|
|
|
|
//
|
|
|
|
// MinimizeWindow does nothing on browsers or mobiles.
|
|
|
|
//
|
|
|
|
// MinimizeWindow is concurrent-safe.
|
|
|
|
func MinimizeWindow() {
|
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.Minimize()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsWindowMinimized reports whether the window is minimized or not.
|
|
|
|
//
|
|
|
|
// IsWindowMinimized always returns false on browsers and mobiles.
|
|
|
|
//
|
|
|
|
// IsWindowMinimized is concurrent-safe.
|
|
|
|
func IsWindowMinimized() bool {
|
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
return w.IsMinimized()
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// RestoreWindow restores the window from its maximized or minimized state.
|
|
|
|
//
|
2020-03-30 19:48:19 +02:00
|
|
|
// RestoreWindow panics when the window is not maximized nor minimized.
|
|
|
|
//
|
2020-03-21 11:26:28 +01:00
|
|
|
// RestoreWindow is concurrent-safe.
|
|
|
|
func RestoreWindow() {
|
2020-03-30 19:48:19 +02:00
|
|
|
if !IsWindowMaximized() && !IsWindowMinimized() {
|
|
|
|
panic("ebiten: RestoreWindow must be called on a maximized or a minimized window")
|
|
|
|
}
|
2020-03-21 11:26:28 +01:00
|
|
|
if w := uiDriver().Window(); w != nil {
|
|
|
|
w.Restore()
|
|
|
|
}
|
|
|
|
}
|