diff options
-rw-r--r-- | platform/linuxbsd/display_server_x11.cpp | 75 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.h | 2 |
2 files changed, 51 insertions, 26 deletions
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 5fe28935b9..759808cb89 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -683,35 +683,49 @@ int DisplayServerX11::get_screen_count() const { return count; } -Point2i DisplayServerX11::screen_get_position(int p_screen) const { - _THREAD_SAFE_METHOD_ +Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const { + Rect2i rect(0, 0, 0, 0); if (p_screen == SCREEN_OF_MAIN_WINDOW) { p_screen = window_get_current_screen(); } - // Using Xinerama Extension - int event_base, error_base; - const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); - if (!ext_okay) { - return Point2i(0, 0); - } + ERR_FAIL_COND_V(p_screen < 0, rect); - int count; - XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); + // Using Xinerama Extension. + int event_base, error_base; + if (XineramaQueryExtension(x11_display, &event_base, &error_base)) { + int count; + XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); + + // Check if screen is valid. + if (p_screen < count) { + rect.position.x = xsi[p_screen].x_org; + rect.position.y = xsi[p_screen].y_org; + rect.size.width = xsi[p_screen].width; + rect.size.height = xsi[p_screen].height; + } else { + ERR_PRINT("Invalid screen index: " + itos(p_screen) + "(count: " + itos(count) + ")."); + } - // Check if screen is valid - ERR_FAIL_INDEX_V(p_screen, count, Point2i(0, 0)); + if (xsi) { + XFree(xsi); + } + } - Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org); + return rect; +} - XFree(xsi); +Point2i DisplayServerX11::screen_get_position(int p_screen) const { + _THREAD_SAFE_METHOD_ - return position; + return _screen_get_rect(p_screen).position; } Size2i DisplayServerX11::screen_get_size(int p_screen) const { - return screen_get_usable_rect(p_screen).size; + _THREAD_SAFE_METHOD_ + + return _screen_get_rect(p_screen).size; } Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const { @@ -1011,22 +1025,31 @@ void DisplayServerX11::window_set_drop_files_callback(const Callable &p_callable int DisplayServerX11::window_get_current_screen(WindowID p_window) const { _THREAD_SAFE_METHOD_ - ERR_FAIL_COND_V(!windows.has(p_window), -1); + int count = get_screen_count(); + if (count < 2) { + // Early exit with single monitor. + return 0; + } + + ERR_FAIL_COND_V(!windows.has(p_window), 0); const WindowData &wd = windows[p_window]; - int x, y; - Window child; - XTranslateCoordinates(x11_display, wd.x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); + const Rect2i window_rect(wd.position, wd.size); - int count = get_screen_count(); + // Find which monitor has the largest overlap with the given window. + int screen_index = 0; + int max_area = 0; for (int i = 0; i < count; i++) { - Point2i pos = screen_get_position(i); - Size2i size = screen_get_size(i); - if ((x >= pos.x && x < pos.x + size.width) && (y >= pos.y && y < pos.y + size.height)) { - return i; + Rect2i screen_rect = _screen_get_rect(i); + Rect2i intersection = screen_rect.intersection(window_rect); + int area = intersection.get_area(); + if (area > max_area) { + max_area = area; + screen_index = i; } } - return 0; + + return screen_index; } void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window) { diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index eb7725b768..4575714bf2 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -197,6 +197,8 @@ class DisplayServerX11 : public DisplayServer { bool _refresh_device_info(); + Rect2i _screen_get_rect(int p_screen) const; + MouseButton _get_mouse_button_state(MouseButton p_x11_button, int p_x11_type); void _get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state); void _flush_mouse_motion(); |