blob: 5e8d5f127f9ff4451b2c1f522a86cd36411e0811 [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øgsberg8334bc12012-01-03 10:29:47 -050049 struct weston_shell shell;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040050
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050051 struct weston_compositor *compositor;
52 struct weston_process process;
53 struct weston_input_device *device;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040054 struct wl_client *client;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040055
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050056 struct weston_surface *surface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040057
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050058 struct weston_surface *lockscreen_surface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040059 struct wl_listener lockscreen_listener;
60
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050061 struct weston_surface *home_surface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040062
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050063 struct weston_surface *switcher_surface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040064 struct wl_listener switcher_listener;
65
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050066 struct tablet_client *current_client;
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -040067
68 int state, previous_state;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040069 int long_press_active;
70 struct wl_event_source *long_press_source;
71};
72
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050073struct tablet_client {
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040074 struct wl_resource resource;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050075 struct tablet_shell *shell;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040076 struct wl_client *client;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050077 struct weston_surface *surface;
Kristian Høgsberg3a53efe2011-05-02 14:21:03 -040078 char *name;
79};
80
Kristian Høgsbergd4af3202011-06-21 17:43:31 -040081static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050082tablet_shell_sigchld(struct weston_process *process, int status)
Kristian Høgsbergd4af3202011-06-21 17:43:31 -040083{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050084 struct tablet_shell *shell =
85 container_of(process, struct tablet_shell, process);
Kristian Høgsbergd4af3202011-06-21 17:43:31 -040086
87 shell->process.pid = 0;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040088
Kristian Høgsberg6336e462011-11-26 17:36:23 -050089 fprintf(stderr,
Kristian Høgsberg9724b512012-01-03 14:35:49 -050090 "weston-tablet-shell crashed, exit code %d\n", status);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -040091}
92
93static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -050094tablet_shell_set_state(struct tablet_shell *shell, int state)
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -040095{
96 static const char *states[] = {
97 "STARTING", "LOCKED", "HOME", "SWITCHER", "TASK"
98 };
99
100 fprintf(stderr, "switching to state %s (from %s)\n",
101 states[state], states[shell->state]);
102 shell->previous_state = shell->state;
103 shell->state = state;
104}
105
106static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500107tablet_shell_map(struct weston_shell *base, struct weston_surface *surface,
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -0500108 int32_t width, int32_t height)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400109{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500110 struct tablet_shell *shell =
111 container_of(base, struct tablet_shell, shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400112
Pekka Paalanenba3cf952012-01-25 16:22:05 +0200113 surface->geometry.x = 0;
114 surface->geometry.y = 0;
115 surface->geometry.dirty = 1;
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400116
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400117 if (surface == shell->lockscreen_surface) {
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500118 /* */
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400119 } else if (surface == shell->switcher_surface) {
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400120 /* */
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400121 } else if (surface == shell->home_surface) {
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400122 if (shell->state == STATE_STARTING) {
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500123 tablet_shell_set_state(shell, STATE_LOCKED);
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400124 shell->previous_state = STATE_HOME;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400125 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500126 TABLET_SHELL_SHOW_LOCKSCREEN);
Kristian Høgsbergb79216e2011-05-08 21:28:45 -0400127 }
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400128 } else if (shell->current_client &&
129 shell->current_client->surface != surface &&
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400130 shell->current_client->client == surface->surface.resource.client) {
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500131 tablet_shell_set_state(shell, STATE_TASK);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400132 shell->current_client->surface = surface;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500133 weston_zoom_run(surface, 0.3, 1.0, NULL, NULL);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400134 }
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -0500135
136 wl_list_insert(&shell->compositor->surface_list, &surface->link);
Pekka Paalanenba3cf952012-01-25 16:22:05 +0200137 weston_surface_configure(surface, surface->geometry.x,
138 surface->geometry.y, width, height);
Pekka Paalanenf07cb5d2012-02-10 13:34:36 +0200139 weston_surface_assign_output(surface);
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -0500140}
141
142static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500143tablet_shell_configure(struct weston_shell *base,
144 struct weston_surface *surface,
Pekka Paalanenddae03c2012-02-06 14:54:20 +0200145 GLfloat x, GLfloat y,
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -0500146 int32_t width, int32_t height)
147{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500148 weston_surface_configure(surface, x, y, width, height);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400149}
150
151static void
152handle_lockscreen_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200153 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400154{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500155 struct tablet_shell *shell =
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400156 container_of(listener,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500157 struct tablet_shell, lockscreen_listener);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400158
159 shell->lockscreen_surface = NULL;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500160 tablet_shell_set_state(shell, shell->previous_state);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400161}
162
163static void
164tablet_shell_set_lockscreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400165 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400166 struct wl_resource *surface_resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400167{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500168 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500169 struct weston_surface *es = surface_resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400170
Pekka Paalanenba3cf952012-01-25 16:22:05 +0200171 es->geometry.x = 0;
172 es->geometry.y = 0;
173 es->geometry.dirty = 1;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400174 shell->lockscreen_surface = es;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400175 shell->lockscreen_listener.func = handle_lockscreen_surface_destroy;
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200176 wl_list_insert(es->surface.resource.destroy_listener_list.prev,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400177 &shell->lockscreen_listener.link);
178}
179
180static void
181handle_switcher_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200182 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400183{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500184 struct tablet_shell *shell =
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400185 container_of(listener,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500186 struct tablet_shell, switcher_listener);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400187
188 shell->switcher_surface = NULL;
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400189 if (shell->state != STATE_LOCKED)
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500190 tablet_shell_set_state(shell, shell->previous_state);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400191}
192
193static void
194tablet_shell_set_switcher(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400195 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400196 struct wl_resource *surface_resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400197{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500198 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500199 struct weston_surface *es = surface_resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400200
201 /* FIXME: Switcher should be centered and the compositor
202 * should do the tinting of the background. With the cache
203 * layer idea, we should be able to hit the framerate on the
204 * fade/zoom in. */
205 shell->switcher_surface = es;
Pekka Paalanenba3cf952012-01-25 16:22:05 +0200206 shell->switcher_surface->geometry.x = 0;
207 shell->switcher_surface->geometry.y = 0;
208 shell->switcher_surface->geometry.dirty = 1;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400209
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400210 shell->switcher_listener.func = handle_switcher_surface_destroy;
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200211 wl_list_insert(es->surface.resource.destroy_listener_list.prev,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400212 &shell->switcher_listener.link);
213}
214
215static void
216tablet_shell_set_homescreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400217 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400218 struct wl_resource *surface_resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400219{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500220 struct tablet_shell *shell = resource->data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400221
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400222 shell->home_surface = surface_resource->data;
Pekka Paalanenba3cf952012-01-25 16:22:05 +0200223 shell->home_surface->geometry.x = 0;
224 shell->home_surface->geometry.y = 0;
225 shell->home_surface->geometry.dirty = 1;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400226}
227
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400228static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500229minimize_zoom_done(struct weston_zoom *zoom, void *data)
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400230{
Kristian Høgsberg698c0582011-12-04 15:20:19 -0500231 struct tablet_shell *shell = data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500232 struct weston_compositor *compositor = shell->compositor;
233 struct weston_input_device *device =
234 (struct weston_input_device *) compositor->input_device;
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400235
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500236 weston_surface_activate(shell->home_surface,
237 device, weston_compositor_get_time());
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400238}
239
240static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500241tablet_shell_switch_to(struct tablet_shell *shell,
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500242 struct weston_surface *surface)
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400243{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500244 struct weston_compositor *compositor = shell->compositor;
245 struct weston_input_device *device =
246 (struct weston_input_device *) compositor->input_device;
247 struct weston_surface *current;
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400248
249 if (shell->state == STATE_SWITCHER) {
250 wl_list_remove(&shell->switcher_listener.link);
251 shell->switcher_surface = NULL;
252 };
253
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400254 if (surface == shell->home_surface) {
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500255 tablet_shell_set_state(shell, STATE_HOME);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400256
257 if (shell->current_client && shell->current_client->surface) {
258 current = shell->current_client->surface;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500259 weston_zoom_run(current, 1.0, 0.3,
Kristian Høgsberg698c0582011-12-04 15:20:19 -0500260 minimize_zoom_done, shell);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400261 }
262 } else {
263 fprintf(stderr, "switch to %p\n", surface);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500264 weston_surface_activate(surface, device,
265 weston_compositor_get_time());
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500266 tablet_shell_set_state(shell, STATE_TASK);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500267 weston_zoom_run(surface, 0.3, 1.0, NULL, NULL);
Kristian Høgsberg57eca742011-06-21 16:40:56 -0400268 }
Kristian Høgsbergbfcf07c2011-05-05 15:25:28 -0400269}
270
271static void
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400272tablet_shell_show_grid(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400273 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400274 struct wl_resource *surface_resource)
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400275{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500276 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500277 struct weston_surface *es = surface_resource->data;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400278
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500279 tablet_shell_switch_to(shell, es);
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400280}
281
282static void
283tablet_shell_show_panels(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400284 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400285 struct wl_resource *surface_resource)
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400286{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500287 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500288 struct weston_surface *es = surface_resource->data;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400289
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500290 tablet_shell_switch_to(shell, es);
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400291}
292
293static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400294destroy_tablet_client(struct wl_resource *resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400295{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500296 struct tablet_client *tablet_client =
297 container_of(resource, struct tablet_client, resource);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400298
299 free(tablet_client->name);
300 free(tablet_client);
301}
302
303static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400304tablet_client_destroy(struct wl_client *client,
305 struct wl_resource *resource)
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400306{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500307 wl_resource_destroy(resource, weston_compositor_get_time());
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400308}
309
310static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400311tablet_client_activate(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400312{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500313 struct tablet_client *tablet_client = resource->data;
314 struct tablet_shell *shell = tablet_client->shell;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400315
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400316 shell->current_client = tablet_client;
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400317 if (!tablet_client->surface)
318 return;
319
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500320 tablet_shell_switch_to(shell, tablet_client->surface);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400321}
322
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500323static const struct tablet_client_interface tablet_client_implementation = {
Kristian Høgsberg81e8c262011-05-04 16:17:20 -0400324 tablet_client_destroy,
325 tablet_client_activate
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400326};
327
328static void
329tablet_shell_create_client(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400330 struct wl_resource *resource,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400331 uint32_t id, const char *name, int fd)
332{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500333 struct tablet_shell *shell = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500334 struct weston_compositor *compositor = shell->compositor;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500335 struct tablet_client *tablet_client;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400336
337 tablet_client = malloc(sizeof *tablet_client);
338 if (tablet_client == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400339 wl_resource_post_no_memory(resource);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400340 return;
341 }
342
343 tablet_client->client = wl_client_create(compositor->wl_display, fd);
344 tablet_client->shell = shell;
345 tablet_client->name = strdup(name);
346
347 tablet_client->resource.destroy = destroy_tablet_client;
348 tablet_client->resource.object.id = id;
349 tablet_client->resource.object.interface =
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500350 &tablet_client_interface;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400351 tablet_client->resource.object.implementation =
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500352 (void (**)(void)) &tablet_client_implementation;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400353
354 wl_client_add_resource(client, &tablet_client->resource);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400355 tablet_client->surface = NULL;
356 shell->current_client = tablet_client;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400357
358 fprintf(stderr, "created client %p, id %d, name %s, fd %d\n",
359 tablet_client->client, id, name, fd);
360}
361
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500362static const struct tablet_shell_interface tablet_shell_implementation = {
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400363 tablet_shell_set_lockscreen,
364 tablet_shell_set_switcher,
365 tablet_shell_set_homescreen,
Kristian Høgsberg92fb0e92011-05-04 16:16:43 -0400366 tablet_shell_show_grid,
367 tablet_shell_show_panels,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400368 tablet_shell_create_client
369};
370
371static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500372launch_ux_daemon(struct tablet_shell *shell)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400373{
Kristian Høgsberg9724b512012-01-03 14:35:49 -0500374 const char *shell_exe = LIBEXECDIR "/weston-tablet-shell";
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400375
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500376 shell->client = weston_client_launch(shell->compositor,
Pekka Paalanen409ef0a2011-12-02 15:30:21 +0200377 &shell->process,
378 shell_exe, tablet_shell_sigchld);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400379}
380
381static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500382toggle_switcher(struct tablet_shell *shell)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400383{
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400384 switch (shell->state) {
385 case STATE_SWITCHER:
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400386 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500387 TABLET_SHELL_HIDE_SWITCHER);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400388 break;
389 default:
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400390 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500391 TABLET_SHELL_SHOW_SWITCHER);
392 tablet_shell_set_state(shell, STATE_SWITCHER);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400393 break;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400394 }
395}
396
397static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500398tablet_shell_lock(struct weston_shell *base)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400399{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500400 struct tablet_shell *shell =
401 container_of(base, struct tablet_shell, shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400402
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400403 if (shell->state == STATE_LOCKED)
404 return;
405 if (shell->state == STATE_SWITCHER)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400406 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500407 TABLET_SHELL_HIDE_SWITCHER);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400408
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400409 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500410 TABLET_SHELL_SHOW_LOCKSCREEN);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400411
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500412 tablet_shell_set_state(shell, STATE_LOCKED);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400413}
414
415static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500416tablet_shell_unlock(struct weston_shell *base)
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200417{
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200418 struct tablet_shell *shell =
419 container_of(base, struct tablet_shell, shell);
420
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500421 weston_compositor_wake(shell->compositor);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200422}
423
424static void
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500425go_home(struct tablet_shell *shell)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400426{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500427 struct weston_input_device *device =
428 (struct weston_input_device *) shell->compositor->input_device;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400429
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400430 if (shell->state == STATE_SWITCHER)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400431 wl_resource_post_event(&shell->resource,
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500432 TABLET_SHELL_HIDE_SWITCHER);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400433
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500434 weston_surface_activate(shell->home_surface, device,
435 weston_compositor_get_time());
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400436
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500437 tablet_shell_set_state(shell, STATE_HOME);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400438}
439
440static int
441long_press_handler(void *data)
442{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500443 struct tablet_shell *shell = data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400444
445 shell->long_press_active = 0;
446 toggle_switcher(shell);
447
448 return 1;
449}
450
451static void
452menu_key_binding(struct wl_input_device *device, uint32_t time,
453 uint32_t key, uint32_t button, uint32_t state, void *data)
454{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500455 struct tablet_shell *shell = data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400456
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400457 if (shell->state == STATE_LOCKED)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400458 return;
459
460 if (state)
461 toggle_switcher(shell);
462}
463
464static void
465home_key_binding(struct wl_input_device *device, uint32_t time,
466 uint32_t key, uint32_t button, uint32_t state, void *data)
467{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500468 struct tablet_shell *shell = data;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400469
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400470 if (shell->state == STATE_LOCKED)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400471 return;
472
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500473 shell->device = (struct weston_input_device *) device;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400474
475 if (state) {
476 wl_event_source_timer_update(shell->long_press_source, 500);
477 shell->long_press_active = 1;
478 } else if (shell->long_press_active) {
479 wl_event_source_timer_update(shell->long_press_source, 0);
480 shell->long_press_active = 0;
481
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400482 switch (shell->state) {
483 case STATE_HOME:
484 case STATE_SWITCHER:
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400485 toggle_switcher(shell);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400486 break;
487 default:
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400488 go_home(shell);
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400489 break;
490 }
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400491 }
492}
493
494static void
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500495destroy_tablet_shell(struct wl_resource *resource)
496{
497}
498
499static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400500bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400501{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500502 struct tablet_shell *shell = data;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400503
504 if (shell->client != client)
505 /* Throw an error or just let the client fail when it
506 * tries to access the object?. */
507 return;
508
Kristian Høgsbergf790c792011-08-19 14:41:57 -0400509 shell->resource.object.id = id;
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500510 shell->resource.object.interface = &tablet_shell_interface;
511 shell->resource.object.implementation =
512 (void (**)(void)) &tablet_shell_implementation;
513 shell->resource.client = client;
514 shell->resource.data = shell;
515 shell->resource.destroy = destroy_tablet_shell;
516
517 wl_client_add_resource(client, &shell->resource);
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400518}
519
Pekka Paalanen3c647232011-12-22 13:43:43 +0200520static void
Kristian Høgsberg3466bc82012-01-03 11:29:15 -0500521tablet_shell_destroy(struct weston_shell *base)
Pekka Paalanen3c647232011-12-22 13:43:43 +0200522{
523 struct tablet_shell *shell =
524 container_of(base, struct tablet_shell, shell);
525
526 wl_event_source_remove(shell->long_press_source);
527 free(shell);
528}
529
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400530void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500531shell_init(struct weston_compositor *compositor);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400532
533WL_EXPORT void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500534shell_init(struct weston_compositor *compositor)
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400535{
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500536 struct tablet_shell *shell;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400537 struct wl_event_loop *loop;
538
539 shell = malloc(sizeof *shell);
540 if (shell == NULL)
541 return;
542
543 memset(shell, 0, sizeof *shell);
544 shell->compositor = compositor;
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400545
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400546 /* FIXME: This will make the object available to all clients. */
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400547 wl_display_add_global(compositor->wl_display,
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500548 &tablet_shell_interface, shell, bind_shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400549
550 loop = wl_display_get_event_loop(compositor->wl_display);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400551 shell->long_press_source =
552 wl_event_loop_add_timer(loop, long_press_handler, shell);
553
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500554 weston_compositor_add_binding(compositor, KEY_LEFTMETA, 0, 0,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400555 home_key_binding, shell);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500556 weston_compositor_add_binding(compositor, KEY_RIGHTMETA, 0, 0,
Kristian Høgsbergd28b4d72011-05-02 14:11:15 -0400557 home_key_binding, shell);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500558 weston_compositor_add_binding(compositor, KEY_LEFTMETA, 0,
Kristian Høgsbergf77ce462011-05-03 13:11:43 -0400559 MODIFIER_SUPER, home_key_binding, shell);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500560 weston_compositor_add_binding(compositor, KEY_RIGHTMETA, 0,
Kristian Høgsbergf77ce462011-05-03 13:11:43 -0400561 MODIFIER_SUPER, home_key_binding, shell);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500562 weston_compositor_add_binding(compositor, KEY_COMPOSE, 0, 0,
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400563 menu_key_binding, shell);
564
565 compositor->shell = &shell->shell;
566
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500567 shell->shell.lock = tablet_shell_lock;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200568 shell->shell.unlock = tablet_shell_unlock;
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500569 shell->shell.map = tablet_shell_map;
570 shell->shell.configure = tablet_shell_configure;
Pekka Paalanen3c647232011-12-22 13:43:43 +0200571 shell->shell.destroy = tablet_shell_destroy;
Kristian Høgsberg47fe08a2011-10-28 12:26:06 -0400572
Kristian Høgsberg1258a4a2011-05-04 11:35:02 -0400573 launch_ux_daemon(shell);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400574
Kristian Høgsberg64f1c3f2011-11-14 15:50:03 -0500575 tablet_shell_set_state(shell, STATE_STARTING);
Kristian Høgsbergeb7e12c2011-04-23 13:17:43 -0400576}