diff --git a/kiwmi/include/input/cursor.h b/kiwmi/include/input/cursor.h index 9f6c570..1fd1014 100644 --- a/kiwmi/include/input/cursor.h +++ b/kiwmi/include/input/cursor.h @@ -39,6 +39,10 @@ struct kiwmi_cursor { struct wl_listener cursor_button; struct wl_listener cursor_axis; struct wl_listener cursor_frame; + struct wl_listener cursor_touch_up; + struct wl_listener cursor_touch_down; + struct wl_listener cursor_touch_motion; + struct wl_listener cursor_touch_frame; struct { struct wl_signal button_down; @@ -46,6 +50,7 @@ struct kiwmi_cursor { struct wl_signal destroy; struct wl_signal motion; struct wl_signal scroll; + struct wl_signal touch; } events; }; @@ -61,6 +66,14 @@ struct kiwmi_cursor_motion_event { double newy; }; +struct kiwmi_cursor_touch_event { + char *event; + int id; + double x; + double y; + bool handled; +}; + struct kiwmi_cursor_scroll_event { const char *device_name; bool is_vertical; diff --git a/kiwmi/include/input/input.h b/kiwmi/include/input/input.h index cbaa60d..0fd7e81 100644 --- a/kiwmi/include/input/input.h +++ b/kiwmi/include/input/input.h @@ -15,6 +15,7 @@ struct kiwmi_input { struct wl_listener new_input; struct kiwmi_cursor *cursor; struct kiwmi_seat *seat; + int touchpads; struct { struct wl_signal keyboard_new; diff --git a/kiwmi/kiwmi/input/cursor.c b/kiwmi/kiwmi/input/cursor.c index 7fce94a..a07cb27 100644 --- a/kiwmi/kiwmi/input/cursor.c +++ b/kiwmi/kiwmi/input/cursor.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -119,6 +120,130 @@ cursor_motion_notify(struct wl_listener *listener, void *data) process_cursor_motion(server, event->time_msec); } +static void +cursor_touch_down_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_cursor *cursor = + wl_container_of(listener, cursor, cursor_touch_down); + struct kiwmi_server *server = cursor->server; + struct kiwmi_desktop *desktop = &server->desktop; + struct wlr_event_touch_down *event = data; + + struct kiwmi_input *input = &server->input; + struct wlr_seat *seat = input->seat->seat; + struct wlr_surface *surface = NULL; + + /* FIXME figure out what scaling should be done here. + * Does the touch co-ordinate system map onto a single output + * (e.g. phone screen) or onto the entire layout (tablet, + * maybe?) + */ + double lx = 720 * event->x; + double ly = 1440 * event->y; + double sx, sy; + + struct kiwmi_view *view = view_at( + desktop, + lx, ly, + &surface, + &sx, &sy); + + wlr_log(WLR_DEBUG, "view %x surface %x %f,%f %f,%f\n", + view, surface, lx, ly, sx, sy); + + /* we send the event to lua with 0..1 co-ordinates, because + * it may not be over any surface + */ + struct kiwmi_cursor_touch_event new_event = { + .event = "down", + .id = event->touch_id, + .x = event->x, + .y = event->y, + }; + + wl_signal_emit(&cursor->events.touch, &new_event); + + if(!new_event.handled && + surface && + wlr_surface_accepts_touch(seat, surface)) { + wlr_log(WLR_DEBUG, "surface %x %f %f\n", + surface, sx, sy); + wlr_seat_touch_notify_down(seat, surface, event->time_msec, + event->touch_id, sx, sy); + } +} + +static void +cursor_touch_up_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_cursor *cursor = + wl_container_of(listener, cursor, cursor_touch_up); + struct kiwmi_server *server = cursor->server; + struct wlr_event_touch_up *event = data; + struct kiwmi_input *input = &server->input; + struct wlr_seat *seat = input->seat->seat; + + struct kiwmi_cursor_touch_event new_event = { + .event = "up", + .id = event->touch_id, + }; + + wl_signal_emit(&cursor->events.touch, &new_event); + if(!new_event.handled) { + wlr_seat_touch_notify_up(seat, event->time_msec, event->touch_id); + } +} + +static void +cursor_touch_motion_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_cursor *cursor = + wl_container_of(listener, cursor, cursor_touch_motion); + struct kiwmi_server *server = cursor->server; + struct wlr_event_touch_motion *event = data; + struct kiwmi_input *input = &server->input; + struct wlr_seat *seat = input->seat->seat; + + struct kiwmi_cursor_touch_event new_event = { + .event = "motion", + .id = event->touch_id, + .x = event->x, + .y = event->y, + }; + + wl_signal_emit(&cursor->events.touch, &new_event); + + + if(!new_event.handled) { + /* UNSURE: should we still send this even if the touch_down + * didn't get sent because the surface doesn't accept + * touch? */ + wlr_seat_touch_notify_motion(seat, event->time_msec, + event->touch_id, event->x, event->y); + } +} + +static void +cursor_touch_frame_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_cursor *cursor = + wl_container_of(listener, cursor, cursor_touch_frame); + struct kiwmi_server *server = cursor->server; + struct kiwmi_input *input = &server->input; + + struct wlr_seat *seat = input->seat->seat; + + struct kiwmi_cursor_touch_event new_event = { + .event = "frame", + }; + + wl_signal_emit(&cursor->events.touch, &new_event); + + if(!new_event.handled) { + wlr_seat_touch_notify_frame(seat); + } +} + static void cursor_motion_absolute_notify(struct wl_listener *listener, void *data) { @@ -252,10 +377,23 @@ cursor_create( cursor->cursor_frame.notify = cursor_frame_notify; wl_signal_add(&cursor->cursor->events.frame, &cursor->cursor_frame); + cursor->cursor_touch_down.notify = cursor_touch_down_notify; + wl_signal_add(&cursor->cursor->events.touch_down, &cursor->cursor_touch_down); + + cursor->cursor_touch_up.notify = cursor_touch_up_notify; + wl_signal_add(&cursor->cursor->events.touch_up, &cursor->cursor_touch_up); + + cursor->cursor_touch_motion.notify = cursor_touch_motion_notify; + wl_signal_add(&cursor->cursor->events.touch_motion, &cursor->cursor_touch_motion); + + cursor->cursor_touch_frame.notify = cursor_touch_frame_notify; + wl_signal_add(&cursor->cursor->events.touch_frame, &cursor->cursor_touch_frame); + wl_signal_init(&cursor->events.button_down); wl_signal_init(&cursor->events.button_up); wl_signal_init(&cursor->events.destroy); wl_signal_init(&cursor->events.motion); + wl_signal_init(&cursor->events.touch); wl_signal_init(&cursor->events.scroll); return cursor; diff --git a/kiwmi/kiwmi/input/input.c b/kiwmi/kiwmi/input/input.c index e70159f..a89f044 100644 --- a/kiwmi/kiwmi/input/input.c +++ b/kiwmi/kiwmi/input/input.c @@ -28,6 +28,13 @@ new_pointer(struct kiwmi_input *input, struct wlr_input_device *device) wlr_cursor_attach_input_device(input->cursor->cursor, device); } +static void +new_touch(struct kiwmi_input *input, struct wlr_input_device *device) +{ + wlr_cursor_attach_input_device(input->cursor->cursor, device); + input->touchpads++; +} + static void new_keyboard(struct kiwmi_input *input, struct wlr_input_device *device) { @@ -53,6 +60,9 @@ new_input_notify(struct wl_listener *listener, void *data) case WLR_INPUT_DEVICE_POINTER: new_pointer(input, device); break; + case WLR_INPUT_DEVICE_TOUCH: + new_touch(input, device); + break; case WLR_INPUT_DEVICE_KEYBOARD: new_keyboard(input, device); break; @@ -65,6 +75,9 @@ new_input_notify(struct wl_listener *listener, void *data) if (!wl_list_empty(&input->keyboards)) { caps |= WL_SEAT_CAPABILITY_KEYBOARD; } + if(input->touchpads) { + caps |= WL_SEAT_CAPABILITY_TOUCH; + } wlr_seat_set_capabilities(input->seat->seat, caps); } diff --git a/kiwmi/kiwmi/luak/kiwmi_cursor.c b/kiwmi/kiwmi/luak/kiwmi_cursor.c index 89dcf07..0c9478b 100644 --- a/kiwmi/kiwmi/luak/kiwmi_cursor.c +++ b/kiwmi/kiwmi/luak/kiwmi_cursor.c @@ -162,6 +162,36 @@ kiwmi_cursor_on_motion_notify(struct wl_listener *listener, void *data) } } +static void +kiwmi_cursor_on_touch_notify(struct wl_listener *listener, void *data) +{ + struct kiwmi_lua_callback *lc = wl_container_of(listener, lc, listener); + struct kiwmi_server *server = lc->server; + lua_State *L = server->lua->L; + struct kiwmi_cursor_touch_event *event = data; + + lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref); + + lua_newtable(L); + + lua_pushnumber(L, event->x); + lua_setfield(L, -2, "x"); + + lua_pushnumber(L, event->y); + lua_setfield(L, -2, "y"); + + lua_pushnumber(L, event->id); + lua_setfield(L, -2, "id"); + + lua_pushstring(L, event->event); + lua_setfield(L, -2, "name"); + + if (lua_pcall(L, 1, 0, 0)) { + wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); + lua_pop(L, 1); + } +} + static void kiwmi_cursor_on_scroll_notify(struct wl_listener *listener, void *data) { @@ -267,6 +297,31 @@ l_kiwmi_cursor_on_motion(lua_State *L) return 0; } +static int +l_kiwmi_cursor_on_touch(lua_State *L) +{ + struct kiwmi_object *obj = + *(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor"); + luaL_checktype(L, 2, LUA_TFUNCTION); + + struct kiwmi_cursor *cursor = obj->object; + struct kiwmi_server *server = cursor->server; + + lua_pushcfunction(L, luaK_kiwmi_lua_callback_new); + lua_pushlightuserdata(L, server); + lua_pushvalue(L, 2); + lua_pushlightuserdata(L, kiwmi_cursor_on_touch_notify); + lua_pushlightuserdata(L, &cursor->events.touch); + lua_pushlightuserdata(L, obj); + + if (lua_pcall(L, 5, 0, 0)) { + wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1)); + return 0; + } + + return 0; +} + static int l_kiwmi_cursor_on_scroll(lua_State *L) { @@ -296,6 +351,7 @@ static const luaL_Reg kiwmi_cursor_events[] = { {"button_down", l_kiwmi_cursor_on_button_down}, {"button_up", l_kiwmi_cursor_on_button_up}, {"motion", l_kiwmi_cursor_on_motion}, + {"touch", l_kiwmi_cursor_on_touch}, {"scroll", l_kiwmi_cursor_on_scroll}, {NULL, NULL}, };