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 <jpetersen@openismus.com>
This commit is contained in:
Jan Arne Petersen 2013-01-16 21:26:55 +01:00 committed by Kristian Høgsberg
parent 23ccfb3ef9
commit ffbb20f730
4 changed files with 139 additions and 57 deletions

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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 {
@ -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