266b5d3f7968e7fae648420572f81fe07d6ba304
[profile/ivi/weston-ivi-shell.git] / compositor / switcher.c
1 /*
2  * Copyright © 2011 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <linux/input.h>
26
27 #include "compositor.h"
28
29 struct wlsc_switcher {
30         struct wlsc_compositor *compositor;
31         struct wlsc_surface *current;
32         struct wl_listener listener;
33 };
34
35 static void
36 wlsc_switcher_next(struct wlsc_switcher *switcher)
37 {
38         struct wl_list *l;
39         struct wl_surface *current;
40
41         wlsc_surface_damage(switcher->current);
42         l = switcher->current->link.next;
43         if (l == &switcher->compositor->surface_list)
44                 l = switcher->compositor->surface_list.next;
45         switcher->current = container_of(l, struct wlsc_surface, link);
46         wl_list_remove(&switcher->listener.link);
47         current = &switcher->current->surface;
48         wl_list_insert(current->resource.destroy_listener_list.prev,
49                        &switcher->listener.link);
50         switcher->compositor->overlay = switcher->current;
51         wlsc_surface_damage(switcher->current);
52 }
53
54 static void
55 switcher_handle_surface_destroy(struct wl_listener *listener,
56                                 struct wl_resource *resource, uint32_t time)
57 {
58         struct wlsc_switcher *switcher =
59                 container_of(listener, struct wlsc_switcher, listener);
60
61         wlsc_switcher_next(switcher);
62 }
63
64 static struct wlsc_switcher *
65 wlsc_switcher_create(struct wlsc_compositor *compositor)
66 {
67         struct wlsc_switcher *switcher;
68
69         switcher = malloc(sizeof *switcher);
70         switcher->compositor = compositor;
71         switcher->current = container_of(compositor->surface_list.next,
72                                          struct wlsc_surface, link);
73         switcher->listener.func = switcher_handle_surface_destroy;
74         wl_list_init(&switcher->listener.link);
75
76         return switcher;
77 }
78
79 static void
80 wlsc_switcher_destroy(struct wlsc_switcher *switcher)
81 {
82         wl_list_remove(&switcher->listener.link);
83         free(switcher);
84 }
85
86 static void
87 switcher_next_binding(struct wl_input_device *device, uint32_t time,
88                       uint32_t key, uint32_t button,
89                       uint32_t state, void *data)
90 {
91         struct wlsc_compositor *compositor = data;
92
93         if (!state)
94                 return;
95         if (wl_list_empty(&compositor->surface_list))
96                 return;
97         if (compositor->switcher == NULL)
98                 compositor->switcher = wlsc_switcher_create(compositor);
99
100         wlsc_switcher_next(compositor->switcher);
101 }
102
103 static void
104 switcher_terminate_binding(struct wl_input_device *device,
105                            uint32_t time, uint32_t key, uint32_t button,
106                            uint32_t state, void *data)
107 {
108         struct wlsc_compositor *compositor = data;
109         struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
110
111         if (compositor->switcher && !state) {
112                 wlsc_surface_activate(compositor->switcher->current, wd, time);
113                 wlsc_switcher_destroy(compositor->switcher);
114                 compositor->switcher = NULL;
115                 compositor->overlay = NULL;
116         }
117 }
118
119 void
120 wlsc_switcher_init(struct wlsc_compositor *compositor)
121 {
122         wlsc_compositor_add_binding(compositor,
123                                     KEY_TAB, 0, MODIFIER_SUPER,
124                                     switcher_next_binding, compositor);
125         wlsc_compositor_add_binding(compositor,
126                                     KEY_LEFTMETA, 0, MODIFIER_SUPER,
127                                     switcher_terminate_binding, compositor);
128         wlsc_compositor_add_binding(compositor,
129                                     KEY_RIGHTMETA, 0, MODIFIER_SUPER,
130                                     switcher_terminate_binding, compositor);
131 }