ivi-shell: add input panel support

Input panels are used for complex text composition for CJK alphabets and for
onscreen keyboards. Support for this is already implemented in libweston and
the desktop shell.

This adds extends the IVI shell to add support for input panels as well. The
low-level parts are implemented in the IVI shell. The positioning of the input
panels is delegated to the controller.
Support for input panels and the relevant protocols is only enabled if the
controller attaches a listener to the new signals.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
This commit is contained in:
Michael Olbrich 2023-02-02 09:36:28 +01:00
parent ad2c014ef3
commit 5d68a6c4b5
6 changed files with 623 additions and 10 deletions

View file

@ -69,6 +69,7 @@ struct ivi_layout_surface;
enum ivi_layout_surface_type {
IVI_LAYOUT_SURFACE_TYPE_IVI,
IVI_LAYOUT_SURFACE_TYPE_DESKTOP,
IVI_LAYOUT_SURFACE_TYPE_INPUT_PANEL,
};
struct ivi_layout_surface_properties
@ -115,6 +116,14 @@ struct ivi_layout_layer_properties
uint32_t event_mask;
};
struct ivi_layout_text_input_state
{
bool overlay_panel;
struct ivi_layout_surface *surface;
struct ivi_layout_surface *input_panel;
pixman_box32_t cursor_rectangle;
};
enum ivi_layout_notification_mask {
IVI_NOTIFICATION_NONE = 0,
IVI_NOTIFICATION_OPACITY = (1 << 1),
@ -613,8 +622,63 @@ struct ivi_layout_interface {
* \return IVI_SUCCEEDED if the method call was successful
* \return IVI_FAILED if the method call was failed
*/
int32_t (*shell_add_destroy_listener_once)(struct wl_listener *listener,
int32_t (*shell_add_destroy_listener_once)(struct wl_listener *listener,
wl_notify_func_t destroy_handler);
/**
* \brief add a listener for notification when input_panel_surface is
* configured
*
* When an input_panel_surface is configured, a signal is emitted
* to the listening controller plugins.
* The pointer of the configured input_panel_surface is sent as the void
* *data argument to the wl_listener::notify callback function of the
* listener.
*/
void (*add_listener_configure_input_panel_surface)(struct wl_listener *listener);
/**
* \brief add a listener for notification when an input_panel_surface
* should be shown.
*
* When a client requests input panels, this signal is emitted for all
* available input panels.
* A pointer to a struct ivi_layout_text_input_state is sent as the void
* *data argument to the wl_listener::notify callback function of the
* listener.
* It contains the surface that requested the input panel, the
* input_panel_surface that should be shown and whether the input panel
* is a toplevel o overlay panel.
* For overlay panels, the relevant cursor_rectangle is filled with
* coordinates relative to the client surface.
*/
void (*add_listener_show_input_panel)(struct wl_listener *listener);
/**
* \brief add a listener for notification when an input_panel_surface
* should be hidden.
*
* When a client requests that input panels are hidden, this signal is
* emitted for all available input panels.
* The pointer of the configured input_panel_surface is sent as the void
* *data argument to the wl_listener::notify callback function of the
* listener.
*/
void (*add_listener_hide_input_panel)(struct wl_listener *listener);
/**
* \brief add a listener for notification when an input_panel_surface
* should be updated.
*
* When the input panels need to be updated in some way, this signal is
* called for available input panels.
* This happens for example when the cursor_rectangle changes.
* A pointer to a struct ivi_layout_text_input_state is sent as the void
* *data argument to the wl_listener::notify callback function of the
* listener.
* See add_listener_show_input_panel for more details.
*/
void (*add_listener_update_input_panel)(struct wl_listener *listener);
};
static inline const struct ivi_layout_interface *

View file

@ -92,7 +92,7 @@ struct ivi_layout_layer {
};
struct ivi_layout {
struct weston_compositor *compositor;
struct ivi_shell *shell;
struct wl_list surface_list; /* ivi_layout_surface::link */
struct wl_list layer_list; /* ivi_layout_layer::link */
@ -115,6 +115,13 @@ struct ivi_layout {
struct wl_signal configure_desktop_changed;
} surface_notification;
struct {
struct wl_signal configure_changed;
struct wl_signal show;
struct wl_signal hide;
struct wl_signal update;
} input_panel_notification;
struct weston_layer layout_layer;
struct ivi_layout_transition_set *transitions;
@ -122,6 +129,11 @@ struct ivi_layout {
struct wl_listener output_created;
struct wl_listener output_destroyed;
struct {
struct ivi_layout_surface *ivisurf;
pixman_box32_t cursor_rectangle;
} text_input;
};
struct ivi_layout *get_instance(void);

View file

@ -27,6 +27,8 @@
#define IVI_LAYOUT_SHELL_H
#include <stdint.h>
#include <stdbool.h>
#include <pixman.h>
/*
* This is the interface that ivi-layout exposes to ivi-shell.
@ -38,6 +40,7 @@ struct weston_compositor;
struct weston_view;
struct weston_surface;
struct ivi_layout_surface;
struct ivi_shell;
void
ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
@ -47,6 +50,28 @@ struct ivi_layout_surface*
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
struct weston_desktop_surface *surface);
void
ivi_layout_input_panel_surface_configure(struct ivi_layout_surface *ivisurf,
int32_t width, int32_t height);
void
ivi_layout_update_text_input_cursor(pixman_box32_t *cursor_rectangle);
void
ivi_layout_show_input_panel(struct ivi_layout_surface *ivisurf,
struct ivi_layout_surface *target_ivisurf,
bool overlay_panel);
void
ivi_layout_hide_input_panel(struct ivi_layout_surface *ivisurf);
void
ivi_layout_update_input_panel(struct ivi_layout_surface *ivisurf,
bool overlay_panel);
struct ivi_layout_surface*
ivi_layout_input_panel_surface_create(struct weston_surface *wl_surface);
void
ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf,
int32_t width, int32_t height);
@ -56,7 +81,7 @@ ivi_layout_surface_create(struct weston_surface *wl_surface,
uint32_t id_surface);
void
ivi_layout_init_with_compositor(struct weston_compositor *ec);
ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell);
void
ivi_layout_fini(void);

View file

@ -28,7 +28,7 @@
* not updated until ivi_layout_commit_changes is called. An overview from
* calling API for updating properties of ivi_surface/ivi_layer to asking
* compositor to compose them by using weston_view_schedule_repaint,
* 0/ initialize this library by ivi_layout_init_with_compositor
* 0/ initialize this library by ivi_layout_init
* with (struct weston_compositor *ec) from ivi-shell.
* 1/ When an API for updating properties of ivi_surface/ivi_layer, it updates
* pending prop of ivi_surface/ivi_layer/ivi_screen which are structure to
@ -321,7 +321,7 @@ output_created_event(struct wl_listener *listener, void *data)
/**
* Internal API to initialize ivi_screens found from output_list of weston_compositor.
* Called by ivi_layout_init_with_compositor.
* Called by ivi_layout_init.
*/
static void
create_screen(struct weston_compositor *ec)
@ -1578,13 +1578,20 @@ void
ivi_layout_surface_set_size(struct ivi_layout_surface *ivisurf,
int32_t width, int32_t height)
{
if (weston_surface_is_desktop_surface(ivisurf->surface)) {
switch (ivisurf->prop.surface_type) {
case IVI_LAYOUT_SURFACE_TYPE_DESKTOP:
weston_desktop_surface_set_size(ivisurf->weston_desktop_surface,
width, height);
} else {
return;
case IVI_LAYOUT_SURFACE_TYPE_IVI:
shell_surface_send_configure(ivisurf->surface,
width, height);
return;
case IVI_LAYOUT_SURFACE_TYPE_INPUT_PANEL:
return;
}
/* there should be no other surface type */
assert(0);
}
static int32_t
@ -2018,6 +2025,127 @@ ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
return ivisurf;
}
struct ivi_layout_surface*
ivi_layout_input_panel_surface_create(struct weston_surface *wl_surface)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_surface *ivisurf;
ivisurf = surface_create(wl_surface, IVI_INVALID_ID,
IVI_LAYOUT_SURFACE_TYPE_INPUT_PANEL);
weston_signal_emit_mutable(&layout->surface_notification.created,
ivisurf);
return ivisurf;
}
void
ivi_layout_input_panel_surface_configure(struct ivi_layout_surface *ivisurf,
int32_t width, int32_t height)
{
struct ivi_layout *layout = get_instance();
weston_signal_emit_mutable(&layout->input_panel_notification.configure_changed,
ivisurf);
}
void
ivi_layout_update_text_input_cursor(pixman_box32_t *cursor_rectangle)
{
struct ivi_layout *layout = get_instance();
memcpy(&layout->text_input.cursor_rectangle, cursor_rectangle,
sizeof(pixman_box32_t));
}
void
ivi_layout_show_input_panel(struct ivi_layout_surface *ivisurf,
struct ivi_layout_surface *target_ivisurf,
bool overlay_panel)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_text_input_state state = {
.overlay_panel = overlay_panel,
.input_panel = ivisurf,
.surface = target_ivisurf,
.cursor_rectangle = layout->text_input.cursor_rectangle
};
layout->text_input.ivisurf = target_ivisurf;
weston_signal_emit_mutable(&layout->input_panel_notification.show,
&state);
}
void
ivi_layout_hide_input_panel(struct ivi_layout_surface *ivisurf)
{
struct ivi_layout *layout = get_instance();
weston_signal_emit_mutable(&layout->input_panel_notification.hide,
ivisurf);
}
void
ivi_layout_update_input_panel(struct ivi_layout_surface *ivisurf,
bool overlay_panel)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_text_input_state state = {
.overlay_panel = overlay_panel,
.input_panel = ivisurf,
.surface =layout->text_input.ivisurf,
.cursor_rectangle = layout->text_input.cursor_rectangle
};
weston_signal_emit_mutable(&layout->input_panel_notification.update,
&state);
}
static void
ivi_layout_add_listener_configure_input_panel_surface(struct wl_listener *listener)
{
struct ivi_layout *layout = get_instance();
assert(listener);
wl_signal_add(&layout->input_panel_notification.configure_changed, listener);
shell_ensure_text_input(layout->shell);
}
static void
ivi_layout_add_listener_show_input_panel(struct wl_listener *listener)
{
struct ivi_layout *layout = get_instance();
assert(listener);
wl_signal_add(&layout->input_panel_notification.show, listener);
shell_ensure_text_input(layout->shell);
}
static void
ivi_layout_add_listener_hide_input_panel(struct wl_listener *listener)
{
struct ivi_layout *layout = get_instance();
assert(listener);
wl_signal_add(&layout->input_panel_notification.hide, listener);
shell_ensure_text_input(layout->shell);
}
static void
ivi_layout_add_listener_update_input_panel(struct wl_listener *listener)
{
struct ivi_layout *layout = get_instance();
assert(listener);
wl_signal_add(&layout->input_panel_notification.update, listener);
shell_ensure_text_input(layout->shell);
}
void
ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf,
int32_t width, int32_t height)
@ -2064,11 +2192,11 @@ ivi_layout_ivi_shell_destroy(void)
static struct ivi_layout_interface ivi_layout_interface;
void
ivi_layout_init_with_compositor(struct weston_compositor *ec)
ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
{
struct ivi_layout *layout = get_instance();
layout->compositor = ec;
layout->shell = shell;
wl_list_init(&layout->surface_list);
wl_list_init(&layout->layer_list);
@ -2083,6 +2211,11 @@ ivi_layout_init_with_compositor(struct weston_compositor *ec)
wl_signal_init(&layout->surface_notification.configure_changed);
wl_signal_init(&layout->surface_notification.configure_desktop_changed);
wl_signal_init(&layout->input_panel_notification.configure_changed);
wl_signal_init(&layout->input_panel_notification.show);
wl_signal_init(&layout->input_panel_notification.hide);
wl_signal_init(&layout->input_panel_notification.update);
wl_signal_init(&layout->shell_notification.destroy_signal);
/* Add layout_layer at the last of weston_compositor.layer_list */
@ -2195,4 +2328,12 @@ static struct ivi_layout_interface ivi_layout_interface = {
* shell interfaces
*/
.shell_add_destroy_listener_once = ivi_layout_shell_add_destroy_listener_once,
/**
* input panel
*/
.add_listener_configure_input_panel_surface = ivi_layout_add_listener_configure_input_panel_surface,
.add_listener_show_input_panel = ivi_layout_add_listener_show_input_panel,
.add_listener_hide_input_panel = ivi_layout_add_listener_hide_input_panel,
.add_listener_update_input_panel = ivi_layout_add_listener_update_input_panel,
};

View file

@ -42,10 +42,12 @@
#include <assert.h>
#include <linux/input.h>
#include "input-method-unstable-v1-server-protocol.h"
#include "ivi-shell.h"
#include "ivi-application-server-protocol.h"
#include "ivi-layout-private.h"
#include "ivi-layout-shell.h"
#include "libweston/libweston.h"
#include "shared/helpers.h"
#include "shared/xalloc.h"
#include "compositor/weston.h"
@ -71,6 +73,28 @@ struct ivi_shell_surface
struct wl_list link;
};
struct ivi_input_panel_surface
{
struct wl_resource* resource;
struct ivi_shell *shell;
struct ivi_layout_surface *layout_surface;
struct weston_surface *surface;
struct wl_listener surface_destroy_listener;
int32_t width;
int32_t height;
struct weston_output *output;
enum {
INPUT_PANEL_NONE,
INPUT_PANEL_TOPLEVEL,
INPUT_PANEL_OVERLAY,
} type;
struct wl_list link;
};
/*
* Implementation of ivi_surface
*/
@ -333,6 +357,9 @@ bind_ivi_application(struct wl_client *client,
shell, NULL);
}
void
input_panel_destroy(struct ivi_shell *shell);
/*
* Called through the compositor's destroy signal.
*/
@ -348,6 +375,10 @@ shell_destroy(struct wl_listener *listener, void *data)
wl_list_remove(&shell->destroy_listener.link);
wl_list_remove(&shell->wake_listener.link);
if (shell->text_backend) {
text_backend_destroy(shell->text_backend);
input_panel_destroy(shell);
}
wl_list_for_each_safe(ivisurf, next, &shell->ivi_surface_list, link) {
if (ivisurf->layout_surface != NULL)
@ -677,6 +708,330 @@ static const struct weston_desktop_api shell_desktop_api = {
* end of libweston-desktop
*/
/*
* input panel
*/
static void
maybe_show_input_panel(struct ivi_input_panel_surface *ipsurf,
struct ivi_shell_surface *target_ivisurf)
{
if (ipsurf->surface->width == 0)
return;
if (ipsurf->type == INPUT_PANEL_NONE)
return;
ivi_layout_show_input_panel(ipsurf->layout_surface,
target_ivisurf->layout_surface,
ipsurf->type == INPUT_PANEL_OVERLAY);
}
static void
show_input_panels(struct wl_listener *listener, void *data)
{
struct ivi_shell *shell = container_of(listener, struct ivi_shell,
show_input_panel_listener);
struct ivi_shell_surface *target_ivisurf;
struct ivi_input_panel_surface *ipsurf;
target_ivisurf = get_ivi_shell_surface(data);
if (!target_ivisurf)
return;
if (shell->text_input_surface)
return;
shell->text_input_surface = target_ivisurf;
wl_list_for_each(ipsurf, &shell->input_panel.surfaces, link)
maybe_show_input_panel(ipsurf, target_ivisurf);
}
static void
hide_input_panels(struct wl_listener *listener, void *data)
{
struct ivi_shell *shell = container_of(listener, struct ivi_shell,
hide_input_panel_listener);
struct ivi_input_panel_surface *ipsurf;
if (!shell->text_input_surface)
return;
shell->text_input_surface = NULL;
wl_list_for_each(ipsurf, &shell->input_panel.surfaces, link)
ivi_layout_hide_input_panel(ipsurf->layout_surface);
}
static void
update_input_panels(struct wl_listener *listener, void *data)
{
ivi_layout_update_text_input_cursor(data);
}
static int
input_panel_get_label(struct weston_surface *surface, char *buf, size_t len)
{
return snprintf(buf, len, "input panel");
}
static void
input_panel_committed(struct weston_surface *surface,
struct weston_coord_surface new_origin)
{
struct ivi_input_panel_surface *ipsurf = surface->committed_private;
struct ivi_shell *shell = ipsurf->shell;
if (surface->width == 0 || surface->height == 0)
return;
if (ipsurf->width != surface->width ||
ipsurf->height != surface->height) {
ipsurf->width = surface->width;
ipsurf->height = surface->height;
ivi_layout_input_panel_surface_configure(ipsurf->layout_surface,
surface->width,
surface->height);
}
if (shell->text_input_surface)
maybe_show_input_panel(ipsurf, shell->text_input_surface);
}
bool
shell_is_input_panel_surface(struct weston_surface *surface)
{
return surface->committed == input_panel_committed;
}
static struct ivi_input_panel_surface *
get_input_panel_surface(struct weston_surface *surface)
{
if (shell_is_input_panel_surface(surface))
return surface->committed_private;
else
return NULL;
}
static void
input_panel_handle_surface_destroy(struct wl_listener *listener, void *data)
{
struct ivi_input_panel_surface *ipsurf =
container_of(listener, struct ivi_input_panel_surface,
surface_destroy_listener);
wl_resource_destroy(ipsurf->resource);
}
static struct ivi_input_panel_surface *
create_input_panel_surface(struct ivi_shell *shell,
struct weston_surface *surface)
{
struct ivi_input_panel_surface *ipsurf;
struct ivi_layout_surface *layout_surface;
layout_surface = ivi_layout_input_panel_surface_create(surface);
ipsurf = xzalloc(sizeof *ipsurf);
surface->committed = input_panel_committed;
surface->committed_private = ipsurf;
weston_surface_set_label_func(surface, input_panel_get_label);
wl_list_init(&ipsurf->link);
wl_list_insert(&shell->input_panel.surfaces, &ipsurf->link);
ipsurf->shell = shell;
ipsurf->width = 0;
ipsurf->height = 0;
ipsurf->layout_surface = layout_surface;
ipsurf->surface = surface;
if (surface->width && surface->height) {
ipsurf->width = surface->width;
ipsurf->height = surface->height;
ivi_layout_input_panel_surface_configure(ipsurf->layout_surface,
surface->width,
surface->height);
}
ipsurf->surface_destroy_listener.notify = input_panel_handle_surface_destroy;
wl_signal_add(&surface->destroy_signal,
&ipsurf->surface_destroy_listener);
return ipsurf;
}
static void
input_panel_surface_set_toplevel(struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *output_resource,
uint32_t position)
{
struct ivi_input_panel_surface *ipsurf =
wl_resource_get_user_data(resource);
struct weston_head *head;
head = weston_head_from_resource(output_resource);
ipsurf->type = INPUT_PANEL_TOPLEVEL;
ipsurf->output = head->output;
}
static void
input_panel_surface_set_overlay_panel(struct wl_client *client,
struct wl_resource *resource)
{
struct ivi_input_panel_surface *ipsurf =
wl_resource_get_user_data(resource);
ipsurf->type = INPUT_PANEL_OVERLAY;
}
static const struct zwp_input_panel_surface_v1_interface input_panel_surface_implementation = {
input_panel_surface_set_toplevel,
input_panel_surface_set_overlay_panel
};
static void
destroy_input_panel_surface_resource(struct wl_resource *resource)
{
struct ivi_input_panel_surface *ipsurf =
wl_resource_get_user_data(resource);
assert(ipsurf->resource == resource);
ivi_layout_surface_destroy(ipsurf->layout_surface);
ipsurf->layout_surface = NULL;
ipsurf->surface->committed = NULL;
ipsurf->surface->committed_private = NULL;
weston_surface_set_label_func(ipsurf->surface, NULL);
ipsurf->surface = NULL;
wl_list_remove(&ipsurf->surface_destroy_listener.link);
wl_list_remove(&ipsurf->link);
free(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 =
wl_resource_get_user_data(surface_resource);
struct ivi_shell *shell = wl_resource_get_user_data(resource);
struct ivi_input_panel_surface *ipsurf;
if (get_input_panel_surface(surface)) {
wl_resource_post_error(surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"wl_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->committed already set");
return;
}
ipsurf->resource =
wl_resource_create(client,
&zwp_input_panel_surface_v1_interface,
1,
id);
wl_resource_set_implementation(ipsurf->resource,
&input_panel_surface_implementation,
ipsurf,
destroy_input_panel_surface_resource);
}
static const struct zwp_input_panel_v1_interface input_panel_implementation = {
input_panel_get_input_panel_surface
};
static void
unbind_input_panel(struct wl_resource *resource)
{
struct ivi_shell *shell = wl_resource_get_user_data(resource);
shell->input_panel.binding = NULL;
}
static void
bind_input_panel(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
{
struct ivi_shell *shell = data;
struct wl_resource *resource;
resource = wl_resource_create(client,
&zwp_input_panel_v1_interface, 1, id);
if (shell->input_panel.binding == NULL) {
wl_resource_set_implementation(resource,
&input_panel_implementation,
shell, unbind_input_panel);
shell->input_panel.binding = resource;
return;
}
wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
"interface object already bound");
}
void
input_panel_destroy(struct ivi_shell *shell)
{
wl_list_remove(&shell->show_input_panel_listener.link);
wl_list_remove(&shell->hide_input_panel_listener.link);
wl_list_remove(&shell->update_input_panel_listener.link);
}
static void
input_panel_setup(struct ivi_shell *shell)
{
struct weston_compositor *ec = shell->compositor;
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);
shell->update_input_panel_listener.notify = update_input_panels;
wl_signal_add(&ec->update_input_panel_signal,
&shell->update_input_panel_listener);
wl_list_init(&shell->input_panel.surfaces);
abort_oom_if_null(wl_global_create(shell->compositor->wl_display,
&zwp_input_panel_v1_interface, 1,
shell, bind_input_panel));
}
void
shell_ensure_text_input(struct ivi_shell *shell)
{
if (shell->text_backend)
return;
shell->text_backend = text_backend_init(shell->compositor);
input_panel_setup(shell);
}
/*
* end of input panel
*/
/*
* Initialization of ivi-shell.
*/
@ -709,7 +1064,7 @@ wet_shell_init(struct weston_compositor *compositor,
shell, bind_ivi_application) == NULL)
goto err_desktop;
ivi_layout_init_with_compositor(compositor);
ivi_layout_init(compositor, shell);
screenshooter_create(compositor);

View file

@ -36,11 +36,22 @@ struct ivi_shell
{
struct wl_listener destroy_listener;
struct wl_listener wake_listener;
struct wl_listener show_input_panel_listener;
struct wl_listener hide_input_panel_listener;
struct wl_listener update_input_panel_listener;
struct weston_compositor *compositor;
struct weston_desktop *desktop;
struct wl_list ivi_surface_list; /* struct ivi_shell_surface::link */
struct text_backend *text_backend;
struct ivi_shell_surface *text_input_surface;
struct {
struct wl_resource *binding;
struct wl_list surfaces;
} input_panel;
};
void
@ -52,4 +63,9 @@ struct ivi_layout_surface;
struct ivi_layout_surface *
shell_get_ivi_layout_surface(struct weston_surface *surface);
void
shell_ensure_text_input(struct ivi_shell *shell);
bool
shell_is_input_panel_surface(struct weston_surface *surface);
#endif /* WESTON_IVI_SHELL_H */