shell: Add support for input panels

This commit is contained in:
Jan Arne Petersen 2012-06-21 21:52:17 +02:00 committed by Kristian Høgsberg
parent 8634f51b63
commit 42feced8de
4 changed files with 154 additions and 0 deletions

View File

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

View 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;

View 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;

View 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;
@ -1907,6 +1916,26 @@ hide_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
surface->surface->output = NULL;
}
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,
@ -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:
@ -2532,6 +2562,30 @@ unlock(struct wl_listener *listener, void *data)
shell->prepare_event_sent = true;
}
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)
{
@ -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;