From: Ning Tang <ning.t...@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.t...@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 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel