diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | input.c | 68 | ||||
-rw-r--r-- | input.h | 4 | ||||
-rw-r--r-- | main.c | 24 | ||||
-rw-r--r-- | makefile | 1 | ||||
-rw-r--r-- | window.c | 73 | ||||
-rw-r--r-- | window.h | 3 |
7 files changed, 165 insertions, 9 deletions
@@ -4,4 +4,5 @@ compile_commands.json compile_flags.txt linux-dmabuf-unstable-v1.h receiver +relative-pointer-unstable-v1.h xdg-shell.h @@ -18,6 +18,7 @@ #include "input.h" #include <errno.h> +#include <linux/input-event-codes.h> #include <linux/uhid.h> #include <stddef.h> #include <stdint.h> @@ -87,6 +88,7 @@ static const struct uhid_event uhid_event_create2 = { struct InputStream { int fd; + unsigned button_state; uint64_t key_state[4]; }; @@ -172,7 +174,7 @@ bool InputStreamKeyPress(struct InputStream* input_stream, unsigned evdev_code, uint64_t key_state_shift = evdev_code & 0x3f; uint64_t key_state = (input_stream->key_state[key_state_row] & ~(1ull << key_state_shift)) | - ((uint64_t)(!!pressed) << key_state_shift); + (((uint64_t) !!pressed) << key_state_shift); if (key_state == input_stream->key_state[key_state_row]) return true; input_stream->key_state[key_state_row] = key_state; @@ -183,6 +185,70 @@ bool InputStreamKeyPress(struct InputStream* input_stream, unsigned evdev_code, return result; } +static size_t InputStreamFormatMouse(const struct InputStream* input_stream, + struct uhid_event* uhid_event, int dx, + int dy, int wheel) { + uhid_event->type = UHID_INPUT2; + uhid_event->u.input2.data[0] = 2; + uhid_event->u.input2.data[1] = input_stream->button_state & 0xff; + uhid_event->u.input2.data[2] = dx & 0xff; + uhid_event->u.input2.data[3] = dx >> 8 & 0xff; + uhid_event->u.input2.data[4] = dy & 0xff; + uhid_event->u.input2.data[5] = dy >> 8 & 0xff; + uhid_event->u.input2.data[6] = wheel & 0xff; + uhid_event->u.input2.size = 7; + return offsetof(struct uhid_event, u.input2.data) + uhid_event->u.input2.size; +} + +bool InputStreamMouseMove(struct InputStream* input_stream, int dx, int dy) { + struct uhid_event uhid_event_input2; + size_t size = + InputStreamFormatMouse(input_stream, &uhid_event_input2, dx, dy, 0); + bool result = Drain(input_stream->fd, &uhid_event_input2, size); + if (!result) LOG("Failed to drain mousemove"); + return result; +} + +bool InputStreamMouseButton(struct InputStream* input_stream, unsigned button, + bool pressed) { + unsigned button_shift; + switch (button) { + case BTN_LEFT: + button_shift = 0; + break; + case BTN_RIGHT: + button_shift = 1; + break; + case BTN_MIDDLE: + button_shift = 2; + break; + default: + // mburakov: Ignore unknown buttons... + return true; + } + + unsigned button_state = (input_stream->button_state & ~(1u << button_shift)) | + (((unsigned)!!pressed) << button_shift); + if (button_state == input_stream->button_state) return true; + input_stream->button_state = button_state; + + struct uhid_event uhid_event_input2; + size_t size = + InputStreamFormatMouse(input_stream, &uhid_event_input2, 0, 0, 0); + bool result = Drain(input_stream->fd, &uhid_event_input2, size); + if (!result) LOG("Failed to drain mousebutton"); + return result; +} + +bool InputStreamMouseWheel(struct InputStream* input_stream, int delta) { + struct uhid_event uhid_event_input2; + size_t size = + InputStreamFormatMouse(input_stream, &uhid_event_input2, 0, 0, delta); + bool result = Drain(input_stream->fd, &uhid_event_input2, size); + if (!result) LOG("Failed to drain mousewheel"); + return result; +} + bool InputStreamHandsoff(struct InputStream* input_stream) { memset(input_stream->key_state, 0, sizeof(input_stream->key_state)); static const struct uhid_event uhid_event_input2 = { @@ -25,6 +25,10 @@ struct InputStream; struct InputStream* InputStreamCreate(int fd); bool InputStreamKeyPress(struct InputStream* input_stream, unsigned evdev_code, bool pressed); +bool InputStreamMouseMove(struct InputStream* input_stream, int dx, int dy); +bool InputStreamMouseButton(struct InputStream* input_stream, unsigned button, + bool pressed); +bool InputStreamMouseWheel(struct InputStream* input_stream, int delta); bool InputStreamHandsoff(struct InputStream* input_stream); void InputStreamDestroy(struct InputStream* input_stream); @@ -98,6 +98,27 @@ static void OnWindowKey(void* user, unsigned key, bool pressed) { } } +static void OnWindowMove(void* user, int dx, int dy) { + if (!InputStreamMouseMove(user, dx, dy)) { + LOG("Failed to handle mouse move"); + g_signal = SIGABRT; + } +} + +static void OnWindowButton(void* user, unsigned button, bool pressed) { + if (!InputStreamMouseButton(user, button, pressed)) { + LOG("Failed to handle mouse button"); + g_signal = SIGABRT; + } +} + +static void OnWindowWheel(void* user, int delta) { + if (!InputStreamMouseWheel(user, delta)) { + LOG("Failed to handle mouse wheel"); + g_signal = SIGABRT; + } +} + static void InputStreamDtor(struct InputStream** input_stream) { if (!*input_stream) return; InputStreamDestroy(*input_stream); @@ -139,6 +160,9 @@ int main(int argc, char* argv[]) { .OnClose = OnWindowClose, .OnFocus = OnWindowFocus, .OnKey = OnWindowKey, + .OnMove = OnWindowMove, + .OnButton = OnWindowButton, + .OnWheel = OnWindowWheel, }; struct Window __attribute__((cleanup(WindowDtor)))* window = WindowCreate(&window_event_handlers, input_stream); @@ -16,6 +16,7 @@ protocols_dir:=\ protocols:=\ linux-dmabuf-unstable-v1 \ + relative-pointer-unstable-v1 \ xdg-shell obj:=$(patsubst %,%.o,$(protocols)) $(obj) @@ -26,6 +26,7 @@ #include "frame.h" #include "linux-dmabuf-unstable-v1.h" +#include "relative-pointer-unstable-v1.h" #include "toolbox/utils.h" #include "xdg-shell.h" @@ -42,7 +43,9 @@ struct Window { struct wl_keyboard* wl_keyboard; struct xdg_wm_base* xdg_wm_base; struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1; + struct zwp_relative_pointer_manager_v1* zwp_relative_pointer_manager_v1; + struct zwp_relative_pointer_v1* zwp_relative_pointer_v1; struct xdg_surface* xdg_surface; struct xdg_toplevel* xdg_toplevel; struct wl_buffer** wl_buffers; @@ -90,6 +93,15 @@ static void OnWlRegistryGlobal(void* data, struct wl_registry* wl_registry, wl_registry, name, &zwp_linux_dmabuf_v1_interface, version); if (!window->zwp_linux_dmabuf_v1) LOG("Failed to bind zwp_linux_dmabuf_v1 (%s)", strerror(errno)); + + } else if (!strcmp(interface, + zwp_relative_pointer_manager_v1_interface.name)) { + window->zwp_relative_pointer_manager_v1 = wl_registry_bind( + wl_registry, name, &zwp_relative_pointer_manager_v1_interface, version); + if (!window->zwp_relative_pointer_manager_v1) { + LOG("Failed to bind zwp_relative_pointer_manager_v1 (%s)", + strerror(errno)); + } } } @@ -132,12 +144,11 @@ static void OnWlPointerMotion(void* data, struct wl_pointer* wl_pointer, static void OnWlPointerButton(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { - (void)data; (void)wl_pointer; (void)serial; (void)time; - (void)button; - (void)state; + struct Window* window = data; + window->event_handlers->OnButton(window->user, button, !!state); } static void OnWlPointerAxis(void* data, struct wl_pointer* wl_pointer, @@ -179,10 +190,14 @@ static void OnWlPointerAxisDiscrete(void* data, struct wl_pointer* wl_pointer, static void OnWlPointerAxisValue120(void* data, struct wl_pointer* wl_pointer, uint32_t axis, int32_t value120) { - (void)data; (void)wl_pointer; - (void)axis; - (void)value120; + if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) { + // mburakov: Current code models regular one-wheeled mouse. + return; + } + struct Window* window = data; + // TODO(mburakov): Why minus is needed here? + window->event_handlers->OnWheel(window->user, -value120 / 120); } static void OnWlKeyboardKeymap(void* data, struct wl_keyboard* wl_keyboard, @@ -252,6 +267,20 @@ static void OnXdgWmBasePing(void* data, struct xdg_wm_base* xdg_wm_base, xdg_wm_base_pong(xdg_wm_base, serial); } +static void OnZwpRelativePointerMotion( + void* data, struct zwp_relative_pointer_v1* zwp_relative_pointer_v1, + uint32_t utime_hi, uint32_t utime_lo, wl_fixed_t dx, wl_fixed_t dy, + wl_fixed_t dx_unaccel, wl_fixed_t dy_unaccel) { + (void)zwp_relative_pointer_v1; + (void)utime_hi; + (void)utime_lo; + (void)dx; + (void)dy; + struct Window* window = data; + window->event_handlers->OnMove(window->user, wl_fixed_to_int(dx_unaccel), + wl_fixed_to_int(dy_unaccel)); +} + static void OnXdgSurfaceConfigure(void* data, struct xdg_surface* xdg_surface, uint32_t serial) { (void)data; @@ -291,6 +320,7 @@ static void OnXdgToplevelWmCapabilities(void* data, (void)xdg_toplevel; (void)capabilities; } + struct Window* WindowCreate(const struct WindowEventHandlers* event_handlers, void* user) { struct Window* window = malloc(sizeof(struct Window)); @@ -327,7 +357,8 @@ struct Window* WindowCreate(const struct WindowEventHandlers* event_handlers, goto rollback_wl_registry; } if (!window->wl_surface || !window->wl_pointer || !window->wl_keyboard || - !window->xdg_wm_base || !window->zwp_linux_dmabuf_v1) { + !window->xdg_wm_base || !window->zwp_linux_dmabuf_v1 || + !window->zwp_relative_pointer_manager_v1) { LOG("Some wayland objects are missing"); goto rollback_globals; } @@ -371,11 +402,29 @@ struct Window* WindowCreate(const struct WindowEventHandlers* event_handlers, goto rollback_globals; } + window->zwp_relative_pointer_v1 = + zwp_relative_pointer_manager_v1_get_relative_pointer( + window->zwp_relative_pointer_manager_v1, window->wl_pointer); + if (!window->zwp_relative_pointer_v1) { + LOG("Failed to get zwp_relative_pointer_v1 (%s)", strerror(errno)); + goto rollback_globals; + } + static const struct zwp_relative_pointer_v1_listener + zwp_relative_pointer_v1_listener = { + .relative_motion = OnZwpRelativePointerMotion, + }; + if (zwp_relative_pointer_v1_add_listener(window->zwp_relative_pointer_v1, + &zwp_relative_pointer_v1_listener, + window)) { + LOG("Failed to add zwp_relative_pointer_v1 listener (%s)", strerror(errno)); + goto rollback_zwp_relative_pointer_v1; + } + window->xdg_surface = xdg_wm_base_get_xdg_surface(window->xdg_wm_base, window->wl_surface); if (!window->xdg_surface) { LOG("Failed to get xdg_surface (%s)", strerror(errno)); - goto rollback_globals; + goto rollback_zwp_relative_pointer_v1; } static const struct xdg_surface_listener xdg_surface_listener = { .configure = OnXdgSurfaceConfigure, @@ -415,7 +464,13 @@ rollback_xdg_toplevel: xdg_toplevel_destroy(window->xdg_toplevel); rollback_xdg_surface: xdg_surface_destroy(window->xdg_surface); +rollback_zwp_relative_pointer_v1: + zwp_relative_pointer_v1_destroy(window->zwp_relative_pointer_v1); rollback_globals: + if (window->zwp_relative_pointer_manager_v1) { + zwp_relative_pointer_manager_v1_destroy( + window->zwp_relative_pointer_manager_v1); + } if (window->zwp_linux_dmabuf_v1) zwp_linux_dmabuf_v1_destroy(window->zwp_linux_dmabuf_v1); if (window->xdg_wm_base) xdg_wm_base_destroy(window->xdg_wm_base); @@ -506,6 +561,8 @@ void WindowDestroy(struct Window* window) { DestroyBuffers(window); xdg_toplevel_destroy(window->xdg_toplevel); xdg_surface_destroy(window->xdg_surface); + zwp_relative_pointer_manager_v1_destroy( + window->zwp_relative_pointer_manager_v1); zwp_linux_dmabuf_v1_destroy(window->zwp_linux_dmabuf_v1); xdg_wm_base_destroy(window->xdg_wm_base); wl_keyboard_release(window->wl_keyboard); @@ -28,6 +28,9 @@ struct WindowEventHandlers { void (*OnClose)(void* user); void (*OnFocus)(void* user, bool focused); void (*OnKey)(void* user, unsigned key, bool pressed); + void (*OnMove)(void* user, int dx, int dy); + void (*OnButton)(void* user, unsigned button, bool pressed); + void (*OnWheel)(void* user, int delta); }; struct Window* WindowCreate( |