shell: Add support for input panels
authorJan Arne Petersen <jpetersen@openismus.com>
Thu, 21 Jun 2012 19:52:17 +0000 (21:52 +0200)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 21 Jun 2012 20:41:06 +0000 (16:41 -0400)
protocol/desktop-shell.xml
src/compositor.c
src/compositor.h
src/shell.c

index a9c181c..86e1063 100644 (file)
 
   </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>
index 4891e35..92e89d4 100644 (file)
@@ -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;
index ed09157..af094fe 100644 (file)
@@ -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;
 
index ff88818..7a3d068 100644 (file)
@@ -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;
@@ -1908,6 +1917,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,
@@ -2401,6 +2430,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:
@@ -2533,6 +2563,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;
@@ -2542,6 +2596,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)
@@ -2579,6 +2644,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:
@@ -2625,6 +2693,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);
@@ -2888,6 +2957,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;
@@ -3158,6 +3279,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);
@@ -3253,6 +3376,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;
@@ -3263,6 +3390,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);
@@ -3300,6 +3428,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;