summaryrefslogtreecommitdiffstats
path: root/platform/linuxbsd/x11/display_server_x11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd/x11/display_server_x11.cpp')
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp105
1 files changed, 65 insertions, 40 deletions
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 2643cd3b1a..f38a9dd278 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -122,6 +122,9 @@ bool DisplayServerX11::has_feature(Feature p_feature) const {
case FEATURE_WINDOW_TRANSPARENCY:
//case FEATURE_HIDPI:
case FEATURE_ICON:
+#ifdef DBUS_ENABLED
+ case FEATURE_NATIVE_DIALOG:
+#endif
//case FEATURE_NATIVE_ICON:
case FEATURE_SWAP_BUFFERS:
#ifdef DBUS_ENABLED
@@ -360,6 +363,17 @@ bool DisplayServerX11::is_dark_mode() const {
}
}
+Error DisplayServerX11::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) {
+ WindowID window_id = _get_focused_window_or_popup();
+
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
+
+ String xid = vformat("x11:%x", (uint64_t)windows[window_id].x11_window);
+ return portal_desktop->file_dialog_show(xid, p_title, p_current_directory, p_filename, p_mode, p_filters, p_callback);
+}
+
#endif
void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {
@@ -379,7 +393,11 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {
if (show_cursor && !previously_shown) {
WindowID window_id = get_window_at_screen_position(mouse_get_position());
- if (window_id != INVALID_WINDOW_ID) {
+ if (window_id != INVALID_WINDOW_ID && window_mouseover_id != window_id) {
+ if (window_mouseover_id != INVALID_WINDOW_ID) {
+ _send_window_event(windows[window_mouseover_id], WINDOW_EVENT_MOUSE_EXIT);
+ }
+ window_mouseover_id = window_id;
_send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER);
}
}
@@ -744,7 +762,7 @@ int DisplayServerX11::get_screen_count() const {
// Using Xinerama Extension
int event_base, error_base;
- if (XineramaQueryExtension(x11_display, &event_base, &error_base)) {
+ if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) {
XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
XFree(xsi);
} else {
@@ -756,7 +774,7 @@ int DisplayServerX11::get_screen_count() const {
int DisplayServerX11::get_primary_screen() const {
int event_base, error_base;
- if (XineramaQueryExtension(x11_display, &event_base, &error_base)) {
+ if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) {
return 0;
} else {
return XDefaultScreen(x11_display);
@@ -809,7 +827,7 @@ Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const {
// Using Xinerama Extension.
int event_base, error_base;
- if (XineramaQueryExtension(x11_display, &event_base, &error_base)) {
+ if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) {
int count;
XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
@@ -1244,7 +1262,7 @@ Ref<Image> DisplayServerX11::screen_get_image(int p_screen) const {
XImage *image = nullptr;
int event_base, error_base;
- if (XineramaQueryExtension(x11_display, &event_base, &error_base)) {
+ if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) {
int xin_count;
XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &xin_count);
if (p_screen < xin_count) {
@@ -1449,6 +1467,11 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
DEBUG_LOG_X11("delete_sub_window: %lu (%u) \n", wd.x11_window, p_id);
+ if (window_mouseover_id == p_id) {
+ window_mouseover_id = INVALID_WINDOW_ID;
+ _send_window_event(windows[p_id], WINDOW_EVENT_MOUSE_EXIT);
+ }
+
window_set_rect_changed_callback(Callable(), p_id);
window_set_window_event_callback(Callable(), p_id);
window_set_input_event_callback(Callable(), p_id);
@@ -1586,6 +1609,7 @@ void DisplayServerX11::window_set_mouse_passthrough(const Vector<Vector2> &p_reg
void DisplayServerX11::_update_window_mouse_passthrough(WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
+ ERR_FAIL_COND(!xshaped_ext_ok);
const Vector<Vector2> region_path = windows[p_window].mpath;
@@ -2102,9 +2126,10 @@ bool DisplayServerX11::_window_maximize_check(WindowID p_window, const char *p_a
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) {
+ // Using EWMH instead of ICCCM, might work better for Wayland users.
+ Atom property = XInternAtom(x11_display, "_NET_WM_STATE", True);
+ Atom hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", True);
+ if (property == None || hidden == None) {
return false;
}
@@ -2112,7 +2137,7 @@ bool DisplayServerX11::_window_minimize_check(WindowID p_window) const {
int format;
unsigned long len;
unsigned long remaining;
- unsigned char *data = nullptr;
+ Atom *atoms = nullptr;
int result = XGetWindowProperty(
x11_display,
@@ -2121,20 +2146,21 @@ bool DisplayServerX11::_window_minimize_check(WindowID p_window) const {
0,
32,
False,
- AnyPropertyType,
+ XA_ATOM,
&type,
&format,
&len,
&remaining,
- &data);
+ (unsigned char **)&atoms);
- if (result == Success && data) {
- long *state = (long *)data;
- if (state[0] == WM_IconicState) {
- XFree(data);
- return true;
+ if (result == Success && atoms) {
+ for (unsigned int i = 0; i < len; i++) {
+ if (atoms[i] == hidden) {
+ XFree(atoms);
+ return true;
+ }
}
- XFree(data);
+ XFree(atoms);
}
return false;
@@ -3957,7 +3983,7 @@ bool DisplayServerX11::mouse_process_popups() {
// Find top popup to close.
while (E) {
// Popup window area.
- Rect2i win_rect = Rect2i(window_get_position(E->get()), window_get_size(E->get()));
+ Rect2i win_rect = Rect2i(window_get_position_with_decorations(E->get()), window_get_size_with_decorations(E->get()));
// Area of the parent window, which responsible for opening sub-menu.
Rect2i safe_rect = window_get_popup_safe_rect(E->get());
if (win_rect.has_point(pos)) {
@@ -4291,7 +4317,8 @@ void DisplayServerX11::process_events() {
break;
}
- if (!mouse_mode_grab) {
+ if (!mouse_mode_grab && window_mouseover_id == window_id) {
+ window_mouseover_id = INVALID_WINDOW_ID;
_send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_EXIT);
}
@@ -4303,7 +4330,11 @@ void DisplayServerX11::process_events() {
break;
}
- if (!mouse_mode_grab) {
+ if (!mouse_mode_grab && window_mouseover_id != window_id) {
+ if (window_mouseover_id != INVALID_WINDOW_ID) {
+ _send_window_event(windows[window_mouseover_id], WINDOW_EVENT_MOUSE_EXIT);
+ }
+ window_mouseover_id = window_id;
_send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER);
}
} break;
@@ -5461,13 +5492,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
}
if (initialize_xinerama(dylibloader_verbose) != 0) {
- r_error = ERR_UNAVAILABLE;
- ERR_FAIL_MSG("Can't load Xinerama dynamically.");
+ xinerama_ext_ok = false;
}
if (initialize_xrandr(dylibloader_verbose) != 0) {
- r_error = ERR_UNAVAILABLE;
- ERR_FAIL_MSG("Can't load Xrandr dynamically.");
+ xrandr_ext_ok = false;
}
if (initialize_xrender(dylibloader_verbose) != 0) {
@@ -5537,42 +5566,36 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
return;
}
- {
+ if (xshaped_ext_ok) {
int version_major = 0;
int version_minor = 0;
int rc = XShapeQueryVersion(x11_display, &version_major, &version_minor);
print_verbose(vformat("Xshape %d.%d detected.", version_major, version_minor));
if (rc != 1 || version_major < 1) {
- ERR_PRINT("Unsupported Xshape library version.");
- r_error = ERR_UNAVAILABLE;
- XCloseDisplay(x11_display);
- return;
+ xshaped_ext_ok = false;
+ print_verbose("Unsupported Xshape library version.");
}
}
- {
+ if (xinerama_ext_ok) {
int version_major = 0;
int version_minor = 0;
int rc = XineramaQueryVersion(x11_display, &version_major, &version_minor);
print_verbose(vformat("Xinerama %d.%d detected.", version_major, version_minor));
if (rc != 1 || version_major < 1) {
- ERR_PRINT("Unsupported Xinerama library version.");
- r_error = ERR_UNAVAILABLE;
- XCloseDisplay(x11_display);
- return;
+ xinerama_ext_ok = false;
+ print_verbose("Unsupported Xinerama library version.");
}
}
- {
+ if (xrandr_ext_ok) {
int version_major = 0;
int version_minor = 0;
int rc = XRRQueryVersion(x11_display, &version_major, &version_minor);
print_verbose(vformat("Xrandr %d.%d detected.", version_major, version_minor));
if (rc != 1 || (version_major == 1 && version_minor < 3) || (version_major < 1)) {
- ERR_PRINT("Unsupported Xrandr library version.");
- r_error = ERR_UNAVAILABLE;
- XCloseDisplay(x11_display);
- return;
+ xrandr_ext_ok = false;
+ print_verbose("Unsupported Xrandr library version.");
}
}
@@ -5638,7 +5661,9 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
if (!xrandr_handle) {
fprintf(stderr, "could not load libXrandr.so.2, Error: %s\n", err);
}
- } else {
+ }
+
+ if (xrandr_handle) {
XRRQueryVersion(x11_display, &xrandr_major, &xrandr_minor);
if (((xrandr_major << 8) | xrandr_minor) >= 0x0105) {
xrr_get_monitors = (xrr_get_monitors_t)dlsym(xrandr_handle, "XRRGetMonitors");