Merge pull request #107583 from bruvzg/non_ex_fs

[3.x] Backport nonexclusive fullscreen mode.
This commit is contained in:
lawnjelly 2025-08-29 15:32:49 +01:00 committed by GitHub
commit 5aed565de5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 113 additions and 11 deletions

View file

@ -403,6 +403,14 @@ bool _OS::is_window_fullscreen() const {
return OS::get_singleton()->is_window_fullscreen(); return OS::get_singleton()->is_window_fullscreen();
} }
void _OS::set_window_use_nonexclusive_fullscreen(bool p_enabled) {
OS::get_singleton()->set_window_use_nonexclusive_fullscreen(p_enabled);
}
bool _OS::is_window_use_nonexclusive_fullscreen() const {
return OS::get_singleton()->is_window_use_nonexclusive_fullscreen();
}
void _OS::set_window_resizable(bool p_enabled) { void _OS::set_window_resizable(bool p_enabled) {
OS::get_singleton()->set_window_resizable(p_enabled); OS::get_singleton()->set_window_resizable(p_enabled);
} }
@ -1371,6 +1379,8 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_display_cutouts"), &_OS::get_display_cutouts); ClassDB::bind_method(D_METHOD("get_display_cutouts"), &_OS::get_display_cutouts);
ClassDB::bind_method(D_METHOD("set_window_fullscreen", "enabled"), &_OS::set_window_fullscreen); ClassDB::bind_method(D_METHOD("set_window_fullscreen", "enabled"), &_OS::set_window_fullscreen);
ClassDB::bind_method(D_METHOD("is_window_fullscreen"), &_OS::is_window_fullscreen); ClassDB::bind_method(D_METHOD("is_window_fullscreen"), &_OS::is_window_fullscreen);
ClassDB::bind_method(D_METHOD("set_window_use_nonexclusive_fullscreen", "enabled"), &_OS::set_window_use_nonexclusive_fullscreen);
ClassDB::bind_method(D_METHOD("is_window_use_nonexclusive_fullscreen"), &_OS::is_window_use_nonexclusive_fullscreen);
ClassDB::bind_method(D_METHOD("set_window_resizable", "enabled"), &_OS::set_window_resizable); ClassDB::bind_method(D_METHOD("set_window_resizable", "enabled"), &_OS::set_window_resizable);
ClassDB::bind_method(D_METHOD("is_window_resizable"), &_OS::is_window_resizable); ClassDB::bind_method(D_METHOD("is_window_resizable"), &_OS::is_window_resizable);
ClassDB::bind_method(D_METHOD("set_window_minimized", "enabled"), &_OS::set_window_minimized); ClassDB::bind_method(D_METHOD("set_window_minimized", "enabled"), &_OS::set_window_minimized);
@ -1568,6 +1578,7 @@ void _OS::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_borderless"), "set_borderless_window", "get_borderless_window"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_borderless"), "set_borderless_window", "get_borderless_window");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_per_pixel_transparency_enabled"), "set_window_per_pixel_transparency_enabled", "get_window_per_pixel_transparency_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_per_pixel_transparency_enabled"), "set_window_per_pixel_transparency_enabled", "get_window_per_pixel_transparency_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_fullscreen"), "set_window_fullscreen", "is_window_fullscreen"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_fullscreen"), "set_window_fullscreen", "is_window_fullscreen");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_use_nonexclusive_fullscreen"), "set_window_use_nonexclusive_fullscreen", "is_window_use_nonexclusive_fullscreen");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_maximized"), "set_window_maximized", "is_window_maximized"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_maximized"), "set_window_maximized", "is_window_maximized");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_minimized"), "set_window_minimized", "is_window_minimized"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_minimized"), "set_window_minimized", "is_window_minimized");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_resizable"), "set_window_resizable", "is_window_resizable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_resizable"), "set_window_resizable", "is_window_resizable");

View file

@ -225,6 +225,8 @@ public:
virtual void set_window_size(const Size2 &p_size); virtual void set_window_size(const Size2 &p_size);
virtual void set_window_fullscreen(bool p_enabled); virtual void set_window_fullscreen(bool p_enabled);
virtual bool is_window_fullscreen() const; virtual bool is_window_fullscreen() const;
virtual void set_window_use_nonexclusive_fullscreen(bool p_enabled);
virtual bool is_window_use_nonexclusive_fullscreen() const;
virtual void set_window_resizable(bool p_enabled); virtual void set_window_resizable(bool p_enabled);
virtual bool is_window_resizable() const; virtual bool is_window_resizable() const;
virtual void set_window_minimized(bool p_enabled); virtual void set_window_minimized(bool p_enabled);

View file

@ -107,6 +107,7 @@ public:
struct VideoMode { struct VideoMode {
int width, height; int width, height;
bool fullscreen; bool fullscreen;
bool non_ex_fs;
bool resizable; bool resizable;
bool borderless_window; bool borderless_window;
bool maximized; bool maximized;
@ -126,6 +127,7 @@ public:
use_vsync = p_use_vsync; use_vsync = p_use_vsync;
vsync_via_compositor = p_vsync_via_compositor; vsync_via_compositor = p_vsync_via_compositor;
layered = false; layered = false;
non_ex_fs = false;
} }
}; };
@ -282,6 +284,8 @@ public:
virtual void set_window_size(const Size2 p_size) {} virtual void set_window_size(const Size2 p_size) {}
virtual void set_window_fullscreen(bool p_enabled) {} virtual void set_window_fullscreen(bool p_enabled) {}
virtual bool is_window_fullscreen() const { return true; } virtual bool is_window_fullscreen() const { return true; }
virtual void set_window_use_nonexclusive_fullscreen(bool p_enabled) {}
virtual bool is_window_use_nonexclusive_fullscreen() const { return false; }
virtual void set_window_resizable(bool p_enabled) {} virtual void set_window_resizable(bool p_enabled) {}
virtual bool is_window_resizable() const { return false; } virtual bool is_window_resizable() const { return false; }
virtual void set_window_minimized(bool p_enabled) {} virtual void set_window_minimized(bool p_enabled) {}

View file

@ -1082,6 +1082,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("display/window/size/resizable", true); GLOBAL_DEF("display/window/size/resizable", true);
GLOBAL_DEF("display/window/size/borderless", false); GLOBAL_DEF("display/window/size/borderless", false);
GLOBAL_DEF("display/window/size/fullscreen", false); GLOBAL_DEF("display/window/size/fullscreen", false);
GLOBAL_DEF("display/window/size/use_nonexclusive_fullscreen", false);
GLOBAL_DEF("display/window/size/always_on_top", false); GLOBAL_DEF("display/window/size/always_on_top", false);
GLOBAL_DEF("display/window/size/test_width", 0); GLOBAL_DEF("display/window/size/test_width", 0);
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_width", PropertyInfo(Variant::INT, "display/window/size/test_width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater")); // 8K resolution ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_width", PropertyInfo(Variant::INT, "display/window/size/test_width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater")); // 8K resolution

View file

@ -1211,7 +1211,7 @@
[b]Note:[/b] Setting [code]window_borderless[/code] to [code]false[/code] disables per-pixel transparency. [b]Note:[/b] Setting [code]window_borderless[/code] to [code]false[/code] disables per-pixel transparency.
</member> </member>
<member name="window_fullscreen" type="bool" setter="set_window_fullscreen" getter="is_window_fullscreen" default="false"> <member name="window_fullscreen" type="bool" setter="set_window_fullscreen" getter="is_window_fullscreen" default="false">
If [code]true[/code], the window is fullscreen. If [code]true[/code], the window is fullscreen. See also [member window_use_nonexclusive_fullscreen].
</member> </member>
<member name="window_maximized" type="bool" setter="set_window_maximized" getter="is_window_maximized" default="false"> <member name="window_maximized" type="bool" setter="set_window_maximized" getter="is_window_maximized" default="false">
If [code]true[/code], the window is maximized. If [code]true[/code], the window is maximized.
@ -1234,6 +1234,11 @@
<member name="window_size" type="Vector2" setter="set_window_size" getter="get_window_size" default="Vector2( 0, 0 )"> <member name="window_size" type="Vector2" setter="set_window_size" getter="get_window_size" default="Vector2( 0, 0 )">
The size of the window (without counting window manager decorations). The size of the window (without counting window manager decorations).
</member> </member>
<member name="window_use_nonexclusive_fullscreen" type="bool" setter="set_window_use_nonexclusive_fullscreen" getter="is_window_use_nonexclusive_fullscreen" default="false">
If [code]true[/code] and [member window_fullscreen] is set, a full screen mode with full multi-window support is used.
If [code]false[/code] and [member window_fullscreen] is set, a single window fullscreen mode is used, this mode has less overhead, but only one window can be open on a given screen at a time (opening a application switching will trigger a full screen transition). This mode might not work with screen recording software.
[b]Note:[/b] This property is only implemented on Windows.
</member>
</members> </members>
<constants> <constants>
<constant name="VIDEO_DRIVER_GLES2" value="1" enum="VideoDriver"> <constant name="VIDEO_DRIVER_GLES2" value="1" enum="VideoDriver">

View file

@ -539,8 +539,9 @@
[b]Note:[/b] This setting is ignored on iOS, Android, and HTML5. [b]Note:[/b] This setting is ignored on iOS, Android, and HTML5.
</member> </member>
<member name="display/window/size/fullscreen" type="bool" setter="" getter="" default="false"> <member name="display/window/size/fullscreen" type="bool" setter="" getter="" default="false">
Sets the main window to full screen when the project starts. Note that this is not [i]exclusive[/i] fullscreen. On Windows and Linux, a borderless window is used to emulate fullscreen. On macOS, a new desktop is used to display the running project. Sets the main window to full screen when the project starts. The display's video mode is not changed. See also [member display/window/size/use_nonexclusive_fullscreen].
Regardless of the platform, enabling fullscreen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling fullscreen mode. Regardless of the platform, enabling fullscreen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling fullscreen mode.
[b]Note:[/b] On macOS, a new desktop is used to display the running project.
[b]Note:[/b] This setting is ignored on iOS, Android, and HTML5. [b]Note:[/b] This setting is ignored on iOS, Android, and HTML5.
</member> </member>
<member name="display/window/size/height" type="int" setter="" getter="" default="600"> <member name="display/window/size/height" type="int" setter="" getter="" default="600">
@ -556,6 +557,11 @@
<member name="display/window/size/test_width" type="int" setter="" getter="" default="0"> <member name="display/window/size/test_width" type="int" setter="" getter="" default="0">
If greater than zero, overrides the window width when running the game. Useful for testing stretch modes. If greater than zero, overrides the window width when running the game. Useful for testing stretch modes.
</member> </member>
<member name="display/window/size/use_nonexclusive_fullscreen" type="bool" setter="" getter="" default="false">
If [code]true[/code] and [member display/window/size/fullscreen] is set, a full screen mode with full multi-window support is used.
If [code]false[/code] and [member display/window/size/fullscreen] is set, a single window fullscreen mode is used, this mode has less overhead, but only one window can be open on a given screen at a time (opening a application switching will trigger a full screen transition). This mode might not work with screen recording software.
[b]Note:[/b] This property is only implemented on Windows.
</member>
<member name="display/window/size/width" type="int" setter="" getter="" default="1024"> <member name="display/window/size/width" type="int" setter="" getter="" default="1024">
Sets the game's main viewport width. On desktop platforms, this is the default window size. Stretch mode settings also use this as a reference when enabled. Sets the game's main viewport width. On desktop platforms, this is the default window size. Stretch mode settings also use this as a reference when enabled.
</member> </member>

View file

@ -151,6 +151,7 @@ HashMap<Main::CLIScope, Vector<String>> forwardable_cli_arguments;
static OS::VideoMode video_mode; static OS::VideoMode video_mode;
static int init_screen = -1; static int init_screen = -1;
static bool init_fullscreen = false; static bool init_fullscreen = false;
static bool init_non_ex_fs = false;
static bool init_maximized = false; static bool init_maximized = false;
static bool init_windowed = false; static bool init_windowed = false;
static bool init_always_on_top = false; static bool init_always_on_top = false;
@ -641,6 +642,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "-f" || I->get() == "--fullscreen") { // force fullscreen } else if (I->get() == "-f" || I->get() == "--fullscreen") { // force fullscreen
init_fullscreen = true; init_fullscreen = true;
} else if (I->get() == "--nonexclusive-fullscreen") { // force fullscreen
init_fullscreen = true;
init_non_ex_fs = true;
} else if (I->get() == "-m" || I->get() == "--maximized") { // force maximized window } else if (I->get() == "-m" || I->get() == "--maximized") { // force maximized window
init_maximized = true; init_maximized = true;
@ -1141,6 +1146,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (editor || project_manager) { if (editor || project_manager) {
Engine::get_singleton()->set_editor_hint(true); Engine::get_singleton()->set_editor_hint(true);
use_custom_res = false; use_custom_res = false;
init_non_ex_fs = true;
input_map->load_default(); //keys for editor input_map->load_default(); //keys for editor
} else { } else {
input_map->load_from_globals(); //keys for game input_map->load_from_globals(); //keys for game
@ -1192,6 +1198,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
video_mode.resizable = GLOBAL_GET("display/window/size/resizable"); video_mode.resizable = GLOBAL_GET("display/window/size/resizable");
video_mode.borderless_window = GLOBAL_GET("display/window/size/borderless"); video_mode.borderless_window = GLOBAL_GET("display/window/size/borderless");
video_mode.fullscreen = GLOBAL_GET("display/window/size/fullscreen"); video_mode.fullscreen = GLOBAL_GET("display/window/size/fullscreen");
video_mode.non_ex_fs = GLOBAL_GET("display/window/size/use_nonexclusive_fullscreen");
video_mode.always_on_top = GLOBAL_GET("display/window/size/always_on_top"); video_mode.always_on_top = GLOBAL_GET("display/window/size/always_on_top");
} }
@ -1487,6 +1494,9 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
if (init_screen != -1) { if (init_screen != -1) {
OS::get_singleton()->set_current_screen(init_screen); OS::get_singleton()->set_current_screen(init_screen);
} }
if (init_non_ex_fs) {
OS::get_singleton()->set_window_use_nonexclusive_fullscreen(true);
}
if (init_windowed) { if (init_windowed) {
//do none.. //do none..
} else if (init_maximized) { } else if (init_maximized) {

View file

@ -71,6 +71,8 @@ __declspec(dllexport) void NoHotPatch() {} // Disable Nahimic code injection.
#define GetProcAddress (void *)GetProcAddress #define GetProcAddress (void *)GetProcAddress
#endif #endif
int constexpr FS_TRANSP_BORDER = 2;
typedef struct { typedef struct {
int count; int count;
int screen; int screen;
@ -1430,6 +1432,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
WindowRect.bottom = current.dmPelsHeight; WindowRect.bottom = current.dmPelsHeight;
*/ */
int off_x = video_mode.non_ex_fs ? FS_TRANSP_BORDER : 0;
// Get the primary monitor without providing hwnd // Get the primary monitor without providing hwnd
// Solution from https://devblogs.microsoft.com/oldnewthing/20070809-00/?p=25643 // Solution from https://devblogs.microsoft.com/oldnewthing/20070809-00/?p=25643
@ -1440,7 +1443,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
EnumSizeData data = { 0, primary_data.screen, Size2() }; EnumSizeData data = { 0, primary_data.screen, Size2() };
EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcSize, (LPARAM)&data); EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcSize, (LPARAM)&data);
WindowRect.right = data.size.width; WindowRect.right = data.size.width + off_x;
WindowRect.bottom = data.size.height; WindowRect.bottom = data.size.height;
/* DEVMODE dmScreenSettings; /* DEVMODE dmScreenSettings;
@ -1706,6 +1709,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
} }
update_real_mouse_position(); update_real_mouse_position();
_update_window_mouse_passthrough();
return OK; return OK;
} }
@ -1869,9 +1873,11 @@ void OS_Windows::set_mouse_mode(MouseMode p_mode) {
void OS_Windows::_set_mouse_mode_impl(MouseMode p_mode) { void OS_Windows::_set_mouse_mode_impl(MouseMode p_mode) {
if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) { if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) {
int off_x = (video_mode.fullscreen && video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
// Mouse is grabbed (captured or confined). // Mouse is grabbed (captured or confined).
RECT clipRect; RECT clipRect;
GetClientRect(hWnd, &clipRect); GetClientRect(hWnd, &clipRect);
clipRect.right -= off_x;
ClientToScreen(hWnd, (POINT *)&clipRect.left); ClientToScreen(hWnd, (POINT *)&clipRect.left);
ClientToScreen(hWnd, (POINT *)&clipRect.right); ClientToScreen(hWnd, (POINT *)&clipRect.right);
ClipCursor(&clipRect); ClipCursor(&clipRect);
@ -1952,7 +1958,16 @@ void OS_Windows::set_window_mouse_passthrough(const PoolVector2Array &p_region)
void OS_Windows::_update_window_mouse_passthrough() { void OS_Windows::_update_window_mouse_passthrough() {
if (mpath.size() == 0) { if (mpath.size() == 0) {
if (video_mode.non_ex_fs && video_mode.fullscreen) {
int cs = get_current_screen();
Size2 size = get_screen_size(cs);
HRGN region = CreateRectRgn(0, 0, size.width, size.height);
SetWindowRgn(hWnd, region, FALSE);
DeleteObject(region);
} else {
SetWindowRgn(hWnd, NULL, TRUE); SetWindowRgn(hWnd, NULL, TRUE);
}
} else { } else {
POINT *points = (POINT *)memalloc(sizeof(POINT) * mpath.size()); POINT *points = (POINT *)memalloc(sizeof(POINT) * mpath.size());
for (int i = 0; i < mpath.size(); i++) { for (int i = 0; i < mpath.size(); i++) {
@ -1966,7 +1981,15 @@ void OS_Windows::_update_window_mouse_passthrough() {
} }
HRGN region = CreatePolygonRgn(points, mpath.size(), ALTERNATE); HRGN region = CreatePolygonRgn(points, mpath.size(), ALTERNATE);
SetWindowRgn(hWnd, region, TRUE); if (video_mode.non_ex_fs && video_mode.fullscreen) {
int cs = get_current_screen();
Size2 size = get_screen_size(cs);
HRGN region_clip = CreateRectRgn(0, 0, size.width, size.height);
CombineRgn(region, region, region_clip, RGN_AND);
DeleteObject(region_clip);
}
SetWindowRgn(hWnd, region, FALSE);
DeleteObject(region); DeleteObject(region);
memfree(points); memfree(points);
} }
@ -2007,8 +2030,9 @@ void OS_Windows::set_current_screen(int p_screen) {
} }
Point2 pos = get_screen_position(p_screen); Point2 pos = get_screen_position(p_screen);
Size2 size = get_screen_size(p_screen); Size2 size = get_screen_size(p_screen);
int off_x = (video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE); MoveWindow(hWnd, pos.x, pos.y, size.width + off_x, size.height, TRUE);
} else { } else {
Vector2 ofs = get_window_position() - get_screen_position(get_current_screen()); Vector2 ofs = get_window_position() - get_screen_position(get_current_screen());
set_window_position(ofs + get_screen_position(p_screen)); set_window_position(ofs + get_screen_position(p_screen));
@ -2137,7 +2161,9 @@ Size2 OS_Windows::get_window_size() const {
RECT r; RECT r;
if (GetClientRect(hWnd, &r)) { // Only area inside of window border if (GetClientRect(hWnd, &r)) { // Only area inside of window border
return Size2(r.right - r.left, r.bottom - r.top); int off_x = (video_mode.fullscreen && video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
return Size2(r.right - r.left - off_x, r.bottom - r.top);
} }
return Size2(); return Size2();
} }
@ -2169,7 +2195,9 @@ void OS_Windows::set_max_window_size(const Size2 p_size) {
Size2 OS_Windows::get_real_window_size() const { Size2 OS_Windows::get_real_window_size() const {
RECT r; RECT r;
if (GetWindowRect(hWnd, &r)) { // Includes area of the window border if (GetWindowRect(hWnd, &r)) { // Includes area of the window border
return Size2(r.right - r.left, r.bottom - r.top); int off_x = (video_mode.fullscreen && video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
return Size2(r.right - r.left - off_x, r.bottom - r.top);
} }
return Size2(); return Size2();
} }
@ -2208,8 +2236,9 @@ void OS_Windows::set_window_size(const Size2 p_size) {
} }
} }
void OS_Windows::set_window_fullscreen(bool p_enabled) { void OS_Windows::set_window_fullscreen(bool p_enabled) {
if (video_mode.fullscreen == p_enabled) if (video_mode.fullscreen == p_enabled) {
return; return;
}
if (layered_window) if (layered_window)
set_window_per_pixel_transparency_enabled(false); set_window_per_pixel_transparency_enabled(false);
@ -2228,8 +2257,9 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) {
video_mode.fullscreen = true; video_mode.fullscreen = true;
_update_window_style(false); _update_window_style(false);
int off_x = (video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE); MoveWindow(hWnd, pos.x, pos.y, size.width + off_x, size.height, TRUE);
SystemParametersInfoA(SPI_GETMOUSETRAILS, 0, &restore_mouse_trails, 0); SystemParametersInfoA(SPI_GETMOUSETRAILS, 0, &restore_mouse_trails, 0);
if (restore_mouse_trails > 1) { if (restore_mouse_trails > 1) {
@ -2259,10 +2289,39 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) {
SystemParametersInfoA(SPI_SETMOUSETRAILS, restore_mouse_trails, 0, 0); SystemParametersInfoA(SPI_SETMOUSETRAILS, restore_mouse_trails, 0, 0);
} }
} }
_update_window_mouse_passthrough();
} }
void OS_Windows::set_window_use_nonexclusive_fullscreen(bool p_enabled) {
if (video_mode.non_ex_fs == p_enabled) {
return;
}
video_mode.non_ex_fs = p_enabled;
if (video_mode.fullscreen) {
int cs = get_current_screen();
Point2 pos = get_screen_position(cs);
Size2 size = get_screen_size(cs);
video_mode.fullscreen = true;
_update_window_style(false);
int off_x = (video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
MoveWindow(hWnd, pos.x, pos.y, size.width + off_x, size.height, TRUE);
_update_window_mouse_passthrough();
}
}
bool OS_Windows::is_window_fullscreen() const { bool OS_Windows::is_window_fullscreen() const {
return video_mode.fullscreen; return video_mode.fullscreen;
} }
bool OS_Windows::is_window_use_nonexclusive_fullscreen() const {
return video_mode.non_ex_fs;
}
void OS_Windows::set_window_resizable(bool p_enabled) { void OS_Windows::set_window_resizable(bool p_enabled) {
if (video_mode.resizable == p_enabled) if (video_mode.resizable == p_enabled)
return; return;
@ -2402,7 +2461,8 @@ void OS_Windows::_update_window_style(bool p_repaint, bool p_maximized) {
if (p_repaint) { if (p_repaint) {
RECT rect; RECT rect;
GetWindowRect(hWnd, &rect); GetWindowRect(hWnd, &rect);
MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); int off_x = (video_mode.fullscreen && video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left + off_x, rect.bottom - rect.top, TRUE);
} }
} }

View file

@ -344,6 +344,7 @@ class OS_Windows : public OS {
Size2 window_rect; Size2 window_rect;
VideoMode video_mode; VideoMode video_mode;
bool non_ex_fs = false;
bool preserve_window_size = false; bool preserve_window_size = false;
MainLoop *main_loop; MainLoop *main_loop;
@ -486,6 +487,8 @@ public:
virtual void set_window_size(const Size2 p_size); virtual void set_window_size(const Size2 p_size);
virtual void set_window_fullscreen(bool p_enabled); virtual void set_window_fullscreen(bool p_enabled);
virtual bool is_window_fullscreen() const; virtual bool is_window_fullscreen() const;
virtual void set_window_use_nonexclusive_fullscreen(bool p_enabled);
virtual bool is_window_use_nonexclusive_fullscreen() const;
virtual void set_window_resizable(bool p_enabled); virtual void set_window_resizable(bool p_enabled);
virtual bool is_window_resizable() const; virtual bool is_window_resizable() const;
virtual void set_window_minimized(bool p_enabled); virtual void set_window_minimized(bool p_enabled);