diff --git a/src/display-wayland.cc b/src/display-wayland.cc index 49dbb77f..d9afc950 100644 --- a/src/display-wayland.cc +++ b/src/display-wayland.cc @@ -25,6 +25,8 @@ */ #include +#include +#include #include "logging.h" #ifdef BUILD_WAYLAND @@ -63,6 +65,7 @@ #endif #ifdef BUILD_MOUSE_EVENTS #include "mouse-events.h" +#include #endif #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -427,32 +430,66 @@ void window_layer_surface_set_size(struct window *window) { } #ifdef BUILD_MOUSE_EVENTS +static std::map> last_known_positions{}; + static void on_pointer_enter(void *data, wl_pointer *pointer, uint32_t serial, - wl_surface *surface, wl_fixed_t sx, - wl_fixed_t sy) { - DBGP("POINTER ENTERED! WOAH!"); + wl_surface *surface, wl_fixed_t surface_x, + wl_fixed_t surface_y) { + auto w = reinterpret_cast(data); + + size_t x = static_cast(wl_fixed_to_double(surface_x)); + size_t y = static_cast(wl_fixed_to_double(surface_y)); + last_known_positions[pointer] = {x, y}; + + size_t abs_x = w->rectangle.x + x; + size_t abs_y = w->rectangle.y + y; + + mouse_crossing_event event { + mouse_event_t::AREA_ENTER, + x, + y, + abs_x, + abs_y + }; } static void on_pointer_leave(void *data, - struct wl_pointer *wl_pointer, + struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) { - DBGP("POINTER LEFT! WOAH!"); + auto w = reinterpret_cast(data); + + std::array last = last_known_positions[pointer]; + size_t x = last[0]; + size_t y = last[1]; + size_t abs_x = w->rectangle.x + x; + size_t abs_y = w->rectangle.y + y; + + mouse_crossing_event event { + mouse_event_t::AREA_LEAVE, + x, + y, + abs_x, + abs_y + }; } static void on_pointer_motion(void *data, - struct wl_pointer *wl_pointer, - uint32_t time, + struct wl_pointer *pointer, + uint32_t _time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - window *w = reinterpret_cast(data); - size_t x = surface_x; - size_t y = surface_y; + auto w = reinterpret_cast(data); + + size_t x = static_cast(wl_fixed_to_double(surface_x)); + size_t y = static_cast(wl_fixed_to_double(surface_y)); + last_known_positions[pointer] = {x, y}; + size_t abs_x = w->rectangle.x + x; size_t abs_y = w->rectangle.y + y; + mouse_move_event event { - mouse_event_type::MOUSE_MOVE, - time, + mouse_event_t::MOUSE_MOVE, x, y, abs_x, @@ -462,12 +499,76 @@ static void on_pointer_motion(void *data, } static void on_pointer_button(void *data, - struct wl_pointer *wl_pointer, + struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { - + auto w = reinterpret_cast(data); + + std::array last = last_known_positions[pointer]; + size_t x = last[0]; + size_t y = last[1]; + size_t abs_x = w->rectangle.x + x; + size_t abs_y = w->rectangle.y + y; + + mouse_button_event event { + mouse_event_t::MOUSE_RELEASE, + x, + y, + abs_x, + abs_y, + static_cast(button), + }; + + switch (static_cast(state)) { + case WL_POINTER_BUTTON_STATE_RELEASED: + // pass; default is MOUSE_RELEASE + break; + case WL_POINTER_BUTTON_STATE_PRESSED: + event.type = mouse_event_t::MOUSE_PRESS; + break; + default: + return; + } + llua_mouse_hook(event); +} + +void on_pointer_axis(void *data, + struct wl_pointer *pointer, + uint32_t time, + uint32_t axis, + wl_fixed_t value) { + if (value == 0) return; + + auto w = reinterpret_cast(data); + + std::array last = last_known_positions[pointer]; + size_t x = last[0]; + size_t y = last[1]; + size_t abs_x = w->rectangle.x + x; + size_t abs_y = w->rectangle.y + y; + + mouse_scroll_event event { + mouse_event_t::MOUSE_SCROLL, + x, + y, + abs_x, + abs_y, + scroll_direction_t::SCROLL_UP, + }; + + switch (static_cast(axis)) { + case WL_POINTER_AXIS_VERTICAL_SCROLL: + event.direction = value > 0 ? scroll_direction_t::SCROLL_DOWN : scroll_direction_t::SCROLL_UP; + break; + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: + event.direction = value > 0 ? scroll_direction_t::SCROLL_RIGHT : scroll_direction_t::SCROLL_LEFT; + break; + default: + return; + } + llua_mouse_hook(event); } static void seat_capability_listener (void *data, wl_seat *seat, uint32_t capability_int) { @@ -481,6 +582,7 @@ static void seat_capability_listener (void *data, wl_seat *seat, uint32_t capabi .leave = on_pointer_leave, .motion = on_pointer_motion, .button = on_pointer_button, + .axis = on_pointer_axis, }; wl_pointer_add_listener(wl_globals.pointer, &listener, data); } diff --git a/src/mouse-events.cc b/src/mouse-events.cc index c9663b29..bdade3b3 100644 --- a/src/mouse-events.cc +++ b/src/mouse-events.cc @@ -22,6 +22,7 @@ #include #include +#include #ifdef BUILD_X11 #include "X11/Xlib.h" @@ -29,9 +30,9 @@ std::string event_type_to_str(int type) { switch (type) { - case MOUSE_DOWN: + case MOUSE_PRESS: return "button_down"; - case MOUSE_UP: + case MOUSE_RELEASE: return "button_up"; case MOUSE_SCROLL: return "mouse_scroll"; @@ -109,11 +110,20 @@ void push_mods(lua_State *L, std::bitset<13> mods) { lua_settable(L, -3); } +// Returns ms since Epoch. +inline size_t current_time_ms() { + struct timespec spec; + clock_gettime(CLOCK_REALTIME, &spec); + return static_cast(static_cast(spec.tv_sec)*1'000 + spec.tv_nsec/1'000'000); +} + /* Class methods */ +mouse_event::mouse_event(mouse_event_t type): type(type), time(current_time_ms()) {}; void mouse_event::push_lua_table(lua_State *L) const { lua_newtable(L); push_table_value(L, "type", event_type_to_str(this->type)); + push_table_value(L, "time", this->time); push_lua_data(L); } @@ -122,7 +132,6 @@ void mouse_positioned_event::push_lua_data(lua_State *L) const { push_table_value(L, "y", this->y); push_table_value(L, "x_abs", this->x_abs); push_table_value(L, "y_abs", this->y_abs); - push_table_value(L, "time", this->time); } #ifdef BUILD_X11 @@ -132,7 +141,6 @@ mouse_move_event::mouse_move_event(XMotionEvent *ev) { this->y = ev->y; this->x_abs = ev->x_root; this->y_abs = ev->y_root; - this->time = ev->time; } #endif /* BUILD_X11 */ @@ -148,34 +156,77 @@ mouse_scroll_event::mouse_scroll_event(XButtonEvent *ev) { this->y = ev->y; this->x_abs = ev->x_root; this->y_abs = ev->y_root; - this->time = ev->time; this->mods = ev->state; - this->up = ev->button == 4; + if (ev->button == 4) { + this->direction = scroll_direction_t::UP; + } else if (ev->button == 5) { + this->direction = scroll_direction_t::DOWN; + } } #endif /* BUILD_X11 */ void mouse_scroll_event::push_lua_data(lua_State *L) const { mouse_positioned_event::push_lua_data(L); - push_table_value(L, "direction", std::string(this->up ? "up" : "down")); + std::string direction = "up"; + switch (this->direction) { + case SCROLL_DOWN: + direction = "down"; + break; + case SCROLL_UP: + break; + case SCROLL_LEFT: + direction = "left"; + break; + case SCROLL_RIGHT: + direction = "right"; + break; + default: + direction = "err"; + break; + } + push_table_value(L, "direction", direction); push_mods(L, this->mods); } #ifdef BUILD_X11 mouse_button_event::mouse_button_event(XButtonEvent *ev) { - this->type = ev->type == ButtonPress ? MOUSE_DOWN : MOUSE_UP; + this->type = ev->type == ButtonPress ? MOUSE_PRESS : MOUSE_RELEASE; this->x = ev->x; this->y = ev->y; this->x_abs = ev->x_root; this->y_abs = ev->y_root; - this->time = ev->time; this->mods = ev->state; - this->button = ev->button; + switch (ev->button) { + case Button1: + this->button = BUTTON_LEFT; + break; + case Button2: + this->button = BUTTON_RIGHT; + break; + case Button3: + this->button = BUTTON_MIDDLE; + break; + } } #endif /* BUILD_X11 */ +std::string button_name(mouse_button_t button) { + switch (button) { + case BUTTON_LEFT: + return "left"; + case BUTTON_RIGHT: + return "right"; + case BUTTON_MIDDLE: + return "middle"; + default: + return std::to_string(button); + } +} + void mouse_button_event::push_lua_data(lua_State *L) const { mouse_positioned_event::push_lua_data(L); - push_table_value(L, "button", this->button); + push_table_value(L, "button_code", static_cast(this->button)); + push_table_value(L, "button", button_name(this->button)); push_mods(L, this->mods); } @@ -186,6 +237,5 @@ mouse_crossing_event::mouse_crossing_event(XCrossingEvent *ev) { this->y = ev->y; this->x_abs = ev->x_root; this->y_abs = ev->y_root; - this->time = ev->time; } #endif /* BUILD_X11 */ diff --git a/src/mouse-events.h b/src/mouse-events.h index 97172132..d9bde1b8 100644 --- a/src/mouse-events.h +++ b/src/mouse-events.h @@ -34,9 +34,9 @@ extern "C" { #include } -enum mouse_event_type { - MOUSE_DOWN = 0, - MOUSE_UP = 1, +enum mouse_event_t { + MOUSE_PRESS = 0, + MOUSE_RELEASE = 1, MOUSE_SCROLL = 2, MOUSE_MOVE = 3, AREA_ENTER = 4, @@ -44,11 +44,35 @@ enum mouse_event_type { MOUSE_EVENT_COUNT = 6, }; -struct mouse_event { - mouse_event_type type; - uint64_t time = 0L; // event time +#ifdef __linux +#include +#elif __FreeBSD__ +#include +#elif __DragonFly__ +#include +#else +// Probably incorrect for some platforms, feel free to add your platform to the +// above list if it has other event codes or a standard file containing them. - mouse_event(mouse_event_type type, uint64_t time): type(type), time(time) {}; +// Left mouse button event code +#define BTN_LEFT 0x110 +// Right mouse button event code +#define BTN_RIGHT 0x111 +// Middle mouse button event code +#define BTN_MIDDLE 0x112 +#endif + +enum mouse_button_t: uint32_t { + BUTTON_LEFT = BTN_LEFT, + BUTTON_RIGHT = BTN_RIGHT, + BUTTON_MIDDLE = BTN_MIDDLE, +}; + +struct mouse_event { + mouse_event_t type; // type of event + size_t time; // ms since epoch when the event happened + + explicit mouse_event(mouse_event_t type); void push_lua_table(lua_State *L) const; @@ -56,10 +80,10 @@ struct mouse_event { }; struct mouse_positioned_event : public mouse_event { - size_t x = 0, y = 0; // positions relative to window - size_t x_abs = 0, y_abs = 0; // positions relative to root + size_t x = 0, y = 0; // position relative to window + size_t x_abs = 0, y_abs = 0; // position relative to root - mouse_positioned_event(mouse_event_type type, uint64_t time, size_t x, size_t y, size_t x_abs, size_t y_abs): mouse_event{type, time}, x(x), y(y), x_abs(x_abs), y_abs() {}; + mouse_positioned_event(mouse_event_t type, size_t x, size_t y, size_t x_abs, size_t y_abs): mouse_event(type), x(x), y(y), x_abs(x_abs), y_abs() {}; void push_lua_data(lua_State *L) const; }; @@ -67,7 +91,7 @@ struct mouse_positioned_event : public mouse_event { struct mouse_move_event : public mouse_positioned_event { std::bitset<13> mods; // held buttons and modifiers (ctrl, shift, ...) - explicit mouse_move_event(mouse_event_type type, uint64_t time, size_t x, size_t y, size_t x_abs, size_t y_abs, std::bitset<13> mods = 0): mouse_positioned_event{type, time, x, y, x_abs, y_abs}, mods(mods) {}; + mouse_move_event(mouse_event_t type, size_t x, size_t y, size_t x_abs, size_t y_abs, std::bitset<13> mods = 0): mouse_positioned_event{type, x, y, x_abs, y_abs}, mods(mods) {}; #ifdef BUILD_X11 explicit mouse_move_event(XMotionEvent *ev); #endif /* BUILD_X11 */ @@ -75,10 +99,18 @@ struct mouse_move_event : public mouse_positioned_event { void push_lua_data(lua_State *L) const; }; +enum scroll_direction_t: uint8_t { + SCROLL_UP = 0, + SCROLL_DOWN, + SCROLL_LEFT, + SCROLL_RIGHT, +}; + struct mouse_scroll_event : public mouse_positioned_event { std::bitset<13> mods; // held buttons and modifiers (ctrl, shift, ...) - bool up = false; + scroll_direction_t direction; + mouse_scroll_event(mouse_event_t type, size_t x, size_t y, size_t x_abs, size_t y_abs, scroll_direction_t direction, std::bitset<13> mods = 0): mouse_positioned_event{type, x, y, x_abs, y_abs}, direction(direction), mods(mods) {}; #ifdef BUILD_X11 explicit mouse_scroll_event(XButtonEvent *ev); #endif /* BUILD_X11 */ @@ -88,8 +120,9 @@ struct mouse_scroll_event : public mouse_positioned_event { struct mouse_button_event : public mouse_positioned_event { std::bitset<13> mods; // held buttons and modifiers (ctrl, shift, ...) - uint button = 0; + mouse_button_t button; + mouse_button_event(mouse_event_t type, size_t x, size_t y, size_t x_abs, size_t y_abs, mouse_button_t button, std::bitset<13> mods = 0): mouse_positioned_event{type, x, y, x_abs, y_abs}, button(button), mods(mods) {}; #ifdef BUILD_X11 explicit mouse_button_event(XButtonEvent *ev); #endif /* BUILD_X11 */ @@ -101,6 +134,7 @@ typedef struct mouse_button_event mouse_press_event; typedef struct mouse_button_event mouse_release_event; struct mouse_crossing_event : public mouse_positioned_event { + mouse_crossing_event(mouse_event_t type, size_t x, size_t y, size_t x_abs, size_t y_abs): mouse_positioned_event{type, x, y, x_abs, y_abs} {}; #ifdef BUILD_X11 explicit mouse_crossing_event(XCrossingEvent *ev); #endif /* BUILD_X11 */