diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index d7b2c427633..cef20bc5d8c 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -857,6 +857,7 @@ Returns the index of the screen containing the window with the keyboard focus, or the primary screen if there's no focused window. + [b]Note:[/b] This method is implemented on Linux/X11, macOS, and Windows. On other platforms, this method always returns the primary screen. @@ -870,19 +871,21 @@ Returns index of the primary screen. + [b]Note:[/b] This method is implemented on Linux/X11, macOS, and Windows. On other platforms, this method always returns [code]0[/code]. Returns the number of displays available. + [b]Note:[/b] This method is implemented on Linux (X11 and Wayland), macOS, and Windows. On other platforms, this method always returns [code]1[/code]. - Returns the index of the screen that overlaps the most with the given rectangle. Returns [code]-1[/code] if the rectangle doesn't overlap with any screen or has no area. + Returns the index of the screen that overlaps the most with the given rectangle. Returns [constant INVALID_SCREEN] if the rectangle doesn't overlap with any screen or has no area. @@ -1694,7 +1697,8 @@ - Returns the dots per inch density of the specified screen. If [param screen] is [constant SCREEN_OF_MAIN_WINDOW] (the default value), a screen with the main window will be used. + Returns the dots per inch density of the specified screen. Returns platform specific default value if [param screen] is invalid. + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. [b]Note:[/b] On macOS, returned value is inaccurate if fractional display scaling mode is used. [b]Note:[/b] On Android devices, the actual screen densities are grouped into six generalized densities: [codeblock lang=text] @@ -1705,15 +1709,16 @@ xxhdpi - 480 dpi xxxhdpi - 640 dpi [/codeblock] - [b]Note:[/b] This method is implemented on Android, Linux (X11/Wayland), macOS and Windows. Returns [code]72[/code] on unsupported platforms. + [b]Note:[/b] This method is implemented on Android, iOS, Linux (X11/Wayland), macOS, Web, and Windows. On other platforms, this method always returns [code]72[/code]. - Returns a screenshot of the [param screen]. - [b]Note:[/b] This method is implemented on Linux (X11), macOS, and Windows. + Returns a screenshot of the [param screen]. Returns [code]null[/code] if [param screen] is invalid or the [DisplayServer] fails to capture screenshot. + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. + [b]Note:[/b] This method is implemented on Linux (X11, excluding XWayland), macOS, and Windows. On other platforms, this method always returns [code]null[/code]. [b]Note:[/b] On macOS, this method requires the "Screen Recording" permission. If permission is not granted, this method returns a screenshot that will not include other application windows or OS elements not related to the application. @@ -1721,8 +1726,8 @@ - Returns a screenshot of the screen region defined by [param rect]. - [b]Note:[/b] This method is implemented on macOS and Windows. + Returns a screenshot of the screen region defined by [param rect]. Returns [code]null[/code] if [param rect] is outside screen bounds or the [DisplayServer] fails to capture screenshot. + [b]Note:[/b] This method is implemented on macOS and Windows. On other platforms, this method always returns [code]null[/code]. [b]Note:[/b] On macOS, this method requires the "Screen Recording" permission. If permission is not granted, this method returns a screenshot that will not include other application windows or OS elements not related to the application. @@ -1738,8 +1743,9 @@ - Returns the [param screen]'s current orientation. See also [method screen_set_orientation]. - [b]Note:[/b] This method is implemented on Android and iOS. + Returns the [param screen]'s current orientation. See also [method screen_set_orientation]. Returns [constant SCREEN_LANDSCAPE] if [param screen] is invalid. + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. + [b]Note:[/b] This method is implemented on Android and iOS. On other platforms, this method always returns [constant SCREEN_LANDSCAPE]. @@ -1747,15 +1753,15 @@ Returns color of the display pixel at the [param position]. - [b]Note:[/b] This method is implemented on Linux (X11), macOS, and Windows. - [b]Note:[/b] On macOS, this method requires "Screen Recording" permission, if permission is not granted it will return desktop wallpaper color. + [b]Note:[/b] This method is implemented on Linux (X11, excluding XWayland), macOS, and Windows. On other platforms, this method always returns [Color]. + [b]Note:[/b] On macOS, this method requires the "Screen Recording" permission. If permission is not granted, this method returns a screenshot that will only contain the desktop wallpaper, the current application's window, and other related UI elements. - Returns the screen's top-left corner position in pixels. On multi-monitor setups, the screen position is relative to the virtual desktop area. On multi-monitor setups with different screen resolutions or orientations, the origin may be located outside any display like this: + Returns the screen's top-left corner position in pixels. Returns [constant Vector2i.ZERO] if [param screen] is invalid. On multi-monitor setups, the screen position is relative to the virtual desktop area. On multi-monitor setups with different screen resolutions or orientations, the origin might be located outside any display like this: [codeblock lang=text] * (0, 0) +-------+ | | @@ -1765,38 +1771,41 @@ +-------------+ +-------+ [/codeblock] See also [method screen_get_size]. - [b]Note:[/b] On Linux (Wayland) this method always returns [code](0, 0)[/code]. + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. - Returns the current refresh rate of the specified screen. If [param screen] is [constant SCREEN_OF_MAIN_WINDOW] (the default value), a screen with the main window will be used. - [b]Note:[/b] Returns [code]-1.0[/code] if the DisplayServer fails to find the refresh rate for the specified screen. On Web, [method screen_get_refresh_rate] will always return [code]-1.0[/code] as there is no way to retrieve the refresh rate on that platform. + Returns the current refresh rate of the specified screen. Returns [code]-1.0[/code] if [param screen] is invalid or the [DisplayServer] fails to find the refresh rate for the specified screen. To fallback to a default refresh rate if the method fails, try: [codeblock] var refresh_rate = DisplayServer.screen_get_refresh_rate() if refresh_rate < 0: refresh_rate = 60.0 [/codeblock] + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. + [b]Note:[/b] This method is implemented on Android, iOS, macOS, Linux (X11 and Wayland), and Windows. On other platforms, this method always returns [code]-1.0[/code]. - Returns the scale factor of the specified screen by index. + Returns the scale factor of the specified screen by index. Returns [code]1.0[/code] if [param screen] is invalid. + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. [b]Note:[/b] On macOS, the returned value is [code]2.0[/code] for hiDPI (Retina) screens, and [code]1.0[/code] for all other cases. [b]Note:[/b] On Linux (Wayland), the returned value is accurate only when [param screen] is [constant SCREEN_OF_MAIN_WINDOW]. Due to API limitations, passing a direct index will return a rounded-up integer, if the screen has a fractional scale (e.g. [code]1.25[/code] would get rounded up to [code]2.0[/code]). - [b]Note:[/b] This method is implemented on Android, iOS, Web, macOS, and Linux (Wayland). + [b]Note:[/b] This method is implemented on Android, iOS, Web, macOS, and Linux (Wayland). On other platforms, this method always returns [code]1.0[/code]. - Returns the screen's size in pixels. See also [method screen_get_position] and [method screen_get_usable_rect]. + Returns the screen's size in pixels. See also [method screen_get_position] and [method screen_get_usable_rect]. Returns [constant Vector2i.ZERO] if [param screen] is invalid. + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. @@ -1804,6 +1813,8 @@ Returns the portion of the screen that is not obstructed by a status bar in pixels. See also [method screen_get_size]. + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. + [b]Note:[/b] This method is implemented on Linux/X11, macOS, and Windows. On other platforms, this method always returns [code]Rect2i(screen_get_position(screen), screen_get_size(screen))[/code]. @@ -1825,6 +1836,8 @@ Sets the [param screen]'s [param orientation]. See also [method screen_get_orientation]. + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. + [b]Note:[/b] This method is implemented on Android and iOS. [b]Note:[/b] On iOS, this method has no effect if [member ProjectSettings.display/window/handheld/orientation] is not set to [constant SCREEN_SENSOR]. @@ -2105,7 +2118,8 @@ - Returns the screen the window specified by [param window_id] is currently positioned on. If the screen overlaps multiple displays, the screen where the window's center is located is returned. See also [method window_set_current_screen]. + Returns the screen the window specified by [param window_id] is currently positioned on. If the screen overlaps multiple displays, the screen where the window's center is located is returned. See also [method window_set_current_screen]. Returns [constant INVALID_SCREEN] if [param window_id] is invalid. + [b]Note:[/b] This method is implemented on Linux/X11, macOS, and Windows. On other platforms, this method always returns [code]0[/code]. @@ -2252,6 +2266,8 @@ Moves the window specified by [param window_id] to the specified [param screen]. See also [method window_get_current_screen]. + [b]Note:[/b] One of the following constants can be used as [param screen]: [constant SCREEN_OF_MAIN_WINDOW], [constant SCREEN_PRIMARY], [constant SCREEN_WITH_MOUSE_FOCUS], or [constant SCREEN_WITH_KEYBOARD_FOCUS]. + [b]Note:[/b] This method is implemented on Linux/X11, macOS, and Windows. @@ -2882,21 +2898,24 @@ Max value of the [enum MouseMode]. + + The ID that refers to a screen that does not exist. This is returned by some [DisplayServer] methods if no screen matches the requested result. + Represents the screen containing the mouse pointer. - [b]Note:[/b] On Linux (Wayland), this constant always represents the screen at index [code]0[/code]. + [b]Note:[/b] On Android, iOS, Web, and Linux (Wayland), this constant always represents the screen at index [code]0[/code]. Represents the screen containing the window with the keyboard focus. - [b]Note:[/b] On Linux (Wayland), this constant always represents the screen at index [code]0[/code]. + [b]Note:[/b] On Android, iOS, Web, and Linux (Wayland), this constant always represents the screen at index [code]0[/code]. Represents the primary screen. - [b]Note:[/b] On Linux (Wayland), this constant always represents the screen at index [code]0[/code]. + [b]Note:[/b] On Android, iOS, Web, and Linux (Wayland), this constant always represents the screen at index [code]0[/code]. Represents the screen where the main window is located. This is usually the default value in functions that allow specifying one of several screens. - [b]Note:[/b] On Linux (Wayland), this constant always represents the screen at index [code]0[/code]. + [b]Note:[/b] On Android, iOS, Web, and Linux (Wayland), this constant always represents the screen at index [code]0[/code]. The ID of the main window spawned by the engine, which can be passed to methods expecting a [code]window_id[/code]. diff --git a/drivers/apple_embedded/display_server_apple_embedded.mm b/drivers/apple_embedded/display_server_apple_embedded.mm index 3f13b23b9ff..46a1e24e142 100644 --- a/drivers/apple_embedded/display_server_apple_embedded.mm +++ b/drivers/apple_embedded/display_server_apple_embedded.mm @@ -492,10 +492,18 @@ int DisplayServerAppleEmbedded::get_primary_screen() const { } Point2i DisplayServerAppleEmbedded::screen_get_position(int p_screen) const { - return Size2i(); + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Point2i()); + + return Point2i(0, 0); } Size2i DisplayServerAppleEmbedded::screen_get_size(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Size2i()); + CALayer *layer = GDTAppDelegateService.viewController.godotView.renderingLayer; if (!layer) { @@ -506,6 +514,10 @@ Size2i DisplayServerAppleEmbedded::screen_get_size(int p_screen) const { } Rect2i DisplayServerAppleEmbedded::screen_get_usable_rect(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i()); + return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen)); } @@ -550,7 +562,8 @@ void DisplayServerAppleEmbedded::window_set_title(const String &p_title, WindowI } int DisplayServerAppleEmbedded::window_get_current_screen(WindowID p_window) const { - return SCREEN_OF_MAIN_WINDOW; + ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, INVALID_SCREEN); + return 0; } void DisplayServerAppleEmbedded::window_set_current_screen(int p_screen, WindowID p_window) { @@ -640,7 +653,10 @@ float DisplayServerAppleEmbedded::screen_get_max_scale() const { } void DisplayServerAppleEmbedded::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) { - screen_orientation = p_orientation; + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX(p_screen, screen_count); + if (@available(iOS 16.0, *)) { [GDTAppDelegateService.viewController setNeedsUpdateOfSupportedInterfaceOrientations]; } @@ -652,6 +668,10 @@ void DisplayServerAppleEmbedded::screen_set_orientation(DisplayServer::ScreenOri } DisplayServer::ScreenOrientation DisplayServerAppleEmbedded::screen_get_orientation(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_LANDSCAPE); + return screen_orientation; } diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 4f0c15eb0c3..32479316adf 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -264,6 +264,10 @@ bool DisplayServerAndroid::screen_is_kept_on() const { } void DisplayServerAndroid::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX(p_screen, screen_count); + GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); ERR_FAIL_NULL(godot_io_java); @@ -271,6 +275,10 @@ void DisplayServerAndroid::screen_set_orientation(DisplayServer::ScreenOrientati } DisplayServer::ScreenOrientation DisplayServerAndroid::screen_get_orientation(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_LANDSCAPE); + GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); ERR_FAIL_NULL_V(godot_io_java, SCREEN_LANDSCAPE); @@ -295,26 +303,46 @@ int DisplayServerAndroid::get_primary_screen() const { } Point2i DisplayServerAndroid::screen_get_position(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Point2i()); + return Point2i(0, 0); } Size2i DisplayServerAndroid::screen_get_size(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Size2i()); + return OS_Android::get_singleton()->get_display_size(); } Rect2i DisplayServerAndroid::screen_get_usable_rect(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i()); + Size2i display_size = OS_Android::get_singleton()->get_display_size(); return Rect2i(0, 0, display_size.width, display_size.height); } int DisplayServerAndroid::screen_get_dpi(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 160); + GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); - ERR_FAIL_NULL_V(godot_io_java, 0); + ERR_FAIL_NULL_V(godot_io_java, 160); return godot_io_java->get_screen_dpi(); } float DisplayServerAndroid::screen_get_scale(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 1.0f); + GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); ERR_FAIL_NULL_V(godot_io_java, 1.0f); @@ -332,6 +360,10 @@ float DisplayServerAndroid::screen_get_scale(int p_screen) const { } float DisplayServerAndroid::screen_get_refresh_rate(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK); + GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); if (!godot_io_java) { ERR_PRINT("An error occurred while trying to get the screen refresh rate."); @@ -487,7 +519,8 @@ void DisplayServerAndroid::window_set_title(const String &p_title, DisplayServer } int DisplayServerAndroid::window_get_current_screen(DisplayServer::WindowID p_window) const { - return SCREEN_OF_MAIN_WINDOW; + ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, INVALID_SCREEN); + return 0; } void DisplayServerAndroid::window_set_current_screen(int p_screen, DisplayServer::WindowID p_window) { diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm index 2d49bd63c47..fa42f8b3a2e 100644 --- a/platform/ios/display_server_ios.mm +++ b/platform/ios/display_server_ios.mm @@ -59,6 +59,10 @@ String DisplayServerIOS::get_name() const { } int DisplayServerIOS::screen_get_dpi(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 72); + struct utsname systemInfo; uname(&systemInfo); @@ -96,6 +100,10 @@ int DisplayServerIOS::screen_get_dpi(int p_screen) const { } float DisplayServerIOS::screen_get_refresh_rate(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK); + float fps = [UIScreen mainScreen].maximumFramesPerSecond; if ([NSProcessInfo processInfo].lowPowerModeEnabled) { fps = 60; @@ -104,5 +112,9 @@ float DisplayServerIOS::screen_get_refresh_rate(int p_screen) const { } float DisplayServerIOS::screen_get_scale(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 1.0f); + return [UIScreen mainScreen].scale; } diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 421c16f67ae..5805d989581 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -576,9 +576,9 @@ int DisplayServerWayland::get_primary_screen() const { Point2i DisplayServerWayland::screen_get_position(int p_screen) const { MutexLock mutex_lock(wayland_thread.mutex); - if (p_screen == SCREEN_OF_MAIN_WINDOW) { - p_screen = window_get_current_screen(); - } + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Point2i()); return wayland_thread.screen_get_data(p_screen).position; } @@ -586,24 +586,27 @@ Point2i DisplayServerWayland::screen_get_position(int p_screen) const { Size2i DisplayServerWayland::screen_get_size(int p_screen) const { MutexLock mutex_lock(wayland_thread.mutex); - if (p_screen == SCREEN_OF_MAIN_WINDOW) { - p_screen = window_get_current_screen(); - } + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Size2i()); return wayland_thread.screen_get_data(p_screen).size; } Rect2i DisplayServerWayland::screen_get_usable_rect(int p_screen) const { - // Unsupported on wayland. - return Rect2i(Point2i(), screen_get_size(p_screen)); + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i()); + + return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen)); } int DisplayServerWayland::screen_get_dpi(int p_screen) const { MutexLock mutex_lock(wayland_thread.mutex); - if (p_screen == SCREEN_OF_MAIN_WINDOW) { - p_screen = window_get_current_screen(); - } + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 96); const WaylandThread::ScreenData &data = wayland_thread.screen_get_data(p_screen); @@ -636,15 +639,19 @@ float DisplayServerWayland::screen_get_scale(int p_screen) const { return wayland_thread.window_state_get_scale_factor(ws); } + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 1.0f); + return wayland_thread.screen_get_data(p_screen).scale; } float DisplayServerWayland::screen_get_refresh_rate(int p_screen) const { MutexLock mutex_lock(wayland_thread.mutex); - if (p_screen == SCREEN_OF_MAIN_WINDOW) { - p_screen = window_get_current_screen(); - } + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK); return wayland_thread.screen_get_data(p_screen).refresh_rate; } @@ -1042,6 +1049,7 @@ void DisplayServerWayland::window_set_drop_files_callback(const Callable &p_call } int DisplayServerWayland::window_get_current_screen(DisplayServer::WindowID p_window_id) const { + ERR_FAIL_COND_V(p_window_id != MAIN_WINDOW_ID, INVALID_SCREEN); // Standard Wayland APIs don't support getting the screen of a window. return 0; } diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 8bb4b09e11d..9c7066427d1 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -1206,7 +1206,8 @@ Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const { Rect2i rect(0, 0, 0, 0); p_screen = _get_screen_index(p_screen); - ERR_FAIL_COND_V(p_screen < 0, rect); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i()); // Using Xinerama Extension. bool found = false; @@ -1294,9 +1295,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const { p_screen = _get_screen_index(p_screen); int screen_count = get_screen_count(); - - // Check if screen is valid. - ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i(0, 0, 0, 0)); + ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i()); bool is_multiscreen = screen_count > 1; @@ -1600,7 +1599,8 @@ int DisplayServerX11::screen_get_dpi(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); - ERR_FAIL_INDEX_V(p_screen, get_screen_count(), 0); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 96); //Get physical monitor Dimensions through XRandR and calculate dpi Size2i sc = screen_get_size(p_screen); @@ -1677,18 +1677,9 @@ Color DisplayServerX11::screen_get_pixel(const Point2i &p_position) const { Ref DisplayServerX11::screen_get_image(int p_screen) const { ERR_FAIL_INDEX_V(p_screen, get_screen_count(), Ref()); - switch (p_screen) { - case SCREEN_PRIMARY: { - p_screen = get_primary_screen(); - } break; - case SCREEN_OF_MAIN_WINDOW: { - p_screen = window_get_current_screen(MAIN_WINDOW_ID); - } break; - default: - break; - } - - ERR_FAIL_COND_V(p_screen < 0, Ref()); + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Ref()); if (xwayland) { return Ref(); @@ -1794,7 +1785,8 @@ float DisplayServerX11::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); - ERR_FAIL_INDEX_V(p_screen, get_screen_count(), SCREEN_REFRESH_RATE_FALLBACK); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK); //Use xrandr to get screen refresh rate. if (xrandr_ext_ok) { @@ -2245,7 +2237,7 @@ int DisplayServerX11::window_get_current_screen(WindowID p_window) const { return 0; } - ERR_FAIL_COND_V(!windows.has(p_window), 0); + ERR_FAIL_COND_V(!windows.has(p_window), INVALID_SCREEN); const WindowData &wd = windows[p_window]; const Rect2i window_rect(wd.position, wd.size); @@ -2281,14 +2273,15 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); - WindowData &wd = windows[p_window]; p_screen = _get_screen_index(p_screen); - ERR_FAIL_INDEX(p_screen, get_screen_count()); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX(p_screen, screen_count); if (window_get_current_screen(p_window) == p_screen) { return; } + WindowData &wd = windows[p_window]; if (wd.embed_parent) { print_line("Embedded window can't be moved to another screen."); diff --git a/platform/macos/display_server_embedded.mm b/platform/macos/display_server_embedded.mm index 2b05e344fa4..2943750fc2b 100644 --- a/platform/macos/display_server_embedded.mm +++ b/platform/macos/display_server_embedded.mm @@ -503,24 +503,52 @@ int DisplayServerEmbedded::get_primary_screen() const { } Point2i DisplayServerEmbedded::screen_get_position(int p_screen) const { - return Size2i(); + _THREAD_SAFE_METHOD_ + + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Point2i()); + + return Point2i(0, 0); } Size2i DisplayServerEmbedded::screen_get_size(int p_screen) const { + _THREAD_SAFE_METHOD_ + + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Size2i()); + return window_get_size(MAIN_WINDOW_ID); } Rect2i DisplayServerEmbedded::screen_get_usable_rect(int p_screen) const { + _THREAD_SAFE_METHOD_ + + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i()); + return Rect2i(screen_get_position(p_screen), screen_get_size(p_screen)); } int DisplayServerEmbedded::screen_get_dpi(int p_screen) const { + _THREAD_SAFE_METHOD_ + + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 72); + return 96; } float DisplayServerEmbedded::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK); + p_screen = _get_screen_index(p_screen); NSArray *screenArray = [NSScreen screens]; if ((NSUInteger)p_screen < [screenArray count]) { @@ -556,7 +584,10 @@ void DisplayServerEmbedded::window_set_title(const String &p_title, WindowID p_w } int DisplayServerEmbedded::window_get_current_screen(WindowID p_window) const { - return SCREEN_OF_MAIN_WINDOW; + _THREAD_SAFE_METHOD_ + ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, INVALID_SCREEN); + + return 0; } void DisplayServerEmbedded::window_set_current_screen(int p_screen, WindowID p_window) { diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 9892ee511cf..057d5c52464 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -1718,13 +1718,16 @@ int DisplayServerMacOS::get_primary_screen() const { int DisplayServerMacOS::get_keyboard_focus_screen() const { const NSUInteger index = [[NSScreen screens] indexOfObject:[NSScreen mainScreen]]; - return (index == NSNotFound) ? 0 : index; + return (index == NSNotFound) ? get_primary_screen() : index; } Point2i DisplayServerMacOS::screen_get_position(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Point2i()); + Point2i position = _get_native_screen_position(p_screen) - _get_screens_origin(); // macOS native y-coordinate relative to _get_screens_origin() is negative, // Godot expects a positive value. @@ -1736,6 +1739,9 @@ Size2i DisplayServerMacOS::screen_get_size(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Size2i()); + NSArray *screenArray = [NSScreen screens]; if ((NSUInteger)p_screen < [screenArray count]) { // Note: Use frame to get the whole screen size. @@ -1750,6 +1756,9 @@ int DisplayServerMacOS::screen_get_dpi(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 72); + NSArray *screenArray = [NSScreen screens]; if ((NSUInteger)p_screen < [screenArray count]) { NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription]; @@ -1771,6 +1780,9 @@ float DisplayServerMacOS::screen_get_scale(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 1.0f); + if (OS::get_singleton()->is_hidpi_allowed()) { NSArray *screens = NSScreen.screens; NSUInteger index = (NSUInteger)p_screen; @@ -1793,6 +1805,9 @@ Rect2i DisplayServerMacOS::screen_get_usable_rect(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i()); + NSArray *screenArray = [NSScreen screens]; if ((NSUInteger)p_screen < [screenArray count]) { const float scale = screen_get_max_scale(); @@ -1849,7 +1864,9 @@ Color DisplayServerMacOS::screen_get_pixel(const Point2i &p_position) const { } Ref DisplayServerMacOS::screen_get_image(int p_screen) const { - ERR_FAIL_INDEX_V(p_screen, get_screen_count(), Ref()); + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Ref()); HashSet exclude_windows; for (HashMap::ConstIterator E = windows.begin(); E; ++E) { @@ -1950,6 +1967,9 @@ float DisplayServerMacOS::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK); + NSArray *screenArray = [NSScreen screens]; if ((NSUInteger)p_screen < [screenArray count]) { NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription]; @@ -2144,7 +2164,7 @@ void DisplayServerMacOS::window_set_mouse_passthrough(const Vector &p_r int DisplayServerMacOS::window_get_current_screen(WindowID p_window) const { _THREAD_SAFE_METHOD_ - ERR_FAIL_COND_V(!windows.has(p_window), -1); + ERR_FAIL_COND_V(!windows.has(p_window), INVALID_SCREEN); const WindowData &wd = windows[p_window]; const NSUInteger index = [[NSScreen screens] indexOfObject:[wd.window_object screen]]; @@ -2155,11 +2175,15 @@ void DisplayServerMacOS::window_set_current_screen(int p_screen, WindowID p_wind _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); - WindowData &wd = windows[p_window]; + + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX(p_screen, screen_count); if (window_get_current_screen(p_window) == p_screen) { return; } + WindowData &wd = windows[p_window]; bool was_fullscreen = false; if (wd.fullscreen) { diff --git a/platform/visionos/display_server_visionos.mm b/platform/visionos/display_server_visionos.mm index 8c385e2694a..76c6938d51c 100644 --- a/platform/visionos/display_server_visionos.mm +++ b/platform/visionos/display_server_visionos.mm @@ -54,14 +54,26 @@ String DisplayServerVisionOS::get_name() const { } int DisplayServerVisionOS::screen_get_dpi(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 72); + // TODO(Apple): Compute this properly from SwiftUI Metric APIs return 72; } float DisplayServerVisionOS::screen_get_refresh_rate(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK); + return 90; } float DisplayServerVisionOS::screen_get_scale(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 1.0f); + return 1; } diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index 067cb40fcb8..961c8efd3dd 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -1217,30 +1217,54 @@ int DisplayServerWeb::get_primary_screen() const { } Point2i DisplayServerWeb::screen_get_position(int p_screen) const { - return Point2i(); // TODO offsetX/Y? + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Point2i()); + + return Point2i(0, 0); // TODO offsetX/Y? } Size2i DisplayServerWeb::screen_get_size(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Size2i()); + int size[2]; godot_js_display_screen_size_get(size, size + 1); return Size2(size[0], size[1]); } Rect2i DisplayServerWeb::screen_get_usable_rect(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i()); + int size[2]; godot_js_display_window_size_get(size, size + 1); return Rect2i(0, 0, size[0], size[1]); } int DisplayServerWeb::screen_get_dpi(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 72); + return godot_js_display_screen_dpi_get(); } float DisplayServerWeb::screen_get_scale(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 1.0f); + return godot_js_display_pixel_ratio_get(); } float DisplayServerWeb::screen_get_refresh_rate(int p_screen) const { + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK); + return SCREEN_REFRESH_RATE_FALLBACK; // Web doesn't have much of a need for the screen refresh rate, and there's no native way to do so. } @@ -1287,7 +1311,8 @@ void DisplayServerWeb::window_set_title(const String &p_title, WindowID p_window } int DisplayServerWeb::window_get_current_screen(WindowID p_window) const { - return 1; + ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, INVALID_SCREEN); + return 0; } void DisplayServerWeb::window_set_current_screen(int p_screen, WindowID p_window) { diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 026ce2f0927..d78f8b42b88 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -1202,6 +1202,9 @@ Point2i DisplayServerWindows::screen_get_position(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Point2i()); + EnumPosData data = { 0, p_screen, Point2() }; EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcPos, (LPARAM)&data); return data.pos - _get_screens_origin(); @@ -1242,6 +1245,9 @@ Size2i DisplayServerWindows::screen_get_size(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Size2i()); + EnumSizeData data = { 0, p_screen, Size2() }; EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcSize, (LPARAM)&data); return data.size; @@ -1307,6 +1313,9 @@ Rect2i DisplayServerWindows::screen_get_usable_rect(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i()); + EnumRectData data = { 0, p_screen, Rect2i() }; EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcUsableSize, (LPARAM)&data); data.rect.position -= _get_screens_origin(); @@ -1385,6 +1394,9 @@ int DisplayServerWindows::screen_get_dpi(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, 72); + EnumDpiData data = { 0, p_screen, 72 }; EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcDpi, (LPARAM)&data); return data.dpi; @@ -1413,18 +1425,9 @@ Color DisplayServerWindows::screen_get_pixel(const Point2i &p_position) const { } Ref DisplayServerWindows::screen_get_image(int p_screen) const { - ERR_FAIL_INDEX_V(p_screen, get_screen_count(), Ref()); - - switch (p_screen) { - case SCREEN_PRIMARY: { - p_screen = get_primary_screen(); - } break; - case SCREEN_OF_MAIN_WINDOW: { - p_screen = window_get_current_screen(MAIN_WINDOW_ID); - } break; - default: - break; - } + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, Ref()); Point2i pos = screen_get_position(p_screen) + _get_screens_origin(); Size2i size = screen_get_size(p_screen); @@ -1541,6 +1544,9 @@ float DisplayServerWindows::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK); + EnumRefreshRateData data = { Vector(), Vector(), 0, p_screen, SCREEN_REFRESH_RATE_FALLBACK }; uint32_t path_count = 0; @@ -2018,7 +2024,7 @@ void DisplayServerWindows::_update_window_mouse_passthrough(WindowID p_window) { int DisplayServerWindows::window_get_current_screen(WindowID p_window) const { _THREAD_SAFE_METHOD_ - ERR_FAIL_COND_V(!windows.has(p_window), -1); + ERR_FAIL_COND_V(!windows.has(p_window), INVALID_SCREEN); EnumScreenData data = { 0, 0, MonitorFromWindow(windows[p_window].hWnd, MONITOR_DEFAULTTONEAREST) }; EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcScreen, (LPARAM)&data); @@ -2029,12 +2035,16 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); - ERR_FAIL_INDEX(p_screen, get_screen_count()); + + p_screen = _get_screen_index(p_screen); + int screen_count = get_screen_count(); + ERR_FAIL_INDEX(p_screen, screen_count); if (window_get_current_screen(p_window) == p_screen) { return; } const WindowData &wd = windows[p_window]; + if (wd.parent_hwnd) { print_line("Embedded window can't be moved to another screen."); return; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index e42d8d70f0f..393eb19b527 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -585,7 +585,7 @@ bool DisplayServer::screen_is_kept_on() const { int DisplayServer::get_screen_from_rect(const Rect2 &p_rect) const { int nearest_area = 0; - int pos_screen = -1; + int pos_screen = INVALID_SCREEN; for (int i = 0; i < get_screen_count(); i++) { Rect2i r; r.position = screen_get_position(i); @@ -1758,6 +1758,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED_HIDDEN); BIND_ENUM_CONSTANT(MOUSE_MODE_MAX); + BIND_CONSTANT(INVALID_SCREEN); BIND_CONSTANT(SCREEN_WITH_MOUSE_FOCUS); BIND_CONSTANT(SCREEN_WITH_KEYBOARD_FOCUS); BIND_CONSTANT(SCREEN_PRIMARY); diff --git a/servers/display_server.h b/servers/display_server.h index a6a4d4eb85e..973b7ea5365 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -318,6 +318,7 @@ public: virtual Rect2i get_display_safe_area() const { return screen_get_usable_rect(); } enum { + INVALID_SCREEN = -1, SCREEN_WITH_MOUSE_FOCUS = -4, SCREEN_WITH_KEYBOARD_FOCUS = -3, SCREEN_PRIMARY = -2, diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index a4216ec861b..aae4602b38d 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -110,7 +110,7 @@ public: void window_set_mouse_passthrough(const Vector &p_region, WindowID p_window = MAIN_WINDOW_ID) override {} - int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override { return -1; } + int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override { return INVALID_SCREEN; } void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override {} Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override { return Point2i(); }