source: mainline/uspace/app/launcher/launcher.c@ b1397ab

topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b1397ab was b1f0a14, checked in by Jiri Svoboda <jiri@…>, 3 years ago

Pass input device ID via display specification argument

This allows launcher to start applications in the correct seat,
meaning the correct seat's focus will be changed to the newly
created window.

  • Property mode set to 100644
File size: 11.1 KB
Line 
1/*
2 * Copyright (c) 2023 Jiri Svoboda
3 * Copyright (c) 2012 Petr Koupy
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup launcher
31 * @{
32 */
33/** @file Launcher
34 */
35
36#include <errno.h>
37#include <gfx/coord.h>
38#include <gfximage/tga.h>
39#include <stdbool.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <str.h>
43#include <str_error.h>
44#include <task.h>
45#include <ui/fixed.h>
46#include <ui/image.h>
47#include <ui/label.h>
48#include <ui/pbutton.h>
49#include <ui/resource.h>
50#include <ui/ui.h>
51#include <ui/window.h>
52
53#include "images.h"
54#include "launcher.h"
55
56#define NAME "launcher"
57
58static const char *display_spec = UI_DISPLAY_DEFAULT;
59
60static void wnd_close(ui_window_t *, void *);
61static void wnd_pos(ui_window_t *, void *, pos_event_t *);
62
63static ui_window_cb_t window_cb = {
64 .close = wnd_close,
65 .pos = wnd_pos
66};
67
68static void pb_clicked(ui_pbutton_t *, void *);
69
70static ui_pbutton_cb_t pbutton_cb = {
71 .clicked = pb_clicked
72};
73
74static int app_launchl(launcher_t *, const char *, ...);
75
76/** Window close button was clicked.
77 *
78 * @param window Window
79 * @param arg Argument (launcher)
80 */
81static void wnd_close(ui_window_t *window, void *arg)
82{
83 launcher_t *launcher = (launcher_t *) arg;
84
85 ui_quit(launcher->ui);
86}
87
88/** Window received position event.
89 *
90 * @param window Window
91 * @param arg Argument (launcher)
92 * @param event Position event
93 */
94static void wnd_pos(ui_window_t *window, void *arg, pos_event_t *event)
95{
96 launcher_t *launcher = (launcher_t *) arg;
97
98 /* Remember ID of device that sent the last event */
99 launcher->ev_pos_id = event->pos_id;
100
101 ui_window_def_pos(window, event);
102}
103
104/** Push button was clicked.
105 *
106 * @param pbutton Push button
107 * @param arg Argument (launcher)
108 */
109static void pb_clicked(ui_pbutton_t *pbutton, void *arg)
110{
111 launcher_t *launcher = (launcher_t *) arg;
112
113 if (pbutton == launcher->pb1) {
114 app_launchl(launcher, "/app/terminal", "-c", "/app/nav", NULL);
115 } else if (pbutton == launcher->pb2) {
116 app_launchl(launcher, "/app/terminal", "-c", "/app/edit", NULL);
117 } else if (pbutton == launcher->pb3) {
118 app_launchl(launcher, "/app/terminal", NULL);
119 } else if (pbutton == launcher->pb4) {
120 app_launchl(launcher, "/app/calculator", NULL);
121 } else if (pbutton == launcher->pb5) {
122 app_launchl(launcher, "/app/uidemo", NULL);
123 } else if (pbutton == launcher->pb6) {
124 app_launchl(launcher, "/app/gfxdemo", "ui", NULL);
125 }
126}
127
128static int app_launchl(launcher_t *launcher, const char *app, ...)
129{
130 errno_t rc;
131 task_id_t id;
132 task_wait_t wait;
133 va_list ap;
134 const char *arg;
135 const char **argv;
136 const char **argp;
137 char *dspec;
138 int cnt = 0;
139 int i;
140 int rv;
141
142 va_start(ap, app);
143 do {
144 arg = va_arg(ap, const char *);
145 cnt++;
146 } while (arg != NULL);
147 va_end(ap);
148
149 argv = calloc(cnt + 4, sizeof(const char *));
150 if (argv == NULL)
151 return -1;
152
153 task_exit_t texit;
154 int retval;
155
156 argp = argv;
157 *argp++ = app;
158
159 rv = asprintf(&dspec, "%s?idev=%zu", display_spec,
160 (size_t)launcher->ev_pos_id);
161 if (rv < 0) {
162 printf("Out of memory.\n");
163 return -1;
164 }
165
166 /* TODO Might be omitted if default display AND only one seat */
167 *argp++ = "-d";
168 *argp++ = dspec;
169
170 va_start(ap, app);
171 do {
172 arg = va_arg(ap, const char *);
173 *argp++ = arg;
174 } while (arg != NULL);
175 va_end(ap);
176
177 *argp++ = NULL;
178
179 printf("%s: Spawning %s", NAME, app);
180 for (i = 0; argv[i] != NULL; i++) {
181 printf(" %s", argv[i]);
182 }
183 printf("\n");
184
185 rc = task_spawnv(&id, &wait, app, argv);
186 if (rc != EOK) {
187 printf("%s: Error spawning %s (%s)\n", NAME, app, str_error(rc));
188 return -1;
189 }
190
191 rc = task_wait(&wait, &texit, &retval);
192 if ((rc != EOK) || (texit != TASK_EXIT_NORMAL)) {
193 printf("%s: Error retrieving retval from %s (%s)\n", NAME,
194 app, str_error(rc));
195 return -1;
196 }
197
198 return retval;
199}
200
201static void print_syntax(void)
202{
203 printf("Syntax: %s [-d <display-spec>]\n", NAME);
204}
205
206int main(int argc, char *argv[])
207{
208 int i;
209 launcher_t launcher;
210 ui_t *ui = NULL;
211 ui_wnd_params_t params;
212 ui_window_t *window = NULL;
213 ui_resource_t *ui_res;
214 gfx_bitmap_params_t logo_params;
215 gfx_bitmap_t *logo_bmp;
216 gfx_context_t *gc;
217 gfx_rect_t logo_rect;
218 gfx_rect_t rect;
219 gfx_coord2_t off;
220 const char *dspec = UI_DISPLAY_DEFAULT;
221 char *qmark;
222 errno_t rc;
223
224 i = 1;
225 while (i < argc) {
226 if (str_cmp(argv[i], "-d") == 0) {
227 ++i;
228 if (i >= argc) {
229 printf("Argument missing.\n");
230 print_syntax();
231 return 1;
232 }
233
234 dspec = argv[i++];
235 } else {
236 printf("Invalid option '%s'.\n", argv[i]);
237 print_syntax();
238 return 1;
239 }
240 }
241
242 display_spec = str_dup(dspec);
243 if (display_spec == NULL) {
244 printf("Out of memory.\n");
245 return 1;
246 }
247
248 /* Remove additional arguments */
249 qmark = str_chr(display_spec, '?');
250 if (qmark != NULL)
251 *qmark = '\0';
252
253 rc = ui_create(dspec, &ui);
254 if (rc != EOK) {
255 printf("Error creating UI on display %s.\n", display_spec);
256 return rc;
257 }
258
259 ui_wnd_params_init(&params);
260 params.caption = "Launcher";
261 params.placement = ui_wnd_place_top_right;
262 params.rect.p0.x = 0;
263 params.rect.p0.y = 0;
264 params.rect.p1.x = 210;
265 params.rect.p1.y = 345;
266
267 memset((void *) &launcher, 0, sizeof(launcher));
268 launcher.ui = ui;
269
270 rc = ui_window_create(ui, &params, &window);
271 if (rc != EOK) {
272 printf("Error creating window.\n");
273 return rc;
274 }
275
276 ui_window_set_cb(window, &window_cb, (void *) &launcher);
277 launcher.window = window;
278
279 ui_res = ui_window_get_res(window);
280 gc = ui_window_get_gc(window);
281
282 rc = decode_tga(gc, (void *) helenos_tga, helenos_tga_size,
283 &logo_bmp, &logo_rect);
284 if (rc != EOK) {
285 printf("Unable to decode logo.\n");
286 return 1;
287 }
288
289 gfx_bitmap_params_init(&logo_params);
290 logo_params.rect = logo_rect;
291
292 rc = ui_fixed_create(&launcher.fixed);
293 if (rc != EOK) {
294 printf("Error creating fixed layout.\n");
295 return rc;
296 }
297
298 rc = ui_image_create(ui_res, logo_bmp, &logo_rect, &launcher.image);
299 if (rc != EOK) {
300 printf("Error creating label.\n");
301 return rc;
302 }
303
304 off.x = 6;
305 off.y = 32;
306 gfx_rect_translate(&off, &logo_rect, &rect);
307
308 /* Adjust for frame width (2 x 1 pixel) */
309 rect.p1.x += 2;
310 rect.p1.y += 2;
311 ui_image_set_rect(launcher.image, &rect);
312 ui_image_set_flags(launcher.image, ui_imgf_frame);
313
314 rc = ui_fixed_add(launcher.fixed, ui_image_ctl(launcher.image));
315 if (rc != EOK) {
316 printf("Error adding control to layout.\n");
317 return rc;
318 }
319
320 rc = ui_label_create(ui_res, "Launch application", &launcher.label);
321 if (rc != EOK) {
322 printf("Error creating label.\n");
323 return rc;
324 }
325
326 rect.p0.x = 60;
327 rect.p0.y = 107;
328 rect.p1.x = 160;
329 rect.p1.y = 120;
330 ui_label_set_rect(launcher.label, &rect);
331 ui_label_set_halign(launcher.label, gfx_halign_center);
332
333 rc = ui_fixed_add(launcher.fixed, ui_label_ctl(launcher.label));
334 if (rc != EOK) {
335 printf("Error adding control to layout.\n");
336 return rc;
337 }
338
339 /* Navigator */
340
341 rc = ui_pbutton_create(ui_res, "Navigator", &launcher.pb1);
342 if (rc != EOK) {
343 printf("Error creating button.\n");
344 return rc;
345 }
346
347 ui_pbutton_set_cb(launcher.pb1, &pbutton_cb, (void *) &launcher);
348
349 rect.p0.x = 15;
350 rect.p0.y = 130;
351 rect.p1.x = 190;
352 rect.p1.y = rect.p0.y + 28;
353 ui_pbutton_set_rect(launcher.pb1, &rect);
354
355 rc = ui_fixed_add(launcher.fixed, ui_pbutton_ctl(launcher.pb1));
356 if (rc != EOK) {
357 printf("Error adding control to layout.\n");
358 return rc;
359 }
360
361 /* Text Editor */
362
363 rc = ui_pbutton_create(ui_res, "Text Editor", &launcher.pb2);
364 if (rc != EOK) {
365 printf("Error creating button.\n");
366 return rc;
367 }
368
369 ui_pbutton_set_cb(launcher.pb2, &pbutton_cb, (void *) &launcher);
370
371 rect.p0.x = 15;
372 rect.p0.y = 130 + 35;
373 rect.p1.x = 190;
374 rect.p1.y = rect.p0.y + 28;
375 ui_pbutton_set_rect(launcher.pb2, &rect);
376
377 rc = ui_fixed_add(launcher.fixed, ui_pbutton_ctl(launcher.pb2));
378 if (rc != EOK) {
379 printf("Error adding control to layout.\n");
380 return rc;
381 }
382
383 /* Terminal */
384
385 rc = ui_pbutton_create(ui_res, "Terminal", &launcher.pb3);
386 if (rc != EOK) {
387 printf("Error creating button.\n");
388 return rc;
389 }
390
391 ui_pbutton_set_cb(launcher.pb3, &pbutton_cb, (void *) &launcher);
392
393 rect.p0.x = 15;
394 rect.p0.y = 130 + 2 * 35;
395 rect.p1.x = 190;
396 rect.p1.y = rect.p0.y + 28;
397 ui_pbutton_set_rect(launcher.pb3, &rect);
398
399 rc = ui_fixed_add(launcher.fixed, ui_pbutton_ctl(launcher.pb3));
400 if (rc != EOK) {
401 printf("Error adding control to layout.\n");
402 return rc;
403 }
404
405 /* Calculator */
406
407 rc = ui_pbutton_create(ui_res, "Calculator", &launcher.pb4);
408 if (rc != EOK) {
409 printf("Error creating button.\n");
410 return rc;
411 }
412
413 ui_pbutton_set_cb(launcher.pb4, &pbutton_cb, (void *) &launcher);
414
415 rect.p0.x = 15;
416 rect.p0.y = 130 + 3 * 35;
417 rect.p1.x = 190;
418 rect.p1.y = rect.p0.y + 28;
419 ui_pbutton_set_rect(launcher.pb4, &rect);
420
421 rc = ui_fixed_add(launcher.fixed, ui_pbutton_ctl(launcher.pb4));
422 if (rc != EOK) {
423 printf("Error adding control to layout.\n");
424 return rc;
425 }
426
427 /* UI Demo */
428
429 rc = ui_pbutton_create(ui_res, "UI Demo", &launcher.pb5);
430 if (rc != EOK) {
431 printf("Error creating button.\n");
432 return rc;
433 }
434
435 ui_pbutton_set_cb(launcher.pb5, &pbutton_cb, (void *) &launcher);
436
437 rect.p0.x = 15;
438 rect.p0.y = 130 + 4 * 35;
439 rect.p1.x = 190;
440 rect.p1.y = rect.p0.y + 28;
441 ui_pbutton_set_rect(launcher.pb5, &rect);
442
443 rc = ui_fixed_add(launcher.fixed, ui_pbutton_ctl(launcher.pb5));
444 if (rc != EOK) {
445 printf("Error adding control to layout.\n");
446 return rc;
447 }
448
449 /* GFX Demo */
450
451 rc = ui_pbutton_create(ui_res, "GFX Demo", &launcher.pb6);
452 if (rc != EOK) {
453 printf("Error creating button.\n");
454 return rc;
455 }
456
457 ui_pbutton_set_cb(launcher.pb6, &pbutton_cb, (void *) &launcher);
458
459 rect.p0.x = 15;
460 rect.p0.y = 130 + 5 * 35;
461 rect.p1.x = 190;
462 rect.p1.y = rect.p0.y + 28;
463 ui_pbutton_set_rect(launcher.pb6, &rect);
464
465 rc = ui_fixed_add(launcher.fixed, ui_pbutton_ctl(launcher.pb6));
466 if (rc != EOK) {
467 printf("Error adding control to layout.\n");
468 return rc;
469 }
470
471 ui_window_add(window, ui_fixed_ctl(launcher.fixed));
472
473 rc = ui_window_paint(window);
474 if (rc != EOK) {
475 printf("Error painting window.\n");
476 return rc;
477 }
478
479 ui_run(ui);
480
481 ui_window_destroy(window);
482 ui_destroy(ui);
483
484 return 0;
485}
486
487/** @}
488 */
Note: See TracBrowser for help on using the repository browser.