On 15/03/16 08:14 AM, Jonas Ådahl wrote: > The new confine client will be used to demonstrate pointer confinement. > It is so far identical to clickdot except that it doesn't respond to > clicks.
So basically just "dot". :P Doesn't build though - looks like it needs to include xalloc.h I'm not really sure I see benefit to copy/pasting an entire file - it'll just make more work for us next time we add yet another bizarro malloc wrapper function header file. I think we could just rename clickdot to pointer-test and pretend it's always been intended to cover this sort of testing. ;) Whining aside, fix the header issue and it's Reviewed-by: Derek Foreman <der...@osg.samsung.com> > Signed-off-by: Jonas Ådahl <jad...@gmail.com> > --- > > This patch does what Peter suggested, i.e. fork clickdot into a separate > client > that demonstrates confinement. The other patches that added various features > to > clickdot now add those features to this new demo client instead. > > > Makefile.am | 7 ++ > clients/confine.c | 330 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 337 insertions(+) > create mode 100644 clients/confine.c > > diff --git a/Makefile.am b/Makefile.am > index 35af909..5c13b38 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -452,6 +452,7 @@ demo_clients = \ > weston-resizor \ > weston-eventdemo \ > weston-clickdot \ > + weston-confine \ > weston-transformed \ > weston-fullscreen \ > weston-stacking \ > @@ -660,6 +661,12 @@ weston_clickdot_SOURCES = > \ > weston_clickdot_LDADD = libtoytoolkit.la > weston_clickdot_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS) > > +weston_confine_SOURCES = \ > + clients/confine.c \ > + shared/helpers.h > +weston_confine_LDADD = libtoytoolkit.la > +weston_confine_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS) > + > weston_transformed_SOURCES = clients/transformed.c > weston_transformed_LDADD = libtoytoolkit.la > weston_transformed_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS) > diff --git a/clients/confine.c b/clients/confine.c > new file mode 100644 > index 0000000..22b1e33 > --- /dev/null > +++ b/clients/confine.c > @@ -0,0 +1,330 @@ > +/* > + * Copyright © 2010 Intel Corporation > + * Copyright © 2012 Collabora, Ltd. > + * Copyright © 2012 Jonas Ådahl > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > + * DEALINGS IN THE 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 <sys/timerfd.h> > +#include <sys/epoll.h> > +#include <unistd.h> > + > +#include <linux/input.h> > +#include <wayland-client.h> > + > +#include "window.h" > +#include "shared/helpers.h" > + > +struct confine { > + struct display *display; > + struct window *window; > + struct widget *widget; > + > + cairo_surface_t *buffer; > + > + struct { > + int32_t x, y; > + int32_t old_x, old_y; > + } line; > + > + int reset; > + > + struct input *cursor_timeout_input; > + int cursor_timeout_fd; > + struct task cursor_timeout_task; > +}; > + > +static void > +draw_line(struct confine *confine, cairo_t *cr, > + struct rectangle *allocation) > +{ > + cairo_t *bcr; > + cairo_surface_t *tmp_buffer = NULL; > + > + if (confine->reset) { > + tmp_buffer = confine->buffer; > + confine->buffer = NULL; > + confine->line.x = -1; > + confine->line.y = -1; > + confine->line.old_x = -1; > + confine->line.old_y = -1; > + confine->reset = 0; > + } > + > + if (confine->buffer == NULL) { > + confine->buffer = > + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, > + allocation->width, > + allocation->height); > + bcr = cairo_create(confine->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(confine->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 (confine->line.x != -1 && confine->line.y != -1) { > + if (confine->line.old_x != -1 && > + confine->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, > + confine->line.old_x, > + confine->line.old_y); > + cairo_line_to(bcr, > + confine->line.x, > + confine->line.y); > + > + cairo_stroke(bcr); > + } > + > + confine->line.old_x = confine->line.x; > + confine->line.old_y = confine->line.y; > + } > + cairo_destroy(bcr); > + > + cairo_set_source_surface(cr, confine->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) > +{ > + struct confine *confine = data; > + cairo_surface_t *surface; > + cairo_t *cr; > + struct rectangle allocation; > + > + widget_get_allocation(confine->widget, &allocation); > + > + surface = window_get_surface(confine->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(confine, cr, &allocation); > + > + cairo_destroy(cr); > + > + cairo_surface_destroy(surface); > +} > + > +static void > +keyboard_focus_handler(struct window *window, > + struct input *device, void *data) > +{ > + struct confine *confine = data; > + > + window_schedule_redraw(confine->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 confine *confine = data; > + > + if (state == WL_KEYBOARD_KEY_STATE_RELEASED) > + return; > + > + switch (sym) { > + case XKB_KEY_Escape: > + display_exit(confine->display); > + break; > + } > +} > + > +static void > +cursor_timeout_reset(struct confine *confine) > +{ > + const long cursor_timeout = 500; > + struct itimerspec its; > + > + its.it_interval.tv_sec = 0; > + its.it_interval.tv_nsec = 0; > + its.it_value.tv_sec = cursor_timeout / 1000; > + its.it_value.tv_nsec = (cursor_timeout % 1000) * 1000 * 1000; > + timerfd_settime(confine->cursor_timeout_fd, 0, &its, NULL); > +} > + > +static int > +motion_handler(struct widget *widget, > + struct input *input, uint32_t time, > + float x, float y, void *data) > +{ > + struct confine *confine = data; > + confine->line.x = x; > + confine->line.y = y; > + > + window_schedule_redraw(confine->window); > + > + cursor_timeout_reset(confine); > + confine->cursor_timeout_input = input; > + > + return CURSOR_BLANK; > +} > + > +static void > +resize_handler(struct widget *widget, > + int32_t width, int32_t height, > + void *data) > +{ > + struct confine *confine = data; > + > + confine->reset = 1; > +} > + > +static void > +leave_handler(struct widget *widget, > + struct input *input, void *data) > +{ > + struct confine *confine = data; > + > + confine->reset = 1; > +} > + > +static void > +cursor_timeout_func(struct task *task, uint32_t events) > +{ > + struct confine *confine = > + container_of(task, struct confine, cursor_timeout_task); > + uint64_t exp; > + > + if (read(confine->cursor_timeout_fd, &exp, sizeof (uint64_t)) != > + sizeof(uint64_t)) > + abort(); > + > + input_set_pointer_image(confine->cursor_timeout_input, > + CURSOR_LEFT_PTR); > +} > + > +static struct confine * > +confine_create(struct display *display) > +{ > + struct confine *confine; > + > + confine = xzalloc(sizeof *confine); > + confine->window = window_create(display); > + confine->widget = window_frame_create(confine->window, confine); > + window_set_title(confine->window, "Wayland Confine"); > + confine->display = display; > + confine->buffer = NULL; > + > + window_set_key_handler(confine->window, key_handler); > + window_set_user_data(confine->window, confine); > + window_set_keyboard_focus_handler(confine->window, > + keyboard_focus_handler); > + > + widget_set_redraw_handler(confine->widget, redraw_handler); > + widget_set_motion_handler(confine->widget, motion_handler); > + widget_set_resize_handler(confine->widget, resize_handler); > + widget_set_leave_handler(confine->widget, leave_handler); > + > + widget_schedule_resize(confine->widget, 500, 400); > + confine->line.x = -1; > + confine->line.y = -1; > + confine->line.old_x = -1; > + confine->line.old_y = -1; > + confine->reset = 0; > + > + confine->cursor_timeout_fd = > + timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); > + confine->cursor_timeout_task.run = cursor_timeout_func; > + display_watch_fd(window_get_display(confine->window), > + confine->cursor_timeout_fd, > + EPOLLIN, &confine->cursor_timeout_task); > + > + return confine; > +} > + > +static void > +confine_destroy(struct confine *confine) > +{ > + display_unwatch_fd(window_get_display(confine->window), > + confine->cursor_timeout_fd); > + close(confine->cursor_timeout_fd); > + if (confine->buffer) > + cairo_surface_destroy(confine->buffer); > + widget_destroy(confine->widget); > + window_destroy(confine->window); > + free(confine); > +} > + > +int > +main(int argc, char *argv[]) > +{ > + struct display *display; > + struct confine *confine; > + > + display = display_create(&argc, argv); > + if (display == NULL) { > + fprintf(stderr, "failed to create display: %m\n"); > + return -1; > + } > + > + confine = confine_create(display); > + > + display_run(display); > + > + confine_destroy(confine); > + display_destroy(display); > + > + return 0; > +} > _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel