From 7a40eb6de646ffd50aa7b5b60f3c05273c0a6951 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 18 Nov 2015 19:38:42 -0500 Subject: [PATCH] Support cursors over wayland clients Apparently wayland has fucking client-side cursors, too --- CMake/FindWayland.cmake | 11 ++++++++--- include/client/client.h | 8 ++++++++ swaybg/CMakeLists.txt | 2 +- wayland/client.c | 43 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/CMake/FindWayland.cmake b/CMake/FindWayland.cmake index 00c17a3c..69130fe0 100644 --- a/CMake/FindWayland.cmake +++ b/CMake/FindWayland.cmake @@ -12,6 +12,7 @@ # WAYLAND_CLIENT_FOUND WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES # WAYLAND_SERVER_FOUND WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES # WAYLAND_EGL_FOUND WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES +# WAYLAND_CURSOR_FOUND WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES # # Copyright (c) 2013 Martin Gräßlin # @@ -27,21 +28,23 @@ IF (NOT WIN32) # Use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls FIND_PACKAGE(PkgConfig) - PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl) + PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor) SET(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS}) FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) + FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) + FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) - set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR}) + set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR} ${WAYLAND_CURSOR_INCLUDE_DIR}) - set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES}) + set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES}) list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR) @@ -50,6 +53,7 @@ IF (NOT WIN32) FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR) FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR) FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR) FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR) MARK_AS_ADVANCED( @@ -57,6 +61,7 @@ IF (NOT WIN32) WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES + WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES ) ENDIF () diff --git a/include/client/client.h b/include/client/client.h index 5b24d315..b823235b 100644 --- a/include/client/client.h +++ b/include/client/client.h @@ -22,6 +22,13 @@ struct buffer { bool busy; }; +struct cursor { + struct wl_surface *surface; + struct wl_cursor_theme *cursor_theme; + struct wl_cursor *cursor; + struct wl_poitner *pointer; +}; + struct client_state { struct wl_compositor *compositor; struct wl_display *display; @@ -34,6 +41,7 @@ struct client_state { struct wl_surface *surface; struct wl_shell_surface *shell_surface; struct wl_callback *frame_cb; + struct cursor cursor; uint32_t width, height; cairo_t *cairo; list_t *outputs; diff --git a/swaybg/CMakeLists.txt b/swaybg/CMakeLists.txt index 5cf4ff05..7f0556df 100644 --- a/swaybg/CMakeLists.txt +++ b/swaybg/CMakeLists.txt @@ -26,7 +26,7 @@ add_executable(swaybg ${proto-xdg-shell} ) -TARGET_LINK_LIBRARIES(swaybg ${WAYLAND_CLIENT_LIBRARIES} ${CAIRO_LIBRARIES} ${PANGO_LIBRARIES} m) +TARGET_LINK_LIBRARIES(swaybg ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES} ${CAIRO_LIBRARIES} ${PANGO_LIBRARIES} m) install( TARGETS swaybg diff --git a/wayland/client.c b/wayland/client.c index 190d5ecb..be93709b 100644 --- a/wayland/client.c +++ b/wayland/client.c @@ -1,4 +1,5 @@ #include +#include #include "wayland-xdg-shell-client-protocol.h" #include #include @@ -44,6 +45,37 @@ static const struct wl_output_listener output_listener = { .scale = display_handle_scale }; +static void pointer_handle_enter(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) { + struct client_state *state = data; + struct wl_cursor_image *image = state->cursor.cursor->images[0]; + wl_pointer_set_cursor(pointer, serial, state->cursor.surface, image->hotspot_x, image->hotspot_y); +} + +static void pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) { +} + +static void pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) { +} + +static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state_w) { +} + +static void pointer_handle_axis(void *data, struct wl_pointer *pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) { +} + +static const struct wl_pointer_listener pointer_listener = { + .enter = pointer_handle_enter, + .leave = pointer_handle_leave, + .motion = pointer_handle_motion, + .button = pointer_handle_button, + .axis = pointer_handle_axis +}; + static void registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct client_state *state = data; @@ -57,6 +89,7 @@ static void registry_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, wl_seat_interface.name) == 0) { state->seat = wl_registry_bind(registry, name, &wl_seat_interface, version); state->pointer = wl_seat_get_pointer(state->seat); + wl_pointer_add_listener(state->pointer, &pointer_listener, state); } else if (strcmp(interface, wl_output_interface.name) == 0) { struct wl_output *output = wl_registry_bind(registry, name, &wl_output_interface, version); struct output_state *ostate = malloc(sizeof(struct output_state)); @@ -111,6 +144,16 @@ struct client_state *client_setup(uint32_t width, uint32_t height) { wl_shell_surface_add_listener(state->shell_surface, &surface_listener, state); wl_shell_surface_set_toplevel(state->shell_surface); + state->cursor.cursor_theme = wl_cursor_theme_load("default", 32, state->shm); // TODO: let you customize this + state->cursor.cursor = wl_cursor_theme_get_cursor(state->cursor.cursor_theme, "left_ptr"); + state->cursor.surface = wl_compositor_create_surface(state->compositor); + + struct wl_cursor_image *image = state->cursor.cursor->images[0]; + struct wl_buffer *cursor_buf = wl_cursor_image_get_buffer(image); + wl_surface_attach(state->cursor.surface, cursor_buf, 0, 0); + wl_surface_damage(state->cursor.surface, 0, 0, image->width, image->height); + wl_surface_commit(state->cursor.surface); + return state; }