blob: cb820bbfb338e418aba50e744be617e10cd23f96 [file] [log] [blame]
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -04001/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <sys/wait.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <fcntl.h>
31#include <linux/input.h>
32
33#include "compositor.h"
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050034#include "tablet-shell-server-protocol.h"
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040035
36/*
37 * TODO: Don't fade back from black until we've received a lockscreen
38 * attachment.
39 */
40
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -040041enum {
42 STATE_STARTING,
43 STATE_LOCKED,
44 STATE_HOME,
45 STATE_SWITCHER,
46 STATE_TASK
47};
48
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050049struct tablet_shell {
Kristian Høgsberg904055a2011-08-18 17:55:30 -040050 struct wl_resource resource;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040051
52 struct wlsc_shell shell;
53
54 struct wlsc_compositor *compositor;
Kristian Høgsbergd4af3202011-06-21 17:43:31 -040055 struct wlsc_process process;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040056 struct wlsc_input_device *device;
57 struct wl_client *client;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040058
59 struct wlsc_surface *surface;
60
61 struct wlsc_surface *lockscreen_surface;
62 struct wl_listener lockscreen_listener;
63
64 struct wlsc_surface *home_surface;
65
66 struct wlsc_surface *switcher_surface;
67 struct wl_listener switcher_listener;
68
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050069 struct tablet_client *current_client;
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -040070
71 int state, previous_state;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040072 int long_press_active;
73 struct wl_event_source *long_press_source;
74};
75
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050076struct tablet_client {
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040077 struct wl_resource resource;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050078 struct tablet_shell *shell;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040079 struct wl_client *client;
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -040080 struct wlsc_surface *surface;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040081 char *name;
82};
83
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050084struct tablet_zoom {
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040085 struct wlsc_surface *surface;
86 struct wlsc_animation animation;
Kristian Høgsberg269c7822011-05-02 14:38:18 -040087 struct wlsc_spring spring;
Kristian Høgsberg0bc0e242011-05-02 14:35:40 -040088 struct wlsc_transform transform;
Kristian Høgsberg132c6532011-05-03 12:41:03 -040089 struct wl_listener listener;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050090 struct tablet_shell *shell;
91 void (*done)(struct tablet_zoom *zoom);
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040092};
93
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040094
Kristian Høgsbergd4af3202011-06-21 17:43:31 -040095static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050096tablet_shell_sigchld(struct wlsc_process *process, int status)
Kristian Høgsbergd4af3202011-06-21 17:43:31 -040097{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050098 struct tablet_shell *shell =
99 container_of(process, struct tablet_shell, process);
Kristian Høgsbergd4af3202011-06-21 17:43:31 -0400100
101 shell->process.pid = 0;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400102
103 fprintf(stderr, "meego-ux-daemon crashed, exit code %d\n", status);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400104}
105
106static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500107tablet_shell_set_state(struct tablet_shell *shell, int state)
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400108{
109 static const char *states[] = {
110 "STARTING", "LOCKED", "HOME", "SWITCHER", "TASK"
111 };
112
113 fprintf(stderr, "switching to state %s (from %s)\n",
114 states[state], states[shell->state]);
115 shell->previous_state = shell->state;
116 shell->state = state;
117}
118
119static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500120tablet_zoom_destroy(struct tablet_zoom *zoom)
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400121{
122 wl_list_remove(&zoom->animation.link);
123 zoom->surface->transform = NULL;
124 if (zoom->done)
125 zoom->done(zoom);
126 free(zoom);
127}
128
129static void
Kristian Høgsberg132c6532011-05-03 12:41:03 -0400130handle_zoom_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200131 struct wl_resource *resource, uint32_t time)
Kristian Høgsberg132c6532011-05-03 12:41:03 -0400132{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500133 struct tablet_zoom *zoom =
134 container_of(listener, struct tablet_zoom, listener);
Kristian Høgsberg132c6532011-05-03 12:41:03 -0400135
Kristian Høgsberg132c6532011-05-03 12:41:03 -0400136 fprintf(stderr, "animation surface gone\n");
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500137 tablet_zoom_destroy(zoom);
Kristian Høgsberg132c6532011-05-03 12:41:03 -0400138}
139
140static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500141tablet_zoom_frame(struct wlsc_animation *animation,
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400142 struct wlsc_output *output, uint32_t msecs)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400143{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500144 struct tablet_zoom *zoom =
145 container_of(animation, struct tablet_zoom, animation);
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400146 struct wlsc_surface *es = zoom->surface;
147 GLfloat scale;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400148
Kristian Høgsberg269c7822011-05-02 14:38:18 -0400149 wlsc_spring_update(&zoom->spring, msecs);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400150
Kristian Høgsberg269c7822011-05-02 14:38:18 -0400151 if (wlsc_spring_done(&zoom->spring)) {
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400152 fprintf(stderr, "animation done\n");
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500153 tablet_zoom_destroy(zoom);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400154 }
155
Kristian Høgsberg269c7822011-05-02 14:38:18 -0400156 scale = zoom->spring.current;
Kristian Høgsberg0bc0e242011-05-02 14:35:40 -0400157 wlsc_matrix_init(&zoom->transform.matrix);
158 wlsc_matrix_translate(&zoom->transform.matrix,
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400159 -es->width / 2.0, -es->height / 2.0, 0);
Kristian Høgsberg0bc0e242011-05-02 14:35:40 -0400160 wlsc_matrix_scale(&zoom->transform.matrix, scale, scale, scale);
161 wlsc_matrix_translate(&zoom->transform.matrix,
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400162 es->width / 2.0, es->height / 2.0, 0);
163
Kristian Høgsberg269c7822011-05-02 14:38:18 -0400164 scale = 1.0 / zoom->spring.current;
Kristian Høgsberg0bc0e242011-05-02 14:35:40 -0400165 wlsc_matrix_init(&zoom->transform.inverse);
166 wlsc_matrix_scale(&zoom->transform.inverse, scale, scale, scale);
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400167
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400168 wlsc_surface_damage(es);
169}
170
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500171static struct tablet_zoom *
172tablet_zoom_run(struct tablet_shell *shell,
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400173 struct wlsc_surface *surface,
174 GLfloat start, GLfloat stop)
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400175{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500176 struct tablet_zoom *zoom;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400177
178 fprintf(stderr, "starting animation for surface %p\n", surface);
179
180 zoom = malloc(sizeof *zoom);
181 if (!zoom)
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400182 return NULL;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400183
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400184 zoom->shell = shell;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400185 zoom->surface = surface;
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400186 zoom->done = NULL;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400187 surface->transform = &zoom->transform;
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400188 wlsc_spring_init(&zoom->spring, 200.0, start, stop);
Kristian Høgsberg269c7822011-05-02 14:38:18 -0400189 zoom->spring.timestamp = wlsc_compositor_get_time();
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500190 zoom->animation.frame = tablet_zoom_frame;
191 tablet_zoom_frame(&zoom->animation, NULL,
Kristian Høgsberg269c7822011-05-02 14:38:18 -0400192 zoom->spring.timestamp);
Kristian Høgsberg0bc0e242011-05-02 14:35:40 -0400193
Kristian Høgsberg132c6532011-05-03 12:41:03 -0400194 zoom->listener.func = handle_zoom_surface_destroy;
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200195 wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
Kristian Høgsberg132c6532011-05-03 12:41:03 -0400196 &zoom->listener.link);
197
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400198 wl_list_insert(shell->compositor->animation_list.prev,
199 &zoom->animation.link);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400200
201 return zoom;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400202}
203
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -0400204static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500205tablet_shell_map(struct wlsc_shell *base, struct wlsc_surface *surface,
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -0500206 int32_t width, int32_t height)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400207{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500208 struct tablet_shell *shell =
209 container_of(base, struct tablet_shell, shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400210
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400211 surface->x = 0;
212 surface->y = 0;
213
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400214 if (surface == shell->lockscreen_surface) {
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400215 wlsc_compositor_fade(shell->compositor, 0.0);
216 wlsc_compositor_wake(shell->compositor);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400217 } else if (surface == shell->switcher_surface) {
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400218 /* */
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400219 } else if (surface == shell->home_surface) {
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400220 if (shell->state == STATE_STARTING) {
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500221 tablet_shell_set_state(shell, STATE_LOCKED);
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400222 shell->previous_state = STATE_HOME;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400223 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500224 TABLET_SHELL_SHOW_LOCKSCREEN);
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400225 }
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400226 } else if (shell->current_client &&
227 shell->current_client->surface != surface &&
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400228 shell->current_client->client == surface->surface.resource.client) {
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500229 tablet_shell_set_state(shell, STATE_TASK);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400230 shell->current_client->surface = surface;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500231 tablet_zoom_run(shell, surface, 0.3, 1.0);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400232 }
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -0500233
234 wl_list_insert(&shell->compositor->surface_list, &surface->link);
235 wlsc_surface_configure(surface, surface->x, surface->y, width, height);
236}
237
238static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500239tablet_shell_configure(struct wlsc_shell *base,
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -0500240 struct wlsc_surface *surface,
241 int32_t x, int32_t y,
242 int32_t width, int32_t height)
243{
244 wlsc_surface_configure(surface, x, y, width, height);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400245}
246
247static void
248handle_lockscreen_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200249 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400250{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500251 struct tablet_shell *shell =
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400252 container_of(listener,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500253 struct tablet_shell, lockscreen_listener);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400254
255 shell->lockscreen_surface = NULL;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500256 tablet_shell_set_state(shell, shell->previous_state);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400257}
258
259static void
260tablet_shell_set_lockscreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400261 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400262 struct wl_resource *surface_resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400263{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500264 struct tablet_shell *shell = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400265 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400266 struct wlsc_input_device *device =
267 (struct wlsc_input_device *) shell->compositor->input_device;
268
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400269 es->x = 0;
270 es->y = 0;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400271 wlsc_surface_activate(es, device, wlsc_compositor_get_time());
272 shell->lockscreen_surface = es;
273
274 shell->lockscreen_listener.func = handle_lockscreen_surface_destroy;
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200275 wl_list_insert(es->surface.resource.destroy_listener_list.prev,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400276 &shell->lockscreen_listener.link);
277}
278
279static void
280handle_switcher_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200281 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400282{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500283 struct tablet_shell *shell =
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400284 container_of(listener,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500285 struct tablet_shell, switcher_listener);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400286
287 shell->switcher_surface = NULL;
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400288 if (shell->state != STATE_LOCKED)
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500289 tablet_shell_set_state(shell, shell->previous_state);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400290}
291
292static void
293tablet_shell_set_switcher(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400294 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400295 struct wl_resource *surface_resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400296{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500297 struct tablet_shell *shell = resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400298 struct wlsc_input_device *device =
299 (struct wlsc_input_device *) shell->compositor->input_device;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400300 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400301
302 /* FIXME: Switcher should be centered and the compositor
303 * should do the tinting of the background. With the cache
304 * layer idea, we should be able to hit the framerate on the
305 * fade/zoom in. */
306 shell->switcher_surface = es;
307 shell->switcher_surface->x = 0;
308 shell->switcher_surface->y = 0;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400309
310 wlsc_surface_activate(es, device, wlsc_compositor_get_time());
311
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400312 shell->switcher_listener.func = handle_switcher_surface_destroy;
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200313 wl_list_insert(es->surface.resource.destroy_listener_list.prev,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400314 &shell->switcher_listener.link);
315}
316
317static void
318tablet_shell_set_homescreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400319 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400320 struct wl_resource *surface_resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400321{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500322 struct tablet_shell *shell = resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400323 struct wlsc_input_device *device =
324 (struct wlsc_input_device *) shell->compositor->input_device;
325
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400326 shell->home_surface = surface_resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400327 shell->home_surface->x = 0;
328 shell->home_surface->y = 0;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400329
330 wlsc_surface_activate(shell->home_surface, device,
331 wlsc_compositor_get_time());
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400332}
333
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400334static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500335minimize_zoom_done(struct tablet_zoom *zoom)
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400336{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500337 struct tablet_shell *shell = zoom->shell;
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400338 struct wlsc_compositor *compositor = shell->compositor;
339 struct wlsc_input_device *device =
340 (struct wlsc_input_device *) compositor->input_device;
341
342 wlsc_surface_activate(shell->home_surface,
343 device, wlsc_compositor_get_time());
344}
345
346static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500347tablet_shell_switch_to(struct tablet_shell *shell,
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400348 struct wlsc_surface *surface)
349{
350 struct wlsc_compositor *compositor = shell->compositor;
351 struct wlsc_input_device *device =
352 (struct wlsc_input_device *) compositor->input_device;
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400353 struct wlsc_surface *current;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500354 struct tablet_zoom *zoom;
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400355
356 if (shell->state == STATE_SWITCHER) {
357 wl_list_remove(&shell->switcher_listener.link);
358 shell->switcher_surface = NULL;
359 };
360
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400361 if (surface == shell->home_surface) {
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500362 tablet_shell_set_state(shell, STATE_HOME);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400363
364 if (shell->current_client && shell->current_client->surface) {
365 current = shell->current_client->surface;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500366 zoom = tablet_zoom_run(shell, current, 1.0, 0.3);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400367 zoom->done = minimize_zoom_done;
368 }
369 } else {
370 fprintf(stderr, "switch to %p\n", surface);
371 wlsc_surface_activate(surface, device,
372 wlsc_compositor_get_time());
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500373 tablet_shell_set_state(shell, STATE_TASK);
374 tablet_zoom_run(shell, surface, 0.3, 1.0);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400375 }
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400376}
377
378static void
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400379tablet_shell_show_grid(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400380 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400381 struct wl_resource *surface_resource)
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400382{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500383 struct tablet_shell *shell = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400384 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400385
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500386 tablet_shell_switch_to(shell, es);
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400387}
388
389static void
390tablet_shell_show_panels(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400391 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400392 struct wl_resource *surface_resource)
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400393{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500394 struct tablet_shell *shell = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400395 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400396
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500397 tablet_shell_switch_to(shell, es);
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400398}
399
400static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400401destroy_tablet_client(struct wl_resource *resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400402{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500403 struct tablet_client *tablet_client =
404 container_of(resource, struct tablet_client, resource);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400405
406 free(tablet_client->name);
407 free(tablet_client);
408}
409
410static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400411tablet_client_destroy(struct wl_client *client,
412 struct wl_resource *resource)
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400413{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400414 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400415}
416
417static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400418tablet_client_activate(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400419{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500420 struct tablet_client *tablet_client = resource->data;
421 struct tablet_shell *shell = tablet_client->shell;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400422
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400423 shell->current_client = tablet_client;
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400424 if (!tablet_client->surface)
425 return;
426
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500427 tablet_shell_switch_to(shell, tablet_client->surface);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400428}
429
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500430static const struct tablet_client_interface tablet_client_implementation = {
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400431 tablet_client_destroy,
432 tablet_client_activate
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400433};
434
435static void
436tablet_shell_create_client(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400437 struct wl_resource *resource,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400438 uint32_t id, const char *name, int fd)
439{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500440 struct tablet_shell *shell = resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400441 struct wlsc_compositor *compositor = shell->compositor;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500442 struct tablet_client *tablet_client;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400443
444 tablet_client = malloc(sizeof *tablet_client);
445 if (tablet_client == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400446 wl_resource_post_no_memory(resource);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400447 return;
448 }
449
450 tablet_client->client = wl_client_create(compositor->wl_display, fd);
451 tablet_client->shell = shell;
452 tablet_client->name = strdup(name);
453
454 tablet_client->resource.destroy = destroy_tablet_client;
455 tablet_client->resource.object.id = id;
456 tablet_client->resource.object.interface =
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500457 &tablet_client_interface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400458 tablet_client->resource.object.implementation =
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500459 (void (**)(void)) &tablet_client_implementation;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400460
461 wl_client_add_resource(client, &tablet_client->resource);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400462 tablet_client->surface = NULL;
463 shell->current_client = tablet_client;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400464
465 fprintf(stderr, "created client %p, id %d, name %s, fd %d\n",
466 tablet_client->client, id, name, fd);
467}
468
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500469static const struct tablet_shell_interface tablet_shell_implementation = {
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400470 tablet_shell_set_lockscreen,
471 tablet_shell_set_switcher,
472 tablet_shell_set_homescreen,
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400473 tablet_shell_show_grid,
474 tablet_shell_show_panels,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400475 tablet_shell_create_client
476};
477
478static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500479launch_ux_daemon(struct tablet_shell *shell)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400480{
481 struct wlsc_compositor *compositor = shell->compositor;
482 char s[32];
483 int sv[2], flags;
484
485 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
486 fprintf(stderr, "socketpair failed\n");
487 return;
488 }
489
Kristian Høgsbergd4af3202011-06-21 17:43:31 -0400490 shell->process.pid = fork();
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500491 shell->process.cleanup = tablet_shell_sigchld;
Kristian Høgsbergd4af3202011-06-21 17:43:31 -0400492
493 switch (shell->process.pid) {
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400494 case 0:
Kristian Høgsberg3d1cad82011-05-02 13:57:38 -0400495 /* SOCK_CLOEXEC closes both ends, so we need to unset
496 * the flag on the client fd. */
497 flags = fcntl(sv[1], F_GETFD);
498 if (flags != -1)
499 fcntl(sv[1], F_SETFD, flags & ~FD_CLOEXEC);
500
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400501 snprintf(s, sizeof s, "%d", sv[1]);
502 setenv("WAYLAND_SOCKET", s, 1);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400503 setenv("QT_QPA_PLATFORM", "waylandgl", 1);
504 if (execl("/usr/libexec/meego-ux-daemon",
505 "/usr/libexec/meego-ux-daemon", NULL) < 0)
506 fprintf(stderr, "exec failed: %m\n");
507 exit(-1);
508
509 default:
510 close(sv[1]);
511 shell->client =
512 wl_client_create(compositor->wl_display, sv[0]);
Kristian Høgsbergd4af3202011-06-21 17:43:31 -0400513 wlsc_watch_process(&shell->process);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400514 break;
515
516 case -1:
517 fprintf(stderr, "failed to fork\n");
518 break;
519 }
520}
521
522static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500523toggle_switcher(struct tablet_shell *shell)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400524{
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400525 switch (shell->state) {
526 case STATE_SWITCHER:
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400527 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500528 TABLET_SHELL_HIDE_SWITCHER);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400529 break;
530 default:
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400531 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500532 TABLET_SHELL_SHOW_SWITCHER);
533 tablet_shell_set_state(shell, STATE_SWITCHER);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400534 break;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400535 }
536}
537
538static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500539tablet_shell_lock(struct wlsc_shell *base)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400540{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500541 struct tablet_shell *shell =
542 container_of(base, struct tablet_shell, shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400543
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400544 if (shell->state == STATE_LOCKED)
545 return;
546 if (shell->state == STATE_SWITCHER)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400547 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500548 TABLET_SHELL_HIDE_SWITCHER);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400549
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400550 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500551 TABLET_SHELL_SHOW_LOCKSCREEN);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400552
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500553 tablet_shell_set_state(shell, STATE_LOCKED);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400554}
555
556static void
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200557tablet_shell_unlock(struct wlsc_shell *base)
558{
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200559 struct tablet_shell *shell =
560 container_of(base, struct tablet_shell, shell);
561
562 wlsc_compositor_wake(shell->compositor);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200563}
564
565static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500566go_home(struct tablet_shell *shell)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400567{
568 struct wlsc_input_device *device =
569 (struct wlsc_input_device *) shell->compositor->input_device;
570
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400571 if (shell->state == STATE_SWITCHER)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400572 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500573 TABLET_SHELL_HIDE_SWITCHER);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400574
575 wlsc_surface_activate(shell->home_surface, device,
576 wlsc_compositor_get_time());
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400577
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500578 tablet_shell_set_state(shell, STATE_HOME);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400579}
580
581static int
582long_press_handler(void *data)
583{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500584 struct tablet_shell *shell = data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400585
586 shell->long_press_active = 0;
587 toggle_switcher(shell);
588
589 return 1;
590}
591
592static void
593menu_key_binding(struct wl_input_device *device, uint32_t time,
594 uint32_t key, uint32_t button, uint32_t state, void *data)
595{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500596 struct tablet_shell *shell = data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400597
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400598 if (shell->state == STATE_LOCKED)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400599 return;
600
601 if (state)
602 toggle_switcher(shell);
603}
604
605static void
606home_key_binding(struct wl_input_device *device, uint32_t time,
607 uint32_t key, uint32_t button, uint32_t state, void *data)
608{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500609 struct tablet_shell *shell = data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400610
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400611 if (shell->state == STATE_LOCKED)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400612 return;
613
614 shell->device = (struct wlsc_input_device *) device;
615
616 if (state) {
617 wl_event_source_timer_update(shell->long_press_source, 500);
618 shell->long_press_active = 1;
619 } else if (shell->long_press_active) {
620 wl_event_source_timer_update(shell->long_press_source, 0);
621 shell->long_press_active = 0;
622
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400623 switch (shell->state) {
624 case STATE_HOME:
625 case STATE_SWITCHER:
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400626 toggle_switcher(shell);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400627 break;
628 default:
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400629 go_home(shell);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400630 break;
631 }
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400632 }
633}
634
635static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400636bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400637{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500638 struct tablet_shell *shell = data;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400639
640 if (shell->client != client)
641 /* Throw an error or just let the client fail when it
642 * tries to access the object?. */
643 return;
644
645 shell->resource.client = client;
Kristian Høgsbergf790c792011-08-19 14:41:57 -0400646 shell->resource.object.id = id;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400647}
648
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400649void
650shell_init(struct wlsc_compositor *compositor);
651
652WL_EXPORT void
653shell_init(struct wlsc_compositor *compositor)
654{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500655 struct tablet_shell *shell;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400656 struct wl_event_loop *loop;
657
658 shell = malloc(sizeof *shell);
659 if (shell == NULL)
660 return;
661
662 memset(shell, 0, sizeof *shell);
663 shell->compositor = compositor;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400664
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500665 shell->resource.object.interface = &tablet_shell_interface;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400666 shell->resource.object.implementation =
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500667 (void (**)(void)) &tablet_shell_implementation;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400668
669 /* FIXME: This will make the object available to all clients. */
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400670 wl_display_add_global(compositor->wl_display,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400671 &wl_shell_interface, shell, bind_shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400672
673 loop = wl_display_get_event_loop(compositor->wl_display);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400674 shell->long_press_source =
675 wl_event_loop_add_timer(loop, long_press_handler, shell);
676
Kristian Høgsbergd28b4d72011-05-02 14:11:15 -0400677 wlsc_compositor_add_binding(compositor, KEY_LEFTMETA, 0, 0,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400678 home_key_binding, shell);
Kristian Høgsbergd28b4d72011-05-02 14:11:15 -0400679 wlsc_compositor_add_binding(compositor, KEY_RIGHTMETA, 0, 0,
680 home_key_binding, shell);
Kristian Høgsbergf77ce462011-05-03 13:11:43 -0400681 wlsc_compositor_add_binding(compositor, KEY_LEFTMETA, 0,
682 MODIFIER_SUPER, home_key_binding, shell);
683 wlsc_compositor_add_binding(compositor, KEY_RIGHTMETA, 0,
684 MODIFIER_SUPER, home_key_binding, shell);
Kristian Høgsberg9d097772011-05-02 15:24:11 -0400685 wlsc_compositor_add_binding(compositor, KEY_COMPOSE, 0, 0,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400686 menu_key_binding, shell);
687
688 compositor->shell = &shell->shell;
689
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500690 shell->shell.lock = tablet_shell_lock;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200691 shell->shell.unlock = tablet_shell_unlock;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500692 shell->shell.map = tablet_shell_map;
693 shell->shell.configure = tablet_shell_configure;
Kristian Høgsberg47fe08a2011-10-28 12:26:06 -0400694
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400695 launch_ux_daemon(shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400696
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500697 tablet_shell_set_state(shell, STATE_STARTING);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400698}