[PATCH weston 3/3] clients: Fork clickdot as confine
Derek Foreman
derekf at osg.samsung.com
Wed May 4 15:11:26 UTC 2016
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 <derekf at osg.samsung.com>
> Signed-off-by: Jonas Ådahl <jadahl at 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;
> +}
>
More information about the wayland-devel
mailing list