From 7a1b32a19888bb4f4a47dc951cf5d72db0899c11 Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Sun, 27 May 2012 14:25:02 -0600 Subject: [PATCH] Implement text cursor position protocol. 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. --- 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 81dab066..e47d6747 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 93754d8a..573cf59b 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 43b0dcda..27ab3008 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 9eb62e6c..3ef648ef 100644 --- a/clients/window.c +++ b/clients/window.c @@ -61,6 +61,7 @@ #include #include #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; @@ -1823,6 +1826,9 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard, if (!window || window->keyboard_device != input) return; + if (state) + window->send_cursor_position = 1; + 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); @@ -2609,6 +2615,21 @@ window_get_title(struct window *window) return window->title; } +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) @@ -2695,6 +2716,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; @@ -3097,6 +3119,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 7e968d0e..a8537b3c 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 00000000..dbeda724 --- /dev/null +++ b/protocol/text-cursor-position.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/.gitignore b/src/.gitignore index 56fc1ae0..eb3bbb5e 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 52457ac8..76062118 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 b82ba08f..a36ccd55 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -1632,7 +1632,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; @@ -2445,9 +2445,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; @@ -2455,10 +2480,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); @@ -2647,6 +2691,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 5752e815..09cd215a 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 e1f3a049..dc4fa474 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 00000000..6f466369 --- /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 + +#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); +}