8 #include <linux/input.h>
10 #include <libtwin/twin.h>
11 #include <libtwin/twin_fbdev.h>
12 #include <libtwin/twin_x11.h>
13 #include <libtwin/twin_linux_mouse.h>
14 #include <libtwin/twin_png.h>
16 #include "petitboot.h"
20 static twin_fbdev_t *pboot_fbdev;
21 static twin_x11_t *pboot_x11;
22 static twin_screen_t *pboot_screen;
24 #define PBOOT_LEFT_PANE_SIZE 200
25 #define PBOOT_LEFT_PANE_COLOR 0x80000000
26 #define PBOOT_LEFT_LINE_COLOR 0xff000000
28 #define PBOOT_LEFT_FOCUS_WIDTH 80
29 #define PBOOT_LEFT_FOCUS_HEIGHT 80
30 #define PBOOT_LEFT_FOCUS_XOFF 60
31 #define PBOOT_LEFT_FOCUS_YOFF 60
32 #define PBOOT_LEFT_FOCUS_XRAD (6 * TWIN_FIXED_ONE)
33 #define PBOOT_LEFT_FOCUS_YRAD (6 * TWIN_FIXED_ONE)
35 #define PBOOT_RIGHT_FOCUS_XOFF 20
36 #define PBOOT_RIGHT_FOCUS_YOFF 60
37 #define PBOOT_RIGHT_FOCUS_HEIGHT 80
38 #define PBOOT_RIGHT_FOCUS_XRAD (6 * TWIN_FIXED_ONE)
39 #define PBOOT_RIGHT_FOCUS_YRAD (6 * TWIN_FIXED_ONE)
41 #define PBOOT_LEFT_ICON_WIDTH 64
42 #define PBOOT_LEFT_ICON_HEIGHT 64
43 #define PBOOT_LEFT_ICON_XOFF 70
44 #define PBOOT_LEFT_ICON_YOFF 70
45 #define PBOOT_LEFT_ICON_STRIDE 100
47 #define PBOOT_RIGHT_OPTION_LMARGIN 30
48 #define PBOOT_RIGHT_OPTION_RMARGIN 30
49 #define PBOOT_RIGHT_OPTION_TMARGIN 70
50 #define PBOOT_RIGHT_OPTION_HEIGHT 64
51 #define PBOOT_RIGHT_OPTION_STRIDE 100
52 #define PBOOT_RIGHT_TITLE_TEXT_SIZE (30 * TWIN_FIXED_ONE)
53 #define PBOOT_RIGHT_SUBTITLE_TEXT_SIZE (18 * TWIN_FIXED_ONE)
54 #define PBOOT_RIGHT_TITLE_XOFFSET 80
55 #define PBOOT_RIGHT_TITLE_YOFFSET 30
56 #define PBOOT_RIGHT_SUBTITLE_XOFFSET 200
57 #define PBOOT_RIGHT_SUBTITLE_YOFFSET 50
58 #define PBOOT_RIGHT_BADGE_XOFFSET 2
59 #define PBOOT_RIGHT_BADGE_YOFFSET 0
62 #define PBOOT_RIGHT_TITLE_COLOR 0xff000000
63 #define PBOOT_RIGHT_SUBTITLE_COLOR 0xff400000
65 #define PBOOT_FOCUS_COLOR 0x10404040
68 typedef struct _pboot_option pboot_option_t;
69 typedef struct _pboot_device pboot_device_t;
86 pboot_option_t options[PBOOT_MAX_OPTION];
89 static twin_pixmap_t *pboot_cursor;
90 static int pboot_cursor_hx;
91 static int pboot_cursor_hy;
93 static pboot_device_t *pboot_devices[PBOOT_MAX_DEV];
94 static int pboot_dev_count;
95 static int pboot_dev_sel = -1;
96 static int pboot_focus_lpane = 1;
98 typedef struct _pboot_lpane {
99 twin_window_t *window;
100 twin_rect_t focus_box;
107 typedef struct _pboot_rpane {
108 twin_window_t *window;
109 twin_rect_t focus_box;
116 static pboot_lpane_t *pboot_lpane;
117 static pboot_rpane_t *pboot_rpane;
119 /* XXX move to twin */
120 static inline twin_bool_t twin_rect_intersect(twin_rect_t r1,
123 return !(r1.left > r2.right ||
124 r1.right < r2.left ||
125 r1.top > r2.bottom ||
129 static void pboot_draw_option_cache(pboot_device_t *dev, pboot_option_t *opt,
137 px = twin_pixmap_create(TWIN_ARGB32, opt->box.right - opt->box.left,
138 opt->box.bottom - opt->box.top);
142 /* Fill background */
143 twin_fill(px, 0x00000000, TWIN_SOURCE, 0, 0, px->width, px->height);
145 /* Allocate a path for drawing */
146 path = twin_path_create();
150 /* TEST - Bounding rectangle */
151 twin_path_rectangle(path, 0, 0,
152 twin_int_to_fixed(px->width),
153 twin_int_to_fixed(px->height));
154 twin_paint_path(px, PBOOT_RIGHT_TITLE_COLOR, path);
155 twin_path_empty(path);
156 twin_fill(px, 0x00000000, TWIN_SOURCE, 2, 2,
157 px->width - 3, px->height - 3);
161 twin_path_set_font_size(path, PBOOT_RIGHT_TITLE_TEXT_SIZE);
162 twin_path_set_font_style(path, TWIN_TEXT_UNHINTED);
163 tx = twin_int_to_fixed(PBOOT_RIGHT_TITLE_XOFFSET);
164 ty = twin_int_to_fixed(PBOOT_RIGHT_TITLE_YOFFSET);
165 twin_path_move (path, tx, ty);
166 twin_path_utf8 (path, opt->title);
167 twin_paint_path (px, PBOOT_RIGHT_TITLE_COLOR, path);
168 twin_path_empty (path);
171 twin_path_set_font_size(path, PBOOT_RIGHT_SUBTITLE_TEXT_SIZE);
172 twin_path_set_font_style(path, TWIN_TEXT_UNHINTED);
173 tx = twin_int_to_fixed(PBOOT_RIGHT_SUBTITLE_XOFFSET);
174 ty = twin_int_to_fixed(PBOOT_RIGHT_SUBTITLE_YOFFSET);
175 twin_path_move (path, tx, ty);
176 twin_path_utf8 (path, opt->subtitle);
177 twin_paint_path (px, PBOOT_RIGHT_SUBTITLE_COLOR, path);
178 twin_path_empty (path);
184 src.source_kind = TWIN_PIXMAP;
185 src.u.pixmap = opt->badge;
187 twin_composite(px, PBOOT_RIGHT_BADGE_XOFFSET,
188 PBOOT_RIGHT_BADGE_YOFFSET,
189 &src, 0, 0, NULL, 0, 0, TWIN_OVER,
190 opt->badge->width, opt->badge->height);
195 twin_path_destroy(path);
198 static void pboot_rpane_draw(twin_window_t *window)
200 twin_pixmap_t *px = window->pixmap;
201 pboot_rpane_t *rpane = window->client_data;
204 twin_fixed_t x, y, w, h;
207 /* Fill background */
208 twin_fill(px, 0x00000000, TWIN_SOURCE, 0, 0, px->width, px->height);
210 /* Nothing to draw, return */
211 if (pboot_dev_sel < 0)
214 /* Create a path for use later */
215 path = twin_path_create();
219 if (rpane->focus_curindex >= 0 &&
220 twin_rect_intersect(rpane->focus_box, px->clip)) {
221 x = twin_int_to_fixed(rpane->focus_box.left + 2);
222 y = twin_int_to_fixed(rpane->focus_box.top + 2);
223 w = twin_int_to_fixed(rpane->focus_box.right -
224 rpane->focus_box.left - 4);
225 h = twin_int_to_fixed(rpane->focus_box.bottom -
226 rpane->focus_box.top - 4);
227 twin_path_rounded_rectangle(path, x, y, w, h,
228 PBOOT_RIGHT_FOCUS_XRAD,
229 PBOOT_RIGHT_FOCUS_YRAD);
230 if (!pboot_focus_lpane)
231 twin_paint_path(px, PBOOT_FOCUS_COLOR, path);
233 twin_paint_stroke(px, PBOOT_FOCUS_COLOR, path,
237 /* Get device and iterate through options */
238 dev = pboot_devices[pboot_dev_sel];
239 for (i = 0; i < dev->option_count; i++) {
240 pboot_option_t *opt = &dev->options[i];
243 if (opt->title == NULL)
245 if (!twin_rect_intersect(opt->box, px->clip))
247 if (opt->cache == NULL)
248 pboot_draw_option_cache(dev, opt, i);
250 src.source_kind = TWIN_PIXMAP;
251 src.u.pixmap = opt->cache;
253 twin_composite(px, opt->box.left, opt->box.top,
254 &src, 0, 0, NULL, 0, 0, TWIN_OVER,
255 opt->box.right - opt->box.left,
256 opt->box.bottom - opt->box.top);
260 twin_path_destroy(path);
263 static twin_time_t pboot_rfocus_timeout (twin_time_t now, void *closure)
265 int dir = 1, dist, pos;
266 const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 2, 3, 4, 5 };
268 dist = abs(pboot_rpane->focus_target - pboot_rpane->focus_start);
269 dir = dist > 5 ? 5 : dist;
270 pos = pboot_rpane->focus_target - (int)pboot_rpane->focus_box.top;
278 twin_window_damage(pboot_rpane->window,
279 pboot_rpane->focus_box.left,
280 pboot_rpane->focus_box.top,
281 pboot_rpane->focus_box.right,
282 pboot_rpane->focus_box.bottom);
284 pboot_rpane->focus_box.top += dir;
285 pboot_rpane->focus_box.bottom += dir;
287 twin_window_damage(pboot_rpane->window,
288 pboot_rpane->focus_box.left,
289 pboot_rpane->focus_box.top,
290 pboot_rpane->focus_box.right,
291 pboot_rpane->focus_box.bottom);
293 twin_window_queue_paint(pboot_rpane->window);
295 return accel[(pos * 10) / dist];
298 static void pboot_set_rfocus(int index)
302 if (pboot_dev_sel < 0 || pboot_dev_sel >= pboot_dev_count)
304 dev = pboot_devices[pboot_dev_sel];
305 if (index < 0 || index >= dev->option_count)
308 pboot_rpane->focus_start = pboot_rpane->focus_box.top;
309 pboot_rpane->focus_target = PBOOT_RIGHT_FOCUS_YOFF +
310 PBOOT_RIGHT_OPTION_STRIDE * index;
311 pboot_rpane->focus_curindex = index;
313 twin_set_timeout(pboot_rfocus_timeout, 0, NULL);
316 static void pboot_select_rpane(void)
318 if (pboot_focus_lpane == 0)
320 pboot_focus_lpane = 0;
322 twin_screen_set_active(pboot_screen, pboot_rpane->window->pixmap);
324 twin_window_damage(pboot_lpane->window,
325 pboot_lpane->focus_box.left,
326 pboot_lpane->focus_box.top,
327 pboot_lpane->focus_box.right,
328 pboot_lpane->focus_box.bottom);
330 twin_window_damage(pboot_rpane->window,
331 pboot_rpane->focus_box.left,
332 pboot_rpane->focus_box.top,
333 pboot_rpane->focus_box.right,
334 pboot_rpane->focus_box.bottom);
336 twin_window_queue_paint(pboot_lpane->window);
337 twin_window_queue_paint(pboot_rpane->window);
342 static void pboot_select_lpane(void)
344 if (pboot_focus_lpane == 1)
346 pboot_focus_lpane = 1;
348 twin_screen_set_active(pboot_screen, pboot_lpane->window->pixmap);
350 twin_window_damage(pboot_lpane->window,
351 pboot_lpane->focus_box.left,
352 pboot_lpane->focus_box.top,
353 pboot_lpane->focus_box.right,
354 pboot_lpane->focus_box.bottom);
356 twin_window_damage(pboot_rpane->window,
357 pboot_rpane->focus_box.left,
358 pboot_rpane->focus_box.top,
359 pboot_rpane->focus_box.right,
360 pboot_rpane->focus_box.bottom);
362 twin_window_queue_paint(pboot_lpane->window);
363 twin_window_queue_paint(pboot_rpane->window);
366 static void pboot_rpane_mousetrack(twin_coord_t x, twin_coord_t y)
372 if (pboot_dev_sel < 0 || pboot_dev_sel >= pboot_dev_count)
374 dev = pboot_devices[pboot_dev_sel];
376 if (y < PBOOT_RIGHT_OPTION_TMARGIN)
378 candidate = (y - PBOOT_RIGHT_OPTION_TMARGIN) /
379 PBOOT_RIGHT_OPTION_STRIDE;
380 if (candidate >= dev->option_count) {
384 if (candidate == pboot_rpane->mouse_target)
386 opt = &dev->options[candidate];
387 if (x < opt->box.left || x > opt->box.right ||
388 y < opt->box.top || y > opt->box.bottom) {
393 /* Ok, so now, we know the mouse hit an icon that wasn't the same
394 * as the previous one, we trigger a focus change
396 pboot_set_rfocus(candidate);
399 pboot_rpane->mouse_target = candidate;
402 static twin_bool_t pboot_rpane_event (twin_window_t *window,
405 /* filter out all mouse events */
406 switch(event->kind) {
408 case TwinEventMotion:
410 pboot_select_rpane();
411 pboot_rpane_mousetrack(event->u.pointer.x, event->u.pointer.y);
413 case TwinEventButtonDown:
414 case TwinEventButtonUp:
416 case TwinEventKeyDown:
417 switch(event->u.key.key) {
419 pboot_set_rfocus(pboot_rpane->focus_curindex - 1);
422 pboot_set_rfocus(pboot_rpane->focus_curindex + 1);
425 pboot_select_lpane();
438 int pboot_add_option(int devindex, const char *title,
439 const char *subtitle, twin_pixmap_t *badge)
446 if (devindex < 0 || devindex >= pboot_dev_count)
448 dev = pboot_devices[devindex];
450 if (dev->option_count >= PBOOT_MAX_OPTION)
452 index = dev->option_count++;
453 opt = &dev->options[index];
455 opt->title = malloc(strlen(title) + 1);
456 strcpy(opt->title, title);
459 opt->subtitle = malloc(strlen(subtitle) + 1);
460 strcpy(opt->subtitle, subtitle);
462 opt->subtitle = NULL;
467 width = pboot_rpane->window->pixmap->width -
468 (PBOOT_RIGHT_OPTION_LMARGIN + PBOOT_RIGHT_OPTION_RMARGIN);
470 opt->box.left = PBOOT_RIGHT_OPTION_LMARGIN;
471 opt->box.right = opt->box.left + width;
472 opt->box.top = PBOOT_RIGHT_OPTION_TMARGIN +
473 index * PBOOT_RIGHT_OPTION_STRIDE;
474 opt->box.bottom = opt->box.top + PBOOT_RIGHT_OPTION_HEIGHT;
480 static void pboot_set_device_select(int sel)
482 LOG("%s: %d -> %d\n", __FUNCTION__, pboot_dev_sel, sel);
483 if (sel == pboot_dev_sel || sel >= pboot_dev_count)
486 pboot_rpane->focus_curindex = -1;
487 pboot_rpane->mouse_target = -1;
488 pboot_rpane->focus_box.top = -2*PBOOT_RIGHT_FOCUS_HEIGHT;
489 pboot_rpane->focus_box.bottom = pboot_rpane->focus_box.top +
490 PBOOT_RIGHT_FOCUS_HEIGHT;
491 twin_window_damage(pboot_rpane->window, 0, 0,
492 pboot_rpane->window->pixmap->width,
493 pboot_rpane->window->pixmap->height);
494 twin_window_queue_paint(pboot_rpane->window);
497 static twin_time_t pboot_lfocus_timeout (twin_time_t now, void *closure)
499 int dir = 1, dist, pos;
500 const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 2, 3, 4, 5 };
502 dist = abs(pboot_lpane->focus_target - pboot_lpane->focus_start);
503 pos = pboot_lpane->focus_target - (int)pboot_lpane->focus_box.top;
505 pboot_set_device_select(pboot_lpane->focus_curindex);
512 twin_window_damage(pboot_lpane->window,
513 pboot_lpane->focus_box.left,
514 pboot_lpane->focus_box.top,
515 pboot_lpane->focus_box.right,
516 pboot_lpane->focus_box.bottom);
518 pboot_lpane->focus_box.top += dir;
519 pboot_lpane->focus_box.bottom += dir;
521 twin_window_damage(pboot_lpane->window,
522 pboot_lpane->focus_box.left,
523 pboot_lpane->focus_box.top,
524 pboot_lpane->focus_box.right,
525 pboot_lpane->focus_box.bottom);
527 twin_window_queue_paint(pboot_lpane->window);
529 return accel[(pos * 10) / dist];
532 static void pboot_set_lfocus(int index)
534 if (index >= pboot_dev_count)
537 pboot_lpane->focus_start = pboot_lpane->focus_box.top;
540 pboot_lpane->focus_target = 0 - PBOOT_LEFT_FOCUS_HEIGHT;
542 pboot_lpane->focus_target = PBOOT_LEFT_FOCUS_YOFF +
543 PBOOT_LEFT_ICON_STRIDE * index;
545 pboot_lpane->focus_curindex = index;
547 twin_set_timeout(pboot_lfocus_timeout, 0, NULL);
550 static void pboot_lpane_mousetrack(twin_coord_t x, twin_coord_t y)
553 twin_coord_t icon_top;
555 if (x < PBOOT_LEFT_ICON_XOFF ||
556 x > (PBOOT_LEFT_ICON_XOFF + PBOOT_LEFT_ICON_WIDTH))
558 if (y < PBOOT_LEFT_ICON_YOFF)
560 candidate = (y - PBOOT_LEFT_ICON_YOFF) / PBOOT_LEFT_ICON_STRIDE;
561 if (candidate >= pboot_dev_count) {
565 if (candidate == pboot_lpane->mouse_target)
567 icon_top = PBOOT_LEFT_ICON_YOFF +
568 candidate * PBOOT_LEFT_ICON_STRIDE;
569 if (y > (icon_top + PBOOT_LEFT_ICON_HEIGHT)) {
574 /* Ok, so now, we know the mouse hit an icon that wasn't the same
575 * as the previous one, we trigger a focus change
577 pboot_set_lfocus(candidate);
580 pboot_lpane->mouse_target = candidate;
583 static twin_bool_t pboot_lpane_event (twin_window_t *window,
586 /* filter out all mouse events */
587 switch(event->kind) {
589 case TwinEventMotion:
591 pboot_select_lpane();
592 pboot_lpane_mousetrack(event->u.pointer.x, event->u.pointer.y);
594 case TwinEventButtonDown:
595 case TwinEventButtonUp:
597 case TwinEventKeyDown:
598 switch(event->u.key.key) {
600 if (pboot_lpane->focus_curindex > 0)
602 pboot_lpane->focus_curindex - 1);
605 pboot_set_lfocus(pboot_lpane->focus_curindex + 1);
608 pboot_select_rpane();
620 twin_bool_t pboot_event_filter(twin_screen_t *screen,
623 switch(event->kind) {
625 case TwinEventMotion:
627 case TwinEventButtonDown:
628 case TwinEventButtonUp:
629 if (pboot_cursor != NULL)
630 twin_screen_set_cursor(pboot_screen, pboot_cursor,
634 case TwinEventKeyDown:
636 twin_screen_set_cursor(pboot_screen, NULL, 0, 0);
644 static void pboot_lpane_draw(twin_window_t *window)
646 twin_pixmap_t *px = window->pixmap;
647 pboot_lpane_t *lpane = window->client_data;
649 twin_fixed_t x, y, w, h;
652 /* Fill background */
653 twin_fill(px, PBOOT_LEFT_PANE_COLOR, TWIN_SOURCE,
654 0, 0, px->width, px->height);
656 /* Create a path for use later */
657 path = twin_path_create();
660 /* Draw right line if needed */
661 if (px->clip.right > (PBOOT_LEFT_PANE_SIZE - 4)) {
662 x = twin_int_to_fixed(PBOOT_LEFT_PANE_SIZE - 4);
663 y = twin_int_to_fixed(px->height);
664 twin_path_rectangle(path, x, 0, 0x40000, y);
665 twin_paint_path(px, PBOOT_LEFT_LINE_COLOR, path);
666 twin_path_empty(path);
670 if (lpane->focus_curindex >= 0 &&
671 twin_rect_intersect(lpane->focus_box, px->clip)) {
672 x = twin_int_to_fixed(lpane->focus_box.left + 2);
673 y = twin_int_to_fixed(lpane->focus_box.top + 2);
674 w = twin_int_to_fixed(lpane->focus_box.right -
675 lpane->focus_box.left - 4);
676 h = twin_int_to_fixed(lpane->focus_box.bottom -
677 lpane->focus_box.top - 4);
678 twin_path_rounded_rectangle(path, x, y, w, h,
679 PBOOT_LEFT_FOCUS_XRAD,
680 PBOOT_LEFT_FOCUS_YRAD);
681 if (pboot_focus_lpane)
682 twin_paint_path(px, PBOOT_FOCUS_COLOR, path);
684 twin_paint_stroke(px, PBOOT_FOCUS_COLOR, path,
689 for (i = 0; i < pboot_dev_count; i++) {
690 pboot_device_t *dev = pboot_devices[i];
693 if (!twin_rect_intersect(dev->box, px->clip))
696 src.source_kind = TWIN_PIXMAP;
697 src.u.pixmap = dev->badge;
699 twin_composite(px, dev->box.left, dev->box.top,
700 &src, 0, 0, NULL, 0, 0, TWIN_OVER,
701 dev->box.right - dev->box.left,
702 dev->box.bottom - dev->box.top);
707 twin_path_destroy(path);
710 static void pboot_create_panels(void)
713 pboot_lpane = calloc(1, sizeof(pboot_lpane_t));
716 pboot_lpane->window = twin_window_create(pboot_screen, TWIN_ARGB32,
718 0, 0, PBOOT_LEFT_PANE_SIZE,
719 pboot_screen->height);
720 assert(pboot_lpane->window);
722 pboot_lpane->window->draw = pboot_lpane_draw;
723 pboot_lpane->window->event = pboot_lpane_event;
724 pboot_lpane->window->client_data = pboot_lpane;
725 pboot_lpane->focus_curindex = -1;
726 pboot_lpane->focus_box.left = PBOOT_LEFT_FOCUS_XOFF;
727 pboot_lpane->focus_box.top = -2*PBOOT_LEFT_FOCUS_HEIGHT;
728 pboot_lpane->focus_box.right = pboot_lpane->focus_box.left +
729 PBOOT_LEFT_FOCUS_WIDTH;
730 pboot_lpane->focus_box.bottom = pboot_lpane->focus_box.top +
731 PBOOT_LEFT_FOCUS_HEIGHT;
732 pboot_lpane->mouse_target = -1;
733 twin_window_show(pboot_lpane->window);
736 pboot_rpane = calloc(1, sizeof(pboot_rpane_t));
739 pboot_rpane->window = twin_window_create(pboot_screen, TWIN_ARGB32,
741 PBOOT_LEFT_PANE_SIZE, 0,
742 pboot_screen->width -
743 PBOOT_LEFT_PANE_SIZE,
744 pboot_screen->height);
745 assert(pboot_rpane->window);
747 pboot_rpane->window->draw = pboot_rpane_draw;
748 pboot_rpane->window->event = pboot_rpane_event;
749 pboot_rpane->window->client_data = pboot_rpane;
751 pboot_rpane->focus_curindex = -1;
752 pboot_rpane->focus_box.left = PBOOT_RIGHT_FOCUS_XOFF;
753 pboot_rpane->focus_box.top = -2*PBOOT_RIGHT_FOCUS_HEIGHT;
754 pboot_rpane->focus_box.right = pboot_rpane->window->pixmap->width -
755 2 * PBOOT_RIGHT_FOCUS_XOFF;
756 pboot_rpane->focus_box.bottom = pboot_rpane->focus_box.top +
757 PBOOT_RIGHT_FOCUS_HEIGHT;
758 pboot_rpane->mouse_target = -1;
759 twin_window_show(pboot_rpane->window);
762 int pboot_add_device(const char *dev_id, const char *name,
763 twin_pixmap_t *pixmap)
768 if (pboot_dev_count >= PBOOT_MAX_DEV)
771 index = pboot_dev_count++;
773 dev = malloc(sizeof(*dev));
774 memset(dev, 0, sizeof(*dev));
775 dev->id = malloc(strlen(dev_id) + 1);
776 strcpy(dev->id, dev_id);
778 dev->box.left = PBOOT_LEFT_ICON_XOFF;
779 dev->box.right = dev->box.left + PBOOT_LEFT_ICON_WIDTH;
780 dev->box.top = PBOOT_LEFT_ICON_YOFF +
781 PBOOT_LEFT_ICON_STRIDE * index;
782 dev->box.bottom = dev->box.top + PBOOT_LEFT_ICON_HEIGHT;
784 pboot_devices[index] = dev;
786 twin_window_damage(pboot_lpane->window,
787 dev->box.left, dev->box.top,
788 dev->box.right, dev->box.bottom);
789 twin_window_queue_paint(pboot_lpane->window);
794 int pboot_remove_device(const char *dev_id)
796 int i, new_dev_index;
797 pboot_device_t *dev = NULL;
799 /* find the matching device */
800 for (i = 0; i < pboot_dev_count; i++) {
801 if (!strcmp(pboot_devices[i]->id, dev_id)) {
802 dev = pboot_devices[i];
810 /* select the newly-focussed device */
811 if (i == pboot_dev_count - 1)
812 new_dev_index = i - 1;
814 new_dev_index = i + 1;
816 memmove(pboot_devices + i, pboot_devices + i + 1,
817 sizeof(*pboot_devices) * (pboot_dev_count + i - 1));
819 pboot_devices[--pboot_dev_count] = NULL;
821 pboot_set_device_select(new_dev_index);
822 twin_window_damage(pboot_lpane->window,
823 dev->box.left, dev->box.top,
824 dev->box.right, dev->box.bottom);
825 twin_window_queue_paint(pboot_lpane->window);
827 /* todo: free device & options */
832 static void exitfunc(void)
835 twin_fbdev_destroy(pboot_fbdev);
839 static void sigint(int sig)
845 int main(int argc, char **argv)
850 signal(SIGINT, sigint);
853 pboot_x11 = twin_x11_create(XOpenDisplay(0), 1024, 768);
854 if (pboot_x11 == NULL) {
855 perror("failed to create x11 screen !\n");
858 pboot_screen = pboot_x11->screen;
860 /* Create screen and mouse drivers */
861 pboot_fbdev = twin_fbdev_create(-1, SIGUSR1);
862 if (pboot_fbdev == NULL) {
863 perror("failed to create fbdev screen !\n");
866 pboot_screen = pboot_fbdev->screen;
867 twin_linux_mouse_create(NULL, pboot_screen);
870 if (pboot_fbdev != NULL) {
871 pboot_cursor = twin_load_X_cursor("artwork/cursor", 2,
874 if (pboot_cursor == NULL)
876 twin_get_default_cursor(&pboot_cursor_hx,
880 /* Set background pixmap */
881 LOG("loading background...");
882 pic = twin_png_to_pixmap("artwork/background.png", TWIN_ARGB32);
883 LOG("%s\n", pic ? "ok" : "failed");
885 twin_screen_set_background(pboot_screen, pic);
887 /* Init more stuffs */
888 pboot_create_panels();
889 twin_window_queue_paint(pboot_lpane->window);
890 twin_window_queue_paint(pboot_rpane->window);
892 if (!pboot_start_device_discovery()) {
893 LOG("Couldn't start device discovery!\n");
898 twin_screen_set_active(pboot_screen, pboot_lpane->window->pixmap);
899 pboot_screen->event_filter = pboot_event_filter;
903 twin_fbdev_activate(pboot_fbdev);