diff options
Diffstat (limited to 'platform/linuxbsd/x11/display_server_x11.cpp')
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.cpp | 99 |
1 files changed, 72 insertions, 27 deletions
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 767ea927c1..a605e664ce 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -139,8 +139,9 @@ bool DisplayServerX11::has_feature(Feature p_feature) const { #endif case FEATURE_CLIPBOARD_PRIMARY: case FEATURE_TEXT_TO_SPEECH: - case FEATURE_SCREEN_CAPTURE: return true; + case FEATURE_SCREEN_CAPTURE: + return !xwayland; default: { } } @@ -502,7 +503,34 @@ Point2i DisplayServerX11::mouse_get_position() const { } BitField<MouseButtonMask> DisplayServerX11::mouse_get_button_state() const { - return last_button_state; + int number_of_screens = XScreenCount(x11_display); + for (int i = 0; i < number_of_screens; i++) { + Window root, child; + int root_x, root_y, win_x, win_y; + unsigned int mask; + if (XQueryPointer(x11_display, XRootWindow(x11_display, i), &root, &child, &root_x, &root_y, &win_x, &win_y, &mask)) { + BitField<MouseButtonMask> last_button_state = 0; + + if (mask & Button1Mask) { + last_button_state.set_flag(MouseButtonMask::LEFT); + } + if (mask & Button2Mask) { + last_button_state.set_flag(MouseButtonMask::MIDDLE); + } + if (mask & Button3Mask) { + last_button_state.set_flag(MouseButtonMask::RIGHT); + } + if (mask & Button4Mask) { + last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1); + } + if (mask & Button5Mask) { + last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2); + } + + return last_button_state; + } + } + return 0; } void DisplayServerX11::clipboard_set(const String &p_text) { @@ -1467,9 +1495,20 @@ int DisplayServerX11::screen_get_dpi(int p_screen) const { return 96; } +int get_image_errorhandler(Display *dpy, XErrorEvent *ev) { + return 0; +} + Color DisplayServerX11::screen_get_pixel(const Point2i &p_position) const { Point2i pos = p_position; + if (xwayland) { + return Color(); + } + + int (*old_handler)(Display *, XErrorEvent *) = XSetErrorHandler(&get_image_errorhandler); + + Color color; int number_of_screens = XScreenCount(x11_display); for (int i = 0; i < number_of_screens; i++) { Window root = XRootWindow(x11_display, i); @@ -1482,12 +1521,15 @@ Color DisplayServerX11::screen_get_pixel(const Point2i &p_position) const { c.pixel = XGetPixel(image, 0, 0); XFree(image); XQueryColor(x11_display, XDefaultColormap(x11_display, i), &c); - return Color(float(c.red) / 65535.0, float(c.green) / 65535.0, float(c.blue) / 65535.0, 1.0); + color = Color(float(c.red) / 65535.0, float(c.green) / 65535.0, float(c.blue) / 65535.0, 1.0); + break; } } } - return Color(); + XSetErrorHandler(old_handler); + + return color; } Ref<Image> DisplayServerX11::screen_get_image(int p_screen) const { @@ -1506,6 +1548,12 @@ Ref<Image> DisplayServerX11::screen_get_image(int p_screen) const { ERR_FAIL_COND_V(p_screen < 0, Ref<Image>()); + if (xwayland) { + return Ref<Image>(); + } + + int (*old_handler)(Display *, XErrorEvent *) = XSetErrorHandler(&get_image_errorhandler); + XImage *image = nullptr; bool found = false; @@ -1548,6 +1596,8 @@ Ref<Image> DisplayServerX11::screen_get_image(int p_screen) const { } } + XSetErrorHandler(old_handler); + Ref<Image> img; if (image) { int width = image->width; @@ -3081,8 +3131,7 @@ void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu cursors_cache.erase(p_shape); } - Rect2 atlas_rect; - Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot, atlas_rect); + Ref<Image> image = _get_cursor_image_from_resource(p_cursor, p_hotspot); ERR_FAIL_COND(image.is_null()); Vector2i texture_size = image->get_size(); @@ -3100,13 +3149,8 @@ void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu cursor_image->pixels = (XcursorPixel *)memalloc(size); for (XcursorPixel index = 0; index < image_size; index++) { - int row_index = floor(index / texture_size.width) + atlas_rect.position.y; - int column_index = (index % int(texture_size.width)) + atlas_rect.position.x; - - if (atlas_rect.has_area()) { - column_index = MIN(column_index, atlas_rect.size.width - 1); - row_index = MIN(row_index, atlas_rect.size.height - 1); - } + int row_index = floor(index / texture_size.width); + int column_index = index % int(texture_size.width); *(cursor_image->pixels + index) = image->get_pixel(column_index, row_index).to_argb32(); } @@ -3351,18 +3395,6 @@ void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Ref<Inp state->set_meta_pressed((p_x11_state & Mod4Mask)); } -BitField<MouseButtonMask> DisplayServerX11::_get_mouse_button_state(MouseButton p_x11_button, int p_x11_type) { - MouseButtonMask mask = mouse_button_to_mask(p_x11_button); - - if (p_x11_type == ButtonPress) { - last_button_state.set_flag(mask); - } else { - last_button_state.clear_flag(mask); - } - - return last_button_state; -} - void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector<XEvent> &p_events, uint32_t &p_event_index, bool p_echo) { WindowData &wd = windows[p_window]; // X11 functions don't know what const is @@ -4175,8 +4207,11 @@ void DisplayServerX11::popup_open(WindowID p_window) { } } + // Detect tooltips and other similar popups that shouldn't block input to their parent. + bool ignores_input = window_get_flag(WINDOW_FLAG_NO_FOCUS, p_window) && window_get_flag(WINDOW_FLAG_MOUSE_PASSTHROUGH, p_window); + WindowData &wd = windows[p_window]; - if (wd.is_popup || has_popup_ancestor) { + if (wd.is_popup || (has_popup_ancestor && !ignores_input)) { // Find current popup parent, or root popup if new window is not transient. List<WindowID>::Element *C = nullptr; List<WindowID>::Element *E = popup_list.back(); @@ -4750,12 +4785,20 @@ void DisplayServerX11::process_events() { } else if (mb->get_button_index() == MouseButton::MIDDLE) { mb->set_button_index(MouseButton::RIGHT); } - mb->set_button_mask(_get_mouse_button_state(mb->get_button_index(), event.xbutton.type)); mb->set_position(Vector2(event.xbutton.x, event.xbutton.y)); mb->set_global_position(mb->get_position()); mb->set_pressed((event.type == ButtonPress)); + if (mb->is_pressed() && mb->get_button_index() >= MouseButton::WHEEL_UP && mb->get_button_index() <= MouseButton::WHEEL_RIGHT) { + MouseButtonMask mask = mouse_button_to_mask(mb->get_button_index()); + BitField<MouseButtonMask> scroll_mask = mouse_get_button_state(); + scroll_mask.set_flag(mask); + mb->set_button_mask(scroll_mask); + } else { + mb->set_button_mask(mouse_get_button_state()); + } + const WindowData &wd = windows[window_id]; if (event.type == ButtonPress) { @@ -5795,6 +5838,8 @@ static ::XIMStyle _get_best_xim_style(const ::XIMStyle &p_style_a, const ::XIMSt DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) { KeyMappingX11::initialize(); + xwayland = OS::get_singleton()->get_environment("XDG_SESSION_TYPE").to_lower() == "wayland"; + native_menu = memnew(NativeMenu); context = p_context; |