wlt: fix shl_hook API changes
[platform/upstream/kmscon.git] / src / wlt_main.c
1 /*
2  * wlt - Wayland Terminal
3  *
4  * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 /*
27  * Wayland Terminal main application
28  */
29
30 #include <errno.h>
31 #include <paths.h>
32 #include <signal.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/signalfd.h>
37 #include <wayland-client.h>
38 #include "conf.h"
39 #include "eloop.h"
40 #include "log.h"
41 #include "shl_dlist.h"
42 #include "shl_misc.h"
43 #include "text.h"
44 #include "wlt_main.h"
45 #include "wlt_terminal.h"
46 #include "wlt_theme.h"
47 #include "wlt_toolkit.h"
48
49 #define LOG_SUBSYSTEM "wlt"
50
51 struct wlt_app {
52         struct ev_eloop *eloop;
53         struct wlt_display *disp;
54         struct wlt_window *wnd;
55 };
56
57 static void sig_generic(struct ev_eloop *eloop, struct signalfd_siginfo *info,
58                         void *data)
59 {
60         struct wlt_app *app = data;
61
62         ev_eloop_exit(app->eloop);
63         log_info("terminating due to caught signal %d", info->ssi_signo);
64 }
65
66 static void window_close(struct wlt_window *wnd, void *data)
67 {
68         struct wlt_app *app = data;
69
70         log_info("closing window");
71         ev_eloop_exit(app->eloop);
72 }
73
74 static void terminal_close(struct wlt_terminal *term, unsigned int event,
75                            void *data)
76 {
77         struct wlt_app *app = data;
78
79         if (event == WLT_TERMINAL_HUP) {
80                 log_info("closing pty");
81                 ev_eloop_exit(app->eloop);
82         }
83 }
84
85 static int window_init(struct wlt_app *app)
86 {
87         int ret;
88         struct wlt_theme *theme;
89         struct wlt_terminal *term;
90
91         ret = wlt_display_create_window(app->disp, &app->wnd,
92                                         600, 400, app);
93         if (ret) {
94                 log_error("cannot create wayland window");
95                 return ret;
96         }
97         wlt_window_set_close_cb(app->wnd, window_close);
98
99         ret = wlt_theme_new(&theme, app->wnd);
100         if (ret) {
101                 log_error("cannot create theme");
102                 return ret;
103         }
104
105         ret = wlt_terminal_new(&term, app->wnd);
106         if (ret) {
107                 log_error("cannot create terminal");
108                 return ret;
109         }
110
111         ret = wlt_terminal_open(term, terminal_close, app);
112         if (ret) {
113                 log_error("cannot open terminal");
114                 return ret;
115         }
116
117         return 0;
118 }
119
120 static void display_event(struct wlt_display *disp, unsigned int event,
121                           void *data)
122 {
123         struct wlt_app *app = data;
124         int ret;
125
126         switch (event) {
127         case WLT_DISPLAY_READY:
128                 log_info("wayland display initialized");
129                 ret = window_init(app);
130                 if (ret)
131                         ev_eloop_exit(app->eloop);
132                 break;
133         case WLT_DISPLAY_HUP:
134                 log_info("wayland display connection lost");
135                 ev_eloop_exit(app->eloop);
136                 break;
137         }
138 }
139
140 static void destroy_app(struct wlt_app *app)
141 {
142         wlt_window_unref(app->wnd);
143         wlt_display_unregister_cb(app->disp, display_event, app);
144         wlt_display_unref(app->disp);
145         ev_eloop_unregister_signal_cb(app->eloop, SIGINT, sig_generic, app);
146         ev_eloop_unregister_signal_cb(app->eloop, SIGTERM, sig_generic, app);
147         ev_eloop_unref(app->eloop);
148 }
149
150 static int setup_app(struct wlt_app *app)
151 {
152         int ret;
153
154         ret = ev_eloop_new(&app->eloop, log_llog);
155         if (ret)
156                 goto err_app;
157
158         ret = ev_eloop_register_signal_cb(app->eloop, SIGTERM,
159                                                 sig_generic, app);
160         if (ret)
161                 goto err_app;
162
163         ret = ev_eloop_register_signal_cb(app->eloop, SIGINT,
164                                                 sig_generic, app);
165         if (ret)
166                 goto err_app;
167
168         ret = wlt_display_new(&app->disp, app->eloop);
169         if (ret)
170                 goto err_app;
171
172         ret = wlt_display_register_cb(app->disp, display_event, app);
173         if (ret)
174                 goto err_app;
175
176         return 0;
177
178 err_app:
179         destroy_app(app);
180         return ret;
181 }
182
183 struct wlt_conf_t wlt_conf;
184 #define WLT_CONF_FROM_FIELD(_mem, _name) \
185         shl_offsetof((_mem), struct wlt_conf_t, _name)
186
187 static void print_help()
188 {
189         /*
190          * Usage/Help information
191          * This should be scaled to a maximum of 80 characters per line:
192          *
193          * 80 char line:
194          *       |   10   |    20   |    30   |    40   |    50   |    60   |    70   |    80   |
195          *      "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
196          * 80 char line starting with tab:
197          *       |10|    20   |    30   |    40   |    50   |    60   |    70   |    80   |
198          *      "\t901234567890123456789012345678901234567890123456789012345678901234567890\n"
199          */
200         fprintf(stderr,
201                 "Usage:\n"
202                 "\t%1$s [options]\n"
203                 "\t%1$s -h [options]\n"
204                 "\t%1$s -l [options] -- /bin/sh [sh-arguments]\n"
205                 "\n"
206                 "You can prefix boolean options with \"no-\" to negate it. If an argument is\n"
207                 "given multiple times, only the last argument matters if not otherwise stated.\n"
208                 "\n"
209                 "General Options:\n"
210                 "\t-h, --help                  [off]   Print this help and exit\n"
211                 "\t-v, --verbose               [off]   Print verbose messages\n"
212                 "\t    --debug                 [off]   Enable debug mode\n"
213                 "\t    --silent                [off]   Suppress notices and warnings\n"
214                 "\n"
215                 "Terminal Options:\n"
216                 "\t-l, --login                 [/bin/sh]\n"
217                 "\t                              Start the given login process instead\n"
218                 "\t                              of the default process; all arguments\n"
219                 "\t                              following '--' will be be parsed as\n"
220                 "\t                              argv to this process. No more options\n"
221                 "\t                              after '--' will be parsed so use it at\n"
222                 "\t                              the end of the argument string\n"
223                 "\t-t, --term <TERM>           [xterm-256color]\n"
224                 "\t                              Value of the TERM environment variable\n"
225                 "\t                              for the child process\n"
226                 "\t    --palette <name>        [default]\n"
227                 "\t                              Select the used color palette\n"
228                 "\t    --sb-size <num>         [1000]\n"
229                 "\t                              Size of the scrollback-buffer in lines\n"
230                 "\n"
231                 "Keyboard Shortcuts and Grabs:\n"
232                 "\t    --grab-scroll-up <grab>   [<Shift>Up]\n"
233                 "\t                                Shortcut to scroll up\n"
234                 "\t    --grab-scroll-down <grab> [<Shift>Down]\n"
235                 "\t                                Shortcut to scroll down\n"
236                 "\t    --grab-page-up <grab>     [<Shift>Prior]\n"
237                 "\t                                Shortcut to scroll page up\n"
238                 "\t    --grab-page-down <grab>   [<Shift>Next]\n"
239                 "\t                                Shortcut to scroll page down\n"
240                 "\t    --grab-fullscreen <grab>  [F11]\n"
241                 "\t                                Shortcut to toggle fullscreen mode\n"
242                 "\t    --grab-zoom-in <grab>     [<Ctrl>plus]\n"
243                 "\t                                Shortcut to increase font size\n"
244                 "\t    --grab-zoom-out <grab>    [<Ctrl>minus]\n"
245                 "\t                                Shortcut to decrease font size\n"
246                 "\t    --grab-copy <grab>        [<Logo>c]\n"
247                 "\t                                Copy selected text\n"
248                 "\t    --grab-paste <grab>       [<Logo>v]\n"
249                 "\t                                Paste selection buffer\n"
250                 "\n"
251                 "Font Options:\n"
252                 "\t    --font-engine <engine>  [pango]\n"
253                 "\t                              Font engine\n"
254                 "\t    --font-size <points>    [15]\n"
255                 "\t                              Font size in points\n"
256                 "\t    --font-name <name>      [monospace]\n"
257                 "\t                              Font name\n"
258                 "\t    --font-dpi <dpi>        [96]\n"
259                 "\t                              Force DPI value for all fonts\n"
260                 "\n"
261                 "Input Options:\n"
262                 "\t    --xkb-repeat-delay <msecs> [250]\n"
263                 "\t                                 Initial delay for key-repeat in ms\n"
264                 "\t    --xkb-repeat-rate <msecs>  [50]\n"
265                 "\t                                 Delay between two key-repeats in ms\n",
266                 "wlterm");
267         /*
268          * 80 char line:
269          *       |   10   |    20   |    30   |    40   |    50   |    60   |    70   |    80   |
270          *      "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
271          * 80 char line starting with tab:
272          *       |10|    20   |    30   |    40   |    50   |    60   |    70   |    80   |
273          *      "\t901234567890123456789012345678901234567890123456789012345678901234567890\n"
274          */
275 }
276
277 static int aftercheck_debug(struct conf_option *opt, int argc, char **argv,
278                             int idx)
279 {
280         struct wlt_conf_t *conf = WLT_CONF_FROM_FIELD(opt->mem, debug);
281
282         /* --debug implies --verbose */
283         if (conf->debug)
284                 conf->verbose = true;
285
286         return 0;
287 }
288
289 static int aftercheck_help(struct conf_option *opt, int argc, char **argv,
290                            int idx)
291 {
292         struct wlt_conf_t *conf = WLT_CONF_FROM_FIELD(opt->mem, help);
293
294         /* exit after printing --help information */
295         if (conf->help) {
296                 print_help();
297                 conf->exit = true;
298         }
299
300         return 0;
301 }
302
303 static char *def_argv[] = { NULL, "-i", NULL };
304
305 static int aftercheck_login(struct conf_option *opt, int argc, char **argv,
306                             int idx)
307 {
308         struct wlt_conf_t *conf = WLT_CONF_FROM_FIELD(opt->mem, login);
309         int ret;
310
311         if (!argv)
312                 return 0;
313
314         /* parse "--login [...] -- args" arguments */
315         if (argv && conf->login) {
316                 if (idx >= argc) {
317                         fprintf(stderr, "Arguments for --login missing\n");
318                         return -EFAULT;
319                 }
320
321                 conf->argv = &argv[idx];
322                 ret = argc - idx;
323         } else if (!conf->argv) {
324                 def_argv[0] = getenv("SHELL") ? : _PATH_BSHELL;
325                 conf->argv = def_argv;
326                 ret = 0;
327         } else {
328                 ret = 0;
329         }
330
331         return ret;
332 }
333
334 static int copy_login(struct conf_option *opt, const struct conf_option *src)
335 {
336         struct wlt_conf_t *conf = WLT_CONF_FROM_FIELD(opt->mem, login);
337         struct wlt_conf_t *s = WLT_CONF_FROM_FIELD(src->mem, login);
338         int ret;
339         char **t;
340
341         ret = shl_dup_array(&t, s->argv);
342         if (ret)
343                 return ret;
344
345         free(conf->argv);
346         conf->argv = t;
347
348         return 0;
349 }
350
351 static struct conf_grab def_grab_scroll_up =
352                 CONF_SINGLE_GRAB(SHL_SHIFT_MASK, XKB_KEY_Up);
353
354 static struct conf_grab def_grab_scroll_down =
355                 CONF_SINGLE_GRAB(SHL_SHIFT_MASK, XKB_KEY_Down);
356
357 static struct conf_grab def_grab_page_up =
358                 CONF_SINGLE_GRAB(SHL_SHIFT_MASK, XKB_KEY_Prior);
359
360 static struct conf_grab def_grab_page_down =
361                 CONF_SINGLE_GRAB(SHL_SHIFT_MASK, XKB_KEY_Next);
362
363 static struct conf_grab def_grab_fullscreen =
364                 CONF_SINGLE_GRAB(0, XKB_KEY_F11);
365
366 static struct conf_grab def_grab_zoom_in =
367                 CONF_SINGLE_GRAB(SHL_CONTROL_MASK, XKB_KEY_plus);
368
369 static struct conf_grab def_grab_zoom_out =
370                 CONF_SINGLE_GRAB(SHL_CONTROL_MASK, XKB_KEY_minus);
371
372 static struct conf_grab def_grab_copy =
373                 CONF_SINGLE_GRAB(SHL_LOGO_MASK, XKB_KEY_c);
374
375 static struct conf_grab def_grab_paste =
376                 CONF_SINGLE_GRAB(SHL_LOGO_MASK, XKB_KEY_v);
377
378 struct conf_option options[] = {
379         CONF_OPTION_BOOL_FULL('h', "help", aftercheck_help, NULL, NULL, &wlt_conf.help, false),
380         CONF_OPTION_BOOL('v', "verbose", &wlt_conf.verbose, false),
381         CONF_OPTION_BOOL_FULL(0, "debug", aftercheck_debug, NULL, NULL, &wlt_conf.debug, false),
382         CONF_OPTION_BOOL(0, "silent", &wlt_conf.silent, false),
383
384         CONF_OPTION_BOOL_FULL('l', "login", aftercheck_login, copy_login, NULL, &wlt_conf.login, false),
385         CONF_OPTION_STRING('t', "term", &wlt_conf.term, "xterm-256color"),
386         CONF_OPTION_STRING(0, "palette", &wlt_conf.palette, NULL),
387         CONF_OPTION_UINT(0, "sb-size", &wlt_conf.sb_size, 1000),
388
389         CONF_OPTION_GRAB(0, "grab-scroll-up", &wlt_conf.grab_scroll_up, &def_grab_scroll_up),
390         CONF_OPTION_GRAB(0, "grab-scroll-down", &wlt_conf.grab_scroll_down, &def_grab_scroll_down),
391         CONF_OPTION_GRAB(0, "grab-page-up", &wlt_conf.grab_page_up, &def_grab_page_up),
392         CONF_OPTION_GRAB(0, "grab-page-down", &wlt_conf.grab_page_down, &def_grab_page_down),
393         CONF_OPTION_GRAB(0, "grab-fullscreen", &wlt_conf.grab_fullscreen, &def_grab_fullscreen),
394         CONF_OPTION_GRAB(0, "grab-zoom-in", &wlt_conf.grab_zoom_in, &def_grab_zoom_in),
395         CONF_OPTION_GRAB(0, "grab-zoom-out", &wlt_conf.grab_zoom_out, &def_grab_zoom_out),
396         CONF_OPTION_GRAB(0, "grab-copy", &wlt_conf.grab_copy, &def_grab_copy),
397         CONF_OPTION_GRAB(0, "grab-paste", &wlt_conf.grab_paste, &def_grab_paste),
398
399         CONF_OPTION_STRING(0, "font-engine", &wlt_conf.font_engine, "pango"),
400         CONF_OPTION_UINT(0, "font-size", &wlt_conf.font_size, 12),
401         CONF_OPTION_STRING(0, "font-name", &wlt_conf.font_name, "monospace"),
402         CONF_OPTION_UINT(0, "font-dpi", &wlt_conf.font_ppi, 96),
403
404         CONF_OPTION_UINT(0, "xkb-repeat-delay", &wlt_conf.xkb_repeat_delay, 250),
405         CONF_OPTION_UINT(0, "xkb-repeat-rate", &wlt_conf.xkb_repeat_rate, 50),
406 };
407
408 int main(int argc, char **argv)
409 {
410         int ret;
411         struct wlt_app app;
412         struct conf_ctx *conf;
413
414         ret = conf_ctx_new(&conf, options, sizeof(options) / sizeof(*options),
415                            &wlt_conf);
416         if (ret)
417                 goto err_out;
418
419         ret = conf_ctx_parse_argv(conf, argc, argv);
420         if (ret)
421                 goto err_conf;
422
423         if (wlt_conf.exit) {
424                 conf_ctx_free(conf);
425                 return EXIT_SUCCESS;
426         }
427
428         if (!wlt_conf.debug && !wlt_conf.verbose && wlt_conf.silent)
429                 log_set_config(&LOG_CONFIG_WARNING(0, 0, 0, 0));
430         else
431                 log_set_config(&LOG_CONFIG_INFO(wlt_conf.debug,
432                                                 wlt_conf.verbose));
433
434         log_print_init("wlterm");
435
436         kmscon_font_register(&kmscon_font_8x16_ops);
437
438         memset(&app, 0, sizeof(app));
439         ret = setup_app(&app);
440         if (ret)
441                 goto err_unload;
442
443         ev_eloop_run(app.eloop, -1);
444
445         destroy_app(&app);
446         kmscon_font_unregister(kmscon_font_8x16_ops.name);
447         conf_ctx_free(conf);
448         log_info("exiting");
449
450         return EXIT_SUCCESS;
451
452 err_unload:
453         kmscon_font_unregister(kmscon_font_8x16_ops.name);
454 err_conf:
455         conf_ctx_free(conf);
456 err_out:
457         log_err("cannot initialize wlterm, errno %d: %s", ret, strerror(-ret));
458         return -ret;
459 }