[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