summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2012-03-14 11:28:13 +0000
committerWill Thompson <will.thompson@collabora.co.uk>2012-03-14 12:47:10 +0000
commit65cda6605a39580bc18927572288f35c0bf9463e (patch)
treefd57d19f825ad7021fe4eb5cef59cf720348e9c2
parenta7a006f55a78dc2c5603a9c50c3546160d316534 (diff)
Add "eyes" client.
Obviously this only works while the pointer is over the surface, for now. Next up: a protocol extension.
-rw-r--r--clients/Makefile.am4
-rw-r--r--clients/eyes.c192
2 files changed, 196 insertions, 0 deletions
diff --git a/clients/Makefile.am b/clients/Makefile.am
index eab8939..c1252b5 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -30,6 +30,7 @@ if BUILD_CLIENTS
terminal = weston-terminal
clients_programs = \
+ eyes \
flower \
screenshot \
image \
@@ -62,6 +63,9 @@ toolkit_libs = \
../shared/libconfig-parser.la \
$(CLIENT_LIBS) $(CAIRO_EGL_LIBS) -lrt -lm
+eyes_SOURCES = eyes.c
+eyes_LDADD = $(toolkit_libs)
+
flower_SOURCES = flower.c
flower_LDADD = $(toolkit_libs)
diff --git a/clients/eyes.c b/clients/eyes.c
new file mode 100644
index 0000000..f91f2ad
--- /dev/null
+++ b/clients/eyes.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright © 2008 Kristian Høgsberg
+ * Copyright © 2012 Collabora Ltd.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <cairo.h>
+#include <glib.h>
+
+#include <linux/input.h>
+#include <wayland-client.h>
+#include "window.h"
+
+struct eyes {
+ struct display *display;
+ struct window *window;
+ struct widget *widget;
+ int width, height;
+ int32_t pointer_x, pointer_y;
+};
+
+static void
+draw_eyeball(cairo_t *cr, int x, int y, int width, int height, int pointer_x, int pointer_y)
+{
+ cairo_matrix_t transform;
+ double transformed_x, transformed_y;
+ double line_width = 9 * (2. / MAX(width, height));
+ double radius = 0.6;
+
+ /* Transform coordinate system so the eyeball appears to be a unit
+ * circle centred at (0, 0)
+ */
+ cairo_save(cr);
+ cairo_translate(cr, x + width / 2., y + height / 2.);
+ cairo_scale(cr, (width - 10) / 2., (height - 10) / 2.);
+ cairo_get_matrix(cr, &transform);
+
+ /* Eyeball */
+ cairo_arc(cr, 0., 0., 1., 0., 2 * M_PI);
+
+ cairo_set_source_rgba(cr, 1., 1., 1., 0.9);
+ cairo_fill_preserve(cr);
+
+ cairo_set_source_rgba(cr, 0., 0., 0., 1.0);
+ cairo_set_line_width(cr, line_width);
+ cairo_stroke(cr);
+
+ /* Pupil */
+ transformed_x = pointer_x;
+ transformed_y = pointer_y;
+ cairo_matrix_invert(&transform);
+ cairo_matrix_transform_point (&transform, &transformed_x, &transformed_y);
+
+ double r_squared = pow(transformed_x, 2) + pow(transformed_y, 2);
+
+ if (r_squared > pow(radius, 2)) {
+ double ratio = radius / sqrt(r_squared);
+ transformed_x *= ratio;
+ transformed_y *= ratio;
+ }
+
+ cairo_arc(cr, transformed_x, transformed_y, line_width, 0., 2 * M_PI);
+ cairo_set_source_rgba(cr, 0., 0., 0., 1.0);
+ cairo_fill(cr);
+
+ cairo_restore(cr);
+}
+
+static void
+draw_stuff(cairo_surface_t *surface, int width, int height, int pointer_x, int pointer_y)
+{
+ cairo_t *cr;
+
+ cr = cairo_create(surface);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgba(cr, 0, 0, 0, 0);
+ cairo_paint(cr);
+
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ draw_eyeball(cr, 0, 0, width / 2, height, pointer_x, pointer_y);
+ draw_eyeball(cr, width / 2, 0, width / 2, height, pointer_x, pointer_y);
+
+ cairo_destroy(cr);
+}
+
+static void
+resize_handler(struct widget *widget,
+ int32_t width, int32_t height, void *data)
+{
+ struct eyes *eyes = data;
+
+ /* Dont resize me */
+ widget_set_size(eyes->widget, eyes->width, eyes->height);
+}
+
+static void
+redraw_handler(struct widget *widget, void *data)
+{
+ struct eyes *eyes = data;
+ cairo_surface_t *surface;
+
+ surface = window_get_surface(eyes->window);
+ if (surface == NULL ||
+ cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
+ fprintf(stderr, "failed to create cairo egl surface\n");
+ return;
+ }
+
+ draw_stuff(surface, eyes->width, eyes->height, eyes->pointer_x, eyes->pointer_y);
+ cairo_surface_destroy(surface);
+}
+
+static int
+motion_handler(struct widget *widget, struct input *input,
+ uint32_t time, int32_t x, int32_t y, void *data)
+{
+ struct eyes *eyes = data;
+
+ eyes->pointer_x = x;
+ eyes->pointer_y = y;
+ widget_schedule_redraw(widget);
+ return POINTER_IBEAM;
+}
+
+static void
+button_handler(struct widget *widget,
+ struct input *input, uint32_t time,
+ int button, int state, void *data)
+{
+ struct eyes *eyes = data;
+
+ switch (button) {
+ case BTN_LEFT:
+ if (state)
+ window_move(eyes->window, input, time);
+ break;
+ case BTN_RIGHT:
+ if (state)
+ window_show_frame_menu(eyes->window, input, time);
+ break;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ struct eyes eyes;
+ struct display *d;
+
+ d = display_create(argc, argv);
+ if (d == NULL) {
+ fprintf(stderr, "failed to create display: %m\n");
+ return -1;
+ }
+
+ eyes.width = 150;
+ eyes.height = 100;
+ eyes.display = d;
+ eyes.window = window_create(d);
+ eyes.widget = window_add_widget(eyes.window, &eyes);
+
+ widget_set_resize_handler(eyes.widget, resize_handler);
+ widget_set_redraw_handler(eyes.widget, redraw_handler);
+ widget_set_motion_handler(eyes.widget, motion_handler);
+ widget_set_button_handler(eyes.widget, button_handler);
+
+ window_schedule_resize(eyes.window, eyes.width, eyes.height);
+
+ display_run(d);
+
+ return 0;
+}