wayland: Add basic input support
diff --git a/src/wl_init.c b/src/wl_init.c
index a0dcacc..d2865da 100644
--- a/src/wl_init.c
+++ b/src/wl_init.c
@@ -26,6 +26,7 @@
#include "internal.h"
+#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -59,6 +60,200 @@
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 @@
{
_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 3326273..bc706d9 100644
--- a/src/wl_platform.h
+++ b/src/wl_platform.h
@@ -68,11 +68,16 @@
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 a7bef77..d3373cb 100644
--- a/src/wl_window.c
+++ b/src/wl_window.c
@@ -65,6 +65,8 @@
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);