Merge pull request #69707 from bruvzg/x11_exfs

[Linux/X11] Split fullscreen mode into `WINDOW_MODE_EXCLUSIVE_FULLSCREEN` and `WINDOW_MODE_FULLSCREEN` to improve multi-window handling.
This commit is contained in:
Rémi Verschelde 2022-12-07 14:29:37 +01:00
commit 39ad411369
No known key found for this signature in database
GPG key ID: C3336907360768E1
3 changed files with 36 additions and 14 deletions

View file

@ -1633,14 +1633,17 @@
Maximized window mode, i.e. [Window] will occupy whole screen area except task bar and still display its borders. Normally happens when the minimize button is pressed.
</constant>
<constant name="WINDOW_MODE_FULLSCREEN" value="3" enum="WindowMode">
Full screen window mode. Note that this is not [i]exclusive[/i] full screen. On Windows and Linux (X11), a borderless window is used to emulate full screen. On macOS, a new desktop is used to display the running project.
Regardless of the platform, enabling full screen 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 full screen mode.
Full screen mode with full multi-window support.
Full screen window cover the entire display area of a screen, have no border or decorations. Display video mode is not changed.
[b]Note:[/b] Regardless of the platform, enabling full screen 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 full screen mode.
</constant>
<constant name="WINDOW_MODE_EXCLUSIVE_FULLSCREEN" value="4" enum="WindowMode">
Exclusive full screen window mode. This mode is implemented on Windows and macOS only. On other platforms, it is equivalent to [constant WINDOW_MODE_FULLSCREEN].
[b]On Windows:[/b] Only one window in exclusive full screen mode can be visible on a given screen at a time. If multiple windows are in exclusive full screen mode for the same screen, the last one being set to this mode takes precedence.
[b]On macOS:[/b] Exclusive full-screen mode prevents Dock and Menu from showing up when the mouse pointer is hovering the edge of the screen.
Regardless of the platform, enabling full screen 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 full screen mode.
A single window full screen mode. This mode has less overhead, but only one window can be open on a given screen at a time (opening a child window or application switching will trigger a full screen transition).
Full screen window cover the entire display area of a screen, have no border or decorations. Display video mode is not changed.
[b]On Windows:[/b] Depending on video driver, full screen transition might cause screens to go black for a moment.
[b]On macOS:[/b] Exclusive full screen mode prevents Dock and Menu from showing up when the mouse pointer is hovering the edge of the screen.
[b]On Linux (X11):[/b] Exclusive full screen mode bypasses compositor.
[b]Note:[/b] Regardless of the platform, enabling full screen 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 full screen mode.
</constant>
<constant name="WINDOW_FLAG_RESIZE_DISABLED" value="0" enum="WindowFlags">
The window can't be resizing by dragging its resize grip. It's still possible to resize the window using [method window_set_size]. This flag is ignored for full screen windows.

View file

@ -1582,7 +1582,7 @@ void DisplayServerX11::_update_size_hints(WindowID p_window) {
xsh->width = wd.size.width;
xsh->height = wd.size.height;
if (window_mode == WINDOW_MODE_FULLSCREEN) {
if (window_mode == WINDOW_MODE_FULLSCREEN || window_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
// Do not set any other hints to prevent the window manager from ignoring the fullscreen flags
} else if (window_get_flag(WINDOW_FLAG_RESIZE_DISABLED, p_window)) {
// If resizing is disabled, use the forced size
@ -1949,7 +1949,7 @@ void DisplayServerX11::_validate_mode_on_map(WindowID p_window) {
// Check if we applied any window modes that didn't take effect while unmapped
const WindowData &wd = windows[p_window];
if (wd.fullscreen && !_window_fullscreen_check(p_window)) {
_set_wm_fullscreen(p_window, true);
_set_wm_fullscreen(p_window, true, wd.exclusive_fullscreen);
} else if (wd.maximized && !_window_maximize_check(p_window, "_NET_WM_STATE")) {
_set_wm_maximized(p_window, true);
} else if (wd.minimized && !_window_minimize_check(p_window)) {
@ -2024,7 +2024,7 @@ void DisplayServerX11::_set_wm_minimized(WindowID p_window, bool p_enabled) {
wd.minimized = p_enabled;
}
void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled, bool p_exclusive) {
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
@ -2063,7 +2063,14 @@ void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
// set bypass compositor hint
Atom bypass_compositor = XInternAtom(x11_display, "_NET_WM_BYPASS_COMPOSITOR", False);
unsigned long compositing_disable_on = p_enabled ? 1 : 0;
unsigned long compositing_disable_on = 0; // Use default.
if (p_enabled) {
if (p_exclusive) {
compositing_disable_on = 1; // Force composition OFF to reduce overhead.
} else {
compositing_disable_on = 2; // Force composition ON to allow popup windows.
}
}
if (bypass_compositor != None) {
XChangeProperty(x11_display, wd.x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1);
}
@ -2109,8 +2116,9 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
case WINDOW_MODE_FULLSCREEN: {
//Remove full-screen
wd.fullscreen = false;
wd.exclusive_fullscreen = false;
_set_wm_fullscreen(p_window, false);
_set_wm_fullscreen(p_window, false, false);
//un-maximize required for always on top
bool on_top = window_get_flag(WINDOW_FLAG_ALWAYS_ON_TOP, p_window);
@ -2143,7 +2151,13 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
}
wd.fullscreen = true;
_set_wm_fullscreen(p_window, true);
if (p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
wd.exclusive_fullscreen = true;
_set_wm_fullscreen(p_window, true, true);
} else {
wd.exclusive_fullscreen = false;
_set_wm_fullscreen(p_window, true, false);
}
} break;
case WINDOW_MODE_MAXIMIZED: {
_set_wm_maximized(p_window, true);
@ -2158,7 +2172,11 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c
const WindowData &wd = windows[p_window];
if (wd.fullscreen) { //if fullscreen, it's not in another mode
return WINDOW_MODE_FULLSCREEN;
if (wd.exclusive_fullscreen) {
return WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
} else {
return WINDOW_MODE_FULLSCREEN;
}
}
// Test maximized.

View file

@ -159,6 +159,7 @@ class DisplayServerX11 : public DisplayServer {
//better to guess on the fly, given WM can change it
//WindowMode mode;
bool fullscreen = false; //OS can't exit from this mode
bool exclusive_fullscreen = false;
bool on_top = false;
bool borderless = false;
bool resize_disabled = false;
@ -283,7 +284,7 @@ class DisplayServerX11 : public DisplayServer {
bool _window_minimize_check(WindowID p_window) const;
void _validate_mode_on_map(WindowID p_window);
void _update_size_hints(WindowID p_window);
void _set_wm_fullscreen(WindowID p_window, bool p_enabled);
void _set_wm_fullscreen(WindowID p_window, bool p_enabled, bool p_exclusive);
void _set_wm_maximized(WindowID p_window, bool p_enabled);
void _set_wm_minimized(WindowID p_window, bool p_enabled);