Skip to content
This repository was archived by the owner on Sep 3, 2022. It is now read-only.

Commit 225a3b2

Browse files
authored
Merge pull request godotengine#57341 from bruvzg/win_multiwin_fs
2 parents 2e320dc + f4ea9cd commit 225a3b2

12 files changed

+49
-13
lines changed

doc/classes/DisplayServer.xml

+5
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,11 @@
908908
Fullscreen window mode. 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.
909909
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.
910910
</constant>
911+
<constant name="WINDOW_MODE_EXCLUSIVE_FULLSCREEN" value="4" enum="WindowMode">
912+
Exclusive fullscreen window mode. This mode is implemented on Windows only. On other platforms, it is equivalent to [constant WINDOW_MODE_FULLSCREEN].
913+
Only one window in exclusive fullscreen mode can be visible on a given screen at a time. If multiple windows are in exclusive fullscreen mode for the same screen, the last one being set to this mode takes precedence.
914+
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.
915+
</constant>
911916
<constant name="WINDOW_FLAG_RESIZE_DISABLED" value="0" enum="WindowFlags">
912917
</constant>
913918
<constant name="WINDOW_FLAG_BORDERLESS" value="1" enum="WindowFlags">

doc/classes/Window.xml

+5
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,11 @@
398398
Fullscreen window mode. 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.
399399
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.
400400
</constant>
401+
<constant name="MODE_EXCLUSIVE_FULLSCREEN" value="4" enum="Mode">
402+
Exclusive fullscreen window mode. This mode is implemented on Windows only. On other platforms, it is equivalent to [constant MODE_FULLSCREEN].
403+
Only one window in exclusive fullscreen mode can be visible on a given screen at a time. If multiple windows are in exclusive fullscreen mode for the same screen, the last one being set to this mode takes precedence.
404+
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.
405+
</constant>
401406
<constant name="FLAG_RESIZE_DISABLED" value="0" enum="Flags">
402407
The window's ability to be resized.
403408
</constant>

platform/javascript/display_server_javascript.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
663663
godot_js_config_canvas_id_get(canvas_id, 256);
664664

665665
// Handle contextmenu, webglcontextlost
666-
godot_js_display_setup_canvas(p_resolution.x, p_resolution.y, p_window_mode == WINDOW_MODE_FULLSCREEN, OS::get_singleton()->is_hidpi_allowed() ? 1 : 0);
666+
godot_js_display_setup_canvas(p_resolution.x, p_resolution.y, (p_window_mode == WINDOW_MODE_FULLSCREEN || p_window_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), OS::get_singleton()->is_hidpi_allowed() ? 1 : 0);
667667

668668
// Check if it's windows.
669669
swap_cancel_ok = godot_js_display_is_swap_ok_cancel() == 1;
@@ -901,6 +901,7 @@ void DisplayServerJavaScript::window_set_mode(WindowMode p_mode, WindowID p_wind
901901
}
902902
window_mode = WINDOW_MODE_WINDOWED;
903903
} break;
904+
case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
904905
case WINDOW_MODE_FULLSCREEN: {
905906
int result = godot_js_display_fullscreen_request();
906907
ERR_FAIL_COND_MSG(result, "The request was denied. Remember that enabling fullscreen is only possible from an input callback for the HTML5 platform.");

platform/linuxbsd/display_server_x11.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1885,6 +1885,7 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
18851885

18861886
XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
18871887
} break;
1888+
case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
18881889
case WINDOW_MODE_FULLSCREEN: {
18891890
//Remove full-screen
18901891
wd.fullscreen = false;
@@ -1937,6 +1938,7 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
19371938

19381939
XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
19391940
} break;
1941+
case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
19401942
case WINDOW_MODE_FULLSCREEN: {
19411943
wd.last_position_before_fs = wd.position;
19421944

platform/osx/display_server_osx.mm

+2
Original file line numberDiff line numberDiff line change
@@ -2670,6 +2670,7 @@ static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplay
26702670
case WINDOW_MODE_MINIMIZED: {
26712671
[wd.window_object deminiaturize:nil];
26722672
} break;
2673+
case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
26732674
case WINDOW_MODE_FULLSCREEN: {
26742675
[wd.window_object setLevel:NSNormalWindowLevel];
26752676
if (wd.layered_window) {
@@ -2703,6 +2704,7 @@ static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplay
27032704
case WINDOW_MODE_MINIMIZED: {
27042705
[wd.window_object performMiniaturize:nil];
27052706
} break;
2707+
case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
27062708
case WINDOW_MODE_FULLSCREEN: {
27072709
if (wd.layered_window)
27082710
_set_window_per_pixel_transparency_enabled(false, p_window);

platform/windows/display_server_windows.cpp

+25-9
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod
539539
if (p_flags & WINDOW_FLAG_BORDERLESS_BIT) {
540540
wd.borderless = true;
541541
}
542-
if (p_flags & WINDOW_FLAG_ALWAYS_ON_TOP_BIT && p_mode != WINDOW_MODE_FULLSCREEN) {
542+
if (p_flags & WINDOW_FLAG_ALWAYS_ON_TOP_BIT && p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
543543
wd.always_on_top = true;
544544
}
545545
if (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) {
@@ -979,7 +979,7 @@ Size2i DisplayServerWindows::window_get_real_size(WindowID p_window) const {
979979
return Size2();
980980
}
981981

982-
void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscreen, bool p_borderless, bool p_resizable, bool p_maximized, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) {
982+
void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) {
983983
// Windows docs for window styles:
984984
// https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles
985985
// https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
@@ -992,6 +992,9 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre
992992

993993
if (p_fullscreen || p_borderless) {
994994
r_style |= WS_POPUP; // p_borderless was WS_EX_TOOLWINDOW in the past.
995+
if (p_fullscreen && p_multiwindow_fs) {
996+
r_style |= WS_BORDER; // Allows child windows to be displayed on top of full screen.
997+
}
995998
} else {
996999
if (p_resizable) {
9971000
if (p_maximized) {
@@ -1022,7 +1025,7 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain
10221025
DWORD style = 0;
10231026
DWORD style_ex = 0;
10241027

1025-
_get_window_style(p_window == MAIN_WINDOW_ID, wd.fullscreen, wd.borderless, wd.resizable, wd.maximized, wd.no_focus, style, style_ex);
1028+
_get_window_style(p_window == MAIN_WINDOW_ID, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.maximized, wd.no_focus, style, style_ex);
10261029

10271030
SetWindowLongPtr(wd.hWnd, GWL_STYLE, style);
10281031
SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex);
@@ -1042,10 +1045,11 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
10421045
ERR_FAIL_COND(!windows.has(p_window));
10431046
WindowData &wd = windows[p_window];
10441047

1045-
if (wd.fullscreen && p_mode != WINDOW_MODE_FULLSCREEN) {
1048+
if (wd.fullscreen && p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
10461049
RECT rect;
10471050

10481051
wd.fullscreen = false;
1052+
wd.multiwindow_fs = false;
10491053
wd.maximized = wd.was_maximized;
10501054

10511055
if (wd.pre_fs_valid) {
@@ -1084,7 +1088,15 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
10841088
wd.minimized = true;
10851089
}
10861090

1087-
if (p_mode == WINDOW_MODE_FULLSCREEN && !wd.fullscreen) {
1091+
if (p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
1092+
wd.multiwindow_fs = false;
1093+
_update_window_style(false);
1094+
} else {
1095+
wd.multiwindow_fs = true;
1096+
_update_window_style(false);
1097+
}
1098+
1099+
if ((p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) && !wd.fullscreen) {
10881100
if (wd.minimized) {
10891101
ShowWindow(wd.hWnd, SW_RESTORE);
10901102
}
@@ -1131,7 +1143,11 @@ DisplayServer::WindowMode DisplayServerWindows::window_get_mode(WindowID p_windo
11311143
const WindowData &wd = windows[p_window];
11321144

11331145
if (wd.fullscreen) {
1134-
return WINDOW_MODE_FULLSCREEN;
1146+
if (wd.multiwindow_fs) {
1147+
return WINDOW_MODE_FULLSCREEN;
1148+
} else {
1149+
return WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
1150+
}
11351151
} else if (wd.minimized) {
11361152
return WINDOW_MODE_MINIMIZED;
11371153
} else if (wd.maximized) {
@@ -3095,7 +3111,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
30953111
DWORD dwExStyle;
30963112
DWORD dwStyle;
30973113

3098-
_get_window_style(window_id_counter == MAIN_WINDOW_ID, p_mode == WINDOW_MODE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT), dwStyle, dwExStyle);
3114+
_get_window_style(window_id_counter == MAIN_WINDOW_ID, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT), dwStyle, dwExStyle);
30993115

31003116
RECT WindowRect;
31013117

@@ -3104,7 +3120,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
31043120
WindowRect.top = p_rect.position.y;
31053121
WindowRect.bottom = p_rect.position.y + p_rect.size.y;
31063122

3107-
if (p_mode == WINDOW_MODE_FULLSCREEN) {
3123+
if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
31083124
int nearest_area = 0;
31093125
Rect2i screen_rect;
31103126
for (int i = 0; i < get_screen_count(); i++) {
@@ -3147,7 +3163,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
31473163
windows.erase(id);
31483164
return INVALID_WINDOW_ID;
31493165
}
3150-
if (p_mode != WINDOW_MODE_FULLSCREEN) {
3166+
if (p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
31513167
wd.pre_fs_valid = true;
31523168
}
31533169

platform/windows/display_server_windows.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ class DisplayServerWindows : public DisplayServer {
331331
bool maximized = false;
332332
bool minimized = false;
333333
bool fullscreen = false;
334+
bool multiwindow_fs = false;
334335
bool borderless = false;
335336
bool resizable = true;
336337
bool window_focused = false;
@@ -400,7 +401,7 @@ class DisplayServerWindows : public DisplayServer {
400401
WNDPROC user_proc = nullptr;
401402

402403
void _send_window_event(const WindowData &wd, WindowEvent p_event);
403-
void _get_window_style(bool p_main_window, bool p_fullscreen, bool p_borderless, bool p_resizable, bool p_maximized, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex);
404+
void _get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex);
404405

405406
MouseMode mouse_mode;
406407
int restore_mouse_trails = 0;

scene/main/viewport.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1231,7 +1231,7 @@ void Viewport::_gui_show_tooltip() {
12311231

12321232
base_tooltip->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
12331233

1234-
panel->set_transient(false);
1234+
panel->set_transient(true);
12351235
panel->set_flag(Window::FLAG_NO_FOCUS, true);
12361236
panel->set_wrap_controls(true);
12371237
panel->add_child(base_tooltip);

scene/main/window.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1614,6 +1614,7 @@ void Window::_bind_methods() {
16141614
BIND_ENUM_CONSTANT(MODE_MINIMIZED);
16151615
BIND_ENUM_CONSTANT(MODE_MAXIMIZED);
16161616
BIND_ENUM_CONSTANT(MODE_FULLSCREEN);
1617+
BIND_ENUM_CONSTANT(MODE_EXCLUSIVE_FULLSCREEN);
16171618

16181619
BIND_ENUM_CONSTANT(FLAG_RESIZE_DISABLED);
16191620
BIND_ENUM_CONSTANT(FLAG_BORDERLESS);

scene/main/window.h

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class Window : public Viewport {
4646
MODE_MINIMIZED = DisplayServer::WINDOW_MODE_MINIMIZED,
4747
MODE_MAXIMIZED = DisplayServer::WINDOW_MODE_MAXIMIZED,
4848
MODE_FULLSCREEN = DisplayServer::WINDOW_MODE_FULLSCREEN,
49+
MODE_EXCLUSIVE_FULLSCREEN = DisplayServer::WINDOW_MODE_EXCLUSIVE_FULLSCREEN,
4950
};
5051

5152
enum Flags {

servers/display_server.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ void DisplayServer::_bind_methods() {
540540
BIND_ENUM_CONSTANT(WINDOW_MODE_MINIMIZED);
541541
BIND_ENUM_CONSTANT(WINDOW_MODE_MAXIMIZED);
542542
BIND_ENUM_CONSTANT(WINDOW_MODE_FULLSCREEN);
543+
BIND_ENUM_CONSTANT(WINDOW_MODE_EXCLUSIVE_FULLSCREEN);
543544

544545
BIND_ENUM_CONSTANT(WINDOW_FLAG_RESIZE_DISABLED);
545546
BIND_ENUM_CONSTANT(WINDOW_FLAG_BORDERLESS);

servers/display_server.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class DisplayServer : public Object {
5353
WINDOW_MODE_WINDOWED,
5454
WINDOW_MODE_MINIMIZED,
5555
WINDOW_MODE_MAXIMIZED,
56-
WINDOW_MODE_FULLSCREEN
56+
WINDOW_MODE_FULLSCREEN,
57+
WINDOW_MODE_EXCLUSIVE_FULLSCREEN,
5758
};
5859

5960
// Keep the VSyncMode enum values in sync with the `display/window/vsync/vsync_mode`

0 commit comments

Comments
 (0)