summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Olbrich <m.olbrich@pengutronix.de>2023-02-02 09:36:28 +0100
committerMichael Olbrich <m.olbrich@pengutronix.de>2023-03-14 10:40:04 +0100
commit5d68a6c4b5c6e1a753d4bf055f341131d6b26e35 (patch)
treec5ca30714ffcde88846272a8206e79cdc80a9e75
parentad2c014ef37e7fc918d584d2ac3ef747ccaa2ce8 (diff)
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>
-rw-r--r--ivi-shell/ivi-layout-export.h66
-rw-r--r--ivi-shell/ivi-layout-private.h14
-rw-r--r--ivi-shell/ivi-layout-shell.h27
-rw-r--r--ivi-shell/ivi-layout.c153
-rw-r--r--ivi-shell/ivi-shell.c357
-rw-r--r--ivi-shell/ivi-shell.h16
6 files changed, 623 insertions, 10 deletions
diff --git a/ivi-shell/ivi-layout-export.h b/ivi-shell/ivi-layout-export.h
index 1e72241b..4ff5abcc 100644
--- a/ivi-shell/ivi-layout-export.h
+++ b/ivi-shell/ivi-layout-export.h
@@ -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 *
diff --git a/ivi-shell/ivi-layout-private.h b/ivi-shell/ivi-layout-private.h
index 0e0e0146..e74ff3e2 100644
--- a/ivi-shell/ivi-layout-private.h
+++ b/ivi-shell/ivi-layout-private.h
@@ -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);
diff --git a/ivi-shell/ivi-layout-shell.h b/ivi-shell/ivi-layout-shell.h
index ee275162..83762fc0 100644
--- a/ivi-shell/ivi-layout-shell.h
+++ b/ivi-shell/ivi-layout-shell.h
@@ -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,
@@ -48,6 +51,28 @@ 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);
diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c
index 7e6cb7ad..19dbe339 100644
--- a/ivi-shell/ivi-layout.c
+++ b/ivi-shell/ivi-layout.c
@@ -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,
};
diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c
index c0fc6046..c4430645 100644
--- a/ivi-shell/ivi-shell.c
+++ b/ivi-shell/ivi-shell.c
@@ -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)
@@ -678,6 +709,330 @@ static const struct weston_desktop_api shell_desktop_api = {
*/
/*
+ * 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.
*/
WL_EXPORT int
@@ -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);
diff --git a/ivi-shell/ivi-shell.h b/ivi-shell/ivi-shell.h
index 64a36d2d..fa206e6b 100644
--- a/ivi-shell/ivi-shell.h
+++ b/ivi-shell/ivi-shell.h
@@ -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 */