diff options
Diffstat (limited to 'platform/linuxbsd')
| -rw-r--r-- | platform/linuxbsd/wayland/detect_prime_egl.cpp | 28 | ||||
| -rw-r--r-- | platform/linuxbsd/wayland/detect_prime_egl.h | 28 | ||||
| -rw-r--r-- | platform/linuxbsd/wayland/display_server_wayland.cpp | 9 | ||||
| -rw-r--r-- | platform/linuxbsd/x11/display_server_x11.cpp | 99 | ||||
| -rw-r--r-- | platform/linuxbsd/x11/display_server_x11.h | 3 | ||||
| -rw-r--r-- | platform/linuxbsd/x11/gl_manager_x11.cpp | 2 |
6 files changed, 119 insertions, 50 deletions
diff --git a/platform/linuxbsd/wayland/detect_prime_egl.cpp b/platform/linuxbsd/wayland/detect_prime_egl.cpp index 4c97a80039..e24c03c869 100644 --- a/platform/linuxbsd/wayland/detect_prime_egl.cpp +++ b/platform/linuxbsd/wayland/detect_prime_egl.cpp @@ -38,15 +38,6 @@ #include <stdlib.h> -#ifdef GLAD_ENABLED -#include "thirdparty/glad/glad/egl.h" -#include "thirdparty/glad/glad/gl.h" -#else -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GL/glcorearb.h> -#endif // GLAD_ENABLED - #include <cstring> #include <sys/types.h> @@ -57,7 +48,7 @@ #undef glGetString // Runs inside a child. Exiting will not quit the engine. -void DetectPrimeEGL::create_context() { +void DetectPrimeEGL::create_context(EGLenum p_platform_enum) { #if defined(GLAD_ENABLED) if (!gladLoaderLoadEGL(nullptr)) { print_verbose("Unable to load EGL, GPU detection skipped."); @@ -65,7 +56,18 @@ void DetectPrimeEGL::create_context() { } #endif - EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + EGLDisplay egl_display = EGL_NO_DISPLAY; + + if (GLAD_EGL_VERSION_1_5) { + egl_display = eglGetPlatformDisplay(p_platform_enum, nullptr, nullptr); + } else if (GLAD_EGL_EXT_platform_base) { +#ifdef EGL_EXT_platform_base + egl_display = eglGetPlatformDisplayEXT(p_platform_enum, nullptr, nullptr); +#endif + } else { + egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + } + EGLConfig egl_config; EGLContext egl_context = EGL_NO_CONTEXT; @@ -110,7 +112,7 @@ void DetectPrimeEGL::create_context() { eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_context); } -int DetectPrimeEGL::detect_prime() { +int DetectPrimeEGL::detect_prime(EGLenum p_platform_enum) { pid_t p; int priorities[4] = {}; String vendors[4]; @@ -168,7 +170,7 @@ int DetectPrimeEGL::detect_prime() { setenv("DRI_PRIME", itos(i).utf8().ptr(), 1); - create_context(); + create_context(p_platform_enum); PFNGLGETSTRINGPROC glGetString = (PFNGLGETSTRINGPROC)eglGetProcAddress("glGetString"); const char *vendor = (const char *)glGetString(GL_VENDOR); diff --git a/platform/linuxbsd/wayland/detect_prime_egl.h b/platform/linuxbsd/wayland/detect_prime_egl.h index 26351b0dce..3391e020d8 100644 --- a/platform/linuxbsd/wayland/detect_prime_egl.h +++ b/platform/linuxbsd/wayland/detect_prime_egl.h @@ -34,6 +34,30 @@ #ifdef GLES3_ENABLED #ifdef EGL_ENABLED +#ifdef GLAD_ENABLED +#include "thirdparty/glad/glad/egl.h" +#include "thirdparty/glad/glad/gl.h" +#else +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GL/glcorearb.h> + +#define GLAD_EGL_VERSION_1_5 1 + +#ifdef EGL_EXT_platform_base +#define GLAD_EGL_EXT_platform_base 1 +#endif + +#define KHRONOS_STATIC 1 +extern "C" EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list); +#undef KHRONOS_STATIC + +#endif // GLAD_ENABLED + +#ifndef EGL_EXT_platform_base +#define GLAD_EGL_EXT_platform_base 0 +#endif + class DetectPrimeEGL { private: struct Vendor { @@ -53,10 +77,10 @@ private: { nullptr, 0 } }; - static void create_context(); + static void create_context(EGLenum p_platform_enum); public: - static int detect_prime(); + static int detect_prime(EGLenum p_platform_enum); }; #endif // GLES3_ENABLED diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 12d3a6fd2f..c231dc0f90 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -1018,8 +1018,7 @@ void DisplayServerWayland::cursor_set_custom_image(const Ref<Resource> &p_cursor wayland_thread.cursor_shape_clear_custom_image(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()); CustomCursor &cursor = custom_cursors[p_shape]; @@ -1343,7 +1342,7 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win if (prime_idx == -1) { print_verbose("Detecting GPUs, set DRI_PRIME in the environment to override GPU detection logic."); - prime_idx = DetectPrimeEGL::detect_prime(); + prime_idx = DetectPrimeEGL::detect_prime(EGL_PLATFORM_WAYLAND_KHR); } if (prime_idx) { @@ -1356,7 +1355,7 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win if (rendering_driver == "opengl3") { egl_manager = memnew(EGLManagerWayland); - if (egl_manager->initialize() != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) { + if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) { memdelete(egl_manager); egl_manager = nullptr; @@ -1376,7 +1375,7 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win if (rendering_driver == "opengl3_es") { egl_manager = memnew(EGLManagerWaylandGLES); - if (egl_manager->initialize() != OK) { + if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK) { memdelete(egl_manager); egl_manager = nullptr; r_error = ERR_CANT_CREATE; 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; diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index 7c69df3df0..341ba5f079 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -263,7 +263,6 @@ class DisplayServerX11 : public DisplayServer { Point2i last_click_pos = Point2i(-100, -100); uint64_t last_click_ms = 0; MouseButton last_click_button_index = MouseButton::NONE; - BitField<MouseButtonMask> last_button_state; bool app_focused = false; uint64_t time_since_no_focus = 0; @@ -292,7 +291,6 @@ class DisplayServerX11 : public DisplayServer { Rect2i _screen_get_rect(int p_screen) const; - BitField<MouseButtonMask> _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(); @@ -332,6 +330,7 @@ class DisplayServerX11 : public DisplayServer { bool xrandr_ext_ok = true; bool xinerama_ext_ok = true; bool xshaped_ext_ok = true; + bool xwayland = false; struct Property { unsigned char *data; diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp index febb7ae584..738ebffa02 100644 --- a/platform/linuxbsd/x11/gl_manager_x11.cpp +++ b/platform/linuxbsd/x11/gl_manager_x11.cpp @@ -357,7 +357,7 @@ void GLManager_X11::set_use_vsync(bool p_use) { GLXDrawable drawable = glXGetCurrentDrawable(); glXSwapIntervalEXT(disp.x11_display, drawable, val); } else { - WARN_PRINT("Could not set V-Sync mode. V-Sync is not supported."); + WARN_PRINT_ONCE("Could not set V-Sync mode, as changing V-Sync mode is not supported by the graphics driver."); return; } use_vsync = p_use; |
