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;
} 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);
}
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;
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);
- }
}
}
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);
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);
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);
&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;
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 */
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(). */