[PATCH weston v4] Implement text cursor position protocol.

Kristian Høgsberg hoegsberg at gmail.com
Thu May 31 10:10:15 PDT 2012


On Sun, May 27, 2012 at 02:25:02PM -0600, Scott Moreau wrote:
> Here we create a new client/compositor interface in weston to allow
> clients to report their x/y cursor position to the compositor. These
> values are then used to center the zoom area on this point. This
> is useful for everyone, especially people who are visually impaired.
> ---
> 
> Made changes discussed for v3 patch.

Committed as is, but just a brief comment below.

Kristian


>  clients/.gitignore                |    2 +
>  clients/Makefile.am               |    6 ++-
>  clients/terminal.c                |   14 ++++++-
>  clients/window.c                  |   26 +++++++++++
>  clients/window.h                  |    3 +
>  protocol/text-cursor-position.xml |   11 +++++
>  src/.gitignore                    |    2 +
>  src/Makefile.am                   |    5 ++
>  src/compositor.c                  |   57 +++++++++++++++++++++---
>  src/compositor.h                  |   13 +++++-
>  src/shell.c                       |    3 +-
>  src/text-cursor-position.c        |   87 +++++++++++++++++++++++++++++++++++++
>  12 files changed, 219 insertions(+), 10 deletions(-)
>  create mode 100644 protocol/text-cursor-position.xml
>  create mode 100644 src/text-cursor-position.c
> 
> diff --git a/clients/.gitignore b/clients/.gitignore
> index 81dab06..e47d674 100644
> --- a/clients/.gitignore
> +++ b/clients/.gitignore
> @@ -10,6 +10,8 @@ libtoytoolkit.a
>  resizor
>  screenshooter-client-protocol.h
>  screenshooter-protocol.c
> +text-cursor-position-client-protocol.h
> +text-cursor-position-protocol.c
>  simple-egl
>  simple-shm
>  simple-touch
> diff --git a/clients/Makefile.am b/clients/Makefile.am
> index 93754d8..573cf59 100644
> --- a/clients/Makefile.am
> +++ b/clients/Makefile.am
> @@ -57,7 +57,9 @@ noinst_LIBRARIES = libtoytoolkit.a
>  
>  libtoytoolkit_a_SOURCES =			\
>  	window.c				\
> -	window.h
> +	window.h				\
> +	text-cursor-position-protocol.c		\
> +	text-cursor-position-client-protocol.h
>  
>  toolkit_libs =						\
>  	libtoytoolkit.a					\
> @@ -106,6 +108,8 @@ weston_tablet_shell_LDADD = $(toolkit_libs)
>  BUILT_SOURCES =					\
>  	screenshooter-client-protocol.h		\
>  	screenshooter-protocol.c		\
> +	text-cursor-position-client-protocol.h	\
> +	text-cursor-position-protocol.c		\
>  	desktop-shell-client-protocol.h		\
>  	desktop-shell-protocol.c		\
>  	tablet-shell-client-protocol.h		\
> diff --git a/clients/terminal.c b/clients/terminal.c
> index 32648dd..3dbf786 100644
> --- a/clients/terminal.c
> +++ b/clients/terminal.c
> @@ -372,6 +372,7 @@ struct terminal {
>  	int data_pitch, attr_pitch;  /* The width in bytes of a line */
>  	int width, height, start, row, column;
>  	int saved_row, saved_column;
> +	int send_cursor_position;
>  	int fd, master;
>  	uint32_t modifiers;
>  	char escape[MAX_ESCAPE+1];
> @@ -926,7 +927,7 @@ redraw_handler(struct widget *widget, void *data)
>  	struct rectangle allocation;
>  	cairo_t *cr;
>  	int top_margin, side_margin;
> -	int row, col;
> +	int row, col, cursor_x, cursor_y;
>  	union utf8_char *p_row;
>  	union decoded_attr attr;
>  	int text_x, text_y;
> @@ -1022,6 +1023,16 @@ redraw_handler(struct widget *widget, void *data)
>  	cairo_paint(cr);
>  	cairo_destroy(cr);
>  	cairo_surface_destroy(surface);
> +
> +	if (terminal->send_cursor_position) {
> +		cursor_x = side_margin + allocation.x +
> +				terminal->column * extents.max_x_advance;
> +		cursor_y = top_margin + allocation.y +
> +				terminal->row * extents.height;
> +		window_set_text_cursor_position(terminal->window,
> +						cursor_x, cursor_y);
> +		terminal->send_cursor_position = 0;
> +	}
>  }
>  
>  static void
> @@ -1029,6 +1040,7 @@ terminal_write(struct terminal *terminal, const char *data, size_t length)
>  {
>  	if (write(terminal->master, data, length) < 0)
>  		abort();
> +	terminal->send_cursor_position = 1;
>  }
>  
>  static void
> diff --git a/clients/window.c b/clients/window.c
> index bab5d76..22b2fc4 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -61,6 +61,7 @@
>  #include <linux/input.h>
>  #include <wayland-client.h>
>  #include "../shared/cairo-util.h"
> +#include "text-cursor-position-client-protocol.h"
>  
>  #include "window.h"
>  
> @@ -72,6 +73,7 @@ struct display {
>  	struct wl_shell *shell;
>  	struct wl_shm *shm;
>  	struct wl_data_device_manager *data_device_manager;
> +	struct text_cursor_position *text_cursor_position;
>  	EGLDisplay dpy;
>  	EGLConfig argb_config;
>  	EGLContext argb_ctx;
> @@ -149,6 +151,7 @@ struct window {
>  	int resize_needed;
>  	int type;
>  	int transparent;
> +	int send_cursor_position;
>  	struct input *keyboard_device;
>  	enum window_buffer_type buffer_type;
>  
> @@ -1822,6 +1825,9 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
>  	if (!window || window->keyboard_device != input)
>  		return;
>  
> +	if (state)
> +		window->send_cursor_position = 1;
> +

I don't think we should track this in window.c.  If a client wants to
set the text cursor position, we shouldn't second guess it.  Maybe the
cursor is moving because text got pasted into the window or such.

>  	num_syms = xkb_key_get_syms(d->xkb.state, code, &syms);
>  	xkb_state_update_key(d->xkb.state, code,
>  			     state ? XKB_KEY_DOWN : XKB_KEY_UP);
> @@ -2594,6 +2600,21 @@ window_get_title(struct window *window)
>  }
>  
>  void
> +window_set_text_cursor_position(struct window *window, int32_t x, int32_t y)
> +{
> +	struct text_cursor_position *text_cursor_position =
> +					window->display->text_cursor_position;
> +
> +	if (!window->send_cursor_position || !text_cursor_position)
> +		return;
> +
> +	text_cursor_position_notify(text_cursor_position,
> +						window->surface, x, y);
> +
> +	window->send_cursor_position = 0;
> +}
> +
> +void
>  window_damage(struct window *window, int32_t x, int32_t y,
>  	      int32_t width, int32_t height)
>  {
> @@ -2679,6 +2700,7 @@ window_create_internal(struct display *display, struct window *parent)
>  	window->allocation.height = 0;
>  	window->saved_allocation = window->allocation;
>  	window->transparent = 1;
> +	window->send_cursor_position = 0;
>  	window->type = TYPE_NONE;
>  	window->input_region = NULL;
>  	window->opaque_region = NULL;
> @@ -3081,6 +3103,10 @@ display_handle_global(struct wl_display *display, uint32_t id,
>  		d->data_device_manager =
>  			wl_display_bind(display, id,
>  					&wl_data_device_manager_interface);
> +	} else if (strcmp(interface, "text_cursor_position") == 0) {
> +		d->text_cursor_position =
> +			wl_display_bind(display, id,
> +					&text_cursor_position_interface);
>  	}
>  }
>  
> diff --git a/clients/window.h b/clients/window.h
> index 7e968d0..a8537b3 100644
> --- a/clients/window.h
> +++ b/clients/window.h
> @@ -307,6 +307,9 @@ window_set_title(struct window *window, const char *title);
>  const char *
>  window_get_title(struct window *window);
>  
> +void
> +window_set_text_cursor_position(struct window *window, int32_t x, int32_t y);
> +
>  int
>  widget_set_tooltip(struct widget *parent, char *entry, float x, float y);
>  
> diff --git a/protocol/text-cursor-position.xml b/protocol/text-cursor-position.xml
> new file mode 100644
> index 0000000..dbeda72
> --- /dev/null
> +++ b/protocol/text-cursor-position.xml
> @@ -0,0 +1,11 @@
> +<protocol name="text_cursor_position">
> +
> +  <interface name="text_cursor_position" version="1">
> +    <request name="notify">
> +      <arg name="surface" type="object" interface="wl_surface"/>
> +      <arg name="x" type="uint"/>
> +      <arg name="y" type="uint"/>
> +    </request>
> +  </interface>
> +
> +</protocol>
> diff --git a/src/.gitignore b/src/.gitignore
> index 56fc1ae..eb3bbb5 100644
> --- a/src/.gitignore
> +++ b/src/.gitignore
> @@ -2,6 +2,8 @@ weston
>  weston-launch
>  screenshooter-protocol.c
>  screenshooter-server-protocol.h
> +text-cursor-position-protocol.c
> +text-cursor-position-server-protocol.h
>  tablet-shell-protocol.c
>  tablet-shell-server-protocol.h
>  xserver-protocol.c
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 52457ac..7606211 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -18,6 +18,9 @@ weston_SOURCES =				\
>  	screenshooter.c				\
>  	screenshooter-protocol.c		\
>  	screenshooter-server-protocol.h		\
> +	text-cursor-position.c			\
> +	text-cursor-position-protocol.c		\
> +	text-cursor-position-server-protocol.h	\
>  	util.c					\
>  	matrix.c				\
>  	matrix.h				\
> @@ -144,6 +147,8 @@ endif
>  BUILT_SOURCES =					\
>  	screenshooter-server-protocol.h		\
>  	screenshooter-protocol.c		\
> +	text-cursor-position-server-protocol.h	\
> +	text-cursor-position-protocol.c		\
>  	tablet-shell-protocol.c			\
>  	tablet-shell-server-protocol.h		\
>  	desktop-shell-protocol.c		\
> diff --git a/src/compositor.c b/src/compositor.c
> index d21459b..d5d6d6e 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -1631,7 +1631,7 @@ notify_motion(struct wl_seat *seat, uint32_t time, wl_fixed_t x, wl_fixed_t y)
>  		if (output->zoom.active &&
>  		    pixman_region32_contains_point(&output->region,
>  						   ix, iy, NULL))
> -			weston_output_update_zoom(output, x, y);
> +			weston_output_update_zoom(output, x, y, ZOOM_POINTER);
>  
>  	weston_device_repick(seat);
>  	interface = seat->pointer->grab->interface;
> @@ -2444,9 +2444,34 @@ weston_output_destroy(struct weston_output *output)
>  }
>  
>  WL_EXPORT void
> -weston_output_update_zoom(struct weston_output *output, wl_fixed_t fx, wl_fixed_t fy)
> +weston_text_cursor_position_notify(struct weston_surface *surface,
> +						int32_t cur_pos_x,
> +						int32_t cur_pos_y)
> +{
> +	struct weston_output *output;
> +	int32_t global_x, global_y;
> +
> +	weston_surface_to_global(surface, cur_pos_x, cur_pos_y,
> +						&global_x, &global_y);
> +
> +	wl_list_for_each(output, &surface->compositor->output_list, link)
> +		if (output->zoom.active &&
> +		    pixman_region32_contains_point(&output->region,
> +						global_x, global_y, NULL))
> +			weston_output_update_zoom(output,
> +						wl_fixed_from_int(global_x),
> +						wl_fixed_from_int(global_y),
> +						ZOOM_TEXT_CURSOR);
> +}
> +
> +WL_EXPORT void
> +weston_output_update_zoom(struct weston_output *output,
> +						wl_fixed_t fx,
> +						wl_fixed_t fy,
> +						uint32_t type)
>  {
>  	int32_t x, y;
> +	float trans_min, trans_max;
>  
>  	if (output->zoom.level >= 1.0)
>  		return;
> @@ -2454,10 +2479,29 @@ weston_output_update_zoom(struct weston_output *output, wl_fixed_t fx, wl_fixed_
>  	x = wl_fixed_to_int(fx);
>  	y = wl_fixed_to_int(fy);
>  
> -	output->zoom.trans_x = (((float)(x - output->x) / output->current->width) *
> -					(output->zoom.level * 2)) - output->zoom.level;
> -	output->zoom.trans_y = (((float)(y - output->y) / output->current->height) *
> -					(output->zoom.level * 2)) - output->zoom.level;
> +	output->zoom.trans_x =
> +		(((float)(x - output->x) / output->current->width) *
> +		(output->zoom.level * 2)) - output->zoom.level;
> +	output->zoom.trans_y =
> +		(((float)(y - output->y) / output->current->height) *
> +		(output->zoom.level * 2)) - output->zoom.level;
> +
> +	if (type == ZOOM_TEXT_CURSOR) {
> +		output->zoom.trans_x *= 1 / output->zoom.level;
> +		output->zoom.trans_y *= 1 / output->zoom.level;
> +
> +		trans_max = output->zoom.level * 2 - output->zoom.level;
> +		trans_min = -trans_max;
> +
> +		if (output->zoom.trans_x > trans_max)
> +			output->zoom.trans_x = trans_max;
> +		else if (output->zoom.trans_x < trans_min)
> +			output->zoom.trans_x = trans_min;
> +		if (output->zoom.trans_y > trans_max)
> +			output->zoom.trans_y = trans_max;
> +		else if (output->zoom.trans_y < trans_min)
> +			output->zoom.trans_y = trans_min;
> +	}
>  
>  	output->dirty = 1;
>  	weston_output_damage(output);
> @@ -2646,6 +2690,7 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display)
>  	weston_layer_init(&ec->cursor_layer, &ec->fade_layer.link);
>  
>  	screenshooter_create(ec);
> +	text_cursor_position_notifier_create(ec);
>  
>  	ec->ping_handler = NULL;
>  
> diff --git a/src/compositor.h b/src/compositor.h
> index 5752e81..09cd215 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -82,6 +82,11 @@ struct weston_border {
>  	int32_t left, right, top, bottom;
>  };
>  
> +enum {
> +	ZOOM_POINTER,
> +	ZOOM_TEXT_CURSOR
> +};
> +
>  struct weston_output_zoom {
>  	int active;
>  	float increment;
> @@ -561,7 +566,10 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display)
>  void
>  weston_compositor_shutdown(struct weston_compositor *ec);
>  void
> -weston_output_update_zoom(struct weston_output *output, int x, int y);
> +weston_output_update_zoom(struct weston_output *output,
> +						int x, int y, uint32_t type);
> +void
> +weston_text_cursor_position_notify(struct weston_surface *surface, int x, int y);
>  void
>  weston_output_update_matrix(struct weston_output *output);
>  void
> @@ -598,6 +606,9 @@ tty_activate_vt(struct tty *tty, int vt);
>  void
>  screenshooter_create(struct weston_compositor *ec);
>  
> +void
> +text_cursor_position_notifier_create(struct weston_compositor *ec);
> +
>  struct weston_process;
>  typedef void (*weston_process_cleanup_func_t)(struct weston_process *process,
>  					    int status);
> diff --git a/src/shell.c b/src/shell.c
> index b37de80..4590fd0 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -1688,7 +1688,8 @@ zoom_binding(struct wl_seat *seat, uint32_t time,
>  
>  			weston_output_update_zoom(output,
>  			                          seat->pointer->x,
> -						  seat->pointer->y);
> +						  seat->pointer->y,
> +						  ZOOM_POINTER);
>  		}
>  	}
>  }
> diff --git a/src/text-cursor-position.c b/src/text-cursor-position.c
> new file mode 100644
> index 0000000..6f46636
> --- /dev/null
> +++ b/src/text-cursor-position.c
> @@ -0,0 +1,87 @@
> +/*
> + * Copyright © 2011 Intel Corporation
> + * Copyright © 2012 Scott Moreau
> + *
> + * 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 <stdlib.h>
> +
> +#include "compositor.h"
> +#include "text-cursor-position-server-protocol.h"
> +
> +struct text_cursor_position {
> +	struct wl_object base;
> +	struct weston_compositor *ec;
> +	struct wl_global *global;
> +	struct wl_listener destroy_listener;
> +};
> +
> +static void
> +text_cursor_position_notify(struct wl_client *client,
> +			    struct wl_resource *resource,
> +			    struct wl_resource *surface_resource,
> +			    uint32_t x, uint32_t y)
> +{
> +	weston_text_cursor_position_notify((struct weston_surface *) surface_resource, x, y);
> +}
> +
> +struct text_cursor_position_interface text_cursor_position_implementation = {
> +	text_cursor_position_notify
> +};
> +
> +static void
> +bind_text_cursor_position(struct wl_client *client,
> +	     void *data, uint32_t version, uint32_t id)
> +{
> +	wl_client_add_object(client, &text_cursor_position_interface,
> +			     &text_cursor_position_implementation, id, data);
> +}
> +
> +static void
> +text_cursor_position_notifier_destroy(struct wl_listener *listener, void *data)
> +{
> +	struct text_cursor_position *text_cursor_position =
> +		container_of(listener, struct text_cursor_position, destroy_listener);
> +
> +	wl_display_remove_global(text_cursor_position->ec->wl_display, text_cursor_position->global);
> +	free(text_cursor_position);
> +}
> +
> +void
> +text_cursor_position_notifier_create(struct weston_compositor *ec)
> +{
> +	struct text_cursor_position *text_cursor_position;
> +
> +	text_cursor_position = malloc(sizeof *text_cursor_position);
> +	if (text_cursor_position == NULL)
> +		return;
> +
> +	text_cursor_position->base.interface = &text_cursor_position_interface;
> +	text_cursor_position->base.implementation =
> +		(void(**)(void)) &text_cursor_position_implementation;
> +	text_cursor_position->ec = ec;
> +
> +	text_cursor_position->global = wl_display_add_global(ec->wl_display,
> +						&text_cursor_position_interface,
> +						text_cursor_position, bind_text_cursor_position);
> +
> +	text_cursor_position->destroy_listener.notify = text_cursor_position_notifier_destroy;
> +	wl_signal_add(&ec->destroy_signal, &text_cursor_position->destroy_listener);
> +}
> -- 
> 1.7.7.6
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list