diff options
author | Will Thompson <will.thompson@collabora.co.uk> | 2012-03-14 11:28:13 +0000 |
---|---|---|
committer | Will Thompson <will.thompson@collabora.co.uk> | 2012-03-14 12:47:10 +0000 |
commit | 65cda6605a39580bc18927572288f35c0bf9463e (patch) | |
tree | fd57d19f825ad7021fe4eb5cef59cf720348e9c2 | |
parent | a7a006f55a78dc2c5603a9c50c3546160d316534 (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.am | 4 | ||||
-rw-r--r-- | clients/eyes.c | 192 |
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; +} |