clients: Add support for tablet cursor motion to window frames in libtoytoolkit
When it comes to a window frame, a tablet tool and cursor act almost identical; they click things, drag things, etc. The tool type and extra axes don't serve any use in the context of a window frame, so tablet pointers share the frame_pointer structures used for the mouse pointer. Co-authored-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Lyude Paul <thatslyude@gmail.com> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Jonas Ådahl <jadahl@gmail.com> Signed-off-by: Bastian Farkas <bfarkas@de.adit-jv.com> Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
This commit is contained in:
parent
0ced0c62ee
commit
6a06669b58
@ -2415,6 +2415,54 @@ frame_touch_up_handler(struct widget *widget,
|
||||
frame_handle_status(frame, input, time, THEME_LOCATION_CLIENT_AREA);
|
||||
}
|
||||
|
||||
static int
|
||||
frame_tablet_tool_motion_handler(struct widget *widget,
|
||||
struct tablet_tool *tool,
|
||||
float x, float y,
|
||||
void *data)
|
||||
{
|
||||
struct window_frame *frame = data;
|
||||
enum theme_location location;
|
||||
|
||||
location = frame_tablet_tool_motion(frame->frame, tool, x, y);
|
||||
if (frame_status(frame->frame) & FRAME_STATUS_REPAINT)
|
||||
widget_schedule_redraw(frame->widget);
|
||||
|
||||
frame_get_pointer_image_for_location(data, location);
|
||||
|
||||
return CURSOR_LEFT_PTR;
|
||||
}
|
||||
|
||||
static void
|
||||
frame_tablet_tool_down_handler(struct widget *widget,
|
||||
struct tablet_tool *tool,
|
||||
void *data)
|
||||
{
|
||||
struct window_frame *frame = data;
|
||||
enum theme_location location;
|
||||
uint32_t time = 0; /* FIXME: we should be doing this in the frame
|
||||
handler where we have the timestamp */
|
||||
|
||||
/* Map a stylus touch to the left mouse button */
|
||||
location = frame_pointer_button(frame->frame, tool, BTN_LEFT, 1);
|
||||
frame_handle_status(frame, tool->input, time, location);
|
||||
}
|
||||
|
||||
static void
|
||||
frame_tablet_tool_up_handler(struct widget *widget, struct tablet_tool *tool,
|
||||
void *data)
|
||||
{
|
||||
struct window_frame *frame = data;
|
||||
enum theme_location location;
|
||||
uint32_t time = 0; /* FIXME: we should be doing this in the frame
|
||||
handler where we have the timestamp */
|
||||
|
||||
/* Map the stylus leaving contact with the tablet as releasing the left
|
||||
* mouse button */
|
||||
location = frame_pointer_button(frame->frame, tool, BTN_LEFT, 0);
|
||||
frame_handle_status(frame, tool->input, time, location);
|
||||
}
|
||||
|
||||
struct widget *
|
||||
window_frame_create(struct window *window, void *data)
|
||||
{
|
||||
@ -2446,6 +2494,12 @@ window_frame_create(struct window *window, void *data)
|
||||
widget_set_button_handler(frame->widget, frame_button_handler);
|
||||
widget_set_touch_down_handler(frame->widget, frame_touch_down_handler);
|
||||
widget_set_touch_up_handler(frame->widget, frame_touch_up_handler);
|
||||
widget_set_tablet_tool_axis_handlers(frame->widget,
|
||||
frame_tablet_tool_motion_handler,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
widget_set_tablet_tool_down_handler(frame->widget, frame_tablet_tool_down_handler);
|
||||
widget_set_tablet_tool_up_handler(frame->widget, frame_tablet_tool_up_handler);
|
||||
|
||||
window->frame = frame;
|
||||
|
||||
|
@ -161,6 +161,13 @@ struct shell_touch_grab {
|
||||
struct weston_touch *touch;
|
||||
};
|
||||
|
||||
struct shell_tablet_tool_grab {
|
||||
struct weston_tablet_tool_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
struct weston_tablet_tool *tool;
|
||||
};
|
||||
|
||||
struct weston_move_grab {
|
||||
struct shell_grab base;
|
||||
wl_fixed_t dx, dy;
|
||||
@ -173,6 +180,11 @@ struct weston_touch_move_grab {
|
||||
wl_fixed_t dx, dy;
|
||||
};
|
||||
|
||||
struct weston_tablet_tool_move_grab {
|
||||
struct shell_tablet_tool_grab base;
|
||||
wl_fixed_t dx, dy;
|
||||
};
|
||||
|
||||
struct rotate_grab {
|
||||
struct shell_grab base;
|
||||
struct weston_matrix rotation;
|
||||
@ -190,10 +202,15 @@ struct shell_seat {
|
||||
struct wl_listener caps_changed_listener;
|
||||
struct wl_listener pointer_focus_listener;
|
||||
struct wl_listener keyboard_focus_listener;
|
||||
struct wl_listener tablet_tool_added_listener;
|
||||
|
||||
struct wl_list link; /** shell::seat_list */
|
||||
};
|
||||
|
||||
struct tablet_tool_listener {
|
||||
struct wl_listener base;
|
||||
struct wl_listener removed_listener;
|
||||
};
|
||||
|
||||
static struct weston_view *
|
||||
shell_fade_create_fade_out_view(struct shell_surface *shsurf,
|
||||
@ -446,6 +463,42 @@ shell_touch_grab_end(struct shell_touch_grab *grab)
|
||||
weston_touch_end_grab(grab->touch);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_tablet_tool_grab_start(struct shell_tablet_tool_grab *grab,
|
||||
const struct weston_tablet_tool_grab_interface *interface,
|
||||
struct shell_surface *shsurf,
|
||||
struct weston_tablet_tool *tool)
|
||||
{
|
||||
struct desktop_shell *shell = shsurf->shell;
|
||||
|
||||
weston_seat_break_desktop_grabs(tool->seat);
|
||||
|
||||
grab->grab.interface = interface;
|
||||
grab->shsurf = shsurf;
|
||||
grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
|
||||
wl_signal_add(&shsurf->destroy_signal, &grab->shsurf_destroy_listener);
|
||||
|
||||
grab->tool = tool;
|
||||
shsurf->grabbed = 1;
|
||||
|
||||
weston_tablet_tool_start_grab(tool, &grab->grab);
|
||||
if (shell->child.desktop_shell)
|
||||
weston_tablet_tool_set_focus(tool,
|
||||
get_default_view(shell->grab_surface),
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_tablet_tool_grab_end(struct shell_tablet_tool_grab *grab)
|
||||
{
|
||||
if (grab->shsurf) {
|
||||
wl_list_remove(&grab->shsurf_destroy_listener.link);
|
||||
grab->shsurf->grabbed = 0;
|
||||
}
|
||||
|
||||
weston_tablet_tool_end_grab(grab->tool);
|
||||
}
|
||||
|
||||
static enum animation_type
|
||||
get_animation_type(char *animation)
|
||||
{
|
||||
@ -1143,6 +1196,148 @@ struct weston_resize_grab {
|
||||
int32_t width, height;
|
||||
};
|
||||
|
||||
static void
|
||||
tablet_tool_noop_grab_proximity_in(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time,
|
||||
struct weston_tablet *tablet)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_move_grab_proximity_out(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time)
|
||||
{
|
||||
struct weston_tablet_tool_move_grab *move =
|
||||
(struct weston_tablet_tool_move_grab *)grab;
|
||||
|
||||
shell_tablet_tool_grab_end(&move->base);
|
||||
free(grab);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_move_grab_up(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time)
|
||||
{
|
||||
struct weston_tablet_tool_move_grab *move =
|
||||
(struct weston_tablet_tool_move_grab *)grab;
|
||||
|
||||
shell_tablet_tool_grab_end(&move->base);
|
||||
free(grab);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_noop_grab_down(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_move_grab_motion(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time,
|
||||
struct weston_coord_global pos)
|
||||
{
|
||||
struct weston_tablet_tool_move_grab *move =
|
||||
(struct weston_tablet_tool_move_grab *)grab;
|
||||
struct shell_surface *shsurf = move->base.shsurf;
|
||||
struct weston_surface *es;
|
||||
|
||||
weston_tablet_tool_cursor_move(grab->tool, pos);
|
||||
|
||||
if (!shsurf)
|
||||
return;
|
||||
|
||||
es = weston_desktop_surface_get_surface(shsurf->desktop_surface);
|
||||
weston_view_set_position(shsurf->view,
|
||||
pos.c.x + wl_fixed_to_double(move->dx),
|
||||
pos.c.y + wl_fixed_to_double(move->dy));
|
||||
weston_compositor_schedule_repaint(es->compositor);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_noop_grab_pressure(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time,
|
||||
uint32_t pressure)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_noop_grab_distance(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time,
|
||||
uint32_t distance)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_noop_grab_tilt(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time,
|
||||
int32_t tilt_x, int32_t tilt_y)
|
||||
{
|
||||
}
|
||||
|
||||
static void tablet_tool_noop_grab_button(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time, uint32_t button,
|
||||
uint32_t state)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_noop_grab_frame(struct weston_tablet_tool_grab *grab,
|
||||
const struct timespec *time)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_move_grab_cancel(struct weston_tablet_tool_grab *grab)
|
||||
{
|
||||
struct weston_tablet_tool_move_grab *move =
|
||||
(struct weston_tablet_tool_move_grab *)grab;
|
||||
|
||||
shell_tablet_tool_grab_end(&move->base);
|
||||
free(grab);
|
||||
}
|
||||
|
||||
static struct weston_tablet_tool_grab_interface tablet_tool_move_grab_interface = {
|
||||
tablet_tool_noop_grab_proximity_in,
|
||||
tablet_tool_move_grab_proximity_out,
|
||||
tablet_tool_move_grab_motion,
|
||||
tablet_tool_noop_grab_down,
|
||||
tablet_tool_move_grab_up,
|
||||
tablet_tool_noop_grab_pressure,
|
||||
tablet_tool_noop_grab_distance,
|
||||
tablet_tool_noop_grab_tilt,
|
||||
tablet_tool_noop_grab_button,
|
||||
tablet_tool_noop_grab_frame,
|
||||
tablet_tool_move_grab_cancel,
|
||||
};
|
||||
|
||||
static int
|
||||
surface_tablet_tool_move(struct shell_surface *shsurf, struct weston_tablet_tool *tool)
|
||||
{
|
||||
struct weston_tablet_tool_move_grab *move;
|
||||
struct weston_coord offset;
|
||||
|
||||
if (!shsurf)
|
||||
return -1;
|
||||
|
||||
if (shsurf->state.fullscreen || shsurf->state.maximized)
|
||||
return 0;
|
||||
|
||||
move = malloc(sizeof(*move));
|
||||
if (!move)
|
||||
return -1;
|
||||
|
||||
offset = weston_coord_sub(shsurf->view->geometry.pos_offset,
|
||||
tool->grab_pos.c);
|
||||
move->dx = wl_fixed_from_double(offset.x);
|
||||
move->dy = wl_fixed_from_double(offset.y);
|
||||
|
||||
shell_tablet_tool_grab_start(&move->base, &tablet_tool_move_grab_interface,
|
||||
shsurf, tool);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resize_grab_motion(struct weston_pointer_grab *grab,
|
||||
const struct timespec *time,
|
||||
@ -1443,6 +1638,26 @@ sync_surface_activated_state(struct shell_surface *shsurf)
|
||||
weston_desktop_surface_set_activated(surface, false);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_tablet_tool_focus(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_tablet_tool *tool = data;
|
||||
struct weston_view *view = tool->focus;
|
||||
struct shell_surface *shsurf;
|
||||
struct weston_desktop_client *client;
|
||||
|
||||
if (!view)
|
||||
return;
|
||||
|
||||
shsurf = get_shell_surface(view->surface);
|
||||
if (!shsurf)
|
||||
return;
|
||||
|
||||
client = weston_desktop_surface_get_client(shsurf->desktop_surface);
|
||||
|
||||
weston_desktop_client_ping(client);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_surface_deactivate(struct shell_surface *shsurf)
|
||||
{
|
||||
@ -1779,11 +1994,43 @@ desktop_shell_destroy_seat(struct shell_seat *shseat)
|
||||
wl_list_remove(&shseat->caps_changed_listener.link);
|
||||
wl_list_remove(&shseat->pointer_focus_listener.link);
|
||||
wl_list_remove(&shseat->seat_destroy_listener.link);
|
||||
wl_list_remove(&shseat->tablet_tool_added_listener.link);
|
||||
|
||||
wl_list_remove(&shseat->link);
|
||||
free(shseat);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_tablet_tool_listener(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct tablet_tool_listener *tool_listener =
|
||||
container_of(listener, struct tablet_tool_listener, removed_listener);
|
||||
|
||||
wl_list_remove(&tool_listener->removed_listener.link);
|
||||
wl_list_remove(&tool_listener->base.link);
|
||||
free(tool_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_tablet_tool_added(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_tablet_tool *tool = data;
|
||||
struct tablet_tool_listener *tool_listener;
|
||||
|
||||
tool_listener = malloc(sizeof *tool_listener);
|
||||
if (!tool_listener) {
|
||||
weston_log("no memory to allocate to shell seat tablet listener\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tool_listener->removed_listener.notify = destroy_tablet_tool_listener;
|
||||
wl_signal_add(&tool->removed_signal,
|
||||
&tool_listener->removed_listener);
|
||||
|
||||
tool_listener->base.notify = handle_tablet_tool_focus;
|
||||
wl_signal_add(&tool->focus_signal, &tool_listener->base);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_shell_seat(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@ -1817,6 +2064,7 @@ static struct shell_seat *
|
||||
create_shell_seat(struct desktop_shell *shell, struct weston_seat *seat)
|
||||
{
|
||||
struct shell_seat *shseat;
|
||||
struct weston_tablet_tool *tool;
|
||||
|
||||
shseat = calloc(1, sizeof *shseat);
|
||||
if (!shseat) {
|
||||
@ -1835,6 +2083,25 @@ create_shell_seat(struct desktop_shell *shell, struct weston_seat *seat)
|
||||
shseat->pointer_focus_listener.notify = handle_pointer_focus;
|
||||
wl_list_init(&shseat->pointer_focus_listener.link);
|
||||
|
||||
shseat->tablet_tool_added_listener.notify = handle_tablet_tool_added;
|
||||
wl_list_init(&shseat->tablet_tool_added_listener.link);
|
||||
|
||||
wl_list_for_each(tool, &seat->tablet_tool_list, link) {
|
||||
struct tablet_tool_listener *listener = malloc(sizeof *listener);
|
||||
|
||||
if (!listener) {
|
||||
weston_log("no memory to allocate to shell seat tablet listener\n");
|
||||
break;
|
||||
}
|
||||
|
||||
listener->removed_listener.notify = destroy_tablet_tool_listener;
|
||||
wl_signal_add(&tool->removed_signal,
|
||||
&listener->removed_listener);
|
||||
|
||||
listener->base.notify = handle_tablet_tool_focus;
|
||||
wl_signal_add(&tool->focus_signal, &listener->base);
|
||||
}
|
||||
|
||||
shseat->caps_changed_listener.notify = shell_seat_caps_changed;
|
||||
wl_signal_add(&seat->updated_caps_signal,
|
||||
&shseat->caps_changed_listener);
|
||||
@ -2303,6 +2570,18 @@ desktop_surface_move(struct weston_desktop_surface *desktop_surface,
|
||||
if ((focus == surface) &&
|
||||
(surface_touch_move(shsurf, touch) < 0))
|
||||
wl_resource_post_no_memory(resource);
|
||||
} else if (!wl_list_empty(&seat->tablet_tool_list)) {
|
||||
struct weston_tablet_tool *tool;
|
||||
|
||||
wl_list_for_each(tool, &seat->tablet_tool_list, link) {
|
||||
if (tool->focus && tool->grab_serial == serial) {
|
||||
focus = weston_surface_get_main_surface(
|
||||
tool->focus->surface);
|
||||
if (focus == surface &&
|
||||
surface_tablet_tool_move(shsurf, tool) < 0)
|
||||
wl_resource_post_no_memory(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -914,6 +914,10 @@ struct weston_tablet_tool {
|
||||
struct wl_listener sprite_destroy_listener;
|
||||
|
||||
struct weston_coord_global pos;
|
||||
struct weston_coord_global grab_pos;
|
||||
|
||||
struct wl_signal focus_signal;
|
||||
struct wl_signal removed_signal;
|
||||
};
|
||||
|
||||
struct weston_tablet {
|
||||
@ -1176,6 +1180,7 @@ struct weston_seat {
|
||||
struct wl_list tablet_list;
|
||||
struct wl_list tablet_tool_list;
|
||||
struct wl_list tablet_seat_resource_list;
|
||||
struct wl_signal tablet_tool_added_signal;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -1535,6 +1535,8 @@ weston_tablet_tool_set_focus(struct weston_tablet_tool *tool,
|
||||
&tool->focus_resource_listener);
|
||||
tool->focus = view;
|
||||
tool->focus_view_listener.notify = tablet_tool_focus_view_destroyed;
|
||||
|
||||
wl_signal_emit(&tool->focus_signal, tool);
|
||||
}
|
||||
|
||||
WL_EXPORT void
|
||||
@ -1823,6 +1825,9 @@ weston_tablet_tool_create(void)
|
||||
tool->default_grab.tool = tool;
|
||||
tool->grab = &tool->default_grab;
|
||||
|
||||
wl_signal_init(&tool->focus_signal);
|
||||
wl_signal_init(&tool->removed_signal);
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
@ -3361,6 +3366,8 @@ notify_tablet_tool_added(struct weston_tablet_tool *tool)
|
||||
struct weston_seat *seat = tool->seat;
|
||||
struct wl_client *client;
|
||||
|
||||
wl_signal_emit(&seat->tablet_tool_added_signal, tool);
|
||||
|
||||
wl_resource_for_each(tablet_seat_resource,
|
||||
&seat->tablet_seat_resource_list) {
|
||||
client = wl_resource_get_client(tablet_seat_resource);
|
||||
@ -3469,6 +3476,7 @@ notify_tablet_tool_down(struct weston_tablet_tool *tool,
|
||||
|
||||
tool->tip_is_down = true;
|
||||
tool->grab_serial = wl_display_get_serial(compositor->wl_display);
|
||||
tool->grab_pos = tool->pos;
|
||||
|
||||
grab->interface->down(grab, time);
|
||||
}
|
||||
@ -4221,6 +4229,8 @@ weston_seat_release_pointer(struct weston_seat *seat)
|
||||
WL_EXPORT void
|
||||
weston_seat_release_tablet_tool(struct weston_tablet_tool *tool)
|
||||
{
|
||||
wl_signal_emit(&tool->removed_signal, tool);
|
||||
|
||||
weston_tablet_tool_destroy(tool);
|
||||
}
|
||||
|
||||
@ -4315,6 +4325,7 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
|
||||
wl_list_init(&seat->tablet_seat_resource_list);
|
||||
wl_list_init(&seat->tablet_list);
|
||||
wl_list_init(&seat->tablet_tool_list);
|
||||
wl_signal_init(&seat->tablet_tool_added_signal);
|
||||
|
||||
seat->global = wl_global_create(ec->wl_display, &wl_seat_interface,
|
||||
MIN(wl_seat_interface.version, 7),
|
||||
|
@ -241,6 +241,10 @@ frame_double_touch_down(struct frame *frame, void *data, int32_t id,
|
||||
void
|
||||
frame_double_touch_up(struct frame *frame, void *data, int32_t id);
|
||||
|
||||
/* May set FRAME_STATUS_REPAINT */
|
||||
enum theme_location
|
||||
frame_tablet_tool_motion(struct frame *frame, void *pointer, int x, int y);
|
||||
|
||||
void
|
||||
frame_repaint(struct frame *frame, cairo_t *cr);
|
||||
|
||||
|
@ -1015,6 +1015,44 @@ frame_double_touch_up(struct frame *frame, void *data, int32_t id)
|
||||
}
|
||||
}
|
||||
|
||||
enum theme_location
|
||||
frame_tablet_tool_motion(struct frame *frame, void *data, int x, int y)
|
||||
{
|
||||
struct frame_pointer *tool_pointer = frame_pointer_get(frame, data);
|
||||
struct frame_button *button,
|
||||
*prev_button = tool_pointer->hover_button;
|
||||
enum theme_location location;
|
||||
|
||||
location = theme_get_location(frame->theme, tool_pointer->x,
|
||||
tool_pointer->y, frame->width,
|
||||
frame->height,
|
||||
frame->flags & FRAME_FLAG_MAXIMIZED ?
|
||||
THEME_FRAME_MAXIMIZED : 0);
|
||||
|
||||
if (!tool_pointer)
|
||||
return location;
|
||||
|
||||
tool_pointer->x = x;
|
||||
tool_pointer->y = y;
|
||||
|
||||
button = frame_find_button(frame, x, y);
|
||||
|
||||
if (prev_button) {
|
||||
if (prev_button == button)
|
||||
/* The button hasn't changed so we're done here */
|
||||
return location;
|
||||
else
|
||||
frame_button_leave(prev_button, tool_pointer);
|
||||
}
|
||||
|
||||
if (button)
|
||||
frame_button_enter(button);
|
||||
|
||||
tool_pointer->hover_button = button;
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
void
|
||||
frame_repaint(struct frame *frame, cairo_t *cr)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user