Merge pull request #42117 from nekomatata/x11-get-window-screen

Fix window_get_current_screen for X11 display server
This commit is contained in:
Rémi Verschelde 2021-10-28 20:57:24 +02:00 committed by GitHub
commit 9fb9b99cab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 26 deletions

View file

@ -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
ERR_FAIL_COND_V(p_screen < 0, rect);
// 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);
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) + ").");
}
if (xsi) {
XFree(xsi);
}
}
int count;
XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
return rect;
}
// Check if screen is valid
ERR_FAIL_INDEX_V(p_screen, count, Point2i(0, 0));
Point2i DisplayServerX11::screen_get_position(int p_screen) const {
_THREAD_SAFE_METHOD_
Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org);
XFree(xsi);
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) {

View file

@ -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();