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( | 
