Skip to content
Commits on Source (13)
......@@ -53,6 +53,7 @@
#include "window.h"
#include "tablet-unstable-v2-client-protocol.h"
#include "weston-desktop-shell-client-protocol.h"
#define DEFAULT_CLOCK_FORMAT CLOCK_FORMAT_MINUTES
......@@ -374,6 +375,56 @@ panel_launcher_touch_up_handler(struct widget *widget, struct input *input,
panel_launcher_activate(launcher);
}
static void
panel_launcher_tablet_tool_proximity_in_handler(struct widget *widget,
struct tablet_tool *tool,
struct tablet *tablet, void *data)
{
struct panel_launcher *launcher;
launcher = widget_get_user_data(widget);
launcher->focused = 1;
widget_schedule_redraw(widget);
}
static void
panel_launcher_tablet_tool_proximity_out_handler(struct widget *widget,
struct tablet_tool *tool, void *data)
{
struct panel_launcher *launcher;
launcher = widget_get_user_data(widget);
launcher->focused = 0;
widget_schedule_redraw(widget);
}
static void
panel_launcher_tablet_tool_up_handler(struct widget *widget,
struct tablet_tool *tool,
void *data)
{
struct panel_launcher *launcher;
launcher = widget_get_user_data(widget);
panel_launcher_activate(launcher);
}
static void
panel_launcher_tablet_tool_button_handler(struct widget *widget,
struct tablet_tool *tool,
uint32_t button,
uint32_t state_w,
void *data)
{
struct panel_launcher *launcher;
enum zwp_tablet_tool_v2_button_state state = state_w;
launcher = widget_get_user_data(widget);
if (state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED)
panel_launcher_activate(launcher);
}
static void
clock_func(struct toytimer *tt)
{
......@@ -706,6 +757,13 @@ panel_add_launcher(struct panel *panel, const char *icon, const char *path, cons
panel_launcher_touch_down_handler);
widget_set_touch_up_handler(launcher->widget,
panel_launcher_touch_up_handler);
widget_set_tablet_tool_up_handler(launcher->widget,
panel_launcher_tablet_tool_up_handler);
widget_set_tablet_tool_proximity_handlers(launcher->widget,
panel_launcher_tablet_tool_proximity_in_handler,
panel_launcher_tablet_tool_proximity_out_handler);
widget_set_tablet_tool_button_handler(launcher->widget,
panel_launcher_tablet_tool_button_handler);
widget_set_redraw_handler(launcher->widget,
panel_launcher_redraw_handler);
widget_set_motion_handler(launcher->widget,
......
......@@ -12,6 +12,8 @@ srcs_toytoolkit = [
relative_pointer_unstable_v1_protocol_c,
pointer_constraints_unstable_v1_client_protocol_h,
pointer_constraints_unstable_v1_protocol_c,
tablet_unstable_v2_client_protocol_h,
tablet_unstable_v2_protocol_c,
ivi_application_client_protocol_h,
ivi_application_protocol_c,
viewporter_client_protocol_h,
......@@ -328,6 +330,13 @@ demo_clients = [
'basename': 'subsurfaces',
'deps': [ 'egl', 'glesv2', 'wayland-egl' ]
},
{
'basename': 'tablet',
'add_sources': [
tablet_unstable_v2_client_protocol_h,
tablet_unstable_v2_protocol_c,
],
},
{ 'basename': 'transformed' },
]
......@@ -373,6 +382,8 @@ if get_option('shell-desktop')
'desktop-shell.c',
weston_desktop_shell_client_protocol_h,
weston_desktop_shell_protocol_c,
tablet_unstable_v2_client_protocol_h,
tablet_unstable_v2_protocol_c,
include_directories: common_inc,
dependencies: dep_toytoolkit,
install_dir: get_option('libexecdir'),
......
/*
* Copyright © 2014 Lyude
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE
*/
#include "config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cairo.h>
#include <math.h>
#include <assert.h>
#include <stdbool.h>
#include <linux/input.h>
#include <wayland-client.h>
#include "window.h"
#include "tablet-unstable-v2-client-protocol.h"
struct display *display;
struct window *window;
struct widget *widget;
cairo_surface_t *draw_buffer;
int old_x, old_y;
int current_x, current_y;
enum zwp_tablet_tool_v2_type tool_type;
bool tablet_is_down;
double current_pressure;
#define WL_TABLET_AXIS_MAX 65535
static void
redraw_handler(struct widget *widget, void *data)
{
cairo_surface_t *surface;
cairo_t *window_cr, *drawing_cr;
struct rectangle allocation;
widget_get_allocation(widget, &allocation);
surface = window_get_surface(window);
/* Setup the background */
window_cr = cairo_create(surface);
cairo_set_operator(window_cr, CAIRO_OPERATOR_SOURCE);
cairo_rectangle(window_cr,
allocation.x,
allocation.y,
allocation.width,
allocation.height);
cairo_set_source_rgba(window_cr, 0, 0, 0, 0.8);
cairo_fill(window_cr);
/* Update the drawing buffer */
if (tablet_is_down) {
if (old_x != -1 && old_y != -1) {
drawing_cr = cairo_create(draw_buffer);
if (tool_type == ZWP_TABLET_TOOL_V2_TYPE_PEN) {
cairo_set_source_rgb(drawing_cr, 1, 1, 1);
cairo_set_line_width(drawing_cr,
current_pressure /
WL_TABLET_AXIS_MAX * 7 + 1);
} else if (tool_type == ZWP_TABLET_TOOL_V2_TYPE_ERASER) {
cairo_set_operator(drawing_cr, CAIRO_OPERATOR_CLEAR);
cairo_set_source_rgb(drawing_cr, 0, 0, 0);
cairo_set_line_width(drawing_cr,
current_pressure /
WL_TABLET_AXIS_MAX * 30 + 10);
}
cairo_set_line_cap(drawing_cr, CAIRO_LINE_CAP_ROUND);
cairo_translate(drawing_cr,
-allocation.x,
-allocation.y);
cairo_move_to(drawing_cr, old_x, old_y);
cairo_line_to(drawing_cr, current_x, current_y);
cairo_stroke(drawing_cr);
cairo_destroy(drawing_cr);
}
old_x = current_x;
old_y = current_y;
}
/* Squash the drawing buffer onto the window's buffer */
cairo_set_source_surface(window_cr,
draw_buffer,
allocation.x,
allocation.y);
cairo_set_operator(window_cr, CAIRO_OPERATOR_ADD);
cairo_rectangle(window_cr,
allocation.x,
allocation.y,
allocation.width,
allocation.height);
cairo_clip(window_cr);
cairo_paint(window_cr);
cairo_destroy(window_cr);
cairo_surface_destroy(surface);
}
static void
resize_handler(struct widget *widget,
int32_t width, int32_t height,
void *data)
{
cairo_surface_t *tmp_buffer;
cairo_t *cr;
tmp_buffer = draw_buffer;
draw_buffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
width, height);
cr = cairo_create(draw_buffer);
cairo_set_source_rgba(cr, 0, 0, 0, 0);
cairo_rectangle(cr, 0, 0, width, height);
cairo_fill(cr);
if (tmp_buffer) {
cairo_set_source_surface(cr, tmp_buffer, 0, 0);
cairo_rectangle(cr, 0, 0, width, height);
cairo_clip(cr);
cairo_paint(cr);
}
cairo_destroy(cr);
cairo_surface_destroy(tmp_buffer);
}
static void
proximity_in_handler(struct widget *widget, struct tablet_tool *tool,
struct tablet *tablet, void *data)
{
tool_type = tablet_tool_get_type(tool);
}
static void
pressure_handler(struct widget *widget, struct tablet_tool *tool,
uint32_t pressure, void *data)
{
current_pressure = pressure;
}
static int
tablet_motion_handler(struct widget *widget, struct tablet_tool *tool,
float x, float y, void *data)
{
int cursor;
current_x = x;
current_y = y;
if (tablet_is_down) {
widget_schedule_redraw(widget);
cursor = CURSOR_HAND1;
} else {
cursor = CURSOR_LEFT_PTR;
}
return cursor;
}
static void
tablet_down_handler(struct widget *widget, struct tablet_tool *tool, void *data)
{
tablet_is_down = true;
}
static void
tablet_up_handler(struct widget *widget, struct tablet_tool *tool, void *data)
{
tablet_is_down = false;
old_x = -1;
old_y = -1;
}
static void
init_globals(void)
{
window = window_create(display);
widget = window_frame_create(window, NULL);
window_set_title(window, "Wayland Tablet Demo");
old_x = -1;
old_y = -1;
widget_set_tablet_tool_axis_handlers(widget,
tablet_motion_handler,
pressure_handler,
NULL, NULL,
NULL, NULL, NULL);
widget_set_tablet_tool_down_handler(widget, tablet_down_handler);
widget_set_tablet_tool_up_handler(widget, tablet_up_handler);
widget_set_tablet_tool_proximity_handlers(widget,
proximity_in_handler,
NULL);
widget_set_redraw_handler(widget, redraw_handler);
widget_set_resize_handler(widget, resize_handler);
widget_schedule_resize(widget, 1000, 800);
}
static void
cleanup(void)
{
widget_destroy(widget);
window_destroy(window);
}
int
main(int argc, char *argv[])
{
display = display_create(&argc, argv);
if (display == NULL) {
fprintf(stderr, "failed to create display: %m\n");
return -1;
}
init_globals();
display_run(display);
cleanup();
display_destroy(display);
return 0;
}
This diff is collapsed.
......@@ -40,6 +40,8 @@ struct widget;
struct display;
struct input;
struct output;
struct tablet;
struct tablet_tool;
struct task {
void (*run)(struct task *task, uint32_t events);
......@@ -265,6 +267,57 @@ typedef void (*widget_axis_handler_t)(struct widget *widget,
uint32_t axis,
wl_fixed_t value,
void *data);
typedef int (*widget_tablet_tool_motion_handler_t)(struct widget *widget,
struct tablet_tool *tool,
float x, float y,
void *data);
typedef void (*widget_tablet_tool_down_handler_t)(struct widget *widget,
struct tablet_tool *tool,
void *data);
typedef void (*widget_tablet_tool_up_handler_t)(struct widget *widget,
struct tablet_tool *tool,
void *data);
typedef void (*widget_tablet_tool_pressure_handler_t)(struct widget *widget,
struct tablet_tool *tool,
uint32_t pressure,
void *data);
typedef void (*widget_tablet_tool_distance_handler_t)(struct widget *widget,
struct tablet_tool *tool,
uint32_t distance,
void *data);
typedef void (*widget_tablet_tool_tilt_handler_t)(struct widget *widget,
struct tablet_tool *tool,
int32_t tilt_x, int32_t tilt_y,
void *data);
typedef void (*widget_tablet_tool_rotation_handler_t)(struct widget *widget,
struct tablet_tool *tool,
int32_t rotation,
void *data);
typedef void (*widget_tablet_tool_slider_handler_t)(struct widget *widget,
struct tablet_tool *tool,
int32_t slider,
void *data);
typedef void (*widget_tablet_tool_wheel_handler_t)(struct widget *widget,
struct tablet_tool *tool,
wl_fixed_t degrees,
int32_t clicks,
void *data);
typedef void (*widget_tablet_tool_proximity_in_handler_t)(struct widget *widget,
struct tablet_tool *tool,
struct tablet *tablet,
void *data);
typedef void (*widget_tablet_tool_proximity_out_handler_t)(struct widget *widget,
struct tablet_tool *tool,
void *data);
typedef void (*widget_tablet_tool_button_handler_t)(struct widget *widget,
struct tablet_tool *tool,
uint32_t button,
uint32_t state,
void *data);
typedef void (*widget_tablet_tool_frame_handler_t)(struct widget *widget,
struct tablet_tool *tool,
uint32_t time,
void *data);
typedef void (*widget_pointer_frame_handler_t)(struct widget *widget,
struct input *input,
......@@ -506,6 +559,8 @@ widget_destroy(struct widget *widget);
void
widget_set_default_cursor(struct widget *widget, int cursor);
void
widget_set_default_tablet_cursor(struct widget *widget, int cursor);
void
widget_get_allocation(struct widget *widget, struct rectangle *allocation);
void
......@@ -578,6 +633,31 @@ widget_set_axis_handlers(struct widget *widget,
widget_axis_source_handler_t axis_source_handler,
widget_axis_stop_handler_t axis_stop_handler,
widget_axis_discrete_handler_t axis_discrete_handler);
void
widget_set_tablet_tool_axis_handlers(struct widget *widget,
widget_tablet_tool_motion_handler_t motion,
widget_tablet_tool_pressure_handler_t pressure,
widget_tablet_tool_distance_handler_t distance,
widget_tablet_tool_tilt_handler_t tilt,
widget_tablet_tool_rotation_handler_t rotation,
widget_tablet_tool_slider_handler_t slider,
widget_tablet_tool_wheel_handler_t wheel);
void
widget_set_tablet_tool_up_handler(struct widget *widget,
widget_tablet_tool_up_handler_t handler);
void
widget_set_tablet_tool_down_handler(struct widget *widget,
widget_tablet_tool_down_handler_t handler);
void
widget_set_tablet_tool_proximity_handlers(struct widget *widget,
widget_tablet_tool_proximity_in_handler_t in_handler,
widget_tablet_tool_proximity_out_handler_t out_handler);
void
widget_set_tablet_tool_button_handler(struct widget *widget,
widget_tablet_tool_button_handler_t handler);
void
widget_set_tablet_tool_frame_handler(struct widget *widget,
widget_tablet_tool_frame_handler_t handler);
void
window_inhibit_redraw(struct window *window);
......@@ -701,6 +781,18 @@ xkb_mod_mask_t
keysym_modifiers_get_mask(struct wl_array *modifiers_map,
const char *name);
uint32_t
tablet_tool_get_type(struct tablet_tool *tool);
uint64_t
tablet_tool_get_serial(struct tablet_tool *tool);
uint64_t
tablet_tool_get_hwid(struct tablet_tool *tool);
void
tablet_tool_set_cursor_image(struct tablet_tool *tool, int cursor);
struct toytimer;
typedef void (*toytimer_cb)(struct toytimer *);
......
......@@ -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);
}
}
}
}
......@@ -3557,6 +3836,20 @@ touch_to_activate_binding(struct weston_touch *touch,
WESTON_ACTIVATE_FLAG_CONFIGURE);
}
static void
tablet_tool_activate_binding(struct weston_tablet_tool *tool,
uint32_t button, void *data)
{
if (tool->grab != &tool->default_grab)
return;
if (tool->focus == NULL)
return;
activate_binding(tool->seat, data, tool->focus,
WESTON_ACTIVATE_FLAG_CLICKED |
WESTON_ACTIVATE_FLAG_CONFIGURE);
}
static void
unfocus_all_seats(struct desktop_shell *shell)
{
......@@ -4660,6 +4953,8 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
weston_compositor_add_touch_binding(ec, 0,
touch_to_activate_binding,
shell);
weston_compositor_add_tablet_tool_binding(ec, BTN_TOUCH, 0,
tablet_tool_activate_binding, shell);
weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
backlight_binding, ec);
weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
......
......@@ -674,6 +674,46 @@ struct weston_touch_grab {
struct weston_touch *touch;
};
struct weston_tablet;
struct weston_tablet_tool;
struct weston_tablet_tool_grab;
struct weston_tablet_tool_grab_interface {
void (*proximity_in)(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
struct weston_tablet *tablet);
void (*proximity_out)(struct weston_tablet_tool_grab *grab,
const struct timespec *time);
void (*motion)(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
struct weston_coord_global pos);
void (*down)(struct weston_tablet_tool_grab *grab,
const struct timespec *time);
void (*up)(struct weston_tablet_tool_grab *grab,
const struct timespec *time);
void (*pressure)(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
uint32_t pressure);
void (*distance)(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
uint32_t distance);
void (*tilt)(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
wl_fixed_t tilt_x,
wl_fixed_t tilt_y);
void (*button)(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
uint32_t button,
uint32_t state);
void (*frame)(struct weston_tablet_tool_grab *grab,
const struct timespec *time);
void (*cancel)(struct weston_tablet_tool_grab *grab);
};
struct weston_tablet_tool_grab {
const struct weston_tablet_tool_grab_interface *interface;
struct weston_tablet_tool *tool;
};
struct weston_data_offer {
struct wl_resource *resource;
struct weston_data_source *source;
......@@ -842,6 +882,58 @@ struct weston_touch {
struct wl_list timestamps_list;
};
struct weston_tablet_tool {
struct weston_seat *seat;
uint32_t type;
struct weston_tablet *current_tablet;
struct wl_list resource_list;
struct wl_list focus_resource_list;
struct weston_view *focus;
struct wl_listener focus_view_listener;
struct wl_listener focus_resource_listener;
uint32_t focus_serial;
uint32_t grab_serial;
struct wl_list link;
uint64_t serial;
uint64_t hwid;
uint32_t capabilities;
struct weston_tablet_tool_grab *grab;
struct weston_tablet_tool_grab default_grab;
int button_count;
bool tip_is_down;
struct timespec frame_time;
struct weston_view *sprite;
struct weston_coord_surface hotspot;
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 {
struct weston_seat *seat;
struct wl_list resource_list;
struct wl_list tool_list;
struct wl_list link;
char *name;
uint32_t vid;
uint32_t pid;
const char *path;
};
struct weston_coord_global
weston_pointer_motion_to_abs(struct weston_pointer *pointer,
struct weston_pointer_motion_event *event);
......@@ -929,6 +1021,64 @@ void
weston_touch_send_frame(struct weston_touch *touch);
void
weston_tablet_tool_set_focus(struct weston_tablet_tool *tool,
struct weston_view *view,
const struct timespec *time);
void
weston_tablet_tool_start_grab(struct weston_tablet_tool *tool,
struct weston_tablet_tool_grab *grab);
void
weston_tablet_tool_end_grab(struct weston_tablet_tool *tool);
void
weston_tablet_tool_send_proximity_out(struct weston_tablet_tool *tool,
const struct timespec *time);
void
weston_tablet_tool_send_motion(struct weston_tablet_tool *tool,
const struct timespec *time,
struct weston_coord_global pos);
void
weston_tablet_tool_send_down(struct weston_tablet_tool *tool,
const struct timespec *time);
void
weston_tablet_tool_send_up(struct weston_tablet_tool *tool,
const struct timespec *time);
void
weston_tablet_tool_send_pressure(struct weston_tablet_tool *tool,
const struct timespec *time,
uint32_t pressure);
void
weston_tablet_tool_send_distance(struct weston_tablet_tool *tool,
const struct timespec *time,
uint32_t distance);
void
weston_tablet_tool_send_tilt(struct weston_tablet_tool *tool,
const struct timespec *time,
wl_fixed_t tilt_x, wl_fixed_t tilt_y);
void
weston_tablet_tool_send_button(struct weston_tablet_tool *tool,
const struct timespec *time,
uint32_t button, uint32_t state);
void
weston_tablet_tool_send_frame(struct weston_tablet_tool *tool,
const struct timespec *time);
void
weston_tablet_tool_cursor_move(struct weston_tablet_tool *tool,
struct weston_coord_global pos);
void
weston_seat_set_selection(struct weston_seat *seat,
struct weston_data_source *source, uint32_t serial);
......@@ -1026,6 +1176,11 @@ struct weston_seat {
struct input_method *input_method;
char *seat_name;
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 {
......@@ -1255,6 +1410,7 @@ struct weston_compositor {
struct wl_list modifier_binding_list;
struct wl_list button_binding_list;
struct wl_list touch_binding_list;
struct wl_list tablet_tool_binding_list;
struct wl_list axis_binding_list;
struct wl_list debug_binding_list;
......@@ -1307,6 +1463,9 @@ struct weston_compositor {
void *user_data;
void (*exit)(struct weston_compositor *c);
struct wl_global *tablet_manager;
struct wl_list tablet_manager_resource_list;
/* Whether to let the compositor run without any input device. */
bool require_input;
......@@ -1931,6 +2090,16 @@ weston_compositor_add_touch_binding(struct weston_compositor *compositor,
weston_touch_binding_handler_t binding,
void *data);
typedef void (*weston_tablet_tool_binding_handler_t)(struct weston_tablet_tool *tool,
uint32_t button,
void *data);
struct weston_binding *
weston_compositor_add_tablet_tool_binding(struct weston_compositor *compositor,
uint32_t button,
enum weston_keyboard_modifier modifier,
weston_tablet_tool_binding_handler_t binding,
void *data);
typedef void (*weston_axis_binding_handler_t)(struct weston_pointer *pointer,
const struct timespec *time,
struct weston_pointer_axis_event *event,
......
......@@ -256,4 +256,46 @@ notify_touch_calibrator_cancel(struct weston_touch_device *device);
void
notify_touch_calibrator_frame(struct weston_touch_device *device);
void
notify_tablet_added(struct weston_tablet *tablet);
void
notify_tablet_tool_added(struct weston_tablet_tool *tool);
void
notify_tablet_tool_proximity_in(struct weston_tablet_tool *tool,
const struct timespec *time,
struct weston_tablet *tablet);
void
notify_tablet_tool_proximity_out(struct weston_tablet_tool *tool,
const struct timespec *time);
void
notify_tablet_tool_motion(struct weston_tablet_tool *tool,
const struct timespec *time,
struct weston_coord_global pos);
void
notify_tablet_tool_pressure(struct weston_tablet_tool *tool,
const struct timespec *time, uint32_t pressure);
void
notify_tablet_tool_distance(struct weston_tablet_tool *tool,
const struct timespec *time, uint32_t distance);
void
notify_tablet_tool_tilt(struct weston_tablet_tool *tool,
const struct timespec *time,
int32_t tilt_x, int32_t tilt_y);
void
notify_tablet_tool_button(struct weston_tablet_tool *tool,
const struct timespec *time,
uint32_t button,
uint32_t state);
void
notify_tablet_tool_up(struct weston_tablet_tool *tool,
const struct timespec *time);
void
notify_tablet_tool_down(struct weston_tablet_tool *tool,
const struct timespec *time);
void
notify_tablet_tool_frame(struct weston_tablet_tool *tool,
const struct timespec *time);
#endif
......@@ -33,6 +33,7 @@
#include "libweston-internal.h"
#include "shared/helpers.h"
#include "shared/timespec-util.h"
#include "tablet-unstable-v2-server-protocol.h"
struct weston_binding {
uint32_t key;
......@@ -137,6 +138,24 @@ weston_compositor_add_touch_binding(struct weston_compositor *compositor,
return binding;
}
WL_EXPORT struct weston_binding *
weston_compositor_add_tablet_tool_binding(struct weston_compositor *compositor,
uint32_t button, uint32_t modifier,
weston_tablet_tool_binding_handler_t handler,
void *data)
{
struct weston_binding *binding;
binding = weston_compositor_add_binding(compositor, 0, button, 0,
modifier, handler, data);
if (binding == NULL)
return NULL;
wl_list_insert(compositor->tablet_tool_binding_list.prev, &binding->link);
return binding;
}
WL_EXPORT struct weston_binding *
weston_compositor_add_axis_binding(struct weston_compositor *compositor,
uint32_t axis, uint32_t modifier,
......@@ -395,6 +414,25 @@ weston_compositor_run_touch_binding(struct weston_compositor *compositor,
}
}
void
weston_compositor_run_tablet_tool_binding(struct weston_compositor *compositor,
struct weston_tablet_tool *tool,
uint32_t button, uint32_t state_w)
{
enum zwp_tablet_tool_v2_button_state state = state_w;
struct weston_binding *b;
if (state != ZWP_TABLET_TOOL_V2_BUTTON_STATE_PRESSED)
return;
wl_list_for_each(b, &compositor->tablet_tool_binding_list, link) {
if (b->modifier == tool->seat->modifier_state) {
weston_tablet_tool_binding_handler_t handler = b->handler;
handler(tool, button, b->data);
}
}
}
int
weston_compositor_run_axis_binding(struct weston_compositor *compositor,
struct weston_pointer *pointer,
......
......@@ -2063,6 +2063,7 @@ weston_view_unmap(struct weston_view *view)
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
struct weston_keyboard *keyboard =
weston_seat_get_keyboard(seat);
struct weston_tablet_tool *tool;
if (keyboard && keyboard->focus == view->surface)
weston_keyboard_set_focus(keyboard, NULL);
......@@ -2070,6 +2071,11 @@ weston_view_unmap(struct weston_view *view)
weston_pointer_clear_focus(pointer);
if (touch && touch->focus == view)
weston_touch_set_focus(touch, NULL);
wl_list_for_each(tool, &seat->tablet_tool_list, link) {
if (tool->focus == view)
weston_tablet_tool_set_focus(tool, NULL, 0);
}
}
}
weston_signal_emit_mutable(&view->unmap_signal, view);
......@@ -8533,8 +8539,10 @@ weston_compositor_create(struct wl_display *display,
wl_list_init(&ec->modifier_binding_list);
wl_list_init(&ec->button_binding_list);
wl_list_init(&ec->touch_binding_list);
wl_list_init(&ec->tablet_tool_binding_list);
wl_list_init(&ec->axis_binding_list);
wl_list_init(&ec->debug_binding_list);
wl_list_init(&ec->tablet_manager_resource_list);
wl_list_init(&ec->plugin_api_list);
......
......@@ -241,6 +241,104 @@ static const struct weston_touch_grab_interface weston_desktop_seat_touch_popup_
.cancel = weston_desktop_seat_popup_grab_touch_cancel,
};
static void
weston_desktop_seat_popup_grab_tablet_tool_proximity_in(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
struct weston_tablet *tablet)
{
}
static void
weston_desktop_seat_popup_grab_tablet_tool_proximity_out(struct weston_tablet_tool_grab *grab,
const struct timespec *time)
{
weston_tablet_tool_send_proximity_out(grab->tool, time);
}
static void
weston_desktop_seat_popup_grab_tablet_tool_motion(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
struct weston_coord_global pos)
{
weston_tablet_tool_send_motion(grab->tool, time, pos);
}
static void
weston_desktop_seat_popup_grab_tablet_tool_down(struct weston_tablet_tool_grab *grab,
const struct timespec *time)
{
weston_tablet_tool_send_down(grab->tool, time);
}
static void
weston_desktop_seat_popup_grab_tablet_tool_up(struct weston_tablet_tool_grab *grab,
const struct timespec *time)
{
weston_tablet_tool_send_up(grab->tool, time);
}
static void
weston_desktop_seat_popup_grab_tablet_tool_pressure(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
uint32_t pressure)
{
weston_tablet_tool_send_pressure(grab->tool, time, pressure);
}
static void
weston_desktop_seat_popup_grab_tablet_tool_distance(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
uint32_t distance)
{
weston_tablet_tool_send_distance(grab->tool, time, distance);
}
static void
weston_desktop_seat_popup_grab_tablet_tool_tilt(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
wl_fixed_t tilt_x, wl_fixed_t tilt_y)
{
weston_tablet_tool_send_tilt(grab->tool, time, tilt_x, tilt_y);
}
static void
weston_desktop_seat_popup_grab_tablet_tool_button(struct weston_tablet_tool_grab *grab,
const struct timespec *time,
uint32_t button, uint32_t state)
{
weston_tablet_tool_send_button(grab->tool, time, button, state);
}
static void
weston_desktop_seat_popup_grab_tablet_tool_frame(struct weston_tablet_tool_grab *grab,
const struct timespec *time)
{
weston_tablet_tool_send_frame(grab->tool, time);
}
static void
weston_desktop_seat_popup_grab_tablet_tool_cancel(struct weston_tablet_tool_grab *grab)
{
struct weston_desktop_seat *seat =
wl_container_of(grab, seat, popup_grab.pointer);
weston_desktop_seat_popup_grab_end(seat);
}
static const struct weston_tablet_tool_grab_interface weston_desktop_seat_tablet_tool_popup_grab_interface = {
weston_desktop_seat_popup_grab_tablet_tool_proximity_in,
weston_desktop_seat_popup_grab_tablet_tool_proximity_out,
weston_desktop_seat_popup_grab_tablet_tool_motion,
weston_desktop_seat_popup_grab_tablet_tool_down,
weston_desktop_seat_popup_grab_tablet_tool_up,
weston_desktop_seat_popup_grab_tablet_tool_pressure,
weston_desktop_seat_popup_grab_tablet_tool_distance,
weston_desktop_seat_popup_grab_tablet_tool_tilt,
weston_desktop_seat_popup_grab_tablet_tool_button,
weston_desktop_seat_popup_grab_tablet_tool_frame,
weston_desktop_seat_popup_grab_tablet_tool_cancel,
};
static void
weston_desktop_seat_destroy(struct wl_listener *listener, void *data)
{
......@@ -318,13 +416,34 @@ weston_desktop_seat_popup_grab_start(struct weston_desktop_seat *seat,
struct weston_keyboard *keyboard = weston_seat_get_keyboard(wseat);
struct weston_pointer *pointer = weston_seat_get_pointer(wseat);
struct weston_touch *touch = weston_seat_get_touch(wseat);
struct weston_tablet_tool *tool;
bool tool_found = false;
if (wseat) {
wl_list_for_each(tool, &wseat->tablet_tool_list, link) {
if (tool->grab_serial == serial) {
tool_found = true;
break;
}
}
}
if ((keyboard == NULL || keyboard->grab_serial != serial) &&
(pointer == NULL || pointer->grab_serial != serial) &&
(touch == NULL || touch->grab_serial != serial)) {
(touch == NULL || touch->grab_serial != serial) &&
!tool_found) {
return false;
}
wl_list_for_each(tool, &wseat->tablet_tool_list, link) {
if (tool->grab->interface != &weston_desktop_seat_tablet_tool_popup_grab_interface) {
struct weston_tablet_tool_grab *grab = zalloc(sizeof(*grab));
grab->interface = &weston_desktop_seat_tablet_tool_popup_grab_interface;
weston_tablet_tool_start_grab(tool, grab);
}
}
seat->popup_grab.initial_up =
(pointer == NULL || pointer->button_count == 0);
seat->popup_grab.client = client;
......@@ -360,6 +479,7 @@ weston_desktop_seat_popup_grab_end(struct weston_desktop_seat *seat)
struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat->seat);
struct weston_pointer *pointer = weston_seat_get_pointer(seat->seat);
struct weston_touch *touch = weston_seat_get_touch(seat->seat);
struct weston_tablet_tool *tool;
while (!wl_list_empty(&seat->popup_grab.surfaces)) {
struct wl_list *link = seat->popup_grab.surfaces.prev;
......@@ -392,6 +512,14 @@ weston_desktop_seat_popup_grab_end(struct weston_desktop_seat *seat)
touch->grab->interface == &weston_desktop_seat_touch_popup_grab_interface)
weston_touch_end_grab(touch);
wl_list_for_each(tool, &seat->seat->tablet_tool_list, link) {
if (tool->grab->interface == &weston_desktop_seat_tablet_tool_popup_grab_interface) {
struct weston_tablet_tool_grab *grab = tool->grab;
weston_tablet_tool_end_grab(tool);
free(grab);
}
}
seat->popup_grab.client = NULL;
if (seat->popup_grab.grab_surface) {
seat->popup_grab.grab_surface = NULL;
......
This diff is collapsed.
......@@ -45,6 +45,13 @@
#include "shared/helpers.h"
#include "shared/timespec-util.h"
#include "tablet-unstable-v2-server-protocol.h"
struct tablet_output_listener {
struct wl_listener base;
struct wl_list tablet_list;
};
void
evdev_led_update(struct evdev_device *device, enum weston_led weston_leds)
{
......@@ -509,6 +516,247 @@ handle_touch_frame(struct libinput_device *libinput_device,
notify_touch_frame(device->touch_device);
}
static void
process_tablet_axis(struct weston_output *output, struct weston_tablet *tablet,
struct weston_tablet_tool *tool,
struct libinput_event_tablet_tool *axis_event)
{
struct timespec time;
const int NORMALIZED_AXIS_MAX = 65535;
timespec_from_usec(&time,
libinput_event_tablet_tool_get_time(axis_event));
if (libinput_event_tablet_tool_x_has_changed(axis_event) ||
libinput_event_tablet_tool_y_has_changed(axis_event)) {
double x, y;
uint32_t width, height;
struct weston_coord_global pos;
width = output->current_mode->width;
height = output->current_mode->height;
x = libinput_event_tablet_tool_get_x_transformed(axis_event,
width);
y = libinput_event_tablet_tool_get_y_transformed(axis_event,
height);
pos = weston_coord_global_from_output_point(x, y, output);
notify_tablet_tool_motion(tool, &time, pos);
}
if (libinput_event_tablet_tool_pressure_has_changed(axis_event)) {
double pressure;
pressure = libinput_event_tablet_tool_get_pressure(axis_event);
/* convert axis range [0.0, 1.0] to [0, 65535] */
pressure *= NORMALIZED_AXIS_MAX;
notify_tablet_tool_pressure(tool, &time, pressure);
}
if (libinput_event_tablet_tool_distance_has_changed(axis_event)) {
double distance;
distance = libinput_event_tablet_tool_get_distance(axis_event);
/* convert axis range [0.0, 1.0] to [0, 65535] */
distance *= NORMALIZED_AXIS_MAX;
notify_tablet_tool_distance(tool, &time, distance);
}
if (libinput_event_tablet_tool_tilt_x_has_changed(axis_event) ||
libinput_event_tablet_tool_tilt_y_has_changed(axis_event)) {
double tx, ty;
tx = libinput_event_tablet_tool_get_tilt_x(axis_event);
ty = libinput_event_tablet_tool_get_tilt_y(axis_event);
notify_tablet_tool_tilt(tool, &time,
wl_fixed_from_double(tx),
wl_fixed_from_double(ty));
}
}
static void
idle_notify_tablet_tool_frame(void *data)
{
struct weston_tablet_tool *tool = data;
notify_tablet_tool_frame(tool, &tool->frame_time);
timespec_from_nsec(&tool->frame_time, 0);
}
/*
* libinput does not provide frame information. So assume that all events that
* belong to the same hardware event have the same timestamp and are created
* together. Use an idle callback to delay the frame event until all events that
* blong together have been handled.
*/
static void
async_notify_tablet_tool_frame(struct weston_tablet_tool *tool,
struct timespec *time)
{
if (timespec_eq(&tool->frame_time, time))
return;
/* If this is a second timestamp, then push out the first frame and use
* the already queued callback for the new timestamp. Otherwise queue a
* new callback. */
if (!timespec_is_zero(&tool->frame_time))
notify_tablet_tool_frame(tool, &tool->frame_time);
else {
struct wl_event_loop *loop;
loop = wl_display_get_event_loop(tool->seat->compositor->wl_display);
wl_event_loop_add_idle(loop, idle_notify_tablet_tool_frame, tool);
}
tool->frame_time = *time;
}
static void
handle_tablet_proximity(struct libinput_device *libinput_device,
struct libinput_event_tablet_tool *proximity_event)
{
struct evdev_device *device;
struct weston_tablet *tablet;
struct weston_tablet_tool *tool;
struct libinput_tablet_tool *libinput_tool;
struct timespec time;
device = libinput_device_get_user_data(libinput_device);
timespec_from_usec(&time,
libinput_event_tablet_tool_get_time(proximity_event));
libinput_tool = libinput_event_tablet_tool_get_tool(proximity_event);
tool = libinput_tablet_tool_get_user_data(libinput_tool);
tablet = device->tablet;
if (libinput_event_tablet_tool_get_proximity_state(proximity_event) ==
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT) {
notify_tablet_tool_proximity_out(tool, &time);
async_notify_tablet_tool_frame(tool, &time);
return;
}
if (!tool) {
uint64_t serial;
enum libinput_tablet_tool_type libinput_tool_type;
uint32_t type;
serial = libinput_tablet_tool_get_serial(libinput_tool);
libinput_tool_type = libinput_tablet_tool_get_type(libinput_tool);
switch (libinput_tool_type) {
case LIBINPUT_TABLET_TOOL_TYPE_PEN:
type = ZWP_TABLET_TOOL_V2_TYPE_PEN;
break;
case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
type = ZWP_TABLET_TOOL_V2_TYPE_ERASER;
break;
default:
weston_log("Unknown libinput tool type %d\n",
libinput_tool_type);
return;
}
tool = weston_seat_add_tablet_tool(device->seat);
tool->serial = serial;
tool->hwid = libinput_tablet_tool_get_tool_id(libinput_tool);
tool->type = type;
tool->capabilities = 0;
if (libinput_tablet_tool_has_distance(libinput_tool))
tool->capabilities |= 1 << ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE;
if (libinput_tablet_tool_has_pressure(libinput_tool))
tool->capabilities |= 1 << ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE;
if (libinput_tablet_tool_has_tilt(libinput_tool))
tool->capabilities |= 1 << ZWP_TABLET_TOOL_V2_CAPABILITY_TILT;
/* unique tools are tracked globally, others per tablet */
if (libinput_tablet_tool_is_unique(libinput_tool))
wl_list_insert(&device->seat->tablet_tool_list, &tool->link);
else
wl_list_insert(&tablet->tool_list, &tool->link);
libinput_tablet_tool_set_user_data(libinput_tool, tool);
notify_tablet_tool_added(tool);
}
notify_tablet_tool_proximity_in(tool, &time, tablet);
process_tablet_axis(device->output, tablet, tool, proximity_event);
async_notify_tablet_tool_frame(tool, &time);
}
static void
handle_tablet_axis(struct libinput_device *libinput_device,
struct libinput_event_tablet_tool *axis_event)
{
struct evdev_device *device =
libinput_device_get_user_data(libinput_device);
struct weston_tablet_tool *tool;
struct weston_tablet *tablet = device->tablet;
struct libinput_tablet_tool *libinput_tool;
struct timespec time;
libinput_tool = libinput_event_tablet_tool_get_tool(axis_event);
tool = libinput_tablet_tool_get_user_data(libinput_tool);
timespec_from_usec(&time,
libinput_event_tablet_tool_get_time(axis_event));
process_tablet_axis(device->output, tablet, tool, axis_event);
async_notify_tablet_tool_frame(tool, &time);
}
static void
handle_tablet_tip(struct libinput_device *libinput_device,
struct libinput_event_tablet_tool *tip_event)
{
struct evdev_device *device =
libinput_device_get_user_data(libinput_device);
struct weston_tablet_tool *tool;
struct libinput_tablet_tool *libinput_tool;
struct timespec time;
libinput_tool = libinput_event_tablet_tool_get_tool(tip_event);
tool = libinput_tablet_tool_get_user_data(libinput_tool);
timespec_from_usec(&time,
libinput_event_tablet_tool_get_time(tip_event));
process_tablet_axis(device->output, device->tablet, tool, tip_event);
if (libinput_event_tablet_tool_get_tip_state(tip_event) ==
LIBINPUT_TABLET_TOOL_TIP_DOWN)
notify_tablet_tool_down(tool, &time);
else
notify_tablet_tool_up(tool, &time);
async_notify_tablet_tool_frame(tool, &time);
}
static void
handle_tablet_button(struct libinput_device *libinput_device,
struct libinput_event_tablet_tool *button_event)
{
struct weston_tablet_tool *tool;
struct libinput_tablet_tool *libinput_tool;
struct timespec time;
uint32_t button;
enum zwp_tablet_tool_v2_button_state state;
libinput_tool = libinput_event_tablet_tool_get_tool(button_event);
tool = libinput_tablet_tool_get_user_data(libinput_tool);
timespec_from_usec(&time,
libinput_event_tablet_tool_get_time(button_event));
button = libinput_event_tablet_tool_get_button(button_event);
if (libinput_event_tablet_tool_get_button_state(button_event) ==
LIBINPUT_BUTTON_STATE_PRESSED)
state = ZWP_TABLET_TOOL_V2_BUTTON_STATE_PRESSED;
else
state = ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED;
notify_tablet_tool_button(tool, &time, button, state);
async_notify_tablet_tool_frame(tool, &time);
}
int
evdev_device_process_event(struct libinput_event *event)
{
......@@ -561,6 +809,22 @@ evdev_device_process_event(struct libinput_event *event)
handle_touch_frame(libinput_device,
libinput_event_get_touch_event(event));
break;
case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
handle_tablet_proximity(libinput_device,
libinput_event_get_tablet_tool_event(event));
break;
case LIBINPUT_EVENT_TABLET_TOOL_TIP:
handle_tablet_tip(libinput_device,
libinput_event_get_tablet_tool_event(event));
break;
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
handle_tablet_axis(libinput_device,
libinput_event_get_tablet_tool_event(event));
break;
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
handle_tablet_button(libinput_device,
libinput_event_get_tablet_tool_event(event));
break;
default:
handled = 0;
weston_log("unknown libinput event %d\n",
......@@ -711,6 +975,33 @@ evdev_device_set_output(struct evdev_device *device,
evdev_device_set_calibration(device);
}
static void
evdev_device_init_tablet(struct evdev_device *device,
struct libinput_device *libinput_device,
struct weston_seat *seat)
{
struct weston_tablet *tablet;
struct udev_device *udev_device;
tablet = weston_seat_add_tablet(seat);
tablet->name = strdup(libinput_device_get_name(libinput_device));
tablet->vid = libinput_device_get_id_vendor(libinput_device);
tablet->pid = libinput_device_get_id_product(libinput_device);
udev_device = libinput_device_get_udev_device(libinput_device);
if (udev_device) {
tablet->path = udev_device_get_devnode(udev_device);
udev_device_unref(udev_device);
}
wl_list_insert(&seat->tablet_list, &tablet->link);
device->seat_caps |= EVDEV_SEAT_TABLET;
device->tablet = tablet;
notify_tablet_added(tablet);
}
struct evdev_device *
evdev_device_create(struct libinput_device *libinput_device,
struct weston_seat *seat)
......@@ -751,6 +1042,10 @@ evdev_device_create(struct libinput_device *libinput_device,
device->seat_caps |= EVDEV_SEAT_TOUCH;
device->touch_device = create_touch_device(device);
}
if (libinput_device_has_capability(libinput_device,
LIBINPUT_DEVICE_CAP_TABLET_TOOL)) {
evdev_device_init_tablet(device, libinput_device, seat);
}
libinput_device_set_user_data(libinput_device, device);
libinput_device_ref(libinput_device);
......@@ -769,6 +1064,8 @@ evdev_device_destroy(struct evdev_device *device)
weston_touch_device_destroy(device->touch_device);
weston_seat_release_touch(device->seat);
}
if (device->seat_caps & EVDEV_SEAT_TABLET)
weston_seat_release_tablet(device->tablet);
if (device->output)
wl_list_remove(&device->output_destroy_listener.link);
......
......@@ -38,7 +38,8 @@
enum evdev_device_seat_capability {
EVDEV_SEAT_POINTER = (1 << 0),
EVDEV_SEAT_KEYBOARD = (1 << 1),
EVDEV_SEAT_TOUCH = (1 << 2)
EVDEV_SEAT_TOUCH = (1 << 2),
EVDEV_SEAT_TABLET = (1 << 3)
};
struct evdev_device {
......@@ -49,6 +50,7 @@ struct evdev_device {
struct wl_list link;
struct weston_output *output;
struct wl_listener output_destroy_listener;
struct weston_tablet *tablet;
char *output_name;
int fd;
bool override_wl_calibration;
......
......@@ -224,6 +224,10 @@ weston_compositor_run_touch_binding(struct weston_compositor *compositor,
const struct timespec *time,
int touch_type);
void
weston_compositor_run_tablet_tool_binding(struct weston_compositor *compositor,
struct weston_tablet_tool *tool,
uint32_t button, uint32_t state_w);
void
weston_compositor_stack_plane(struct weston_compositor *ec,
struct weston_plane *plane,
struct weston_plane *above);
......@@ -300,6 +304,15 @@ weston_seat_release_pointer(struct weston_seat *seat);
void
weston_seat_release_touch(struct weston_seat *seat);
struct weston_tablet *
weston_seat_add_tablet(struct weston_seat *seat);
struct weston_tablet_tool *
weston_seat_add_tablet_tool(struct weston_seat *seat);
void
weston_seat_release_tablet_tool(struct weston_tablet_tool *tablet_tool);
void
weston_seat_release_tablet(struct weston_tablet *tablet);
void
weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap);
......@@ -349,6 +362,25 @@ weston_touch_start_drag(struct weston_touch *touch,
bool
weston_touch_device_can_calibrate(struct weston_touch_device *device);
/* weston_tablet */
void
weston_tablet_manager_init(struct weston_compositor *ec);
struct weston_tablet *
weston_tablet_create(void);
void
weston_tablet_destroy(struct weston_tablet *tablet);
/* weston_tablet_tool */
struct weston_tablet_tool *
weston_tablet_tool_create(void);
void
weston_tablet_tool_destroy(struct weston_tablet_tool *tool);
/* weston_surface */
pixman_box32_t
weston_surface_to_buffer_rect(struct weston_surface *surface,
......
......@@ -73,6 +73,8 @@ srcs_libweston = [
weston_direct_display_server_protocol_h,
weston_output_capture_protocol_c,
weston_output_capture_server_protocol_h,
tablet_unstable_v2_protocol_c,
tablet_unstable_v2_server_protocol_h,
]
subdir('desktop')
......@@ -225,7 +227,8 @@ lib_libinput_backend = static_library(
'libinput-backend',
[
'libinput-device.c',
'libinput-seat.c'
'libinput-seat.c',
tablet_unstable_v2_server_protocol_h
],
dependencies: [
dep_libweston_private,
......
......@@ -139,7 +139,7 @@ endif
dep_wayland_server = dependency('wayland-server', version: '>= 1.20.0')
dep_wayland_client = dependency('wayland-client', version: '>= 1.20.0')
dep_pixman = dependency('pixman-1', version: '>= 0.25.2')
dep_libinput = dependency('libinput', version: '>= 0.8.0')
dep_libinput = dependency('libinput', version: '>= 1.2.0')
dep_libevdev = dependency('libevdev')
dep_libm = cc.find_library('m')
dep_libdl = cc.find_library('dl')
......
......@@ -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)
{
......