From ffbb20f730e63b6d5d1710fa06f37931271f0de0 Mon Sep 17 00:00:00 2001 From: Jan Arne Petersen Date: Wed, 16 Jan 2013 21:26:55 +0100 Subject: [PATCH] text: Move input_panel interface to input-method Move the input_panel interface from desktop-shell to input-method (since it is not really tied to desktop-shell). Add an input_panel_surface interface like wl_shell_surface to make it easier to extend it. Also add a parameter to the set_toplevel request to be able to specify where to show an input panel surface on the screen. Signed-off-by: Jan Arne Petersen --- clients/keyboard.c | 11 +-- protocol/desktop-shell.xml | 18 ----- protocol/input-method.xml | 24 +++++++ src/shell.c | 143 ++++++++++++++++++++++++++++--------- 4 files changed, 139 insertions(+), 57 deletions(-) diff --git a/clients/keyboard.c b/clients/keyboard.c index 564afefd..986dcff7 100644 --- a/clients/keyboard.c +++ b/clients/keyboard.c @@ -31,8 +31,6 @@ #include "window.h" #include "input-method-client-protocol.h" #include "text-client-protocol.h" -#include "desktop-shell-client-protocol.h" - struct virtual_keyboard { struct input_panel *input_panel; @@ -641,6 +639,7 @@ keyboard_create(struct output *output, struct virtual_keyboard *virtual_keyboard { struct keyboard *keyboard; const struct layout *layout; + struct input_panel_surface *ips; layout = get_current_layout(virtual_keyboard); @@ -664,9 +663,11 @@ keyboard_create(struct output *output, struct virtual_keyboard *virtual_keyboard layout->columns * key_width, layout->rows * key_height); - input_panel_set_surface(virtual_keyboard->input_panel, - window_get_wl_surface(keyboard->window), - output_get_wl_output(output)); + + ips = input_panel_get_input_panel_surface(virtual_keyboard->input_panel, + window_get_wl_surface(keyboard->window)); + + input_panel_surface_set_toplevel(ips, INPUT_PANEL_SURFACE_POSITION_CENTER_BOTTOM); } static void diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml index 2b6afbd2..d48c3dd3 100644 --- a/protocol/desktop-shell.xml +++ b/protocol/desktop-shell.xml @@ -98,22 +98,4 @@ - - - - Only one client can bind this interface at a time. - - - - - A keybaord surface is only shown, when a text model is active - - - - - - - - - diff --git a/protocol/input-method.xml b/protocol/input-method.xml index d23b0b8a..b4ffa726 100644 --- a/protocol/input-method.xml +++ b/protocol/input-method.xml @@ -157,4 +157,28 @@ + + + + Only one client can bind this interface at a time. + + + + + + + + + + + + + + + + A keybaord surface is only shown, when a text model is active + + + + diff --git a/src/shell.c b/src/shell.c index 1b304e18..4d5a4f3b 100644 --- a/src/shell.c +++ b/src/shell.c @@ -35,6 +35,7 @@ #include #include "compositor.h" #include "desktop-shell-server-protocol.h" +#include "input-method-server-protocol.h" #include "workspaces-server-protocol.h" #include "../shared/config-parser.h" @@ -65,9 +66,13 @@ struct workspace { }; struct input_panel_surface { + struct wl_resource resource; + + struct desktop_shell *shell; + struct wl_list link; struct weston_surface *surface; - struct wl_listener listener; + struct wl_listener surface_destroy_listener; }; struct desktop_shell { @@ -3282,59 +3287,129 @@ input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy) } static void -destroy_input_panel_surface(struct wl_listener *listener, - void *data) +destroy_input_panel_surface(struct input_panel_surface *input_panel_surface) { - struct input_panel_surface *input_panel_surface = - container_of(listener, struct input_panel_surface, listener); - - wl_list_remove(&listener->link); + wl_list_remove(&input_panel_surface->surface_destroy_listener.link); wl_list_remove(&input_panel_surface->link); + input_panel_surface->surface->configure = NULL; + free(input_panel_surface); } -static void -input_panel_set_surface(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *surface_resource, - struct wl_resource *output_resource) +static struct input_panel_surface * +get_input_panel_surface(struct weston_surface *surface) +{ + if (surface->configure == input_panel_configure) { + return surface->private; + } else { + return NULL; + } +} + +static void +input_panel_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct input_panel_surface *ipsurface = container_of(listener, + struct input_panel_surface, + surface_destroy_listener); + + if (ipsurface->resource.client) { + wl_resource_destroy(&ipsurface->resource); + } else { + wl_signal_emit(&ipsurface->resource.destroy_signal, + &ipsurface->resource); + destroy_input_panel_surface(ipsurface); + } +} +static struct input_panel_surface * +create_input_panel_surface(struct desktop_shell *shell, + struct weston_surface *surface) { - struct desktop_shell *shell = resource->data; - struct weston_surface *surface = surface_resource->data; - struct weston_output *output = output_resource->data; struct input_panel_surface *input_panel_surface; + input_panel_surface = calloc(1, sizeof *input_panel_surface); + if (!input_panel_surface) + return NULL; + surface->configure = input_panel_configure; - surface->private = shell; - surface->output = output; + surface->private = input_panel_surface; - /* Do not do anything when surface is already in the list of - * input panel surfaces - */ - wl_list_for_each(input_panel_surface, &shell->input_panel.surfaces, link) { - if (input_panel_surface->surface == surface) - return; - } - - input_panel_surface = malloc(sizeof *input_panel_surface); - if (!input_panel_surface) { - wl_resource_post_no_memory(resource); - return; - } + input_panel_surface->shell = shell; input_panel_surface->surface = surface; - input_panel_surface->listener.notify = destroy_input_panel_surface; - wl_signal_add(&surface_resource->destroy_signal, - &input_panel_surface->listener); + wl_signal_init(&input_panel_surface->resource.destroy_signal); + input_panel_surface->surface_destroy_listener.notify = input_panel_handle_surface_destroy; + wl_signal_add(&surface->surface.resource.destroy_signal, + &input_panel_surface->surface_destroy_listener); + + wl_list_init(&input_panel_surface->link); + + return input_panel_surface; +} + +static void +input_panel_surface_set_toplevel(struct wl_client *client, + struct wl_resource *resource, + uint32_t position) +{ + 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); } +static const struct input_panel_surface_interface input_panel_surface_implementation = { + input_panel_surface_set_toplevel +}; + +static void +destroy_input_panel_surface_resource(struct wl_resource *resource) +{ + struct input_panel_surface *ipsurf = resource->data; + + destroy_input_panel_surface(ipsurf); +} + +static void +input_panel_get_input_panel_surface(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *surface_resource) +{ + struct weston_surface *surface = surface_resource->data; + struct desktop_shell *shell = resource->data; + struct input_panel_surface *ipsurf; + + if (get_input_panel_surface(surface)) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "input_panel::get_input_panel_surface already requested"); + return; + } + + ipsurf = create_input_panel_surface(shell, surface); + if (!ipsurf) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "surface->configure already set"); + return; + } + + ipsurf->resource.destroy = destroy_input_panel_surface_resource; + ipsurf->resource.object.id = id; + ipsurf->resource.object.interface = &input_panel_surface_interface; + ipsurf->resource.object.implementation = + (void (**)(void)) &input_panel_surface_implementation; + ipsurf->resource.data = ipsurf; + + wl_client_add_resource(client, &ipsurf->resource); +} + static const struct input_panel_interface input_panel_implementation = { - input_panel_set_surface + input_panel_get_input_panel_surface }; static void