From 2f5faff7f9142f07a872032929beaa06d05f3e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 31 Jul 2012 16:36:34 -0400 Subject: [PATCH] shell: Always track focus state per workspace It's a little simpler than always creating and destroying it when we switch workspace, and we'll need the focus_state soon. --- src/shell.c | 81 ++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/src/shell.c b/src/shell.c index fd82fcf0..bfb2978c 100644 --- a/src/shell.c +++ b/src/shell.c @@ -50,6 +50,7 @@ enum animation_type { struct focus_state { struct weston_seat *seat; + struct workspace *ws; struct weston_surface *keyboard_focus; struct wl_list link; struct wl_listener seat_destroy_listener; @@ -213,6 +214,13 @@ struct rotate_grab { } center; }; +static void +activate(struct desktop_shell *shell, struct weston_surface *es, + struct weston_seat *seat); + +static struct workspace * +get_current_workspace(struct desktop_shell *shell); + static struct shell_surface * get_shell_surface(struct weston_surface *surface); @@ -383,36 +391,29 @@ focus_state_surface_destroy(struct wl_listener *listener, void *data) } static struct focus_state * -focus_state_create(struct weston_seat *seat) +focus_state_create(struct weston_seat *seat, struct workspace *ws) { - struct wl_keyboard *keyboard = seat->seat.keyboard; struct focus_state *state; - struct wl_surface *surface; - struct shell_surface *shsurf; state = malloc(sizeof *state); if (state == NULL) return NULL; - surface = keyboard->focus; - shsurf = get_shell_surface((struct weston_surface *)keyboard->focus); - + state->ws = ws; state->seat = seat; - state->keyboard_focus = shsurf->surface; - wl_list_init(&state->link); + wl_list_insert(&ws->focus_list, &state->link); state->seat_destroy_listener.notify = focus_state_seat_destroy; state->surface_destroy_listener.notify = focus_state_surface_destroy; wl_signal_add(&seat->seat.destroy_signal, &state->seat_destroy_listener); - wl_signal_add(&surface->resource.destroy_signal, - &state->surface_destroy_listener); + wl_list_init(&state->surface_destroy_listener.link); return state; } static void -pop_focus_state(struct desktop_shell *shell, struct workspace *ws) +restore_focus_state(struct desktop_shell *shell, struct workspace *ws) { struct focus_state *state, *next; @@ -420,30 +421,6 @@ pop_focus_state(struct desktop_shell *shell, struct workspace *ws) if (state->keyboard_focus) wl_keyboard_set_focus(state->seat->seat.keyboard, &state->keyboard_focus->surface); - - focus_state_destroy(state); - } - wl_list_init(&ws->focus_list); -} - -static void -push_focus_state(struct desktop_shell *shell, struct workspace *ws) -{ - struct weston_seat *seat; - struct focus_state *state; - struct wl_keyboard *keyboard; - - wl_list_for_each(seat, &shell->compositor->seat_list, link) { - keyboard = seat->seat.keyboard; - if (keyboard && keyboard->focus) { - state = focus_state_create(seat); - if (state == NULL) - return; - - wl_list_insert(&ws->focus_list, &state->link); - - wl_keyboard_set_focus(seat->seat.keyboard, NULL); - } } } @@ -598,8 +575,7 @@ reverse_workspace_change_animation(struct desktop_shell *shell, shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir; shell->workspaces.anim_timestamp = 0; - push_focus_state(shell, from); - pop_focus_state(shell, to); + restore_focus_state(shell, to); workspace_damage_all_surfaces(from); workspace_damage_all_surfaces(to); @@ -720,8 +696,7 @@ animate_workspace_change(struct desktop_shell *shell, workspace_translate_in(to, 0); - push_focus_state(shell, from); - pop_focus_state(shell, to); + restore_focus_state(shell, to); workspace_damage_all_surfaces(from); workspace_damage_all_surfaces(to); @@ -759,8 +734,7 @@ change_workspace(struct desktop_shell *shell, unsigned int index) wl_list_insert(&from->layer.link, &to->layer.link); wl_list_remove(&from->layer.link); - push_focus_state(shell, from); - pop_focus_state(shell, to); + restore_focus_state(shell, to); } else animate_workspace_change(shell, index, from, to); @@ -2004,7 +1978,7 @@ resume_desktop(struct desktop_shell *shell) &shell->panel_layer.link); wl_list_insert(&shell->panel_layer.link, &ws->layer.link); - pop_focus_state(shell, get_current_workspace(shell)); + restore_focus_state(shell, get_current_workspace(shell)); shell->locked = false; shell->compositor->idle_time = shell->compositor->option_idle_time; @@ -2364,10 +2338,26 @@ static void activate(struct desktop_shell *shell, struct weston_surface *es, struct weston_seat *seat) { - struct workspace *ws; + struct workspace *ws = get_current_workspace(shell); + struct focus_state *state; weston_surface_activate(es, seat); + wl_list_for_each(state, &ws->focus_list, link) + if (state->seat == seat) + break; + + if (&state->link == &ws->focus_list) { + state = focus_state_create(seat, ws); + if (state == NULL) + return; + } + + state->keyboard_focus = es; + wl_list_remove(&state->surface_destroy_listener.link); + wl_signal_add(&es->surface.resource.destroy_signal, + &state->surface_destroy_listener); + switch (get_shell_surface_type(es)) { case SHELL_SURFACE_FULLSCREEN: /* should on top of panels */ @@ -2452,9 +2442,6 @@ lock(struct wl_listener *listener, void *data) launch_screensaver(shell); - /* stash keyboard foci in current workspace */ - push_focus_state(shell, get_current_workspace(shell)); - /* TODO: disable bindings that should not work while locked. */ /* All this must be undone in resume_desktop(). */