[PATCH 1/3] shell: Add support for input panels

Jan Arne Petersen jpetersen at openismus.com
Thu Jun 21 12:52:17 PDT 2012


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

---
 protocol/desktop-shell.xml |   17 ++++++
 src/compositor.c           |    2 +
 src/compositor.h           |    3 +
 src/shell.c                |  132 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 154 insertions(+)

diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml
index a9c181c..86e1063 100644
--- a/protocol/desktop-shell.xml
+++ b/protocol/desktop-shell.xml
@@ -64,4 +64,21 @@
 
   </interface>
 
+  <interface name="input_panel" version="1">
+    <description summary="interface for implementing keyboards">
+      Only one client can bind this interface at a time.
+    </description>
+
+    <request name="set_surface">
+      <description summary="set the surface type as a keyboard">
+	A keybaord surface is only shown, when a text model is active
+      </description>
+
+      <arg name="surface" type="object" interface="wl_shell_surface"/>
+      <arg name="output" type="object" interface="wl_output"/>
+    </request>
+
+  </interface>
+
+
 </protocol>
diff --git a/src/compositor.c b/src/compositor.c
index 4891e35..92e89d4 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -2981,6 +2981,8 @@ weston_compositor_init(struct weston_compositor *ec,
 	wl_signal_init(&ec->activate_signal);
 	wl_signal_init(&ec->lock_signal);
 	wl_signal_init(&ec->unlock_signal);
+	wl_signal_init(&ec->show_input_panel_signal);
+	wl_signal_init(&ec->hide_input_panel_signal);
 	ec->launcher_sock = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
 
 	ec->output_id_pool = 0;
diff --git a/src/compositor.h b/src/compositor.h
index ed09157..af094fe 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -278,6 +278,9 @@ struct weston_compositor {
 	struct wl_signal lock_signal;
 	struct wl_signal unlock_signal;
 
+	struct wl_signal show_input_panel_signal;
+	struct wl_signal hide_input_panel_signal;
+
 	struct wl_event_loop *input_loop;
 	struct wl_event_source *input_loop_source;
 
diff --git a/src/shell.c b/src/shell.c
index 6333180..809bf06 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -69,6 +69,8 @@ struct desktop_shell {
 	struct wl_listener lock_listener;
 	struct wl_listener unlock_listener;
 	struct wl_listener destroy_listener;
+	struct wl_listener show_input_panel_listener;
+	struct wl_listener hide_input_panel_listener;
 
 	struct weston_layer fullscreen_layer;
 	struct weston_layer panel_layer;
@@ -117,6 +119,11 @@ struct desktop_shell {
 		struct weston_process process;
 	} screensaver;
 
+	struct {
+		struct wl_resource *binding;
+		struct wl_list surfaces;
+	} input_panel;
+
 	uint32_t binding_modifier;
 	enum animation_type win_animation_type;
 	struct weston_surface *debug_repaint_surface;
@@ -129,6 +136,7 @@ enum shell_surface_type {
 	SHELL_SURFACE_BACKGROUND,
 	SHELL_SURFACE_LOCK,
 	SHELL_SURFACE_SCREENSAVER,
+	SHELL_SURFACE_INPUT_PANEL,
 
 	SHELL_SURFACE_TOPLEVEL,
 	SHELL_SURFACE_TRANSIENT,
@@ -1222,6 +1230,7 @@ reset_shell_surface_type(struct shell_surface *surface)
 		break;
 	case SHELL_SURFACE_PANEL:
 	case SHELL_SURFACE_BACKGROUND:
+	case SHELL_SURFACE_INPUT_PANEL:
 		wl_list_remove(&surface->link);
 		wl_list_init(&surface->link);
 		break;
@@ -1912,6 +1921,26 @@ hide_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
 }
 
 static void
+show_input_panel(struct desktop_shell *shell, struct shell_surface *surface)
+{
+	wl_list_remove(&surface->surface->layer_link);
+	wl_list_insert(&shell->panel_layer.surface_list, &surface->surface->layer_link);
+	surface->surface->output = surface->output;
+	weston_surface_damage(surface->surface);
+}
+
+static void
+hide_input_panel(struct desktop_shell *shell, struct shell_surface *surface)
+{
+	weston_surface_damage_below(surface->surface);
+	wl_list_remove(&surface->surface->layer_link);
+	wl_list_init(&surface->surface->layer_link);
+	surface->surface->output = NULL;
+
+	weston_compositor_schedule_repaint(surface->surface->compositor);
+}
+
+static void
 desktop_shell_set_background(struct wl_client *client,
 			     struct wl_resource *resource,
 			     struct wl_resource *output_resource,
@@ -2405,6 +2434,7 @@ activate(struct desktop_shell *shell, struct weston_surface *es,
 	case SHELL_SURFACE_BACKGROUND:
 	case SHELL_SURFACE_PANEL:
 	case SHELL_SURFACE_LOCK:
+	case SHELL_SURFACE_INPUT_PANEL:
 		break;
 
 	case SHELL_SURFACE_SCREENSAVER:
@@ -2537,6 +2567,30 @@ unlock(struct wl_listener *listener, void *data)
 }
 
 static void
+show_input_panels(struct wl_listener *listener, void *data)
+{
+	struct desktop_shell *shell =
+		container_of(listener, struct desktop_shell, show_input_panel_listener);
+	struct shell_surface *priv;
+
+	wl_list_for_each(priv, &shell->input_panel.surfaces, link) {
+		show_input_panel(shell, priv);
+	}
+}
+
+static void
+hide_input_panels(struct wl_listener *listener, void *data)
+{
+	struct desktop_shell *shell =
+		container_of(listener, struct desktop_shell, hide_input_panel_listener);
+	struct shell_surface *priv;
+
+	wl_list_for_each(priv, &shell->input_panel.surfaces, link) {
+		hide_input_panel(shell, priv);
+	}
+}
+
+static void
 center_on_output(struct weston_surface *surface, struct weston_output *output)
 {
 	struct weston_mode *mode = output->current;
@@ -2546,6 +2600,17 @@ center_on_output(struct weston_surface *surface, struct weston_output *output)
 	weston_surface_set_position(surface, output->x + x, output->y + y);
 }
 
+
+static void
+bottom_center_on_output(struct weston_surface *surface, struct weston_output *output)
+{
+	struct weston_mode *mode = output->current;
+	GLfloat x = (mode->width - surface->geometry.width) / 2;
+	GLfloat y = mode->height - surface->geometry.height;
+
+	weston_surface_set_position(surface, output->x + x, output->y + y);
+}
+
 static void
 map(struct desktop_shell *shell, struct weston_surface *surface,
     int32_t width, int32_t height, int32_t sx, int32_t sy)
@@ -2583,6 +2648,9 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
 	case SHELL_SURFACE_LOCK:
 		center_on_output(surface, get_default_output(compositor));
 		break;
+	case SHELL_SURFACE_INPUT_PANEL:
+		bottom_center_on_output(surface, get_default_output(compositor));
+		break;
 	case SHELL_SURFACE_POPUP:
 		shell_map_popup(shsurf);
 	case SHELL_SURFACE_NONE:
@@ -2629,6 +2697,7 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
 		break;
 	case SHELL_SURFACE_FULLSCREEN:
 	case SHELL_SURFACE_NONE:
+	case SHELL_SURFACE_INPUT_PANEL:
 		break;
 	default:
 		ws = get_current_workspace(shell);
@@ -2892,6 +2961,58 @@ bind_screensaver(struct wl_client *client,
 	wl_resource_destroy(resource);
 }
 
+static void
+input_panel_set_surface(struct wl_client *client,
+			struct wl_resource *resource,
+			struct wl_resource *shell_surface_resource,
+			struct wl_resource *output_resource)
+{
+	struct desktop_shell *shell = resource->data;
+	struct shell_surface *surface = shell_surface_resource->data;
+	struct weston_output *output = output_resource->data;
+
+	surface->next_type = SHELL_SURFACE_INPUT_PANEL;
+
+	surface->fullscreen_output = output;
+	surface->output = output;
+	wl_list_insert(shell->input_panel.surfaces.prev, &surface->link);
+}
+
+static const struct input_panel_interface input_panel_implementation = {
+	input_panel_set_surface
+};
+
+static void
+unbind_input_panel(struct wl_resource *resource)
+{
+	struct desktop_shell *shell = resource->data;
+
+	shell->input_panel.binding = NULL;
+	free(resource);
+}
+
+static void
+bind_input_panel(struct wl_client *client,
+	      void *data, uint32_t version, uint32_t id)
+{
+	struct desktop_shell *shell = data;
+	struct wl_resource *resource;
+
+	resource = wl_client_add_object(client, &input_panel_interface,
+					&input_panel_implementation,
+					id, shell);
+
+	if (shell->input_panel.binding == NULL) {
+		resource->destroy = unbind_input_panel;
+		shell->input_panel.binding = resource;
+		return;
+	}
+
+	wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+			       "interface object already bound");
+	wl_resource_destroy(resource);
+}
+
 struct switcher {
 	struct desktop_shell *shell;
 	struct weston_surface *current;
@@ -3162,6 +3283,8 @@ shell_destroy(struct wl_listener *listener, void *data)
 
 	wl_list_remove(&shell->lock_listener.link);
 	wl_list_remove(&shell->unlock_listener.link);
+	wl_list_remove(&shell->show_input_panel_listener.link);
+	wl_list_remove(&shell->hide_input_panel_listener.link);
 
 	wl_array_for_each(ws, &shell->workspaces.array)
 		workspace_destroy(*ws);
@@ -3257,6 +3380,10 @@ shell_init(struct weston_compositor *ec)
 	wl_signal_add(&ec->lock_signal, &shell->lock_listener);
 	shell->unlock_listener.notify = unlock;
 	wl_signal_add(&ec->unlock_signal, &shell->unlock_listener);
+	shell->show_input_panel_listener.notify = show_input_panels;
+	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);
 	ec->ping_handler = ping_handler;
 	ec->shell_interface.create_shell_surface = create_shell_surface;
 	ec->shell_interface.set_toplevel = set_toplevel;
@@ -3267,6 +3394,7 @@ shell_init(struct weston_compositor *ec)
 	wl_list_init(&shell->backgrounds);
 	wl_list_init(&shell->panels);
 	wl_list_init(&shell->screensaver.surfaces);
+	wl_list_init(&shell->input_panel.surfaces);
 
 	weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
 	weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
@@ -3304,6 +3432,10 @@ shell_init(struct weston_compositor *ec)
 				  shell, bind_screensaver) == NULL)
 		return -1;
 
+	if (wl_display_add_global(ec->wl_display, &input_panel_interface,
+				  shell, bind_input_panel) == NULL)
+		return -1;
+
 	shell->child.deathstamp = weston_compositor_get_time();
 	if (launch_desktop_shell_process(shell) != 0)
 		return -1;
-- 
1.7.10.4



More information about the wayland-devel mailing list