[PATCH weston 19/19] tablet: Add demo application for tablets
Stephen Chandler Paul
thatslyude at gmail.com
Wed Aug 6 16:08:09 PDT 2014
This is just a hacked version of clickdot that responds to tablet events
instead of cursor events
Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>
---
.gitignore | 1 +
Makefile.am | 8 ++
clients/tablet.c | 341 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 350 insertions(+)
create mode 100644 clients/tablet.c
diff --git a/.gitignore b/.gitignore
index fbffaa5..c3f473a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,6 +54,7 @@ weston-simple-damage
weston-smoke
weston-stacking
weston-subsurfaces
+weston-tablet
weston-transformed
weston-view
diff --git a/Makefile.am b/Makefile.am
index cb22509..8165969 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -500,6 +500,14 @@ weston_scaler_SOURCES = clients/scaler.c
weston_scaler_LDADD = libtoytoolkit.la
weston_scaler_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+if ENABLE_LIBINPUT_BACKEND
+demo_clients += weston-tablet
+weston_tablet_SOURCES = clients/tablet.c
+weston_tablet_LDADD = libtoytoolkit.la
+weston_tablet_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+
+endif
+
if HAVE_CAIRO_GLESV2
demo_clients += weston-nested weston-nested-client
diff --git a/clients/tablet.c b/clients/tablet.c
new file mode 100644
index 0000000..c5c2182
--- /dev/null
+++ b/clients/tablet.c
@@ -0,0 +1,341 @@
+/*
+ * 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 <linux/input.h>
+#include <wayland-client.h>
+
+#include "window.h"
+
+struct tablet_view {
+ struct display *display;
+ struct window *window;
+ struct widget *widget;
+
+ int cursor;
+
+ cairo_surface_t *buffer;
+
+ enum {
+ TABLET_TOOL_UP = 0,
+ TABLET_TOOL_DOWN = 1,
+ } tablet_contact_status;
+
+ struct {
+ int32_t x, y;
+ } dot;
+
+ struct {
+ int32_t x, y;
+ int32_t old_x, old_y;
+ } line;
+
+ int reset;
+};
+
+static void
+draw_line(struct tablet_view *tablet_view, cairo_t *cr,
+ struct rectangle *allocation)
+{
+ cairo_t *bcr;
+ cairo_surface_t *tmp_buffer = NULL;
+
+ if (tablet_view->reset) {
+ tmp_buffer = tablet_view->buffer;
+ tablet_view->buffer = NULL;
+ tablet_view->line.x = -1;
+ tablet_view->line.y = -1;
+ tablet_view->line.old_x = -1;
+ tablet_view->line.old_y = -1;
+ tablet_view->reset = 0;
+ }
+
+ if (tablet_view->buffer == NULL) {
+ tablet_view->buffer =
+ cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ allocation->width,
+ allocation->height);
+ bcr = cairo_create(tablet_view->buffer);
+ cairo_set_source_rgba(bcr, 0, 0, 0, 0);
+ cairo_rectangle(bcr,
+ 0, 0,
+ allocation->width, allocation->height);
+ cairo_fill(bcr);
+ }
+ else
+ bcr = cairo_create(tablet_view->buffer);
+
+ if (tmp_buffer) {
+ cairo_set_source_surface(bcr, tmp_buffer, 0, 0);
+ cairo_rectangle(bcr, 0, 0,
+ allocation->width, allocation->height);
+ cairo_clip(bcr);
+ cairo_paint(bcr);
+
+ cairo_surface_destroy(tmp_buffer);
+ }
+
+ if (tablet_view->line.x != -1 && tablet_view->line.y != -1) {
+ if (tablet_view->line.old_x != -1 &&
+ tablet_view->line.old_y != -1) {
+ cairo_set_line_width(bcr, 2.0);
+ cairo_set_source_rgb(bcr, 1, 1, 1);
+ cairo_translate(bcr,
+ -allocation->x, -allocation->y);
+
+ cairo_move_to(bcr,
+ tablet_view->line.old_x,
+ tablet_view->line.old_y);
+ cairo_line_to(bcr,
+ tablet_view->line.x,
+ tablet_view->line.y);
+
+ cairo_stroke(bcr);
+ }
+
+ tablet_view->line.old_x = tablet_view->line.x;
+ tablet_view->line.old_y = tablet_view->line.y;
+ }
+ cairo_destroy(bcr);
+
+ cairo_set_source_surface(cr, tablet_view->buffer,
+ allocation->x, allocation->y);
+ cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
+ cairo_rectangle(cr,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+ cairo_clip(cr);
+ cairo_paint(cr);
+}
+
+static void
+redraw_handler(struct widget *widget, void *data)
+{
+ static const double r = 10.0;
+ struct tablet_view *tablet_view = data;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ struct rectangle allocation;
+
+ widget_get_allocation(tablet_view->widget, &allocation);
+
+ surface = window_get_surface(tablet_view->window);
+
+ cr = cairo_create(surface);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_rectangle(cr,
+ allocation.x,
+ allocation.y,
+ allocation.width,
+ allocation.height);
+ cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
+ cairo_fill(cr);
+
+ draw_line(tablet_view, cr, &allocation);
+
+ cairo_translate(cr, tablet_view->dot.x + 0.5, tablet_view->dot.y + 0.5);
+ cairo_set_line_width(cr, 1.0);
+ cairo_set_source_rgb(cr, 0.1, 0.9, 0.9);
+ cairo_move_to(cr, 0.0, -r);
+ cairo_line_to(cr, 0.0, r);
+ cairo_move_to(cr, -r, 0.0);
+ cairo_line_to(cr, r, 0.0);
+ cairo_arc(cr, 0.0, 0.0, r, 0.0, 2.0 * M_PI);
+ cairo_stroke(cr);
+
+ cairo_destroy(cr);
+
+ cairo_surface_destroy(surface);
+}
+
+static void
+keyboard_focus_handler(struct window *window,
+ struct input *device, void *data)
+{
+ struct tablet_view *tablet_view = data;
+
+ window_schedule_redraw(tablet_view->window);
+}
+
+static void
+key_handler(struct window *window, struct input *input, uint32_t time,
+ uint32_t key, uint32_t sym,
+ enum wl_keyboard_key_state state, void *data)
+{
+ struct tablet_view *tablet_view = data;
+
+ if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
+ return;
+
+ switch (sym) {
+ case XKB_KEY_Escape:
+ display_exit(tablet_view->display);
+ break;
+ }
+}
+
+static void
+button_handler(struct widget *widget, struct tablet *tablet, uint32_t button,
+ enum wl_tablet_button_state state, uint32_t time, void *data)
+{
+ struct tablet_view *tablet_view = data;
+
+ if (state == WL_TABLET_BUTTON_STATE_PRESSED && button == BTN_STYLUS)
+ tablet_get_position(tablet,
+ &tablet_view->dot.x, &tablet_view->dot.y);
+
+ widget_schedule_redraw(widget);
+}
+
+static int
+motion_handler(struct widget *widget, struct tablet *tablet, float x, float y,
+ uint32_t time, void *data)
+{
+ struct tablet_view *tablet_view = data;
+
+ if (tablet_view->tablet_contact_status == TABLET_TOOL_DOWN) {
+ tablet_view->line.x = x;
+ tablet_view->line.y = y;
+
+ window_schedule_redraw(tablet_view->window);
+ }
+
+ return tablet_view->cursor;
+}
+
+static void
+resize_handler(struct widget *widget,
+ int32_t width, int32_t height,
+ void *data)
+{
+ struct tablet_view *tablet_view = data;
+
+ tablet_view->reset = 1;
+}
+
+static void
+down_handler(struct widget *widget, struct tablet *tablet, uint32_t time,
+ void *data)
+{
+ struct tablet_view *tablet_view = data;
+
+ tablet_view->tablet_contact_status = TABLET_TOOL_DOWN;
+}
+
+static void
+up_handler(struct widget *widget, struct tablet *tablet, uint32_t time,
+ void *data)
+{
+ struct tablet_view *tablet_view = data;
+
+ tablet_view->tablet_contact_status = TABLET_TOOL_UP;
+}
+
+static void
+proximity_in_handler(struct widget *widget, struct tablet *tablet,
+ struct tablet_tool *tool, void *data)
+{
+ struct tablet_view *tablet_view = data;
+
+ if (tablet_tool_get_type(tool) == WL_TABLET_TOOL_TYPE_PEN)
+ tablet_view->cursor = CURSOR_HAND1;
+ else
+ tablet_view->cursor = CURSOR_LEFT;
+}
+
+static struct tablet_view *
+tablet_view_create(struct display *display)
+{
+ struct tablet_view *tablet_view;
+
+ tablet_view = xzalloc(sizeof *tablet_view);
+ tablet_view->window = window_create(display);
+ tablet_view->widget = window_frame_create(tablet_view->window, tablet_view);
+ window_set_title(tablet_view->window, "Wayland Tablet");
+ tablet_view->display = display;
+ tablet_view->buffer = NULL;
+
+ window_set_key_handler(tablet_view->window, key_handler);
+ window_set_user_data(tablet_view->window, tablet_view);
+ window_set_keyboard_focus_handler(tablet_view->window,
+ keyboard_focus_handler);
+
+ widget_set_redraw_handler(tablet_view->widget, redraw_handler);
+ widget_set_tablet_button_handler(tablet_view->widget, button_handler);
+ widget_set_tablet_motion_handler(tablet_view->widget, motion_handler);
+ widget_set_resize_handler(tablet_view->widget, resize_handler);
+ widget_set_tablet_down_handler(tablet_view->widget, down_handler);
+ widget_set_tablet_up_handler(tablet_view->widget, up_handler);
+ widget_set_tablet_proximity_in_handler(tablet_view->widget,
+ proximity_in_handler);
+
+ widget_schedule_resize(tablet_view->widget, 1000, 800);
+ tablet_view->dot.x = 250;
+ tablet_view->dot.y = 200;
+ tablet_view->line.x = -1;
+ tablet_view->line.y = -1;
+ tablet_view->line.old_x = -1;
+ tablet_view->line.old_y = -1;
+ tablet_view->reset = 0;
+
+ return tablet_view;
+}
+
+static void
+tablet_view_destroy(struct tablet_view *tablet_view)
+{
+ if (tablet_view->buffer)
+ cairo_surface_destroy(tablet_view->buffer);
+ widget_destroy(tablet_view->widget);
+ window_destroy(tablet_view->window);
+ free(tablet_view);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct display *display;
+ struct tablet_view *tablet_view;
+
+ display = display_create(&argc, argv);
+ if (display == NULL) {
+ fprintf(stderr, "failed to create display: %m\n");
+ return -1;
+ }
+
+ tablet_view = tablet_view_create(display);
+
+ display_run(display);
+
+ tablet_view_destroy(tablet_view);
+ display_destroy(display);
+
+ return 0;
+}
--
1.8.5.5
More information about the wayland-devel
mailing list