mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 07:53:26 +00:00
X11: Fix minimization of maximized windows
This commit is contained in:
parent
b4472f4670
commit
12f8c78231
2 changed files with 83 additions and 49 deletions
|
@ -1915,9 +1915,22 @@ void DisplayServerX11::show_window(WindowID p_id) {
|
|||
|
||||
DEBUG_LOG_X11("show_window: %lu (%u) \n", wd.x11_window, p_id);
|
||||
|
||||
// Setup initial minimize/maximize state.
|
||||
// `_NET_WM_STATE` can be set directly when the window is unmapped.
|
||||
LocalVector<Atom> hints;
|
||||
if (wd.maximized) {
|
||||
hints.push_back(XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False));
|
||||
hints.push_back(XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False));
|
||||
}
|
||||
if (wd.minimized) {
|
||||
hints.push_back(XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False));
|
||||
}
|
||||
XChangeProperty(x11_display, wd.x11_window, XInternAtom(x11_display, "_NET_WM_STATE", False), XA_ATOM, 32, PropModeReplace, (unsigned char *)hints.ptr(), hints.size());
|
||||
|
||||
XMapWindow(x11_display, wd.x11_window);
|
||||
XSync(x11_display, False);
|
||||
_validate_mode_on_map(p_id);
|
||||
|
||||
_validate_fullscreen_on_map(p_id);
|
||||
|
||||
if (p_id == MAIN_WINDOW_ID) {
|
||||
// Get main window size for boot splash drawing.
|
||||
|
@ -2446,6 +2459,52 @@ void DisplayServerX11::_update_actions_hints(WindowID p_window) {
|
|||
}
|
||||
}
|
||||
|
||||
void DisplayServerX11::_update_wm_state_hints(WindowID p_window) {
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
Atom type;
|
||||
int format;
|
||||
unsigned long len;
|
||||
unsigned long remaining;
|
||||
unsigned char *data = nullptr;
|
||||
|
||||
int result = XGetWindowProperty(
|
||||
x11_display,
|
||||
wd.x11_window,
|
||||
XInternAtom(x11_display, "_NET_WM_STATE", False),
|
||||
0,
|
||||
1024,
|
||||
False,
|
||||
XA_ATOM,
|
||||
&type,
|
||||
&format,
|
||||
&len,
|
||||
&remaining,
|
||||
&data);
|
||||
if (result != Success) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocalVector<Atom> hints;
|
||||
if (data) {
|
||||
hints.resize(len);
|
||||
Atom *atoms = (Atom *)data;
|
||||
for (unsigned long i = 0; i < len; i++) {
|
||||
hints[i] = atoms[i];
|
||||
}
|
||||
XFree(data);
|
||||
}
|
||||
|
||||
Atom fullscreen_atom = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False);
|
||||
Atom maximized_horz_atom = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
|
||||
Atom maximized_vert_atom = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
|
||||
Atom hidden_atom = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False);
|
||||
|
||||
wd.fullscreen = hints.has(fullscreen_atom);
|
||||
wd.maximized = hints.has(maximized_horz_atom) && hints.has(maximized_vert_atom);
|
||||
wd.minimized = hints.has(hidden_atom);
|
||||
}
|
||||
|
||||
Point2i DisplayServerX11::window_get_position(WindowID p_window) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
@ -2853,15 +2912,11 @@ bool DisplayServerX11::_window_fullscreen_check(WindowID p_window) const {
|
|||
return retval;
|
||||
}
|
||||
|
||||
void DisplayServerX11::_validate_mode_on_map(WindowID p_window) {
|
||||
void DisplayServerX11::_validate_fullscreen_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, 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)) {
|
||||
_set_wm_minimized(p_window, true);
|
||||
}
|
||||
|
||||
if (wd.on_top) {
|
||||
|
@ -3060,13 +3115,15 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
|
|||
|
||||
} break;
|
||||
case WINDOW_MODE_MAXIMIZED: {
|
||||
_set_wm_maximized(p_window, false);
|
||||
// Varies between target modes, so do nothing here.
|
||||
} break;
|
||||
}
|
||||
|
||||
switch (p_mode) {
|
||||
case WINDOW_MODE_WINDOWED: {
|
||||
//do nothing
|
||||
if (wd.maximized) {
|
||||
_set_wm_maximized(p_window, false);
|
||||
}
|
||||
} break;
|
||||
case WINDOW_MODE_MINIMIZED: {
|
||||
_set_wm_minimized(p_window, true);
|
||||
|
@ -3100,27 +3157,20 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c
|
|||
ERR_FAIL_COND_V(!windows.has(p_window), WINDOW_MODE_WINDOWED);
|
||||
const WindowData &wd = windows[p_window];
|
||||
|
||||
if (wd.fullscreen) { //if fullscreen, it's not in another mode
|
||||
if (wd.exclusive_fullscreen) {
|
||||
return WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
|
||||
} else {
|
||||
return WINDOW_MODE_FULLSCREEN;
|
||||
}
|
||||
}
|
||||
|
||||
// Test maximized.
|
||||
// Using EWMH -- Extended Window Manager Hints
|
||||
if (_window_maximize_check(p_window, "_NET_WM_STATE")) {
|
||||
return WINDOW_MODE_MAXIMIZED;
|
||||
}
|
||||
|
||||
{
|
||||
if (_window_minimize_check(p_window)) {
|
||||
return WINDOW_MODE_MINIMIZED;
|
||||
}
|
||||
|
||||
if (wd.fullscreen) {
|
||||
if (wd.exclusive_fullscreen) {
|
||||
return WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
|
||||
}
|
||||
return WINDOW_MODE_FULLSCREEN;
|
||||
}
|
||||
|
||||
// All other discarded, return windowed.
|
||||
if (_window_maximize_check(p_window, "_NET_WM_STATE")) {
|
||||
return WINDOW_MODE_MAXIMIZED;
|
||||
}
|
||||
|
||||
return WINDOW_MODE_WINDOWED;
|
||||
}
|
||||
|
@ -4400,11 +4450,6 @@ void DisplayServerX11::_window_changed(XEvent *event) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Query display server about a possible new window state.
|
||||
wd.fullscreen = _window_fullscreen_check(window_id);
|
||||
wd.maximized = _window_maximize_check(window_id, "_NET_WM_STATE") && !wd.fullscreen;
|
||||
wd.minimized = _window_minimize_check(window_id) && !wd.fullscreen && !wd.maximized;
|
||||
|
||||
// Readjusting the window position if the window is being reparented by the window manager for decoration
|
||||
Window root, parent, *children;
|
||||
unsigned int nchildren;
|
||||
|
@ -5035,7 +5080,7 @@ void DisplayServerX11::process_events() {
|
|||
}
|
||||
|
||||
// Have we failed to set fullscreen while the window was unmapped?
|
||||
_validate_mode_on_map(window_id);
|
||||
_validate_fullscreen_on_map(window_id);
|
||||
|
||||
// On KDE Plasma, when the parent window of an embedded process is restored after being minimized,
|
||||
// only the embedded window receives the Map notification, causing it to
|
||||
|
@ -5056,24 +5101,6 @@ void DisplayServerX11::process_events() {
|
|||
Main::force_redraw();
|
||||
} break;
|
||||
|
||||
case NoExpose: {
|
||||
DEBUG_LOG_X11("[%u] NoExpose drawable=%lu (%u) \n", frame, event.xnoexpose.drawable, window_id);
|
||||
if (ime_window_event) {
|
||||
break;
|
||||
}
|
||||
|
||||
windows[window_id].minimized = true;
|
||||
} break;
|
||||
|
||||
case VisibilityNotify: {
|
||||
DEBUG_LOG_X11("[%u] VisibilityNotify window=%lu (%u), state=%u \n", frame, event.xvisibility.window, window_id, event.xvisibility.state);
|
||||
if (ime_window_event) {
|
||||
break;
|
||||
}
|
||||
|
||||
windows[window_id].minimized = _window_minimize_check(window_id);
|
||||
} break;
|
||||
|
||||
case LeaveNotify: {
|
||||
DEBUG_LOG_X11("[%u] LeaveNotify window=%lu (%u), mode='%u' \n", frame, event.xcrossing.window, window_id, event.xcrossing.mode);
|
||||
if (ime_window_event) {
|
||||
|
@ -5217,6 +5244,12 @@ void DisplayServerX11::process_events() {
|
|||
_window_changed(&event);
|
||||
} break;
|
||||
|
||||
case PropertyNotify: {
|
||||
if (event.xproperty.atom == XInternAtom(x11_display, "_NET_WM_STATE", False)) {
|
||||
_update_wm_state_hints(window_id);
|
||||
}
|
||||
} break;
|
||||
|
||||
case ButtonPress:
|
||||
case ButtonRelease: {
|
||||
if (ime_window_event || ignore_events) {
|
||||
|
|
|
@ -352,9 +352,10 @@ class DisplayServerX11 : public DisplayServer {
|
|||
bool _window_maximize_check(WindowID p_window, const char *p_atom_name) const;
|
||||
bool _window_fullscreen_check(WindowID p_window) const;
|
||||
bool _window_minimize_check(WindowID p_window) const;
|
||||
void _validate_mode_on_map(WindowID p_window);
|
||||
void _validate_fullscreen_on_map(WindowID p_window);
|
||||
void _update_size_hints(WindowID p_window);
|
||||
void _update_actions_hints(WindowID p_window);
|
||||
void _update_wm_state_hints(WindowID p_window);
|
||||
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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue