[PATCH 18/18] text: Move input_panel interface to input-method

Weng Xuetian wengxt at gmail.com
Wed Jan 16 14:34:23 PST 2013


On Wednesday 16 January 2013 21:26:55,Jan Arne Petersen :
> From: Jan Arne Petersen <jpetersen at openismus.com>
> 
> 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 <jpetersen at openismus.com>
> ---
>  clients/keyboard.c         |  11 ++--
>  protocol/desktop-shell.xml |  18 ------
>  protocol/input-method.xml  |  24 ++++++++
>  src/shell.c                | 141
> ++++++++++++++++++++++++++++++++++----------- 4 files changed, 138
> insertions(+), 56 deletions(-)
> 
> diff --git a/clients/keyboard.c b/clients/keyboard.c
> index 564afef..986dcff 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 2b6afbd..d48c3dd 100644
> --- a/protocol/desktop-shell.xml
> +++ b/protocol/desktop-shell.xml
> @@ -98,22 +98,4 @@
>      </request>
> 
>    </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_surface"/>
> -      <arg name="output" type="object" interface="wl_output"/>
> -    </request>
> -
> -  </interface>
> -
> -
>  </protocol>
> diff --git a/protocol/input-method.xml b/protocol/input-method.xml
> index d23b0b8..b4ffa72 100644
> --- a/protocol/input-method.xml
> +++ b/protocol/input-method.xml
> @@ -157,4 +157,28 @@
>        <arg name="context" type="object" interface="input_method_context"/>
>      </event>
>    </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="get_input_panel_surface">
> +      <arg name="id" type="new_id" interface="input_panel_surface"/>
> +      <arg name="surface" type="object" interface="wl_surface"/>
> +    </request>
> +  </interface>
> +
> +  <interface name="input_panel_surface" version="1">
> +    <enum name="position">
> +      <entry name="center_bottom" value="0"/>
> +    </enum>
> +
> +    <request name="set_toplevel">
> +      <description summary="set the surface type as a keyboard">
> +	A keybaord surface is only shown, when a text model is active
> +      </description>
> +      <arg name="position" type="uint"/>
> +    </request>
> +  </interface>
>  </protocol>
> diff --git a/src/shell.c b/src/shell.c
> index 898d228..a3b9d4c 100644
> --- a/src/shell.c
> +++ b/src/shell.c
> @@ -35,6 +35,7 @@
>  #include <wayland-server.h>
>  #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 {
> @@ -3245,59 +3250,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 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_set_surface(struct wl_client *client,
> -			struct wl_resource *resource,
> -			struct wl_resource *surface_resource,
> -			struct wl_resource *output_resource)
> +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
So what's the plan for show input panel at the position of the current focused 
cursor?

In that case it's more complicated, in all current implementation, by default 
is shown at the bottom of the rect, with some offset. And if you take offset 
into consideration, you will miss the part that in X we can know everything 
about the screen, input method will want to keep the input panel in one screen 
in multi screen settings.

And some fancy implementation use a comic style popup, which have a pointer 
points to the current position, http://wstaw.org/m/2012/08/31/gs-kimpanel.png 
. While keep the input panel inside one screen, the pointer will still point 
to the exact position of current cursor rect.

Any plan about how can this be achieved (in the future)?

Regards
Xuetian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20130116/730488d2/attachment.pgp>


More information about the wayland-devel mailing list