diff --git a/src/wl_init.c b/src/wl_init.c index a0dcaccf..d2865dae 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -26,6 +26,7 @@ #include "internal.h" +#include #include #include #include @@ -59,6 +60,200 @@ static const struct wl_shell_surface_listener shellSurfaceListener = { handlePopupDone }; +static void pointerHandleEnter(void* data, + struct wl_pointer* pointer, + uint32_t serial, + struct wl_surface* surface, + wl_fixed_t sx, + wl_fixed_t sy) +{ + _GLFWwindow* window = wl_surface_get_user_data(surface); + + _glfw.wl.pointerFocus = window; + _glfwInputCursorEnter(window, GL_TRUE); +} + +static void pointerHandleLeave(void* data, + struct wl_pointer* pointer, + uint32_t serial, + struct wl_surface* surface) +{ + _GLFWwindow* window = wl_surface_get_user_data(surface); + + _glfw.wl.pointerFocus = NULL; + _glfwInputCursorEnter(window, GL_FALSE); +} + +static void pointerHandleMotion(void* data, + struct wl_pointer* pointer, + uint32_t time, + wl_fixed_t sx, + wl_fixed_t sy) +{ + _GLFWwindow* window = _glfw.wl.pointerFocus; + + if (window->cursorMode == GLFW_CURSOR_DISABLED) + { + /* TODO */ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: GLFW_CURSOR_DISABLED not supported"); + return; + } + + _glfwInputCursorMotion(window, + wl_fixed_to_double(sx), + wl_fixed_to_double(sy)); +} + +static void pointerHandleButton(void* data, + struct wl_pointer* wl_pointer, + uint32_t serial, + uint32_t time, + uint32_t button, + uint32_t state) +{ + _GLFWwindow* window = _glfw.wl.pointerFocus; + int glfwButton; + + /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev + * codes. */ + glfwButton = button - BTN_LEFT; + + /* TODO: modifiers */ + _glfwInputMouseClick(window, + glfwButton, + state == WL_POINTER_BUTTON_STATE_PRESSED + ? GLFW_PRESS + : GLFW_RELEASE, + 0); +} + +static void pointerHandleAxis(void* data, + struct wl_pointer* wl_pointer, + uint32_t time, + uint32_t axis, + wl_fixed_t value) +{ + _GLFWwindow* window = _glfw.wl.pointerFocus; + double scroll_factor; + double x, y; + + /* Wayland scroll events are in pointer motion coordinate space (think + * two finger scroll). The factor 10 is commonly used to convert to + * "scroll step means 1.0. */ + scroll_factor = 1.0/10.0; + + switch (axis) + { + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: + x = wl_fixed_to_double(value) * scroll_factor; + y = 0.0; + break; + case WL_POINTER_AXIS_VERTICAL_SCROLL: + x = 0.0; + y = wl_fixed_to_double(value) * scroll_factor; + break; + default: + break; + } + + _glfwInputScroll(window, x, y); +} + +static const struct wl_pointer_listener pointerListener = { + pointerHandleEnter, + pointerHandleLeave, + pointerHandleMotion, + pointerHandleButton, + pointerHandleAxis, +}; + +static void keyboardHandleKeymap(void* data, + struct wl_keyboard* keyboard, + uint32_t format, + int fd, + uint32_t size) +{ + /* TODO */ +} + +static void keyboardHandleEnter(void* data, + struct wl_keyboard* keyboard, + uint32_t serial, + struct wl_surface* surface, + struct wl_array* keys) +{ + _glfwInputWindowFocus(wl_surface_get_user_data(surface), GL_TRUE); +} + +static void keyboardHandleLeave(void* data, + struct wl_keyboard* keyboard, + uint32_t serial, + struct wl_surface* surface) +{ + _glfwInputWindowFocus(wl_surface_get_user_data(surface), GL_FALSE); +} + +static void keyboardHandleKey(void* data, + struct wl_keyboard* keyboard, + uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state) +{ + /* TODO */ +} + +static void keyboardHandleModifiers(void* data, + struct wl_keyboard* keyboard, + uint32_t serial, + uint32_t modsDepressed, + uint32_t modsLatched, + uint32_t modsLocked, + uint32_t group) +{ + /* TODO */ +} + +static const struct wl_keyboard_listener keyboardListener = { + keyboardHandleKeymap, + keyboardHandleEnter, + keyboardHandleLeave, + keyboardHandleKey, + keyboardHandleModifiers, +}; + +static void seatHandleCapabilities(void* data, + struct wl_seat* seat, + enum wl_seat_capability caps) +{ + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer) + { + _glfw.wl.pointer = wl_seat_get_pointer(seat); + wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL); + } + else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer) + { + wl_pointer_destroy(_glfw.wl.pointer); + _glfw.wl.pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard) + { + _glfw.wl.keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL); + } + else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard) + { + wl_keyboard_destroy(_glfw.wl.keyboard); + _glfw.wl.keyboard = NULL; + } +} + +static const struct wl_seat_listener seatListener = { + seatHandleCapabilities +}; + static void registryHandleGlobal(void* data, struct wl_registry* registry, uint32_t name, @@ -79,6 +274,15 @@ static void registryHandleGlobal(void* data, { _glfwAddOutput(name, version); } + else if (strcmp(interface, "wl_seat") == 0) + { + if (!_glfw.wl.seat) + { + _glfw.wl.seat = + wl_registry_bind(registry, name, &wl_seat_interface, 1); + wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL); + } + } } static void registryHandleGlobalRemove(void *data, diff --git a/src/wl_platform.h b/src/wl_platform.h index 33262733..bc706d90 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -68,11 +68,16 @@ typedef struct _GLFWlibraryWayland struct wl_registry* registry; struct wl_compositor* compositor; struct wl_shell* shell; + struct wl_seat* seat; + struct wl_pointer* pointer; + struct wl_keyboard* keyboard; _GLFWmonitor** monitors; int monitorsCount; int monitorsSize; + _GLFWwindow* pointerFocus; + _GLFWwindow* keyboardFocus; } _GLFWlibraryWayland; typedef struct _GLFWmonitorWayland diff --git a/src/wl_window.c b/src/wl_window.c index a7bef77c..d3373cb5 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -65,6 +65,8 @@ static GLboolean createSurface(_GLFWwindow* window, if (!window->wl.surface) return GL_FALSE; + wl_surface_set_user_data(window->wl.surface, window); + window->wl.native = wl_egl_window_create(window->wl.surface, wndconfig->width, wndconfig->height);