blob: 633c08f1e0cd23861f08a0cbb380893351790624 [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>
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040028#include <linux/input.h>
29
30#include "compositor.h"
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050031#include "tablet-shell-server-protocol.h"
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040032
33/*
34 * TODO: Don't fade back from black until we've received a lockscreen
35 * attachment.
36 */
37
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -040038enum {
39 STATE_STARTING,
40 STATE_LOCKED,
41 STATE_HOME,
42 STATE_SWITCHER,
43 STATE_TASK
44};
45
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050046struct tablet_shell {
Kristian Høgsberg904055a2011-08-18 17:55:30 -040047 struct wl_resource resource;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040048
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -040049 struct wl_listener lock_listener;
50 struct wl_listener unlock_listener;
51 struct wl_listener destroy_listener;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040052
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050053 struct weston_compositor *compositor;
54 struct weston_process process;
55 struct weston_input_device *device;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040056 struct wl_client *client;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040057
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050058 struct weston_surface *surface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040059
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050060 struct weston_surface *lockscreen_surface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040061 struct wl_listener lockscreen_listener;
Tiago Vignatti0a386112012-03-28 13:04:02 +030062 struct weston_layer lockscreen_layer;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040063
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050064 struct weston_surface *home_surface;
Tiago Vignatti0a386112012-03-28 13:04:02 +030065 struct weston_layer homescreen_layer;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040066
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050067 struct weston_surface *switcher_surface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040068 struct wl_listener switcher_listener;
69
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050070 struct tablet_client *current_client;
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -040071
72 int state, previous_state;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040073 int long_press_active;
74 struct wl_event_source *long_press_source;
75};
76
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050077struct tablet_client {
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040078 struct wl_resource resource;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050079 struct tablet_shell *shell;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040080 struct wl_client *client;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050081 struct weston_surface *surface;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040082 char *name;
83};
84
Kristian Høgsbergd4af3202011-06-21 17:43:31 -040085static void
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -040086tablet_shell_destroy(struct wl_listener *listener, void *data);
87
88static struct tablet_shell *
89get_shell(struct weston_compositor *compositor)
90{
91 struct wl_listener *l;
92
93 l = wl_signal_get(&compositor->destroy_signal, tablet_shell_destroy);
94 if (l)
95 return container_of(l, struct tablet_shell, destroy_listener);
96
97 return NULL;
98}
99
100static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500101tablet_shell_sigchld(struct weston_process *process, int status)
Kristian Høgsbergd4af3202011-06-21 17:43:31 -0400102{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500103 struct tablet_shell *shell =
104 container_of(process, struct tablet_shell, process);
Kristian Høgsbergd4af3202011-06-21 17:43:31 -0400105
106 shell->process.pid = 0;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400107
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500108 fprintf(stderr,
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500109 "weston-tablet-shell crashed, exit code %d\n", status);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400110}
111
112static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500113tablet_shell_set_state(struct tablet_shell *shell, int state)
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400114{
115 static const char *states[] = {
116 "STARTING", "LOCKED", "HOME", "SWITCHER", "TASK"
117 };
118
119 fprintf(stderr, "switching to state %s (from %s)\n",
120 states[state], states[shell->state]);
121 shell->previous_state = shell->state;
122 shell->state = state;
123}
124
125static void
Kristian Høgsberg34486162012-03-29 13:08:32 -0400126tablet_shell_surface_configure(struct weston_surface *surface,
127 int32_t sx, int32_t sy)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400128{
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -0400129 struct tablet_shell *shell = get_shell(surface->compositor);
Kristian Høgsberg34486162012-03-29 13:08:32 -0400130 int32_t width, height;
131
132 if (weston_surface_is_mapped(surface))
133 return;
134
135 width = surface->buffer->width;
136 height = surface->buffer->height;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400137
Pekka Paalanen8fb8d3b2012-02-13 13:03:59 +0200138 weston_surface_configure(surface, 0, 0, width, height);
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400139
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400140 if (surface == shell->lockscreen_surface) {
Tiago Vignatti0a386112012-03-28 13:04:02 +0300141 wl_list_insert(&shell->lockscreen_layer.surface_list,
142 &surface->layer_link);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400143 } else if (surface == shell->switcher_surface) {
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400144 /* */
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400145 } else if (surface == shell->home_surface) {
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400146 if (shell->state == STATE_STARTING) {
Tiago Vignatti0a386112012-03-28 13:04:02 +0300147 /* homescreen always visible, at the bottom */
148 wl_list_insert(&shell->homescreen_layer.surface_list,
149 &surface->layer_link);
150
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500151 tablet_shell_set_state(shell, STATE_LOCKED);
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400152 shell->previous_state = STATE_HOME;
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -0500153 tablet_shell_send_show_lockscreen(&shell->resource);
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400154 }
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400155 } else if (shell->current_client &&
156 shell->current_client->surface != surface &&
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400157 shell->current_client->client == surface->surface.resource.client) {
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500158 tablet_shell_set_state(shell, STATE_TASK);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400159 shell->current_client->surface = surface;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500160 weston_zoom_run(surface, 0.3, 1.0, NULL, NULL);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400161 }
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -0500162
163 wl_list_insert(&shell->compositor->surface_list, &surface->link);
Pekka Paalanenf07cb5d2012-02-10 13:34:36 +0200164 weston_surface_assign_output(surface);
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -0500165}
166
167static void
Kristian Høgsberg27e30522012-04-11 23:18:23 -0400168handle_lockscreen_surface_destroy(struct wl_listener *listener, void *data)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400169{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500170 struct tablet_shell *shell =
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400171 container_of(listener,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500172 struct tablet_shell, lockscreen_listener);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400173
174 shell->lockscreen_surface = NULL;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500175 tablet_shell_set_state(shell, shell->previous_state);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400176}
177
178static void
179tablet_shell_set_lockscreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400180 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400181 struct wl_resource *surface_resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400182{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500183 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500184 struct weston_surface *es = surface_resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400185
Pekka Paalanen8fb8d3b2012-02-13 13:03:59 +0200186 weston_surface_set_position(es, 0, 0);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400187 shell->lockscreen_surface = es;
Tiago Vignatti0a386112012-03-28 13:04:02 +0300188 shell->lockscreen_surface->configure = tablet_shell_surface_configure;
Kristian Høgsberg27e30522012-04-11 23:18:23 -0400189 shell->lockscreen_listener.notify = handle_lockscreen_surface_destroy;
190 wl_signal_add(&es->surface.resource.destroy_signal,
191 &shell->lockscreen_listener);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400192}
193
194static void
Kristian Høgsberg27e30522012-04-11 23:18:23 -0400195handle_switcher_surface_destroy(struct wl_listener *listener, void *data)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400196{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500197 struct tablet_shell *shell =
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400198 container_of(listener,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500199 struct tablet_shell, switcher_listener);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400200
201 shell->switcher_surface = NULL;
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400202 if (shell->state != STATE_LOCKED)
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500203 tablet_shell_set_state(shell, shell->previous_state);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400204}
205
206static void
207tablet_shell_set_switcher(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400208 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400209 struct wl_resource *surface_resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400210{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500211 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500212 struct weston_surface *es = surface_resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400213
214 /* FIXME: Switcher should be centered and the compositor
215 * should do the tinting of the background. With the cache
216 * layer idea, we should be able to hit the framerate on the
217 * fade/zoom in. */
218 shell->switcher_surface = es;
Pekka Paalanen8fb8d3b2012-02-13 13:03:59 +0200219 weston_surface_set_position(shell->switcher_surface, 0, 0);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400220
Kristian Høgsberg27e30522012-04-11 23:18:23 -0400221 shell->switcher_listener.notify = handle_switcher_surface_destroy;
222 wl_signal_add(&es->surface.resource.destroy_signal,
223 &shell->switcher_listener);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400224}
225
226static void
227tablet_shell_set_homescreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400228 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400229 struct wl_resource *surface_resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400230{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500231 struct tablet_shell *shell = resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400232
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400233 shell->home_surface = surface_resource->data;
Tiago Vignatti0a386112012-03-28 13:04:02 +0300234 shell->home_surface->configure = tablet_shell_surface_configure;
235
Pekka Paalanen8fb8d3b2012-02-13 13:03:59 +0200236 weston_surface_set_position(shell->home_surface, 0, 0);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400237}
238
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400239static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500240minimize_zoom_done(struct weston_zoom *zoom, void *data)
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400241{
Kristian Høgsberg698c0582011-12-04 15:20:19 -0500242 struct tablet_shell *shell = data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500243 struct weston_compositor *compositor = shell->compositor;
244 struct weston_input_device *device =
245 (struct weston_input_device *) compositor->input_device;
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400246
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400247 weston_surface_activate(shell->home_surface, device);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400248}
249
250static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500251tablet_shell_switch_to(struct tablet_shell *shell,
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500252 struct weston_surface *surface)
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400253{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500254 struct weston_compositor *compositor = shell->compositor;
255 struct weston_input_device *device =
256 (struct weston_input_device *) compositor->input_device;
257 struct weston_surface *current;
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400258
259 if (shell->state == STATE_SWITCHER) {
260 wl_list_remove(&shell->switcher_listener.link);
261 shell->switcher_surface = NULL;
262 };
263
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400264 if (surface == shell->home_surface) {
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500265 tablet_shell_set_state(shell, STATE_HOME);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400266
267 if (shell->current_client && shell->current_client->surface) {
268 current = shell->current_client->surface;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500269 weston_zoom_run(current, 1.0, 0.3,
Kristian Høgsberg698c0582011-12-04 15:20:19 -0500270 minimize_zoom_done, shell);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400271 }
272 } else {
273 fprintf(stderr, "switch to %p\n", surface);
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400274 weston_surface_activate(surface, device);
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500275 tablet_shell_set_state(shell, STATE_TASK);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500276 weston_zoom_run(surface, 0.3, 1.0, NULL, NULL);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400277 }
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400278}
279
280static void
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400281tablet_shell_show_grid(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400282 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400283 struct wl_resource *surface_resource)
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400284{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500285 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500286 struct weston_surface *es = surface_resource->data;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400287
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500288 tablet_shell_switch_to(shell, es);
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400289}
290
291static void
292tablet_shell_show_panels(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400293 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400294 struct wl_resource *surface_resource)
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400295{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500296 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500297 struct weston_surface *es = surface_resource->data;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400298
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500299 tablet_shell_switch_to(shell, es);
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400300}
301
302static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400303destroy_tablet_client(struct wl_resource *resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400304{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500305 struct tablet_client *tablet_client =
306 container_of(resource, struct tablet_client, resource);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400307
308 free(tablet_client->name);
309 free(tablet_client);
310}
311
312static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400313tablet_client_destroy(struct wl_client *client,
314 struct wl_resource *resource)
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400315{
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400316 wl_resource_destroy(resource);
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400317}
318
319static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400320tablet_client_activate(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400321{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500322 struct tablet_client *tablet_client = resource->data;
323 struct tablet_shell *shell = tablet_client->shell;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400324
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400325 shell->current_client = tablet_client;
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400326 if (!tablet_client->surface)
327 return;
328
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500329 tablet_shell_switch_to(shell, tablet_client->surface);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400330}
331
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500332static const struct tablet_client_interface tablet_client_implementation = {
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400333 tablet_client_destroy,
334 tablet_client_activate
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400335};
336
337static void
338tablet_shell_create_client(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400339 struct wl_resource *resource,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400340 uint32_t id, const char *name, int fd)
341{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500342 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500343 struct weston_compositor *compositor = shell->compositor;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500344 struct tablet_client *tablet_client;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400345
346 tablet_client = malloc(sizeof *tablet_client);
347 if (tablet_client == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400348 wl_resource_post_no_memory(resource);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400349 return;
350 }
351
352 tablet_client->client = wl_client_create(compositor->wl_display, fd);
353 tablet_client->shell = shell;
354 tablet_client->name = strdup(name);
355
356 tablet_client->resource.destroy = destroy_tablet_client;
357 tablet_client->resource.object.id = id;
358 tablet_client->resource.object.interface =
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500359 &tablet_client_interface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400360 tablet_client->resource.object.implementation =
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500361 (void (**)(void)) &tablet_client_implementation;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400362
363 wl_client_add_resource(client, &tablet_client->resource);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400364 tablet_client->surface = NULL;
365 shell->current_client = tablet_client;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400366
367 fprintf(stderr, "created client %p, id %d, name %s, fd %d\n",
368 tablet_client->client, id, name, fd);
369}
370
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500371static const struct tablet_shell_interface tablet_shell_implementation = {
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400372 tablet_shell_set_lockscreen,
373 tablet_shell_set_switcher,
374 tablet_shell_set_homescreen,
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400375 tablet_shell_show_grid,
376 tablet_shell_show_panels,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400377 tablet_shell_create_client
378};
379
380static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500381launch_ux_daemon(struct tablet_shell *shell)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400382{
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500383 const char *shell_exe = LIBEXECDIR "/weston-tablet-shell";
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400384
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500385 shell->client = weston_client_launch(shell->compositor,
Pekka Paalanen409ef0a2011-12-02 15:30:21 +0200386 &shell->process,
387 shell_exe, tablet_shell_sigchld);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400388}
389
390static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500391toggle_switcher(struct tablet_shell *shell)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400392{
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400393 switch (shell->state) {
394 case STATE_SWITCHER:
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -0500395 tablet_shell_send_hide_switcher(&shell->resource);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400396 break;
397 default:
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -0500398 tablet_shell_send_show_switcher(&shell->resource);
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500399 tablet_shell_set_state(shell, STATE_SWITCHER);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400400 break;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400401 }
402}
403
404static void
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -0400405tablet_shell_lock(struct wl_listener *listener, void *data)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400406{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500407 struct tablet_shell *shell =
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -0400408 container_of(listener, struct tablet_shell, lock_listener);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400409
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400410 if (shell->state == STATE_LOCKED)
411 return;
412 if (shell->state == STATE_SWITCHER)
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -0500413 tablet_shell_send_hide_switcher(&shell->resource);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400414
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -0500415 tablet_shell_send_show_lockscreen(&shell->resource);
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500416 tablet_shell_set_state(shell, STATE_LOCKED);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400417}
418
419static void
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -0400420tablet_shell_unlock(struct wl_listener *listener, void *data)
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200421{
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200422 struct tablet_shell *shell =
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -0400423 container_of(listener, struct tablet_shell, lock_listener);
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200424
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500425 weston_compositor_wake(shell->compositor);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200426}
427
428static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500429go_home(struct tablet_shell *shell)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400430{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500431 struct weston_input_device *device =
432 (struct weston_input_device *) shell->compositor->input_device;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400433
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400434 if (shell->state == STATE_SWITCHER)
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -0500435 tablet_shell_send_hide_switcher(&shell->resource);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400436
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400437 weston_surface_activate(shell->home_surface, device);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400438
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500439 tablet_shell_set_state(shell, STATE_HOME);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400440}
441
442static int
443long_press_handler(void *data)
444{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500445 struct tablet_shell *shell = data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400446
447 shell->long_press_active = 0;
448 toggle_switcher(shell);
449
450 return 1;
451}
452
453static void
454menu_key_binding(struct wl_input_device *device, uint32_t time,
Scott Moreau6a3633d2012-03-20 08:47:59 -0600455 uint32_t key, uint32_t button, uint32_t axis, int32_t state, void *data)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400456{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500457 struct tablet_shell *shell = data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400458
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400459 if (shell->state == STATE_LOCKED)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400460 return;
461
462 if (state)
463 toggle_switcher(shell);
464}
465
466static void
467home_key_binding(struct wl_input_device *device, uint32_t time,
Scott Moreau6a3633d2012-03-20 08:47:59 -0600468 uint32_t key, uint32_t button, uint32_t axis, int32_t state, void *data)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400469{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500470 struct tablet_shell *shell = data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400471
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400472 if (shell->state == STATE_LOCKED)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400473 return;
474
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500475 shell->device = (struct weston_input_device *) device;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400476
477 if (state) {
478 wl_event_source_timer_update(shell->long_press_source, 500);
479 shell->long_press_active = 1;
480 } else if (shell->long_press_active) {
481 wl_event_source_timer_update(shell->long_press_source, 0);
482 shell->long_press_active = 0;
483
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400484 switch (shell->state) {
485 case STATE_HOME:
486 case STATE_SWITCHER:
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400487 toggle_switcher(shell);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400488 break;
489 default:
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400490 go_home(shell);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400491 break;
492 }
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400493 }
494}
495
496static void
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500497destroy_tablet_shell(struct wl_resource *resource)
498{
499}
500
501static void
Tiago Vignattibe143262012-04-16 17:31:41 +0300502bind_tablet_shell(struct wl_client *client, void *data, uint32_t version,
503 uint32_t id)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400504{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500505 struct tablet_shell *shell = data;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400506
507 if (shell->client != client)
508 /* Throw an error or just let the client fail when it
509 * tries to access the object?. */
510 return;
511
Kristian Høgsbergf790c792011-08-19 14:41:57 -0400512 shell->resource.object.id = id;
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500513 shell->resource.object.interface = &tablet_shell_interface;
514 shell->resource.object.implementation =
515 (void (**)(void)) &tablet_shell_implementation;
516 shell->resource.client = client;
517 shell->resource.data = shell;
518 shell->resource.destroy = destroy_tablet_shell;
519
520 wl_client_add_resource(client, &shell->resource);
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400521}
522
Pekka Paalanen3c647232011-12-22 13:43:43 +0200523static void
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -0400524tablet_shell_destroy(struct wl_listener *listener, void *data)
Pekka Paalanen3c647232011-12-22 13:43:43 +0200525{
526 struct tablet_shell *shell =
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -0400527 container_of(listener, struct tablet_shell, destroy_listener);
Pekka Paalanen3c647232011-12-22 13:43:43 +0200528
Tiago Vignatti0a386112012-03-28 13:04:02 +0300529 if (shell->home_surface)
530 shell->home_surface->configure = NULL;
531
532 if (shell->lockscreen_surface)
533 shell->lockscreen_surface->configure = NULL;
534
Pekka Paalanen3c647232011-12-22 13:43:43 +0200535 wl_event_source_remove(shell->long_press_source);
536 free(shell);
537}
538
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400539void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500540shell_init(struct weston_compositor *compositor);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400541
542WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500543shell_init(struct weston_compositor *compositor)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400544{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500545 struct tablet_shell *shell;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400546 struct wl_event_loop *loop;
547
548 shell = malloc(sizeof *shell);
549 if (shell == NULL)
550 return;
551
552 memset(shell, 0, sizeof *shell);
553 shell->compositor = compositor;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400554
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -0400555 shell->destroy_listener.notify = tablet_shell_destroy;
556 wl_signal_add(&compositor->destroy_signal, &shell->destroy_listener);
557 shell->lock_listener.notify = tablet_shell_lock;
558 wl_signal_add(&compositor->lock_signal, &shell->lock_listener);
559 shell->unlock_listener.notify = tablet_shell_unlock;
560 wl_signal_add(&compositor->unlock_signal, &shell->unlock_listener);
561
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400562 /* FIXME: This will make the object available to all clients. */
Tiago Vignattibe143262012-04-16 17:31:41 +0300563 wl_display_add_global(compositor->wl_display, &tablet_shell_interface,
564 shell, bind_tablet_shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400565
566 loop = wl_display_get_event_loop(compositor->wl_display);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400567 shell->long_press_source =
568 wl_event_loop_add_timer(loop, long_press_handler, shell);
569
Scott Moreau6a3633d2012-03-20 08:47:59 -0600570 weston_compositor_add_binding(compositor, KEY_LEFTMETA, 0, 0, 0,
571 home_key_binding, shell);
572 weston_compositor_add_binding(compositor, KEY_RIGHTMETA, 0, 0, 0,
573 home_key_binding, shell);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500574 weston_compositor_add_binding(compositor, KEY_LEFTMETA, 0, 0,
Scott Moreau6a3633d2012-03-20 08:47:59 -0600575 MODIFIER_SUPER, home_key_binding, shell);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500576 weston_compositor_add_binding(compositor, KEY_RIGHTMETA, 0, 0,
Kristian Høgsbergf77ce462011-05-03 13:11:43 -0400577 MODIFIER_SUPER, home_key_binding, shell);
Scott Moreau6a3633d2012-03-20 08:47:59 -0600578 weston_compositor_add_binding(compositor, KEY_COMPOSE, 0, 0, 0,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400579 menu_key_binding, shell);
580
Tiago Vignatti0a386112012-03-28 13:04:02 +0300581 weston_layer_init(&shell->homescreen_layer,
582 &compositor->cursor_layer.link);
583 weston_layer_init(&shell->lockscreen_layer,
584 &compositor->cursor_layer.link);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400585 launch_ux_daemon(shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400586
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500587 tablet_shell_set_state(shell, STATE_STARTING);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400588}