[RFC PATCH 06/12] tablet-shell: Applications can run on tablet
juan.j.zhao at linux.intel.com
juan.j.zhao at linux.intel.com
Fri Aug 3 04:21:35 PDT 2012
From: Juan Zhao <juan.j.zhao at intel.com>
Add a event in tablet-client. When a client is connected to server, the
set_fullscreen event would be sent. and client will call shell_surface's
set_fullscreen method to be fullscreen.
Client application like dnd clickdot can run on tablet-shell.
listener is added in window.c and that can be moved to application side.
And simple-egl is still not sure how to resize the egl surface, so this
version can't run fullscreen.
Signed-off-by: Tang Ning <tecton69 at gmail.com>
---
clients/Makefile.am | 9 +-
clients/window.c | 23 +++
protocol/tablet-shell.xml | 2 +
src/tablet-shell.c | 383 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 415 insertions(+), 2 deletions(-)
diff --git a/clients/Makefile.am b/clients/Makefile.am
index 133eaca..a1cb865 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -24,7 +24,10 @@ simple_clients_programs = \
simple-shm \
simple-touch
-simple_egl_SOURCES = simple-egl.c
+simple_egl_SOURCES = \
+ simple-egl.c \
+ tablet-shell-client-protocol.h \
+ tablet-shell-protocol.c
simple_egl_CPPFLAGS = $(SIMPLE_CLIENT_CFLAGS)
simple_egl_LDADD = $(SIMPLE_CLIENT_LIBS) -lm
@@ -66,7 +69,9 @@ libtoytoolkit_a_SOURCES = \
window.c \
window.h \
text-cursor-position-protocol.c \
- text-cursor-position-client-protocol.h
+ text-cursor-position-client-protocol.h \
+ tablet-shell-client-protocol.h \
+ tablet-shell-protocol.c
toolkit_libs = \
libtoytoolkit.a \
diff --git a/clients/window.c b/clients/window.c
index d0b7a7d..18447d5 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -63,6 +63,7 @@
#include "../shared/cairo-util.h"
#include "text-cursor-position-client-protocol.h"
#include "../shared/os-compatibility.h"
+#include "tablet-shell-client-protocol.h"
#include "window.h"
@@ -74,6 +75,7 @@ struct display {
struct wl_shell *shell;
struct wl_shm *shm;
struct wl_data_device_manager *data_device_manager;
+ struct tablet_client *tablet_client;
struct text_cursor_position *text_cursor_position;
EGLDisplay dpy;
EGLConfig argb_config;
@@ -3247,6 +3249,22 @@ static const struct wl_output_listener output_listener = {
};
static void
+tablet_client_handle_set_fullscreen(void *data,
+ struct tablet_client *tablet_client)
+{
+ struct display *display = data;
+ struct window *window;
+ wl_list_for_each (window, &display->window_list, link) {
+ if (window->fullscreen_handler)
+ window->fullscreen_handler(window, window->user_data);
+ }
+}
+
+static const struct tablet_client_listener tablet_client_listener = {
+ tablet_client_handle_set_fullscreen
+};
+
+static void
display_add_output(struct display *d, uint32_t id)
{
struct output *output;
@@ -3411,6 +3429,11 @@ display_handle_global(struct wl_display *display, uint32_t id,
d->text_cursor_position =
wl_display_bind(display, id,
&text_cursor_position_interface);
+ } else if (strcmp(interface, "tablet_client") == 0) {
+ d->tablet_client =
+ wl_display_bind(display, id, &tablet_client_interface);
+ tablet_client_add_listener(d->tablet_client,
+ &tablet_client_listener, d);
}
}
diff --git a/protocol/tablet-shell.xml b/protocol/tablet-shell.xml
index 10f1756..430f346 100644
--- a/protocol/tablet-shell.xml
+++ b/protocol/tablet-shell.xml
@@ -35,6 +35,8 @@
<interface name="tablet_client" version="1">
<request name="destroy" type="destructor"/>
<request name="activate"/>
+
+ <event name="set_fullscreen" />
</interface>
</protocol>
diff --git a/src/tablet-shell.c b/src/tablet-shell.c
index f17d888..b2db2b7 100644
--- a/src/tablet-shell.c
+++ b/src/tablet-shell.c
@@ -45,6 +45,7 @@ enum {
struct tablet_shell {
struct wl_resource resource;
+ struct wl_resource client_resource;
struct wl_listener lock_listener;
struct wl_listener unlock_listener;
@@ -75,6 +76,36 @@ struct tablet_shell {
struct wl_event_source *long_press_source;
};
+struct ping_timer {
+ struct wl_event_source *source;
+ uint32_t serial;
+};
+
+struct shell_surface {
+ struct wl_resource resource;
+
+ struct weston_surface *surface;
+ struct weston_surface *parent_surface;
+ struct wl_listener surface_destroy_listener;
+ struct tablet_shell *shell;
+
+ char *path, *class;
+ char *title;
+ int unresponsive;
+ struct ping_timer *ping_timer;
+ struct weston_output *output;
+ struct wl_list link;
+
+ int is_fullscreen;
+ struct {
+ enum wl_shell_surface_fullscreen_method type;
+ struct weston_transform transform;
+ uint32_t framerate;
+ } fullscreen;
+
+ const struct weston_shell_client *client;
+};
+
struct tablet_client {
struct wl_resource resource;
struct tablet_shell *shell;
@@ -84,6 +115,283 @@ struct tablet_client {
};
static void
+tablet_shell_surface_configure(struct weston_surface *surface,
+ int32_t sx, int32_t sy);
+
+static void
+shell_surface_configure(struct weston_surface *surface,
+ int32_t sx, int32_t sy);
+
+static struct shell_surface *
+get_shell_surface(struct weston_surface *surface)
+{
+ if (surface->configure == shell_surface_configure)
+ return surface->private;
+ else
+ return NULL;
+}
+
+static void
+ping_timer_destroy(struct shell_surface *shsurf)
+{
+ if (!shsurf || !shsurf->ping_timer)
+ return;
+
+ if (shsurf->ping_timer->source)
+ wl_event_source_remove(shsurf->ping_timer->source);
+
+ free(shsurf->ping_timer);
+ shsurf->ping_timer = NULL;
+}
+static void
+shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
+ uint32_t serial)
+{
+ struct shell_surface *shsurf = resource->data;
+ int was_unresponsive;
+
+ if (shsurf->ping_timer->serial == serial) {
+ was_unresponsive = shsurf->unresponsive;
+ shsurf->unresponsive = 0;
+ if (was_unresponsive) {
+ // Received pong from previous...
+ }
+ ping_timer_destroy(shsurf);
+ }
+}
+
+static void
+shell_surface_set_title(struct wl_client *client,
+ struct wl_resource *resource, const char *title)
+{
+ return;
+}
+static void
+shell_surface_set_class(struct wl_client *client,
+ struct wl_resource *resource, const char *class)
+{
+ return;
+}
+
+static void
+shell_surface_move(struct wl_client *client, struct wl_resource *resource,
+ struct wl_resource *seat_resource, uint32_t serial)
+{
+ return;
+}
+static void
+shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
+ struct wl_resource *seat_resource, uint32_t serial,
+ uint32_t edges)
+{
+ return;
+}
+
+static void
+shell_surface_set_toplevel(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ return;
+}
+
+static void
+shell_surface_set_transient(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *parent_resource,
+ int x, int y, uint32_t flags)
+{
+ return;
+}
+static void
+shell_surface_set_fullscreen(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t method,
+ uint32_t framerate,
+ struct wl_resource *output_resource)
+{
+ struct shell_surface *shsurf = resource->data;
+ struct weston_surface *es = shsurf->surface;
+
+ if (output_resource)
+ shsurf->output = output_resource->data;
+ else
+ shsurf->output = container_of(es->compositor->output_list.next,
+ struct weston_output, link);
+
+ shsurf->client->send_configure(shsurf->surface, 0,
+ shsurf->output->current->width,
+ shsurf->output->current->height);
+}
+
+static void
+shell_surface_set_popup(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *seat_resource,
+ uint32_t serial,
+ struct wl_resource *parent_resource,
+ int32_t x, int32_t y, uint32_t flags)
+{
+ return;
+}
+
+static void
+shell_surface_set_maximized(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *output_resource)
+{
+ return;
+}
+static const struct wl_shell_surface_interface shell_surface_implementation = {
+ shell_surface_pong,
+ shell_surface_move,
+ shell_surface_resize,
+ shell_surface_set_toplevel,
+ shell_surface_set_transient,
+ shell_surface_set_fullscreen,
+ shell_surface_set_popup,
+ shell_surface_set_maximized,
+ shell_surface_set_title,
+ shell_surface_set_class
+};
+
+static void
+destroy_shell_surface(struct shell_surface *shsurf)
+{
+ wl_list_remove(&shsurf->surface_destroy_listener.link);
+ shsurf->surface->configure = NULL;
+ ping_timer_destroy(shsurf);
+
+ wl_list_remove(&shsurf->link);
+ free(shsurf);
+ weston_log("shell surface destroyed\n");
+}
+
+static void
+shell_destroy_shell_surface(struct wl_resource *resource)
+{
+ struct shell_surface *shsurf = resource->data;
+ destroy_shell_surface(shsurf);
+}
+
+static void
+shell_handle_surface_destroy(struct wl_listener *listener, void *data)
+{
+ struct shell_surface *shsurf =
+ container_of(listener, struct shell_surface,
+ surface_destroy_listener);
+ if (shsurf->resource.client) {
+ wl_resource_destroy(&shsurf->resource);
+ } else {
+ wl_signal_emit(&shsurf->resource.destroy_signal,
+ &shsurf->resource);
+ destroy_shell_surface(shsurf);
+ }
+}
+
+static struct shell_surface *
+create_shell_surface(void *shell, struct weston_surface *surface,
+ const struct weston_shell_client *client)
+{
+ struct shell_surface *shsurf;
+
+ if (surface->configure) {
+ weston_log("surface->configure already set\n");
+ return NULL;
+ }
+
+ shsurf = calloc(1, sizeof *shsurf);
+ if (!shsurf) {
+ weston_log("no memory to allocate shell surface\n");
+ return NULL;
+ }
+
+ surface->configure = shell_surface_configure;
+ surface->private = shsurf;
+ surface->compositor->shell_interface.shell = shell;
+
+ shsurf->shell = (struct tablet_shell *) shell;
+ shsurf->unresponsive = 0;
+ shsurf->surface = surface;
+ shsurf->ping_timer = NULL;
+
+ wl_signal_init(&shsurf->resource.destroy_signal);
+ shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
+ wl_signal_add(&surface->surface.resource.destroy_signal,
+ &shsurf->surface_destroy_listener);
+
+ /* init link so its safe to always remove it in destroy_shell_surface */
+ wl_list_init(&shsurf->link);
+
+ shsurf->client = client;
+
+ return shsurf;
+}
+
+static void
+send_configure(struct weston_surface *surface,
+ uint32_t edges, int32_t width, int32_t height)
+{
+ struct shell_surface *shsurf = get_shell_surface(surface);
+
+ wl_shell_surface_send_configure(&shsurf->resource,
+ edges, width, height);
+}
+
+static const struct weston_shell_client shell_client = {
+ send_configure
+};
+
+static void
+shell_get_shell_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 tablet_shell *shell = resource->data;
+ struct shell_surface *shsurf;
+
+ weston_log("get shell surface\n");
+
+ if (get_shell_surface(surface)) {
+ wl_resource_post_error(surface_resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "tablet_shell::get_shell_surface already requested");
+ return;
+ }
+
+ shsurf = create_shell_surface(shell, surface, &shell_client);
+ if (!shsurf) {
+ wl_resource_post_error(surface_resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "surface->configure already set");
+ return;
+ }
+
+ shsurf->resource.destroy = shell_destroy_shell_surface;
+ shsurf->resource.object.id = id;
+ shsurf->resource.object.interface = &wl_shell_surface_interface;
+ shsurf->resource.object.implementation =
+ (void (**)(void)) &shell_surface_implementation;
+ shsurf->resource.data = shsurf;
+
+ wl_client_add_resource(client, &shsurf->resource);
+}
+
+static const struct wl_shell_interface shell_implementation = {
+ shell_get_shell_surface
+};
+
+static void
+bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+ struct tablet_shell *shell = data;
+
+ wl_client_add_object(client, &wl_shell_interface,
+ &shell_implementation, id, shell);
+}
+
+static void
tablet_shell_destroy(struct wl_listener *listener, void *data);
static struct tablet_shell *
@@ -166,6 +474,57 @@ tablet_shell_surface_configure(struct weston_surface *surface,
}
static void
+configure(struct tablet_shell *shell, struct weston_surface *surface,
+ GLfloat x, GLfloat y, int32_t width, int32_t height)
+{
+ surface->geometry.x = x;
+ surface->geometry.y = y;
+ surface->geometry.width = width;
+ surface->geometry.height = height;
+ surface->geometry.dirty = 1;
+
+ weston_surface_assign_output(surface);
+}
+
+static void
+shell_surface_configure(struct weston_surface *surface,
+ int32_t sx, int32_t sy)
+{
+ struct tablet_shell *shell = get_shell(surface->compositor);
+ int32_t width, height;
+
+ if (!weston_surface_is_mapped(surface)) {
+ width = surface->buffer->width;
+ height = surface->buffer->height;
+
+ weston_surface_configure(surface, 0, 0, width, height);
+// tablet_shell_set_state(shell, STATE_TASK);
+
+ wl_list_insert(&shell->application_layer.surface_list,
+ &surface->layer_link);
+ // have a try
+ tablet_client_send_set_fullscreen(&shell->client_resource);
+ weston_surface_assign_output(surface);
+ }
+ if (sx != 0 || sy != 0 ||
+ surface->geometry.width != surface->buffer->width ||
+ surface->geometry.height != surface->buffer->height) {
+ GLfloat from_x, from_y;
+ GLfloat to_x, to_y;
+
+ weston_surface_to_global_float(surface, 0, 0,
+ &from_x, &from_y);
+ weston_surface_to_global_float(surface, sx, sy,
+ &to_x, &to_y);
+ configure(shell, surface,
+ surface->geometry.x + to_x - from_x,
+ surface->geometry.y + to_y - from_y,
+ surface->buffer->width,
+ surface->buffer->height);
+ }
+}
+
+static void
handle_lockscreen_surface_destroy(struct wl_listener *listener, void *data)
{
struct tablet_shell *shell =
@@ -515,6 +874,23 @@ bind_tablet_shell(struct wl_client *client, void *data, uint32_t version,
}
static void
+bind_tablet_client(struct wl_client *client, void *data, uint32_t version,
+ uint32_t id)
+{
+ struct tablet_shell *shell = data;
+ fprintf(stderr, "bind_tablet_client\n");
+ shell->client_resource.object.id = id;
+ shell->client_resource.object.interface = &tablet_client_interface;
+ shell->client_resource.object.implementation =
+ (void (**)(void)) &tablet_client_implementation;
+ shell->client_resource.client = client;
+ shell->client_resource.data = shell;
+ shell->client_resource.destroy = destroy_tablet_shell;
+
+ wl_client_add_resource(client, &shell->client_resource);
+}
+
+static void
tablet_shell_destroy(struct wl_listener *listener, void *data)
{
struct tablet_shell *shell =
@@ -553,10 +929,17 @@ shell_init(struct weston_compositor *compositor)
shell->unlock_listener.notify = tablet_shell_unlock;
wl_signal_add(&compositor->unlock_signal, &shell->unlock_listener);
+ wl_display_add_global(compositor->wl_display, &tablet_client_interface,
+ shell, bind_tablet_client);
+
/* FIXME: This will make the object available to all clients. */
wl_display_add_global(compositor->wl_display, &tablet_shell_interface,
shell, bind_tablet_shell);
+ if (wl_display_add_global(compositor->wl_display, &wl_shell_interface,
+ shell, bind_shell) == NULL)
+ return;
+
loop = wl_display_get_event_loop(compositor->wl_display);
shell->long_press_source =
wl_event_loop_add_timer(loop, long_press_handler, shell);
--
1.7.11
More information about the wayland-devel
mailing list