Subversion Repositories Kolibri OS

Rev

Rev 4364 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2008,2010 Vincent Sanders <vince@simtec.co.uk>
  3.  *
  4.  * Framebuffer windowing toolkit core.
  5.  *
  6.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  7.  *
  8.  * NetSurf is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; version 2 of the License.
  11.  *
  12.  * NetSurf is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19.  */
  20.  
  21. #include <sys/types.h>
  22. #include <assert.h>
  23. #include <stdint.h>
  24. #include <string.h>
  25. #include <stdbool.h>
  26. #include <stdarg.h>
  27.  
  28. #include <libnsfb.h>
  29. #include <libnsfb_plot.h>
  30. #include <libnsfb_plot_util.h>
  31. #include <libnsfb_event.h>
  32. #include <libnsfb_cursor.h>
  33.  
  34. #include "utils/utils.h"
  35. #include "utils/log.h"
  36. #include "css/css.h"
  37. #include "desktop/browser.h"
  38. #include "desktop/plotters.h"
  39.  
  40. #include "framebuffer/gui.h"
  41. #include "framebuffer/fbtk.h"
  42. #include "framebuffer/image_data.h"
  43.  
  44. #include "widget.h"
  45.  
  46. #ifdef DBG
  47. #undef DBG
  48. #endif
  49. //#define DBG(s) __menuet__debug_out(s) /* For the debug messages in BOARD */
  50. #define DBG(s) LOG((s))            /* So that we see debug in Netsurf's LOG files */
  51.  
  52.  
  53. #ifdef FBTK_LOGGING
  54.  
  55. /* tree dump debug, also example of depth first tree walk */
  56. static void
  57. dump_tk_tree(fbtk_widget_t *widget)
  58. {
  59.         widget = fbtk_get_root_widget(widget);
  60.         int indent = 0;
  61.  
  62.         while (widget != NULL) {
  63.                 /* LOG(("%*s%p", indent, "", widget)); */
  64.                 if (widget->first_child != NULL) {
  65.                         widget = widget->first_child;
  66.                         indent += 6;
  67.                 } else if (widget->next != NULL) {
  68.                         widget = widget->next;
  69.                 } else {
  70.                         while ((widget->parent != NULL) &&
  71.                                (widget->parent->next == NULL)) {
  72.                                 widget = widget->parent;
  73.                                 indent -= 6;
  74.                         }
  75.                         if (widget->parent != NULL) {
  76.                                 indent -= 6;
  77.                                 widget = widget->parent->next;
  78.                         } else {
  79.                                 widget = NULL;
  80.                         }
  81.                 }
  82.         }
  83. }
  84.  
  85. #endif
  86.  
  87. /* exported function documented in fbtk.h */
  88. void
  89. fbtk_request_redraw(fbtk_widget_t *widget)
  90. {
  91.         fbtk_widget_t *cwidget;
  92.         fbtk_widget_t *pwidget;
  93.  
  94.         assert(widget != NULL);
  95.  
  96.         /* if widget not mapped do not try to redraw it */
  97.         pwidget = widget;
  98.         while (pwidget != NULL) {
  99.                 if (pwidget->mapped == false)
  100.                         return;
  101.                 pwidget = pwidget->parent;
  102.         }
  103.  
  104.         widget->redraw.needed = true;
  105.         widget->redraw.x = 0;
  106.         widget->redraw.y = 0;
  107.         widget->redraw.width = widget->width;
  108.         widget->redraw.height = widget->height;
  109.  
  110.         /* LOG(("redrawing %p %d,%d %d,%d", */
  111.         /*      widget, */
  112.         /*      widget->redraw.x, */
  113.         /*      widget->redraw.y, */
  114.         /*      widget->redraw.width, */
  115.         /*      widget->redraw.height)); */
  116.  
  117.         cwidget = widget->last_child;
  118.         while (cwidget != NULL) {
  119.                 fbtk_request_redraw(cwidget);
  120.                 cwidget = cwidget->prev;
  121.         }
  122.  
  123.         while (widget->parent != NULL) {
  124.                 widget = widget->parent;
  125.                 widget->redraw.child = true;
  126.         }
  127. }
  128.  
  129.  
  130.  
  131. /* exported function documented in fbtk.h */
  132. int
  133. fbtk_set_mapping(fbtk_widget_t *widget, bool map)
  134. {
  135.         /* LOG(("setting mapping on %p to %d", widget, map)); */
  136.         widget->mapped = map;
  137.         if (map) {
  138.                 fbtk_request_redraw(widget);
  139.         } else {
  140.                 fbtk_request_redraw(widget->parent);
  141.         }
  142.         return 0;
  143. }
  144.  
  145. /** swap the widget given with the next sibling.
  146.  *
  147.  * Swap a sibling widget with the next deepest in the hierachy
  148.  */
  149. static void
  150. swap_siblings(fbtk_widget_t *lw)
  151. {
  152.         fbtk_widget_t *rw; /* the widget to swap lw with */
  153.         fbtk_widget_t *before;
  154.         fbtk_widget_t *after;
  155.  
  156.         rw = lw->next;
  157.         /* LOG(("Swapping %p with %p", lw, rw)); */
  158.         before = lw->prev;
  159.         after = rw->next;
  160.  
  161.         if (before == NULL) {
  162.                 /* left widget is currently the first child */
  163.                 lw->parent->first_child = rw;
  164.         } else {
  165.                 before->next = rw;
  166.         }
  167.         rw->prev = before;
  168.         rw->next = lw;
  169.  
  170.         if (after == NULL) {
  171.                 /* right widget is currently the last child */
  172.                 rw->parent->last_child = lw;
  173.         } else {
  174.                 after->prev = lw;
  175.         }
  176.         lw->next = after;
  177.         lw->prev = rw;
  178. }
  179.  
  180.  
  181.  
  182. /* exported function documented in fbtk.h */
  183. int
  184. fbtk_set_zorder(fbtk_widget_t *widget, int z)
  185. {
  186.         while (z != 0) {
  187.                 if (z < 0) {
  188.                         if (widget->prev == NULL)
  189.                                 break; /* cannot go any shallower */
  190.  
  191.                         /* swap with previous entry */
  192.                         swap_siblings(widget->prev);
  193.  
  194.                         z++;
  195.                 } else {
  196.                         if (widget->next == NULL)
  197.                                 break; /* cannot go any deeper */
  198.  
  199.                         /* swap with subsequent entry */
  200.                         swap_siblings(widget);
  201.  
  202.                         z--;
  203.                 }
  204.         }
  205.  
  206.         return z;
  207. }
  208.  
  209.  
  210. /* exported function documented in fbtk.h */
  211. bool
  212. fbtk_set_pos_and_size(fbtk_widget_t *widget,
  213.                       int x, int y,
  214.                       int width, int height)
  215. {
  216.         if ((widget->x != x) ||
  217.             (widget->y != y) ||
  218.             (widget->width != width) ||
  219.             (widget->height != height)) {
  220.                 widget->x = x;
  221.                 widget->y = y;
  222.                 widget->width = width;
  223.                 widget->height = height;
  224.                 /* @todo This should limit the redrawn area to the sum
  225.                  * of the old and new widget dimensions, not redraw the lot.
  226.                  */
  227.                 fbtk_request_redraw(widget->parent);
  228.                 return true;
  229.         }
  230.         return false;
  231. }
  232.  
  233.  
  234. /* exported function docuemnted in fbtk.h */
  235. void
  236. fbtk_set_caret(fbtk_widget_t *widget, bool set,
  237.                 int x, int y, int height,
  238.                 void (*remove_caret)(fbtk_widget_t *widget))
  239. {
  240.         fbtk_widget_t *root;
  241.  
  242.         assert(widget != NULL);
  243.         root = fbtk_get_root_widget(widget);
  244.  
  245.         if (root->u.root.caret.owner != NULL &&
  246.                         root->u.root.caret.remove_cb != NULL)
  247.                 root->u.root.caret.remove_cb(widget);
  248.  
  249.         if (set) {
  250.                 assert(remove_caret != NULL);
  251.  
  252.                 root->u.root.caret.owner = widget;
  253.                 root->u.root.caret.x = x;
  254.                 root->u.root.caret.y = y;
  255.                 root->u.root.caret.height = height;
  256.                 root->u.root.caret.remove_cb = remove_caret;
  257.  
  258.         } else {
  259.                 root->u.root.caret.owner = NULL;
  260.                 root->u.root.caret.remove_cb = NULL;
  261.         }
  262. }
  263.  
  264. /* exported function documented in fbtk.h */
  265. int
  266. fbtk_destroy_widget(fbtk_widget_t *widget)
  267. {
  268.         fbtk_widget_t *parent;
  269.         int ret = 0;
  270.  
  271.         ret = fbtk_post_callback(widget, FBTK_CBT_DESTROY);
  272.  
  273.         while (widget->first_child != NULL) {
  274.                 fbtk_destroy_widget(widget->first_child);
  275.         }
  276.  
  277.         parent = widget->parent;
  278.         if (parent != NULL) {
  279.  
  280.                 /* unlink from siblings */
  281.                 if (widget->prev != NULL) {
  282.                         widget->prev->next = widget->next;
  283.                 } else {
  284.                         /* must be the first widget, unlink from parent */
  285.                         parent->first_child = widget->next;
  286.                 }
  287.                 if (widget->next != NULL) {
  288.                         widget->next->prev = widget->prev;
  289.                 } else {
  290.                         /* must be the last widget, unlink from parent */
  291.                         parent->last_child = widget->prev;
  292.                 }
  293.  
  294.                 free(widget);
  295.         }
  296.  
  297.         return ret;
  298. }
  299.  
  300. /* region coverage flags. */
  301. enum {
  302.         POINT_LEFTOF_REGION = 1,
  303.         POINT_RIGHTOF_REGION = 2,
  304.         POINT_ABOVE_REGION = 4,
  305.         POINT_BELOW_REGION = 8,
  306. };
  307.  
  308. /* Computes where a point lies in respect to an area. */
  309. #define REGION(x,y,cx1,cx2,cy1,cy2)                     \
  310.         (( (y) > (cy2) ? POINT_BELOW_REGION : 0) |      \
  311.          ( (y) < (cy1) ? POINT_ABOVE_REGION : 0) |      \
  312.          ( (x) > (cx2) ? POINT_RIGHTOF_REGION : 0) |    \
  313.          ( (x) < (cx1) ? POINT_LEFTOF_REGION : 0) )
  314.  
  315. /* swap two integers */
  316. #define SWAP(a, b) do { int t; t=(a); (a)=(b); (b)=t;  } while(0)
  317.  
  318. /* exported function documented in fbtk.h */
  319. bool
  320. fbtk_clip_rect(const bbox_t *  clip, bbox_t *  box)
  321. {
  322.         uint8_t region1;
  323.         uint8_t region2;
  324.  
  325.         /* ensure co-ordinates are in ascending order */
  326.         if (box->x1 < box->x0)
  327.                 SWAP(box->x0, box->x1);
  328.         if (box->y1 < box->y0)
  329.                 SWAP(box->y0, box->y1);
  330.  
  331.         region1 = REGION(box->x0, box->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1);
  332.         region2 = REGION(box->x1, box->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1);
  333.  
  334.         /* area lies entirely outside the clipping rectangle */
  335.         if ((region1 | region2) && (region1 & region2))
  336.                 return false;
  337.  
  338.         if (box->x0 < clip->x0)
  339.                 box->x0 = clip->x0;
  340.         if (box->x0 > clip->x1)
  341.                 box->x0 = clip->x1;
  342.  
  343.         if (box->x1 < clip->x0)
  344.                 box->x1 = clip->x0;
  345.         if (box->x1 > clip->x1)
  346.                 box->x1 = clip->x1;
  347.  
  348.         if (box->y0 < clip->y0)
  349.                 box->y0 = clip->y0;
  350.         if (box->y0 > clip->y1)
  351.                 box->y0 = clip->y1;
  352.  
  353.         if (box->y1 < clip->y0)
  354.                 box->y1 = clip->y0;
  355.         if (box->y1 > clip->y1)
  356.                 box->y1 = clip->y1;
  357.  
  358.         return true;
  359. }
  360.  
  361. /* exported function documented in fbtk.h */
  362. bool
  363. fbtk_clip_to_widget(fbtk_widget_t *widget, bbox_t *  box)
  364. {
  365.         bbox_t wbox;
  366.         wbox.x0 = 0;
  367.         wbox.y0 = 0;
  368.         wbox.x1 = widget->width;
  369.         wbox.y1 = widget->height;
  370.         return fbtk_clip_rect(&wbox, box);
  371. }
  372.  
  373.  
  374.  
  375. /* internally exported function documented in widget.h */
  376. int
  377. fbtk_set_ptr(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  378. {
  379.         fbtk_widget_t *root = fbtk_get_root_widget(widget);
  380.         struct fbtk_bitmap *bm = cbi->context;
  381.  
  382.         nsfb_cursor_set(root->u.root.fb,
  383.                         (nsfb_colour_t *)bm->pixdata,
  384.                         bm->width,
  385.                         bm->height,
  386.                         bm->width,
  387.                         bm->hot_x,
  388.                         bm->hot_y);
  389.  
  390.         return 0;
  391. }
  392.  
  393.  
  394.  
  395. /* internally exported function documented in widget.h */
  396. fbtk_widget_t *
  397. fbtk_get_root_widget(fbtk_widget_t *widget)
  398. {
  399.         while (widget->parent != NULL)
  400.                 widget = widget->parent;
  401.  
  402.         /* check root widget was found */
  403.         if (widget->type != FB_WIDGET_TYPE_ROOT) {
  404.                 /* LOG(("Widget with null parent that is not the root widget!")); */
  405.                 return NULL;
  406.         }
  407.  
  408.         return widget;
  409. }
  410.  
  411.  
  412. /* exported function documented in fbtk.h */
  413. int
  414. fbtk_get_absx(fbtk_widget_t *widget)
  415. {
  416.         int x = widget->x;
  417.  
  418.         while (widget->parent != NULL) {
  419.                 widget = widget->parent;
  420.                 x += widget->x;
  421.         }
  422.  
  423.         return x;
  424. }
  425.  
  426. /* exported function documented in fbtk.h */
  427. int
  428. fbtk_get_absy(fbtk_widget_t *widget)
  429. {
  430.         int y = widget->y;
  431.  
  432.         while (widget->parent != NULL) {
  433.                 widget = widget->parent;
  434.                 y += widget->y;
  435.         }
  436.  
  437.         return y;
  438. }
  439.  
  440. /* exported function documented in fbtk.h */
  441. int
  442. fbtk_get_height(fbtk_widget_t *widget)
  443. {
  444.         return widget->height;
  445. }
  446.  
  447. /* exported function documented in fbtk.h */
  448. int
  449. fbtk_get_width(fbtk_widget_t *widget)
  450. {
  451.         return widget->width;
  452. }
  453.  
  454. /* exported function documented in fbtk.h */
  455. bool
  456. fbtk_get_bbox(fbtk_widget_t *widget, nsfb_bbox_t *bbox)
  457. {
  458.         bbox->x0 = widget->x;
  459.         bbox->y0 = widget->y;
  460.         bbox->x1 = widget->x + widget->width;
  461.         bbox->y1 = widget->y + widget->height;
  462.  
  463.         widget = widget->parent;
  464.         while (widget != NULL) {
  465.                 bbox->x0 += widget->x;
  466.                 bbox->y0 += widget->y;
  467.                 bbox->x1 += widget->x;
  468.                 bbox->y1 += widget->y;
  469.                 widget = widget->parent;
  470.         }
  471.  
  472.         return true;
  473. }
  474.  
  475. bool
  476. fbtk_get_caret(fbtk_widget_t *widget, int *x, int *y, int *height)
  477. {
  478.         fbtk_widget_t *root = fbtk_get_root_widget(widget);
  479.  
  480.         if (root->u.root.caret.owner == widget) {
  481.                 *x = root->u.root.caret.x;
  482.                 *y = root->u.root.caret.y;
  483.                 *height = root->u.root.caret.height;
  484.  
  485.                 return true;
  486.  
  487.         } else {
  488.                 *x = 0;
  489.                 *y = 0;
  490.                 *height = 0;
  491.  
  492.                 return false;
  493.         }
  494. }
  495.  
  496. /* exported function documented in fbtk.h */
  497. fbtk_widget_t *
  498. fbtk_get_widget_at(fbtk_widget_t *nwid, int x, int y)
  499. {
  500.         fbtk_widget_t *widget = NULL; /* found widget */
  501.  
  502.         /* require the root widget to start */
  503.         nwid = fbtk_get_root_widget(nwid);
  504.  
  505.         while (nwid != NULL) {
  506.                 if ((nwid->mapped) &&
  507.                     (x >= nwid->x) &&
  508.                     (y >= nwid->y) &&
  509.                     (x < (nwid->x + nwid->width)) &&
  510.                     (y < (nwid->y + nwid->height))) {
  511.                         widget = nwid;
  512.                         x -= nwid->x;
  513.                         y -= nwid->y;
  514.                         nwid = nwid->first_child;
  515.                 } else {
  516.                         nwid = nwid->next;
  517.                 }
  518.         }
  519.  
  520.         return widget;
  521. }
  522.  
  523.  
  524.  
  525.  
  526. /* internally exported function documented in widget.h */
  527. fbtk_widget_t *
  528. fbtk_widget_new(fbtk_widget_t *parent,
  529.                 enum fbtk_widgettype_e type,
  530.                 int x,
  531.                 int y,
  532.                 int width,
  533.                 int height)
  534. {
  535.         /* LOG(("New widget...")); */
  536.  
  537.         fbtk_widget_t *neww; /* new widget */
  538.  
  539.         if (parent == NULL)
  540.         {/* LOG(("parent null...")); */
  541.                 return NULL;}
  542.  
  543.         /* LOG(("calloc...")); */
  544.         neww = calloc(1, sizeof(fbtk_widget_t));
  545.         if (neww == NULL)
  546.                 return NULL;
  547.  
  548.         /* LOG(("super!...")); */
  549.         /* LOG(("creating %p %d,%d %d,%d", neww, x, y, width, height)); */
  550.  
  551.         /* make new window fit inside parent */
  552.         if (width == 0) {
  553.                 width = parent->width - x;
  554.         } else if (width < 0) {
  555.                 width = parent->width + width - x;
  556.         }
  557.         if ((width + x) > parent->width) {
  558.                 width = parent->width - x;
  559.         }
  560.  
  561.         if (height == 0) {
  562.                 height = parent->height - y;
  563.         } else if (height < 0) {
  564.                 height = parent->height + height - y;
  565.         }
  566.         if ((height + y) > parent->height) {
  567.                 height = parent->height - y;
  568.         }
  569.  
  570.  
  571.         /* LOG(("using %p %d,%d %d,%d", neww, x, y, width, height)); */
  572.         /* set values */
  573.         neww->type = type;
  574.         neww->x = x;
  575.         neww->y = y;
  576.         neww->width = width;
  577.         neww->height = height;
  578.  
  579.         /* insert into widget heiarchy */
  580.  
  581.         /* LOG(("into hierarchy...")); */
  582.         neww->parent = parent;
  583.  
  584.         if (parent->first_child == NULL) {
  585.                 /* no child widgets yet */
  586.                 /* LOG(("no childs yet...")); */
  587.                 parent->last_child = neww;
  588.         } else {
  589.                 /* add new widget to front of sibling chain */
  590.                 neww->next = parent->first_child;
  591.                 neww->next->prev = neww;
  592.                 /* LOG(("n front of sibling...")); */
  593.         }
  594.         parent->first_child = neww;
  595.  
  596.  
  597.         /* LOG(("Widget OK...")); */
  598.         return neww;
  599. }
  600.  
  601. /* exported function documented in fbtk.h */
  602. bool
  603. fbtk_get_redraw_pending(fbtk_widget_t *widget)
  604. {
  605.         fbtk_widget_t *root;
  606.  
  607.         /* ensure we have the root widget */
  608.         root = fbtk_get_root_widget(widget);
  609.  
  610.         return root->redraw.needed | root->redraw.child;
  611. }
  612.  
  613. /** Perform a depth-first tree-walk, calling the redraw callback of the widgets in turn.
  614.  *
  615.  * This function makes no decisions of its own and simply walks the
  616.  * widget tree depth first calling widgets redraw callbacks if flagged
  617.  * to do so.
  618.  * The tree search is optimised with a flag to indicate wether the
  619.  * children of a node should be considered.
  620.  */
  621.  #include <menuet/os.h>
  622.  
  623. static int
  624. do_redraw(nsfb_t *nsfb, fbtk_widget_t *widget)
  625. {
  626.         nsfb_bbox_t plot_ctx;
  627.         fbtk_widget_t *cwidget; /* child widget */
  628.  
  629.  
  630.         /* LOG(("DO REDRAW")); */
  631.         //DBG("\n***********\nDO REDRAW\n********\n");
  632.         /* check if the widget requires redrawing */
  633.         if (widget->redraw.needed == true) {
  634.                 plot_ctx.x0 = fbtk_get_absx(widget) + widget->redraw.x;
  635.                 plot_ctx.y0 = fbtk_get_absy(widget) + widget->redraw.y;
  636.                 plot_ctx.x1 = plot_ctx.x0 + widget->redraw.width;
  637.                 plot_ctx.y1 = plot_ctx.y0 + widget->redraw.height;
  638.  
  639.                 /* LOG(("clipping %p %d,%d %d,%d", */
  640.                 /*      widget, plot_ctx.x0, plot_ctx.y0, */
  641.                 /*      plot_ctx.x1, plot_ctx.y1)); */
  642.                 if (nsfb_plot_set_clip(nsfb, &plot_ctx) == true) {
  643.                        
  644.         /* LOG(("POST CALLBACK")); */
  645.         //DBG("\n***********\nPOST CALLBACK\n********\n");
  646.                        
  647.                         fbtk_post_callback(widget, FBTK_CBT_REDRAW);
  648.                 }
  649.                 widget->redraw.needed = false;
  650.         }
  651.  
  652.        
  653.         /* LOG(("DO CHILD")); */
  654.         //DBG("\n***********\nDO CHILD\n********\n");
  655.  
  656.         /* walk the widgets children if child flag is set */
  657.         if (widget->redraw.child) {
  658.                 /* LOG(("DO CHILD 2")); */
  659.         //DBG("\n***********\nDO CHILD 2\n********\n");
  660.                 cwidget = widget->last_child;
  661.                 while (cwidget != NULL) {
  662.                                 /* LOG(("DO CHILD 3 ZZZ")); */
  663.         //DBG("\n***********\nDO CHILD 3 ZZZ\n********\n");
  664.                         do_redraw(nsfb, cwidget);
  665.                         cwidget = cwidget->prev;
  666.                 }
  667.                         /* LOG(("DO CHILD 4")); */
  668.         //DBG("\n***********\nDO CHILD 4\n********\n");
  669.                 widget->redraw.child = false;
  670.         }
  671.  
  672.  
  673.         /* LOG(("SUP")); */
  674.         //DBG("\n***********\nFIN REDRAW\n********\n");
  675.  
  676.         return 1;
  677. }
  678.  
  679. /* exported function documented in fbtk.h */
  680. int
  681. fbtk_redraw(fbtk_widget_t *widget)
  682. {
  683.         fbtk_widget_t *root;
  684.  
  685.         /* ensure we have the root widget */
  686.         root = fbtk_get_root_widget(widget);
  687.  
  688.         return do_redraw(root->u.root.fb, root);
  689. }
  690.  
  691. /* exported function documented in fbtk.h */
  692. fbtk_callback
  693. fbtk_get_handler(fbtk_widget_t *widget, fbtk_callback_type cbt)
  694. {
  695.         if ((cbt <= FBTK_CBT_START) || (cbt >= FBTK_CBT_END)) {
  696.                 /* type out of range, no way to report error so return NULL */
  697.                 return NULL;
  698.         }
  699.  
  700.         return widget->callback[cbt];
  701. }
  702.  
  703. /* exported function documented in fbtk.h */
  704. fbtk_callback
  705. fbtk_set_handler(fbtk_widget_t *widget,
  706.                  fbtk_callback_type cbt,
  707.                  fbtk_callback cb,
  708.                  void *context)
  709. {
  710.         fbtk_callback prevcb;
  711.  
  712.         if ((cbt <= FBTK_CBT_START) || (cbt >= FBTK_CBT_END)) {
  713.                 /* type out of range, no way to report error so return NULL */
  714.                 return NULL;
  715.         }
  716.  
  717.         prevcb = widget->callback[cbt];
  718.  
  719.         widget->callback[cbt] = cb;
  720.         widget->callback_context[cbt] = context;
  721.  
  722.         return prevcb;
  723. }
  724.  
  725. /* exported function docuemnted in fbtk.h */
  726. int
  727. fbtk_post_callback(fbtk_widget_t *widget, fbtk_callback_type cbt, ...)
  728. {
  729.        
  730.         /* LOG(("DO POST CALLBACK")); */
  731.         //DBG("\n***********\nDO POST CALLBACK\n********\n");
  732.        
  733.         fbtk_callback_info cbi;
  734.         int ret = 0;
  735.         va_list ap;
  736.  
  737.         if (widget == NULL)
  738.                 return -1;
  739.         /* if the widget is not mapped do not attempt to post any
  740.          * events to it
  741.          */
  742.         if (widget->mapped == false)
  743.                 return ret;
  744.  
  745.         /* LOG(("DO POST CALLBACK 2")); */
  746.         //DBG("\n***********\nDO POST CALLBACK 2\n********\n");
  747.  
  748.         if (widget->callback[cbt] != NULL) {
  749.                 cbi.type = cbt;
  750.                 cbi.context = widget->callback_context[cbt];
  751.  
  752.         /* LOG(("DO POST CALLBACK 3 - VA")); */
  753.         //DBG("\n***********\nDO POST CALLBACK 3 - VA\n********\n");
  754.        
  755.                 va_start(ap, cbt);
  756.  
  757.                 switch (cbt) {
  758.                 case FBTK_CBT_SCROLLX:
  759.                         //DBG("\n***********\n scroll x - VA\n********\n");
  760.                         cbi.x = va_arg(ap,int);
  761.                         break;
  762.  
  763.                 case FBTK_CBT_SCROLLY:
  764.                         //DBG("\n***********\n scroll y - VA\n********\n");
  765.                         cbi.y = va_arg(ap,int);
  766.                         break;
  767.  
  768.                 case FBTK_CBT_CLICK:
  769.                         //DBG("\n***********\n click - VA\n********\n");
  770.                         cbi.event = va_arg(ap, void *);
  771.                         cbi.x = va_arg(ap, int);
  772.                         cbi.y = va_arg(ap, int);
  773.                         break;
  774.  
  775.                 case FBTK_CBT_INPUT:
  776.                         //DBG("\n***********\n input - VA\n********\n");
  777.                         cbi.event = va_arg(ap, void *);
  778.                         break;
  779.  
  780.                 case FBTK_CBT_POINTERMOVE:
  781.                         //DBG("\n***********\n mouse move - VA\n********\n");
  782.                         cbi.x = va_arg(ap, int);
  783.                         cbi.y = va_arg(ap, int);
  784.                         break;
  785.  
  786.                 case FBTK_CBT_REDRAW:
  787.                 //DBG("\n***********\n red - VA\n********\n");
  788.                         break;
  789.  
  790.                 case FBTK_CBT_USER:
  791.                 //DBG("\n***********\n user - VA\n********\n");
  792.                         break;
  793.  
  794.                 case FBTK_CBT_STRIP_FOCUS:
  795.                 //DBG("\n***********\n focus - VA\n********\n");
  796.                         break;
  797.  
  798.                 default:
  799.                 //DBG("\n***********\n wtf - VA\n********\n");
  800.                         break;
  801.                 }
  802.                
  803.                 /* LOG(("DO POST CALLBACK free")); */
  804.         //DBG("\n***********\nDO POST CALLBACK free\n********\n");
  805.                 va_end(ap);
  806.  
  807.                
  808.                 /* LOG(("DO CALLBACK YEAH")); */
  809.         //DBG("\n***********\nWTF IS THIS\n********\n");
  810.         char zupa[64];
  811.        
  812.         sprintf (zupa, "ADDRESS of callback is %x \n",(widget->callback[cbt]));
  813.         //DBG(zupa);
  814.         /* LOG(("ADDRESS of callback is %x \n",(widget->callback[cbt]))); */
  815.        
  816.                 ret = (widget->callback[cbt])(widget, &cbi);
  817.                         /* LOG(("DO CALLBACK YEAH 2")); */
  818.         //DBG("\n***********\nWTF IS THIS!!!12121\n********\n");
  819.         }
  820.  
  821. /* LOG(("DO POST CALLBACK OK")); */
  822.         //DBG("\n***********\nDO POST CALLBACK OK\n********\n");
  823.         return ret;
  824. }
  825.  
  826. /* exported function docuemnted in fbtk.h */
  827. void
  828. fbtk_set_focus(fbtk_widget_t *widget)
  829. {
  830.         fbtk_widget_t *root;
  831.  
  832.         /* ensure we have the root widget */
  833.         root = fbtk_get_root_widget(widget);
  834.  
  835.         if (root->u.root.input != NULL &&
  836.                         root->u.root.input != widget) {
  837.                 /* inform previous holder of focus that it's being stripped
  838.                  * of focus */
  839.                 fbtk_post_callback(root->u.root.input, FBTK_CBT_STRIP_FOCUS);
  840.         }
  841.  
  842.         root->u.root.input = widget;
  843. }
  844.  
  845.  
  846.  
  847. /* exported function docuemnted in fbtk.h */
  848. nsfb_t *
  849. fbtk_get_nsfb(fbtk_widget_t *widget)
  850. {
  851.         fbtk_widget_t *root;
  852.  
  853.         /* ensure we have the root widget */
  854.         root = fbtk_get_root_widget(widget);
  855.  
  856.         return root->u.root.fb;
  857. }
  858.  
  859. /* exported function docuemnted in fbtk.h */
  860. fbtk_widget_t *
  861. fbtk_init(nsfb_t *fb)
  862. {
  863.         fbtk_widget_t *root;
  864.  
  865.         /* create and configure root widget */
  866.         root = calloc(1, sizeof(fbtk_widget_t));
  867.         if (root == NULL)
  868.                 return NULL;
  869.  
  870.         root->type = FB_WIDGET_TYPE_ROOT;
  871.         root->u.root.fb = fb;
  872.         root->u.root.caret.owner = NULL;
  873.  
  874.         nsfb_get_geometry(fb, &root->width, &root->height, NULL);
  875.  
  876.         root->mapped = true;
  877.  
  878.         return root;
  879. }
  880.  
  881. /*
  882.  * Local Variables:
  883.  * c-basic-offset:8
  884.  * End:
  885.  */
  886.