blob: 45733b11978ef26dae08526318285e9849f9c43e [file] [log] [blame]
Kristian Høgsberg6336e462011-11-26 17:36:23 -05001/*
Tiago Vignatti0a386112012-03-28 13:04:02 +03002 * Copyright © 2011, 2012 Intel Corporation
Kristian Høgsberg6336e462011-11-26 17:36:23 -05003 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include <stdint.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Daniel Stone6d4a3c12012-06-18 19:39:56 +010027#include <unistd.h>
Tiago Vignatti0a386112012-03-28 13:04:02 +030028#include <sys/wait.h>
Kristian Høgsberg6336e462011-11-26 17:36:23 -050029
30#include "window.h"
Kristian Høgsberg5a315bc2012-05-15 22:33:43 -040031#include "../shared/cairo-util.h"
Kristian Høgsberg9b935c82011-12-08 12:44:27 -050032#include "../shared/config-parser.h"
Kristian Høgsberg6336e462011-11-26 17:36:23 -050033
34#include "tablet-shell-client-protocol.h"
35
Tiago Vignatti0a386112012-03-28 13:04:02 +030036struct tablet {
Kristian Høgsberg6336e462011-11-26 17:36:23 -050037 struct display *display;
38 struct tablet_shell *tablet_shell;
39 struct rectangle allocation;
Kristian Høgsberg6336e462011-11-26 17:36:23 -050040 struct window *switcher;
Tiago Vignatti0a386112012-03-28 13:04:02 +030041
42 struct homescreen *homescreen;
43 struct lockscreen *lockscreen;
44};
45
46struct homescreen {
47 struct window *window;
48 struct widget *widget;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050049 struct wl_list launcher_list;
50};
51
Tiago Vignatti0a386112012-03-28 13:04:02 +030052struct lockscreen {
53 struct window *window;
54 struct widget *widget;
55};
56
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050057struct launcher {
Alex Wu5b72a4d2012-06-18 16:52:31 +080058 struct widget *widget;
59 struct homescreen *homescreen;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050060 cairo_surface_t *icon;
Alex Wu5b72a4d2012-06-18 16:52:31 +080061 int focused, pressed;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050062 char *path;
63 struct wl_list link;
64};
65
66static char *key_lockscreen_icon;
67static char *key_lockscreen_background;
68static char *key_homescreen_background;
Kristian Høgsberg6336e462011-11-26 17:36:23 -050069
70static void
Tiago Vignatti0a386112012-03-28 13:04:02 +030071sigchild_handler(int s)
72{
73 int status;
74 pid_t pid;
75
76 while (pid = waitpid(-1, &status, WNOHANG), pid > 0)
77 fprintf(stderr, "child %d exited\n", pid);
78}
79
80static void
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050081paint_background(cairo_t *cr, const char *path, struct rectangle *allocation)
Kristian Høgsberg6336e462011-11-26 17:36:23 -050082{
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050083 cairo_surface_t *image = NULL;
84 cairo_pattern_t *pattern;
85 cairo_matrix_t matrix;
86 double sx, sy;
Kristian Høgsberg6336e462011-11-26 17:36:23 -050087
88 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050089 if (path)
Kristian Høgsbergf02a6492012-03-12 01:05:25 -040090 image = load_cairo_surface(path);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -050091 if (image) {
92 pattern = cairo_pattern_create_for_surface(image);
93 sx = (double) cairo_image_surface_get_width(image) /
94 allocation->width;
95 sy = (double) cairo_image_surface_get_height(image) /
96 allocation->height;
97 cairo_matrix_init_scale(&matrix, sx, sy);
98 cairo_pattern_set_matrix(pattern, &matrix);
99 cairo_set_source(cr, pattern);
100 cairo_pattern_destroy (pattern);
101 cairo_surface_destroy(image);
102 cairo_paint(cr);
103 } else {
Tiago Vignatti0a386112012-03-28 13:04:02 +0300104 fprintf(stderr, "couldn't load background image: %s\n", path);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500105 cairo_set_source_rgb(cr, 0.2, 0, 0);
106 cairo_paint(cr);
107 }
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500108}
109
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500110static void
Tiago Vignatti0a386112012-03-28 13:04:02 +0300111homescreen_draw(struct widget *widget, void *data)
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500112{
Tiago Vignatti0a386112012-03-28 13:04:02 +0300113 struct homescreen *homescreen = data;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500114 cairo_surface_t *surface;
115 struct rectangle allocation;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500116 cairo_t *cr;
117 struct launcher *launcher;
118 const int rows = 4, columns = 5, icon_width = 128, icon_height = 128;
119 int x, y, i, width, height, vmargin, hmargin, vpadding, hpadding;
120
Tiago Vignatti0a386112012-03-28 13:04:02 +0300121 surface = window_get_surface(homescreen->window);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500122 cr = cairo_create(surface);
123
Tiago Vignatti0a386112012-03-28 13:04:02 +0300124 widget_get_allocation(widget, &allocation);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500125 paint_background(cr, key_homescreen_background, &allocation);
126
127 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
128
129 width = allocation.width - columns * icon_width;
130 hpadding = width / (columns + 1);
131 hmargin = (width - hpadding * (columns - 1)) / 2;
132
133 height = allocation.height - rows * icon_height;
134 vpadding = height / (rows + 1);
135 vmargin = (height - vpadding * (rows - 1)) / 2;
136
137 x = hmargin;
138 y = vmargin;
139 i = 0;
140
Tiago Vignatti0a386112012-03-28 13:04:02 +0300141 wl_list_for_each(launcher, &homescreen->launcher_list, link) {
Alex Wu5b72a4d2012-06-18 16:52:31 +0800142 widget_set_allocation(launcher->widget,
143 x, y, icon_width, icon_height);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500144 x += icon_width + hpadding;
145 i++;
146 if (i == columns) {
147 x = hmargin;
148 y += icon_height + vpadding;
149 i = 0;
150 }
151 }
152
Tiago Vignatti0a386112012-03-28 13:04:02 +0300153 cairo_destroy(cr);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500154 cairo_surface_destroy(surface);
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500155}
156
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500157static void
Tiago Vignatti0a386112012-03-28 13:04:02 +0300158lockscreen_draw(struct widget *widget, void *data)
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500159{
Tiago Vignatti0a386112012-03-28 13:04:02 +0300160 struct lockscreen *lockscreen = data;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500161 cairo_surface_t *surface;
162 cairo_surface_t *icon;
163 struct rectangle allocation;
164 cairo_t *cr;
165 int width, height;
166
Tiago Vignatti0a386112012-03-28 13:04:02 +0300167 surface = window_get_surface(lockscreen->window);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500168 cr = cairo_create(surface);
169
Tiago Vignatti0a386112012-03-28 13:04:02 +0300170 widget_get_allocation(widget, &allocation);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500171 paint_background(cr, key_lockscreen_background, &allocation);
172
173 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300174 icon = load_cairo_surface(key_lockscreen_icon);
Tiago Vignattid0810202012-03-28 20:56:48 +0300175 if (icon) {
176 width = cairo_image_surface_get_width(icon);
177 height = cairo_image_surface_get_height(icon);
178 cairo_set_source_surface(cr, icon,
179 allocation.x + (allocation.width - width) / 2,
180 allocation.y + (allocation.height - height) / 2);
181 } else {
182 fprintf(stderr, "couldn't load lockscreen icon: %s\n",
183 key_lockscreen_icon);
184 cairo_set_source_rgb(cr, 0.2, 0, 0);
185 }
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500186 cairo_paint(cr);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300187 cairo_destroy(cr);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500188 cairo_surface_destroy(icon);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500189 cairo_surface_destroy(surface);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300190}
191
192static void
193lockscreen_button_handler(struct widget *widget,
194 struct input *input, uint32_t time,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100195 uint32_t button,
196 enum wl_pointer_button_state state, void *data)
Tiago Vignatti0a386112012-03-28 13:04:02 +0300197{
198 struct lockscreen *lockscreen = data;
199
Daniel Stone4dbadb12012-05-30 16:31:51 +0100200 if (state == WL_POINTER_BUTTON_STATE_PRESSED && lockscreen->window) {
Tiago Vignatti0a386112012-03-28 13:04:02 +0300201 window_destroy(lockscreen->window);
202 lockscreen->window = NULL;
203 }
204}
205
206static struct homescreen *
207homescreen_create(struct tablet *tablet)
208{
209 struct homescreen *homescreen;
210
Peter Huttererf3d62272013-08-08 11:57:05 +1000211 homescreen = zalloc (sizeof *homescreen);
Scott Moreaufe89f072012-07-11 20:57:15 -0600212 homescreen->window = window_create_custom(tablet->display);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300213 homescreen->widget =
214 window_add_widget(homescreen->window, homescreen);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300215 window_set_user_data(homescreen->window, homescreen);
216 window_set_title(homescreen->window, "homescreen");
217 widget_set_redraw_handler(homescreen->widget, homescreen_draw);
218
219 return homescreen;
220}
221
222static struct lockscreen *
223lockscreen_create(struct tablet *tablet)
224{
225 struct lockscreen *lockscreen;
226
Peter Huttererf3d62272013-08-08 11:57:05 +1000227 lockscreen = zalloc (sizeof *lockscreen);
Scott Moreaufe89f072012-07-11 20:57:15 -0600228 lockscreen->window = window_create_custom(tablet->display);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300229 lockscreen->widget =
230 window_add_widget(lockscreen->window, lockscreen);
231 window_set_user_data(lockscreen->window, lockscreen);
232 window_set_title(lockscreen->window, "lockscreen");
Tiago Vignatti0a386112012-03-28 13:04:02 +0300233 widget_set_redraw_handler(lockscreen->widget, lockscreen_draw);
234 widget_set_button_handler(lockscreen->widget,
235 lockscreen_button_handler);
236
237 return lockscreen;
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500238}
239
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500240static void
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500241show_lockscreen(void *data, struct tablet_shell *tablet_shell)
242{
Tiago Vignatti0a386112012-03-28 13:04:02 +0300243 struct tablet *tablet = data;
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500244
Tiago Vignatti0a386112012-03-28 13:04:02 +0300245 tablet->lockscreen = lockscreen_create(tablet);
246 tablet_shell_set_lockscreen(tablet->tablet_shell,
247 window_get_wl_surface(tablet->lockscreen->window));
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500248
Tiago Vignatti0a386112012-03-28 13:04:02 +0300249 widget_schedule_resize(tablet->lockscreen->widget,
250 tablet->allocation.width,
251 tablet->allocation.height);
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500252}
253
254static void
255show_switcher(void *data, struct tablet_shell *tablet_shell)
256{
Tiago Vignatti0a386112012-03-28 13:04:02 +0300257 struct tablet *tablet = data;
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500258
Scott Moreaufe89f072012-07-11 20:57:15 -0600259 tablet->switcher = window_create_custom(tablet->display);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300260 window_set_user_data(tablet->switcher, tablet);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300261 tablet_shell_set_switcher(tablet->tablet_shell,
262 window_get_wl_surface(tablet->switcher));
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500263}
264
265static void
266hide_switcher(void *data, struct tablet_shell *tablet_shell)
267{
268}
269
270static const struct tablet_shell_listener tablet_shell_listener = {
271 show_lockscreen,
272 show_switcher,
273 hide_switcher
274};
275
Alex Wu5b72a4d2012-06-18 16:52:31 +0800276static int
277launcher_enter_handler(struct widget *widget, struct input *input,
278 float x, float y, void *data)
279{
280 struct launcher *launcher = data;
281
282 launcher->focused = 1;
283 widget_schedule_redraw(widget);
284
285 return CURSOR_LEFT_PTR;
286}
287
288static void
289launcher_leave_handler(struct widget *widget,
290 struct input *input, void *data)
291{
292 struct launcher *launcher = data;
293
294 launcher->focused = 0;
295 widget_schedule_redraw(widget);
296}
297
298static void
299launcher_activate(struct launcher *widget)
300{
301 pid_t pid;
302
303 pid = fork();
304 if (pid < 0) {
305 fprintf(stderr, "fork failed: %m\n");
306 return;
307 }
308
309 if (pid)
310 return;
311
312 if (execl(widget->path, widget->path, NULL) < 0) {
313 fprintf(stderr, "execl '%s' failed: %m\n", widget->path);
314 exit(1);
315 }
316}
317
318static void
319launcher_button_handler(struct widget *widget,
320 struct input *input, uint32_t time,
321 uint32_t button,
322 enum wl_pointer_button_state state, void *data)
323{
324 struct launcher *launcher;
325
326 launcher = widget_get_user_data(widget);
327 widget_schedule_redraw(widget);
328 if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
329 launcher_activate(launcher);
330 launcher->pressed = 0;
331 } else if (state == WL_POINTER_BUTTON_STATE_PRESSED)
332 launcher->pressed = 1;
333}
334
335static void
336launcher_redraw_handler(struct widget *widget, void *data)
337{
338 struct launcher *launcher = data;
339 cairo_surface_t *surface;
340 struct rectangle allocation;
341 cairo_t *cr;
342
343 surface = window_get_surface(launcher->homescreen->window);
344 cr = cairo_create(surface);
345
346 widget_get_allocation(widget, &allocation);
347 if (launcher->pressed) {
348 allocation.x++;
349 allocation.y++;
350 }
351
352 cairo_set_source_surface(cr, launcher->icon,
353 allocation.x, allocation.y);
354 cairo_paint(cr);
355
356 if (launcher->focused) {
357 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
358 cairo_mask_surface(cr, launcher->icon,
359 allocation.x, allocation.y);
360 }
361
362 cairo_destroy(cr);
363}
364
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500365static void
Tiago Vignatti0a386112012-03-28 13:04:02 +0300366tablet_shell_add_launcher(struct tablet *tablet,
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500367 const char *icon, const char *path)
368{
369 struct launcher *launcher;
Tiago Vignatti0a386112012-03-28 13:04:02 +0300370 struct homescreen *homescreen = tablet->homescreen;
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500371
Brian Lovinbc919262013-08-07 15:34:59 -0700372 launcher = xmalloc(sizeof *launcher);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300373 launcher->icon = load_cairo_surface(icon);
Juan Zhao8634f512012-06-20 19:29:27 -0700374 if ( !launcher->icon ||
375 cairo_surface_status (launcher->icon) != CAIRO_STATUS_SUCCESS) {
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500376 fprintf(stderr, "couldn't load %s\n", icon);
377 free(launcher);
378 return;
379 }
Rob Bradfordc48c34d2013-07-26 16:29:42 +0100380 launcher->path = strdup(path);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500381
Alex Wu5b72a4d2012-06-18 16:52:31 +0800382 launcher->homescreen = homescreen;
383 launcher->widget = widget_add_widget(homescreen->widget, launcher);
384 widget_set_enter_handler(launcher->widget,
385 launcher_enter_handler);
386 widget_set_leave_handler(launcher->widget,
387 launcher_leave_handler);
388 widget_set_button_handler(launcher->widget,
389 launcher_button_handler);
390 widget_set_redraw_handler(launcher->widget,
391 launcher_redraw_handler);
392
Tiago Vignatti0a386112012-03-28 13:04:02 +0300393 wl_list_insert(&homescreen->launcher_list, &launcher->link);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500394}
395
396static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400397global_handler(struct display *display, uint32_t name,
Tiago Vignatti0a386112012-03-28 13:04:02 +0300398 const char *interface, uint32_t version, void *data)
399{
400 struct tablet *tablet = data;
401
402 if (!strcmp(interface, "tablet_shell")) {
403 tablet->tablet_shell =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400404 display_bind(display, name,
405 &tablet_shell_interface, 1);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300406 tablet_shell_add_listener(tablet->tablet_shell,
407 &tablet_shell_listener, tablet);
408 }
409}
410
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500411int main(int argc, char *argv[])
412{
Tiago Vignatti0a386112012-03-28 13:04:02 +0300413 struct tablet tablet = { 0 };
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500414 struct display *display;
Tiago Vignatti0a386112012-03-28 13:04:02 +0300415 struct output *output;
Kristian Høgsbergb1595602013-09-21 22:35:13 -0700416 struct weston_config *config;
417 struct weston_config_section *s;
418 char *icon, *path;
419 const char *name;
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500420
Kristian Høgsberg4172f662013-02-20 15:27:49 -0500421 display = display_create(&argc, argv);
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500422 if (display == NULL) {
423 fprintf(stderr, "failed to create display: %m\n");
424 return -1;
425 }
426
Tiago Vignatti0a386112012-03-28 13:04:02 +0300427 tablet.display = display;
428
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400429 display_set_user_data(tablet.display, &tablet);
430 display_set_global_handler(tablet.display, global_handler);
Tiago Vignatti0a386112012-03-28 13:04:02 +0300431
432 tablet.homescreen = homescreen_create(&tablet);
433 tablet_shell_set_homescreen(tablet.tablet_shell,
434 window_get_wl_surface(tablet.homescreen->window));
Tiago Vignattib67c91d2013-04-09 11:48:06 -0300435
436 wl_display_roundtrip (display_get_display(tablet.display));
437
Tiago Vignatti0a386112012-03-28 13:04:02 +0300438 wl_list_init(&tablet.homescreen->launcher_list);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500439
Kristian Høgsberg1abe0482013-09-21 23:02:31 -0700440 config = weston_config_parse("weston.ini");
Kristian Høgsbergb1595602013-09-21 22:35:13 -0700441 s = weston_config_get_section(config, "shell", NULL, NULL);
442 weston_config_section_get_string(s, "lockscreen-icon",
443 &key_lockscreen_icon, NULL);
444 weston_config_section_get_string(s, "lockscreen",
445 &key_lockscreen_background, NULL);
446 weston_config_section_get_string(s, "homescreen",
447 &key_homescreen_background, NULL);
448
449 s = NULL;
450 while (weston_config_next_section(config, &s, &name)) {
451 if (strcmp(name, "launcher") != 0)
452 continue;
453
454 weston_config_section_get_string(s, "icon", &icon, NULL);
455 weston_config_section_get_string(s, "path", &path, NULL);
456
Kristian Høgsbergd58e3952013-10-09 13:05:55 -0700457 if (icon != NULL && path != NULL)
458 tablet_shell_add_launcher(&tablet, icon, path);
459 else
Kristian Høgsbergb1595602013-09-21 22:35:13 -0700460 fprintf(stderr, "invalid launcher section\n");
Kristian Høgsbergb1595602013-09-21 22:35:13 -0700461
Kristian Høgsbergb1595602013-09-21 22:35:13 -0700462 free(icon);
463 free(path);
464 }
465
466 weston_config_destroy(config);
467
Tiago Vignatti0a386112012-03-28 13:04:02 +0300468 signal(SIGCHLD, sigchild_handler);
Kristian Høgsbergf033a7b2011-11-26 23:38:41 -0500469
Tiago Vignatti0a386112012-03-28 13:04:02 +0300470 output = display_get_output(tablet.display);
471 output_get_allocation(output, &tablet.allocation);
472 widget_schedule_resize(tablet.homescreen->widget,
473 tablet.allocation.width,
474 tablet.allocation.height);
Kristian Høgsberg6336e462011-11-26 17:36:23 -0500475 display_run(display);
476
477 return 0;
478}