Browse Source

wayland: Add basic input support

Jonas Ådahl 11 năm trước cách đây
mục cha
commit
a75cf5a163
3 tập tin đã thay đổi với 211 bổ sung0 xóa
  1. 204 0
      src/wl_init.c
  2. 5 0
      src/wl_platform.h
  3. 2 0
      src/wl_window.c

+ 204 - 0
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 @@ 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,

+ 5 - 0
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

+ 2 - 0
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);