[PATCH 17/19] tablet-shell: add task manager to tablet-shell.
ning.tang at intel.com
ning.tang at intel.com
Mon Sep 24 19:40:02 PDT 2012
From: Ning Tang <ning.tang at intel.com>
Tablet-shell can run multitask. Key binding super + tab will switch
between applications. Home screen is treated as a special client.
One client may have several shell surface.
They would be moved to a list when the client is
hung. When switched back, shell surfaces will be
placed in order. Surfaces are inserted in application_layer.
Signed-off-by: Ning Tang <ning.tang at intel.com>
---
src/tablet-shell.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 194 insertions(+), 29 deletions(-)
diff --git a/src/tablet-shell.c b/src/tablet-shell.c
index 27d0486..7ab37a6 100644
--- a/src/tablet-shell.c
+++ b/src/tablet-shell.c
@@ -29,6 +29,7 @@
#include "compositor.h"
#include "tablet-shell-server-protocol.h"
+#include <wayland-server.h>
/*
* TODO: Don't fade back from black until we've received a lockscreen
@@ -42,6 +43,19 @@ enum {
STATE_TASK
};
+struct shell_surface;
+
+struct client_task {
+ struct wl_client *client;
+ struct wl_list shsurf_list;
+ struct wl_list link;
+};
+
+struct task_manager {
+ struct wl_list task_list;
+ struct client_task *home_task;
+};
+
struct tablet_shell {
struct wl_resource resource;
struct wl_resource client_resource;
@@ -64,6 +78,7 @@ struct tablet_shell {
struct wl_listener switcher_listener;
struct tablet_client *current_client;
+ struct task_manager task_manager;
int state, previous_state;
int long_press_active;
@@ -89,6 +104,7 @@ struct shell_surface {
uint32_t framerate;
} fullscreen;
+ struct client_task *client_task;
const struct weston_shell_client *client;
};
@@ -108,6 +124,10 @@ static void
black_surface_configure(struct weston_surface *es,
int32_t sx, int32_t sy);
+static void
+tablet_shell_surface_configure(struct weston_surface *es,
+ int32_t sx, int32_t sy);
+
static struct shell_surface *
get_shell_surface(struct weston_surface *surface)
{
@@ -115,6 +135,8 @@ get_shell_surface(struct weston_surface *surface)
return surface->private;
else if (surface->configure == black_surface_configure)
return get_shell_surface(surface->private);
+ else if (surface->configure == tablet_shell_surface_configure)
+ return surface->private;
else
return NULL;
}
@@ -122,16 +144,25 @@ get_shell_surface(struct weston_surface *surface)
static void
destroy_shell_surface(struct shell_surface *shsurf)
{
+ struct tablet_shell *shell = shsurf->shell;
+ struct weston_surface *surface;
wl_list_remove(&shsurf->surface_destroy_listener.link);
shsurf->surface->configure = NULL;
- if (shsurf->black_surface)
- {
+ if (shsurf->black_surface) {
wl_list_remove(&shsurf->black_surface->layer_link);
weston_surface_destroy(shsurf->black_surface);
}
- wl_list_remove(&shsurf->link);
free(shsurf);
+ if (shell->state == STATE_HOME ||
+ wl_list_length(&shell->application_layer.surface_list) == 1) {
+ weston_surface_damage(shell->home_surface);
+ } else {
+ surface =
+ container_of(shell->application_layer.surface_list.next,
+ struct weston_surface, layer_link);
+ weston_surface_damage(surface);
+ }
}
static void
@@ -290,7 +321,7 @@ create_shell_surface(void *shell, struct weston_surface *surface,
}
shsurf = calloc(1, sizeof *shsurf);
- if (!shsurf) {
+ if (!shsurf) {
weston_log("no memory to allocate shell surface\n");
return NULL;
}
@@ -330,6 +361,42 @@ static const struct weston_shell_client shell_client = {
};
static void
+hang_client(struct tablet_shell *shell, int home);
+
+static void
+bring_client_back(struct tablet_shell *shell, struct wl_seat *seat);
+
+static void
+shell_surface_create_client(struct shell_surface *shsurf,
+ struct wl_client *client)
+{
+ struct client_task *task;
+ task = calloc(1, sizeof *task);
+ task->client = client;
+ wl_list_init(&task->link);
+ wl_list_init(&task->shsurf_list);
+ shsurf->client_task = task;
+}
+
+static void
+shell_surface_add_client(struct shell_surface *shsurf,
+ struct wl_client *client,
+ struct tablet_shell *shell)
+{
+ struct weston_surface *surface;
+ struct shell_surface *current_shsurf;
+ surface = container_of(shell->application_layer.surface_list.next,
+ struct weston_surface, layer_link);
+ current_shsurf = get_shell_surface(surface);
+ if (client == current_shsurf->client_task->client)
+ shsurf->client_task = current_shsurf->client_task;
+ else {
+ hang_client(shell, 0);
+ shell_surface_create_client(shsurf, client);
+ }
+}
+
+static void
shell_get_shell_surface(struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
@@ -362,6 +429,13 @@ shell_get_shell_surface(struct wl_client *client,
shsurf->resource.data = shsurf;
wl_client_add_resource(client, &shsurf->resource);
+ if (wl_list_length(&shell->application_layer.surface_list) >= 1)
+ shell_surface_add_client(shsurf, client, shell);
+ else {
+ shell_surface_create_client(shsurf, client);
+ wl_list_insert(shell->task_manager.task_list.prev,
+ &shell->task_manager.home_task->link);
+ }
}
static const struct wl_shell_interface shell_implementation = {
@@ -544,6 +618,10 @@ shell_surface_configure(struct weston_surface *surface,
struct shell_surface *shsurf = get_shell_surface(surface);
struct weston_seat *seat;
+ if (shsurf->client_task->link.next &&
+ shsurf->client_task->link.next != &shsurf->client_task->link)
+ return;
+
if (!weston_surface_is_mapped(surface)) {
tablet_shell_set_state(shell, STATE_TASK);
@@ -617,11 +695,17 @@ tablet_shell_set_homescreen(struct wl_client *client,
struct wl_resource *surface_resource)
{
struct tablet_shell *shell = resource->data;
+ struct shell_surface *shsurf;
shell->home_surface = surface_resource->data;
shell->home_surface->configure = tablet_shell_surface_configure;
weston_surface_set_position(shell->home_surface, 0, 0);
+ shsurf = calloc(1, sizeof *shsurf);
+ wl_list_init(&shsurf->link);
+ shsurf->surface = shell->home_surface;
+ shell->task_manager.home_task->shsurf_list = shsurf->link;
+ shell->home_surface->private = shsurf;
}
static void
@@ -775,6 +859,21 @@ launch_ux_daemon(struct tablet_shell *shell)
}
static void
+task_manager_init(struct tablet_shell *shell)
+{
+ struct client_task *home_task;
+ home_task = calloc(1, sizeof *home_task);
+ if (!home_task) {
+ weston_log("no memory to allocate client task\n");
+ return;
+ }
+ shell->task_manager.home_task = home_task;
+ wl_list_init(&home_task->link);
+ wl_list_init(&home_task->shsurf_list);
+ wl_list_init(&shell->task_manager.task_list);
+}
+
+static void
toggle_switcher(struct tablet_shell *shell)
{
switch (shell->state) {
@@ -783,7 +882,7 @@ toggle_switcher(struct tablet_shell *shell)
break;
default:
tablet_shell_send_show_switcher(&shell->resource);
- tablet_shell_set_state(shell, STATE_SWITCHER);
+// tablet_shell_set_state(shell, STATE_SWITCHER);
break;
}
}
@@ -804,6 +903,7 @@ go_home(struct tablet_shell *shell, struct weston_seat *seat)
tablet_shell_send_hide_switcher(&shell->resource);
weston_surface_activate(shell->home_surface, seat);
+ weston_surface_damage(shell->home_surface);
tablet_shell_set_state(shell, STATE_HOME);
}
@@ -822,9 +922,9 @@ long_press_handler(void *data)
static void
menu_key_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
{
- struct tablet_shell *shell = data;
+// struct tablet_shell *shell = data;
- toggle_switcher(shell);
+// toggle_switcher(shell);
}
static void
@@ -843,7 +943,7 @@ home_key_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
switch (shell->state) {
case STATE_HOME:
case STATE_SWITCHER:
- toggle_switcher(shell);
+// toggle_switcher(shell);
break;
default:
go_home(shell, (struct weston_seat *) seat);
@@ -881,40 +981,101 @@ force_kill_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
{
struct tablet_shell *shell = data;
struct wl_client *client;
- struct weston_surface * focus;
- struct shell_surface * shsurf;
+ struct weston_surface *focus;
+ struct shell_surface *shsurf = NULL;
pid_t pid;
uid_t uid;
gid_t gid;
- int client_cnt;
if (!seat->keyboard->focus)
return;
- client = seat->keyboard->focus->resource.client;
- shsurf = get_shell_surface(seat->keyboard->focus);
+ focus = container_of(shell->application_layer.surface_list.next,
+ struct weston_surface, layer_link);
+ if (focus)
+ shsurf = get_shell_surface(focus);
if (!shsurf)
return;
+ if (shell->state != STATE_TASK)
+ return;
+ client = focus->surface.resource.client;
wl_client_get_credentials(client, &pid, &uid, &gid);
- client_cnt = wl_list_length(&shell->application_layer.surface_list);
- if (client_cnt > 2) {
- wl_list_for_each(focus, &shell->application_layer.surface_list,
- layer_link) {
- client_cnt--;
- if (client_cnt < 2) {
- weston_surface_activate(focus, seat);
- break;
- }
+ kill(pid, SIGKILL);
+ bring_client_back(shell, seat);
+ weston_compositor_schedule_repaint(shell->compositor);
+}
+
+static void
+bring_client_back(struct tablet_shell *shell, struct wl_seat *seat)
+{
+ struct shell_surface *shsurf;
+ struct client_task *task;
+ task = container_of(shell->task_manager.task_list.next,
+ struct client_task, link);
+ wl_list_remove(&task->link);
+ wl_list_init(&task->link);
+ if (task == shell->task_manager.home_task) {
+ go_home(shell, seat);
+ return;
+ }
+ tablet_shell_set_state(shell, STATE_TASK);
+ while (wl_list_length(&task->shsurf_list)) {
+ shsurf = container_of(task->shsurf_list.prev,
+ struct shell_surface, link);
+ wl_list_remove(&shsurf->link);
+ wl_list_insert(&shell->application_layer.surface_list,
+ &shsurf->surface->layer_link);
+ weston_surface_damage(shsurf->surface);
+ if (shsurf->black_surface) {
+ wl_list_insert(&shsurf->surface->layer_link,
+ &shsurf->black_surface->layer_link);
+ weston_surface_damage(shsurf->black_surface);
}
+ weston_surface_activate(shsurf->surface, seat);
}
- else
- focus = NULL;
- kill(pid, SIGKILL);
- if (focus == NULL) {
- tablet_shell_set_state(shell, STATE_HOME);
- weston_surface_activate(shell->home_surface, seat);
+}
+
+static void
+hang_client(struct tablet_shell *shell, int home)
+{
+ struct weston_surface *surface;
+ struct shell_surface *shsurf;
+ struct client_task *task;
+ if (home) {
+ task = shell->task_manager.home_task;
+ wl_list_insert(shell->task_manager.task_list.prev,
+ &task->link);
+ return;
}
- weston_compositor_schedule_repaint(shell->compositor);
+ while (wl_list_length(&shell->application_layer.surface_list)) {
+ surface =
+ container_of(shell->application_layer.surface_list.next,
+ struct weston_surface, layer_link);
+ shsurf = get_shell_surface(surface);
+ task = shsurf->client_task;
+ wl_list_insert(task->shsurf_list.prev, &shsurf->link);
+ wl_list_remove(&shsurf->surface->layer_link);
+ wl_list_init(&shsurf->surface->layer_link);
+ if (shsurf->black_surface) {
+ wl_list_remove(&shsurf->black_surface->layer_link);
+ wl_list_init(&shsurf->black_surface->layer_link);
+ }
+ }
+ wl_list_insert(shell->task_manager.task_list.prev,
+ &task->link);
+}
+
+static void
+switch_task(struct wl_seat *seat, uint32_t time, uint32_t key,
+ void *data)
+{
+ struct tablet_shell *shell = data;
+
+ if (wl_list_length(&shell->application_layer.surface_list) != 0)
+ hang_client(shell, 0);
+ else if (shell->state == STATE_HOME)
+ hang_client(shell, 1);
+ bring_client_back(shell, seat);
}
static void
@@ -1034,6 +1195,9 @@ module_init(struct weston_compositor *compositor)
shell);
weston_compositor_add_key_binding(compositor, KEY_ESC, 0,
force_kill_binding, shell);
+ weston_compositor_add_key_binding(compositor, KEY_TAB,
+ MODIFIER_SUPER,
+ switch_task, shell);
weston_compositor_add_key_binding(compositor, KEY_T,
MODIFIER_CTRL, launch_terminal,
shell);
@@ -1042,6 +1206,7 @@ module_init(struct weston_compositor *compositor)
&compositor->cursor_layer.link);
weston_layer_init(&shell->application_layer,
&compositor->cursor_layer.link);
+ task_manager_init(shell);
launch_ux_daemon(shell);
tablet_shell_set_state(shell, STATE_STARTING);
--
1.7.12.1
More information about the wayland-devel
mailing list