<div dir="ltr">This is cool, but are we sure we want it?<br><br>From the "Clarifying scope and goals for weston" mail sent by Kristian [1]:<div><br>"The desktop shell in weston serves three goals: to validate wl_shell<br>
protocol, to make weston do something useful when you start it up, and<br>to provide a reference for how to implement a shell module. The<br>desktop shell is not supposed to be a generally useful desktop<br>environment. When we're implementing something for the weston desktop<br>
shell, we go for simplicity and protocol coverage rather than full<br>configurability or external dependencies."</div><div><br></div><div>It seems to me this Exposay is out of scope, and adds a quite big amount of code</div>
<div>to shell.c, which is already quite big and complex to understand. If anything, i think</div><div>it should go in a separate file.<br><br>[1] <a href="http://lists.freedesktop.org/archives/wayland-devel/2013-April/008659.html">http://lists.freedesktop.org/archives/wayland-devel/2013-April/008659.html</a></div>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/7/3 Tomeu Vizoso <span dir="ltr"><<a href="mailto:tomeu@tomeuvizoso.net" target="_blank">tomeu@tomeuvizoso.net</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
From: Daniel Stone <<a href="mailto:daniel@fooishbar.org">daniel@fooishbar.org</a>><br>
<br>
Exposay provides window overview functions which, when a key which<br>
produces the binding modifier is pressed on its own, scales all<br>
currently-open windows down to be shown overlaid on the desktop,<br>
providing keyboard and mouse navigation to be able to switch window<br>
focus.<br>
<br>
Signed-off-by: Daniel Stone <<a href="mailto:daniel@fooishbar.org">daniel@fooishbar.org</a>><br>
---<br>
src/shell.c | 574 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>
1 file changed, 574 insertions(+)<br>
<br>
diff --git a/src/shell.c b/src/shell.c<br>
index 80b3e8b..cadcb55 100644<br>
--- a/src/shell.c<br>
+++ b/src/shell.c<br>
@@ -1,6 +1,7 @@<br>
/*<br>
* Copyright © 2010-2012 Intel Corporation<br>
* Copyright © 2011-2012 Collabora, Ltd.<br>
+ * Copyright © 2013 Raspberry Pi Foundation<br>
*<br>
* Permission to use, copy, modify, distribute, and sell this software and<br>
* its documentation for any purpose is hereby granted without fee, provided<br>
@@ -57,6 +58,19 @@ enum fade_type {<br>
FADE_OUT<br>
};<br>
<br>
+enum exposay_target_state {<br>
+ EXPOSAY_TARGET_OVERVIEW, /* show all windows */<br>
+ EXPOSAY_TARGET_CANCEL, /* return to normal, same focus */<br>
+ EXPOSAY_TARGET_SWITCH, /* return to normal, switch focus */<br>
+};<br>
+<br>
+enum exposay_layout_state {<br>
+ EXPOSAY_LAYOUT_INACTIVE = 0, /* normal desktop */<br>
+ EXPOSAY_LAYOUT_ANIMATE_TO_INACTIVE, /* in transition to normal */<br>
+ EXPOSAY_LAYOUT_OVERVIEW, /* show all windows */<br>
+ EXPOSAY_LAYOUT_ANIMATE_TO_OVERVIEW, /* in transition to all windows */<br>
+};<br>
+<br>
struct focus_state {<br>
struct weston_seat *seat;<br>
struct workspace *ws;<br>
@@ -184,6 +198,34 @@ struct desktop_shell {<br>
struct wl_event_source *startup_timer;<br>
} fade;<br>
<br>
+ struct exposay {<br>
+ /* XXX: Make these exposay_surfaces. */<br>
+ struct weston_surface *focus_prev;<br>
+ struct weston_surface *focus_current;<br>
+ struct weston_surface *clicked;<br>
+ struct workspace *workspace;<br>
+ struct weston_seat *seat;<br>
+ struct wl_list surface_list;<br>
+<br>
+ struct weston_keyboard_grab grab_kbd;<br>
+ struct weston_pointer_grab grab_ptr;<br>
+<br>
+ enum exposay_target_state state_target;<br>
+ enum exposay_layout_state state_cur;<br>
+ int in_flight; /* number of animations still running */<br>
+<br>
+ int num_surfaces;<br>
+ int grid_size;<br>
+ int surface_size;<br>
+<br>
+ int hpadding_outer;<br>
+ int vpadding_outer;<br>
+ int padding_inner;<br>
+<br>
+ int row_current;<br>
+ int column_current;<br>
+ } exposay;<br>
+<br>
uint32_t binding_modifier;<br>
enum animation_type win_animation_type;<br>
enum animation_type focus_animation_type;<br>
@@ -4289,6 +4331,533 @@ switcher_binding(struct weston_seat *seat, uint32_t time, uint32_t key,<br>
switcher_next(switcher);<br>
}<br>
<br>
+struct exposay_surface {<br>
+ struct desktop_shell *shell;<br>
+ struct weston_surface *surface;<br>
+ struct wl_list link;<br>
+<br>
+ int x;<br>
+ int y;<br>
+ int width;<br>
+ int height;<br>
+ double scale;<br>
+<br>
+ int row;<br>
+ int column;<br>
+<br>
+ /* The animations only apply a transformation for their own lifetime,<br>
+ * and don't have an option to indefinitely maintain the<br>
+ * transformation in a steady state - so, we apply our own once the<br>
+ * animation has finished. */<br>
+ struct weston_transform transform;<br>
+};<br>
+<br>
+static void exposay_set_state(struct desktop_shell *shell,<br>
+ enum exposay_target_state state,<br>
+ struct weston_seat *seat);<br>
+static void exposay_check_state(struct desktop_shell *shell);<br>
+<br>
+static void<br>
+exposay_in_flight_inc(struct desktop_shell *shell)<br>
+{<br>
+ shell->exposay.in_flight++;<br>
+}<br>
+<br>
+static void<br>
+exposay_in_flight_dec(struct desktop_shell *shell)<br>
+{<br>
+ if (--shell->exposay.in_flight > 0)<br>
+ return;<br>
+<br>
+ exposay_check_state(shell);<br>
+}<br>
+<br>
+static void<br>
+exposay_animate_in_done(struct weston_surface_animation *animation, void *data)<br>
+{<br>
+ struct exposay_surface *esurface = data;<br>
+<br>
+ wl_list_insert(&esurface->surface->geometry.transformation_list,<br>
+ &esurface->transform.link);<br>
+ weston_matrix_init(&esurface->transform.matrix);<br>
+ weston_matrix_scale(&esurface->transform.matrix,<br>
+ esurface->scale, esurface->scale, 1.0f);<br>
+ weston_matrix_translate(&esurface->transform.matrix,<br>
+ esurface->x - esurface->surface->geometry.x,<br>
+ esurface->y - esurface->surface->geometry.y,<br>
+ 0);<br>
+<br>
+ weston_surface_geometry_dirty(esurface->surface);<br>
+ weston_compositor_schedule_repaint(esurface->surface->compositor);<br>
+<br>
+ exposay_in_flight_dec(esurface->shell);<br>
+}<br>
+<br>
+static void<br>
+exposay_animate_in(struct exposay_surface *esurface)<br>
+{<br>
+ exposay_in_flight_inc(esurface->shell);<br>
+<br>
+ weston_move_scale_run(esurface->surface,<br>
+ esurface->x - esurface->surface->geometry.x,<br>
+ esurface->y - esurface->surface->geometry.y,<br>
+ 1.0, esurface->scale, 0,<br>
+ exposay_animate_in_done, esurface);<br>
+}<br>
+<br>
+static void<br>
+exposay_animate_out_done(struct weston_surface_animation *animation, void *data)<br>
+{<br>
+ struct exposay_surface *esurface = data;<br>
+ struct desktop_shell *shell = esurface->shell;<br>
+<br>
+ wl_list_remove(&esurface->link);<br>
+ free(esurface);<br>
+<br>
+ exposay_in_flight_dec(shell);<br>
+}<br>
+<br>
+static void<br>
+exposay_animate_out(struct exposay_surface *esurface)<br>
+{<br>
+ exposay_in_flight_inc(esurface->shell);<br>
+<br>
+ /* Remove the static transformation set up by<br>
+ * exposay_transform_in_done(). */<br>
+ wl_list_remove(&esurface->transform.link);<br>
+ weston_surface_geometry_dirty(esurface->surface);<br>
+<br>
+ weston_move_scale_run(esurface->surface,<br>
+ esurface->x - esurface->surface->geometry.x,<br>
+ esurface->y - esurface->surface->geometry.y,<br>
+ 1.0, esurface->scale, 1,<br>
+ exposay_animate_out_done, esurface);<br>
+}<br>
+<br>
+static void<br>
+exposay_highlight_surface(struct desktop_shell *shell,<br>
+ struct exposay_surface *esurface)<br>
+{<br>
+ struct weston_surface *ws = NULL;<br>
+<br>
+ if (esurface) {<br>
+ shell->exposay.row_current = esurface->row;<br>
+ shell->exposay.column_current = esurface->column;<br>
+ ws = esurface->surface;<br>
+ }<br>
+<br>
+ animate_focus_change(shell, shell->exposay.workspace,<br>
+ shell->exposay.focus_current, ws);<br>
+ shell->exposay.focus_current = ws;<br>
+}<br>
+<br>
+static int<br>
+exposay_is_animating(struct desktop_shell *shell)<br>
+{<br>
+ if (shell->exposay.state_cur == EXPOSAY_LAYOUT_INACTIVE ||<br>
+ shell->exposay.state_cur == EXPOSAY_LAYOUT_OVERVIEW)<br>
+ return 0;<br>
+<br>
+ return (shell->exposay.in_flight > 0);<br>
+}<br>
+<br>
+static void<br>
+exposay_pick(struct desktop_shell *shell, int x, int y)<br>
+{<br>
+ struct exposay_surface *esurface;<br>
+<br>
+ if (exposay_is_animating(shell))<br>
+ return;<br>
+<br>
+ wl_list_for_each(esurface, &shell->exposay.surface_list, link) {<br>
+ if (x < esurface->x || x > esurface->x + esurface->width)<br>
+ continue;<br>
+ if (y < esurface->y || y > esurface->y + esurface->height)<br>
+ continue;<br>
+<br>
+ exposay_highlight_surface(shell, esurface);<br>
+ return;<br>
+ }<br>
+}<br>
+<br>
+/* Pretty lame layout for now; just tries to make a square. Should take<br>
+ * aspect ratio into account really. Also needs to be notified of surface<br>
+ * addition and removal and adjust layout/animate accordingly. */<br>
+static enum exposay_layout_state<br>
+exposay_layout(struct desktop_shell *shell)<br>
+{<br>
+ struct workspace *workspace = shell->exposay.workspace;<br>
+ struct weston_compositor *compositor = shell->compositor;<br>
+ struct weston_output *output = get_default_output(compositor);<br>
+ struct weston_surface *ws;<br>
+ struct exposay_surface *esurface;<br>
+ int w, h;<br>
+ int i;<br>
+ int last_row_removed = 0;<br>
+<br>
+ wl_list_init(&shell->exposay.surface_list);<br>
+<br>
+ shell->exposay.num_surfaces = 0;<br>
+ wl_list_for_each(ws, &workspace->layer.surface_list, layer_link) {<br>
+ if (!get_shell_surface(ws))<br>
+ continue;<br>
+ shell->exposay.num_surfaces++;<br>
+ }<br>
+<br>
+ if (shell->exposay.num_surfaces == 0) {<br>
+ shell->exposay.grid_size = 0;<br>
+ shell->exposay.hpadding_outer = 0;<br>
+ shell->exposay.vpadding_outer = 0;<br>
+ shell->exposay.padding_inner = 0;<br>
+ shell->exposay.surface_size = 0;<br>
+ return EXPOSAY_LAYOUT_OVERVIEW;<br>
+ }<br>
+<br>
+ /* Lay the grid out as square as possible, losing surfaces from the<br>
+ * bottom row if required. Start with fixed padding of a 10% margin<br>
+ * around the outside and 80px internal padding between surfaces, and<br>
+ * maximise the area made available to surfaces after this, but only<br>
+ * to a maximum of 1/3rd the total output size.<br>
+ *<br>
+ * If we can't make a square grid, add one extra row at the bottom<br>
+ * which will have a smaller number of columns.<br>
+ *<br>
+ * XXX: Surely there has to be a better way to express this maths,<br>
+ * right?!<br>
+ */<br>
+ shell->exposay.grid_size = floor(sqrtf(shell->exposay.num_surfaces));<br>
+ if (pow(shell->exposay.grid_size, 2) != shell->exposay.num_surfaces)<br>
+ shell->exposay.grid_size++;<br>
+ last_row_removed = pow(shell->exposay.grid_size, 2) - shell->exposay.num_surfaces;<br>
+<br>
+ shell->exposay.hpadding_outer = (output->width / 10);<br>
+ shell->exposay.vpadding_outer = (output->height / 10);<br>
+ shell->exposay.padding_inner = 80;<br>
+<br>
+ w = output->width - (shell->exposay.hpadding_outer * 2);<br>
+ w -= shell->exposay.padding_inner * (shell->exposay.grid_size - 1);<br>
+ w /= shell->exposay.grid_size;<br>
+<br>
+ h = output->height - (shell->exposay.vpadding_outer * 2);<br>
+ h -= shell->exposay.padding_inner * (shell->exposay.grid_size - 1);<br>
+ h /= shell->exposay.grid_size;<br>
+<br>
+ shell->exposay.surface_size = (w < h) ? w : h;<br>
+ if (shell->exposay.surface_size > (output->width / 2))<br>
+ shell->exposay.surface_size = output->width / 2;<br>
+ if (shell->exposay.surface_size > (output->height / 2))<br>
+ shell->exposay.surface_size = output->height / 2;<br>
+<br>
+ i = 0;<br>
+ wl_list_for_each(ws, &workspace->layer.surface_list, layer_link) {<br>
+ int pad;<br>
+<br>
+ pad = shell->exposay.surface_size + shell->exposay.padding_inner;<br>
+<br>
+ if (!get_shell_surface(ws))<br>
+ continue;<br>
+<br>
+ esurface = malloc(sizeof(*esurface));<br>
+ if (!esurface) {<br>
+ exposay_set_state(shell, EXPOSAY_TARGET_CANCEL,<br>
+ shell->exposay.seat);<br>
+ break;<br>
+ }<br>
+<br>
+ wl_list_insert(&shell->exposay.surface_list, &esurface->link);<br>
+ esurface->shell = shell;<br>
+ esurface->surface = ws;<br>
+<br>
+ esurface->row = i / shell->exposay.grid_size;<br>
+ esurface->column = i % shell->exposay.grid_size;<br>
+<br>
+ esurface->x = shell->exposay.hpadding_outer;<br>
+ esurface->x += pad * esurface->column;<br>
+ esurface->y = shell->exposay.vpadding_outer;<br>
+ esurface->y += pad * esurface->row;<br>
+<br>
+ if (esurface->row == shell->exposay.grid_size - 1)<br>
+ esurface->x += (shell->exposay.surface_size + shell->exposay.padding_inner) * last_row_removed / 2;<br>
+<br>
+ if (ws->geometry.width > ws->geometry.height)<br>
+ esurface->scale = shell->exposay.surface_size / (float) ws->geometry.width;<br>
+ else<br>
+ esurface->scale = shell->exposay.surface_size / (float) ws->geometry.height;<br>
+ esurface->width = ws->geometry.width * esurface->scale;<br>
+ esurface->height = ws->geometry.height * esurface->scale;<br>
+<br>
+ if (shell->exposay.focus_current == esurface->surface)<br>
+ exposay_highlight_surface(shell, esurface);<br>
+<br>
+ exposay_animate_in(esurface);<br>
+<br>
+ i++;<br>
+ }<br>
+<br>
+ weston_compositor_schedule_repaint(shell->compositor);<br>
+<br>
+ return EXPOSAY_LAYOUT_ANIMATE_TO_OVERVIEW;<br>
+}<br>
+<br>
+static void<br>
+exposay_motion(struct weston_pointer_grab *grab, uint32_t time)<br>
+{<br>
+ struct desktop_shell *shell =<br>
+ container_of(grab, struct desktop_shell, exposay.grab_ptr);<br>
+<br>
+ exposay_pick(shell,<br>
+ wl_fixed_to_int(grab->pointer->x),<br>
+ wl_fixed_to_int(grab->pointer->y));<br>
+}<br>
+<br>
+static void<br>
+exposay_button(struct weston_pointer_grab *grab, uint32_t time, uint32_t button,<br>
+ uint32_t state_w)<br>
+{<br>
+ struct desktop_shell *shell =<br>
+ container_of(grab, struct desktop_shell, exposay.grab_ptr);<br>
+ struct weston_seat *seat = grab->pointer->seat;<br>
+ enum wl_pointer_button_state state = state_w;<br>
+<br>
+ if (button != BTN_LEFT)<br>
+ return;<br>
+<br>
+ /* Store the surface we clicked on, and don't do anything if we end up<br>
+ * releasing on a different surface. */<br>
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED) {<br>
+ shell->exposay.clicked = shell->exposay.focus_current;<br>
+ return;<br>
+ }<br>
+<br>
+ if (shell->exposay.focus_current == shell->exposay.clicked)<br>
+ exposay_set_state(shell, EXPOSAY_TARGET_SWITCH, seat);<br>
+ else<br>
+ shell->exposay.clicked = NULL;<br>
+}<br>
+<br>
+static const struct weston_pointer_grab_interface exposay_ptr_grab = {<br>
+ noop_grab_focus,<br>
+ exposay_motion,<br>
+ exposay_button,<br>
+};<br>
+<br>
+static int<br>
+exposay_maybe_move(struct desktop_shell *shell, int row, int column)<br>
+{<br>
+ struct exposay_surface *esurface;<br>
+<br>
+ wl_list_for_each(esurface, &shell->exposay.surface_list, link) {<br>
+ if (esurface->row != row || esurface->column != column)<br>
+ continue;<br>
+<br>
+ exposay_highlight_surface(shell, esurface);<br>
+ return 1;<br>
+ }<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+static void<br>
+exposay_key(struct weston_keyboard_grab *grab, uint32_t time, uint32_t key,<br>
+ uint32_t state_w)<br>
+{<br>
+ struct weston_seat *seat = grab->keyboard->seat;<br>
+ struct desktop_shell *shell =<br>
+ container_of(grab, struct desktop_shell, exposay.grab_kbd);<br>
+ enum wl_keyboard_key_state state = state_w;<br>
+<br>
+ if (state != WL_KEYBOARD_KEY_STATE_RELEASED)<br>
+ return;<br>
+<br>
+ switch (key) {<br>
+ case KEY_ESC:<br>
+ exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, seat);<br>
+ break;<br>
+ case KEY_ENTER:<br>
+ exposay_set_state(shell, EXPOSAY_TARGET_SWITCH, seat);<br>
+ break;<br>
+ case KEY_UP:<br>
+ exposay_maybe_move(shell, shell->exposay.row_current - 1,<br>
+ shell->exposay.column_current);<br>
+ break;<br>
+ case KEY_DOWN:<br>
+ /* Special case for trying to move to the bottom row when it<br>
+ * has fewer items than all the others. */<br>
+ if (!exposay_maybe_move(shell, shell->exposay.row_current + 1,<br>
+ shell->exposay.column_current) &&<br>
+ shell->exposay.row_current < (shell->exposay.grid_size - 1)) {<br>
+ exposay_maybe_move(shell, shell->exposay.row_current + 1,<br>
+ (shell->exposay.num_surfaces %<br>
+ shell->exposay.grid_size) - 1);<br>
+ }<br>
+ break;<br>
+ case KEY_LEFT:<br>
+ exposay_maybe_move(shell, shell->exposay.row_current,<br>
+ shell->exposay.column_current - 1);<br>
+ break;<br>
+ case KEY_RIGHT:<br>
+ exposay_maybe_move(shell, shell->exposay.row_current,<br>
+ shell->exposay.column_current + 1);<br>
+ break;<br>
+ case KEY_TAB:<br>
+ /* Try to move right, then down (and to the leftmost column),<br>
+ * then if all else fails, to the top left. */<br>
+ if (!exposay_maybe_move(shell, shell->exposay.row_current,<br>
+ shell->exposay.column_current + 1) &&<br>
+ !exposay_maybe_move(shell, shell->exposay.row_current + 1, 0))<br>
+ exposay_maybe_move(shell, 0, 0);<br>
+ break;<br>
+ default:<br>
+ break;<br>
+ }<br>
+}<br>
+<br>
+static void<br>
+exposay_modifier(struct weston_keyboard_grab *grab, uint32_t serial,<br>
+ uint32_t mods_depressed, uint32_t mods_latched,<br>
+ uint32_t mods_locked, uint32_t group)<br>
+{<br>
+}<br>
+<br>
+static const struct weston_keyboard_grab_interface exposay_kbd_grab = {<br>
+ exposay_key,<br>
+ exposay_modifier,<br>
+};<br>
+<br>
+/**<br>
+ * Called when the transition from overview -> inactive has completed.<br>
+ */<br>
+static enum exposay_layout_state<br>
+exposay_set_inactive(struct desktop_shell *shell)<br>
+{<br>
+ struct weston_seat *seat = shell->exposay.seat;<br>
+<br>
+ weston_keyboard_end_grab(seat->keyboard);<br>
+ weston_pointer_end_grab(seat->pointer);<br>
+ if (seat->keyboard->input_method_resource)<br>
+ seat->keyboard->grab = &seat->keyboard->input_method_grab;<br>
+<br>
+ return EXPOSAY_LAYOUT_INACTIVE;<br>
+}<br>
+<br>
+/**<br>
+ * Begins the transition from overview to inactive. */<br>
+static enum exposay_layout_state<br>
+exposay_transition_inactive(struct desktop_shell *shell, int switch_focus)<br>
+{<br>
+ struct exposay_surface *esurface;<br>
+<br>
+ /* Call activate() before we start the animations to avoid<br>
+ * animating back the old state and then immediately transitioning<br>
+ * to the new. */<br>
+ if (switch_focus && shell->exposay.focus_current)<br>
+ activate(shell, shell->exposay.focus_current,<br>
+ shell->exposay.seat);<br>
+ else if (shell->exposay.focus_prev)<br>
+ activate(shell, shell->exposay.focus_prev,<br>
+ shell->exposay.seat);<br>
+<br>
+ wl_list_for_each(esurface, &shell->exposay.surface_list, link)<br>
+ exposay_animate_out(esurface);<br>
+ weston_compositor_schedule_repaint(shell->compositor);<br>
+<br>
+ return EXPOSAY_LAYOUT_ANIMATE_TO_INACTIVE;<br>
+}<br>
+<br>
+static enum exposay_layout_state<br>
+exposay_transition_active(struct desktop_shell *shell)<br>
+{<br>
+ struct weston_seat *seat = shell->exposay.seat;<br>
+<br>
+ shell->exposay.workspace = get_current_workspace(shell);<br>
+ shell->exposay.focus_prev = seat->keyboard->focus;<br>
+ shell->exposay.focus_current = seat->keyboard->focus;<br>
+ shell->exposay.clicked = NULL;<br>
+ wl_list_init(&shell->exposay.surface_list);<br>
+<br>
+ lower_fullscreen_layer(shell);<br>
+ shell->exposay.grab_kbd.interface = &exposay_kbd_grab;<br>
+ weston_keyboard_start_grab(seat->keyboard,<br>
+ &shell->exposay.grab_kbd);<br>
+ weston_keyboard_set_focus(seat->keyboard, NULL);<br>
+<br>
+ shell->exposay.grab_ptr.interface = &exposay_ptr_grab;<br>
+ weston_pointer_start_grab(seat->pointer,<br>
+ &shell->exposay.grab_ptr);<br>
+ weston_pointer_set_focus(seat->pointer, NULL,<br>
+ seat->pointer->x, seat->pointer->y);<br>
+<br>
+ return exposay_layout(shell);<br>
+}<br>
+<br>
+static void<br>
+exposay_check_state(struct desktop_shell *shell)<br>
+{<br>
+ enum exposay_layout_state state_new = shell->exposay.state_cur;<br>
+ int do_switch = 0;<br>
+<br>
+ /* Don't do anything whilst animations are running, just store up<br>
+ * target state changes and only act on them when the animations have<br>
+ * completed. */<br>
+ if (exposay_is_animating(shell))<br>
+ return;<br>
+<br>
+ switch (shell->exposay.state_target) {<br>
+ case EXPOSAY_TARGET_OVERVIEW:<br>
+ switch (shell->exposay.state_cur) {<br>
+ case EXPOSAY_LAYOUT_OVERVIEW:<br>
+ goto out;<br>
+ case EXPOSAY_LAYOUT_ANIMATE_TO_OVERVIEW:<br>
+ state_new = EXPOSAY_LAYOUT_OVERVIEW;<br>
+ break;<br>
+ default:<br>
+ state_new = exposay_transition_active(shell);<br>
+ break;<br>
+ }<br>
+ break;<br>
+<br>
+ case EXPOSAY_TARGET_SWITCH:<br>
+ do_switch = 1; /* fallthrough */<br>
+ case EXPOSAY_TARGET_CANCEL:<br>
+ switch (shell->exposay.state_cur) {<br>
+ case EXPOSAY_LAYOUT_INACTIVE:<br>
+ goto out;<br>
+ case EXPOSAY_LAYOUT_ANIMATE_TO_INACTIVE:<br>
+ state_new = exposay_set_inactive(shell);<br>
+ break;<br>
+ default:<br>
+ state_new = exposay_transition_inactive(shell, do_switch);<br>
+ break;<br>
+ }<br>
+<br>
+ break;<br>
+ }<br>
+<br>
+out:<br>
+ shell->exposay.state_cur = state_new;<br>
+}<br>
+<br>
+static void<br>
+exposay_set_state(struct desktop_shell *shell, enum exposay_target_state state,<br>
+ struct weston_seat *seat)<br>
+{<br>
+ shell->exposay.state_target = state;<br>
+ shell->exposay.seat = seat;<br>
+ exposay_check_state(shell);<br>
+}<br>
+<br>
+static void<br>
+exposay_binding(struct weston_seat *seat, enum weston_keyboard_modifier modifier,<br>
+ void *data)<br>
+{<br>
+ struct desktop_shell *shell = data;<br>
+<br>
+ if (shell->exposay.state_target == EXPOSAY_TARGET_OVERVIEW)<br>
+ exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, seat);<br>
+ else<br>
+ exposay_set_state(shell, EXPOSAY_TARGET_OVERVIEW, seat);<br>
+}<br>
+<br>
static void<br>
backlight_binding(struct weston_seat *seat, uint32_t time, uint32_t key,<br>
void *data)<br>
@@ -4731,6 +5300,8 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)<br>
workspace_move_surface_down_binding,<br>
shell);<br>
<br>
+ weston_compositor_add_modifier_binding(ec, mod, exposay_binding, shell);<br>
+<br>
/* Add bindings for mod+F[1-6] for workspace 1 to 6. */<br>
if (shell->workspaces.num > 1) {<br>
num_workspace_bindings = shell->workspaces.num;<br>
@@ -4802,6 +5373,9 @@ module_init(struct weston_compositor *ec,<br>
<br>
shell_configuration(shell);<br>
<br>
+ shell->exposay.state_cur = EXPOSAY_LAYOUT_INACTIVE;<br>
+ shell->exposay.state_target = EXPOSAY_TARGET_CANCEL;<br>
+<br>
for (i = 0; i < shell->workspaces.num; i++) {<br>
pws = wl_array_add(&shell->workspaces.array, sizeof *pws);<br>
if (pws == NULL)<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.3.1<br>
<br>
_______________________________________________<br>
wayland-devel mailing list<br>
<a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
</font></span></blockquote></div><br></div>