|
@@ -1823,6 +1823,47 @@ bool DisplayServerX11::_window_maximize_check(WindowID p_window, const char *p_a
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
+bool DisplayServerX11::_window_minimize_check(WindowID p_window) const {
|
|
|
+ const WindowData &wd = windows[p_window];
|
|
|
+
|
|
|
+ // Using ICCCM -- Inter-Client Communication Conventions Manual
|
|
|
+ Atom property = XInternAtom(x11_display, "WM_STATE", True);
|
|
|
+ if (property == None) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ Atom type;
|
|
|
+ int format;
|
|
|
+ unsigned long len;
|
|
|
+ unsigned long remaining;
|
|
|
+ unsigned char *data = nullptr;
|
|
|
+
|
|
|
+ int result = XGetWindowProperty(
|
|
|
+ x11_display,
|
|
|
+ wd.x11_window,
|
|
|
+ property,
|
|
|
+ 0,
|
|
|
+ 32,
|
|
|
+ False,
|
|
|
+ AnyPropertyType,
|
|
|
+ &type,
|
|
|
+ &format,
|
|
|
+ &len,
|
|
|
+ &remaining,
|
|
|
+ &data);
|
|
|
+
|
|
|
+ if (result == Success && data) {
|
|
|
+ long *state = (long *)data;
|
|
|
+ if (state[0] == WM_IconicState) {
|
|
|
+ XFree(data);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ XFree(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
bool DisplayServerX11::_window_fullscreen_check(WindowID p_window) const {
|
|
|
ERR_FAIL_COND_V(!windows.has(p_window), false);
|
|
|
const WindowData &wd = windows[p_window];
|
|
@@ -1869,11 +1910,15 @@ bool DisplayServerX11::_window_fullscreen_check(WindowID p_window) const {
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
-void DisplayServerX11::_validate_fullscreen_on_map(WindowID p_window) {
|
|
|
+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)) {
|
|
|
- // Unmapped fullscreen attempt didn't take effect, redo...
|
|
|
_set_wm_fullscreen(p_window, true);
|
|
|
+ } 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);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1911,6 +1956,37 @@ void DisplayServerX11::_set_wm_maximized(WindowID p_window, bool p_enabled) {
|
|
|
usleep(10000);
|
|
|
}
|
|
|
}
|
|
|
+ wd.maximized = p_enabled;
|
|
|
+}
|
|
|
+
|
|
|
+void DisplayServerX11::_set_wm_minimized(WindowID p_window, bool p_enabled) {
|
|
|
+ WindowData &wd = windows[p_window];
|
|
|
+ // Using ICCCM -- Inter-Client Communication Conventions Manual
|
|
|
+ XEvent xev;
|
|
|
+ Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False);
|
|
|
+
|
|
|
+ memset(&xev, 0, sizeof(xev));
|
|
|
+ xev.type = ClientMessage;
|
|
|
+ xev.xclient.window = wd.x11_window;
|
|
|
+ xev.xclient.message_type = wm_change;
|
|
|
+ xev.xclient.format = 32;
|
|
|
+ xev.xclient.data.l[0] = p_enabled ? WM_IconicState : WM_NormalState;
|
|
|
+
|
|
|
+ XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
|
|
+
|
|
|
+ Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
|
|
|
+ Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False);
|
|
|
+
|
|
|
+ memset(&xev, 0, sizeof(xev));
|
|
|
+ xev.type = ClientMessage;
|
|
|
+ xev.xclient.window = wd.x11_window;
|
|
|
+ xev.xclient.message_type = wm_state;
|
|
|
+ xev.xclient.format = 32;
|
|
|
+ xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
|
|
+ xev.xclient.data.l[1] = wm_hidden;
|
|
|
+
|
|
|
+ XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
|
|
+ wd.minimized = p_enabled;
|
|
|
}
|
|
|
|
|
|
void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
|
|
@@ -1992,32 +2068,7 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
|
|
|
//do nothing
|
|
|
} break;
|
|
|
case WINDOW_MODE_MINIMIZED: {
|
|
|
- //Un-Minimize
|
|
|
- // Using ICCCM -- Inter-Client Communication Conventions Manual
|
|
|
- XEvent xev;
|
|
|
- Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False);
|
|
|
-
|
|
|
- memset(&xev, 0, sizeof(xev));
|
|
|
- xev.type = ClientMessage;
|
|
|
- xev.xclient.window = wd.x11_window;
|
|
|
- xev.xclient.message_type = wm_change;
|
|
|
- xev.xclient.format = 32;
|
|
|
- xev.xclient.data.l[0] = WM_NormalState;
|
|
|
-
|
|
|
- XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
|
|
-
|
|
|
- Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
|
|
|
- Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False);
|
|
|
-
|
|
|
- memset(&xev, 0, sizeof(xev));
|
|
|
- xev.type = ClientMessage;
|
|
|
- xev.xclient.window = wd.x11_window;
|
|
|
- xev.xclient.message_type = wm_state;
|
|
|
- xev.xclient.format = 32;
|
|
|
- xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
|
|
|
- xev.xclient.data.l[1] = wm_hidden;
|
|
|
-
|
|
|
- XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
|
|
+ _set_wm_minimized(p_window, false);
|
|
|
} break;
|
|
|
case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
|
|
|
case WINDOW_MODE_FULLSCREEN: {
|
|
@@ -2046,31 +2097,7 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
|
|
|
//do nothing
|
|
|
} break;
|
|
|
case WINDOW_MODE_MINIMIZED: {
|
|
|
- // Using ICCCM -- Inter-Client Communication Conventions Manual
|
|
|
- XEvent xev;
|
|
|
- Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False);
|
|
|
-
|
|
|
- memset(&xev, 0, sizeof(xev));
|
|
|
- xev.type = ClientMessage;
|
|
|
- xev.xclient.window = wd.x11_window;
|
|
|
- xev.xclient.message_type = wm_change;
|
|
|
- xev.xclient.format = 32;
|
|
|
- xev.xclient.data.l[0] = WM_IconicState;
|
|
|
-
|
|
|
- XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
|
|
-
|
|
|
- Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
|
|
|
- Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False);
|
|
|
-
|
|
|
- memset(&xev, 0, sizeof(xev));
|
|
|
- xev.type = ClientMessage;
|
|
|
- xev.xclient.window = wd.x11_window;
|
|
|
- xev.xclient.message_type = wm_state;
|
|
|
- xev.xclient.format = 32;
|
|
|
- xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
|
|
|
- xev.xclient.data.l[1] = wm_hidden;
|
|
|
-
|
|
|
- XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
|
|
+ _set_wm_minimized(p_window, true);
|
|
|
} break;
|
|
|
case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
|
|
|
case WINDOW_MODE_FULLSCREEN: {
|
|
@@ -2105,40 +2132,9 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c
|
|
|
return WINDOW_MODE_MAXIMIZED;
|
|
|
}
|
|
|
|
|
|
- { // Test minimized.
|
|
|
- // Using ICCCM -- Inter-Client Communication Conventions Manual
|
|
|
- Atom property = XInternAtom(x11_display, "WM_STATE", True);
|
|
|
- if (property == None) {
|
|
|
- return WINDOW_MODE_WINDOWED;
|
|
|
- }
|
|
|
-
|
|
|
- Atom type;
|
|
|
- int format;
|
|
|
- unsigned long len;
|
|
|
- unsigned long remaining;
|
|
|
- unsigned char *data = nullptr;
|
|
|
-
|
|
|
- int result = XGetWindowProperty(
|
|
|
- x11_display,
|
|
|
- wd.x11_window,
|
|
|
- property,
|
|
|
- 0,
|
|
|
- 32,
|
|
|
- False,
|
|
|
- AnyPropertyType,
|
|
|
- &type,
|
|
|
- &format,
|
|
|
- &len,
|
|
|
- &remaining,
|
|
|
- &data);
|
|
|
-
|
|
|
- if (result == Success && data) {
|
|
|
- long *state = (long *)data;
|
|
|
- if (state[0] == WM_IconicState) {
|
|
|
- XFree(data);
|
|
|
- return WINDOW_MODE_MINIMIZED;
|
|
|
- }
|
|
|
- XFree(data);
|
|
|
+ {
|
|
|
+ if (_window_minimize_check(p_window)) {
|
|
|
+ return WINDOW_MODE_MINIMIZED;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3658,9 +3654,6 @@ void DisplayServerX11::process_events() {
|
|
|
|
|
|
const WindowData &wd = windows[window_id];
|
|
|
|
|
|
- // Have we failed to set fullscreen while the window was unmapped?
|
|
|
- _validate_fullscreen_on_map(window_id);
|
|
|
-
|
|
|
XWindowAttributes xwa;
|
|
|
XSync(x11_display, False);
|
|
|
XGetWindowAttributes(x11_display, wd.x11_window, &xwa);
|
|
@@ -3671,6 +3664,9 @@ void DisplayServerX11::process_events() {
|
|
|
if ((xwa.map_state == IsViewable) && !wd.no_focus && !wd.is_popup) {
|
|
|
XSetInputFocus(x11_display, wd.x11_window, RevertToPointerRoot, CurrentTime);
|
|
|
}
|
|
|
+
|
|
|
+ // Have we failed to set fullscreen while the window was unmapped?
|
|
|
+ _validate_mode_on_map(window_id);
|
|
|
} break;
|
|
|
|
|
|
case Expose: {
|
|
@@ -3690,8 +3686,7 @@ void DisplayServerX11::process_events() {
|
|
|
case VisibilityNotify: {
|
|
|
DEBUG_LOG_X11("[%u] VisibilityNotify window=%lu (%u), state=%u \n", frame, event.xvisibility.window, window_id, event.xvisibility.state);
|
|
|
|
|
|
- XVisibilityEvent *visibility = (XVisibilityEvent *)&event;
|
|
|
- windows[window_id].minimized = (visibility->state == VisibilityFullyObscured);
|
|
|
+ windows[window_id].minimized = _window_minimize_check(window_id);
|
|
|
} break;
|
|
|
|
|
|
case LeaveNotify: {
|
|
@@ -5003,7 +4998,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
|
|
|
_window_changed(&xevent);
|
|
|
} else if (xevent.type == MapNotify) {
|
|
|
// Have we failed to set fullscreen while the window was unmapped?
|
|
|
- _validate_fullscreen_on_map(main_window);
|
|
|
+ _validate_mode_on_map(main_window);
|
|
|
}
|
|
|
}
|
|
|
|