[PATCH weston v5] Implement text cursor position protocol.

Scott Moreau oreaus at gmail.com
Tue May 29 13:18:31 PDT 2012


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.
---

This variant moves the user input detection from the client to the compositor.

 clients/.gitignore                |    2 +
 clients/Makefile.am               |    6 ++-
 clients/terminal.c                |   14 +++++-
 clients/window.c                  |   17 +++++++
 clients/window.h                  |    3 +
 protocol/text-cursor-position.xml |   11 +++++
 src/.gitignore                    |    2 +
 src/Makefile.am                   |    5 ++
 src/compositor.c                  |   61 ++++++++++++++++++++++---
 src/compositor.h                  |   14 +++++-
 src/shell.c                       |    3 +-
 src/text-cursor-position.c        |   91 +++++++++++++++++++++++++++++++++++++
 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..cb7fb73 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;
@@ -2594,6 +2596,17 @@ 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 (text_cursor_position)
+		text_cursor_position_notify(text_cursor_position,
+						window->surface, x, y);
+}
+
+void
 window_damage(struct window *window, int32_t x, int32_t y,
 	      int32_t width, int32_t height)
 {
@@ -3081,6 +3094,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..488aec1 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;
@@ -1766,6 +1766,8 @@ notify_key(struct wl_seat *seat, uint32_t time, uint32_t key, uint32_t state)
 		if (compositor->ping_handler && focus)
 			compositor->ping_handler(focus, serial);
 
+		compositor->process_text_cursor_zoom = 1;
+
 		weston_compositor_idle_inhibit(compositor);
 		seat->keyboard->grab_key = key;
 		seat->keyboard->grab_time = time;
@@ -2444,9 +2446,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 +2481,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,9 +2692,12 @@ 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;
 
+	ec->process_text_cursor_zoom = 0;
+
 	wl_data_device_manager_init(ec->wl_display);
 
 	glActiveTexture(GL_TEXTURE0);
diff --git a/src/compositor.h b/src/compositor.h
index 5752e81..ec73762 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;
@@ -279,6 +284,7 @@ struct weston_compositor {
 	void (*ping_handler)(struct weston_surface *surface, uint32_t serial);
 
 	int launcher_sock;
+	int process_text_cursor_zoom;
 
 	uint32_t output_id_pool;
 
@@ -561,7 +567,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 +607,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 e1f3a04..dc4fa47 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1689,7 +1689,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..56b55e3
--- /dev/null
+++ b/src/text-cursor-position.c
@@ -0,0 +1,91 @@
+/*
+ * 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)
+{
+	struct weston_surface *surface =
+				(struct weston_surface *) surface_resource;
+
+	if (surface->compositor->process_text_cursor_zoom)
+		weston_text_cursor_position_notify(surface, 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



More information about the wayland-devel mailing list