mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-23 20:46:50 +03:00
c105738fa3
This changes the LOG macro to be varadic removing the need for all callsites to have double bracketing and allows for future improvement on how we use the logging macros. The callsites were changed with coccinelle and the changes checked by hand. Compile tested for several frontends but not all. A formatting annotation has also been added which allows the compiler to check the parameters and types passed to the logging.
830 lines
17 KiB
C
830 lines
17 KiB
C
/*
|
|
* Copyright 2008,2010 Vincent Sanders <vince@simtec.co.uk>
|
|
*
|
|
* Framebuffer windowing toolkit core.
|
|
*
|
|
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
|
*
|
|
* NetSurf is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* NetSurf is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <stdarg.h>
|
|
|
|
#include <libnsfb.h>
|
|
#include <libnsfb_plot.h>
|
|
#include <libnsfb_plot_util.h>
|
|
#include <libnsfb_event.h>
|
|
#include <libnsfb_cursor.h>
|
|
|
|
#include "utils/utils.h"
|
|
#include "utils/log.h"
|
|
#include "desktop/browser.h"
|
|
#include "desktop/plotters.h"
|
|
|
|
#include "framebuffer/gui.h"
|
|
#include "framebuffer/fbtk.h"
|
|
#include "framebuffer/image_data.h"
|
|
|
|
#include "widget.h"
|
|
|
|
#ifdef FBTK_LOGGING
|
|
|
|
/* tree dump debug, also example of depth first tree walk */
|
|
static void
|
|
dump_tk_tree(fbtk_widget_t *widget)
|
|
{
|
|
widget = fbtk_get_root_widget(widget);
|
|
int indent = 0;
|
|
|
|
while (widget != NULL) {
|
|
LOG("%*s%p", indent, "", widget);
|
|
if (widget->first_child != NULL) {
|
|
widget = widget->first_child;
|
|
indent += 6;
|
|
} else if (widget->next != NULL) {
|
|
widget = widget->next;
|
|
} else {
|
|
while ((widget->parent != NULL) &&
|
|
(widget->parent->next == NULL)) {
|
|
widget = widget->parent;
|
|
indent -= 6;
|
|
}
|
|
if (widget->parent != NULL) {
|
|
indent -= 6;
|
|
widget = widget->parent->next;
|
|
} else {
|
|
widget = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/* exported function documented in fbtk.h */
|
|
void
|
|
fbtk_request_redraw(fbtk_widget_t *widget)
|
|
{
|
|
fbtk_widget_t *cwidget;
|
|
fbtk_widget_t *pwidget;
|
|
|
|
assert(widget != NULL);
|
|
|
|
/* if widget not mapped do not try to redraw it */
|
|
pwidget = widget;
|
|
while (pwidget != NULL) {
|
|
if (pwidget->mapped == false)
|
|
return;
|
|
pwidget = pwidget->parent;
|
|
}
|
|
|
|
widget->redraw.needed = true;
|
|
widget->redraw.x = 0;
|
|
widget->redraw.y = 0;
|
|
widget->redraw.width = widget->width;
|
|
widget->redraw.height = widget->height;
|
|
|
|
#ifdef FBTK_LOGGING
|
|
LOG("redrawing %p %d,%d %d,%d", widget, widget->redraw.x, widget->redraw.y, widget->redraw.width, widget->redraw.height);
|
|
#endif
|
|
|
|
cwidget = widget->last_child;
|
|
while (cwidget != NULL) {
|
|
fbtk_request_redraw(cwidget);
|
|
cwidget = cwidget->prev;
|
|
}
|
|
|
|
while (widget->parent != NULL) {
|
|
widget = widget->parent;
|
|
widget->redraw.child = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* exported function documented in fbtk.h */
|
|
int
|
|
fbtk_set_mapping(fbtk_widget_t *widget, bool map)
|
|
{
|
|
LOG("setting mapping on %p to %d", widget, map);
|
|
widget->mapped = map;
|
|
if (map) {
|
|
fbtk_request_redraw(widget);
|
|
} else {
|
|
fbtk_request_redraw(widget->parent);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/** swap the widget given with the next sibling.
|
|
*
|
|
* Swap a sibling widget with the next deepest in the hierachy
|
|
*/
|
|
static void
|
|
swap_siblings(fbtk_widget_t *lw)
|
|
{
|
|
fbtk_widget_t *rw = lw->next; /* the widget to swap lw with */
|
|
fbtk_widget_t *before;
|
|
fbtk_widget_t *after;
|
|
|
|
assert(rw != NULL);
|
|
|
|
LOG("Swapping %p with %p", lw, rw);
|
|
before = lw->prev;
|
|
after = rw->next;
|
|
|
|
if (before == NULL) {
|
|
/* left widget is currently the first child */
|
|
lw->parent->first_child = rw;
|
|
} else {
|
|
before->next = rw;
|
|
}
|
|
rw->prev = before;
|
|
rw->next = lw;
|
|
|
|
if (after == NULL) {
|
|
/* right widget is currently the last child */
|
|
rw->parent->last_child = lw;
|
|
} else {
|
|
after->prev = lw;
|
|
}
|
|
lw->next = after;
|
|
lw->prev = rw;
|
|
}
|
|
|
|
|
|
|
|
/* exported function documented in fbtk.h */
|
|
int
|
|
fbtk_set_zorder(fbtk_widget_t *widget, int z)
|
|
{
|
|
while (z != 0) {
|
|
if (z < 0) {
|
|
if (widget->prev == NULL)
|
|
break; /* cannot go any shallower */
|
|
|
|
/* swap with previous entry */
|
|
swap_siblings(widget->prev);
|
|
|
|
z++;
|
|
} else {
|
|
if (widget->next == NULL)
|
|
break; /* cannot go any deeper */
|
|
|
|
/* swap with subsequent entry */
|
|
swap_siblings(widget);
|
|
|
|
z--;
|
|
}
|
|
}
|
|
|
|
return z;
|
|
}
|
|
|
|
|
|
/* exported function documented in fbtk.h */
|
|
bool
|
|
fbtk_set_pos_and_size(fbtk_widget_t *widget,
|
|
int x, int y,
|
|
int width, int height)
|
|
{
|
|
if (widget->parent != NULL) {
|
|
fbtk_widget_t *parent = widget->parent;
|
|
|
|
/* make new window fit inside parent */
|
|
if (width == 0) {
|
|
width = parent->width - x;
|
|
} else if (width < 0) {
|
|
width = parent->width + width - x;
|
|
}
|
|
if ((width + x) > parent->width) {
|
|
width = parent->width - x;
|
|
}
|
|
|
|
if (height == 0) {
|
|
height = parent->height - y;
|
|
} else if (height < 0) {
|
|
height = parent->height + height - y;
|
|
}
|
|
if ((height + y) > parent->height) {
|
|
height = parent->height - y;
|
|
}
|
|
}
|
|
|
|
if ((widget->x != x) ||
|
|
(widget->y != y) ||
|
|
(widget->width != width) ||
|
|
(widget->height != height)) {
|
|
widget->x = x;
|
|
widget->y = y;
|
|
widget->width = width;
|
|
widget->height = height;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/* exported function docuemnted in fbtk.h */
|
|
void
|
|
fbtk_set_caret(fbtk_widget_t *widget, bool set,
|
|
int x, int y, int height,
|
|
void (*remove_caret)(fbtk_widget_t *widget))
|
|
{
|
|
fbtk_widget_t *root;
|
|
|
|
assert(widget != NULL);
|
|
root = fbtk_get_root_widget(widget);
|
|
|
|
if (root->u.root.caret.owner != NULL &&
|
|
root->u.root.caret.remove_cb != NULL)
|
|
root->u.root.caret.remove_cb(widget);
|
|
|
|
if (set) {
|
|
assert(remove_caret != NULL);
|
|
|
|
root->u.root.caret.owner = widget;
|
|
root->u.root.caret.x = x;
|
|
root->u.root.caret.y = y;
|
|
root->u.root.caret.height = height;
|
|
root->u.root.caret.remove_cb = remove_caret;
|
|
|
|
} else {
|
|
root->u.root.caret.owner = NULL;
|
|
root->u.root.caret.remove_cb = NULL;
|
|
}
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
int
|
|
fbtk_destroy_widget(fbtk_widget_t *widget)
|
|
{
|
|
fbtk_widget_t *parent;
|
|
int ret = 0;
|
|
|
|
ret = fbtk_post_callback(widget, FBTK_CBT_DESTROY);
|
|
|
|
while (widget->first_child != NULL) {
|
|
fbtk_destroy_widget(widget->first_child);
|
|
}
|
|
|
|
parent = widget->parent;
|
|
if (parent != NULL) {
|
|
|
|
/* unlink from siblings */
|
|
if (widget->prev != NULL) {
|
|
widget->prev->next = widget->next;
|
|
} else {
|
|
/* must be the first widget, unlink from parent */
|
|
parent->first_child = widget->next;
|
|
}
|
|
if (widget->next != NULL) {
|
|
widget->next->prev = widget->prev;
|
|
} else {
|
|
/* must be the last widget, unlink from parent */
|
|
parent->last_child = widget->prev;
|
|
}
|
|
|
|
free(widget);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* region coverage flags. */
|
|
enum {
|
|
POINT_LEFTOF_REGION = 1,
|
|
POINT_RIGHTOF_REGION = 2,
|
|
POINT_ABOVE_REGION = 4,
|
|
POINT_BELOW_REGION = 8,
|
|
};
|
|
|
|
/* Computes where a point lies in respect to an area. */
|
|
#define REGION(x,y,cx1,cx2,cy1,cy2) \
|
|
(( (y) > (cy2) ? POINT_BELOW_REGION : 0) | \
|
|
( (y) < (cy1) ? POINT_ABOVE_REGION : 0) | \
|
|
( (x) > (cx2) ? POINT_RIGHTOF_REGION : 0) | \
|
|
( (x) < (cx1) ? POINT_LEFTOF_REGION : 0) )
|
|
|
|
/* swap two integers */
|
|
#define SWAP(a, b) do { int t; t=(a); (a)=(b); (b)=t; } while(0)
|
|
|
|
/* exported function documented in fbtk.h */
|
|
bool
|
|
fbtk_clip_rect(const bbox_t * restrict clip, bbox_t * restrict box)
|
|
{
|
|
uint8_t region1;
|
|
uint8_t region2;
|
|
|
|
/* ensure co-ordinates are in ascending order */
|
|
if (box->x1 < box->x0)
|
|
SWAP(box->x0, box->x1);
|
|
if (box->y1 < box->y0)
|
|
SWAP(box->y0, box->y1);
|
|
|
|
region1 = REGION(box->x0, box->y0, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1);
|
|
region2 = REGION(box->x1, box->y1, clip->x0, clip->x1 - 1, clip->y0, clip->y1 - 1);
|
|
|
|
/* area lies entirely outside the clipping rectangle */
|
|
if ((region1 | region2) && (region1 & region2))
|
|
return false;
|
|
|
|
if (box->x0 < clip->x0)
|
|
box->x0 = clip->x0;
|
|
if (box->x0 > clip->x1)
|
|
box->x0 = clip->x1;
|
|
|
|
if (box->x1 < clip->x0)
|
|
box->x1 = clip->x0;
|
|
if (box->x1 > clip->x1)
|
|
box->x1 = clip->x1;
|
|
|
|
if (box->y0 < clip->y0)
|
|
box->y0 = clip->y0;
|
|
if (box->y0 > clip->y1)
|
|
box->y0 = clip->y1;
|
|
|
|
if (box->y1 < clip->y0)
|
|
box->y1 = clip->y0;
|
|
if (box->y1 > clip->y1)
|
|
box->y1 = clip->y1;
|
|
|
|
return true;
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
bool
|
|
fbtk_clip_to_widget(fbtk_widget_t *widget, bbox_t * restrict box)
|
|
{
|
|
bbox_t wbox;
|
|
wbox.x0 = 0;
|
|
wbox.y0 = 0;
|
|
wbox.x1 = widget->width;
|
|
wbox.y1 = widget->height;
|
|
return fbtk_clip_rect(&wbox, box);
|
|
}
|
|
|
|
|
|
|
|
/* internally exported function documented in widget.h */
|
|
int
|
|
fbtk_set_ptr(fbtk_widget_t *widget, fbtk_callback_info *cbi)
|
|
{
|
|
fbtk_widget_t *root = fbtk_get_root_widget(widget);
|
|
struct fbtk_bitmap *bm = cbi->context;
|
|
|
|
nsfb_cursor_set(root->u.root.fb,
|
|
(nsfb_colour_t *)bm->pixdata,
|
|
bm->width,
|
|
bm->height,
|
|
bm->width,
|
|
bm->hot_x,
|
|
bm->hot_y);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/* internally exported function documented in widget.h */
|
|
fbtk_widget_t *
|
|
fbtk_get_root_widget(fbtk_widget_t *widget)
|
|
{
|
|
while (widget->parent != NULL)
|
|
widget = widget->parent;
|
|
|
|
/* check root widget was found */
|
|
if (widget->type != FB_WIDGET_TYPE_ROOT) {
|
|
LOG("Widget with null parent that is not the root widget!");
|
|
return NULL;
|
|
}
|
|
|
|
return widget;
|
|
}
|
|
|
|
|
|
/* exported function documented in fbtk.h */
|
|
int
|
|
fbtk_get_absx(fbtk_widget_t *widget)
|
|
{
|
|
int x = widget->x;
|
|
|
|
while (widget->parent != NULL) {
|
|
widget = widget->parent;
|
|
x += widget->x;
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
int
|
|
fbtk_get_absy(fbtk_widget_t *widget)
|
|
{
|
|
int y = widget->y;
|
|
|
|
while (widget->parent != NULL) {
|
|
widget = widget->parent;
|
|
y += widget->y;
|
|
}
|
|
|
|
return y;
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
int
|
|
fbtk_get_height(fbtk_widget_t *widget)
|
|
{
|
|
return widget->height;
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
int
|
|
fbtk_get_width(fbtk_widget_t *widget)
|
|
{
|
|
return widget->width;
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
bool
|
|
fbtk_get_bbox(fbtk_widget_t *widget, nsfb_bbox_t *bbox)
|
|
{
|
|
bbox->x0 = widget->x;
|
|
bbox->y0 = widget->y;
|
|
bbox->x1 = widget->x + widget->width;
|
|
bbox->y1 = widget->y + widget->height;
|
|
|
|
widget = widget->parent;
|
|
while (widget != NULL) {
|
|
bbox->x0 += widget->x;
|
|
bbox->y0 += widget->y;
|
|
bbox->x1 += widget->x;
|
|
bbox->y1 += widget->y;
|
|
widget = widget->parent;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
fbtk_get_caret(fbtk_widget_t *widget, int *x, int *y, int *height)
|
|
{
|
|
fbtk_widget_t *root = fbtk_get_root_widget(widget);
|
|
|
|
if (root->u.root.caret.owner == widget) {
|
|
*x = root->u.root.caret.x;
|
|
*y = root->u.root.caret.y;
|
|
*height = root->u.root.caret.height;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
*x = 0;
|
|
*y = 0;
|
|
*height = 0;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
fbtk_widget_t *
|
|
fbtk_get_widget_at(fbtk_widget_t *nwid, int x, int y)
|
|
{
|
|
fbtk_widget_t *widget = NULL; /* found widget */
|
|
|
|
/* require the root widget to start */
|
|
nwid = fbtk_get_root_widget(nwid);
|
|
|
|
while (nwid != NULL) {
|
|
if ((nwid->mapped) &&
|
|
(x >= nwid->x) &&
|
|
(y >= nwid->y) &&
|
|
(x < (nwid->x + nwid->width)) &&
|
|
(y < (nwid->y + nwid->height))) {
|
|
widget = nwid;
|
|
x -= nwid->x;
|
|
y -= nwid->y;
|
|
nwid = nwid->first_child;
|
|
} else {
|
|
nwid = nwid->next;
|
|
}
|
|
}
|
|
|
|
return widget;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* internally exported function documented in widget.h */
|
|
fbtk_widget_t *
|
|
fbtk_widget_new(fbtk_widget_t *parent,
|
|
enum fbtk_widgettype_e type,
|
|
int x,
|
|
int y,
|
|
int width,
|
|
int height)
|
|
{
|
|
fbtk_widget_t *neww; /* new widget */
|
|
|
|
if (parent == NULL)
|
|
return NULL;
|
|
|
|
neww = calloc(1, sizeof(fbtk_widget_t));
|
|
if (neww == NULL)
|
|
return NULL;
|
|
|
|
#ifdef FBTK_LOGGING
|
|
LOG("creating %p %d,%d %d,%d", neww, x, y, width, height);
|
|
#endif
|
|
|
|
/* make new window fit inside parent */
|
|
if (width == 0) {
|
|
width = parent->width - x;
|
|
} else if (width < 0) {
|
|
width = parent->width + width - x;
|
|
}
|
|
if ((width + x) > parent->width) {
|
|
width = parent->width - x;
|
|
}
|
|
|
|
if (height == 0) {
|
|
height = parent->height - y;
|
|
} else if (height < 0) {
|
|
height = parent->height + height - y;
|
|
}
|
|
if ((height + y) > parent->height) {
|
|
height = parent->height - y;
|
|
}
|
|
|
|
#ifdef FBTK_LOGGING
|
|
LOG("using %p %d,%d %d,%d", neww, x, y, width, height);
|
|
#endif
|
|
/* set values */
|
|
neww->type = type;
|
|
neww->x = x;
|
|
neww->y = y;
|
|
neww->width = width;
|
|
neww->height = height;
|
|
|
|
/* insert into widget heiarchy */
|
|
|
|
neww->parent = parent;
|
|
|
|
if (parent->first_child == NULL) {
|
|
/* no child widgets yet */
|
|
parent->last_child = neww;
|
|
} else {
|
|
/* add new widget to front of sibling chain */
|
|
neww->next = parent->first_child;
|
|
neww->next->prev = neww;
|
|
}
|
|
parent->first_child = neww;
|
|
|
|
return neww;
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
bool
|
|
fbtk_get_redraw_pending(fbtk_widget_t *widget)
|
|
{
|
|
fbtk_widget_t *root;
|
|
|
|
/* ensure we have the root widget */
|
|
root = fbtk_get_root_widget(widget);
|
|
|
|
return root->redraw.needed | root->redraw.child;
|
|
}
|
|
|
|
/** Perform a depth-first tree-walk, calling the redraw callback of the widgets in turn.
|
|
*
|
|
* This function makes no decisions of its own and simply walks the
|
|
* widget tree depth first calling widgets redraw callbacks if flagged
|
|
* to do so.
|
|
* The tree search is optimised with a flag to indicate wether the
|
|
* children of a node should be considered.
|
|
*/
|
|
static int
|
|
do_redraw(nsfb_t *nsfb, fbtk_widget_t *widget)
|
|
{
|
|
nsfb_bbox_t plot_ctx;
|
|
fbtk_widget_t *cwidget; /* child widget */
|
|
|
|
/* check if the widget requires redrawing */
|
|
if (widget->redraw.needed == true) {
|
|
plot_ctx.x0 = fbtk_get_absx(widget) + widget->redraw.x;
|
|
plot_ctx.y0 = fbtk_get_absy(widget) + widget->redraw.y;
|
|
plot_ctx.x1 = plot_ctx.x0 + widget->redraw.width;
|
|
plot_ctx.y1 = plot_ctx.y0 + widget->redraw.height;
|
|
|
|
#ifdef FBTK_LOGGING
|
|
LOG("clipping %p %d,%d %d,%d", widget, plot_ctx.x0, plot_ctx.y0, plot_ctx.x1, plot_ctx.y1);
|
|
#endif
|
|
if (nsfb_plot_set_clip(nsfb, &plot_ctx) == true) {
|
|
fbtk_post_callback(widget, FBTK_CBT_REDRAW);
|
|
}
|
|
widget->redraw.needed = false;
|
|
}
|
|
|
|
/* walk the widgets children if child flag is set */
|
|
if (widget->redraw.child) {
|
|
cwidget = widget->last_child;
|
|
while (cwidget != NULL) {
|
|
do_redraw(nsfb, cwidget);
|
|
cwidget = cwidget->prev;
|
|
}
|
|
widget->redraw.child = false;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
int
|
|
fbtk_redraw(fbtk_widget_t *widget)
|
|
{
|
|
fbtk_widget_t *root;
|
|
|
|
/* ensure we have the root widget */
|
|
root = fbtk_get_root_widget(widget);
|
|
|
|
return do_redraw(root->u.root.fb, root);
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
fbtk_callback
|
|
fbtk_get_handler(fbtk_widget_t *widget, fbtk_callback_type cbt)
|
|
{
|
|
if ((cbt <= FBTK_CBT_START) || (cbt >= FBTK_CBT_END)) {
|
|
/* type out of range, no way to report error so return NULL */
|
|
return NULL;
|
|
}
|
|
|
|
return widget->callback[cbt];
|
|
}
|
|
|
|
/* exported function documented in fbtk.h */
|
|
fbtk_callback
|
|
fbtk_set_handler(fbtk_widget_t *widget,
|
|
fbtk_callback_type cbt,
|
|
fbtk_callback cb,
|
|
void *context)
|
|
{
|
|
fbtk_callback prevcb;
|
|
|
|
if ((cbt <= FBTK_CBT_START) || (cbt >= FBTK_CBT_END)) {
|
|
/* type out of range, no way to report error so return NULL */
|
|
return NULL;
|
|
}
|
|
|
|
prevcb = widget->callback[cbt];
|
|
|
|
widget->callback[cbt] = cb;
|
|
widget->callback_context[cbt] = context;
|
|
|
|
return prevcb;
|
|
}
|
|
|
|
/* exported function docuemnted in fbtk.h */
|
|
int
|
|
fbtk_post_callback(fbtk_widget_t *widget, fbtk_callback_type cbt, ...)
|
|
{
|
|
fbtk_callback_info cbi;
|
|
int ret = 0;
|
|
va_list ap;
|
|
|
|
if (widget == NULL)
|
|
return -1;
|
|
/* if the widget is not mapped do not attempt to post any
|
|
* events to it
|
|
*/
|
|
if (widget->mapped == false)
|
|
return ret;
|
|
|
|
if (widget->callback[cbt] != NULL) {
|
|
cbi.type = cbt;
|
|
cbi.context = widget->callback_context[cbt];
|
|
|
|
va_start(ap, cbt);
|
|
|
|
switch (cbt) {
|
|
case FBTK_CBT_SCROLLX:
|
|
cbi.x = va_arg(ap,int);
|
|
break;
|
|
|
|
case FBTK_CBT_SCROLLY:
|
|
cbi.y = va_arg(ap,int);
|
|
break;
|
|
|
|
case FBTK_CBT_CLICK:
|
|
cbi.event = va_arg(ap, void *);
|
|
cbi.x = va_arg(ap, int);
|
|
cbi.y = va_arg(ap, int);
|
|
break;
|
|
|
|
case FBTK_CBT_INPUT:
|
|
cbi.event = va_arg(ap, void *);
|
|
break;
|
|
|
|
case FBTK_CBT_POINTERMOVE:
|
|
cbi.x = va_arg(ap, int);
|
|
cbi.y = va_arg(ap, int);
|
|
break;
|
|
|
|
case FBTK_CBT_REDRAW:
|
|
break;
|
|
|
|
case FBTK_CBT_USER:
|
|
break;
|
|
|
|
case FBTK_CBT_STRIP_FOCUS:
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
va_end(ap);
|
|
|
|
ret = (widget->callback[cbt])(widget, &cbi);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* exported function docuemnted in fbtk.h */
|
|
void
|
|
fbtk_set_focus(fbtk_widget_t *widget)
|
|
{
|
|
fbtk_widget_t *root;
|
|
|
|
/* ensure we have the root widget */
|
|
root = fbtk_get_root_widget(widget);
|
|
|
|
if (root->u.root.input != NULL &&
|
|
root->u.root.input != widget) {
|
|
/* inform previous holder of focus that it's being stripped
|
|
* of focus */
|
|
fbtk_post_callback(root->u.root.input, FBTK_CBT_STRIP_FOCUS);
|
|
}
|
|
|
|
root->u.root.input = widget;
|
|
}
|
|
|
|
|
|
|
|
/* exported function docuemnted in fbtk.h */
|
|
nsfb_t *
|
|
fbtk_get_nsfb(fbtk_widget_t *widget)
|
|
{
|
|
fbtk_widget_t *root;
|
|
|
|
/* ensure we have the root widget */
|
|
root = fbtk_get_root_widget(widget);
|
|
|
|
return root->u.root.fb;
|
|
}
|
|
|
|
/* exported function docuemnted in fbtk.h */
|
|
fbtk_widget_t *
|
|
fbtk_init(nsfb_t *fb)
|
|
{
|
|
fbtk_widget_t *root;
|
|
|
|
/* create and configure root widget */
|
|
root = calloc(1, sizeof(fbtk_widget_t));
|
|
if (root == NULL)
|
|
return NULL;
|
|
|
|
root->type = FB_WIDGET_TYPE_ROOT;
|
|
root->u.root.fb = fb;
|
|
root->u.root.caret.owner = NULL;
|
|
|
|
nsfb_get_geometry(fb, &root->width, &root->height, NULL);
|
|
|
|
root->mapped = true;
|
|
|
|
return root;
|
|
}
|
|
|
|
/*
|
|
* Local Variables:
|
|
* c-basic-offset:8
|
|
* End:
|
|
*/
|