diff options
author | EncryptedCicada | 2021-12-16 10:08:32 +0530 |
---|---|---|
committer | EncryptedCicada | 2021-12-16 10:08:32 +0530 |
commit | 3c94b47ff80eb81fae96049b4ed1b26657afe390 (patch) | |
tree | c2c5fdf23620dd295d3fb160804669d5be5dd668 | |
download | aur-3c94b47ff80eb81fae96049b4ed1b26657afe390.tar.gz |
Initial upload
-rw-r--r-- | .SRCINFO | 40 | ||||
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | 0001-libdecoration-support.patch | 1328 | ||||
-rw-r--r-- | 0002-set-O_NONBLOCK-on-repeat-timerfd.patch | 33 | ||||
-rw-r--r-- | 0003-Continue-poll-if-timerfd-cant-be-read.patch | 46 | ||||
-rw-r--r-- | 0003-wayland-don-t-crash-app-on-api-calls-to-window-focus.patch | 39 | ||||
-rw-r--r-- | 0004-fix-broken-opengl-screenshots-on-mutter.patch | 33 | ||||
-rw-r--r-- | 0005-don-t-crash-on-get-scancode-name.patch | 10 | ||||
-rw-r--r-- | PKGBUILD | 66 | ||||
-rw-r--r-- | README.md | 104 |
10 files changed, 1705 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..e6fd301bbdd7 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,40 @@ +pkgbase = glfw-wayland-minecraft-libdecoration + pkgdesc = A free, open source, portable framework for graphical application development (wayland, patched for Minecraft and Gnome) + pkgver = 3.4.0 + pkgrel = 1 + url = https://github.com/EncryptedCicada/minecraft-wayland + arch = x86_64 + license = custom:ZLIB + makedepends = mesa + makedepends = cmake + makedepends = doxygen + makedepends = vulkan-headers + makedepends = vulkan-icd-loader + makedepends = extra-cmake-modules + makedepends = wayland-protocols + makedepends = libxi + makedepends = libxrandr + makedepends = libxcursor + makedepends = libxkbcommon + makedepends = libxinerama + depends = wayland + depends = libxkbcommon + depends = libgl + depends = libdecor + provides = glfw=3.4.0 + conflicts = glfw + conflicts = glfw-wayland + source = https://github.com/glfw/glfw/archive/87d5646f5d2bad0562744501633bf8105f59c193.tar.gz + source = 0001-libdecoration-support.patch + source = 0002-set-O_NONBLOCK-on-repeat-timerfd.patch + source = 0003-wayland-don-t-crash-app-on-api-calls-to-window-focus.patch + source = 0004-fix-broken-opengl-screenshots-on-mutter.patch + source = 0005-don-t-crash-on-get-scancode-name.patch + sha256sums = 7b8c990cfb039110d38c7f5bb21948c402933be3f93f333fe7dcda3deaf72aa4 + sha256sums = c163b4a0a6496d758bc656203c23151015683754a6b5c2fc4944df7296d6b5af + sha256sums = 5cd74a83dc7824c7696c1534f880b7a4a0992bb6dba6e4531ad1c040541f1d30 + sha256sums = a442f8c7e40fb09775f922b95402108b366114874ee96e370c29e5f8500a02b7 + sha256sums = 27aea70b07df2d46ac7469c129d28d695eff1ec9492489aa7b2558dd780ebdf0 + sha256sums = 16a2410511d75f00902ab1869942a80d85261f8390a97be946f82662891351e5 + +pkgname = glfw-wayland-minecraft-libdecoration diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..d53251af9d26 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +* +!*.patch +!.SRCINFO +!.gitignore +!PKGBUILD +!README.md
\ No newline at end of file diff --git a/0001-libdecoration-support.patch b/0001-libdecoration-support.patch new file mode 100644 index 000000000000..3a33e93990b6 --- /dev/null +++ b/0001-libdecoration-support.patch @@ -0,0 +1,1328 @@ +From 96ad19143d8d20553bfb86d440faaaf91eaff955 Mon Sep 17 00:00:00 2001 +From: Christian Rauch <Rauch.Christian@gmx.de> +Date: Sun, 12 Apr 2020 14:21:03 +0100 +Subject: [PATCH 1/8] wl: fix resize glitches + +--- + src/wl_window.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/wl_window.c b/src/wl_window.c +index 939f9c196..3899c858c 100644 +--- a/src/wl_window.c ++++ b/src/wl_window.c +@@ -292,7 +292,6 @@ static void setOpaqueRegion(_GLFWwindow* window) + + wl_region_add(region, 0, 0, window->wl.width, window->wl.height); + wl_surface_set_opaque_region(window->wl.surface, region); +- wl_surface_commit(window->wl.surface); + wl_region_destroy(region); + } + + +From 69f6e358e266581ec21d3e602c626d54abb06b39 Mon Sep 17 00:00:00 2001 +From: Christian Rauch <Rauch.Christian@gmx.de> +Date: Sat, 9 May 2020 21:06:23 +0100 +Subject: [PATCH 2/8] wl: initialise fullscreen + +--- + src/wl_window.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/wl_window.c b/src/wl_window.c +index 3899c858c..46cd742c6 100644 +--- a/src/wl_window.c ++++ b/src/wl_window.c +@@ -826,6 +826,9 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, + window->wl.visible = GLFW_FALSE; + } + ++ if (window->monitor) ++ setFullscreen(window, window->monitor, window->videoMode.refreshRate); ++ + window->wl.currentCursor = NULL; + + window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*)); + +From ce0e2096b556c6753b8c21ec841b09321f9ee54e Mon Sep 17 00:00:00 2001 +From: Christian Rauch <Rauch.Christian@gmx.de> +Date: Mon, 3 May 2021 23:46:21 +0100 +Subject: [PATCH 3/8] make windows opaque by default + +--- + src/window.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/window.c b/src/window.c +index 518b27fd5..688971f36 100644 +--- a/src/window.c ++++ b/src/window.c +@@ -279,7 +279,7 @@ void glfwDefaultWindowHints(void) + _glfw.hints.framebuffer.redBits = 8; + _glfw.hints.framebuffer.greenBits = 8; + _glfw.hints.framebuffer.blueBits = 8; +- _glfw.hints.framebuffer.alphaBits = 8; ++ _glfw.hints.framebuffer.alphaBits = 0; + _glfw.hints.framebuffer.depthBits = 24; + _glfw.hints.framebuffer.stencilBits = 8; + _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE; + +From 5df88303d22f5fd0861b6b8023e795c84ef31ae9 Mon Sep 17 00:00:00 2001 +From: Christian Rauch <Rauch.Christian@gmx.de> +Date: Fri, 19 Jun 2020 00:05:12 +0100 +Subject: [PATCH 4/8] cmake: enable AddressSanitizer in Debug builds + +--- + CMakeLists.txt | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 59ab473c9..fb9fab99a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -66,6 +66,25 @@ if (GLFW_BUILD_DOCS) + find_package(Doxygen) + endif() + ++if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") ++ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} \ ++ -fsanitize=address \ ++ -fsanitize=bool \ ++ -fsanitize=bounds \ ++ -fsanitize=enum \ ++ -fsanitize=float-cast-overflow \ ++ -fsanitize=float-divide-by-zero \ ++ -fsanitize=nonnull-attribute \ ++ -fsanitize=returns-nonnull-attribute \ ++ -fsanitize=signed-integer-overflow \ ++ -fsanitize=undefined \ ++ -fsanitize=vla-bound \ ++ -fno-sanitize=alignment \ ++ -fsanitize=leak \ ++ -fsanitize=object-size \ ++ ") ++endif() ++ + #-------------------------------------------------------------------- + # Set compiler specific flags + #-------------------------------------------------------------------- + +From 8b539bd285d2b7abc3511286f34bffbdc78c9837 Mon Sep 17 00:00:00 2001 +From: Christian Rauch <Rauch.Christian@gmx.de> +Date: Fri, 16 Jul 2021 23:40:45 +0100 +Subject: [PATCH 5/8] CI: install libdecor from upstream + +--- + .github/workflows/build.yml | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml +index d87ae8d1d..efe120a3c 100644 +--- a/.github/workflows/build.yml ++++ b/.github/workflows/build.yml +@@ -43,6 +43,12 @@ jobs: + run: | + sudo apt update + sudo apt install wayland-protocols libwayland-dev libxkbcommon-dev ++ sudo apt install meson libpango1.0-dev ++ git clone --depth 1 https://gitlab.gnome.org/jadahl/libdecor.git --branch 0.1.0 ++ cd libdecor ++ meson build --buildtype release -Ddemo=false -Ddbus=disabled ++ ninja -C build ++ sudo meson install -C build + + - name: Configure static library + run: cmake -S . -B build-static -D GLFW_USE_WAYLAND=ON + +From b2ecb88f3f2cf7bccbf56afacfe2de130873a610 Mon Sep 17 00:00:00 2001 +From: Christian Rauch <Rauch.Christian@gmx.de> +Date: Sun, 9 Feb 2020 14:01:58 +0000 +Subject: [PATCH 6/8] cmake: add 'libdecor' dependency + +--- + CMakeLists.txt | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index fb9fab99a..2ff626ac7 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -40,6 +40,8 @@ cmake_dependent_option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF + "UNIX;NOT APPLE" OFF) + cmake_dependent_option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON + "MSVC" OFF) ++cmake_dependent_option(GLFW_USE_LIBDECOR "use libdecor for client-side window decorations" ON ++ "GLFW_USE_WAYLAND" OFF) + + if (BUILD_SHARED_LIBS AND UNIX) + # On Unix-like systems, shared libraries can use the soname system. +@@ -225,6 +227,14 @@ if (_GLFW_WAYLAND) + list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIRS}") + list(APPEND glfw_LIBRARIES "${Wayland_LINK_LIBRARIES}") + ++ if (GLFW_USE_LIBDECOR) ++ pkg_check_modules(libdecor REQUIRED libdecor-0) ++ list(APPEND glfw_PKG_DEPS "libdecor-0") ++ list(APPEND glfw_INCLUDE_DIRS "${libdecor_INCLUDE_DIRS}") ++ list(APPEND glfw_LIBRARIES "${libdecor_LINK_LIBRARIES}") ++ add_definitions(-DWITH_DECORATION) ++ endif() ++ + include(CheckIncludeFiles) + include(CheckFunctionExists) + check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H) + +From 7ec585b8eb5169896876f11a68c12311237fd9e1 Mon Sep 17 00:00:00 2001 +From: Christian Rauch <Rauch.Christian@gmx.de> +Date: Sun, 9 Feb 2020 14:56:27 +0000 +Subject: [PATCH 7/8] wl: deactivate 'viewporter' decorations + +--- + src/wl_init.c | 13 +++++++++++ + src/wl_platform.h | 10 +++++++++ + src/wl_window.c | 57 ++++++++++++++++++++++++++++++++++++++++++----- + 3 files changed, 74 insertions(+), 6 deletions(-) + +diff --git a/src/wl_init.c b/src/wl_init.c +index 1ba497b71..d49e44e77 100644 +--- a/src/wl_init.c ++++ b/src/wl_init.c +@@ -56,6 +56,7 @@ static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, + _GLFWwindow* window = _glfw.windowListHead; + if (!which) + which = &focus; ++#ifndef WITH_DECORATION + while (window) + { + if (surface == window->wl.decorations.top.surface) +@@ -80,6 +81,7 @@ static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, + } + window = window->next; + } ++#endif + return window; + } + +@@ -103,7 +105,10 @@ static void pointerHandleEnter(void* data, + return; + } + ++#ifndef WITH_DECORATION + window->wl.decorations.focus = focus; ++#endif ++ + _glfw.wl.serial = serial; + _glfw.wl.pointerFocus = window; + +@@ -194,6 +199,7 @@ static void pointerHandleMotion(void* data, + x = wl_fixed_to_double(sx); + y = wl_fixed_to_double(sy); + ++#ifndef WITH_DECORATION + switch (window->wl.decorations.focus) + { + case mainWindow: +@@ -231,6 +237,7 @@ static void pointerHandleMotion(void* data, + default: + assert(0); + } ++#endif + if (_glfw.wl.cursorPreviousName != cursorName) + setCursor(window, cursorName); + } +@@ -248,6 +255,7 @@ static void pointerHandleButton(void* data, + + if (!window) + return; ++#ifndef WITH_DECORATION + if (button == BTN_LEFT) + { + switch (window->wl.decorations.focus) +@@ -306,6 +314,7 @@ static void pointerHandleButton(void* data, + // Don’t pass the button to the user if it was related to a decoration. + if (window->wl.decorations.focus != mainWindow) + return; ++#endif + + _glfw.wl.serial = serial; + +@@ -840,11 +849,13 @@ static void registryHandleGlobal(void* data, + &zxdg_decoration_manager_v1_interface, + 1); + } ++#ifndef WITH_DECORATION + else if (strcmp(interface, "wp_viewporter") == 0) + { + _glfw.wl.viewporter = + wl_registry_bind(registry, name, &wp_viewporter_interface, 1); + } ++#endif + else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) + { + _glfw.wl.relativePointerManager = +@@ -1249,8 +1260,10 @@ void _glfwPlatformTerminate(void) + wl_compositor_destroy(_glfw.wl.compositor); + if (_glfw.wl.shm) + wl_shm_destroy(_glfw.wl.shm); ++#ifndef WITH_DECORATION + if (_glfw.wl.viewporter) + wp_viewporter_destroy(_glfw.wl.viewporter); ++#endif + if (_glfw.wl.decorationManager) + zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager); + if (_glfw.wl.wmBase) +diff --git a/src/wl_platform.h b/src/wl_platform.h +index 966155fdd..4591becbd 100644 +--- a/src/wl_platform.h ++++ b/src/wl_platform.h +@@ -56,7 +56,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR + + #include "wayland-xdg-shell-client-protocol.h" + #include "wayland-xdg-decoration-client-protocol.h" ++#ifndef WITH_DECORATION + #include "wayland-viewporter-client-protocol.h" ++#endif + #include "wayland-relative-pointer-unstable-v1-client-protocol.h" + #include "wayland-pointer-constraints-unstable-v1-client-protocol.h" + #include "wayland-idle-inhibit-unstable-v1-client-protocol.h" +@@ -146,6 +148,7 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st + #define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH) + #define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH) + ++#ifndef WITH_DECORATION + typedef enum _GLFWdecorationSideWayland + { + mainWindow, +@@ -163,6 +166,7 @@ typedef struct _GLFWdecorationWayland + struct wp_viewport* viewport; + + } _GLFWdecorationWayland; ++#endif + + // Wayland-specific per-window data + // +@@ -204,12 +208,16 @@ typedef struct _GLFWwindowWayland + + GLFWbool wasFullscreen; + ++#ifndef WITH_DECORATION + struct { + GLFWbool serverSide; + struct wl_buffer* buffer; + _GLFWdecorationWayland top, left, right, bottom; + int focus; + } decorations; ++#else ++ GLFWbool ssd; ++#endif + + } _GLFWwindowWayland; + +@@ -231,7 +239,9 @@ typedef struct _GLFWlibraryWayland + struct wl_data_source* dataSource; + struct xdg_wm_base* wmBase; + struct zxdg_decoration_manager_v1* decorationManager; ++#ifndef WITH_DECORATION + struct wp_viewporter* viewporter; ++#endif + struct zwp_relative_pointer_manager_v1* relativePointerManager; + struct zwp_pointer_constraints_v1* pointerConstraints; + struct zwp_idle_inhibit_manager_v1* idleInhibitManager; +diff --git a/src/wl_window.c b/src/wl_window.c +index 46cd742c6..9e10e8a3f 100644 +--- a/src/wl_window.c ++++ b/src/wl_window.c +@@ -40,6 +40,10 @@ + #include <sys/timerfd.h> + #include <poll.h> + ++#ifdef WITH_DECORATION ++#include <libdecoration.h> ++#endif ++ + + static int createTmpfileCloexec(char* tmpname) + { +@@ -182,6 +186,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) + return buffer; + } + ++#ifndef WITH_DECORATION + static void createDecoration(_GLFWdecorationWayland* decoration, + struct wl_surface* parent, + struct wl_buffer* buffer, GLFWbool opaque, +@@ -211,7 +216,14 @@ static void createDecoration(_GLFWdecorationWayland* decoration, + else + wl_surface_commit(decoration->surface); + } ++#endif + ++#ifdef WITH_DECORATION ++static void createDecorations(_GLFWwindow* window) ++{ ++ // ++} ++#else + static void createDecorations(_GLFWwindow* window) + { + unsigned char data[] = { 224, 224, 224, 255 }; +@@ -243,7 +255,9 @@ static void createDecorations(_GLFWwindow* window) + -_GLFW_DECORATION_WIDTH, window->wl.height, + window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH); + } ++#endif + ++#ifndef WITH_DECORATION + static void destroyDecoration(_GLFWdecorationWayland* decoration) + { + if (decoration->subsurface) +@@ -256,7 +270,14 @@ static void destroyDecoration(_GLFWdecorationWayland* decoration) + decoration->subsurface = NULL; + decoration->viewport = NULL; + } ++#endif + ++#ifdef WITH_DECORATION ++static void destroyDecorations(_GLFWwindow* window) ++{ ++ // ++} ++#else + static void destroyDecorations(_GLFWwindow* window) + { + destroyDecoration(&window->wl.decorations.top); +@@ -264,6 +285,7 @@ static void destroyDecorations(_GLFWwindow* window) + destroyDecoration(&window->wl.decorations.right); + destroyDecoration(&window->wl.decorations.bottom); + } ++#endif + + static void xdgDecorationHandleConfigure(void* data, + struct zxdg_toplevel_decoration_v1* decoration, +@@ -271,9 +293,11 @@ static void xdgDecorationHandleConfigure(void* data, + { + _GLFWwindow* window = data; + +- window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); +- +- if (!window->wl.decorations.serverSide) ++#ifdef WITH_DECORATION ++ if (!(window->wl.ssd = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE))) ++#else ++ if (!(window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE))) ++#endif + createDecorations(window); + } + +@@ -307,6 +331,7 @@ static void resizeWindow(_GLFWwindow* window) + _glfwInputFramebufferSize(window, scaledWidth, scaledHeight); + _glfwInputWindowContentScale(window, scale, scale); + ++#ifndef WITH_DECORATION + if (!window->wl.decorations.top.surface) + return; + +@@ -333,6 +358,7 @@ static void resizeWindow(_GLFWwindow* window) + wp_viewport_set_destination(window->wl.decorations.bottom.viewport, + window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH); + wl_surface_commit(window->wl.decorations.bottom.surface); ++#endif + } + + static void checkScaleChange(_GLFWwindow* window) +@@ -465,7 +491,11 @@ static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, + monitor->wl.output); + } + setIdleInhibitor(window, GLFW_TRUE); ++#ifdef WITH_DECORATION ++ if (!window->wl.ssd) ++#else + if (!window->wl.decorations.serverSide) ++#endif + destroyDecorations(window); + } + +@@ -573,7 +603,11 @@ static void setXdgDecorations(_GLFWwindow* window) + } + else + { ++#ifdef WITH_DECORATION ++ window->wl.ssd = GLFW_FALSE; ++#else + window->wl.decorations.serverSide = GLFW_FALSE; ++#endif + createDecorations(window); + } + } +@@ -689,8 +723,12 @@ static void incrementCursorImage(_GLFWwindow* window) + { + _GLFWcursor* cursor; + +- if (!window || window->wl.decorations.focus != mainWindow) ++ if (!window) return; ++ ++#ifndef WITH_DECORATION ++ if (window->wl.decorations.focus != mainWindow) + return; ++#endif + + cursor = window->wl.currentCursor; + if (cursor && cursor->wl.cursor) +@@ -860,9 +898,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) + destroyDecorations(window); + if (window->wl.xdg.decoration) + zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration); +- ++#ifndef WITH_DECORATION + if (window->wl.decorations.buffer) + wl_buffer_destroy(window->wl.decorations.buffer); ++#endif + + if (window->wl.native) + wl_egl_window_destroy(window->wl.native); +@@ -967,6 +1006,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, + int* left, int* top, + int* right, int* bottom) + { ++#ifndef WITH_DECORATION + if (window->decorated && !window->monitor && !window->wl.decorations.serverSide) + { + if (top) +@@ -978,6 +1018,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, + if (bottom) + *bottom = _GLFW_DECORATION_WIDTH; + } ++#endif + } + + void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, +@@ -1461,10 +1502,14 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) + + window->wl.currentCursor = cursor; + ++ if (window != _glfw.wl.pointerFocus) return; ++ ++#ifndef WITH_DECORATION + // If we're not in the correct window just save the cursor + // the next time the pointer enters the window the cursor will change +- if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow) ++ if (window->wl.decorations.focus != mainWindow) + return; ++#endif + + // Unlock possible pointer lock if no longer disabled. + if (window->cursorMode != GLFW_CURSOR_DISABLED && isPointerLocked(window)) + +From 2fad37473f20406159dde6e43c3c24fa241686d7 Mon Sep 17 00:00:00 2001 +From: Christian Rauch <Rauch.Christian@gmx.de> +Date: Mon, 10 Feb 2020 00:59:44 +0000 +Subject: [PATCH 8/8] wl: add decorations + +--- + src/wl_init.c | 64 +++++++++-- + src/wl_platform.h | 19 +++- + src/wl_window.c | 271 +++++++++++++++++++++++++++++++++------------- + 3 files changed, 265 insertions(+), 89 deletions(-) + +diff --git a/src/wl_init.c b/src/wl_init.c +index d49e44e77..b6cdb39dd 100644 +--- a/src/wl_init.c ++++ b/src/wl_init.c +@@ -44,11 +44,14 @@ + #include <wayland-client.h> + + ++const char *proxy_tag = "glfw-proxy"; ++ + static inline int min(int n1, int n2) + { + return n1 < n2 ? n1 : n2; + } + ++#ifndef WITH_DECORATION + static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, + int* which) + { +@@ -56,7 +59,6 @@ static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, + _GLFWwindow* window = _glfw.windowListHead; + if (!which) + which = &focus; +-#ifndef WITH_DECORATION + while (window) + { + if (surface == window->wl.decorations.top.surface) +@@ -81,9 +83,22 @@ static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, + } + window = window->next; + } +-#endif + return window; + } ++#endif ++ ++#ifdef WITH_DECORATION ++void decoration_error(struct libdecor *context, ++ enum libdecor_error error, ++ const char *message) ++{ ++ _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Caught error (%d): %s\n", error, message); ++} ++ ++static struct libdecor_interface decoration_interface = { ++ decoration_error, ++}; ++#endif + + static void pointerHandleEnter(void* data, + struct wl_pointer* pointer, +@@ -96,8 +111,16 @@ static void pointerHandleEnter(void* data, + if (!surface) + return; + +- int focus = 0; ++ if (wl_proxy_get_tag((struct wl_proxy *) surface) != &proxy_tag) ++ return; ++ + _GLFWwindow* window = wl_surface_get_user_data(surface); ++ ++#ifdef WITH_DECORATION ++ if (surface != window->wl.surface) ++ return; ++#else ++ int focus = 0; + if (!window) + { + window = findWindowFromDecorationSurface(surface, &focus); +@@ -105,7 +128,6 @@ static void pointerHandleEnter(void* data, + return; + } + +-#ifndef WITH_DECORATION + window->wl.decorations.focus = focus; + #endif + +@@ -196,10 +218,16 @@ static void pointerHandleMotion(void* data, + + if (window->cursorMode == GLFW_CURSOR_DISABLED) + return; ++ + x = wl_fixed_to_double(sx); + y = wl_fixed_to_double(sy); + +-#ifndef WITH_DECORATION ++#ifdef WITH_DECORATION ++ window->wl.cursorPosX = x; ++ window->wl.cursorPosY = y; ++ _glfwInputCursorPos(window, x, y); ++ _glfw.wl.cursorPreviousName = NULL; ++#else + switch (window->wl.decorations.focus) + { + case mainWindow: +@@ -251,11 +279,11 @@ static void pointerHandleButton(void* data, + { + _GLFWwindow* window = _glfw.wl.pointerFocus; + int glfwButton; +- uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; + + if (!window) + return; + #ifndef WITH_DECORATION ++ uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; + if (button == BTN_LEFT) + { + switch (window->wl.decorations.focus) +@@ -477,13 +505,21 @@ static void keyboardHandleEnter(void* data, + if (!surface) + return; + ++ if (wl_proxy_get_tag((struct wl_proxy *) surface) != &proxy_tag) ++ return; ++ + _GLFWwindow* window = wl_surface_get_user_data(surface); ++#ifdef WITH_DECORATION ++ if (surface != window->wl.surface) ++ return; ++#else + if (!window) + { + window = findWindowFromDecorationSurface(surface, NULL); + if (!window) + return; + } ++#endif + + _glfw.wl.serial = serial; + _glfw.wl.keyboardFocus = window; +@@ -778,6 +814,7 @@ static const struct wl_data_device_listener dataDeviceListener = { + dataDeviceHandleSelection, + }; + ++#ifndef WITH_DECORATION + static void wmBaseHandlePing(void* data, + struct xdg_wm_base* wmBase, + uint32_t serial) +@@ -788,6 +825,7 @@ static void wmBaseHandlePing(void* data, + static const struct xdg_wm_base_listener wmBaseListener = { + wmBaseHandlePing + }; ++#endif + + static void registryHandleGlobal(void* data, + struct wl_registry* registry, +@@ -836,6 +874,7 @@ static void registryHandleGlobal(void* data, + &wl_data_device_manager_interface, 1); + } + } ++#ifndef WITH_DECORATION + else if (strcmp(interface, "xdg_wm_base") == 0) + { + _glfw.wl.wmBase = +@@ -849,7 +888,6 @@ static void registryHandleGlobal(void* data, + &zxdg_decoration_manager_v1_interface, + 1); + } +-#ifndef WITH_DECORATION + else if (strcmp(interface, "wp_viewporter") == 0) + { + _glfw.wl.viewporter = +@@ -1163,12 +1201,14 @@ int _glfwPlatformInit(void) + if (_glfw.wl.seatVersion >= 4) + _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + ++#ifndef WITH_DECORATION + if (!_glfw.wl.wmBase) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to find xdg-shell in your compositor"); + return GLFW_FALSE; + } ++#endif + + if (_glfw.wl.pointer && _glfw.wl.shm) + { +@@ -1214,6 +1254,10 @@ int _glfwPlatformInit(void) + _glfw.wl.clipboardSize = 4096; + } + ++#ifdef WITH_DECORATION ++ _glfw.wl.csd_context = libdecor_new(_glfw.wl.display, &decoration_interface); ++#endif ++ + return GLFW_TRUE; + } + +@@ -1260,14 +1304,16 @@ void _glfwPlatformTerminate(void) + wl_compositor_destroy(_glfw.wl.compositor); + if (_glfw.wl.shm) + wl_shm_destroy(_glfw.wl.shm); +-#ifndef WITH_DECORATION ++#ifdef WITH_DECORATION ++ libdecor_unref(_glfw.wl.csd_context); ++#else + if (_glfw.wl.viewporter) + wp_viewporter_destroy(_glfw.wl.viewporter); +-#endif + if (_glfw.wl.decorationManager) + zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager); + if (_glfw.wl.wmBase) + xdg_wm_base_destroy(_glfw.wl.wmBase); ++#endif + if (_glfw.wl.dataSource) + wl_data_source_destroy(_glfw.wl.dataSource); + if (_glfw.wl.dataDevice) +diff --git a/src/wl_platform.h b/src/wl_platform.h +index 4591becbd..b6b3392e4 100644 +--- a/src/wl_platform.h ++++ b/src/wl_platform.h +@@ -54,14 +54,17 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR + #endif + #include "xkb_unicode.h" + ++#include "wayland-relative-pointer-unstable-v1-client-protocol.h" ++#include "wayland-pointer-constraints-unstable-v1-client-protocol.h" ++#include "wayland-idle-inhibit-unstable-v1-client-protocol.h" ++ ++#ifdef WITH_DECORATION ++#include <libdecor.h> ++#else + #include "wayland-xdg-shell-client-protocol.h" + #include "wayland-xdg-decoration-client-protocol.h" +-#ifndef WITH_DECORATION + #include "wayland-viewporter-client-protocol.h" + #endif +-#include "wayland-relative-pointer-unstable-v1-client-protocol.h" +-#include "wayland-pointer-constraints-unstable-v1-client-protocol.h" +-#include "wayland-idle-inhibit-unstable-v1-client-protocol.h" + + #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) + #define _glfw_dlclose(handle) dlclose(handle) +@@ -181,11 +184,13 @@ typedef struct _GLFWwindowWayland + struct wl_egl_window* native; + struct wl_callback* callback; + ++#ifndef WITH_DECORATION + struct { + struct xdg_surface* surface; + struct xdg_toplevel* toplevel; + struct zxdg_toplevel_decoration_v1* decoration; + } xdg; ++#endif + + _GLFWcursor* currentCursor; + double cursorPosX, cursorPosY; +@@ -216,7 +221,7 @@ typedef struct _GLFWwindowWayland + int focus; + } decorations; + #else +- GLFWbool ssd; ++ struct libdecor_frame *decoration_frame; + #endif + + } _GLFWwindowWayland; +@@ -237,9 +242,11 @@ typedef struct _GLFWlibraryWayland + struct wl_data_device* dataDevice; + struct wl_data_offer* dataOffer; + struct wl_data_source* dataSource; ++#ifdef WITH_DECORATION ++ struct libdecor *csd_context; ++#else + struct xdg_wm_base* wmBase; + struct zxdg_decoration_manager_v1* decorationManager; +-#ifndef WITH_DECORATION + struct wp_viewporter* viewporter; + #endif + struct zwp_relative_pointer_manager_v1* relativePointerManager; +diff --git a/src/wl_window.c b/src/wl_window.c +index 9e10e8a3f..47cc14377 100644 +--- a/src/wl_window.c ++++ b/src/wl_window.c +@@ -41,10 +41,12 @@ + #include <poll.h> + + #ifdef WITH_DECORATION +-#include <libdecoration.h> ++#include <libdecor.h> + #endif + + ++extern const char *proxy_tag; ++ + static int createTmpfileCloexec(char* tmpname) + { + int fd; +@@ -186,7 +188,61 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) + return buffer; + } + +-#ifndef WITH_DECORATION ++#ifdef WITH_DECORATION ++static void resizeWindow(_GLFWwindow* window); ++void frame_configure(struct libdecor_frame *frame, struct libdecor_configuration *configuration, void *user_data) ++{ ++ _GLFWwindow* window = user_data; ++ ++ int width, height; ++ if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) { ++ width = window->wl.width; ++ height = window->wl.height; ++ } ++ ++ window->wl.width = width; ++ window->wl.height = height; ++ resizeWindow(window); ++ ++ _glfwInputWindowSize(window, width, height); ++ _glfwPlatformSetWindowSize(window, width, height); ++ _glfwInputWindowDamage(window); ++ ++ struct libdecor_state *state = libdecor_state_new(width, height); ++ libdecor_frame_commit(frame, state, configuration); ++ libdecor_state_free(state); ++} ++ ++void frame_close(struct libdecor_frame *frame, void *user_data) ++{ ++ _glfwInputWindowCloseRequest(user_data); ++} ++ ++void frame_commit(struct libdecor_frame *frame, void *user_data) ++{ ++ _GLFWwindow* window = user_data; ++ ++ _glfwInputWindowDamage(window); ++} ++ ++static struct libdecor_frame_interface frame_interface = { ++ frame_configure, ++ frame_close, ++ frame_commit, ++}; ++#endif ++ ++#ifdef WITH_DECORATION ++static void createDecorations(_GLFWwindow* window) ++{ ++ // TODO: enable decoration ++} ++ ++static void destroyDecorations(_GLFWwindow* window) ++{ ++ // TODO: disable decoration ++} ++#else + static void createDecoration(_GLFWdecorationWayland* decoration, + struct wl_surface* parent, + struct wl_buffer* buffer, GLFWbool opaque, +@@ -216,14 +272,7 @@ static void createDecoration(_GLFWdecorationWayland* decoration, + else + wl_surface_commit(decoration->surface); + } +-#endif + +-#ifdef WITH_DECORATION +-static void createDecorations(_GLFWwindow* window) +-{ +- // +-} +-#else + static void createDecorations(_GLFWwindow* window) + { + unsigned char data[] = { 224, 224, 224, 255 }; +@@ -255,9 +304,7 @@ static void createDecorations(_GLFWwindow* window) + -_GLFW_DECORATION_WIDTH, window->wl.height, + window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH); + } +-#endif + +-#ifndef WITH_DECORATION + static void destroyDecoration(_GLFWdecorationWayland* decoration) + { + if (decoration->subsurface) +@@ -270,14 +317,7 @@ static void destroyDecoration(_GLFWdecorationWayland* decoration) + decoration->subsurface = NULL; + decoration->viewport = NULL; + } +-#endif + +-#ifdef WITH_DECORATION +-static void destroyDecorations(_GLFWwindow* window) +-{ +- // +-} +-#else + static void destroyDecorations(_GLFWwindow* window) + { + destroyDecoration(&window->wl.decorations.top); +@@ -287,23 +327,21 @@ static void destroyDecorations(_GLFWwindow* window) + } + #endif + ++#ifndef WITH_DECORATION + static void xdgDecorationHandleConfigure(void* data, + struct zxdg_toplevel_decoration_v1* decoration, + uint32_t mode) + { + _GLFWwindow* window = data; + +-#ifdef WITH_DECORATION +- if (!(window->wl.ssd = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE))) +-#else + if (!(window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE))) +-#endif + createDecorations(window); + } + + static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = { + xdgDecorationHandleConfigure, + }; ++#endif + + // Makes the surface considered as XRGB instead of ARGB. + static void setOpaqueRegion(_GLFWwindow* window) +@@ -392,6 +430,9 @@ static void surfaceHandleEnter(void *data, + struct wl_surface *surface, + struct wl_output *output) + { ++ if (wl_proxy_get_tag((struct wl_proxy *) output) != &proxy_tag) ++ return; ++ + _GLFWwindow* window = data; + _GLFWmonitor* monitor = wl_output_get_user_data(output); + +@@ -412,6 +453,9 @@ static void surfaceHandleLeave(void *data, + struct wl_surface *surface, + struct wl_output *output) + { ++ if (wl_proxy_get_tag((struct wl_proxy *) output) != &proxy_tag) ++ return; ++ + _GLFWwindow* window = data; + _GLFWmonitor* monitor = wl_output_get_user_data(output); + GLFWbool found; +@@ -452,8 +496,7 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable) + } + } + +-static GLFWbool createSurface(_GLFWwindow* window, +- const _GLFWwndconfig* wndconfig) ++static GLFWbool createSurface(_GLFWwindow* window) + { + window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor); + if (!window->wl.surface) +@@ -464,41 +507,60 @@ static GLFWbool createSurface(_GLFWwindow* window, + window); + + wl_surface_set_user_data(window->wl.surface, window); ++ wl_proxy_set_tag((struct wl_proxy *) window->wl.surface, &proxy_tag); ++ ++ wl_display_roundtrip(_glfw.wl.display); ++ wl_display_roundtrip(_glfw.wl.display); + + window->wl.native = wl_egl_window_create(window->wl.surface, +- wndconfig->width, +- wndconfig->height); ++ window->wl.width, ++ window->wl.height); + if (!window->wl.native) + return GLFW_FALSE; + +- window->wl.width = wndconfig->width; +- window->wl.height = wndconfig->height; +- window->wl.scale = 1; +- + if (!window->wl.transparent) + setOpaqueRegion(window); + + return GLFW_TRUE; + } + ++#ifdef WITH_DECORATION ++static GLFWbool createSurfaceDecoration(_GLFWwindow* window) ++{ ++ window->wl.decoration_frame = libdecor_decorate(_glfw.wl.csd_context, ++ window->wl.surface, ++ &frame_interface, ++ window); ++ libdecor_frame_map(window->wl.decoration_frame); ++ ++ window->wl.scale = 1; ++ ++ return GLFW_TRUE; ++} ++#endif ++ + static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, + int refreshRate) + { ++#ifdef WITH_DECORATION ++ libdecor_frame_set_fullscreen(window->wl.decoration_frame, monitor->wl.output); ++#else + if (window->wl.xdg.toplevel) + { + xdg_toplevel_set_fullscreen( + window->wl.xdg.toplevel, + monitor->wl.output); + } ++#endif + setIdleInhibitor(window, GLFW_TRUE); +-#ifdef WITH_DECORATION +- if (!window->wl.ssd) +-#else ++#ifndef WITH_DECORATION + if (!window->wl.decorations.serverSide) +-#endif + destroyDecorations(window); ++#endif + } + ++#ifndef WITH_DECORATION ++ + static void xdgToplevelHandleConfigure(void* data, + struct xdg_toplevel* toplevel, + int32_t width, +@@ -603,11 +665,7 @@ static void setXdgDecorations(_GLFWwindow* window) + } + else + { +-#ifdef WITH_DECORATION +- window->wl.ssd = GLFW_FALSE; +-#else + window->wl.decorations.serverSide = GLFW_FALSE; +-#endif + createDecorations(window); + } + } +@@ -672,6 +730,7 @@ static GLFWbool createXdgSurface(_GLFWwindow* window) + + return GLFW_TRUE; + } ++#endif + + static void setCursorImage(_GLFWwindow* window, + _GLFWcursorWayland* cursorWayland) +@@ -825,7 +884,17 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, + { + window->wl.transparent = fbconfig->transparent; + +- if (!createSurface(window, wndconfig)) ++ window->wl.visible = wndconfig->visible; ++ window->wl.width = wndconfig->width; ++ window->wl.height = wndconfig->height; ++ ++ // TODO: enable visibility support ++ window->wl.visible = GLFW_TRUE; ++ ++ // unsupported on Wayland by design ++ window->focusOnShow = GLFW_FALSE; ++ ++ if (!createSurface(window)) + return GLFW_FALSE; + + if (ctxconfig->client != GLFW_NO_API) +@@ -847,9 +916,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, + } + } + +- if (wndconfig->title) +- window->wl.title = _glfw_strdup(wndconfig->title); +- ++#ifndef WITH_DECORATION + if (wndconfig->visible) + { + if (!createXdgSurface(window)) +@@ -863,6 +930,16 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, + window->wl.xdg.toplevel = NULL; + window->wl.visible = GLFW_FALSE; + } ++#else ++ if (!createSurfaceDecoration(window)) ++ return GLFW_FALSE; ++#endif ++ ++ window->wl.scale = 1; ++ ++ _glfwPlatformSetWindowTitle(window, wndconfig->title); ++ ++ _glfwPlatformSetWindowResizable(window, wndconfig->resizable); + + if (window->monitor) + setFullscreen(window, window->monitor, window->videoMode.refreshRate); +@@ -873,6 +950,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, + window->wl.monitorsCount = 0; + window->wl.monitorsSize = 1; + ++ wl_display_roundtrip(_glfw.wl.display); ++ + return GLFW_TRUE; + } + +@@ -896,9 +975,11 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) + window->context.destroy(window); + + destroyDecorations(window); ++#ifdef WITH_DECORATION ++ libdecor_frame_unref(window->wl.decoration_frame); ++#else + if (window->wl.xdg.decoration) + zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration); +-#ifndef WITH_DECORATION + if (window->wl.decorations.buffer) + wl_buffer_destroy(window->wl.decorations.buffer); + #endif +@@ -906,11 +987,13 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) + if (window->wl.native) + wl_egl_window_destroy(window->wl.native); + ++#ifndef WITH_DECORATION + if (window->wl.xdg.toplevel) + xdg_toplevel_destroy(window->wl.xdg.toplevel); + + if (window->wl.xdg.surface) + xdg_surface_destroy(window->wl.xdg.surface); ++#endif + + if (window->wl.surface) + wl_surface_destroy(window->wl.surface); +@@ -924,8 +1007,15 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) + if (window->wl.title) + free(window->wl.title); + window->wl.title = _glfw_strdup(title); +- if (window->wl.xdg.toplevel) +- xdg_toplevel_set_title(window->wl.xdg.toplevel, title); ++ ++#ifdef WITH_DECORATION ++ if (window->wl.decoration_frame) { ++ libdecor_frame_set_title(window->wl.decoration_frame, window->wl.title); ++ libdecor_frame_set_app_id(window->wl.decoration_frame, window->wl.title); ++ } ++#else ++ xdg_toplevel_set_title(window->wl.xdg.toplevel, title); ++#endif + } + + void _glfwPlatformSetWindowIcon(_GLFWwindow* window, +@@ -971,16 +1061,23 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, + int minwidth, int minheight, + int maxwidth, int maxheight) + { ++ if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) ++ minwidth = minheight = 0; ++ if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE) ++ maxwidth = maxheight = 0; ++#ifdef WITH_DECORATION ++ libdecor_frame_set_min_content_size(window->wl.decoration_frame, ++ minwidth, minheight); ++ libdecor_frame_set_max_content_size(window->wl.decoration_frame, ++ maxwidth, maxheight); ++#else + if (window->wl.xdg.toplevel) + { +- if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) +- minwidth = minheight = 0; +- if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE) +- maxwidth = maxheight = 0; + xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight); + xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight); +- wl_surface_commit(window->wl.surface); + } ++#endif ++ wl_surface_commit(window->wl.surface); + } + + void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, +@@ -1032,31 +1129,37 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, + + void _glfwPlatformIconifyWindow(_GLFWwindow* window) + { +- if (window->wl.xdg.toplevel) +- xdg_toplevel_set_minimized(window->wl.xdg.toplevel); ++#ifdef WITH_DECORATION ++ libdecor_frame_set_minimized(window->wl.decoration_frame); ++#else ++ xdg_toplevel_set_minimized(window->wl.xdg.toplevel); ++#endif + } + + void _glfwPlatformRestoreWindow(_GLFWwindow* window) + { +- if (window->wl.xdg.toplevel) +- { +- if (window->monitor) +- xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); +- if (window->wl.maximized) +- xdg_toplevel_unset_maximized(window->wl.xdg.toplevel); +- // There is no way to unset minimized, or even to know if we are +- // minimized, so there is nothing to do in this case. +- } ++#ifdef WITH_DECORATION ++ libdecor_frame_unset_fullscreen(window->wl.decoration_frame); ++ libdecor_frame_unset_maximized(window->wl.decoration_frame); ++#else ++ if (window->monitor) ++ xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); ++ if (window->wl.maximized) ++ xdg_toplevel_unset_maximized(window->wl.xdg.toplevel); ++ // There is no way to unset minimized, or even to know if we are ++ // minimized, so there is nothing to do in this case. ++#endif + _glfwInputWindowMonitor(window, NULL); + window->wl.maximized = GLFW_FALSE; + } + + void _glfwPlatformMaximizeWindow(_GLFWwindow* window) + { +- if (window->wl.xdg.toplevel) +- { +- xdg_toplevel_set_maximized(window->wl.xdg.toplevel); +- } ++#ifdef WITH_DECORATION ++ libdecor_frame_set_maximized(window->wl.decoration_frame); ++#else ++ xdg_toplevel_set_maximized(window->wl.xdg.toplevel); ++#endif + window->wl.maximized = GLFW_TRUE; + } + +@@ -1064,13 +1167,18 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) + { + if (!window->wl.visible) + { +- createXdgSurface(window); + window->wl.visible = GLFW_TRUE; ++#ifndef WITH_DECORATION ++ createXdgSurface(window); ++#else ++ // TODO: enable visibility support ++#endif + } + } + + void _glfwPlatformHideWindow(_GLFWwindow* window) + { ++#ifndef WITH_DECORATION + if (window->wl.xdg.toplevel) + { + xdg_toplevel_destroy(window->wl.xdg.toplevel); +@@ -1078,6 +1186,9 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) + window->wl.xdg.toplevel = NULL; + window->wl.xdg.surface = NULL; + } ++#else ++ // TODO: enable visibility support ++#endif + window->wl.visible = GLFW_FALSE; + } + +@@ -1106,11 +1217,14 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, + } + else + { +- if (window->wl.xdg.toplevel) +- xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); ++#ifdef WITH_DECORATION ++ libdecor_frame_unset_fullscreen(window->wl.decoration_frame); ++#else ++ xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); + setIdleInhibitor(window, GLFW_FALSE); + if (!_glfw.wl.decorationManager) + createDecorations(window); ++#endif + } + _glfwInputWindowMonitor(window, monitor); + } +@@ -1149,9 +1263,14 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) + + void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) + { +- // TODO +- _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, +- "Wayland: Window attribute setting not implemented yet"); ++#ifdef WITH_DECORATION ++ if (enabled) ++ libdecor_frame_set_capabilities(window->wl.decoration_frame, ++ LIBDECOR_ACTION_RESIZE); ++ else ++ libdecor_frame_unset_capabilities(window->wl.decoration_frame, ++ LIBDECOR_ACTION_RESIZE); ++#endif + } + + void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) +@@ -1167,9 +1286,13 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) + + void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) + { +- // TODO +- _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, +- "Wayland: Window attribute setting not implemented yet"); ++#ifdef WITH_DECORATION ++ if (window->wl.maximized) ++ libdecor_frame_unset_maximized(window->wl.decoration_frame); ++ ++ if (window->wl.wasFullscreen) ++ libdecor_frame_unset_fullscreen(window->wl.decoration_frame); ++#endif + } + + void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) diff --git a/0002-set-O_NONBLOCK-on-repeat-timerfd.patch b/0002-set-O_NONBLOCK-on-repeat-timerfd.patch new file mode 100644 index 000000000000..e21cf69be0e3 --- /dev/null +++ b/0002-set-O_NONBLOCK-on-repeat-timerfd.patch @@ -0,0 +1,33 @@ +From 963e728881d7551aab0b843c79915f2419d4d36e Mon Sep 17 00:00:00 2001 +From: Stone Tickle <lattis@mochiro.moe> +Date: Fri, 5 Jun 2020 12:51:25 +0900 +Subject: [PATCH] Wayland: Set O_NONBLOCK on repeat timerfd + +Fixes #1710 +Fixes #1711 +--- + src/wl_init.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/wl_init.c b/src/wl_init.c +index acfe477d4..bba908fa9 100644 +--- a/src/wl_init.c ++++ b/src/wl_init.c +@@ -1336,7 +1336,7 @@ int _glfwInitWayland(void) + + _glfw.wl.timerfd = -1; + if (_glfw.wl.seatVersion >= 4) +- _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); ++ _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + + if (!_glfw.wl.wmBase) + { +@@ -1370,7 +1370,7 @@ int _glfwInitWayland(void) + wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm); + _glfw.wl.cursorSurface = + wl_compositor_create_surface(_glfw.wl.compositor); +- _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); ++ _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + } + + if (_glfw.wl.seat && _glfw.wl.dataDeviceManager) diff --git a/0003-Continue-poll-if-timerfd-cant-be-read.patch b/0003-Continue-poll-if-timerfd-cant-be-read.patch new file mode 100644 index 000000000000..5eb7513fa298 --- /dev/null +++ b/0003-Continue-poll-if-timerfd-cant-be-read.patch @@ -0,0 +1,46 @@ +From 68879081cb39f50bd65d12e0f1869f5970dc71b9 Mon Sep 17 00:00:00 2001 +From: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> +Date: Tue, 14 Dec 2021 09:29:01 +0100 +Subject: [PATCH] =?UTF-8?q?Wayland:=20Continue=20poll()=20if=20timerfd=20c?= + =?UTF-8?q?an=E2=80=99t=20be=20read?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In the case the key repeat timerfd was interrupted before read(), the +cursor timerfd wasn’t read at all even when it could. + +Related to #1711 +--- + src/wl_window.c | 11 +++-------- + 2 files changed, 4 insertions(+), 8 deletions(-) + +diff --git a/src/wl_window.c b/src/wl_window.c +index b4c59d693..8ed803b4b 100644 +--- a/src/wl_window.c ++++ b/src/wl_window.c +@@ -751,10 +751,7 @@ static void handleEvents(int timeout) + if (fds[1].revents & POLLIN) + { + read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats)); +- if (read_ret != 8) +- return; +- +- if (_glfw.wl.keyboardFocus) ++ if (read_ret == 8 && _glfw.wl.keyboardFocus) + { + for (uint64_t i = 0; i < repeats; ++i) + { +@@ -770,10 +767,8 @@ static void handleEvents(int timeout) + if (fds[2].revents & POLLIN) + { + read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)); +- if (read_ret != 8) +- return; +- +- incrementCursorImage(_glfw.wl.pointerFocus); ++ if (read_ret == 8) ++ incrementCursorImage(_glfw.wl.pointerFocus); + } + } + else diff --git a/0003-wayland-don-t-crash-app-on-api-calls-to-window-focus.patch b/0003-wayland-don-t-crash-app-on-api-calls-to-window-focus.patch new file mode 100644 index 000000000000..15e312aa6007 --- /dev/null +++ b/0003-wayland-don-t-crash-app-on-api-calls-to-window-focus.patch @@ -0,0 +1,39 @@ +From 8400d399b74f55bf128488f7ea73609babbf4eaf Mon Sep 17 00:00:00 2001 +From: ninja- <ninja-@users.noreply.github.com> +Date: Tue, 30 Jun 2020 19:41:48 +0200 +Subject: [PATCH 3/4] wayland: don't crash app on api calls to window focus or + window icon - just ignore them + +--- + src/wl_window.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/wl_window.c b/src/wl_window.c +index 47cc1437..f3bda65b 100644 +--- a/src/wl_window.c ++++ b/src/wl_window.c +@@ -1021,8 +1021,8 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) + void _glfwPlatformSetWindowIcon(_GLFWwindow* window, + int count, const GLFWimage* images) + { +- _glfwInputError(GLFW_FEATURE_UNAVAILABLE, +- "Wayland: The platform does not support setting the window icon"); ++ // _glfwInputError(GLFW_FEATURE_UNAVAILABLE, ++ // "Wayland: The platform does not support setting the window icon"); + } + + void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +@@ -1201,8 +1201,8 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) + + void _glfwPlatformFocusWindow(_GLFWwindow* window) + { +- _glfwInputError(GLFW_FEATURE_UNAVAILABLE, +- "Wayland: The platform does not support setting the input focus"); ++ // _glfwInputError(GLFW_FEATURE_UNAVAILABLE, ++ // "Wayland: The platform does not support setting the input focus"); + } + + void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, +-- +2.32.0 + diff --git a/0004-fix-broken-opengl-screenshots-on-mutter.patch b/0004-fix-broken-opengl-screenshots-on-mutter.patch new file mode 100644 index 000000000000..c850f99cb381 --- /dev/null +++ b/0004-fix-broken-opengl-screenshots-on-mutter.patch @@ -0,0 +1,33 @@ +From 4d47891ca1f3979c20f0acc3539a80d8fa97a2ad Mon Sep 17 00:00:00 2001 +From: ninja- <ninja-@users.noreply.github.com> +Date: Tue, 30 Jun 2020 19:41:52 +0200 +Subject: [PATCH 4/4] fix broken opengl screenshots on mutter + +(admicos) This breaks more than just screenshots. On sway, the window is +rendered half transparent. And we do not want that. +--- + src/egl_context.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/egl_context.c b/src/egl_context.c +index 975c67be..b5cbeaff 100644 +--- a/src/egl_context.c ++++ b/src/egl_context.c +@@ -175,6 +175,14 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, + u->samples = getEGLConfigAttrib(n, EGL_SAMPLES); + u->doublebuffer = desired->doublebuffer; + ++#if defined(_GLFW_WAYLAND) ++ // Avoid using transparent buffer on Wayland if transparency is not requested. ++ // Otherwise mutter will fail to properly screenshot OpenGL content. ++ if (u->alphaBits > 0 && !desired->transparent) { ++ continue; ++ } ++#endif // _GLFW_WAYLAND ++ + u->handle = (uintptr_t) n; + usableCount++; + } +-- +2.32.0 + diff --git a/0005-don-t-crash-on-get-scancode-name.patch b/0005-don-t-crash-on-get-scancode-name.patch new file mode 100644 index 000000000000..9a4c7200902d --- /dev/null +++ b/0005-don-t-crash-on-get-scancode-name.patch @@ -0,0 +1,10 @@ +--- a/src/wl_window.c ++++ b/src/wl_window.c +@@ -1378,8 +1378,6 @@ + const char* _glfwPlatformGetScancodeName(int scancode) + { + // TODO +- _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, +- "Wayland: Key names not yet implemented"); + return NULL; + } diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..ffaffbe23db4 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,66 @@ +# Maintainer: EncryptedCicada <me@varnit.com> +# Maintainer: Ecmel Berk Canlıer <me@ecmelberk.com> +# Contributor: Sven-Hendrik Haase <svenstaro@gmail.com> +# Contributor: philefou <tuxication AT gmail DOT com> +# Contributor: lindquist <tomas@famolsen.dk> +# Contributor: Christoph Siegenthaler <csi@gmx.ch> +# Contributor: Mihai Militaru <mihai.militaru@ephemeros.org> +# Contributor: SpepS <dreamspepser at yahoo dot it> + +pkgname=glfw-wayland-minecraft-libdecoration +pkgdesc="A free, open source, portable framework for graphical application development (wayland, patched for Minecraft and Gnome)" +pkgver=3.4.0 +_pkggit=87d5646f5d2bad0562744501633bf8105f59c193 +pkgrel=1 +arch=('x86_64') +url="https://github.com/EncryptedCicada/minecraft-wayland" +license=('custom:ZLIB') +depends=('wayland' 'libxkbcommon' 'libgl' 'libdecor') +conflicts=('glfw' 'glfw-wayland') +provides=("glfw=$pkgver") +makedepends=('mesa' 'cmake' 'doxygen' 'vulkan-headers' 'vulkan-icd-loader' + 'extra-cmake-modules' 'wayland-protocols' 'libxi' 'libxrandr' + 'libxcursor' 'libxkbcommon' 'libxinerama') +source=("https://github.com/glfw/glfw/archive/${_pkggit}.tar.gz" + "0001-libdecoration-support.patch" + "0002-set-O_NONBLOCK-on-repeat-timerfd.patch" + "0003-wayland-don-t-crash-app-on-api-calls-to-window-focus.patch" + "0004-fix-broken-opengl-screenshots-on-mutter.patch" + "0005-don-t-crash-on-get-scancode-name.patch") +sha256sums=('7b8c990cfb039110d38c7f5bb21948c402933be3f93f333fe7dcda3deaf72aa4' + 'c163b4a0a6496d758bc656203c23151015683754a6b5c2fc4944df7296d6b5af' + '5cd74a83dc7824c7696c1534f880b7a4a0992bb6dba6e4531ad1c040541f1d30' + 'a442f8c7e40fb09775f922b95402108b366114874ee96e370c29e5f8500a02b7' + '27aea70b07df2d46ac7469c129d28d695eff1ec9492489aa7b2558dd780ebdf0' + '16a2410511d75f00902ab1869942a80d85261f8390a97be946f82662891351e5') + +prepare() { + cd "$srcdir/glfw-$_pkggit" + rm -rf build-wayland || true + mkdir build-wayland + + for patch in "$srcdir/00"*.patch; do + echo "Applying patch $patch" + patch -p1 < "$patch" + done +} + +build() { + cd "$srcdir/glfw-$_pkggit/build-wayland" + + cmake .. \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DBUILD_SHARED_LIBS=ON \ + -DGLFW_USE_WAYLAND=ON \ + -DGLFW_USE_LIBDECOR=ON +} + +package() { + cd "$srcdir/glfw-$_pkggit"/build-wayland + + make DESTDIR=$pkgdir install + + cd .. + install -Dm644 LICENSE.md "$pkgdir/usr/share/licenses/$pkgname/LICENSE.md" +} diff --git a/README.md b/README.md new file mode 100644 index 000000000000..2f94d279d959 --- /dev/null +++ b/README.md @@ -0,0 +1,104 @@ +<B> This repository is for hosting the Gnome specific changes of the parent repository and to host the package on AUR. Please submit any issues or PRs on the parent repository </B> + +# The better way of running Minecraft Without XWayland + +Because I **REALLY** had nothing better to do with my life. + +## Requirements + +- A version of Minecraft >= 1.13 + + - Older versions are not guaranteed to work. You can still try, though. + +- The MultiMC Minecraft Launcher + + - Use it even if you don't plan to do this. It's great! + - If you don't want to do that, throw this into your Java arguments, changing + the file path as needed: `-Dorg.lwjgl.glfw.libname=/usr/lib/libglfw.so` + +- A distro with a patched GLFW package + + - This guide has steps for Arch, Fedora, and Gentoo + - Or the knowledge on how to patch packages in your distribution. + - In which case you can skip step 2 of this guide, as it will not apply to you + and you should know what to do with the `.patch` files in this repo already + +## Side effects + +- Forge will not work without another workaround +- The controls page (and anywhere a keyboard key is shown) is a bit wonky + - Keys you replace through your compositor (example: `caps:swapescape`) will + require you to use the original key +- Originally made for Sway, GNOME needs to manually makepkg the `libdecoration` + branch for GNOME specific fixes (until a new GLFW version releases. See steps for Gnome on Arch below.) + - I haven't received any bug reports from KDE, so it'll (probably) work + +## Step 1: Setting up MultiMC to use the system GLFW + +Go to `Settings` > `Minecraft`, and enable `Use system installation of GLFW`. + +If you have a Wayland-compatible version of GLFW installed (`glfw-wayland` on +Arch) you can try launching the game. It will most likely error out with +something about window focus not being supported. In that case, you are in the +right direction. + +## Step 2: Installing the patched GLFW library + +If you're not under an Arch-based system, you're mostly on your own here. You +can try waiting for someone else to write a guide I guess. + +### Option 1: Use the AUR + +Install the `glfw-wayland-minecraft-libdecoration` package from the AUR. + +### Option 2: Build the PKGBUILD manually + +`git clone` this repository to somewhere, and run `makepkg -si` inside. It will +ask you to replace your existing GLFW package if already installed. + +### Option 3: Install the Fedora package + +Install the Fedora package from https://copr.fedorainfracloud.org/coprs/lyessaadi/minecraft-wayland-glfw/. +See https://github.com/Admicos/minecraft-wayland/issues/4 for more information. + +### Option 4: Patch the Gentoo package + +Patch Gentoo's GLFW package by following the guide at https://github.com/Admicos/minecraft-wayland/issues/6 + +## Step 3: There is no step 3 + +This should be it. Try launching Minecraft now and see if it works. + +## Bonus: XWayland per instance + +If some version of Minecraft doesn't work with the patch enabled, you can +disable it through MultiMC just for that version by + +- Right clicking on your instance +- Clicking `Edit instance` +- Going to `Settings` > `Workarounds` +- Enabling `Native Libraries` override switch +- Disabling the GLFW option + +You can also disable the global switch and enable the patch per instance if +that's how you want to roll. + +## Bonus: Making Forge work + +Due to "Forge being Forge", you will need to add +`-Dfml.earlyprogresswindow=false` to your Java arguments to make Forge instances +start up properly. See [issue #1](https://github.com/Admicos/minecraft-wayland/issues/1) +for more information. + +## Thanks To + +I really didn't do much on this other than "re-discovering" these things which +aren't even that old. Here are the proper credits: + +- `ninja-` on GitHub + + - For https://github.com/glfw/glfw/pull/1725 + +- `annacrombie` on GitHub + + - For https://github.com/glfw/glfw/pull/1711 |