diff options
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r-- | platform/linuxbsd/detect.py | 68 | ||||
-rw-r--r-- | platform/linuxbsd/freedesktop_portal_desktop.cpp | 49 | ||||
-rw-r--r-- | platform/linuxbsd/freedesktop_portal_desktop.h | 13 | ||||
-rw-r--r-- | platform/linuxbsd/joypad_linux.cpp | 6 | ||||
-rw-r--r-- | platform/linuxbsd/os_linuxbsd.cpp | 4 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/SCsub | 1 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/display_server_wayland.cpp | 81 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/display_server_wayland.h | 5 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/egl_manager_wayland_gles.cpp | 64 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/egl_manager_wayland_gles.h | 53 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/wayland_thread.cpp | 197 | ||||
-rw-r--r-- | platform/linuxbsd/wayland/wayland_thread.h | 62 | ||||
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.cpp | 94 | ||||
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.h | 1 | ||||
-rw-r--r-- | platform/linuxbsd/x11/gl_manager_x11.cpp | 14 | ||||
-rw-r--r-- | platform/linuxbsd/x11/gl_manager_x11.h | 1 |
16 files changed, 447 insertions, 266 deletions
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 27dec73b65..47f3bcadc9 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -1,7 +1,7 @@ import os import platform import sys -from methods import get_compiler_version, using_gcc +from methods import print_warning, print_error, get_compiler_version, using_gcc from platform_methods import detect_arch from typing import TYPE_CHECKING @@ -20,7 +20,7 @@ def can_build(): pkgconf_error = os.system("pkg-config --version > /dev/null") if pkgconf_error: - print("Error: pkg-config not found. Aborting.") + print_error("pkg-config not found. Aborting.") return False return True @@ -50,7 +50,7 @@ def get_opts(): BoolVariable("wayland", "Enable Wayland display", True), BoolVariable("libdecor", "Enable libdecor support", True), BoolVariable("touch", "Enable touch events", True), - BoolVariable("execinfo", "Use libexecinfo on systems where glibc is not available", None), + BoolVariable("execinfo", "Use libexecinfo on systems where glibc is not available", False), ] @@ -75,7 +75,7 @@ def configure(env: "SConsEnvironment"): # Validate arch. supported_arches = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64"] if env["arch"] not in supported_arches: - print( + print_error( 'Unsupported CPU architecture "%s" for Linux / *BSD. Supported architectures are: %s.' % (env["arch"], ", ".join(supported_arches)) ) @@ -128,7 +128,9 @@ def configure(env: "SConsEnvironment"): found_wrapper = True break if not found_wrapper: - print("Couldn't locate mold installation path. Make sure it's installed in /usr or /usr/local.") + print_error( + "Couldn't locate mold installation path. Make sure it's installed in /usr or /usr/local." + ) sys.exit(255) else: env.Append(LINKFLAGS=["-fuse-ld=mold"]) @@ -185,7 +187,7 @@ def configure(env: "SConsEnvironment"): if env["lto"] != "none": if env["lto"] == "thin": if not env["use_llvm"]: - print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") + print_error("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") sys.exit(255) env.Append(CCFLAGS=["-flto=thin"]) env.Append(LINKFLAGS=["-flto=thin"]) @@ -209,7 +211,7 @@ def configure(env: "SConsEnvironment"): if env["wayland"]: if os.system("wayland-scanner -v 2>/dev/null") != 0: - print("wayland-scanner not found. Disabling Wayland support.") + print_warning("wayland-scanner not found. Disabling Wayland support.") env["wayland"] = False if env["touch"]: @@ -227,7 +229,7 @@ def configure(env: "SConsEnvironment"): env["builtin_harfbuzz"], ] if (not all(ft_linked_deps)) and any(ft_linked_deps): # All or nothing. - print( + print_error( "These libraries should be either all builtin, or all system provided:\n" "freetype, libpng, zlib, graphite, harfbuzz.\n" "Please specify `builtin_<name>=no` for all of them, or none." @@ -307,7 +309,7 @@ def configure(env: "SConsEnvironment"): if not env["builtin_embree"] and env["arch"] in ["x86_64", "arm64"]: # No pkgconfig file so far, hardcode expected lib name. - env.Append(LIBS=["embree3"]) + env.Append(LIBS=["embree4"]) if not env["builtin_openxr"]: env.ParseConfig("pkg-config openxr --cflags --libs") @@ -318,7 +320,7 @@ def configure(env: "SConsEnvironment"): env.ParseConfig("pkg-config fontconfig --cflags --libs") env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"]) else: - print("Warning: fontconfig development libraries not found. Disabling the system fonts support.") + print_warning("fontconfig development libraries not found. Disabling the system fonts support.") env["fontconfig"] = False else: env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"]) @@ -329,7 +331,7 @@ def configure(env: "SConsEnvironment"): env.ParseConfig("pkg-config alsa --cflags --libs") env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) else: - print("Warning: ALSA development libraries not found. Disabling the ALSA audio driver.") + print_warning("ALSA development libraries not found. Disabling the ALSA audio driver.") env["alsa"] = False else: env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) @@ -340,7 +342,7 @@ def configure(env: "SConsEnvironment"): env.ParseConfig("pkg-config libpulse --cflags --libs") env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"]) else: - print("Warning: PulseAudio development libraries not found. Disabling the PulseAudio audio driver.") + print_warning("PulseAudio development libraries not found. Disabling the PulseAudio audio driver.") env["pulseaudio"] = False else: env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"]) @@ -351,7 +353,7 @@ def configure(env: "SConsEnvironment"): env.ParseConfig("pkg-config dbus-1 --cflags --libs") env.Append(CPPDEFINES=["DBUS_ENABLED"]) else: - print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.") + print_warning("D-Bus development libraries not found. Disabling screensaver prevention.") env["dbus"] = False else: env.Append(CPPDEFINES=["DBUS_ENABLED"]) @@ -362,7 +364,7 @@ def configure(env: "SConsEnvironment"): env.ParseConfig("pkg-config speech-dispatcher --cflags --libs") env.Append(CPPDEFINES=["SPEECHD_ENABLED"]) else: - print("Warning: speech-dispatcher development libraries not found. Disabling text to speech support.") + print_warning("speech-dispatcher development libraries not found. Disabling text to speech support.") env["speechd"] = False else: env.Append(CPPDEFINES=["SPEECHD_ENABLED"]) @@ -373,11 +375,11 @@ def configure(env: "SConsEnvironment"): env.Append(CPPDEFINES=["XKB_ENABLED"]) else: if env["wayland"]: - print("Error: libxkbcommon development libraries required by Wayland not found. Aborting.") + print_error("libxkbcommon development libraries required by Wayland not found. Aborting.") sys.exit(255) else: - print( - "Warning: libxkbcommon development libraries not found. Disabling dead key composition and key label support." + print_warning( + "libxkbcommon development libraries not found. Disabling dead key composition and key label support." ) else: env.Append(CPPDEFINES=["XKB_ENABLED"]) @@ -390,7 +392,7 @@ def configure(env: "SConsEnvironment"): env.ParseConfig("pkg-config libudev --cflags --libs") env.Append(CPPDEFINES=["UDEV_ENABLED"]) else: - print("Warning: libudev development libraries not found. Disabling controller hotplugging support.") + print_warning("libudev development libraries not found. Disabling controller hotplugging support.") env["udev"] = False else: env.Append(CPPDEFINES=["UDEV_ENABLED"]) @@ -416,31 +418,31 @@ def configure(env: "SConsEnvironment"): if env["x11"]: if not env["use_sowrap"]: if os.system("pkg-config --exists x11"): - print("Error: X11 libraries not found. Aborting.") + print_error("X11 libraries not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config x11 --cflags --libs") if os.system("pkg-config --exists xcursor"): - print("Error: Xcursor library not found. Aborting.") + print_error("Xcursor library not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config xcursor --cflags --libs") if os.system("pkg-config --exists xinerama"): - print("Error: Xinerama library not found. Aborting.") + print_error("Xinerama library not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config xinerama --cflags --libs") if os.system("pkg-config --exists xext"): - print("Error: Xext library not found. Aborting.") + print_error("Xext library not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config xext --cflags --libs") if os.system("pkg-config --exists xrandr"): - print("Error: XrandR library not found. Aborting.") + print_error("XrandR library not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config xrandr --cflags --libs") if os.system("pkg-config --exists xrender"): - print("Error: XRender library not found. Aborting.") + print_error("XRender library not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config xrender --cflags --libs") if os.system("pkg-config --exists xi"): - print("Error: Xi library not found. Aborting.") + print_error("Xi library not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config xi --cflags --libs") env.Append(CPPDEFINES=["X11_ENABLED"]) @@ -448,20 +450,20 @@ def configure(env: "SConsEnvironment"): if env["wayland"]: if not env["use_sowrap"]: if os.system("pkg-config --exists libdecor-0"): - print("Warning: libdecor development libraries not found. Disabling client-side decorations.") + print_warning("libdecor development libraries not found. Disabling client-side decorations.") env["libdecor"] = False else: env.ParseConfig("pkg-config libdecor-0 --cflags --libs") if os.system("pkg-config --exists wayland-client"): - print("Error: Wayland client library not found. Aborting.") + print_error("Wayland client library not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config wayland-client --cflags --libs") if os.system("pkg-config --exists wayland-cursor"): - print("Error: Wayland cursor library not found. Aborting.") + print_error("Wayland cursor library not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config wayland-cursor --cflags --libs") if os.system("pkg-config --exists wayland-egl"): - print("Error: Wayland EGL library not found. Aborting.") + print_error("Wayland EGL library not found. Aborting.") sys.exit(255) env.ParseConfig("pkg-config wayland-egl --cflags --libs") @@ -489,16 +491,12 @@ def configure(env: "SConsEnvironment"): env.Append(LIBS=["dl"]) if platform.libc_ver()[0] != "glibc": - # The default crash handler depends on glibc, so if the host uses - # a different libc (BSD libc, musl), fall back to libexecinfo. - if not "execinfo" in env: - print("Note: Using `execinfo=yes` for the crash handler as required on platforms where glibc is missing.") - env["execinfo"] = True - if env["execinfo"]: env.Append(LIBS=["execinfo"]) env.Append(CPPDEFINES=["CRASH_HANDLER_ENABLED"]) else: + # The default crash handler depends on glibc, so if the host uses + # a different libc (BSD libc, musl), libexecinfo is required. print("Note: Using `execinfo=no` disables the crash handler on platforms where glibc is missing.") else: env.Append(CPPDEFINES=["CRASH_HANDLER_ENABLED"]) diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp index 214725832f..e65404a531 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.cpp +++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp @@ -496,24 +496,30 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo return OK; } -void FreeDesktopPortalDesktop::_file_dialog_callback(const Callable &p_callable, const Variant &p_status, const Variant &p_list, const Variant &p_index, const Variant &p_options, bool p_opt_in_cb) { - if (p_opt_in_cb) { - Variant ret; - Callable::CallError ce; - const Variant *args[4] = { &p_status, &p_list, &p_index, &p_options }; - - p_callable.callp(args, 4, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialogs callback: %s.", Variant::get_callable_error_text(p_callable, args, 4, ce))); - } - } else { - Variant ret; - Callable::CallError ce; - const Variant *args[3] = { &p_status, &p_list, &p_index }; +void FreeDesktopPortalDesktop::process_file_dialog_callbacks() { + MutexLock lock(file_dialog_mutex); + while (!pending_cbs.is_empty()) { + FileDialogCallback cb = pending_cbs.front()->get(); + pending_cbs.pop_front(); + + if (cb.opt_in_cb) { + Variant ret; + Callable::CallError ce; + const Variant *args[4] = { &cb.status, &cb.files, &cb.index, &cb.options }; + + cb.callback.callp(args, 4, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(cb.callback, args, 4, ce))); + } + } else { + Variant ret; + Callable::CallError ce; + const Variant *args[3] = { &cb.status, &cb.files, &cb.index }; - p_callable.callp(args, 3, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialogs callback: %s.", Variant::get_callable_error_text(p_callable, args, 3, ce))); + cb.callback.callp(args, 3, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(cb.callback, args, 3, ce))); + } } } } @@ -556,7 +562,14 @@ void FreeDesktopPortalDesktop::_thread_monitor(void *p_ud) { file_chooser_parse_response(&iter, fd.filter_names, cancel, uris, index, options); if (fd.callback.is_valid()) { - callable_mp(portal, &FreeDesktopPortalDesktop::_file_dialog_callback).call_deferred(fd.callback, !cancel, uris, index, options, fd.opt_in_cb); + FileDialogCallback cb; + cb.callback = fd.callback; + cb.status = !cancel; + cb.files = uris; + cb.index = index; + cb.options = options; + cb.opt_in_cb = fd.opt_in_cb; + portal->pending_cbs.push_back(cb); } if (fd.prev_focus != DisplayServer::INVALID_WINDOW_ID) { callable_mp(DisplayServer::get_singleton(), &DisplayServer::window_move_to_foreground).call_deferred(fd.prev_focus); diff --git a/platform/linuxbsd/freedesktop_portal_desktop.h b/platform/linuxbsd/freedesktop_portal_desktop.h index ba9c352e62..96c38de2c2 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.h +++ b/platform/linuxbsd/freedesktop_portal_desktop.h @@ -56,8 +56,6 @@ private: static void append_dbus_dict_bool(DBusMessageIter *p_iter, const String &p_key, bool p_value); static bool file_chooser_parse_response(DBusMessageIter *p_iter, const Vector<String> &p_names, bool &r_cancel, Vector<String> &r_urls, int &r_index, Dictionary &r_options); - void _file_dialog_callback(const Callable &p_callable, const Variant &p_status, const Variant &p_list, const Variant &p_index, const Variant &p_options, bool p_opt_in_cb); - struct FileDialogData { Vector<String> filter_names; DisplayServer::WindowID prev_focus = DisplayServer::INVALID_WINDOW_ID; @@ -67,6 +65,16 @@ private: bool opt_in_cb = false; }; + struct FileDialogCallback { + Callable callback; + Variant status; + Variant files; + Variant index; + Variant options; + bool opt_in_cb = false; + }; + List<FileDialogCallback> pending_cbs; + Mutex file_dialog_mutex; Vector<FileDialogData> file_dialogs; Thread monitor_thread; @@ -86,6 +94,7 @@ public: bool is_supported() { return !unsupported; } Error file_dialog_show(DisplayServer::WindowID p_window_id, const String &p_xid, const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, DisplayServer::FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb); + void process_file_dialog_callbacks(); // Retrieve the system's preferred color scheme. // 0: No preference or unknown. diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp index 827c567785..6e546c4531 100644 --- a/platform/linuxbsd/joypad_linux.cpp +++ b/platform/linuxbsd/joypad_linux.cpp @@ -175,7 +175,7 @@ void JoypadLinux::enumerate_joypads(udev *p_udev) { if (devnode) { String devnode_str = devnode; - if (devnode_str.find(ignore_str) == -1) { + if (!devnode_str.contains(ignore_str)) { open_joypad(devnode); } } @@ -214,7 +214,7 @@ void JoypadLinux::monitor_joypads(udev *p_udev) { const char *devnode = udev_device_get_devnode(dev); if (devnode) { String devnode_str = devnode; - if (devnode_str.find(ignore_str) == -1) { + if (!devnode_str.contains(ignore_str)) { if (action == "add") { open_joypad(devnode); } else if (String(action) == "remove") { @@ -244,7 +244,7 @@ void JoypadLinux::monitor_joypads() { continue; } sprintf(fname, "/dev/input/%.*s", 16, current->d_name); - if (attached_devices.find(fname) == -1) { + if (!attached_devices.has(fname)) { open_joypad(fname); } } diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 68b4cd7f5a..6355562feb 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -184,7 +184,7 @@ String OS_LinuxBSD::get_processor_name() const { while (!f->eof_reached()) { const String line = f->get_line(); - if (line.find("model name") != -1) { + if (line.contains("model name")) { return line.split(":")[1].strip_edges(); } } @@ -269,7 +269,7 @@ String OS_LinuxBSD::get_systemd_os_release_info_value(const String &key) const { if (f.is_valid()) { while (!f->eof_reached()) { const String line = f->get_line(); - if (line.find(key) != -1) { + if (line.contains(key)) { String value = line.split("=")[1].strip_edges(); value = value.trim_prefix("\""); return value.trim_suffix("\""); diff --git a/platform/linuxbsd/wayland/SCsub b/platform/linuxbsd/wayland/SCsub index cab45b7672..add5bdb504 100644 --- a/platform/linuxbsd/wayland/SCsub +++ b/platform/linuxbsd/wayland/SCsub @@ -199,6 +199,7 @@ if env["vulkan"]: if env["opengl3"]: source_files.append("egl_manager_wayland.cpp") + source_files.append("egl_manager_wayland_gles.cpp") objects = [] diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index d00d5deb2c..f7995472d0 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -46,6 +46,8 @@ #ifdef GLES3_ENABLED #include "detect_prime_egl.h" #include "drivers/gles3/rasterizer_gles3.h" +#include "wayland/egl_manager_wayland.h" +#include "wayland/egl_manager_wayland_gles.h" #endif String DisplayServerWayland::_get_app_id_from_context(Context p_context) { @@ -548,7 +550,15 @@ float DisplayServerWayland::screen_get_scale(int p_screen) const { MutexLock mutex_lock(wayland_thread.mutex); if (p_screen == SCREEN_OF_MAIN_WINDOW) { - p_screen = window_get_current_screen(); + // Wayland does not expose fractional scale factors at the screen-level, but + // some code relies on it. Since this special screen is the default and a lot + // of code relies on it, we'll return the window's scale, which is what we + // really care about. After all, we have very little use of the actual screen + // enumeration APIs and we're (for now) in single-window mode anyways. + struct wl_surface *wl_surface = wayland_thread.window_get_wl_surface(MAIN_WINDOW_ID); + WaylandThread::WindowState *ws = wayland_thread.wl_surface_get_window_state(wl_surface); + + return wayland_thread.window_state_get_scale_factor(ws); } return wayland_thread.screen_get_data(p_screen).scale; @@ -1161,6 +1171,12 @@ void DisplayServerWayland::process_events() { } } +#ifdef DBUS_ENABLED + if (portal_desktop) { + portal_desktop->process_file_dialog_callbacks(); + } +#endif + wayland_thread.mutex.unlock(); Input::get_singleton()->flush_buffered_events(); @@ -1174,14 +1190,6 @@ void DisplayServerWayland::release_rendering_thread() { #endif } -void DisplayServerWayland::make_rendering_thread() { -#ifdef GLES3_ENABLED - if (egl_manager) { - egl_manager->make_current(); - } -#endif -} - void DisplayServerWayland::swap_buffers() { #ifdef GLES3_ENABLED if (egl_manager) { @@ -1210,6 +1218,7 @@ Vector<String> DisplayServerWayland::get_rendering_drivers_func() { #ifdef GLES3_ENABLED drivers.push_back("opengl3"); + drivers.push_back("opengl3_es"); #endif return drivers; @@ -1260,14 +1269,14 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win #ifdef RD_ENABLED #ifdef VULKAN_ENABLED - if (p_rendering_driver == "vulkan") { + if (rendering_driver == "vulkan") { rendering_context = memnew(RenderingContextDriverVulkanWayland); } #endif if (rendering_context) { if (rendering_context->initialize() != OK) { - ERR_PRINT(vformat("Could not initialize %s", p_rendering_driver)); + ERR_PRINT(vformat("Could not initialize %s", rendering_driver)); memdelete(rendering_context); rendering_context = nullptr; r_error = ERR_CANT_CREATE; @@ -1277,7 +1286,14 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win #endif #ifdef GLES3_ENABLED - if (p_rendering_driver == "opengl3") { + if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") { +#ifdef SOWRAP_ENABLED + if (initialize_wayland_egl(dylibloader_verbose) != 0) { + WARN_PRINT("Can't load the Wayland EGL library."); + return; + } +#endif // SOWRAP_ENABLED + if (getenv("DRI_PRIME") == nullptr) { int prime_idx = -1; @@ -1320,23 +1336,38 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win } } - egl_manager = memnew(EGLManagerWayland); + if (rendering_driver == "opengl3") { + egl_manager = memnew(EGLManagerWayland); -#ifdef SOWRAP_ENABLED - if (initialize_wayland_egl(dylibloader_verbose) != 0) { - WARN_PRINT("Can't load the Wayland EGL library."); - return; - } -#endif // SOWRAP_ENABLED + if (egl_manager->initialize() != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) { + memdelete(egl_manager); + egl_manager = nullptr; - if (egl_manager->initialize() != OK) { - memdelete(egl_manager); - egl_manager = nullptr; - r_error = ERR_CANT_CREATE; - ERR_FAIL_MSG("Could not initialize GLES3."); + bool fallback = GLOBAL_GET("rendering/gl_compatibility/fallback_to_gles"); + if (fallback) { + WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES."); + rendering_driver = "opengl3_es"; + } else { + r_error = ERR_UNAVAILABLE; + ERR_FAIL_MSG("Could not initialize OpenGL."); + } + } else { + RasterizerGLES3::make_current(true); + } } - RasterizerGLES3::make_current(true); + if (rendering_driver == "opengl3_es") { + egl_manager = memnew(EGLManagerWaylandGLES); + + if (egl_manager->initialize() != OK) { + memdelete(egl_manager); + egl_manager = nullptr; + r_error = ERR_CANT_CREATE; + ERR_FAIL_MSG("Could not initialize GLES3."); + } + + RasterizerGLES3::make_current(false); + } } #endif // GLES3_ENABLED diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h index b7d7bee005..1bad358462 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.h +++ b/platform/linuxbsd/wayland/display_server_wayland.h @@ -45,7 +45,7 @@ #endif //RD_ENABLED #ifdef GLES3_ENABLED -#include "wayland/egl_manager_wayland.h" +#include "drivers/egl/egl_manager.h" #endif #if defined(SPEECHD_ENABLED) @@ -126,7 +126,7 @@ class DisplayServerWayland : public DisplayServer { #endif #ifdef GLES3_ENABLED - EGLManagerWayland *egl_manager = nullptr; + EGLManager *egl_manager = nullptr; #endif #ifdef SPEECHD_ENABLED @@ -276,7 +276,6 @@ public: virtual void process_events() override; virtual void release_rendering_thread() override; - virtual void make_rendering_thread() override; virtual void swap_buffers() override; virtual void set_context(Context p_context) override; diff --git a/platform/linuxbsd/wayland/egl_manager_wayland_gles.cpp b/platform/linuxbsd/wayland/egl_manager_wayland_gles.cpp new file mode 100644 index 0000000000..9431b18f05 --- /dev/null +++ b/platform/linuxbsd/wayland/egl_manager_wayland_gles.cpp @@ -0,0 +1,64 @@ +/**************************************************************************/ +/* egl_manager_wayland_gles.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "egl_manager_wayland_gles.h" + +#ifdef WAYLAND_ENABLED +#ifdef EGL_ENABLED +#ifdef GLES3_ENABLED + +const char *EGLManagerWaylandGLES::_get_platform_extension_name() const { + return "EGL_KHR_platform_wayland"; +} + +EGLenum EGLManagerWaylandGLES::_get_platform_extension_enum() const { + return EGL_PLATFORM_WAYLAND_KHR; +} + +EGLenum EGLManagerWaylandGLES::_get_platform_api_enum() const { + return EGL_OPENGL_ES_API; +} + +Vector<EGLAttrib> EGLManagerWaylandGLES::_get_platform_display_attributes() const { + return Vector<EGLAttrib>(); +} + +Vector<EGLint> EGLManagerWaylandGLES::_get_platform_context_attribs() const { + Vector<EGLint> ret; + ret.push_back(EGL_CONTEXT_MAJOR_VERSION); + ret.push_back(3); + ret.push_back(EGL_NONE); + + return ret; +} + +#endif // GLES3_ENABLED +#endif // EGL_ENABLED +#endif // WAYLAND_ENABLED diff --git a/platform/linuxbsd/wayland/egl_manager_wayland_gles.h b/platform/linuxbsd/wayland/egl_manager_wayland_gles.h new file mode 100644 index 0000000000..f526f18277 --- /dev/null +++ b/platform/linuxbsd/wayland/egl_manager_wayland_gles.h @@ -0,0 +1,53 @@ +/**************************************************************************/ +/* egl_manager_wayland_gles.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef EGL_MANAGER_WAYLAND_GLES_H +#define EGL_MANAGER_WAYLAND_GLES_H + +#ifdef WAYLAND_ENABLED +#ifdef EGL_ENABLED +#ifdef GLES3_ENABLED + +#include "drivers/egl/egl_manager.h" + +class EGLManagerWaylandGLES : public EGLManager { +public: + virtual const char *_get_platform_extension_name() const override; + virtual EGLenum _get_platform_extension_enum() const override; + virtual EGLenum _get_platform_api_enum() const override; + virtual Vector<EGLAttrib> _get_platform_display_attributes() const override; + virtual Vector<EGLint> _get_platform_context_attribs() const override; +}; + +#endif // GLES3_ENABLED +#endif // EGL_ENABLED +#endif // WAYLAND_ENABLED + +#endif // EGL_MANAGER_WAYLAND_GLES_H diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp index 7f9008e952..aabf1abdda 100644 --- a/platform/linuxbsd/wayland/wayland_thread.cpp +++ b/platform/linuxbsd/wayland/wayland_thread.cpp @@ -371,28 +371,22 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re } if (strcmp(interface, zxdg_exporter_v1_interface.name) == 0) { - registry->wl_exporter = (struct zxdg_exporter_v1 *)wl_registry_bind(wl_registry, name, &zxdg_exporter_v1_interface, 1); - registry->wl_exporter_name = name; + registry->xdg_exporter = (struct zxdg_exporter_v1 *)wl_registry_bind(wl_registry, name, &zxdg_exporter_v1_interface, 1); + registry->xdg_exporter_name = name; return; } if (strcmp(interface, wl_compositor_interface.name) == 0) { - registry->wl_compositor = (struct wl_compositor *)wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4); + registry->wl_compositor = (struct wl_compositor *)wl_registry_bind(wl_registry, name, &wl_compositor_interface, CLAMP((int)version, 1, 6)); registry->wl_compositor_name = name; return; } - if (strcmp(interface, wl_subcompositor_interface.name) == 0) { - registry->wl_subcompositor = (struct wl_subcompositor *)wl_registry_bind(wl_registry, name, &wl_subcompositor_interface, 1); - registry->wl_subcompositor_name = name; - return; - } - if (strcmp(interface, wl_data_device_manager_interface.name) == 0) { - registry->wl_data_device_manager = (struct wl_data_device_manager *)wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3); + registry->wl_data_device_manager = (struct wl_data_device_manager *)wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, CLAMP((int)version, 1, 3)); registry->wl_data_device_manager_name = name; - // This global creates some seats data. Let's do that for the ones already available. + // This global creates some seat data. Let's do that for the ones already available. for (struct wl_seat *wl_seat : registry->wl_seats) { SeatState *ss = wl_seat_get_seat_state(wl_seat); ERR_FAIL_NULL(ss); @@ -406,7 +400,7 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re } if (strcmp(interface, wl_output_interface.name) == 0) { - struct wl_output *wl_output = (struct wl_output *)wl_registry_bind(wl_registry, name, &wl_output_interface, 2); + struct wl_output *wl_output = (struct wl_output *)wl_registry_bind(wl_registry, name, &wl_output_interface, CLAMP((int)version, 1, 4)); wl_proxy_tag_godot((struct wl_proxy *)wl_output); registry->wl_outputs.push_back(wl_output); @@ -421,7 +415,7 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re } if (strcmp(interface, wl_seat_interface.name) == 0) { - struct wl_seat *wl_seat = (struct wl_seat *)wl_registry_bind(wl_registry, name, &wl_seat_interface, 5); + struct wl_seat *wl_seat = (struct wl_seat *)wl_registry_bind(wl_registry, name, &wl_seat_interface, CLAMP((int)version, 1, 9)); wl_proxy_tag_godot((struct wl_proxy *)wl_seat); SeatState *ss = memnew(SeatState); @@ -466,7 +460,7 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re } if (strcmp(interface, xdg_wm_base_interface.name) == 0) { - registry->xdg_wm_base = (struct xdg_wm_base *)wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, MAX(2, MIN(6, (int)version))); + registry->xdg_wm_base = (struct xdg_wm_base *)wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, CLAMP((int)version, 1, 6)); registry->xdg_wm_base_name = name; xdg_wm_base_add_listener(registry->xdg_wm_base, &xdg_wm_base_listener, nullptr); @@ -502,7 +496,7 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re if (strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) { registry->wp_primary_selection_device_manager = (struct zwp_primary_selection_device_manager_v1 *)wl_registry_bind(wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1); - // This global creates some seats data. Let's do that for the ones already available. + // This global creates some seat data. Let's do that for the ones already available. for (struct wl_seat *wl_seat : registry->wl_seats) { SeatState *ss = wl_seat_get_seat_state(wl_seat); ERR_FAIL_NULL(ss); @@ -570,13 +564,13 @@ void WaylandThread::_wl_registry_on_global_remove(void *data, struct wl_registry return; } - if (name == registry->wl_exporter_name) { - if (registry->wl_exporter) { - zxdg_exporter_v1_destroy(registry->wl_exporter); - registry->wl_exporter = nullptr; + if (name == registry->xdg_exporter_name) { + if (registry->xdg_exporter) { + zxdg_exporter_v1_destroy(registry->xdg_exporter); + registry->xdg_exporter = nullptr; } - registry->wl_exporter_name = 0; + registry->xdg_exporter_name = 0; return; } @@ -592,17 +586,6 @@ void WaylandThread::_wl_registry_on_global_remove(void *data, struct wl_registry return; } - if (name == registry->wl_subcompositor_name) { - if (registry->wl_subcompositor) { - wl_subcompositor_destroy(registry->wl_subcompositor); - registry->wl_subcompositor = nullptr; - } - - registry->wl_subcompositor_name = 0; - - return; - } - if (name == registry->wl_data_device_manager_name) { if (registry->wl_data_device_manager) { wl_data_device_manager_destroy(registry->wl_data_device_manager); @@ -1000,6 +983,12 @@ void WaylandThread::_wl_output_on_geometry(void *data, struct wl_output *wl_outp ss->pending_data.make.parse_utf8(make); ss->pending_data.model.parse_utf8(model); + + // `wl_output::done` is a version 2 addition. We'll directly update the data + // for compatibility. + if (wl_output_get_version(wl_output) == 1) { + ss->data = ss->pending_data; + } } void WaylandThread::_wl_output_on_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { @@ -1010,8 +999,17 @@ void WaylandThread::_wl_output_on_mode(void *data, struct wl_output *wl_output, ss->pending_data.size.height = height; ss->pending_data.refresh_rate = refresh ? refresh / 1000.0f : -1; + + // `wl_output::done` is a version 2 addition. We'll directly update the data + // for compatibility. + if (wl_output_get_version(wl_output) == 1) { + ss->data = ss->pending_data; + } } +// NOTE: The following `wl_output` events are only for version 2 onwards, so we +// can assume that they're "atomic" (i.e. rely on the `wl_output::done` event). + void WaylandThread::_wl_output_on_done(void *data, struct wl_output *wl_output) { ScreenState *ss = (ScreenState *)data; ERR_FAIL_NULL(ss); @@ -1523,7 +1521,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point wayland_thread->push_message(msg); } - if (pd.discrete_scroll_vector - old_pd.discrete_scroll_vector != Vector2i()) { + if (pd.discrete_scroll_vector_120 - old_pd.discrete_scroll_vector_120 != Vector2i()) { // This is a discrete scroll (eg. from a scroll wheel), so we'll just emit // scroll wheel buttons. if (pd.scroll_vector.y != 0) { @@ -1596,13 +1594,13 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point if (test_button == MouseButton::WHEEL_UP || test_button == MouseButton::WHEEL_DOWN) { // If this is a discrete scroll, specify how many "clicks" it did for this // pointer frame. - mb->set_factor(abs(pd.discrete_scroll_vector.y)); + mb->set_factor(Math::abs(pd.discrete_scroll_vector_120.y / (float)120)); } if (test_button == MouseButton::WHEEL_RIGHT || test_button == MouseButton::WHEEL_LEFT) { // If this is a discrete scroll, specify how many "clicks" it did for this // pointer frame. - mb->set_factor(abs(pd.discrete_scroll_vector.x)); + mb->set_factor(fabs(pd.discrete_scroll_vector_120.x / (float)120)); } mb->set_button_mask(pd.pressed_button_mask); @@ -1661,7 +1659,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point // Reset the scroll vectors as we already handled them. pd.scroll_vector = Vector2(); - pd.discrete_scroll_vector = Vector2(); + pd.discrete_scroll_vector_120 = Vector2i(); // Update the data all getters read. Wayland's specification requires us to do // this, since all pointer actions are sent in individual events. @@ -1683,6 +1681,9 @@ void WaylandThread::_wl_pointer_on_axis_source(void *data, struct wl_pointer *wl void WaylandThread::_wl_pointer_on_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) { } +// NOTE: This event is deprecated since version 8 and superseded by +// `wl_pointer::axis_value120`. This thus converts the data to its +// fraction-of-120 format. void WaylandThread::_wl_pointer_on_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete) { SeatState *ss = (SeatState *)data; ERR_FAIL_NULL(ss); @@ -1694,17 +1695,37 @@ void WaylandThread::_wl_pointer_on_axis_discrete(void *data, struct wl_pointer * PointerData &pd = ss->pointer_data_buffer; + // NOTE: We can allow ourselves to not accumulate this data (and thus just + // assign it) as the spec guarantees only one event per axis type. + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { - pd.discrete_scroll_vector.y = discrete; + pd.discrete_scroll_vector_120.y = discrete * 120; } if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { - pd.discrete_scroll_vector.x = discrete; + pd.discrete_scroll_vector_120.x = discrete * 120; } } -// TODO: Add support to this event. +// Supersedes `wl_pointer::axis_discrete` Since version 8. void WaylandThread::_wl_pointer_on_axis_value120(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t value120) { + SeatState *ss = (SeatState *)data; + ERR_FAIL_NULL(ss); + + if (!ss->pointed_surface) { + // We're probably on a decoration or some other third-party thing. + return; + } + + PointerData &pd = ss->pointer_data_buffer; + + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { + pd.discrete_scroll_vector_120.y += value120; + } + + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { + pd.discrete_scroll_vector_120.x += value120; + } } // TODO: Add support to this event. @@ -1999,7 +2020,7 @@ void WaylandThread::_wp_relative_pointer_on_relative_motion(void *data, struct z pd.relative_motion_time = uptime_lo; } -void WaylandThread::_wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers) { +void WaylandThread::_wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers) { SeatState *ss = (SeatState *)data; ERR_FAIL_NULL(ss); @@ -2009,7 +2030,7 @@ void WaylandThread::_wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_po } } -void WaylandThread::_wp_pointer_gesture_pinch_on_update(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation) { +void WaylandThread::_wp_pointer_gesture_pinch_on_update(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation) { SeatState *ss = (SeatState *)data; ERR_FAIL_NULL(ss); @@ -2068,7 +2089,7 @@ void WaylandThread::_wp_pointer_gesture_pinch_on_update(void *data, struct zwp_p } } -void WaylandThread::_wp_pointer_gesture_pinch_on_end(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled) { +void WaylandThread::_wp_pointer_gesture_pinch_on_end(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled) { SeatState *ss = (SeatState *)data; ERR_FAIL_NULL(ss); @@ -2093,7 +2114,7 @@ void WaylandThread::_wp_primary_selection_device_on_selection(void *data, struct ss->wp_primary_selection_offer = id; } -void WaylandThread::_wp_primary_selection_offer_on_offer(void *data, struct zwp_primary_selection_offer_v1 *zwp_primary_selection_offer_v1, const char *mime_type) { +void WaylandThread::_wp_primary_selection_offer_on_offer(void *data, struct zwp_primary_selection_offer_v1 *wp_primary_selection_offer_v1, const char *mime_type) { OfferState *os = (OfferState *)data; ERR_FAIL_NULL(os); @@ -2147,10 +2168,10 @@ void WaylandThread::_wp_primary_selection_source_on_cancelled(void *data, struct } } -void WaylandThread::_wp_tablet_seat_on_tablet_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_v2 *id) { +void WaylandThread::_wp_tablet_seat_on_tablet_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_v2 *id) { } -void WaylandThread::_wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_tool_v2 *id) { +void WaylandThread::_wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_tool_v2 *id) { SeatState *ss = (SeatState *)data; ERR_FAIL_NULL(ss); @@ -2163,31 +2184,31 @@ void WaylandThread::_wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_ ss->tablet_tools.push_back(id); } -void WaylandThread::_wp_tablet_seat_on_pad_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id) { +void WaylandThread::_wp_tablet_seat_on_pad_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id) { } -void WaylandThread::_wp_tablet_tool_on_type(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t tool_type) { - TabletToolState *state = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_type(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t tool_type) { + TabletToolState *state = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (state && tool_type == ZWP_TABLET_TOOL_V2_TYPE_ERASER) { state->is_eraser = true; } } -void WaylandThread::_wp_tablet_tool_on_hardware_serial(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t hardware_serial_hi, uint32_t hardware_serial_lo) { +void WaylandThread::_wp_tablet_tool_on_hardware_serial(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_serial_hi, uint32_t hardware_serial_lo) { } -void WaylandThread::_wp_tablet_tool_on_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t hardware_id_hi, uint32_t hardware_id_lo) { +void WaylandThread::_wp_tablet_tool_on_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_id_hi, uint32_t hardware_id_lo) { } -void WaylandThread::_wp_tablet_tool_on_capability(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t capability) { +void WaylandThread::_wp_tablet_tool_on_capability(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t capability) { } -void WaylandThread::_wp_tablet_tool_on_done(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) { +void WaylandThread::_wp_tablet_tool_on_done(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2) { } -void WaylandThread::_wp_tablet_tool_on_removed(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_removed(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2199,7 +2220,7 @@ void WaylandThread::_wp_tablet_tool_on_removed(void *data, struct zwp_tablet_too return; } - List<struct zwp_tablet_tool_v2 *>::Element *E = ss->tablet_tools.find(zwp_tablet_tool_v2); + List<struct zwp_tablet_tool_v2 *>::Element *E = ss->tablet_tools.find(wp_tablet_tool_v2); if (E && E->get()) { struct zwp_tablet_tool_v2 *tool = E->get(); @@ -2213,8 +2234,8 @@ void WaylandThread::_wp_tablet_tool_on_removed(void *data, struct zwp_tablet_too } } -void WaylandThread::_wp_tablet_tool_on_proximity_in(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_proximity_in(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2241,8 +2262,8 @@ void WaylandThread::_wp_tablet_tool_on_proximity_in(void *data, struct zwp_table DEBUG_LOG_WAYLAND_THREAD("Tablet tool entered window."); } -void WaylandThread::_wp_tablet_tool_on_proximity_out(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_proximity_out(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2268,8 +2289,8 @@ void WaylandThread::_wp_tablet_tool_on_proximity_out(void *data, struct zwp_tabl DEBUG_LOG_WAYLAND_THREAD("Tablet tool left window."); } -void WaylandThread::_wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2286,8 +2307,8 @@ void WaylandThread::_wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v td.button_time = OS::get_singleton()->get_ticks_msec(); } -void WaylandThread::_wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2302,8 +2323,8 @@ void WaylandThread::_wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 td.button_time = OS::get_singleton()->get_ticks_msec(); } -void WaylandThread::_wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t x, wl_fixed_t y) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t x, wl_fixed_t y) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2323,8 +2344,8 @@ void WaylandThread::_wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool td.motion_time = OS::get_singleton()->get_ticks_msec(); } -void WaylandThread::_wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t pressure) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t pressure) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2333,12 +2354,12 @@ void WaylandThread::_wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_to ts->data_pending.pressure = pressure; } -void WaylandThread::_wp_tablet_tool_on_distance(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t distance) { +void WaylandThread::_wp_tablet_tool_on_distance(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t distance) { // Unsupported } -void WaylandThread::_wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t tilt_x, wl_fixed_t tilt_y) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t tilt_x, wl_fixed_t tilt_y) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2350,20 +2371,20 @@ void WaylandThread::_wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v td.tilt.y = wl_fixed_to_double(tilt_y); } -void WaylandThread::_wp_tablet_tool_on_rotation(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t degrees) { +void WaylandThread::_wp_tablet_tool_on_rotation(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees) { // Unsupported. } -void WaylandThread::_wp_tablet_tool_on_slider(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, int32_t position) { +void WaylandThread::_wp_tablet_tool_on_slider(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, int32_t position) { // Unsupported. } -void WaylandThread::_wp_tablet_tool_on_wheel(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t degrees, int32_t clicks) { +void WaylandThread::_wp_tablet_tool_on_wheel(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees, int32_t clicks) { // TODO } -void WaylandThread::_wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, uint32_t button, uint32_t state) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, uint32_t button, uint32_t state) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2398,8 +2419,8 @@ void WaylandThread::_wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool } } -void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t time) { - TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2); +void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t time) { + TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2); if (!ts) { return; @@ -2440,7 +2461,7 @@ void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_ // According to the tablet proto spec, tilt is expressed in degrees relative // to the Z axis of the tablet, so it shouldn't go over 90 degrees either way, // I think. We'll clamp it just in case. - td.tilt = td.tilt.clamp(Vector2(-90, -90), Vector2(90, 90)); + td.tilt = td.tilt.clampf(-90, 90); mm->set_tilt(td.tilt / 90); @@ -3071,8 +3092,8 @@ void WaylandThread::window_create(DisplayServer::WindowID p_window_id, int p_wid // "loop". wl_surface_commit(ws.wl_surface); - if (registry.wl_exporter) { - ws.xdg_exported = zxdg_exporter_v1_export(registry.wl_exporter, ws.wl_surface); + if (registry.xdg_exporter) { + ws.xdg_exported = zxdg_exporter_v1_export(registry.xdg_exporter, ws.wl_surface); zxdg_exported_v1_add_listener(ws.xdg_exported, &xdg_exported_listener, &ws); } @@ -3406,7 +3427,7 @@ bool WaylandThread::window_get_idle_inhibition(DisplayServer::WindowID p_window_ WaylandThread::ScreenData WaylandThread::screen_get_data(int p_screen) const { ERR_FAIL_INDEX_V(p_screen, registry.wl_outputs.size(), ScreenData()); - return wl_output_get_screen_state(registry.wl_outputs[p_screen])->data; + return wl_output_get_screen_state(registry.wl_outputs.get(p_screen))->data; } int WaylandThread::get_screen_count() const { @@ -3529,9 +3550,6 @@ Error WaylandThread::init() { ERR_FAIL_NULL_V_MSG(registry.wl_shm, ERR_UNAVAILABLE, "Can't obtain the Wayland shared memory global."); ERR_FAIL_NULL_V_MSG(registry.wl_compositor, ERR_UNAVAILABLE, "Can't obtain the Wayland compositor global."); - ERR_FAIL_NULL_V_MSG(registry.wl_subcompositor, ERR_UNAVAILABLE, "Can't obtain the Wayland subcompositor global."); - ERR_FAIL_NULL_V_MSG(registry.wl_data_device_manager, ERR_UNAVAILABLE, "Can't obtain the Wayland data device manager global."); - ERR_FAIL_NULL_V_MSG(registry.wp_pointer_constraints, ERR_UNAVAILABLE, "Can't obtain the Wayland pointer constraints global."); ERR_FAIL_NULL_V_MSG(registry.xdg_wm_base, ERR_UNAVAILABLE, "Can't obtain the Wayland XDG shell global."); if (!registry.xdg_decoration_manager) { @@ -3660,7 +3678,10 @@ void WaylandThread::cursor_shape_set_custom_image(DisplayServer::CursorShape p_c munmap(cursor.buffer_data, cursor.buffer_data_size); } - cursor.buffer_data = (uint32_t *)mmap(nullptr, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + // NOTE: From `wl_keyboard`s of version 7 or later, the spec requires the mmap + // operation to be done with MAP_PRIVATE, as "MAP_SHARED may fail". We'll do it + // regardless of global version. + cursor.buffer_data = (uint32_t *)mmap(nullptr, data_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (cursor.wl_buffer) { // Clean up the old Wayland buffer. @@ -4179,18 +4200,14 @@ void WaylandThread::destroy() { xdg_wm_base_destroy(registry.xdg_wm_base); } - if (registry.wl_exporter) { - zxdg_exporter_v1_destroy(registry.wl_exporter); + if (registry.xdg_exporter) { + zxdg_exporter_v1_destroy(registry.xdg_exporter); } if (registry.wl_shm) { wl_shm_destroy(registry.wl_shm); } - if (registry.wl_subcompositor) { - wl_subcompositor_destroy(registry.wl_subcompositor); - } - if (registry.wl_compositor) { wl_compositor_destroy(registry.wl_compositor); } diff --git a/platform/linuxbsd/wayland/wayland_thread.h b/platform/linuxbsd/wayland/wayland_thread.h index d49f0c9d34..d35a5b7139 100644 --- a/platform/linuxbsd/wayland/wayland_thread.h +++ b/platform/linuxbsd/wayland/wayland_thread.h @@ -133,8 +133,8 @@ public: struct xdg_wm_base *xdg_wm_base = nullptr; uint32_t xdg_wm_base_name = 0; - struct zxdg_exporter_v1 *wl_exporter = nullptr; - uint32_t wl_exporter_name = 0; + struct zxdg_exporter_v1 *xdg_exporter = nullptr; + uint32_t xdg_exporter_name = 0; // wayland-protocols globals. @@ -300,8 +300,8 @@ public: // The amount "scrolled" in pixels, in each direction. Vector2 scroll_vector; - // The amount of scroll "clicks" in each direction. - Vector2i discrete_scroll_vector; + // The amount of scroll "clicks" in each direction, in fractions of 120. + Vector2i discrete_scroll_vector_120; uint32_t pinch_scale = 1; }; @@ -579,41 +579,41 @@ private: static void _wp_relative_pointer_on_relative_motion(void *data, struct zwp_relative_pointer_v1 *wp_relative_pointer_v1, uint32_t uptime_hi, uint32_t uptime_lo, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_unaccel, wl_fixed_t dy_unaccel); - static void _wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers); - static void _wp_pointer_gesture_pinch_on_update(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation); - static void _wp_pointer_gesture_pinch_on_end(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled); + static void _wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers); + static void _wp_pointer_gesture_pinch_on_update(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation); + static void _wp_pointer_gesture_pinch_on_end(void *data, struct zwp_pointer_gesture_pinch_v1 *zp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled); static void _wp_primary_selection_device_on_data_offer(void *data, struct zwp_primary_selection_device_v1 *wp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *offer); static void _wp_primary_selection_device_on_selection(void *data, struct zwp_primary_selection_device_v1 *wp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *id); - static void _wp_primary_selection_offer_on_offer(void *data, struct zwp_primary_selection_offer_v1 *zwp_primary_selection_offer_v1, const char *mime_type); + static void _wp_primary_selection_offer_on_offer(void *data, struct zwp_primary_selection_offer_v1 *wp_primary_selection_offer_v1, const char *mime_type); static void _wp_primary_selection_source_on_send(void *data, struct zwp_primary_selection_source_v1 *wp_primary_selection_source_v1, const char *mime_type, int32_t fd); static void _wp_primary_selection_source_on_cancelled(void *data, struct zwp_primary_selection_source_v1 *wp_primary_selection_source_v1); - static void _wp_tablet_seat_on_tablet_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_v2 *id); - static void _wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_tool_v2 *id); - static void _wp_tablet_seat_on_pad_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id); - - static void _wp_tablet_tool_on_type(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t tool_type); - static void _wp_tablet_tool_on_hardware_serial(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t hardware_serial_hi, uint32_t hardware_serial_lo); - static void _wp_tablet_tool_on_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t hardware_id_hi, uint32_t hardware_id_lo); - static void _wp_tablet_tool_on_capability(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t capability); - static void _wp_tablet_tool_on_done(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2); - static void _wp_tablet_tool_on_removed(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2); - static void _wp_tablet_tool_on_proximity_in(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface); - static void _wp_tablet_tool_on_proximity_out(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2); - static void _wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial); - static void _wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2); - static void _wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t x, wl_fixed_t y); - static void _wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t pressure); - static void _wp_tablet_tool_on_distance(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t distance); - static void _wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t tilt_x, wl_fixed_t tilt_y); - static void _wp_tablet_tool_on_rotation(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t degrees); - static void _wp_tablet_tool_on_slider(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, int32_t position); - static void _wp_tablet_tool_on_wheel(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t degrees, int32_t clicks); - static void _wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, uint32_t button, uint32_t state); - static void _wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t time); + static void _wp_tablet_seat_on_tablet_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_v2 *id); + static void _wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_tool_v2 *id); + static void _wp_tablet_seat_on_pad_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id); + + static void _wp_tablet_tool_on_type(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t tool_type); + static void _wp_tablet_tool_on_hardware_serial(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_serial_hi, uint32_t hardware_serial_lo); + static void _wp_tablet_tool_on_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_id_hi, uint32_t hardware_id_lo); + static void _wp_tablet_tool_on_capability(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t capability); + static void _wp_tablet_tool_on_done(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2); + static void _wp_tablet_tool_on_removed(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2); + static void _wp_tablet_tool_on_proximity_in(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface); + static void _wp_tablet_tool_on_proximity_out(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2); + static void _wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial); + static void _wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2); + static void _wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t x, wl_fixed_t y); + static void _wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t pressure); + static void _wp_tablet_tool_on_distance(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t distance); + static void _wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t tilt_x, wl_fixed_t tilt_y); + static void _wp_tablet_tool_on_rotation(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees); + static void _wp_tablet_tool_on_slider(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, int32_t position); + static void _wp_tablet_tool_on_wheel(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees, int32_t clicks); + static void _wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, uint32_t button, uint32_t state); + static void _wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t time); static void _xdg_toplevel_decoration_on_configure(void *data, struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration, uint32_t mode); diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 9069dd423f..daf0247540 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -1007,7 +1007,8 @@ int DisplayServerX11::get_screen_count() const { if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) { XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); XFree(xsi); - } else { + } + if (count == 0) { count = XScreenCount(x11_display); } @@ -1068,25 +1069,29 @@ Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const { ERR_FAIL_COND_V(p_screen < 0, rect); // Using Xinerama Extension. + bool found = false; int event_base, error_base; if (xinerama_ext_ok && 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) { + if (count > 0) { + // 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; + found = true; + } else { + ERR_PRINT(vformat("Invalid screen index: %d (count: %d).", p_screen, count)); + } + } XFree(xsi); } - } else { + } + + if (!found) { int count = XScreenCount(x11_display); if (p_screen < count) { Window root = XRootWindow(x11_display, p_screen); @@ -1097,7 +1102,7 @@ Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const { rect.size.width = xwa.width; rect.size.height = xwa.height; } else { - ERR_PRINT("Invalid screen index: " + itos(p_screen) + "(count: " + itos(count) + ")."); + ERR_PRINT(vformat("Invalid screen index: %d (count: %d).", p_screen, count)); } } @@ -1503,25 +1508,33 @@ Ref<Image> DisplayServerX11::screen_get_image(int p_screen) const { XImage *image = nullptr; + bool found = false; int event_base, error_base; if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) { int xin_count; XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &xin_count); - if (p_screen < xin_count) { - int x_count = XScreenCount(x11_display); - for (int i = 0; i < x_count; i++) { - Window root = XRootWindow(x11_display, i); - XWindowAttributes root_attrs; - XGetWindowAttributes(x11_display, root, &root_attrs); - if ((xsi[p_screen].x_org >= root_attrs.x) && (xsi[p_screen].x_org <= root_attrs.x + root_attrs.width) && (xsi[p_screen].y_org >= root_attrs.y) && (xsi[p_screen].y_org <= root_attrs.y + root_attrs.height)) { - image = XGetImage(x11_display, root, xsi[p_screen].x_org, xsi[p_screen].y_org, xsi[p_screen].width, xsi[p_screen].height, AllPlanes, ZPixmap); - break; + if (xsi) { + if (xin_count > 0) { + if (p_screen < xin_count) { + int x_count = XScreenCount(x11_display); + for (int i = 0; i < x_count; i++) { + Window root = XRootWindow(x11_display, i); + XWindowAttributes root_attrs; + XGetWindowAttributes(x11_display, root, &root_attrs); + if ((xsi[p_screen].x_org >= root_attrs.x) && (xsi[p_screen].x_org <= root_attrs.x + root_attrs.width) && (xsi[p_screen].y_org >= root_attrs.y) && (xsi[p_screen].y_org <= root_attrs.y + root_attrs.height)) { + found = true; + image = XGetImage(x11_display, root, xsi[p_screen].x_org, xsi[p_screen].y_org, xsi[p_screen].width, xsi[p_screen].height, AllPlanes, ZPixmap); + break; + } + } + } else { + ERR_PRINT(vformat("Invalid screen index: %d (count: %d).", p_screen, xin_count)); } } - } else { - ERR_FAIL_V_MSG(Ref<Image>(), "Invalid screen index: " + itos(p_screen) + "(count: " + itos(xin_count) + ")."); + XFree(xsi); } - } else { + } + if (!found) { int x_count = XScreenCount(x11_display); if (p_screen < x_count) { Window root = XRootWindow(x11_display, p_screen); @@ -1531,7 +1544,7 @@ Ref<Image> DisplayServerX11::screen_get_image(int p_screen) const { image = XGetImage(x11_display, root, root_attrs.x, root_attrs.y, root_attrs.width, root_attrs.height, AllPlanes, ZPixmap); } else { - ERR_FAIL_V_MSG(Ref<Image>(), "Invalid screen index: " + itos(p_screen) + "(count: " + itos(x_count) + ")."); + ERR_PRINT(vformat("Invalid screen index: %d (count: %d).", p_screen, x_count)); } } @@ -2225,7 +2238,7 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) { ERR_FAIL_COND(!windows.has(p_window)); Size2i size = p_size; - size = size.max(Size2i(1, 1)); + size = size.maxi(1); WindowData &wd = windows[p_window]; @@ -4268,7 +4281,9 @@ bool DisplayServerX11::_window_focus_check() { } void DisplayServerX11::process_events() { - _THREAD_SAFE_METHOD_ + ERR_FAIL_COND(!Thread::is_main_thread()); + + _THREAD_SAFE_LOCK_ #ifdef DISPLAY_SERVER_X11_DEBUG_LOGS_ENABLED static int frame = 0; @@ -4992,7 +5007,7 @@ void DisplayServerX11::process_events() { files.write[i] = files[i].replace("file://", "").uri_decode(); } - if (!windows[window_id].drop_files_callback.is_null()) { + if (windows[window_id].drop_files_callback.is_valid()) { windows[window_id].drop_files_callback.call(files); } @@ -5097,6 +5112,14 @@ void DisplayServerX11::process_events() { */ } +#ifdef DBUS_ENABLED + if (portal_desktop) { + portal_desktop->process_file_dialog_callbacks(); + } +#endif + + _THREAD_SAFE_UNLOCK_ + Input::get_singleton()->flush_buffered_events(); } @@ -5111,17 +5134,6 @@ void DisplayServerX11::release_rendering_thread() { #endif } -void DisplayServerX11::make_rendering_thread() { -#if defined(GLES3_ENABLED) - if (gl_manager) { - gl_manager->make_current(); - } - if (gl_manager_egl) { - gl_manager_egl->make_current(); - } -#endif -} - void DisplayServerX11::swap_buffers() { #if defined(GLES3_ENABLED) if (gl_manager) { diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index 715a8e48e6..8a7062857c 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -526,7 +526,6 @@ public: virtual void process_events() override; virtual void release_rendering_thread() override; - virtual void make_rendering_thread() override; virtual void swap_buffers() override; virtual void set_context(Context p_context) override; diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp index 602dd784e0..febb7ae584 100644 --- a/platform/linuxbsd/x11/gl_manager_x11.cpp +++ b/platform/linuxbsd/x11/gl_manager_x11.cpp @@ -311,20 +311,6 @@ void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) { _internal_set_current_window(&win); } -void GLManager_X11::make_current() { - if (!_current_window) { - return; - } - if (!_current_window->in_use) { - WARN_PRINT("current window not in use!"); - return; - } - const GLDisplay &disp = get_current_display(); - if (!glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context)) { - ERR_PRINT("glXMakeCurrent failed"); - } -} - void GLManager_X11::swap_buffers() { if (!_current_window) { return; diff --git a/platform/linuxbsd/x11/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h index 235c7d22f9..06e147e39f 100644 --- a/platform/linuxbsd/x11/gl_manager_x11.h +++ b/platform/linuxbsd/x11/gl_manager_x11.h @@ -117,7 +117,6 @@ public: void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height); void release_current(); - void make_current(); void swap_buffers(); void window_make_current(DisplayServer::WindowID p_window_id); |