diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index c49edf93..7981099a 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -3955,254 +3955,6 @@ terminate_binding(struct weston_seat *seat, uint32_t time, uint32_t key, wl_display_terminate(compositor->wl_display); } -struct alt_tab { - struct desktop_shell *shell; - struct weston_keyboard_grab grab; - - struct wl_list *current; - - struct wl_list preview_list; -}; - -struct alt_tab_preview { - struct alt_tab *alt_tab; - - struct weston_view *view; - struct weston_transform transform; - - struct wl_listener listener; - - struct wl_list link; -}; - -static void -alt_tab_next(struct alt_tab *alt_tab) -{ - alt_tab->current = alt_tab->current->next; - - /* Make sure we're not pointing to the list header e.g. after - * cycling through the whole list. */ - if (alt_tab->current->next == alt_tab->preview_list.next) - alt_tab->current = alt_tab->current->next; -} - -static void -alt_tab_destroy(struct alt_tab *alt_tab) -{ - struct alt_tab_preview *preview, *next; - struct weston_keyboard *keyboard = alt_tab->grab.keyboard; - - if (alt_tab->current && alt_tab->current != &alt_tab->preview_list) { - preview = wl_container_of(alt_tab->current, preview, link); - - activate(alt_tab->shell, preview->view->surface, - (struct weston_seat *) keyboard->seat); - } - - wl_list_for_each_safe(preview, next, &alt_tab->preview_list, link) { - wl_list_remove(&preview->link); - wl_list_remove(&preview->listener.link); - weston_view_destroy(preview->view); - free(preview); - } - - weston_keyboard_end_grab(keyboard); - if (keyboard->input_method_resource) - keyboard->grab = &keyboard->input_method_grab; - - free(alt_tab); -} - -static void -alt_tab_handle_surface_destroy(struct wl_listener *listener, void *data) -{ - struct alt_tab_preview *preview = - container_of(listener, struct alt_tab_preview, listener); - struct alt_tab *alt_tab = preview->alt_tab; - int advance = 0; - - /* If the preview that we're removing is the currently selected one, - * we want to move to the next one. So we move to ->prev and then - * call _next() after removing the preview. */ - if (alt_tab->current == &preview->link) { - alt_tab->current = alt_tab->current->prev; - advance = 1; - } - - wl_list_remove(&preview->listener.link); - wl_list_remove(&preview->link); - - free(preview); - - if (advance) - alt_tab_next(alt_tab); - - /* If the last preview goes away, stop the alt-tab */ - if (wl_list_empty(alt_tab->current)) - alt_tab_destroy(alt_tab); -} - -static void -alt_tab_key(struct weston_keyboard_grab *grab, - uint32_t time, uint32_t key, uint32_t state_w) -{ - struct alt_tab *alt_tab = container_of(grab, struct alt_tab, grab); - enum wl_keyboard_key_state state = state_w; - - if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED) - alt_tab_next(alt_tab); -} - -static void -alt_tab_modifier(struct weston_keyboard_grab *grab, uint32_t serial, - uint32_t mods_depressed, uint32_t mods_latched, - uint32_t mods_locked, uint32_t group) -{ - struct alt_tab *alt_tab = container_of(grab, struct alt_tab, grab); - struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat; - - if ((seat->modifier_state & MODIFIER_ALT) == 0) - alt_tab_destroy(alt_tab); -} - -static void -alt_tab_cancel(struct weston_keyboard_grab *grab) -{ - struct alt_tab *alt_tab = container_of(grab, struct alt_tab, grab); - - alt_tab_destroy(alt_tab); -} - -static const struct weston_keyboard_grab_interface alt_tab_grab = { - alt_tab_key, - alt_tab_modifier, - alt_tab_cancel, -}; - -static int -view_for_alt_tab(struct weston_view *view) -{ - struct shell_surface *shsurf = get_shell_surface(view->surface); - if (!shsurf) - return 0; - - if (shsurf->parent) - return 0; - - if (view != get_default_view(view->surface)) - return 0; - - return 1; -} - -static void -alt_tab_binding(struct weston_seat *seat, uint32_t time, uint32_t key, - void *data) -{ - struct alt_tab *alt_tab; - struct desktop_shell *shell = data; - struct weston_output *output = get_default_output(shell->compositor); - struct workspace *ws; - struct weston_view *view; - int num_surfaces = 0; - int x, y, side, margin; - - wl_list_for_each(view, &shell->compositor->view_list, link) { - - if (view_for_alt_tab(view)) - num_surfaces++; - } - - if (!num_surfaces) - return; - - alt_tab = malloc(sizeof *alt_tab); - if (!alt_tab) - return; - - alt_tab->shell = shell; - wl_list_init(&alt_tab->preview_list); - alt_tab->current = &alt_tab->preview_list; - - restore_all_output_modes(shell->compositor); - lower_fullscreen_layer(alt_tab->shell); - - alt_tab->grab.interface = &alt_tab_grab; - weston_keyboard_start_grab(seat->keyboard, &alt_tab->grab); - weston_keyboard_set_focus(seat->keyboard, NULL); - - ws = get_current_workspace(shell); - - /* FIXME: add some visual candy e.g. prelight the selected view - * and/or add a black surrounding background à la gnome-shell */ - - /* Determine the size for each preview */ - side = output->width / num_surfaces; - if (side > 200) - side = 200; - margin = side / 4; - side -= margin; - - x = margin; - y = (output->height - side) / 2; - - /* Create a view for each surface */ - wl_list_for_each(view, &shell->compositor->view_list, link) { - struct alt_tab_preview *preview; - struct weston_view *v; - float scale; - - if (!view_for_alt_tab(view)) - continue; - - preview = malloc(sizeof *preview); - if (!preview) { - alt_tab_destroy(alt_tab); - return; - } - - preview->alt_tab = alt_tab; - - preview->view = v = weston_view_create(view->surface); - v->output = view->output; - - wl_list_remove(&v->layer_link); - wl_list_insert(&ws->layer.view_list, &v->layer_link); - weston_view_damage_below(v); - weston_surface_damage(v->surface); - - weston_view_set_position(v, x, y); - - preview->listener.notify = alt_tab_handle_surface_destroy; - wl_signal_add(&v->destroy_signal, &preview->listener); - - if (view->surface->width > view->surface->height) - scale = side / (float) view->surface->width; - else - scale = side / (float) view->surface->height; - - wl_list_insert(&v->geometry.transformation_list, - &preview->transform.link); - weston_matrix_init(&preview->transform.matrix); - weston_matrix_scale(&preview->transform.matrix, - scale, scale, 1.0f); - - weston_view_geometry_dirty(v); - weston_compositor_schedule_repaint(v->surface->compositor); - - /* Insert at the end of the list */ - wl_list_insert(alt_tab->preview_list.prev, &preview->link); - - x += side + margin; - } - - /* Start at the second preview so a simple tab changes window. - * We set `current' to the first preview and not the second because - * we're going to receive a key press callback for the initial - * tab which will make `current' point to the second element. */ - alt_tab_next(alt_tab); -} - static void rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time, wl_fixed_t x, wl_fixed_t y) @@ -5667,9 +5419,6 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell) weston_compositor_add_key_binding(ec, KEY_BACKSPACE, MODIFIER_CTRL | MODIFIER_ALT, terminate_binding, ec); - weston_compositor_add_key_binding(ec, KEY_TAB, - MODIFIER_ALT, - alt_tab_binding, shell); weston_compositor_add_button_binding(ec, BTN_LEFT, 0, click_to_activate_binding, shell);