mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-12 16:35:58 +01:00
wlr-seat: basic touch
This commit is contained in:
parent
0fe51b66e4
commit
e5a31ae870
8 changed files with 217 additions and 43 deletions
|
@ -39,7 +39,6 @@ struct roots_cursor {
|
|||
uint32_t resize_edges;
|
||||
// Ring buffer of input events that could trigger move/resize/rotate
|
||||
int input_events_idx;
|
||||
struct wl_list touch_points;
|
||||
struct roots_input_event input_events[16];
|
||||
|
||||
struct wl_listener motion;
|
||||
|
|
|
@ -43,13 +43,6 @@ struct roots_touch {
|
|||
struct wl_list link;
|
||||
};
|
||||
|
||||
struct roots_touch_point {
|
||||
struct roots_touch *device;
|
||||
int32_t slot;
|
||||
double x, y;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
struct roots_tablet_tool {
|
||||
struct roots_seat *seat;
|
||||
struct wlr_input_device *device;
|
||||
|
|
|
@ -126,4 +126,11 @@ void wlr_cursor_map_to_region(struct wlr_cursor *cur, struct wlr_box *box);
|
|||
void wlr_cursor_map_input_to_region(struct wlr_cursor *cur,
|
||||
struct wlr_input_device *dev, struct wlr_box *box);
|
||||
|
||||
/**
|
||||
* Convert absolute coordinates to layout coordinates for the device.
|
||||
*/
|
||||
bool wlr_cursor_absolute_to_layout_coords(struct wlr_cursor *cur,
|
||||
struct wlr_input_device *device, double x_mm, double y_mm,
|
||||
double width_mm, double height_mm, double *lx, double *ly);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -103,6 +103,23 @@ struct wlr_seat_keyboard_state {
|
|||
struct wlr_seat_keyboard_grab *default_grab;
|
||||
};
|
||||
|
||||
struct wlr_touch_point {
|
||||
int32_t touch_id;
|
||||
struct wlr_surface *surface;
|
||||
struct wlr_seat_client *client;
|
||||
double sx, sy;
|
||||
|
||||
struct wl_listener surface_destroy;
|
||||
struct wl_listener resource_destroy;
|
||||
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
struct wlr_seat_touch_state {
|
||||
struct wlr_seat *seat;
|
||||
struct wl_list touch_points; // wlr_touch_point::link
|
||||
};
|
||||
|
||||
struct wlr_seat {
|
||||
struct wl_global *wl_global;
|
||||
struct wl_display *display;
|
||||
|
@ -117,6 +134,7 @@ struct wlr_seat {
|
|||
|
||||
struct wlr_seat_pointer_state pointer_state;
|
||||
struct wlr_seat_keyboard_state keyboard_state;
|
||||
struct wlr_seat_touch_state touch_state;
|
||||
|
||||
struct wl_listener selection_data_source_destroy;
|
||||
|
||||
|
@ -328,4 +346,17 @@ void wlr_seat_keyboard_clear_focus(struct wlr_seat *wlr_seat);
|
|||
|
||||
// TODO: May be useful to be able to simulate keyboard input events
|
||||
|
||||
struct wlr_touch_point *wlr_seat_touch_get_point(struct wlr_seat *seat,
|
||||
int32_t touch_id);
|
||||
|
||||
void wlr_seat_touch_notify_down(struct wlr_seat *seat,
|
||||
struct wlr_surface *surface, uint32_t time, int32_t touch_id, double sx,
|
||||
double sy);
|
||||
|
||||
void wlr_seat_touch_notify_up(struct wlr_seat *seat, uint32_t time,
|
||||
int32_t touch_id);
|
||||
|
||||
void wlr_seat_touch_notify_motion(struct wlr_seat *seat, uint32_t time,
|
||||
int32_t touch_id, double sx, double sy);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -214,50 +214,57 @@ void roots_cursor_handle_axis(struct roots_cursor *cursor,
|
|||
|
||||
void roots_cursor_handle_touch_down(struct roots_cursor *cursor,
|
||||
struct wlr_event_touch_down *event) {
|
||||
struct roots_touch_point *point =
|
||||
calloc(1, sizeof(struct roots_touch_point));
|
||||
if (!point) {
|
||||
wlr_log(L_ERROR, "could not allocate memory for touch point");
|
||||
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
|
||||
struct wlr_surface *surface = NULL;
|
||||
double lx, ly;
|
||||
bool result =
|
||||
wlr_cursor_absolute_to_layout_coords(cursor->cursor,
|
||||
event->device, event->x_mm, event->y_mm, event->width_mm,
|
||||
event->height_mm, &lx, &ly);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
double sx, sy;
|
||||
view_at(desktop, lx, ly, &surface, &sx, &sy);
|
||||
|
||||
point->device = event->device->data;
|
||||
point->slot = event->slot;
|
||||
point->x = event->x_mm / event->width_mm;
|
||||
point->y = event->y_mm / event->height_mm;
|
||||
wlr_cursor_warp_absolute(cursor->cursor, event->device, point->x, point->y);
|
||||
roots_cursor_update_position(cursor, event->time_msec);
|
||||
wl_list_insert(&cursor->touch_points, &point->link);
|
||||
roots_cursor_press_button(cursor, event->device,
|
||||
event->time_msec, BTN_LEFT, 1);
|
||||
if (surface) {
|
||||
wlr_seat_touch_notify_down(cursor->seat->seat, surface,
|
||||
event->time_msec, event->slot, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
void roots_cursor_handle_touch_up(struct roots_cursor *cursor,
|
||||
struct wlr_event_touch_up *event) {
|
||||
struct roots_touch_point *point;
|
||||
wl_list_for_each(point, &cursor->touch_points, link) {
|
||||
if (point->slot == event->slot) {
|
||||
wl_list_remove(&point->link);
|
||||
free(point);
|
||||
break;
|
||||
}
|
||||
}
|
||||
roots_cursor_press_button(cursor, event->device,
|
||||
event->time_msec, BTN_LEFT, 0);
|
||||
// TODO
|
||||
wlr_seat_touch_notify_up(cursor->seat->seat, event->time_msec, event->slot);
|
||||
//roots_cursor_press_button(cursor, event->device, event->time_msec, BTN_LEFT, 0);
|
||||
}
|
||||
|
||||
void roots_cursor_handle_touch_motion(struct roots_cursor *cursor,
|
||||
struct wlr_event_touch_motion *event) {
|
||||
struct roots_touch_point *point;
|
||||
wl_list_for_each(point, &cursor->touch_points, link) {
|
||||
if (point->slot == event->slot) {
|
||||
point->x = event->x_mm / event->width_mm;
|
||||
point->y = event->y_mm / event->height_mm;
|
||||
wlr_cursor_warp_absolute(cursor->cursor, event->device,
|
||||
point->x, point->y);
|
||||
roots_cursor_update_position(cursor, event->time_msec);
|
||||
break;
|
||||
}
|
||||
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
|
||||
struct wlr_touch_point *point =
|
||||
wlr_seat_touch_get_point(cursor->seat->seat, event->slot);
|
||||
if (!point) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_surface *surface = NULL;
|
||||
double lx, ly;
|
||||
bool result =
|
||||
wlr_cursor_absolute_to_layout_coords(cursor->cursor,
|
||||
event->device, event->x_mm, event->y_mm, event->width_mm,
|
||||
event->height_mm, &lx, &ly);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
double sx, sy;
|
||||
view_at(desktop, lx, ly, &surface, &sx, &sy);
|
||||
|
||||
if (surface == point->surface) {
|
||||
wlr_seat_touch_notify_motion(cursor->seat->seat, event->time_msec,
|
||||
event->slot, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -188,8 +188,6 @@ static void roots_seat_init_cursor(struct roots_seat *seat) {
|
|||
// TODO: be able to configure per-seat cursor themes
|
||||
seat->cursor->xcursor_manager = desktop->xcursor_manager;
|
||||
|
||||
wl_list_init(&seat->cursor->touch_points);
|
||||
|
||||
roots_seat_configure_cursor(seat);
|
||||
roots_seat_configure_xcursor(seat);
|
||||
|
||||
|
|
|
@ -637,3 +637,21 @@ void wlr_cursor_map_input_to_region(struct wlr_cursor *cur,
|
|||
|
||||
c_device->mapped_box = box;
|
||||
}
|
||||
|
||||
bool wlr_cursor_absolute_to_layout_coords(struct wlr_cursor *cur,
|
||||
struct wlr_input_device *device, double x_mm, double y_mm,
|
||||
double width_mm, double height_mm, double *lx, double *ly) {
|
||||
if (width_mm <= 0 || height_mm <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wlr_box *mapping = get_mapping(cur, device);
|
||||
if (!mapping) {
|
||||
mapping = wlr_output_layout_get_box(cur->state->layout, NULL);
|
||||
}
|
||||
|
||||
*lx = x_mm > 0 ? mapping->width * (x_mm / width_mm) + mapping->x : cur->x;
|
||||
*ly = y_mm > 0 ? mapping->height * (y_mm / height_mm) + mapping->y : cur->y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
121
types/wlr_seat.c
121
types/wlr_seat.c
|
@ -338,6 +338,10 @@ struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) {
|
|||
wl_list_init(
|
||||
&wlr_seat->keyboard_state.surface_destroy.link);
|
||||
|
||||
// touch state
|
||||
wlr_seat->touch_state.seat = wlr_seat;
|
||||
wl_list_init(&wlr_seat->touch_state.touch_points);
|
||||
|
||||
struct wl_global *wl_global = wl_global_create(display,
|
||||
&wl_seat_interface, 6, wlr_seat, wl_seat_bind);
|
||||
if (!wl_global) {
|
||||
|
@ -819,3 +823,120 @@ void wlr_seat_keyboard_notify_key(struct wlr_seat *seat, uint32_t time,
|
|||
struct wlr_seat_keyboard_grab *grab = seat->keyboard_state.grab;
|
||||
grab->interface->key(grab, time, key, state);
|
||||
}
|
||||
|
||||
static void touch_point_destroy(struct wlr_touch_point *point) {
|
||||
wl_list_remove(&point->surface_destroy.link);
|
||||
wl_list_remove(&point->resource_destroy.link);
|
||||
wl_list_remove(&point->link);
|
||||
free(point);
|
||||
}
|
||||
|
||||
static void handle_touch_point_resource_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_touch_point *point =
|
||||
wl_container_of(listener, point, resource_destroy);
|
||||
touch_point_destroy(point);
|
||||
}
|
||||
|
||||
static void handle_touch_point_surface_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_touch_point *point =
|
||||
wl_container_of(listener, point, surface_destroy);
|
||||
touch_point_destroy(point);
|
||||
}
|
||||
|
||||
static struct wlr_touch_point *touch_point_create(
|
||||
struct wlr_seat *seat, int32_t touch_id,
|
||||
struct wlr_surface *surface, double sx, double sy) {
|
||||
struct wl_client *wl_client = wl_resource_get_client(surface->resource);
|
||||
struct wlr_seat_client *client = wlr_seat_client_for_wl_client(seat, wl_client);
|
||||
|
||||
if (!client || !client->touch) {
|
||||
// touch points are not valid without a connected client with touch
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_touch_point *point = calloc(1, sizeof(struct wlr_touch_point));
|
||||
if (!point) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
point->touch_id = touch_id;
|
||||
point->surface = surface;
|
||||
point->client = client;
|
||||
|
||||
point->sx = sx;
|
||||
point->sy = sy;
|
||||
|
||||
wl_signal_add(&surface->events.destroy, &point->surface_destroy);
|
||||
point->surface_destroy.notify = handle_touch_point_surface_destroy;
|
||||
wl_resource_add_destroy_listener(surface->resource,
|
||||
&point->resource_destroy);
|
||||
point->resource_destroy.notify = handle_touch_point_resource_destroy;
|
||||
|
||||
wl_list_insert(&seat->touch_state.touch_points, &point->link);
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
struct wlr_touch_point *wlr_seat_touch_get_point(
|
||||
struct wlr_seat *seat, int32_t touch_id) {
|
||||
struct wlr_touch_point *point = NULL;
|
||||
wl_list_for_each(point, &seat->touch_state.touch_points, link) {
|
||||
if (point->touch_id == touch_id) {
|
||||
return point;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wlr_seat_touch_notify_down(struct wlr_seat *seat,
|
||||
struct wlr_surface *surface, uint32_t time, int32_t touch_id, double sx,
|
||||
double sy) {
|
||||
if (wlr_seat_touch_get_point(seat, touch_id)) {
|
||||
wlr_log(L_ERROR, "got touch down for a touch point that's already down");
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_touch_point *point =
|
||||
touch_point_create(seat, touch_id, surface, sx, sy);
|
||||
if (!point) {
|
||||
wlr_log(L_ERROR, "could not create touch point");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t serial = wl_display_next_serial(seat->display);
|
||||
wl_touch_send_down(point->client->touch, serial, time, surface->resource,
|
||||
touch_id, wl_fixed_from_double(sx), wl_fixed_from_double(sy));
|
||||
wl_touch_send_frame(point->client->touch);
|
||||
}
|
||||
|
||||
void wlr_seat_touch_notify_up(struct wlr_seat *seat, uint32_t time, int32_t touch_id) {
|
||||
struct wlr_touch_point *point = wlr_seat_touch_get_point(seat, touch_id);
|
||||
if (!point) {
|
||||
wlr_log(L_ERROR, "got touch notify up for unknown touch point");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t serial = wl_display_next_serial(seat->display);
|
||||
wl_touch_send_up(point->client->touch, serial, time, touch_id);
|
||||
wl_touch_send_frame(point->client->touch);
|
||||
touch_point_destroy(point);
|
||||
}
|
||||
|
||||
void wlr_seat_touch_notify_motion(struct wlr_seat *seat, uint32_t time, int32_t touch_id,
|
||||
double sx, double sy) {
|
||||
struct wlr_touch_point *point = wlr_seat_touch_get_point(seat, touch_id);
|
||||
if (!point) {
|
||||
wlr_log(L_ERROR, "got touch motion notify for unknown touch point");
|
||||
return;
|
||||
}
|
||||
|
||||
point->sx = sx;
|
||||
point->sy = sy;
|
||||
|
||||
wl_touch_send_motion(point->client->touch, time, touch_id,
|
||||
wl_fixed_from_double(sx), wl_fixed_from_double(sy));
|
||||
wl_touch_send_frame(point->client->touch);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue