[PATCH 14/18] text: Add support for panels following the cursor

Jan Arne Petersen jpetersen at openismus.com
Sun Apr 7 15:12:07 PDT 2013


From: Jan Arne Petersen <jpetersen at openismus.com>

Add input_panel_surface::set_panel to specify input panel surfaces which
are overlaying the application and are following the input cursor.

Signed-off-by: Jan Arne Petersen <jpetersen at openismus.com>
---
 protocol/input-method.xml |  3 ++
 src/compositor.c          |  1 +
 src/compositor.h          |  1 +
 src/shell.c               | 76 ++++++++++++++++++++++++++++++++++++++++++-----
 src/text-backend.c        | 23 +++++++++++---
 5 files changed, 93 insertions(+), 11 deletions(-)

diff --git a/protocol/input-method.xml b/protocol/input-method.xml
index 3fc468c..8a4ea7f 100644
--- a/protocol/input-method.xml
+++ b/protocol/input-method.xml
@@ -210,5 +210,8 @@
       </description>
       <arg name="position" type="uint"/>
     </request>
+
+    <request name="set_panel">
+    </request>
   </interface>
 </protocol>
diff --git a/src/compositor.c b/src/compositor.c
index e7c22db..e078850 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3150,6 +3150,7 @@ weston_compositor_init(struct weston_compositor *ec,
 	wl_signal_init(&ec->wake_signal);
 	wl_signal_init(&ec->show_input_panel_signal);
 	wl_signal_init(&ec->hide_input_panel_signal);
+	wl_signal_init(&ec->update_input_panel_signal);
 	wl_signal_init(&ec->seat_created_signal);
 	ec->launcher_sock = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
 
diff --git a/src/compositor.h b/src/compositor.h
index 7d1d68e..cde5e9a 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -309,6 +309,7 @@ struct weston_compositor {
 
 	struct wl_signal show_input_panel_signal;
 	struct wl_signal hide_input_panel_signal;
+	struct wl_signal update_input_panel_signal;
 
 	struct wl_signal seat_created_signal;
 
diff --git a/src/shell.c b/src/shell.c
index de5d6f6..4e268a8 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -78,6 +78,8 @@ struct input_panel_surface {
 	struct wl_list link;
 	struct weston_surface *surface;
 	struct wl_listener surface_destroy_listener;
+
+	uint32_t panel;
 };
 
 struct desktop_shell {
@@ -88,6 +90,7 @@ struct desktop_shell {
 	struct wl_listener destroy_listener;
 	struct wl_listener show_input_panel_listener;
 	struct wl_listener hide_input_panel_listener;
+	struct wl_listener update_input_panel_listener;
 
 	struct weston_layer fullscreen_layer;
 	struct weston_layer panel_layer;
@@ -111,6 +114,11 @@ struct desktop_shell {
 	bool showing_input_panels;
 	bool prepare_event_sent;
 
+	struct {
+		struct weston_surface *surface;
+		pixman_box32_t cursor_rectangle;
+	} text_input;
+
 	struct weston_surface *lock_surface;
 	struct wl_listener lock_surface_listener;
 
@@ -3031,6 +3039,8 @@ show_input_panels(struct wl_listener *listener, void *data)
 	struct input_panel_surface *surface, *next;
 	struct weston_surface *ws;
 
+	shell->text_input.surface = (struct weston_surface*)data;
+
 	if (shell->showing_input_panels)
 		return;
 
@@ -3043,6 +3053,9 @@ show_input_panels(struct wl_listener *listener, void *data)
 	wl_list_for_each_safe(surface, next,
 			      &shell->input_panel.surfaces, link) {
 		ws = surface->surface;
+		if (!weston_surface_is_mapped(ws)) {
+			continue;
+		}
 		wl_list_insert(&shell->input_panel_layer.surface_list,
 			       &ws->layer_link);
 		weston_surface_geometry_dirty(ws);
@@ -3074,6 +3087,16 @@ hide_input_panels(struct wl_listener *listener, void *data)
 }
 
 static void
+update_input_panels(struct wl_listener *listener, void *data)
+{
+	struct desktop_shell *shell =
+		container_of(listener, struct desktop_shell,
+			     update_input_panel_listener);
+
+	memcpy(&shell->text_input.cursor_rectangle, data, sizeof(pixman_box32_t));
+}
+
+static void
 center_on_output(struct weston_surface *surface, struct weston_output *output)
 {
 	int32_t width = weston_surface_buffer_width(surface);
@@ -3487,26 +3510,47 @@ bind_screensaver(struct wl_client *client,
 static void
 input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
 {
+	struct input_panel_surface *ip_surface = surface->private;
+	struct desktop_shell *shell = ip_surface->shell;
 	struct weston_mode *mode;
 	float x, y;
+	uint32_t show_surface = 0;
 
 	if (width == 0)
 		return;
 
-	if (!weston_surface_is_mapped(surface))
-		return;
+	if (!weston_surface_is_mapped(surface)) {
+		if (!shell->showing_input_panels)
+			return;
+
+		wl_list_insert(&shell->input_panel_layer.surface_list,
+			       &surface->layer_link);
+		weston_surface_geometry_dirty(surface);
+		weston_surface_update_transform(surface);
+		show_surface = 1;
+	}
 
 	mode = surface->output->current;
-	x = (mode->width - width) / 2;
-	y = mode->height - height;
+
+	if (ip_surface->panel) {
+		x = shell->text_input.surface->geometry.x + shell->text_input.cursor_rectangle.x2;
+		y = shell->text_input.surface->geometry.y + shell->text_input.cursor_rectangle.y2;
+	} else {
+		x = surface->output->x + (mode->width - width) / 2;
+		y = surface->output->y + mode->height - height;
+	}
 
 	/* Don't map the input panel here, wait for
 	 * show_input_panels signal. */
 
 	weston_surface_configure(surface,
-				 surface->output->x + x,
-				 surface->output->y + y,
+				 x, y,
 				 width, height);
+
+	if (show_surface) {
+		weston_surface_damage(surface);
+		weston_slide_run(surface, surface->geometry.height, 0, NULL, NULL);
+	}
 }
 
 static void
@@ -3582,10 +3626,26 @@ input_panel_surface_set_toplevel(struct wl_client *client,
 
 	wl_list_insert(&shell->input_panel.surfaces,
 		       &input_panel_surface->link);
+
+	input_panel_surface->panel = 0;
+}
+
+static void
+input_panel_surface_set_panel(struct wl_client *client,
+			      struct wl_resource *resource)
+{
+	struct input_panel_surface *input_panel_surface = resource->data;
+	struct desktop_shell *shell = input_panel_surface->shell;
+
+	wl_list_insert(&shell->input_panel.surfaces,
+		       &input_panel_surface->link);
+
+	input_panel_surface->panel = 1;
 }
 
 static const struct input_panel_surface_interface input_panel_surface_implementation = {
-	input_panel_surface_set_toplevel
+	input_panel_surface_set_toplevel,
+	input_panel_surface_set_panel
 };
 
 static void
@@ -4194,6 +4254,8 @@ module_init(struct weston_compositor *ec,
 	wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener);
 	shell->hide_input_panel_listener.notify = hide_input_panels;
 	wl_signal_add(&ec->hide_input_panel_signal, &shell->hide_input_panel_listener);
+	shell->update_input_panel_listener.notify = update_input_panels;
+	wl_signal_add(&ec->update_input_panel_signal, &shell->update_input_panel_listener);
 	ec->ping_handler = ping_handler;
 	ec->shell_interface.shell = shell;
 	ec->shell_interface.create_shell_surface = create_shell_surface;
diff --git a/src/text-backend.c b/src/text-backend.c
index 13fff24..07a066c 100644
--- a/src/text-backend.c
+++ b/src/text-backend.c
@@ -41,6 +41,8 @@ struct text_input {
 
 	struct wl_surface *surface;
 
+	pixman_box32_t cursor_rectangle;
+
 	uint32_t input_panel_visible;
 };
 
@@ -185,8 +187,10 @@ text_input_activate(struct wl_client *client,
 
 	input_method_context_create(text_input, input_method, serial);
 
-	if (text_input->input_panel_visible)
-		wl_signal_emit(&ec->show_input_panel_signal, ec);
+	if (text_input->input_panel_visible) {
+		wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
+		wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
+	}
 
 	text_input_send_enter(&text_input->resource, &text_input->surface->resource);
 }
@@ -226,6 +230,15 @@ text_input_set_cursor_rectangle(struct wl_client *client,
 				int32_t width,
 				int32_t height)
 {
+	struct text_input *text_input = resource->data;
+	struct weston_compositor *ec = text_input->ec;
+
+	text_input->cursor_rectangle.x1 = x;
+	text_input->cursor_rectangle.y1 = y;
+	text_input->cursor_rectangle.x2 = x + width;
+	text_input->cursor_rectangle.y2 = y + height;
+
+	wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
 }
 
 static void
@@ -283,8 +296,10 @@ text_input_show_input_panel(struct wl_client *client,
 
 	text_input->input_panel_visible = 1;
 
-	if (!wl_list_empty(&text_input->input_methods))
-		wl_signal_emit(&ec->show_input_panel_signal, ec);
+	if (!wl_list_empty(&text_input->input_methods)) {
+		wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
+		wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
+	}
 }
 
 static void
-- 
1.8.1.4



More information about the wayland-devel mailing list