diff options
Diffstat (limited to 'platform/linuxbsd/x11/display_server_x11.cpp')
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.cpp | 100 |
1 files changed, 80 insertions, 20 deletions
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 5d70af56bd..0972bf700e 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -128,6 +128,7 @@ bool DisplayServerX11::has_feature(Feature p_feature) const { #endif case FEATURE_CLIPBOARD_PRIMARY: case FEATURE_TEXT_TO_SPEECH: + case FEATURE_SCREEN_CAPTURE: return true; default: { } @@ -604,7 +605,7 @@ String DisplayServerX11::_clipboard_get_impl(Atom p_source, Window x11_window, A success = true; } } else { - printf("Failed to get selection data chunk.\n"); + print_verbose("Failed to get selection data chunk."); done = true; } @@ -631,7 +632,7 @@ String DisplayServerX11::_clipboard_get_impl(Atom p_source, Window x11_window, A if (result == Success) { ret.parse_utf8((const char *)data); } else { - printf("Failed to get selection data.\n"); + print_verbose("Failed to get selection data."); } if (data) { @@ -1169,6 +1170,29 @@ int DisplayServerX11::screen_get_dpi(int p_screen) const { return 96; } +Color DisplayServerX11::screen_get_pixel(const Point2i &p_position) const { + Point2i pos = p_position; + + int number_of_screens = XScreenCount(x11_display); + for (int i = 0; i < number_of_screens; i++) { + Window root = XRootWindow(x11_display, i); + XWindowAttributes root_attrs; + XGetWindowAttributes(x11_display, root, &root_attrs); + if ((pos.x >= root_attrs.x) && (pos.x <= root_attrs.x + root_attrs.width) && (pos.y >= root_attrs.y) && (pos.y <= root_attrs.y + root_attrs.height)) { + XImage *image = XGetImage(x11_display, root, pos.x, pos.y, 1, 1, AllPlanes, XYPixmap); + if (image) { + XColor c; + 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); + } + } + } + + return Color(); +} + float DisplayServerX11::screen_get_refresh_rate(int p_screen) const { _THREAD_SAFE_METHOD_ @@ -1329,12 +1353,14 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) { wd.xic = nullptr; } XDestroyWindow(x11_display, wd.x11_xim_window); +#ifdef XKB_ENABLED if (xkb_loaded) { if (wd.xkb_state) { xkb_compose_state_unref(wd.xkb_state); wd.xkb_state = nullptr; } } +#endif XUnmapWindow(x11_display, wd.x11_window); XDestroyWindow(x11_display, wd.x11_window); @@ -2055,6 +2081,22 @@ void DisplayServerX11::_validate_mode_on_map(WindowID p_window) { } else if (wd.minimized && !_window_minimize_check(p_window)) { _set_wm_minimized(p_window, true); } + + if (wd.on_top) { + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_above = XInternAtom(x11_display, "_NET_WM_STATE_ABOVE", False); + + XClientMessageEvent xev; + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.window = wd.x11_window; + xev.message_type = wm_state; + xev.format = 32; + xev.data.l[0] = _NET_WM_STATE_ADD; + xev.data.l[1] = wm_above; + xev.data.l[3] = 1; + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xev); + } } bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const { @@ -2597,6 +2639,8 @@ DisplayServerX11::CursorShape DisplayServerX11::cursor_get_shape() const { void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { _THREAD_SAFE_METHOD_ + ERR_FAIL_INDEX(p_shape, CURSOR_MAX); + if (p_cursor.is_valid()) { HashMap<CursorShape, Vector<Variant>>::Iterator cursor_c = cursors_cache.find(p_shape); @@ -2610,16 +2654,12 @@ void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu } Ref<Texture2D> texture = p_cursor; + ERR_FAIL_COND(!texture.is_valid()); Ref<AtlasTexture> atlas_texture = p_cursor; - Ref<Image> image; Size2i texture_size; Rect2i atlas_rect; - if (texture.is_valid()) { - image = texture->get_image(); - } - - if (!image.is_valid() && atlas_texture.is_valid()) { + if (atlas_texture.is_valid()) { texture = atlas_texture->get_atlas(); atlas_rect.size.width = texture->get_width(); @@ -2629,17 +2669,16 @@ void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu texture_size.width = atlas_texture->get_region().size.x; texture_size.height = atlas_texture->get_region().size.y; - } else if (image.is_valid()) { + } else { texture_size.width = texture->get_width(); texture_size.height = texture->get_height(); } - ERR_FAIL_COND(!texture.is_valid()); ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); - image = texture->get_image(); + Ref<Image> image = texture->get_image(); ERR_FAIL_COND(!image.is_valid()); @@ -2804,7 +2843,7 @@ Key DisplayServerX11::keyboard_get_keycode_from_physical(Key p_keycode) const { Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK; unsigned int xkeycode = KeyMappingX11::get_xlibcode(keycode_no_mod); - KeySym xkeysym = XkbKeycodeToKeysym(x11_display, xkeycode, 0, 0); + KeySym xkeysym = XkbKeycodeToKeysym(x11_display, xkeycode, keyboard_get_current_layout(), 0); if (is_ascii_lower_case(xkeysym)) { xkeysym -= ('a' - 'A'); } @@ -2897,7 +2936,7 @@ BitField<MouseButtonMask> DisplayServerX11::_get_mouse_button_state(MouseButton } 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]; + WindowData &wd = windows[p_window]; // X11 functions don't know what const is XKeyEvent *xkeyevent = p_event; @@ -2942,11 +2981,13 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, XLookupString(&xkeyevent_no_mod, nullptr, 0, &keysym_keycode, nullptr); String keysym; +#ifdef XKB_ENABLED if (xkb_loaded) { KeySym keysym_unicode_nm = 0; // keysym used to find unicode XLookupString(&xkeyevent_no_mod, nullptr, 0, &keysym_unicode_nm, nullptr); keysym = String::chr(xkb_keysym_to_utf32(xkb_keysym_to_upper(keysym_unicode_nm))); } +#endif // Meanwhile, XLookupString returns keysyms useful for unicode. @@ -3035,6 +3076,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, } } while (status == XBufferOverflow); #endif +#ifdef XKB_ENABLED } else if (xkeyevent->type == KeyPress && wd.xkb_state && xkb_loaded) { xkb_compose_feed_result res = xkb_compose_state_feed(wd.xkb_state, keysym_unicode); if (res == XKB_COMPOSE_FEED_ACCEPTED) { @@ -3093,6 +3135,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, return; } } +#endif } /* Phase 2, obtain a Godot keycode from the keysym */ @@ -3295,7 +3338,7 @@ Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p return p_property; } else { char *target_name = XGetAtomName(x11_display, p_target); - printf("Target '%s' not supported.\n", target_name); + print_verbose(vformat("Target '%s' not supported.", target_name)); if (target_name) { XFree(target_name); } @@ -4826,7 +4869,7 @@ DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, W vformat("Your video card drivers seem not to support the required Vulkan version.\n\n" "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n" "You can enable the OpenGL 3 driver by starting the engine from the\n" - "command line with the command:\n'%s --rendering-driver opengl3'\n\n" + "command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n" "If you recently updated your video card drivers, try rebooting.", executable_name), "Unable to initialize Vulkan video driver"); @@ -4849,7 +4892,9 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V #ifdef GLES3_ENABLED if (gl_manager) { - visualInfo = gl_manager->get_vi(x11_display); + Error err; + visualInfo = gl_manager->get_vi(x11_display, err); + ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't acquire visual info from display."); vi_selected = true; } #endif @@ -4948,11 +4993,11 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V window_attributes_ime.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask | ExposureMask; wd.x11_xim_window = XCreateWindow(x11_display, wd.x11_window, 0, 0, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, CWEventMask, &window_attributes_ime); - +#ifdef XKB_ENABLED if (dead_tbl && xkb_loaded) { wd.xkb_state = xkb_compose_state_new(dead_tbl, XKB_COMPOSE_STATE_NO_FLAGS); } - +#endif // Enable receiving notification when the window is initialized (MapNotify) // so the focus can be set at the right time. if (!wd.no_focus && !wd.is_popup) { @@ -5217,6 +5262,7 @@ 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, Error &r_error) { KeyMappingX11::initialize(); +#ifdef SOWRAP_ENABLED #ifdef DEBUG_ENABLED int dylibloader_verbose = 1; #else @@ -5231,9 +5277,12 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode r_error = ERR_UNAVAILABLE; ERR_FAIL_MSG("Can't load XCursor dynamically."); } - +#ifdef XKB_ENABLED xkb_loaded = (initialize_xkbcommon(dylibloader_verbose) == 0); - + if (!xkb_context_new || !xkb_compose_table_new_from_locale || !xkb_compose_table_unref || !xkb_context_unref || !xkb_compose_state_feed || !xkb_compose_state_unref || !xkb_compose_state_new || !xkb_compose_state_get_status || !xkb_compose_state_get_utf8 || !xkb_keysym_to_utf32 || !xkb_keysym_to_upper) { + xkb_loaded = false; + } +#endif if (initialize_xext(dylibloader_verbose) != 0) { r_error = ERR_UNAVAILABLE; ERR_FAIL_MSG("Can't load Xext dynamically."); @@ -5258,7 +5307,13 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode r_error = ERR_UNAVAILABLE; ERR_FAIL_MSG("Can't load Xinput2 dynamically."); } +#else +#ifdef XKB_ENABLED + xkb_loaded = true; +#endif +#endif +#ifdef XKB_ENABLED if (xkb_loaded) { xkb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (xkb_ctx) { @@ -5275,6 +5330,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode dead_tbl = xkb_compose_table_new_from_locale(xkb_ctx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); } } +#endif Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); @@ -5717,16 +5773,19 @@ DisplayServerX11::~DisplayServerX11() { wd.xic = nullptr; } XDestroyWindow(x11_display, wd.x11_xim_window); +#ifdef XKB_ENABLED if (xkb_loaded) { if (wd.xkb_state) { xkb_compose_state_unref(wd.xkb_state); wd.xkb_state = nullptr; } } +#endif XUnmapWindow(x11_display, wd.x11_window); XDestroyWindow(x11_display, wd.x11_window); } +#ifdef XKB_ENABLED if (xkb_loaded) { if (dead_tbl) { xkb_compose_table_unref(dead_tbl); @@ -5735,6 +5794,7 @@ DisplayServerX11::~DisplayServerX11() { xkb_context_unref(xkb_ctx); } } +#endif //destroy drivers #if defined(VULKAN_ENABLED) |