From 5bebf2f2fc27a31c8b2efa7a837baef63c1b0a97 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Wed, 7 Jul 2010 18:08:17 +0000 Subject: Merge branches/vince/netsurf-fbtk-rework to trunk. svn path=/trunk/netsurf/; revision=10605 --- framebuffer/fbtk.c | 1209 ---------------------------- framebuffer/fbtk.h | 358 ++++++--- framebuffer/fbtk/bitmap.c | 137 ++++ framebuffer/fbtk/event.c | 273 +++++++ framebuffer/fbtk/fbtk.c | 726 +++++++++++++++++ framebuffer/fbtk/fill.c | 81 ++ framebuffer/fbtk/osk.c | 202 +++++ framebuffer/fbtk/scroll.c | 543 +++++++++++++ framebuffer/fbtk/text.c | 421 ++++++++++ framebuffer/fbtk/user.c | 64 ++ framebuffer/fbtk/widget.h | 246 ++++++ framebuffer/fbtk/window.c | 91 +++ framebuffer/fbtk_widget.h | 109 --- framebuffer/fbtk_widget_scroll.c | 305 ------- framebuffer/framebuffer.c | 6 +- framebuffer/gui.c | 1503 +++++++++++++++++++---------------- framebuffer/gui.h | 45 +- framebuffer/image_data.h | 3 + framebuffer/localhistory.c | 162 ++++ framebuffer/options.h | 54 +- framebuffer/res/icons/history.png | Bin 0 -> 884 bytes framebuffer/res/icons/history_g.png | Bin 0 -> 798 bytes framebuffer/thumbnail.c | 13 +- 23 files changed, 4119 insertions(+), 2432 deletions(-) delete mode 100644 framebuffer/fbtk.c create mode 100644 framebuffer/fbtk/bitmap.c create mode 100644 framebuffer/fbtk/event.c create mode 100644 framebuffer/fbtk/fbtk.c create mode 100644 framebuffer/fbtk/fill.c create mode 100644 framebuffer/fbtk/osk.c create mode 100644 framebuffer/fbtk/scroll.c create mode 100644 framebuffer/fbtk/text.c create mode 100644 framebuffer/fbtk/user.c create mode 100644 framebuffer/fbtk/widget.h create mode 100644 framebuffer/fbtk/window.c delete mode 100644 framebuffer/fbtk_widget.h delete mode 100644 framebuffer/fbtk_widget_scroll.c create mode 100644 framebuffer/localhistory.c create mode 100644 framebuffer/res/icons/history.png create mode 100644 framebuffer/res/icons/history_g.png (limited to 'framebuffer') diff --git a/framebuffer/fbtk.c b/framebuffer/fbtk.c deleted file mode 100644 index 56215bdd5..000000000 --- a/framebuffer/fbtk.c +++ /dev/null @@ -1,1209 +0,0 @@ -/* - * Copyright 2008 Vincent Sanders - * - * Framebuffer windowing toolkit - * - * 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 . - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "utils/utils.h" -#include "utils/log.h" -#include "css/css.h" -#include "desktop/browser.h" -#include "desktop/plotters.h" - -#include "framebuffer/gui.h" -#include "framebuffer/fbtk.h" -#include "framebuffer/fbtk_widget.h" -#include "framebuffer/bitmap.h" -#include "framebuffer/image_data.h" - -static plot_font_style_t root_style = { - .family = PLOT_FONT_FAMILY_SANS_SERIF, - .size = 11 * FONT_SIZE_SCALE, - .weight = 400, - .flags = FONTF_NONE, -}; - - -/* widget list */ -struct fbtk_widget_list_s { - struct fbtk_widget_list_s *next; - struct fbtk_widget_list_s *prev; - fbtk_widget_t *widget; -} ; - -enum { - POINT_LEFTOF_REGION = 1, - POINT_RIGHTOF_REGION = 2, - POINT_ABOVE_REGION = 4, - POINT_BELOW_REGION = 8, -}; - -#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) ) - -#define SWAP(a, b) do { int t; t=(a); (a)=(b); (b)=t; } while(0) - -/* clip a rectangle to another rectangle */ -bool fbtk_clip_rect(const bbox_t * restrict clip, bbox_t * restrict box) -{ - uint8_t region1; - uint8_t region2; - - 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; -} - -/* clip a rectangle to a widgets area rectangle */ -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); -} - - -/* creates a new widget of a given type */ -fbtk_widget_t * -new_widget(enum fbtk_widgettype_e type) -{ - fbtk_widget_t *neww; - neww = calloc(1, sizeof(fbtk_widget_t)); - neww->type = type; - return neww; -} - - -/* find the root widget from any widget in the toolkits hierarchy */ -fbtk_widget_t * -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; -} - - -/* set widget to be redrawn */ -void -fbtk_request_redraw(fbtk_widget_t *widget) -{ - widget->redraw_required = true; - - if (widget->type == FB_WIDGET_TYPE_WINDOW) { - fbtk_widget_list_t *lent = widget->u.window.widgets; - - while (lent != NULL) { - lent->widget->redraw_required = true; - lent = lent->next; - } - } - - while (widget->parent != NULL) { - widget = widget->parent; - widget->redraw_required = true; - } -} - -fbtk_widget_t * -add_widget_to_window(fbtk_widget_t *window, fbtk_widget_t *widget) -{ - fbtk_widget_list_t *newent; - fbtk_widget_list_t **nextent; - fbtk_widget_list_t *prevent; /* previous entry pointer */ - - if (window->type == FB_WIDGET_TYPE_WINDOW) { - /* caller attached widget to a window */ - - nextent = &window->u.window.widgets; - prevent = NULL; - while (*nextent != NULL) { - prevent = (*nextent); - nextent = &(prevent->next); - } - - newent = calloc(1, sizeof(struct fbtk_widget_list_s)); - - newent->widget = widget; - newent->next = NULL; - newent->prev = prevent; - - *nextent = newent; - - window->u.window.widgets_end = newent; - } - widget->parent = window; - - fbtk_request_redraw(widget); - - return widget; -} - -static void -remove_widget_from_window(fbtk_widget_t *window, fbtk_widget_t *widget) -{ - fbtk_widget_list_t *lent = window->u.window.widgets; - - while ((lent != NULL) && (lent->widget != widget)) { - lent = lent->next; - } - - if (lent != NULL) { - if (lent->prev == NULL) { - window->u.window.widgets = lent->next; - } else { - lent->prev->next = lent->next; - } - if (lent->next == NULL) { - window->u.window.widgets_end = lent->prev; - } else { - lent->next->prev = lent->prev; - } - free(lent); - } -} - -static void -fbtk_redraw_widget(fbtk_widget_t *widget) -{ - nsfb_bbox_t saved_plot_ctx; - nsfb_bbox_t plot_ctx; - fbtk_widget_t *root = get_root_widget(widget); - - //LOG(("widget %p type %d", widget, widget->type)); - if (widget->redraw_required == false) - return; - - widget->redraw_required = false; - - /* ensure there is a redraw handler */ - if (fbtk_get_handler(widget, FBTK_CBT_REDRAW) == NULL) - return; - - /* get the current clipping rectangle */ - nsfb_plot_get_clip(root->u.root.fb, &saved_plot_ctx); - - plot_ctx.x0 = fbtk_get_x(widget); - plot_ctx.y0 = fbtk_get_y(widget); - plot_ctx.x1 = plot_ctx.x0 + widget->width; - plot_ctx.y1 = plot_ctx.y0 + widget->height; - - /* clip widget to the current area and redraw if its exposed */ - if (nsfb_plot_clip(&saved_plot_ctx, &plot_ctx )) { - - nsfb_plot_set_clip(root->u.root.fb, &plot_ctx); - - fbtk_post_callback(widget, FBTK_CBT_REDRAW); - - /* restore clipping rectangle */ - nsfb_plot_set_clip(root->u.root.fb, &saved_plot_ctx); - - //LOG(("OS redrawing %d,%d %d,%d", fb_plot_ctx.x0, fb_plot_ctx.y0, fb_plot_ctx.x1, fb_plot_ctx.y1)); - } - -} - -/*************** redraw widgets **************/ - -static int -fb_redraw_fill(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - nsfb_bbox_t bbox; - fbtk_widget_t *root = get_root_widget(widget); - - fbtk_get_bbox(widget, &bbox); - - nsfb_claim(root->u.root.fb, &bbox); - - /* clear background */ - if ((widget->bg & 0xFF000000) != 0) { - /* transparent polygon filling isnt working so fake it */ - nsfb_plot_rectangle_fill(root->u.root.fb, &bbox, widget->bg); - } - - nsfb_update(root->u.root.fb, &bbox); - return 0; -} - - - -static int -fb_redraw_bitmap(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - nsfb_bbox_t bbox; - nsfb_bbox_t rect; - fbtk_widget_t *root = get_root_widget(widget); - - fbtk_get_bbox(widget, &bbox); - - rect = bbox; - - nsfb_claim(root->u.root.fb, &bbox); - - /* clear background */ - if ((widget->bg & 0xFF000000) != 0) { - /* transparent polygon filling isnt working so fake it */ - nsfb_plot_rectangle_fill(root->u.root.fb, &bbox, widget->bg); - } - - /* plot the image */ - nsfb_plot_bitmap(root->u.root.fb, - &rect, - (nsfb_colour_t *)widget->u.bitmap.bitmap->pixdata, - widget->u.bitmap.bitmap->width, - widget->u.bitmap.bitmap->height, - widget->u.bitmap.bitmap->width, - !widget->u.bitmap.bitmap->opaque); - - nsfb_update(root->u.root.fb, &bbox); - - return 0; -} - -static int -fbtk_window_default_redraw(fbtk_widget_t *window, fbtk_callback_info *cbi) -{ - fbtk_widget_list_t *lent; - int res = 0; - - /* get the list of widgets */ - lent = window->u.window.widgets; - - while (lent != NULL) { - fbtk_redraw_widget(lent->widget); - lent = lent->next; - } - return res; -} - -static int -fbtk_window_default_move(fbtk_widget_t *window, fbtk_callback_info *cbi) -{ - fbtk_widget_list_t *lent; - fbtk_widget_t *widget; - int res = 0; - - /* get the list of widgets */ - lent = window->u.window.widgets_end; - - while (lent != NULL) { - widget = lent->widget; - - if ((cbi->x > widget->x) && - (cbi->y > widget->y) && - (cbi->x < widget->x + widget->width) && - (cbi->y < widget->y + widget->height)) { - res = fbtk_post_callback(widget, - FBTK_CBT_POINTERMOVE, - cbi->x - widget->x, - cbi->y - widget->y); - break; - } - lent = lent->prev; - } - return res; -} - -static int -fbtk_window_default_click(fbtk_widget_t *window, fbtk_callback_info *cbi) -{ - fbtk_widget_list_t *lent; - fbtk_widget_t *widget; - int res = 0; - - /* get the list of widgets */ - lent = window->u.window.widgets; - - while (lent != NULL) { - widget = lent->widget; - - if ((cbi->x > widget->x) && - (cbi->y > widget->y) && - (cbi->x < widget->x + widget->width) && - (cbi->y < widget->y + widget->height)) { - if (fbtk_get_handler(widget, FBTK_CBT_INPUT) != NULL) { - fbtk_widget_t *root = get_root_widget(widget); - root->u.root.input = widget; - } - - res = fbtk_post_callback(widget, - FBTK_CBT_CLICK, - cbi->event, - cbi->x - widget->x, - cbi->y - widget->y); - if (res != 0) - break; - - } - lent = lent->next; - } - return res; -} - -static int -fb_redraw_text(fbtk_widget_t *widget, fbtk_callback_info *cbi ) -{ - nsfb_bbox_t bbox; - nsfb_bbox_t rect; - fbtk_widget_t *root = get_root_widget(widget); - - fbtk_get_bbox(widget, &bbox); - - rect = bbox; - - nsfb_claim(root->u.root.fb, &bbox); - - /* clear background */ - if ((widget->bg & 0xFF000000) != 0) { - /* transparent polygon filling isnt working so fake it */ - nsfb_plot_rectangle_fill(root->u.root.fb, &bbox, widget->bg); - } - - - if (widget->u.text.outline) { - rect.x1--; - rect.y1--; - nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0x00000000, false, false); - } - - if (widget->u.text.text != NULL) { - root_style.background = widget->bg; - root_style.foreground = widget->fg; - - plot.text(bbox.x0 + 3, - bbox.y0 + 17, - widget->u.text.text, - strlen(widget->u.text.text), - &root_style); - } - - nsfb_update(root->u.root.fb, &bbox); - - return 0; -} - - - - -static int -text_input(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - int value; - if (cbi->event == NULL) { - /* gain focus */ - if (widget->u.text.text == NULL) - widget->u.text.text = calloc(1,1); - widget->u.text.idx = strlen(widget->u.text.text); - - fbtk_request_redraw(widget); - - return 0; - } - - if (cbi->event->type != NSFB_EVENT_KEY_DOWN) - return 0; - - value = cbi->event->value.keycode; - switch (value) { - case NSFB_KEY_BACKSPACE: - if (widget->u.text.idx <= 0) - break; - widget->u.text.idx--; - widget->u.text.text[widget->u.text.idx] = 0; - break; - - case NSFB_KEY_RETURN: - widget->u.text.enter(widget->u.text.pw, widget->u.text.text); - break; - - case NSFB_KEY_PAGEUP: - case NSFB_KEY_PAGEDOWN: - case NSFB_KEY_RIGHT: - case NSFB_KEY_LEFT: - case NSFB_KEY_UP: - case NSFB_KEY_DOWN: - case NSFB_KEY_RSHIFT: - case NSFB_KEY_LSHIFT: - /* Not handling any of these correctly yet, but avoid putting - * charcters in the text widget when they're pressed. */ - break; - - default: - /* allow for new character and null */ - { - char *temp = realloc(widget->u.text.text, - widget->u.text.idx + 2); - if (temp != NULL) { - widget->u.text.text = temp; - widget->u.text.text[widget->u.text.idx] = value; - widget->u.text.text[widget->u.text.idx + 1] = '\0'; - widget->u.text.idx++; - } - } - break; - } - - fbtk_request_redraw(widget); - - return 0; -} - -/* sets the enter action on a writable icon */ -void -fbtk_writable_text(fbtk_widget_t *widget, fbtk_enter_t enter, void *pw) -{ - widget->u.text.enter = enter; - widget->u.text.pw = pw; - - fbtk_set_handler(widget, FBTK_CBT_INPUT, text_input, widget); -} - - -/********** acessors ***********/ -int -fbtk_get_height(fbtk_widget_t *widget) -{ - return widget->height; -} - -int -fbtk_get_width(fbtk_widget_t *widget) -{ - return widget->width; -} - -int -fbtk_get_x(fbtk_widget_t *widget) -{ - int x = widget->x; - - while (widget->parent != NULL) { - widget = widget->parent; - x += widget->x; - } - - return x; -} - -int -fbtk_get_y(fbtk_widget_t *widget) -{ - int y = widget->y; - - while (widget->parent != NULL) { - widget = widget->parent; - y += widget->y; - } - - return y; -} - -/* get widgets bounding box in screen co-ordinates */ -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; - - while (widget->parent != NULL) { - widget = widget->parent; - bbox->x0 += widget->x; - bbox->y0 += widget->y; - bbox->x1 += widget->x; - bbox->y1 += widget->y; - } - - return true; -} - -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]; -} - -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; -} - - -void * -fbtk_get_userpw(fbtk_widget_t *widget) -{ - if ((widget == NULL) || (widget->type != FB_WIDGET_TYPE_USER)) - return NULL; - - return widget->u.user.pw; -} - -void -fbtk_set_text(fbtk_widget_t *widget, const char *text) -{ - if ((widget == NULL) || (widget->type != FB_WIDGET_TYPE_TEXT)) - return; - if (widget->u.text.text != NULL) { - if (strcmp(widget->u.text.text, text) == 0) - return; /* text is being set to the same thing */ - free(widget->u.text.text); - } - widget->u.text.text = strdup(text); - widget->u.text.idx = strlen(text); - - fbtk_request_redraw(widget); -} - - -void -fbtk_set_bitmap(fbtk_widget_t *widget, struct bitmap *image) -{ - if ((widget == NULL) || (widget->type != FB_WIDGET_TYPE_BITMAP)) - return; - - widget->u.bitmap.bitmap = image; - - fbtk_request_redraw(widget); -} - -void -fbtk_set_pos_and_size(fbtk_widget_t *widget, int x, int y, int width, int height) -{ - 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; - fbtk_request_redraw(widget); - LOG(("%d,%d %d,%d",x,y,width,height)); - } -} - -int -fbtk_count_children(fbtk_widget_t *widget) -{ - int count = 0; - fbtk_widget_list_t *lent; - - if (widget->type != FB_WIDGET_TYPE_WINDOW) { - if (widget->type != FB_WIDGET_TYPE_ROOT) - return -1; - widget = widget->u.root.rootw; - } - - lent = widget->u.window.widgets; - - while (lent != NULL) { - count++; - lent = lent->next; - } - - return count; -} - - -void -fbtk_input(fbtk_widget_t *root, nsfb_event_t *event) -{ - fbtk_widget_t *input; - - root = get_root_widget(root); - - /* obtain widget with input focus */ - input = root->u.root.input; - if (input == NULL) - return; /* no widget with input */ - - fbtk_post_callback(input, FBTK_CBT_INPUT, event); -} - -void -fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event) -{ - fbtk_widget_t *root; - nsfb_bbox_t cloc; - - /* ensure we have the root widget */ - root = get_root_widget(widget); - - nsfb_cursor_loc_get(root->u.root.fb, &cloc); - - - /* post the click */ - fbtk_post_callback(root->u.root.rootw, FBTK_CBT_CLICK, event, cloc.x0, cloc.y0); -} - - - -void -fbtk_move_pointer(fbtk_widget_t *widget, int x, int y, bool relative) -{ - fbtk_widget_t *root; - nsfb_bbox_t cloc; - - /* ensure we have the root widget */ - root = get_root_widget(widget); - - if (relative) { - nsfb_cursor_loc_get(root->u.root.fb, &cloc); - cloc.x0 += x; - cloc.y0 += y; - } else { - cloc.x0 = x; - cloc.y0 = y; - } - - root->redraw_required = true; - - /* update the pointer cursor */ - nsfb_cursor_loc_set(root->u.root.fb, &cloc); - - /* post the movement */ - fbtk_post_callback(root->u.root.rootw, FBTK_CBT_POINTERMOVE, cloc.x0, cloc.y0); - -} - -bool -fbtk_redraw_pending(fbtk_widget_t *widget) -{ - fbtk_widget_t *root; - - /* ensure we have the root widget */ - root = get_root_widget(widget); - - return root->redraw_required; -} - -int -fbtk_redraw(fbtk_widget_t *widget) -{ - fbtk_widget_t *root; - - /* ensure we have the root widget */ - root = get_root_widget(widget); - - if (!root->redraw_required) - return 0; - - fbtk_post_callback(root->u.root.rootw, FBTK_CBT_REDRAW); - - widget->redraw_required = false; - - return 1; -} - -/****** widget destruction ********/ -int fbtk_destroy_widget(fbtk_widget_t *widget) -{ - if (widget->type == FB_WIDGET_TYPE_WINDOW) { - /* TODO: walk child widgets and destroy them */ - } - - remove_widget_from_window(widget->parent, widget); - free(widget); - - return 0; -} - - -/************** Widget creation *************/ -fbtk_widget_t * -fbtk_create_text(fbtk_widget_t *window, - int x, int y, - int width, int height, - colour bg, colour fg, - bool outline) -{ - fbtk_widget_t *newt = new_widget(FB_WIDGET_TYPE_TEXT); - - newt->x = x; - newt->y = y; - newt->width = width; - newt->height = height; - newt->u.text.outline = outline; - - newt->fg = fg; - newt->bg = bg; - - fbtk_set_handler(newt, FBTK_CBT_REDRAW, fb_redraw_text, NULL); - - return add_widget_to_window(window, newt); -} - -fbtk_widget_t * -fbtk_create_bitmap(fbtk_widget_t *window, int x, int y, colour c, struct bitmap *image) -{ - fbtk_widget_t *newb = new_widget(FB_WIDGET_TYPE_BITMAP); - - newb->x = x; - newb->y = y; - newb->width = image->width; - newb->height = image->height; - newb->bg = c; - - newb->u.bitmap.bitmap = image; - - fbtk_set_handler(newb, FBTK_CBT_REDRAW, fb_redraw_bitmap, NULL); - - return add_widget_to_window(window, newb); -} - -static void -fbtk_width_height(fbtk_widget_t *parent, int x, int y, int *width, int *height) -{ - /* make widget fit inside parent */ - if (*width == 0) { - *width = parent->width - x; - } else if (*width < 0) { - *width = parent->width + *width; - } - if ((*width + x) > parent->width) { - *width = parent->width - x; - } - - if (*height == 0) { - *height = parent->height - y; - } else if (*height < 0) { - *height = parent->height + *height; - } - if ((*height + y) > parent->height) { - *height = parent->height - y; - } -} - -fbtk_widget_t * -fbtk_create_fill(fbtk_widget_t *window, int x, int y, int width, int height, colour c) -{ - fbtk_widget_t *neww = new_widget(FB_WIDGET_TYPE_FILL); - - neww->x = x; - neww->y = y; - neww->width = width; - neww->height = height; - - fbtk_width_height(window, x, y, &neww->width, &neww->height); - - neww->bg = c; - - fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_fill, NULL); - - return add_widget_to_window(window, neww); -} - -/* set pointer to bitmap in context on cursor move */ -static int -fbtk_set_ptr_move(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - fbtk_widget_t *root = get_root_widget(widget); - struct bitmap *bm = cbi->context; - - nsfb_cursor_set(root->u.root.fb, - (nsfb_colour_t *)bm->pixdata, - bm->width, - bm->height, - bm->width); - - return 0; -} - -fbtk_widget_t * -fbtk_create_button(fbtk_widget_t *window, - int x, int y, - colour c, - struct bitmap *image, - fbtk_callback click, - void *pw) -{ - fbtk_widget_t *newb = fbtk_create_bitmap(window, x, y, c, image); - - fbtk_set_handler(newb, FBTK_CBT_CLICK, click, pw); - fbtk_set_handler(newb, FBTK_CBT_POINTERMOVE, fbtk_set_ptr_move, &hand_image); - - return newb; -} - -fbtk_widget_t * -fbtk_create_writable_text(fbtk_widget_t *window, - int x, int y, - int width, int height, - colour bg, colour fg, - bool outline, - fbtk_enter_t enter, void *pw) -{ - fbtk_widget_t *newt = fbtk_create_text(window, x, y, width, height, bg,fg,outline); - newt->u.text.enter = enter; - newt->u.text.pw = pw; - - fbtk_set_handler(newt, FBTK_CBT_INPUT, text_input, newt); - - return newt; -} - -/* create user widget - * - * @param x coord relative to parent - */ -fbtk_widget_t * -fbtk_create_user(fbtk_widget_t *window, - int x, int y, - int width, int height, - void *pw) -{ - fbtk_widget_t *newu = new_widget(FB_WIDGET_TYPE_USER); - - - /* make new window fit inside parent */ - if (width == 0) { - width = window->width - x; - } else if (width < 0) { - width = window->width + width; - } - if ((width + x) > window->width) { - width = window->width - x; - } - - if (height == 0) { - height = window->height - y; - } else if (height < 0) { - height = window->height + height; - } - if ((height + y) > window->height) { - height = window->height - y; - } - - newu->x = x; - newu->y = y; - newu->width = width; - newu->height = height; - - newu->u.user.pw = pw; - - return add_widget_to_window(window, newu); -} - - -/* create new window - * - * @param x coord relative to parent - */ -fbtk_widget_t * -fbtk_create_window(fbtk_widget_t *parent, - int x, int y, int width, int height) -{ - fbtk_widget_t *newwin; - - LOG(("Creating window %p %d,%d %d,%d",parent,x,y,width,height)); - if (parent == NULL) - return NULL; - - if ((parent->type == FB_WIDGET_TYPE_ROOT) && - (parent->u.root.rootw != NULL)) { - LOG(("Using root window")); - parent = parent->u.root.rootw; - } - - newwin = new_widget(FB_WIDGET_TYPE_WINDOW); - - /* make new window fit inside parent */ - if (width == 0) { - width = parent->width - x; - } else if (width < 0) { - width = parent->width + width; - } - if ((width + x) > parent->width) { - width = parent->width - x; - } - - if (height == 0) { - height = parent->height - y; - } else if (height < 0) { - height = parent->height + height; - } - if ((height + y) > parent->height) { - height = parent->height - y; - } - - newwin->x = x; - newwin->y = y; - newwin->width = width; - newwin->height = height; - - fbtk_set_handler(newwin, FBTK_CBT_REDRAW, fbtk_window_default_redraw, NULL); - fbtk_set_handler(newwin, FBTK_CBT_POINTERMOVE, fbtk_window_default_move, NULL); - fbtk_set_handler(newwin, FBTK_CBT_CLICK, fbtk_window_default_click, NULL); - LOG(("Created window %p %d,%d %d,%d",newwin,x,y,width,height)); - - return add_widget_to_window(parent, newwin); -} - -int -fbtk_post_callback(fbtk_widget_t *widget, fbtk_callback_type cbt, ...) -{ - fbtk_callback_info cbi; - int ret = 0; - va_list ap; - - 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; - - default: - break; - } - va_end(ap); - - ret = (widget->callback[cbt])(widget, &cbi); - } - - return ret; -} - -bool fbtk_event(fbtk_widget_t *root, nsfb_event_t *event, int timeout) -{ - bool unused = false; /* is the event available */ - - /* ensure we have the root widget */ - root = get_root_widget(root); - - //LOG(("Reading event with timeout %d",timeout)); - - if (nsfb_event(root->u.root.fb, event, timeout) == false) - return false; - - switch (event->type) { - case NSFB_EVENT_KEY_DOWN: - case NSFB_EVENT_KEY_UP: - if ((event->value.controlcode >= NSFB_KEY_MOUSE_1) && - (event->value.controlcode <= NSFB_KEY_MOUSE_5)) { - fbtk_click(root, event); - } else { - fbtk_input(root, event); - } - break; - - case NSFB_EVENT_CONTROL: - unused = true; - break; - - case NSFB_EVENT_MOVE_RELATIVE: - fbtk_move_pointer(root, event->value.vector.x, event->value.vector.y, true); - break; - - case NSFB_EVENT_MOVE_ABSOLUTE: - fbtk_move_pointer(root, event->value.vector.x, event->value.vector.y, false); - break; - - default: - break; - - } - return unused; -} - - -nsfb_t * -fbtk_get_nsfb(fbtk_widget_t *widget) -{ - fbtk_widget_t *root; - - /* ensure we have the root widget */ - root = get_root_widget(widget); - - return root->u.root.fb; -} - -/* Initialise toolkit for use */ -fbtk_widget_t * -fbtk_init(nsfb_t *fb) -{ - fbtk_widget_t *root = new_widget(FB_WIDGET_TYPE_ROOT); - - nsfb_get_geometry(fb, &root->width, &root->height, NULL); - - LOG(("width %d height %d",root->width, root->height)); - root->u.root.fb = fb; - root->x = 0; - root->y = 0; - root->u.root.rootw = fbtk_create_window(root, 0, 0, 0, 0); - - return root; -} - -static int keymap[] = { - /* 0 1 2 3 4 5 6 7 8 9 */ - -1, -1, -1, -1, -1, -1, -1, -1, 8, 9, /* 0 - 9 */ - -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, /* 10 - 19 */ - -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, /* 20 - 29 */ - -1, -1, ' ', '!', '"', '#', '$', -1, '&','\'', /* 30 - 39 */ - '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', /* 40 - 49 */ - '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', /* 50 - 59 */ - '<', '=', '>', '?', '@', -1, -1, -1, -1, -1, /* 60 - 69 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */ - -1, '[','\\', ']', '~', '_', '`', 'a', 'b', 'c', /* 90 - 99 */ - 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', /* 100 - 109 */ - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 110 - 119 */ - 'x', 'y', 'z', -1, -1, -1, -1, -1, -1, -1, /* 120 - 129 */ -}; - -static int sh_keymap[] = { - /* 0 1 2 3 4 5 6 7 8 9 */ - -1, -1, -1, -1, -1, -1, -1, -1, 8, 9, /* 0 - 9 */ - -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, /* 10 - 19 */ - -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, /* 20 - 29 */ - -1, -1, ' ', '!', '"', '~', '$', -1, '&', '@', /* 30 - 39 */ - '(', ')', '*', '+', '<', '_', '>', '?', ')', '!', /* 40 - 49 */ - '"', 243, '$', '%', '^', '&', '*', '(', ';', ':', /* 50 - 59 */ - '<', '+', '>', '?', '@', -1, -1, -1, -1, -1, /* 60 - 69 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */ - -1, '{', '|', '}', '~', '_', 254, 'A', 'B', 'C', /* 90 - 99 */ - 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', /* 100 - 109 */ - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 110 - 119 */ - 'X', 'Y', 'Z', -1, -1, -1, -1, -1, -1, -1, /* 120 - 129 */ -}; - - -/* performs character mapping */ -int fbtk_keycode_to_ucs4(int code, uint8_t mods) -{ - int ucs4 = -1; - - if (mods) { - if ((code >= 0) && (code < (int) NOF_ELEMENTS(sh_keymap))) - ucs4 = sh_keymap[code]; - } else { - if ((code >= 0) && (code < (int) NOF_ELEMENTS(keymap))) - ucs4 = keymap[code]; - } - return ucs4; -} - -/* - * Local Variables: - * c-basic-offset:8 - * End: - */ diff --git a/framebuffer/fbtk.h b/framebuffer/fbtk.h index fd104452b..61050f46f 100644 --- a/framebuffer/fbtk.h +++ b/framebuffer/fbtk.h @@ -1,5 +1,5 @@ /* - * Copyright 2008 Vincent Sanders + * Copyright 2008,2010 Vincent Sanders * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -27,6 +27,7 @@ typedef struct fbtk_widget_s fbtk_widget_t; +/* Widget Callback handling */ typedef enum fbtk_callback_type { FBTK_CBT_START = 0, FBTK_CBT_SCROLLX, @@ -34,7 +35,10 @@ typedef enum fbtk_callback_type { FBTK_CBT_CLICK, FBTK_CBT_INPUT, FBTK_CBT_POINTERMOVE, + FBTK_CBT_POINTERLEAVE, + FBTK_CBT_POINTERENTER, FBTK_CBT_REDRAW, + FBTK_CBT_DESTROY, FBTK_CBT_USER, FBTK_CBT_END, } fbtk_callback_type; @@ -51,29 +55,212 @@ typedef struct fbtk_callback_info { typedef int (*fbtk_callback)(fbtk_widget_t *widget, fbtk_callback_info *cbi); - -/* user widget callback */ -typedef int (*fbtk_user_t)(fbtk_widget_t *widget, void *pw); - - /* enter pressed on writable icon */ typedef int (*fbtk_enter_t)(void *pw, char *text); -/* helper function to allow simple method to call callbacks */ -int fbtk_post_callback(fbtk_widget_t *widget, fbtk_callback_type cbt, ...); +/************************ Core ****************************/ -/* Widget creation */ /** Initialise widget toolkit. * - * Initialises widget toolkit and creates root window against a framebuffer. + * Initialises widget toolkit against a framebuffer. * * @param fb The underlying framebuffer. * @return The root widget handle. */ fbtk_widget_t *fbtk_init(nsfb_t *fb); +/** Retrieve the framebuffer library handle from toolkit widget. + * + * @param widget A fbtk widget. + * @return The underlying framebuffer. + */ +nsfb_t *fbtk_get_nsfb(fbtk_widget_t *widget); + +/** Perform any pending widget redraws. + * + * @param widget A fbtk widget. + */ +int fbtk_redraw(fbtk_widget_t *widget); + +/** Determine if there are any redraws pending for a widget. + * + * Mainly used by clients on the root widget to determine if they need + * to call ::fbtk_redraw + * + * @param widget to check. + */ +bool fbtk_get_redraw_pending(fbtk_widget_t *widget); + +/** clip a bounding box to a widgets area. + */ +bool fbtk_clip_to_widget(fbtk_widget_t *widget, bbox_t * restrict box); + +/** clip one bounding box to another. + */ +bool fbtk_clip_rect(const bbox_t * restrict clip, bbox_t * restrict box); + +/***************** Callback processing ********************/ + +/** Helper function to allow simple calling of callbacks with parameters. + * + * @param widget The fbtk widget to post the callback to. + * @param cbt The type of callback to post + * @param ... Parameters appropriate for the callback type. + */ +int fbtk_post_callback(fbtk_widget_t *widget, fbtk_callback_type cbt, ...); + +/** Set a callback handler. + * + * Set a callback handler and the pointer to pass for a widget. + * + * @param widget The widget to set the handler for. + * @param cbt The type of callback to set. + * @param cb The callback. + * @param pw The private pointer to pass when calling teh callback. + * @return The previous callback handler for the type or NULL. + */ +fbtk_callback fbtk_set_handler(fbtk_widget_t *widget, fbtk_callback_type cbt, fbtk_callback cb, void *pw); + +/** Get a callback handler. + */ +fbtk_callback fbtk_get_handler(fbtk_widget_t *widget, fbtk_callback_type cbt); + + +/******************* Event processing **********************/ + +/** Retrive events from the framebuffer input. + * + * Obtain events from the framebuffer input system with a + * timeout. Some events may be used by the toolkit instead of being + * returned to the caller. + * + * @param root An fbtk widget. + * @param event an event structure to update. + * @param timeout The number of miliseconds to wait for an event. 0 + * means do not wait and -1 means wait foreevr. + * @return wether \a event has been updated. + */ +bool fbtk_event(fbtk_widget_t *root, nsfb_event_t *event, int timeout); + +/** Insert mouse button press into toolkit. + */ +void fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event); + +/** Insert input into toolkit. + */ +void fbtk_input(fbtk_widget_t *widget, nsfb_event_t *event); + +/** Move pointer. + * + * Move the pointer cursor to a given location. + * + * @param widget any tookit widget. + * @parm x movement in horizontal plane. + * @parm y movement in vertical plane. + * @parm relative Wheter the /a x and /a y should be considered relative to + * current pointer position. + */ +void fbtk_warp_pointer(fbtk_widget_t *widget, int x, int y, bool relative); + +/** Toggle pointer grab. + * + * Toggles the movement grab for a widget. + * + * @param widget The widget trying to grab the movement. + * @return true if the grab was ok, false if the grab failed (already grabbed). + */ +bool fbtk_tgrab_pointer(fbtk_widget_t *widget); + +/** Convert a framebuffer keycode to ucs4. + * + * Character mapping between keycode with modifier state and ucs-4. + */ +int fbtk_keycode_to_ucs4(int code, uint8_t mods); + + +/******************* Widget Information **********************/ + +/** Obtain the widget at a point on screen. + * + * @param widget any tookit widget. + * @parm x location in horizontal plane. + * @parm y location in vertical plane. + * @return widget or NULL. + */ +fbtk_widget_t *fbtk_get_widget_at(fbtk_widget_t *widget, int x, int y); + +/** Get a widget's absolute horizontal screen co-ordinate. + * + * @param widget The widget to inspect. + * @return The absolute screen co-ordinate. + */ +int fbtk_get_absx(fbtk_widget_t *widget); + +/** Get a widget's absolute vertical screen co-ordinate. + * + * @param widget The widget to inspect. + * @return The absolute screen co-ordinate. + */ +int fbtk_get_absy(fbtk_widget_t *widget); + +/** Get a widget's width. + * + * @param widget The widget to inspect. + * @return The widget width. + */ +int fbtk_get_width(fbtk_widget_t *widget); + +/** Get a widget's height. + * + * @param widget The widget to inspect. + * @return The widget height. + */ +int fbtk_get_height(fbtk_widget_t *widget); + +/** Get a widget's bounding box in absolute screen co-ordinates. + * + * @param widget The widget to inspect. + * @param bbox The bounding box structure to update. + * @return If the \a bbox parameter has been updated. + */ +bool fbtk_get_bbox(fbtk_widget_t *widget, struct nsfb_bbox_s *bbox); + + +/******************* Widget Manipulation **********************/ + +/** Change the widget's position and size. + * + */ +bool fbtk_set_pos_and_size(fbtk_widget_t *widget, int x, int y, int width, int height); + +/** Map a widget and request it is redrawn. + */ +int fbtk_set_mapping(fbtk_widget_t *widget, bool mapped); + +/** Set the z order of a widget. + */ +int fbtk_set_zorder(fbtk_widget_t *widget, int z); + +/** Indicate a widget should be redrawn. + */ +void fbtk_request_redraw(fbtk_widget_t *widget); + +/** Destroy a widget and all its descendants. + * + * Removes a widget from the hierachy and frees it and all its children. + * + * @param widget The widget to destroy. + * @return 0 on success or -1 on error. + */ +int fbtk_destroy_widget(fbtk_widget_t *widget); + + + +/********************************* Widgets *********************************/ + + /** Create a window widget. * * @param parent The parent window or the root widget for a top level window. @@ -88,23 +275,9 @@ fbtk_widget_t *fbtk_init(nsfb_t *fb); * @param c The background colour. * @return new window widget handle or NULL on error. */ -fbtk_widget_t *fbtk_create_window(fbtk_widget_t *parent, int x, int y, int width, int height); +fbtk_widget_t *fbtk_create_window(fbtk_widget_t *parent, int x, int y, int width, int height, colour bg); -/** Create a text widget. - * - * @param window The window to add the text widget to. - * @return new widget handle or NULL on error. - */ -fbtk_widget_t *fbtk_create_text(fbtk_widget_t *window, int x, int y, int width, int height, colour bg, colour fg, bool outline); -/** Create a bitmap widget. - * - * Create a widget which shows a bitmap. - * - * @param window The window to add the bitmap widget to. - * @return new widget handle or NULL on error. - */ -fbtk_widget_t *fbtk_create_bitmap(fbtk_widget_t *window, int x, int y, colour c,struct bitmap *image); /** Create a filled rectangle * @@ -116,6 +289,9 @@ fbtk_widget_t *fbtk_create_bitmap(fbtk_widget_t *window, int x, int y, colour c, fbtk_widget_t * fbtk_create_fill(fbtk_widget_t *window, int x, int y, int width, int height, colour c); + + + /** Create a horizontal scroll widget * * Create a horizontal scroll widget. @@ -136,6 +312,14 @@ fbtk_create_hscroll(fbtk_widget_t *window, int x, int y, int width, int height, fbtk_widget_t * fbtk_create_vscroll(fbtk_widget_t *window, int x, int y, int width, int height, colour fg, colour bg, fbtk_callback callback, void *context); +bool fbtk_set_scroll_parameters(fbtk_widget_t *widget, int min, int max, int thumb, int page); + +bool fbtk_set_scroll_position(fbtk_widget_t *widget, int pos); + + + + + /** Create a user widget. * * Create a widget which is to be handled entirely by the calling application. @@ -146,6 +330,20 @@ fbtk_create_vscroll(fbtk_widget_t *window, int x, int y, int width, int height, */ fbtk_widget_t *fbtk_create_user(fbtk_widget_t *window, int x, int y, int width, int height, void *pw); +void *fbtk_get_userpw(fbtk_widget_t *widget); + + + +/** Create a bitmap widget. + * + * Create a widget which shows a bitmap. + * + * @param window The window to add the bitmap widget to. + * @return new widget handle or NULL on error. + */ +fbtk_widget_t *fbtk_create_bitmap(fbtk_widget_t *window, int x, int y, int width, int height, colour c,struct bitmap *image); + +void fbtk_set_bitmap(fbtk_widget_t *widget, struct bitmap *image); /** Create a button widget. * @@ -155,7 +353,25 @@ fbtk_widget_t *fbtk_create_user(fbtk_widget_t *window, int x, int y, int width, * @param window The window to add the button widget to. * @return new widget handle or NULL on error. */ -fbtk_widget_t *fbtk_create_button(fbtk_widget_t *window, int x, int y, colour c, struct bitmap *image, fbtk_callback click, void *pw); +fbtk_widget_t *fbtk_create_button(fbtk_widget_t *window, int x, int y, int width, int height, colour c, struct bitmap *image, fbtk_callback click, void *pw); + + + + + +/** Create a text widget. + * + * @param window The window to add the text widget to. + * @return new widget handle or NULL on error. + */ +fbtk_widget_t *fbtk_create_text(fbtk_widget_t *window, int x, int y, int width, int height, colour bg, colour fg, bool outline); + +/** Create a button with text. + * + * @param window The window to add the text widget to. + * @return new widget handle or NULL on error. + */ +fbtk_widget_t *fbtk_create_text_button(fbtk_widget_t *window, int x, int y, int width, int height, colour bg, colour fg, fbtk_callback click, void *pw); /** Create a writable text widget. * @@ -168,94 +384,28 @@ fbtk_widget_t *fbtk_create_button(fbtk_widget_t *window, int x, int y, colour c, */ fbtk_widget_t *fbtk_create_writable_text(fbtk_widget_t *window, int x, int y, int width, int height, colour bg, colour fg, bool outline, fbtk_enter_t enter, void *pw); - -/* Widget Destruction */ - -/** Destroy and free a widget and all its children. - * - * @param widget The widget to destroy. - * @return 0 on success or -1 on error. - */ -int fbtk_destroy_widget(fbtk_widget_t *widget); - -/* Widget information */ - -int fbtk_get_y(fbtk_widget_t *widget); -int fbtk_get_x(fbtk_widget_t *widget); -int fbtk_get_width(fbtk_widget_t *widget); -int fbtk_get_height(fbtk_widget_t *widget); -void *fbtk_get_userpw(fbtk_widget_t *widget); -nsfb_t *fbtk_get_nsfb(fbtk_widget_t *widget); - -/* Set widget properties */ - -void fbtk_set_text(fbtk_widget_t *widget, const char *text); -void fbtk_set_bitmap(fbtk_widget_t *widget, struct bitmap *image); -void fbtk_set_scroll(fbtk_widget_t *widget, int pct); -void fbtk_set_scroll_pos(fbtk_widget_t *widget, int pos); -void fbtk_set_pos_and_size(fbtk_widget_t *widget, int x, int y, int width, int height); -; - -/** Set a callback handler */ -fbtk_callback fbtk_set_handler(fbtk_widget_t *widget, fbtk_callback_type cbt, fbtk_callback cb, void *pw); - -/** Get a callback handler */ -fbtk_callback fbtk_get_handler(fbtk_widget_t *widget, fbtk_callback_type cbt); - /** Alter a text widget to be writable. + * + * @param widget Text widget. + * @param enter The routine to call when enter is pressed. + * @param pw The context to pass to teh enter callback routine. */ void fbtk_writable_text(fbtk_widget_t *widget, fbtk_enter_t enter, void *pw); - -/* General routines */ - -bool fbtk_clip_rect(const bbox_t * restrict clip, bbox_t * restrict box); - -/** Pointer movement. - * - * Pointer has been moved. +/** Change the text of a text widget. * - * @param widget any tookit widget. - * @parm x movement in horizontal plane. - * @parm y movement in vertical plane. - * @parm relative Wether the /a x and /a y should be considered relative to - * current pointer position. - */ -void fbtk_move_pointer(fbtk_widget_t *widget, int x, int y, bool relative); - -/** Mouse has been clicked - */ -void fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event); - -/** Input has been recived + * @param widget Text widget. + * @param text The new UTF-8 text to put in the widget. */ -void fbtk_input(fbtk_widget_t *widget, nsfb_event_t *event); - -/** Indicate a widget has to be redrawn - */ -void fbtk_request_redraw(fbtk_widget_t *widget); - -/** Cause a redraw to happen. - */ -int fbtk_redraw(fbtk_widget_t *widget); +void fbtk_set_text(fbtk_widget_t *widget, const char *text); -bool fbtk_redraw_pending(fbtk_widget_t *widget); -int fbtk_count_children(fbtk_widget_t *widget); -bool fbtk_get_bbox(fbtk_widget_t *widget, struct nsfb_bbox_s *bbox); -bool fbtk_event(fbtk_widget_t *root, nsfb_event_t *event, int timeout); +/** enable the on screen keyboard for input */ +void fbtk_enable_oskb(fbtk_widget_t *widget); -/* keycode to ucs4 */ -int fbtk_keycode_to_ucs4(int code, uint8_t mods); - -/* clip a box to a widgets area */ -bool fbtk_clip_to_widget(fbtk_widget_t *widget, bbox_t * restrict box); +/** show the osk. */ +void map_osk(void); #endif - - - - - diff --git a/framebuffer/fbtk/bitmap.c b/framebuffer/fbtk/bitmap.c new file mode 100644 index 000000000..af2311287 --- /dev/null +++ b/framebuffer/fbtk/bitmap.c @@ -0,0 +1,137 @@ +/* + * Copyright 2010 Vincent Sanders + * + * Framebuffer windowing toolkit bitmaped image widget + * + * 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 . + */ + +#include +#include + +#include +#include + +#include "desktop/browser.h" + +#include "framebuffer/gui.h" +#include "framebuffer/fbtk.h" +#include "framebuffer/bitmap.h" +#include "framebuffer/image_data.h" + +#include "widget.h" + +static int +fb_redraw_bitmap(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + nsfb_bbox_t bbox; + nsfb_bbox_t rect; + nsfb_t *nsfb; + + nsfb = fbtk_get_nsfb(widget); + + fbtk_get_bbox(widget, &bbox); + + rect = bbox; + + nsfb_claim(nsfb, &bbox); + + /* clear background */ + if ((widget->bg & 0xFF000000) != 0) { + /* transparent polygon filling isnt working so fake it */ + nsfb_plot_rectangle_fill(nsfb, &bbox, widget->bg); + } + + /* plot the image */ + nsfb_plot_bitmap(nsfb, + &rect, + (nsfb_colour_t *)widget->u.bitmap.bitmap->pixdata, + widget->u.bitmap.bitmap->width, + widget->u.bitmap.bitmap->height, + widget->u.bitmap.bitmap->width, + !widget->u.bitmap.bitmap->opaque); + + nsfb_update(nsfb, &bbox); + + return 0; +} + +/* exported function documented in fbtk.h */ +void +fbtk_set_bitmap(fbtk_widget_t *widget, struct bitmap *image) +{ + if ((widget == NULL) || (widget->type != FB_WIDGET_TYPE_BITMAP)) + return; + + widget->u.bitmap.bitmap = image; + + fbtk_request_redraw(widget); +} + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_bitmap(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + colour c, + struct bitmap *image) +{ + fbtk_widget_t *neww; + + neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_BITMAP, x, y, width, height); + + neww->bg = c; + neww->mapped = true; + neww->u.bitmap.bitmap = image; + + fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_bitmap, NULL); + + return neww; +} + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_button(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + colour c, + struct bitmap *image, + fbtk_callback click, + void *pw) +{ + fbtk_widget_t *neww; + + neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_BITMAP, x, y, width, height); + + neww->bg = c; + neww->mapped = true; + neww->u.bitmap.bitmap = image; + + fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_bitmap, NULL); + fbtk_set_handler(neww, FBTK_CBT_CLICK, click, pw); + fbtk_set_handler(neww, FBTK_CBT_POINTERENTER, fbtk_set_ptr, &hand_image); + + return neww; +} + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk/event.c b/framebuffer/fbtk/event.c new file mode 100644 index 000000000..c1ddaeeb0 --- /dev/null +++ b/framebuffer/fbtk/event.c @@ -0,0 +1,273 @@ +/* + * Copyright 2010 Vincent Sanders + * + * Framebuffer windowing toolkit event processing. + * + * 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 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "utils/utils.h" +#include "utils/log.h" +#include "css/css.h" +#include "desktop/browser.h" +#include "desktop/plotters.h" + +#include "framebuffer/gui.h" +#include "framebuffer/fbtk.h" +#include "framebuffer/bitmap.h" +#include "framebuffer/image_data.h" + +#include "widget.h" + +/* exported function documented in fbtk.h */ +void +fbtk_input(fbtk_widget_t *root, nsfb_event_t *event) +{ + fbtk_widget_t *input; + + root = fbtk_get_root_widget(root); + + /* obtain widget with input focus */ + input = root->u.root.input; + if (input == NULL) + return; /* no widget with input */ + + fbtk_post_callback(input, FBTK_CBT_INPUT, event); +} + +/* exported function documented in fbtk.h */ +void +fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event) +{ + fbtk_widget_t *root; + fbtk_widget_t *clicked; + nsfb_bbox_t cloc; + int x, y; + + /* ensure we have the root widget */ + root = fbtk_get_root_widget(widget); + + nsfb_cursor_loc_get(root->u.root.fb, &cloc); + + clicked = fbtk_get_widget_at(root, cloc.x0, cloc.y0); + + if (clicked == NULL) + return; + + if (fbtk_get_handler(clicked, FBTK_CBT_INPUT) != NULL) { + root->u.root.input = clicked; + } + + x = fbtk_get_absx(clicked); + y = fbtk_get_absy(clicked); + + LOG(("clicked %p at %d,%d", clicked, x, y)); + + /* post the click */ + fbtk_post_callback(clicked, FBTK_CBT_CLICK, event, cloc.x0 - x, cloc.y0 - y); +} + +/* exported function documented in fbtk.h */ +bool +fbtk_tgrab_pointer(fbtk_widget_t *widget) +{ + fbtk_widget_t *root; + + /* ensure we have the root widget */ + root = fbtk_get_root_widget(widget); + + if (root->u.root.grabbed == widget) { + /* release pointer grab */ + root->u.root.grabbed = NULL; + return true; + } else if (root->u.root.grabbed == NULL) { + /* set pointer grab */ + root->u.root.grabbed = widget; + return true; + } + /* pointer was already grabbed */ + return false; +} + +/* exported function documented in fbtk.h */ +void +fbtk_warp_pointer(fbtk_widget_t *widget, int x, int y, bool relative) +{ + fbtk_widget_t *root; + fbtk_widget_t *moved; + nsfb_bbox_t cloc; + + /* ensure we have the root widget */ + root = fbtk_get_root_widget(widget); + + if (relative) { + nsfb_cursor_loc_get(root->u.root.fb, &cloc); + cloc.x0 += x; + cloc.y0 += y; + } else { + cloc.x0 = x; + cloc.y0 = y; + } + + if (root->u.root.grabbed == NULL) { + /* update the pointer cursor */ + nsfb_cursor_loc_set(root->u.root.fb, &cloc); + + moved = fbtk_get_widget_at(root, cloc.x0, cloc.y0); + + x = fbtk_get_absx(moved); + y = fbtk_get_absy(moved); + + /* post enter and leaving messages */ + if (moved != root->u.root.prev) { + fbtk_post_callback(root->u.root.prev, FBTK_CBT_POINTERLEAVE); + root->u.root.prev = moved; + fbtk_post_callback(root->u.root.prev, FBTK_CBT_POINTERENTER); + } + } else { + /* pointer movement has been grabbed by a widget */ + moved = root->u.root.grabbed; + + /* ensure pointer remains within widget boundary */ + x = fbtk_get_absx(moved); + y = fbtk_get_absy(moved); + + if (cloc.x0 < x) + cloc.x0 = x; + if (cloc.y0 < y) + cloc.y0 = y; + if (cloc.x0 > (x + moved->width)) + cloc.x0 = (x + moved->width); + if (cloc.y0 > (y + moved->height)) + cloc.y0 = (y + moved->height); + + /* update the pointer cursor */ + nsfb_cursor_loc_set(root->u.root.fb, &cloc); + } + + /* post the movement */ + fbtk_post_callback(moved, FBTK_CBT_POINTERMOVE, cloc.x0 - x, cloc.y0 - y); + +} + +/* exported function documented in fbtk.h */ +bool +fbtk_event(fbtk_widget_t *root, nsfb_event_t *event, int timeout) +{ + bool unused = false; /* is the event available */ + + /* ensure we have the root widget */ + root = fbtk_get_root_widget(root); + + if (nsfb_event(root->u.root.fb, event, timeout) == false) + return false; + + switch (event->type) { + case NSFB_EVENT_KEY_DOWN: + case NSFB_EVENT_KEY_UP: + if ((event->value.controlcode >= NSFB_KEY_MOUSE_1) && + (event->value.controlcode <= NSFB_KEY_MOUSE_5)) { + fbtk_click(root, event); + } else { + fbtk_input(root, event); + } + break; + + case NSFB_EVENT_CONTROL: + unused = true; + break; + + case NSFB_EVENT_MOVE_RELATIVE: + fbtk_warp_pointer(root, event->value.vector.x, event->value.vector.y, true); + break; + + case NSFB_EVENT_MOVE_ABSOLUTE: + fbtk_warp_pointer(root, event->value.vector.x, event->value.vector.y, false); + break; + + default: + break; + + } + return unused; +} + +static int keymap[] = { + /* 0 1 2 3 4 5 6 7 8 9 */ + -1, -1, -1, -1, -1, -1, -1, -1, 8, 9, /* 0 - 9 */ + -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, /* 10 - 19 */ + -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, /* 20 - 29 */ + -1, -1, ' ', '!', '"', '#', '$', -1, '&','\'', /* 30 - 39 */ + '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', /* 40 - 49 */ + '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', /* 50 - 59 */ + '<', '=', '>', '?', '@', -1, -1, -1, -1, -1, /* 60 - 69 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */ + -1, '[','\\', ']', '~', '_', '`', 'a', 'b', 'c', /* 90 - 99 */ + 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', /* 100 - 109 */ + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 110 - 119 */ + 'x', 'y', 'z', -1, -1, -1, -1, -1, -1, -1, /* 120 - 129 */ +}; + +static int sh_keymap[] = { + /* 0 1 2 3 4 5 6 7 8 9 */ + -1, -1, -1, -1, -1, -1, -1, -1, 8, 9, /* 0 - 9 */ + -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, /* 10 - 19 */ + -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, /* 20 - 29 */ + -1, -1, ' ', '!', '"', '~', '$', -1, '&', '@', /* 30 - 39 */ + '(', ')', '*', '+', '<', '_', '>', '?', ')', '!', /* 40 - 49 */ + '"', 243, '$', '%', '^', '&', '*', '(', ';', ':', /* 50 - 59 */ + '<', '+', '>', '?', '@', -1, -1, -1, -1, -1, /* 60 - 69 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */ + -1, '{', '|', '}', '~', '_', 254, 'A', 'B', 'C', /* 90 - 99 */ + 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', /* 100 - 109 */ + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 110 - 119 */ + 'X', 'Y', 'Z', -1, -1, -1, -1, -1, -1, -1, /* 120 - 129 */ +}; + + +/* exported function documented in fbtk.h */ +int +fbtk_keycode_to_ucs4(int code, uint8_t mods) +{ + int ucs4 = -1; + + if (mods) { + if ((code >= 0) && (code < (int) NOF_ELEMENTS(sh_keymap))) + ucs4 = sh_keymap[code]; + } else { + if ((code >= 0) && (code < (int) NOF_ELEMENTS(keymap))) + ucs4 = keymap[code]; + } + return ucs4; +} + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk/fbtk.c b/framebuffer/fbtk/fbtk.c new file mode 100644 index 000000000..f8b3d850c --- /dev/null +++ b/framebuffer/fbtk/fbtk.c @@ -0,0 +1,726 @@ +/* + * Copyright 2008,2010 Vincent Sanders + * + * 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 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "utils/utils.h" +#include "utils/log.h" +#include "css/css.h" +#include "desktop/browser.h" +#include "desktop/plotters.h" + +#include "framebuffer/gui.h" +#include "framebuffer/fbtk.h" +#include "framebuffer/bitmap.h" +#include "framebuffer/image_data.h" + +#include "widget.h" + +/* 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; + } + } + } +} + +/* exported function documented in fbtk.h */ +void +fbtk_request_redraw(fbtk_widget_t *widget) +{ + fbtk_widget_t *cwidget; + fbtk_widget_t *pwidget; + + /* 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; + + LOG(("redrawing %p %d,%d %d,%d", + widget, + widget->redraw.x, + widget->redraw.y, + widget->redraw.width, + widget->redraw.height)); + + 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; /* the widget to swap lw with */ + fbtk_widget_t *before; + fbtk_widget_t *after; + + rw = lw->next; + 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->x != x) || + (widget->y != y) || + (widget->width != width) || + (widget->height != height)) { + widget->x = x; + widget->y = y; + widget->width = width; + widget->height = height; + /* @todo This should limit the redrawn area to the sum + * of the old and new widget dimensions, not redraw the lot. + */ + fbtk_request_redraw(widget->parent); + return true; + } + return false; +} + +/* 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 bitmap *bm = cbi->context; + + nsfb_cursor_set(root->u.root.fb, + (nsfb_colour_t *)bm->pixdata, + bm->width, + bm->height, + bm->width); + + 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; +} + +/* 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; + + LOG(("creating %p %d,%d %d,%d", neww, x, y, width, height)); + + /* 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; + } + + + LOG(("using %p %d,%d %d,%d", neww, x, y, width, height)); + /* 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; + + LOG(("clipping %p %d,%d %d,%d", + widget, plot_ctx.x0, plot_ctx.y0, + plot_ctx.x1, plot_ctx.y1)); + 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; + + default: + break; + } + va_end(ap); + + ret = (widget->callback[cbt])(widget, &cbi); + } + + return ret; +} + + + +/* 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; + + nsfb_get_geometry(fb, &root->width, &root->height, NULL); + + root->mapped = true; + + return root; +} + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk/fill.c b/framebuffer/fbtk/fill.c new file mode 100644 index 000000000..ce16b5bcf --- /dev/null +++ b/framebuffer/fbtk/fill.c @@ -0,0 +1,81 @@ +/* + * Copyright 2010 Vincent Sanders + * + * Framebuffer windowing toolkit filled area widget + * + * 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 . + */ + +#include +#include + +#include +#include + +#include "desktop/browser.h" + +#include "framebuffer/gui.h" +#include "framebuffer/fbtk.h" + +#include "widget.h" + +static int +fb_redraw_fill(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + nsfb_bbox_t bbox; + nsfb_t *nsfb; + + nsfb = fbtk_get_nsfb(widget); + + fbtk_get_bbox(widget, &bbox); + + nsfb_claim(nsfb, &bbox); + + /* clear background */ + if ((widget->bg & 0xFF000000) != 0) { + /* transparent polygon filling isnt working so fake it */ + nsfb_plot_rectangle_fill(nsfb, &bbox, widget->bg); + } + + nsfb_update(nsfb, &bbox); + + return 0; +} + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_fill(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + colour c) +{ + fbtk_widget_t *neww; + + neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_FILL, x, y, width, height); + neww->bg = c; + neww->mapped = true; + + fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_fill, NULL); + + return neww; +} + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk/osk.c b/framebuffer/fbtk/osk.c new file mode 100644 index 000000000..36fb765d3 --- /dev/null +++ b/framebuffer/fbtk/osk.c @@ -0,0 +1,202 @@ +/* + * Copyright 2010 Vincent Sanders + * + * Framebuffer windowing toolkit on screen keyboard. + * + * 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 . + */ + +#include +#include + +#include +#include +#include +#include + +#include "utils/log.h" +#include "desktop/browser.h" + +#include "framebuffer/gui.h" +#include "framebuffer/fbtk.h" +#include "framebuffer/bitmap.h" +#include "framebuffer/image_data.h" + +#include "widget.h" + +struct kbd_button_s { + int x; + int y; + int w; + int h; + const char *t; + enum nsfb_key_code_e keycode; +}; + +#define KEYCOUNT 58 + +static struct kbd_button_s kbdbase[KEYCOUNT] = { + { 0, 0, 20, 15, "`", NSFB_KEY_BACKQUOTE}, + { 20, 0, 20, 15, "1", NSFB_KEY_1}, + { 40, 0, 20, 15, "2", NSFB_KEY_2}, + { 60, 0, 20, 15, "3", NSFB_KEY_3}, + { 80, 0, 20, 15, "4", NSFB_KEY_4}, + { 100, 0, 20, 15, "5", NSFB_KEY_5}, + { 120, 0, 20, 15, "6", NSFB_KEY_6}, + { 140, 0, 20, 15, "7", NSFB_KEY_7}, + { 160, 0, 20, 15, "8", NSFB_KEY_8}, + { 180, 0, 20, 15, "9", NSFB_KEY_9}, + { 200, 0, 20, 15, "0", NSFB_KEY_0}, + { 220, 0, 20, 15, "-", NSFB_KEY_MINUS}, + { 240, 0, 20, 15, "=", NSFB_KEY_EQUALS}, + { 260, 0, 40, 15, "\xe2\x8c\xab", NSFB_KEY_BACKSPACE}, + { 0, 15, 30, 15, "\xe2\x86\xb9", NSFB_KEY_TAB}, + { 30, 15, 20, 15, "q", NSFB_KEY_q}, + { 50, 15, 20, 15, "w", NSFB_KEY_w}, + { 70, 15, 20, 15, "e", NSFB_KEY_e}, + { 90, 15, 20, 15, "r", NSFB_KEY_r}, + { 110, 15, 20, 15, "t", NSFB_KEY_t}, + { 130, 15, 20, 15, "y", NSFB_KEY_y}, + { 150, 15, 20, 15, "u", NSFB_KEY_u}, + { 170, 15, 20, 15, "i", NSFB_KEY_i}, + { 190, 15, 20, 15, "o", NSFB_KEY_o}, + { 210, 15, 20, 15, "p", NSFB_KEY_p}, + { 230, 15, 20, 15, "[", NSFB_KEY_LEFTBRACKET}, + { 250, 15, 20, 15, "]", NSFB_KEY_RIGHTBRACKET}, + { 275, 15, 25, 30, "\xe2\x8f\x8e", NSFB_KEY_RETURN}, + { 35, 30, 20, 15, "a", NSFB_KEY_a}, + { 55, 30, 20, 15, "s", NSFB_KEY_s}, + { 75, 30, 20, 15, "d", NSFB_KEY_d}, + { 95, 30, 20, 15, "f", NSFB_KEY_f}, + { 115, 30, 20, 15, "g", NSFB_KEY_g}, + { 135, 30, 20, 15, "h", NSFB_KEY_h}, + { 155, 30, 20, 15, "j", NSFB_KEY_j}, + { 175, 30, 20, 15, "k", NSFB_KEY_k}, + { 195, 30, 20, 15, "l", NSFB_KEY_l}, + { 215, 30, 20, 15, ";", NSFB_KEY_SEMICOLON}, + { 235, 30, 20, 15, "'", NSFB_KEY_l}, + { 255, 30, 20, 15, "#", NSFB_KEY_HASH}, + { 0, 45, 25, 15, "\xe2\x87\xa7", NSFB_KEY_LSHIFT}, + { 25, 45, 20, 15, "\\", NSFB_KEY_SLASH}, + { 45, 45, 20, 15, "z", NSFB_KEY_z}, + { 65, 45, 20, 15, "x", NSFB_KEY_x}, + { 85, 45, 20, 15, "c", NSFB_KEY_c}, + { 105, 45, 20, 15, "v", NSFB_KEY_v}, + { 125, 45, 20, 15, "b", NSFB_KEY_b}, + { 145, 45, 20, 15, "n", NSFB_KEY_n}, + { 165, 45, 20, 15, "m", NSFB_KEY_m}, + { 185, 45, 20, 15, ",", NSFB_KEY_COMMA}, + { 205, 45, 20, 15, ".", NSFB_KEY_PERIOD}, + { 225, 45, 20, 15, "/", NSFB_KEY_BACKSLASH}, + { 245, 45, 55, 15, "\xe2\x87\xa7", NSFB_KEY_RSHIFT}, + { 40, 67, 185, 15, "", NSFB_KEY_SPACE}, + { 250, 60, 20, 15, "\xe2\x96\xb2", NSFB_KEY_UP}, + { 230, 67, 20, 15, "\xe2\x97\x80", NSFB_KEY_LEFT}, + { 270, 67, 20, 15, "\xe2\x96\xb6", NSFB_KEY_RIGHT}, + { 250, 75, 20, 15, "\xe2\x96\xbc", NSFB_KEY_DOWN}, +}; + +static fbtk_widget_t *osk; + +static int +osk_close(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; + + fbtk_set_mapping(osk, false); + + return 0; +} + +static int +osk_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + nsfb_event_t event; + struct kbd_button_s *kbd_button = cbi->context; + + event.type = cbi->event->type; + event.value.keycode = kbd_button->keycode; + fbtk_input(widget, &event); + + return 0; +} + +/* exported function documented in fbtk.h */ +void +fbtk_enable_oskb(fbtk_widget_t *fbtk) +{ + fbtk_widget_t *widget; + int kloop; + int maxx = 0; + int maxy = 0; + int ww; + int wh; + fbtk_widget_t *root = fbtk_get_root_widget(fbtk); + int furniture_width = 18; + + for (kloop=0; kloop < KEYCOUNT; kloop++) { + if ((kbdbase[kloop].x + kbdbase[kloop].w) > maxx) + maxx=kbdbase[kloop].x + kbdbase[kloop].w; + if ((kbdbase[kloop].y + kbdbase[kloop].h) > maxy) + maxy=kbdbase[kloop].y + kbdbase[kloop].h; + } + + ww = fbtk_get_width(root); + + /* scale window height apropriately */ + wh = (maxy * ww) / maxx; + + osk = fbtk_create_window(root, 0, fbtk_get_height(root) - wh, 0, wh, 0xff202020); + + for (kloop=0; kloop < KEYCOUNT; kloop++) { + widget = fbtk_create_text_button(osk, + (kbdbase[kloop].x * ww) / maxx, + (kbdbase[kloop].y * ww) / maxx, + (kbdbase[kloop].w * ww) / maxx, + (kbdbase[kloop].h *ww) / maxx, + FB_FRAME_COLOUR, + FB_COLOUR_BLACK, + osk_click, + &kbdbase[kloop]); + fbtk_set_text(widget, kbdbase[kloop].t); + } + + widget = fbtk_create_text_button(osk, + fbtk_get_width(osk) - furniture_width, + fbtk_get_height(osk) - furniture_width, + furniture_width, + furniture_width, + FB_FRAME_COLOUR, + FB_COLOUR_BLACK, + osk_close, + NULL); + fbtk_set_text(widget, "\xe2\x8c\xa8"); + +} + +/* exported function documented in fbtk.h */ +void +map_osk(void) +{ + fbtk_set_zorder(osk, INT_MIN); + fbtk_set_mapping(osk, true); +} + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk/scroll.c b/framebuffer/fbtk/scroll.c new file mode 100644 index 000000000..356fd11c7 --- /dev/null +++ b/framebuffer/fbtk/scroll.c @@ -0,0 +1,543 @@ +/* + * Copyright 2010 Vincent Sanders + * + * Framebuffer windowing toolkit scrollbar widgets + * + * 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 . + */ + +#include + +#include +#include +#include +#include + +#include "utils/log.h" +#include "desktop/browser.h" + +#include "framebuffer/gui.h" +#include "framebuffer/fbtk.h" +#include "framebuffer/bitmap.h" +#include "framebuffer/image_data.h" + +#include "widget.h" + +/* Vertical scroll widget */ + +static int +vscroll_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int vscroll; + int vpos; + + nsfb_bbox_t bbox; + nsfb_bbox_t rect; + fbtk_widget_t *root = fbtk_get_root_widget(widget); + + fbtk_get_bbox(widget, &bbox); + + nsfb_claim(root->u.root.fb, &bbox); + + rect = bbox; + + /* background */ + nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg); + + /* scroll well */ + rect.x0 = bbox.x0 + 2; + rect.y0 = bbox.y0 + 1; + rect.x1 = bbox.x1 - 3; + rect.y1 = bbox.y1 - 2; + + nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->fg); + nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0xFF999999, false, false); + + /* scroll bar */ + if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) { + vscroll = ((widget->height - 4) * widget->u.scroll.thumb) / + (widget->u.scroll.maximum - widget->u.scroll.minimum) ; + vpos = ((widget->height - 4) * widget->u.scroll.position) / + (widget->u.scroll.maximum - widget->u.scroll.minimum) ; + } else { + vscroll = (widget->height - 4); + vpos = 0; + } + + rect.x0 = bbox.x0 + 5; + rect.y0 = bbox.y0 + 3 + vpos; + rect.x1 = bbox.x0 + widget->width - 5; + rect.y1 = bbox.y0 + vscroll + vpos; + + nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg); + + nsfb_update(root->u.root.fb, &bbox); + + return 0; +} + +static int +vscroll_drag(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int newpos; + fbtk_widget_t *scrollw = cbi->context; + + newpos = ((widget->u.scroll.maximum - widget->u.scroll.minimum) / + (widget->height - 4)) * (cbi->y - widget->u.scroll.drag); + + if (newpos < scrollw->u.scroll.minimum) + newpos = scrollw->u.scroll.minimum; + + if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb )) + newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb); + + if (newpos == scrollw->u.scroll.position) + return 0; + + return fbtk_post_callback(widget, FBTK_CBT_SCROLLY, newpos); +} + +static int +vscrollu_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int newpos; + fbtk_widget_t *scrollw = cbi->context; + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; + + newpos = scrollw->u.scroll.position - scrollw->u.scroll.page; + if (newpos < scrollw->u.scroll.minimum) + newpos = scrollw->u.scroll.minimum; + + if (newpos == scrollw->u.scroll.position) + return 0; + + return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLY, newpos); +} + +static int +vscrolld_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int newpos; + fbtk_widget_t *scrollw = cbi->context; + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; + + newpos = scrollw->u.scroll.position + scrollw->u.scroll.page; + if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb )) + newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb); + + if (newpos == scrollw->u.scroll.position) + return 0; + + return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLY, newpos); +} + +static int +vscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int vscroll; + int vpos; + int newpos; + int ret = 0; + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) { + /* end all drags, just in case */ + if (fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, NULL, NULL) != NULL) + fbtk_tgrab_pointer(widget); + return 0; + } + + switch (cbi->event->value.keycode) { + + case NSFB_KEY_MOUSE_4: + /* scroll up */ + newpos = widget->u.scroll.position - widget->u.scroll.page; + if (newpos < widget->u.scroll.minimum) + newpos = widget->u.scroll.minimum; + ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos); + break; + + case NSFB_KEY_MOUSE_5: + /* scroll down */ + newpos = widget->u.scroll.position + widget->u.scroll.page; + if (newpos > widget->u.scroll.maximum) + newpos = widget->u.scroll.maximum; + ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos); + break; + + default: + + if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) { + vscroll = ((widget->height - 4) * widget->u.scroll.thumb) / + (widget->u.scroll.maximum - widget->u.scroll.minimum) ; + vpos = ((widget->height - 4) * widget->u.scroll.position) / + (widget->u.scroll.maximum - widget->u.scroll.minimum) ; + } else { + vscroll = (widget->height - 4); + vpos = 0; + } + + if (cbi->y < vpos) { + /* above bar */ + newpos = widget->u.scroll.position - widget->u.scroll.thumb; + if (newpos < widget->u.scroll.minimum) + newpos = widget->u.scroll.minimum; + ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos); + } else if (cbi->y > (vpos + vscroll)) { + /* below bar */ + newpos = widget->u.scroll.position + widget->u.scroll.thumb; + if (newpos > widget->u.scroll.maximum) + newpos = widget->u.scroll.maximum; + ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, newpos); + } else { + /* on bar - start drag */ + widget->u.scroll.drag = cbi->y - vpos; + fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, vscroll_drag, widget); + fbtk_tgrab_pointer(widget); + } + } + return ret; +} + + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_vscroll(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + colour fg, + colour bg, + fbtk_callback callback, + void *context) +{ + fbtk_widget_t *neww; + + neww = fbtk_widget_new(parent, + FB_WIDGET_TYPE_VSCROLL, + x, + y + scrollu.height, + width, + height - scrollu.height - scrolld.height); + + neww->fg = fg; + neww->bg = bg; + neww->mapped = true; + + fbtk_set_handler(neww, FBTK_CBT_REDRAW, vscroll_redraw, NULL); + + fbtk_set_handler(neww, FBTK_CBT_CLICK, vscrollarea_click, neww); + + fbtk_set_handler(neww, FBTK_CBT_SCROLLY, callback, context); + + neww->u.scroll.btnul = fbtk_create_button(parent, + x, + y, + width, + scrollu.height, + fg, + &scrollu, + vscrollu_click, + neww); + + neww->u.scroll.btndr = fbtk_create_button(parent, + x, + y + height - scrolld.height, + width, + scrolld.height, + fg, + &scrolld, + vscrolld_click, + neww); + + + return neww; +} + +/* Horizontal scroll widget */ + +static int +hscroll_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int hscroll; + int hpos; + nsfb_bbox_t bbox; + nsfb_bbox_t rect; + fbtk_widget_t *root = fbtk_get_root_widget(widget); + + fbtk_get_bbox(widget, &bbox); + + nsfb_claim(root->u.root.fb, &bbox); + + rect = bbox; + + /* background */ + nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg); + + /* scroll well */ + rect.x0 = bbox.x0 + 1; + rect.y0 = bbox.y0 + 2; + rect.x1 = bbox.x1 - 2; + rect.y1 = bbox.y1 - 3; + nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->fg); + + /* scroll well outline */ + nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0xFF999999, false, false); + + if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) { + hscroll = ((widget->width - 4) * widget->u.scroll.thumb) / + (widget->u.scroll.maximum - widget->u.scroll.minimum) ; + hpos = ((widget->width - 4) * widget->u.scroll.position) / + (widget->u.scroll.maximum - widget->u.scroll.minimum) ; + } else { + hscroll = (widget->width - 4); + hpos = 0; + } + + LOG(("hscroll %d", hscroll)); + + rect.x0 = bbox.x0 + 3 + hpos; + rect.y0 = bbox.y0 + 5; + rect.x1 = bbox.x0 + hscroll + hpos; + rect.y1 = bbox.y0 + widget->height - 5; + + nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg); + + nsfb_update(root->u.root.fb, &bbox); + + return 0; +} + +static int +hscrolll_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int newpos; + fbtk_widget_t *scrollw = cbi->context; + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; + + newpos = scrollw->u.scroll.position - scrollw->u.scroll.page; + if (newpos < scrollw->u.scroll.minimum) + newpos = scrollw->u.scroll.minimum; + + if (newpos == scrollw->u.scroll.position) { + LOG(("horiz scroll was the same %d", newpos)); + return 0; + } + + return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLX, newpos); +} + +static int +hscrollr_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int newpos; + fbtk_widget_t *scrollw = cbi->context; + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; + + newpos = scrollw->u.scroll.position + scrollw->u.scroll.page; + if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb )) + newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb); + + if (newpos == scrollw->u.scroll.position) + return 0; + + return fbtk_post_callback(scrollw, FBTK_CBT_SCROLLX, newpos); +} + +static int +hscroll_drag(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int newpos; + fbtk_widget_t *scrollw = cbi->context; + + newpos = ((widget->u.scroll.maximum - widget->u.scroll.minimum) / + (widget->width - 4)) * (cbi->x - widget->u.scroll.drag); + + if (newpos < scrollw->u.scroll.minimum) + newpos = scrollw->u.scroll.minimum; + + if (newpos > (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb )) + newpos = (scrollw->u.scroll.maximum - scrollw->u.scroll.thumb); + + if (newpos == scrollw->u.scroll.position) + return 0; + + return fbtk_post_callback(widget, FBTK_CBT_SCROLLX, newpos); +} + +static int +hscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int hscroll; + int hpos; + int newpos; + int ret = 0; + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) { + /* end all drags, just in case */ + if (fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, NULL, NULL) != NULL) + fbtk_tgrab_pointer(widget); + return 0; + } + + if ((widget->u.scroll.maximum - widget->u.scroll.minimum) > 0) { + hscroll = ((widget->width - 4) * widget->u.scroll.thumb) / + (widget->u.scroll.maximum - widget->u.scroll.minimum) ; + hpos = ((widget->width - 4) * widget->u.scroll.position) / + (widget->u.scroll.maximum - widget->u.scroll.minimum) ; + } else { + hscroll = (widget->width - 4); + hpos = 0; + } + + if (cbi->x < hpos) { + /* left of bar */ + newpos = widget->u.scroll.position - widget->u.scroll.page; + if (newpos < widget->u.scroll.minimum) + newpos = widget->u.scroll.minimum; + ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, newpos); + } else if (cbi->x > (hpos + hscroll)) { + /* right of bar */ + newpos = widget->u.scroll.position + widget->u.scroll.page; + if (newpos > widget->u.scroll.maximum) + newpos = widget->u.scroll.maximum; + ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, newpos); + } else { + /* on bar - start drag */ + widget->u.scroll.drag = cbi->x - hpos; + fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, hscroll_drag, widget); + fbtk_tgrab_pointer(widget); + } + return ret; +} + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_hscroll(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + colour fg, + colour bg, + fbtk_callback callback, + void *context) +{ + fbtk_widget_t *neww; + + neww = fbtk_widget_new(parent, + FB_WIDGET_TYPE_HSCROLL, + x + scrolll.width, + y, + width - scrolll.width - scrollr.width, + height); + + neww->fg = fg; + neww->bg = bg; + neww->mapped = true; + + fbtk_set_handler(neww, FBTK_CBT_REDRAW, hscroll_redraw, NULL); + fbtk_set_handler(neww, FBTK_CBT_CLICK, hscrollarea_click, neww); + fbtk_set_handler(neww, FBTK_CBT_SCROLLX, callback, context); + + neww->u.scroll.btnul = fbtk_create_button(parent, + x, + y, + scrolll.width, + height, + fg, + &scrolll, + hscrolll_click, + neww); + + neww->u.scroll.btndr = fbtk_create_button(parent, + x + width - scrollr.width, + y, + scrollr.width, + height, + fg, + &scrollr, + hscrollr_click, + neww); + + return neww; +} + + +/* exported function documented in fbtk.h */ +bool +fbtk_set_scroll_parameters(fbtk_widget_t *widget, + int min, + int max, + int thumb, + int page) +{ + if (widget == NULL) + return false; + + if ((widget->type != FB_WIDGET_TYPE_HSCROLL) && + (widget->type != FB_WIDGET_TYPE_VSCROLL)) + return false; + + widget->u.scroll.minimum = min; + widget->u.scroll.maximum = max; + widget->u.scroll.thumb = thumb; + widget->u.scroll.page = page; + + if (widget->u.scroll.position > max) + widget->u.scroll.position = max; + if (widget->u.scroll.position < min) + widget->u.scroll.position = min; + + fbtk_request_redraw(widget); + + return true; +} + +/* exported function documented in fbtk.h */ +bool +fbtk_set_scroll_position(fbtk_widget_t *widget, int position) +{ + if (widget == NULL) + return false; + + if ((widget->type != FB_WIDGET_TYPE_HSCROLL) && + (widget->type != FB_WIDGET_TYPE_VSCROLL)) + return false; + + if ((position < widget->u.scroll.minimum) || + (position > widget->u.scroll.maximum)) + return false; + + widget->u.scroll.position = position; + + fbtk_request_redraw(widget); + + return true; +} + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk/text.c b/framebuffer/fbtk/text.c new file mode 100644 index 000000000..ed090fe36 --- /dev/null +++ b/framebuffer/fbtk/text.c @@ -0,0 +1,421 @@ +/* + * Copyright 2010 Vincent Sanders + * + * Framebuffer windowing toolkit scrollbar widgets. + * + * 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 . + */ + +#include +#include +#include + +#include +#include +#include +#include + +#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" + +#define TEXT_WIDGET_BORDER 3 /**< The pixel border round a text widget. */ + +/* Lighten a colour by taking seven eights of each channel's intensity + * and adding a full eighth + */ +#define brighten_colour(c1) \ + (((((7 * ((c1 >> 16) & 0xff)) >> 3) + 32) << 16) | \ + ((((7 * ((c1 >> 8) & 0xff)) >> 3) + 32) << 8) | \ + ((((7 * (c1 & 0xff)) >> 3) + 32) << 0)) + +/** Text redraw callback. + * + * Called when a text widget requires redrawing. + * + * @param widget The widget to be redrawn. + * @param cbi The callback parameters. + * @return The callback result. + */ +static int +fb_redraw_text(fbtk_widget_t *widget, fbtk_callback_info *cbi ) +{ + nsfb_bbox_t bbox; + nsfb_bbox_t rect; + fbtk_widget_t *root; + plot_font_style_t font_style; + int fh; + int border; + + border = (widget->height * 10) / 90; + + root = fbtk_get_root_widget(widget); + + fbtk_get_bbox(widget, &bbox); + + rect = bbox; + + nsfb_claim(root->u.root.fb, &bbox); + + /* clear background */ + if ((widget->bg & 0xFF000000) != 0) { + /* transparent polygon filling isnt working so fake it */ + nsfb_plot_rectangle_fill(root->u.root.fb, &bbox, widget->bg); + } + + if (widget->u.text.outline) { + rect.x1--; + rect.y1--; + nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0x00000000, false, false); + border++; + } + + if (widget->u.text.text != NULL) { + fh = widget->height - border - border; + font_style.family = PLOT_FONT_FAMILY_SANS_SERIF; + font_style.size = fh * FONT_SIZE_SCALE; + font_style.weight = 400; + font_style.flags = FONTF_NONE; + font_style.background = widget->bg; + font_style.foreground = widget->fg; + + LOG(("plotting %p at %d,%d %d,%d w/h %d,%d font h %d border %d", + widget, bbox.x0, bbox.y0, bbox.x1, bbox.y1, + widget->width, widget->height, fh, border)); + /* Call the fb text plotting, baseline is 3/4 down the + * font, somewhere along the way the co-ordinate + * system for the baseline is to the "higher value + * pixel co-ordinate" due to this the + 1 is neccessary. + */ + plot.text(bbox.x0 + border, + bbox.y0 + (((fh * 3) + 3)/4) + border + 1, + widget->u.text.text, + strlen(widget->u.text.text), + &font_style); + } + + nsfb_update(root->u.root.fb, &bbox); + + return 0; +} + +/** Text button redraw callback. + * + * Called when a text widget requires redrawing. + * + * @param widget The widget to be redrawn. + * @param cbi The callback parameters. + * @return The callback result. + */ +static int +fb_redraw_text_button(fbtk_widget_t *widget, fbtk_callback_info *cbi ) +{ + nsfb_bbox_t bbox; + nsfb_bbox_t rect; + nsfb_bbox_t line; + nsfb_plot_pen_t pen; + plot_font_style_t font_style; + int fh; + int border; + fbtk_widget_t *root = fbtk_get_root_widget(widget); + + if (widget->height < 20) { + border = 0; + } else { + border = (widget->height * 10) / 90; + } + + pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID; + pen.stroke_width = 1; + pen.stroke_colour = brighten_colour(widget->bg); + + fbtk_get_bbox(widget, &bbox); + + rect = bbox; + rect.x1--; + rect.y1--; + + nsfb_claim(root->u.root.fb, &bbox); + + /* clear background */ + if ((widget->bg & 0xFF000000) != 0) { + /* transparent polygon filling isnt working so fake it */ + nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg); + } + + if (widget->u.text.outline) { + line.x0 = rect.x0; + line.y0 = rect.y0; + line.x1 = rect.x0; + line.y1 = rect.y1; + nsfb_plot_line(root->u.root.fb, &line, &pen); + line.x0 = rect.x0; + line.y0 = rect.y0; + line.x1 = rect.x1; + line.y1 = rect.y0; + nsfb_plot_line(root->u.root.fb, &line, &pen); + pen.stroke_colour = darken_colour(widget->bg); + line.x0 = rect.x0; + line.y0 = rect.y1; + line.x1 = rect.x1; + line.y1 = rect.y1; + nsfb_plot_line(root->u.root.fb, &line, &pen); + line.x0 = rect.x1; + line.y0 = rect.y0; + line.x1 = rect.x1; + line.y1 = rect.y1; + nsfb_plot_line(root->u.root.fb, &line, &pen); + border++; + } + + if (widget->u.text.text != NULL) { + fh = widget->height - border - border; + font_style.family = PLOT_FONT_FAMILY_SANS_SERIF; + font_style.size = fh * FONT_SIZE_SCALE; + font_style.weight = 400; + font_style.flags = FONTF_NONE; + font_style.background = widget->bg; + font_style.foreground = widget->fg; + + LOG(("plotting %p at %d,%d %d,%d w/h %d,%d font h %d border %d", + widget, bbox.x0, bbox.y0, bbox.x1, bbox.y1, + widget->width, widget->height, fh, border)); + /* Call the fb text plotting, baseline is 3/4 down the + * font, somewhere along the way the co-ordinate + * system for the baseline is to the "higher value + * pixel co-ordinate" due to this the + 1 is neccessary. + */ + plot.text(bbox.x0 + border, + bbox.y0 + (((fh * 3) + 3)/4) + border + 1, + widget->u.text.text, + strlen(widget->u.text.text), + &font_style); + } + + nsfb_update(root->u.root.fb, &bbox); + + return 0; +} + +/** Routine called when text events occour in writeable widget. + * + * @param widget The widget reciving input events. + * @param cbi The callback parameters. + * @return The callback result. + */ +static int +text_input(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + int value; + static uint8_t modifier = 0; + char *temp; + + if (cbi->event == NULL) { + /* gain focus */ + if (widget->u.text.text == NULL) + widget->u.text.text = calloc(1,1); + widget->u.text.idx = strlen(widget->u.text.text); + + fbtk_request_redraw(widget); + + return 0; + } + + value = cbi->event->value.keycode; + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) { + switch (value) { + case NSFB_KEY_RSHIFT: + modifier &= ~1; + break; + + case NSFB_KEY_LSHIFT: + modifier &= ~(1<<1); + break; + + default: + break; + } + return 0; + } + + switch (value) { + case NSFB_KEY_BACKSPACE: + if (widget->u.text.idx <= 0) + break; + widget->u.text.idx--; + widget->u.text.text[widget->u.text.idx] = 0; + break; + + case NSFB_KEY_RETURN: + widget->u.text.enter(widget->u.text.pw, widget->u.text.text); + break; + + case NSFB_KEY_PAGEUP: + case NSFB_KEY_PAGEDOWN: + case NSFB_KEY_RIGHT: + case NSFB_KEY_LEFT: + case NSFB_KEY_UP: + case NSFB_KEY_DOWN: + /* Not handling any of these correctly yet, but avoid putting + * charcters in the text widget when they're pressed. */ + break; + + case NSFB_KEY_RSHIFT: + modifier |= 1; + break; + + case NSFB_KEY_LSHIFT: + modifier |= 1<<1; + break; + + default: + /* allow for new character and null */ + temp = realloc(widget->u.text.text, widget->u.text.idx + 2); + if (temp != NULL) { + widget->u.text.text = temp; + widget->u.text.text[widget->u.text.idx] = fbtk_keycode_to_ucs4(value, modifier); + widget->u.text.text[widget->u.text.idx + 1] = '\0'; + widget->u.text.idx++; + } + + break; + } + + fbtk_request_redraw(widget); + + return 0; +} + +/* exported function documented in fbtk.h */ +void +fbtk_writable_text(fbtk_widget_t *widget, fbtk_enter_t enter, void *pw) +{ + widget->u.text.enter = enter; + widget->u.text.pw = pw; + + fbtk_set_handler(widget, FBTK_CBT_INPUT, text_input, widget); +} + +/* exported function documented in fbtk.h */ +void +fbtk_set_text(fbtk_widget_t *widget, const char *text) +{ + if ((widget == NULL) || (widget->type != FB_WIDGET_TYPE_TEXT)) + return; + if (widget->u.text.text != NULL) { + if (strcmp(widget->u.text.text, text) == 0) + return; /* text is being set to the same thing */ + free(widget->u.text.text); + } + widget->u.text.text = strdup(text); + widget->u.text.idx = strlen(text); + + fbtk_request_redraw(widget); +} + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_text(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + colour bg, + colour fg, + bool outline) +{ + fbtk_widget_t *neww; + + neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_TEXT, x, y, width, height); + neww->fg = fg; + neww->bg = bg; + neww->mapped = true; + neww->u.text.outline = outline; + + fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_text, NULL); + + return neww; +} + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_writable_text(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + colour bg, + colour fg, + bool outline, + fbtk_enter_t enter, + void *pw) +{ + fbtk_widget_t *neww; + + neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_TEXT, x, y, width, height); + neww->fg = fg; + neww->bg = bg; + neww->mapped = true; + + neww->u.text.outline = outline; + neww->u.text.enter = enter; + neww->u.text.pw = pw; + + fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_text, NULL); + fbtk_set_handler(neww, FBTK_CBT_INPUT, text_input, neww); + + return neww; +} + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_text_button(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + colour bg, + colour fg, + fbtk_callback click, + void *pw) +{ + fbtk_widget_t *neww; + + neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_TEXT, x, y, width, height); + neww->fg = fg; + neww->bg = bg; + neww->mapped = true; + + neww->u.text.outline = true; + + fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_text_button, NULL); + fbtk_set_handler(neww, FBTK_CBT_CLICK, click, pw); + fbtk_set_handler(neww, FBTK_CBT_POINTERENTER, fbtk_set_ptr, &hand_image); + + return neww; +} + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk/user.c b/framebuffer/fbtk/user.c new file mode 100644 index 000000000..7b0f36ef7 --- /dev/null +++ b/framebuffer/fbtk/user.c @@ -0,0 +1,64 @@ +/* + * Copyright 2010 Vincent Sanders + * + * Framebuffer windowing toolkit user widget. + * + * 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 . + */ + +#include + +#include + +#include "desktop/plotters.h" +#include "framebuffer/gui.h" +#include "framebuffer/fbtk.h" + +#include "widget.h" + +/* exported function documented in fbtk.h */ +void * +fbtk_get_userpw(fbtk_widget_t *widget) +{ + if ((widget == NULL) || + (widget->type != FB_WIDGET_TYPE_USER)) + return NULL; + + return widget->u.user.pw; +} + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_user(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + void *pw) +{ + fbtk_widget_t *neww; + + neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_USER, x, y, width, height); + neww->u.user.pw = pw; + neww->mapped = true; + + return neww; +} + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk/widget.h b/framebuffer/fbtk/widget.h new file mode 100644 index 000000000..75a2a646d --- /dev/null +++ b/framebuffer/fbtk/widget.h @@ -0,0 +1,246 @@ +/* + * Copyright 2010 Vincent Sanders + * + * 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 . + */ + +#ifndef NETSURF_FB_FBTK_WIDGET_H +#define NETSURF_FB_FBTK_WIDGET_H + +#include + +enum fbtk_widgettype_e { + FB_WIDGET_TYPE_ROOT = 0, + FB_WIDGET_TYPE_WINDOW, + FB_WIDGET_TYPE_BITMAP, + FB_WIDGET_TYPE_FILL, + FB_WIDGET_TYPE_TEXT, + FB_WIDGET_TYPE_HSCROLL, + FB_WIDGET_TYPE_VSCROLL, + FB_WIDGET_TYPE_USER, +}; + + +/** Widget description. + * + * A widget is an entry in a tree structure which represents a + * rectangular area with co-ordinates relative to its parent widget. + * This area has a distinct set of callback operations for handling + * events which occour within its boundries. A widget may have an + * arbitrary number of child widgets. The order within the tree + * determines a widgets z order. + * + * --- + * A + * | + * +----------+ + * +--->| Button 3 | + * | +----------+ + * | | A + * | V | + * | +----------+ + * | | Button 2 | + * | +----------+ + * | | A + * | V | + * | +----------+ + * | | Button 1 | + * | +----------+ + * | | A + * | V | + * --- | +----------+ + * A | +->| Filled | + * | | | +----------+ + * +----------+ | | | + * +---->| |-+ | V + * | | Window 1 | | --- --- + * | | |---+ A + * | +----------+ | + * | | A +----------+ --- + * | | | +--->| Button 2 | A + * | | | | +----------+ | + * | | | | | A +-------------+ + * | | | | | | +--->| Button Up | + * | | | | | | | +-------------+ + * | | | | | | | | A + * | | | | | | | V | + * | | | | | | | +-------------+ + * | | | | | | | | Button Down | + * | | | | | | | +-------------+ + * | | | | | | | | A + * | | | | | | | V | + * | | | | | | | +-------------+ + * | | | | | | | +->| Scroller | + * | | | | V | | | +-------------+ + * | | | | +----------+ | | | + * | | | | | |-+ | V + * | | | | | V Scroll | | --- + * | | | | | |---+ + * | | | | +----------+ + * | | | | | A + * | | | | V | + * | | | | +----------+ + * | | | | +->| Button 1 | + * | | | | | +----------+ + * | +----------+ | | | + * | | |-+ | V + * | | Window 2 | | --- + * | | |---+ + * | +----------+ + * | | A + * | V | + * | +------------+ + * --- | | Background | + * A | +->| Bitmap | + * | | | +------------+ + * +------+ | | | + * | |-+ | V + * | Root | | --- + * | |---+ + * +------+ + * | + * V + * --- + * + * Every widget is contained within this generic wrapper. The + * integrated union provides for data specific to a widget type. + */ +struct fbtk_widget_s { + struct fbtk_widget_s *next; /* next lower z ordered widget in tree */ + struct fbtk_widget_s *prev; /* next higher z ordered widget in tree */ + + struct fbtk_widget_s *parent; /* parent widget */ + + struct fbtk_widget_s *first_child; /* first child widget */ + struct fbtk_widget_s *last_child; /* last child widget */ + + /* flags */ + bool mapped; /**< The widget is mapped/visible . */ + + /* Generic properties */ + int x; + int y; + int width; + int height; + colour bg; + colour fg; + + /* event callback handlers */ + fbtk_callback callback[FBTK_CBT_END]; + void *callback_context[FBTK_CBT_END]; + + /* widget redraw */ + struct { + bool child; /* A child of this widget requires redrawing */ + bool needed; /* the widget requires redrawing */ + int x; + int y; + int width; + int height; + } redraw; + + enum fbtk_widgettype_e type; /**< The type of the widget */ + + + union { + /* toolkit base handle */ + struct { + nsfb_t *fb; + struct fbtk_widget_s *prev; /* previous widget pointer wasin */ + struct fbtk_widget_s *grabbed; /* widget that has grabbed pointer movement. */ + struct fbtk_widget_s *input; + } root; + + /* bitmap */ + struct { + struct bitmap *bitmap; + } bitmap; + + /* text */ + struct { + char* text; + bool outline; + fbtk_enter_t enter; + void *pw; + int idx; + } text; + + /* application driven widget */ + struct { + void *pw; /* private data for user widget */ + } user; + + struct { + int minimum; /* lowest value of scrollbar */ + int maximum; /* highest value of scrollbar */ + int thumb; /* size of bar representing a page */ + int page; /* amount to page document */ + int position; /* position of bar */ + int drag; /* offset to start of drag */ + struct fbtk_widget_s *btnul; /* scroll button up/left */ + struct fbtk_widget_s *btndr; /* scroll button down/right*/ + } scroll; + + } u; +}; + + +/* These functions are not considered part of the public API but are + * not static as they are used by the higher level widget provision + * routines + */ + + +/** creates a new widget and insert it into to hierachy. + * + * The widget is set to defaults of false, 0 or NULL. + * + * @param parent The parent widget. The new widget will be added with + * the shallowest z order relative to its siblings. + * @param type The type of the widget. + * @param x The x co-ordinate relative to the parent widget. + * @param y The y co-ordinate relative to the parent widget. + * @param width the widgets width. This will be clipped to the parent, if + * the value is 0 the largest extent which can fit within the parent + * is used, if the value is negative the largest value that will fit + * within the parent less the value given will be used. + * @param height the widgets width. This will be clipped to the parent, if + * the value is 0 the largest extent which can fit within the parent + * is used, if the value is negative the largest value that will fit + * within the parent less the value given will be used. + */ +fbtk_widget_t *fbtk_widget_new(fbtk_widget_t *parent, enum fbtk_widgettype_e type, int x, int y, int width, int height); + +/** find the root widget from any widget in the toolkit hierarchy. + * + * @param widget Any widget. + * @return The root widget or NULL if \a widget was not valid. + */ +fbtk_widget_t *fbtk_get_root_widget(fbtk_widget_t *widget); + +/** set pointer to bitmap in context. + * + * widget helper callback to set cursor image to the bitmap passed in + * the callbacks private data. + */ +int fbtk_set_ptr(fbtk_widget_t *widget, fbtk_callback_info *cbi); + +#endif + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk/window.c b/framebuffer/fbtk/window.c new file mode 100644 index 000000000..a2c9227e6 --- /dev/null +++ b/framebuffer/fbtk/window.c @@ -0,0 +1,91 @@ +/* + * Copyright 2010 Vincent Sanders + * + * Framebuffer windowing toolkit window widget. + * + * 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 . + */ + +#include +#include + +#include +#include + +#include "desktop/browser.h" + +#include "framebuffer/gui.h" +#include "framebuffer/fbtk.h" + +#include "widget.h" + +/** Window redraw callback. + * + * Called when a window requires redrawing. + * + * @param widget The widget to be redrawn. + * @param cbi The callback parameters. + * @return The callback result. + */ +static int +fb_redraw_window(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + nsfb_bbox_t bbox; + nsfb_t *nsfb; + + if ((widget->bg & 0xFF000000) == 0) + return 0; + + nsfb = fbtk_get_nsfb(widget); + + fbtk_get_bbox(widget, &bbox); + + nsfb_claim(nsfb, &bbox); + + nsfb_plot_rectangle_fill(nsfb, &bbox, widget->bg); + + nsfb_update(nsfb, &bbox); + + return 0; +} + +/* exported function documented in fbtk.h */ +fbtk_widget_t * +fbtk_create_window(fbtk_widget_t *parent, + int x, + int y, + int width, + int height, + colour bg) +{ + fbtk_widget_t *neww; + + if (parent == NULL) + return NULL; + + neww = fbtk_widget_new(parent, FB_WIDGET_TYPE_WINDOW, x, y, width, height); + + neww->bg = bg; + + fbtk_set_handler(neww, FBTK_CBT_REDRAW, fb_redraw_window, NULL); + + return neww; +} + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/fbtk_widget.h b/framebuffer/fbtk_widget.h deleted file mode 100644 index c542c2012..000000000 --- a/framebuffer/fbtk_widget.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2008 Vincent Sanders - * - * 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 . - */ - -#ifndef NETSURF_FB_FBTK_WIDGET_H -#define NETSURF_FB_FBTK_WIDGET_H - -enum fbtk_widgettype_e { - FB_WIDGET_TYPE_ROOT = 0, - FB_WIDGET_TYPE_WINDOW, - FB_WIDGET_TYPE_BITMAP, - FB_WIDGET_TYPE_FILL, - FB_WIDGET_TYPE_TEXT, - FB_WIDGET_TYPE_HSCROLL, - FB_WIDGET_TYPE_VSCROLL, - FB_WIDGET_TYPE_USER, -}; - -typedef struct fbtk_widget_list_s fbtk_widget_list_t; - -/* wrapper struct for all widget types */ -struct fbtk_widget_s { - /* Generic properties */ - int x; - int y; - int width; - int height; - colour bg; - colour fg; - - /* event callback handlers */ - fbtk_callback callback[FBTK_CBT_END]; - void *callback_context[FBTK_CBT_END]; - - bool redraw_required; /* the widget requires redrawing */ - - fbtk_widget_t *parent; /* parent widget */ - - /* Widget specific */ - enum fbtk_widgettype_e type; - - union { - /* toolkit base handle */ - struct { - nsfb_t *fb; - fbtk_widget_t *rootw; - fbtk_widget_t *input; - } root; - - /* window */ - struct { - /* widgets associated with this window */ - fbtk_widget_list_t *widgets; /* begining of list */ - fbtk_widget_list_t *widgets_end; /* end of list */ - } window; - - /* bitmap */ - struct { - struct bitmap *bitmap; - } bitmap; - - /* text */ - struct { - char* text; - bool outline; - fbtk_enter_t enter; - void *pw; - int idx; - } text; - - /* application driven widget */ - struct { - void *pw; /* private data for user widget */ - } user; - - struct { - int pos; - int pct; - struct fbtk_widget_s *btnul; /* scroll button up/left */ - struct fbtk_widget_s *btndr; /* scroll button down/right*/ - } scroll; - - } u; -}; - - -/* widget manipulation functions */ - -fbtk_widget_t *get_root_widget(fbtk_widget_t *widget); - -fbtk_widget_t *new_widget(enum fbtk_widgettype_e type); - -fbtk_widget_t *add_widget_to_window(fbtk_widget_t *window, fbtk_widget_t *widget); - -#endif diff --git a/framebuffer/fbtk_widget_scroll.c b/framebuffer/fbtk_widget_scroll.c deleted file mode 100644 index c28887bda..000000000 --- a/framebuffer/fbtk_widget_scroll.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright 2008 Vincent Sanders - * - * Framebuffer windowing toolkit scrollbar widgets - * - * 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 . - */ - -#include - -#include -#include -#include -#include - -#include "utils/log.h" -#include "desktop/browser.h" - -#include "framebuffer/gui.h" -#include "framebuffer/fbtk.h" -#include "framebuffer/fbtk_widget.h" -#include "framebuffer/bitmap.h" -#include "framebuffer/image_data.h" - -/** Vertical scroll widget */ - -static int -vscroll_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - int vscroll; - int vpos; - - nsfb_bbox_t bbox; - nsfb_bbox_t rect; - fbtk_widget_t *root = get_root_widget(widget); - - fbtk_get_bbox(widget, &bbox); - - nsfb_claim(root->u.root.fb, &bbox); - - rect = bbox; - - /* background */ - nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg); - - rect.x0 = bbox.x0 + 2; - rect.y0 = bbox.y0 + 1; - rect.x1 = bbox.x1 - 3; - rect.y1 = bbox.y1 - 2; - nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->fg); - - /* scroll well */ - nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0xFF999999, false, false); - - /* scroll well outline */ - vscroll = ((widget->height - 4) * widget->u.scroll.pct) / 100 ; - vpos = ((widget->height - 4) * widget->u.scroll.pos) / 100 ; - - LOG(("scroll %d",vscroll)); - - rect.x0 = bbox.x0 + 5; - rect.y0 = bbox.y0 + 3 + vpos; - rect.x1 = bbox.x0 + widget->width - 5; - rect.y1 = bbox.y0 + vscroll + vpos; - - nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg); - - nsfb_update(root->u.root.fb, &bbox); - - return 0; -} - -static int -vscrollu_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - int ret = 0; - if (cbi->event->type == NSFB_EVENT_KEY_DOWN) - ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, -1); - return ret; -} - -static int -vscrolld_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - int ret = 0; - if (cbi->event->type == NSFB_EVENT_KEY_DOWN) - ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, 1); - return ret; -} - -static int -vscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - int vscroll; - int vpos; - int ret = 0; - - if (cbi->event->type != NSFB_EVENT_KEY_DOWN) - return 0; - - vscroll = ((widget->height - 4) * widget->u.scroll.pct) / 100 ; - vpos = ((widget->height - 4) * widget->u.scroll.pos) / 100 ; - - if (cbi->y < vpos) { - /* above bar */ - ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, -1); - } else if (cbi->y > (vpos + vscroll)) { - /* below bar */ - ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLY, 1); - } - return ret; -} - - -fbtk_widget_t * -fbtk_create_vscroll(fbtk_widget_t *window, - int x, int y, - int width, int height, - colour fg, - colour bg, - fbtk_callback callback, - void *context) -{ - fbtk_widget_t *neww = new_widget(FB_WIDGET_TYPE_VSCROLL); - - neww->x = x; - neww->y = y + scrollu.height; - neww->width = width; - neww->height = height - scrollu.height - scrolld.height; - neww->fg = fg; - neww->bg = bg; - - fbtk_set_handler(neww, FBTK_CBT_REDRAW, vscroll_redraw, NULL); - - fbtk_set_handler(neww, FBTK_CBT_CLICK, vscrollarea_click, neww); - - fbtk_set_handler(neww, FBTK_CBT_SCROLLY, callback, context); - - neww->u.scroll.btnul = fbtk_create_button(window, x + (width - scrollu.width) / 2, y, fg, &scrollu, vscrollu_click, neww); - - neww->u.scroll.btndr = fbtk_create_button(window, x + (width - scrolld.width) / 2, y + height - scrolld.height, fg, &scrolld, vscrolld_click, neww); - - - return add_widget_to_window(window, neww); -} - -/* Horizontal scroll widget */ - -static int -hscroll_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - int hscroll; - int hpos; - nsfb_bbox_t bbox; - nsfb_bbox_t rect; - fbtk_widget_t *root = get_root_widget(widget); - - fbtk_get_bbox(widget, &bbox); - - nsfb_claim(root->u.root.fb, &bbox); - - rect = bbox; - - /* background */ - nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg); - - /* scroll well */ - rect.x0 = bbox.x0 + 1; - rect.y0 = bbox.y0 + 2; - rect.x1 = bbox.x1 - 2; - rect.y1 = bbox.y1 - 3; - nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->fg); - - /* scroll well outline */ - nsfb_plot_rectangle(root->u.root.fb, &rect, 1, 0xFF999999, false, false); - - hscroll = ((widget->width - 4) * widget->u.scroll.pct) / 100 ; - hpos = ((widget->width - 4) * widget->u.scroll.pos) / 100 ; - - LOG(("hscroll %d",hscroll)); - - rect.x0 = bbox.x0 + 3 + hpos; - rect.y0 = bbox.y0 + 5; - rect.x1 = bbox.x0 + hscroll + hpos; - rect.y1 = bbox.y0 + widget->height - 5; - - nsfb_plot_rectangle_fill(root->u.root.fb, &rect, widget->bg); - - nsfb_update(root->u.root.fb, &bbox); - - return 0; -} - -static int -hscrolll_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - int ret = 0; - if (cbi->event->type == NSFB_EVENT_KEY_DOWN) - ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, -1); - return ret; -} - -static int -hscrollr_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - int ret = 0; - if (cbi->event->type == NSFB_EVENT_KEY_DOWN) - ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, 1); - return ret; -} - -static int -hscrollarea_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) -{ - int hscroll; - int hpos; - int ret; - - if (cbi->event->type != NSFB_EVENT_KEY_DOWN) - return 0; - - hscroll = ((widget->width - 4) * widget->u.scroll.pct) / 100 ; - hpos = ((widget->width - 4) * widget->u.scroll.pos) / 100 ; - - if (cbi->x < hpos) { - /* above bar */ - ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, -1); - } else if (cbi->x > (hpos + hscroll)) { - /* below bar */ - ret = fbtk_post_callback(cbi->context, FBTK_CBT_SCROLLX, 1); - } - return ret; -} - -fbtk_widget_t * -fbtk_create_hscroll(fbtk_widget_t *window, - int x, int y, - int width, int height, - colour fg, - colour bg, - fbtk_callback callback, - void *context) -{ - fbtk_widget_t *neww = new_widget(FB_WIDGET_TYPE_HSCROLL); - - neww->x = x + scrolll.width; - neww->y = y; - neww->width = width - scrolll.width - scrollr.width; - neww->height = height; - neww->fg = fg; - neww->bg = bg; - - fbtk_set_handler(neww, FBTK_CBT_REDRAW, hscroll_redraw, NULL); - fbtk_set_handler(neww, FBTK_CBT_CLICK, hscrollarea_click, neww); - fbtk_set_handler(neww, FBTK_CBT_SCROLLX, callback, context); - - neww->u.scroll.btnul = fbtk_create_button(window, x, y + ((height - scrolll.height) / 2), fg, &scrolll, hscrolll_click, neww); - - neww->u.scroll.btndr = fbtk_create_button(window, x + width - scrollr.width, y + ((height - scrolll.height) / 2), fg, &scrollr, hscrollr_click, neww); - - return add_widget_to_window(window, neww); -} - - -void -fbtk_set_scroll(fbtk_widget_t *widget, int pct) -{ - if (widget == NULL) - return; - - if ((widget->type == FB_WIDGET_TYPE_HSCROLL) || - (widget->type == FB_WIDGET_TYPE_VSCROLL)) { - - widget->u.scroll.pct = pct; - fbtk_request_redraw(widget); - } -} - -void -fbtk_set_scroll_pos(fbtk_widget_t *widget, int pos) -{ - if (widget == NULL) - return; - - if ((widget->type == FB_WIDGET_TYPE_HSCROLL) || - (widget->type == FB_WIDGET_TYPE_VSCROLL)) { - - widget->u.scroll.pos = pos; - - fbtk_request_redraw(widget); - } -} - diff --git a/framebuffer/framebuffer.c b/framebuffer/framebuffer.c index 0400a1abe..6c7ba102b 100644 --- a/framebuffer/framebuffer.c +++ b/framebuffer/framebuffer.c @@ -67,14 +67,16 @@ framebuffer_plot_arc(int x, int y, int radius, int angle1, int angle2, const plo return nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour); } -static bool framebuffer_plot_polygon(const int *p, unsigned int n, const plot_style_t *style) +static bool +framebuffer_plot_polygon(const int *p, unsigned int n, const plot_style_t *style) { return nsfb_plot_polygon(nsfb, p, n, style->fill_colour); } #ifdef FB_USE_FREETYPE -static bool framebuffer_plot_text(int x, int y, const char *text, size_t length, +static bool +framebuffer_plot_text(int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle) { uint32_t ucs4; diff --git a/framebuffer/gui.c b/framebuffer/gui.c index 50c3da2ff..a329f4a46 100644 --- a/framebuffer/gui.c +++ b/framebuffer/gui.c @@ -53,6 +53,7 @@ #include "framebuffer/findfile.h" #include "framebuffer/image_data.h" #include "framebuffer/font.h" +#include "framebuffer/options.h" #include "content/urldb.h" #include "desktop/history_core.h" @@ -63,7 +64,6 @@ char *quirks_stylesheet_url; char *adblock_stylesheet_url; char *options_file_location; - fbtk_widget_t *fbtk; struct gui_window *input_window = NULL; @@ -81,8 +81,8 @@ struct browser_widget_s { */ bbox_t redraw_box; /**< Area requiring redraw. */ bool pan_required; /**< flag indicating the foreground loop - * needs to pan the window. - */ + * needs to pan the window. + */ int panx, pany; /**< Panning required. */ }; @@ -91,67 +91,115 @@ struct browser_widget_s { static void fb_queue_redraw(struct fbtk_widget_s *widget, int x0, int y0, int x1, int y1) { - struct browser_widget_s *bwidget = fbtk_get_userpw(widget); + struct browser_widget_s *bwidget = fbtk_get_userpw(widget); - bwidget->redraw_box.x0 = min(bwidget->redraw_box.x0, x0); - bwidget->redraw_box.y0 = min(bwidget->redraw_box.y0, y0); - bwidget->redraw_box.x1 = max(bwidget->redraw_box.x1, x1); - bwidget->redraw_box.y1 = max(bwidget->redraw_box.y1, y1); + bwidget->redraw_box.x0 = min(bwidget->redraw_box.x0, x0); + bwidget->redraw_box.y0 = min(bwidget->redraw_box.y0, y0); + bwidget->redraw_box.x1 = max(bwidget->redraw_box.x1, x1); + bwidget->redraw_box.y1 = max(bwidget->redraw_box.y1, y1); - if (fbtk_clip_to_widget(widget, &bwidget->redraw_box)) { - bwidget->redraw_required = true; - fbtk_request_redraw(widget); - } else { - bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX; - bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = -(INT_MAX); - bwidget->redraw_required = false; - } + if (fbtk_clip_to_widget(widget, &bwidget->redraw_box)) { + bwidget->redraw_required = true; + fbtk_request_redraw(widget); + } else { + bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX; + bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = -(INT_MAX); + bwidget->redraw_required = false; + } } -static void fb_pan(fbtk_widget_t *widget, - struct browser_widget_s *bwidget, - struct browser_window *bw) +/* queue a window scroll */ +static void +widget_scroll_y(struct gui_window *gw, int y, bool abs) { - int x; - int y; - int width; + struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser); + int content_height; int height; - nsfb_bbox_t srcbox; - nsfb_bbox_t dstbox; - nsfb_t *nsfb = fbtk_get_nsfb(widget); + LOG(("window scroll")); + if (abs) { + bwidget->pany = y - bwidget->scrolly; + } else { + bwidget->pany += y; + } + bwidget->pan_required = true; - int content_height = content_get_height(bw->current_content); - int content_width = content_get_width(bw->current_content); + content_height = content_get_height(gw->bw->current_content); - height = fbtk_get_height(widget); - width = fbtk_get_width(widget); - x = fbtk_get_x(widget); - y = fbtk_get_y(widget); + height = fbtk_get_height(gw->browser); /* dont pan off the top */ if ((bwidget->scrolly + bwidget->pany) < 0) - bwidget->pany = - bwidget->scrolly; + bwidget->pany = -bwidget->scrolly; - /* do not pan off the bottom of the content */ + /* do not pan off the bottom of the content */ if ((bwidget->scrolly + bwidget->pany) > (content_height - height)) bwidget->pany = (content_height - height) - bwidget->scrolly; + fbtk_request_redraw(gw->browser); + + fbtk_set_scroll_position(gw->vscroll, bwidget->scrolly + bwidget->pany); +} + +/* queue a window scroll */ +static void +widget_scroll_x(struct gui_window *gw, int x, bool abs) +{ + struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser); + int content_width; + int width; + + if (abs) { + bwidget->panx = x - bwidget->scrollx; + } else { + bwidget->panx += x; + } + bwidget->pan_required = true; + + content_width = content_get_width(gw->bw->current_content); + + width = fbtk_get_width(gw->browser); + + /* dont pan off the left */ if ((bwidget->scrollx + bwidget->panx) < 0) bwidget->panx = - bwidget->scrollx; - /* do not pan off the right of the content */ + /* do not pan off the right of the content */ if ((bwidget->scrollx + bwidget->panx) > (content_width - width)) bwidget->panx = (content_width - width) - bwidget->scrollx; - LOG(("panning %d, %d",bwidget->panx, bwidget->pany)); + fbtk_request_redraw(gw->browser); + + fbtk_set_scroll_position(gw->hscroll, bwidget->scrollx + bwidget->panx); +} + +static void +fb_pan(fbtk_widget_t *widget, + struct browser_widget_s *bwidget, + struct browser_window *bw) +{ + int x; + int y; + int width; + int height; + nsfb_bbox_t srcbox; + nsfb_bbox_t dstbox; + + nsfb_t *nsfb = fbtk_get_nsfb(widget); + + height = fbtk_get_height(widget); + width = fbtk_get_width(widget); + + LOG(("panning %d, %d", bwidget->panx, bwidget->pany)); + + x = fbtk_get_absx(widget); + y = fbtk_get_absy(widget); - /* pump up the volume. dance, dance! lets do it */ + /* if the pan exceeds the viewport size just redraw the whole area */ if (bwidget->pany > height || bwidget->pany < -height || - bwidget->panx > width || bwidget->panx < -width) { + bwidget->panx > width || bwidget->panx < -width) { - /* pan in any direction by more than viewport size */ bwidget->scrolly += bwidget->pany; bwidget->scrollx += bwidget->panx; fb_queue_redraw(widget, 0, 0, width, height); @@ -163,7 +211,6 @@ static void fb_pan(fbtk_widget_t *widget, if (bwidget->pany < 0) { /* pan up by less then viewport height */ - srcbox.x0 = x; srcbox.y0 = y; srcbox.x1 = srcbox.x0 + width; @@ -184,7 +231,6 @@ static void fb_pan(fbtk_widget_t *widget, if (bwidget->pany > 0) { /* pan down by less then viewport height */ - srcbox.x0 = x; srcbox.y0 = y + bwidget->pany; srcbox.x1 = srcbox.x0 + width; @@ -200,13 +246,11 @@ static void fb_pan(fbtk_widget_t *widget, /* redraw newly exposed area */ bwidget->scrolly += bwidget->pany; - fb_queue_redraw(widget, 0, height - bwidget->pany, width, - height); + fb_queue_redraw(widget, 0, height - bwidget->pany, width, height); } if (bwidget->panx < 0) { /* pan left by less then viewport width */ - srcbox.x0 = x; srcbox.y0 = y; srcbox.x1 = srcbox.x0 + width + bwidget->panx; @@ -242,8 +286,7 @@ static void fb_pan(fbtk_widget_t *widget, /* redraw newly exposed area */ bwidget->scrollx += bwidget->panx; - fb_queue_redraw(widget, width - bwidget->panx, 0, width, - height); + fb_queue_redraw(widget, width - bwidget->panx, 0, width, height); } @@ -252,101 +295,110 @@ static void fb_pan(fbtk_widget_t *widget, bwidget->pany = 0; } -static void fb_redraw(fbtk_widget_t *widget, - struct browser_widget_s *bwidget, - struct browser_window *bw) +static void +fb_redraw(fbtk_widget_t *widget, + struct browser_widget_s *bwidget, + struct browser_window *bw) { - int x; - int y; - int width; - int height; + int x; + int y; + int width; + int height; + if (bw->current_content == NULL) + return; - LOG(("redraw box %d,%d to %d,%d",bwidget->redraw_box.x0,bwidget->redraw_box.y0, bwidget->redraw_box.x1, bwidget->redraw_box.y1)); + LOG(("%d,%d to %d,%d", + bwidget->redraw_box.x0, + bwidget->redraw_box.y0, + bwidget->redraw_box.x1, + bwidget->redraw_box.y1)); - height = fbtk_get_height(widget); - width = fbtk_get_width(widget); - x = fbtk_get_x(widget); - y = fbtk_get_y(widget); + height = fbtk_get_height(widget); + width = fbtk_get_width(widget); + x = fbtk_get_absx(widget); + y = fbtk_get_absy(widget); - /* adjust clipping co-ordinates according to window location */ - bwidget->redraw_box.y0 += y; - bwidget->redraw_box.y1 += y; - bwidget->redraw_box.x0 += x; - bwidget->redraw_box.x1 += x; + /* adjust clipping co-ordinates according to window location */ + bwidget->redraw_box.y0 += y; + bwidget->redraw_box.y1 += y; + bwidget->redraw_box.x0 += x; + bwidget->redraw_box.x1 += x; - nsfb_claim(fbtk_get_nsfb(widget), &bwidget->redraw_box); + nsfb_claim(fbtk_get_nsfb(widget), &bwidget->redraw_box); - /* redraw bounding box is relative to window */ + /* redraw bounding box is relative to window */ current_redraw_browser = bw; - content_redraw(bw->current_content, - x - bwidget->scrollx, y - bwidget->scrolly, - width, height, - bwidget->redraw_box.x0, bwidget->redraw_box.y0, - bwidget->redraw_box.x1, bwidget->redraw_box.y1, - bw->scale, 0xFFFFFF); + content_redraw(bw->current_content, + x - bwidget->scrollx, y - bwidget->scrolly, + width, height, + bwidget->redraw_box.x0, bwidget->redraw_box.y0, + bwidget->redraw_box.x1, bwidget->redraw_box.y1, + bw->scale, 0xFFFFFF); current_redraw_browser = NULL; - nsfb_update(fbtk_get_nsfb(widget), &bwidget->redraw_box); + nsfb_update(fbtk_get_nsfb(widget), &bwidget->redraw_box); - bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX; - bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = -(INT_MAX); - bwidget->redraw_required = false; + bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX; + bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = INT_MIN; + bwidget->redraw_required = false; } static int fb_browser_window_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - struct gui_window *gw = cbi->context; - struct browser_widget_s *bwidget; - - bwidget = fbtk_get_userpw(widget); - if (bwidget == NULL) { - LOG(("browser widget from widget %p was null", widget)); - return -1; - } + struct gui_window *gw = cbi->context; + struct browser_widget_s *bwidget; - if (bwidget->pan_required) { - int pos; - fb_pan(widget, bwidget, gw->bw); - pos = (bwidget->scrollx * 100) / content_get_width(gw->bw->current_content); - fbtk_set_scroll_pos(gw->hscroll, pos); - pos = (bwidget->scrolly * 100) / content_get_height(gw->bw->current_content); - fbtk_set_scroll_pos(gw->vscroll, pos); + bwidget = fbtk_get_userpw(widget); + if (bwidget == NULL) { + LOG(("browser widget from widget %p was null", widget)); + return -1; + } - } + if (bwidget->pan_required) { + fb_pan(widget, bwidget, gw->bw); + } - if (bwidget->redraw_required) { - fb_redraw(widget, bwidget, gw->bw); - } - return 0; + if (bwidget->redraw_required) { + fb_redraw(widget, bwidget, gw->bw); + } else { + bwidget->redraw_box.x0 = 0; + bwidget->redraw_box.y0 = 0; + bwidget->redraw_box.x1 = fbtk_get_width(widget); + bwidget->redraw_box.y1 = fbtk_get_height(widget); + fb_redraw(widget, bwidget, gw->bw); + } + return 0; } + static const char *fename; static int febpp; static int fewidth; static int feheight; static const char *feurl; -static bool process_cmdline(int argc, char** argv) +static bool +process_cmdline(int argc, char** argv) { int opt; - LOG(("argc %d, argv %p", argc, argv)); + LOG(("argc %d, argv %p", argc, argv)); fename = "sdl"; febpp = 32; - if ((option_window_width != 0) && (option_window_height != 0)) { - fewidth = option_window_width; - feheight = option_window_height; - } else { - fewidth = 800; - feheight = 600; - } + if ((option_window_width != 0) && (option_window_height != 0)) { + fewidth = option_window_width; + feheight = option_window_height; + } else { + fewidth = 800; + feheight = 600; + } - if (option_homepage_url != NULL && option_homepage_url[0] != '\0') - feurl = option_homepage_url; + if (option_homepage_url != NULL && option_homepage_url[0] != '\0') + feurl = option_homepage_url; else feurl = NETSURF_HOMEPAGE; @@ -370,9 +422,9 @@ static bool process_cmdline(int argc, char** argv) break; default: - fprintf(stderr, + fprintf(stderr, "Usage: %s [-f frontend] [-b bpp] url\n", - argv[0]); + argv[0]); return false; } } @@ -385,10 +437,11 @@ static bool process_cmdline(int argc, char** argv) } -static void gui_init(int argc, char** argv) +static void +gui_init(int argc, char** argv) { char buf[PATH_MAX]; - nsfb_t *nsfb; + nsfb_t *nsfb; fb_find_resource(buf, "Aliases", "./framebuffer/res/Aliases"); LOG(("Using '%s' as Aliases file", buf)); @@ -405,29 +458,32 @@ static void gui_init(int argc, char** argv) fb_find_resource(buf, "quirks.css", "./framebuffer/res/quirks.css"); quirks_stylesheet_url = path_to_url(buf); - if (process_cmdline(argc,argv) != true) + if (process_cmdline(argc,argv) != true) die("unable to process command line.\n"); - nsfb = framebuffer_initialise(fename, fewidth, feheight, febpp); - if (nsfb == NULL) - die("Unable to initialise framebuffer"); + nsfb = framebuffer_initialise(fename, fewidth, feheight, febpp); + if (nsfb == NULL) + die("Unable to initialise framebuffer"); + + framebuffer_set_cursor(&pointer_image); - framebuffer_set_cursor(&pointer_image); + if (fb_font_init() == false) + die("Unable to initialise the font system"); - if (fb_font_init() == false) - die("Unable to initialise the font system"); + fbtk = fbtk_init(nsfb); - fbtk = fbtk_init(nsfb); + fbtk_enable_oskb(fbtk); } /** Entry point from OS. * - * /param argc The number of arguments in the string vector. + * /param argc The number of arguments in the string vector. * /param argv The argument string vector. * /return The return code to the OS */ -int main(int argc, char** argv) +int +main(int argc, char** argv) { struct browser_window *bw; char options[PATH_MAX]; @@ -443,7 +499,7 @@ int main(int argc, char** argv) gui_init(argc, argv); - LOG(("calling browser_window_create")); + LOG(("calling browser_window_create")); bw = browser_window_create(feurl, 0, 0, true, false); netsurf_main_loop(); @@ -456,42 +512,45 @@ int main(int argc, char** argv) } -void gui_multitask(void) +void +gui_multitask(void) { - // LOG(("gui_multitask")); + /* LOG(("gui_multitask")); */ } -void gui_poll(bool active) +void +gui_poll(bool active) { - nsfb_event_t event; - int timeout; /* timeout in miliseconds */ + nsfb_event_t event; + int timeout; /* timeout in miliseconds */ /* run the scheduler and discover how long to wait for the next event */ timeout = schedule_run(); - /* if active do not wait for event, return immediately */ + /* if active do not wait for event, return immediately */ if (active) - timeout = 0; + timeout = 0; - /* if redraws are pending do not wait for event, return immediately */ - if (fbtk_redraw_pending(fbtk)) - timeout = 0; + /* if redraws are pending do not wait for event, return immediately */ + if (fbtk_get_redraw_pending(fbtk)) + timeout = 0; - if (fbtk_event(fbtk, &event, timeout)) { - if ((event.type == NSFB_EVENT_CONTROL) && - (event.value.controlcode == NSFB_CONTROL_QUIT)) - netsurf_quit = true; - } + if (fbtk_event(fbtk, &event, timeout)) { + if ((event.type == NSFB_EVENT_CONTROL) && + (event.value.controlcode == NSFB_CONTROL_QUIT)) + netsurf_quit = true; + } - fbtk_redraw(fbtk); + fbtk_redraw(fbtk); } -void gui_quit(void) +void +gui_quit(void) { - LOG(("gui_quit")); - framebuffer_finalise(); + LOG(("gui_quit")); + framebuffer_finalise(); /* We don't care if this fails as we're about to exit, anyway */ hubbub_finalise(ns_realloc, NULL); @@ -501,174 +560,174 @@ void gui_quit(void) static int fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - struct browser_window *bw = cbi->context; - struct browser_widget_s *bwidget = fbtk_get_userpw(widget); + struct gui_window *gw = cbi->context; + struct browser_widget_s *bwidget = fbtk_get_userpw(widget); - if (cbi->event->type != NSFB_EVENT_KEY_DOWN && + if (cbi->event->type != NSFB_EVENT_KEY_DOWN && cbi->event->type != NSFB_EVENT_KEY_UP) - return 0; - - LOG(("browser window clicked at %d,%d",cbi->x,cbi->y)); - - switch (cbi->event->type) { - case NSFB_EVENT_KEY_DOWN: - switch (cbi->event->value.keycode) { - case NSFB_KEY_MOUSE_1: - browser_window_mouse_click(bw, - BROWSER_MOUSE_PRESS_1, - cbi->x + bwidget->scrollx, - cbi->y + bwidget->scrolly); - break; - - case NSFB_KEY_MOUSE_3: - browser_window_mouse_click(bw, - BROWSER_MOUSE_PRESS_2, - cbi->x + bwidget->scrollx, - cbi->y + bwidget->scrolly); - break; - - case NSFB_KEY_MOUSE_4: - /* scroll up */ - fb_window_scroll(widget, 0, -100); - break; - - case NSFB_KEY_MOUSE_5: - /* scroll down */ - fb_window_scroll(widget, 0, 100); - break; - - default: - break; - - } + return 0; + + LOG(("browser window clicked at %d,%d", cbi->x, cbi->y)); + + switch (cbi->event->type) { + case NSFB_EVENT_KEY_DOWN: + switch (cbi->event->value.keycode) { + case NSFB_KEY_MOUSE_1: + browser_window_mouse_click(gw->bw, + BROWSER_MOUSE_PRESS_1, + cbi->x + bwidget->scrollx, + cbi->y + bwidget->scrolly); + break; + + case NSFB_KEY_MOUSE_3: + browser_window_mouse_click(gw->bw, + BROWSER_MOUSE_PRESS_2, + cbi->x + bwidget->scrollx, + cbi->y + bwidget->scrolly); + break; + + case NSFB_KEY_MOUSE_4: + /* scroll up */ + widget_scroll_y(gw, -100, false); + break; + + case NSFB_KEY_MOUSE_5: + /* scroll down */ + widget_scroll_y(gw, 100, false); + break; + + default: + break; + + } break; - case NSFB_EVENT_KEY_UP: - switch (cbi->event->value.keycode) { - case NSFB_KEY_MOUSE_1: - browser_window_mouse_click(bw, - BROWSER_MOUSE_CLICK_1, - cbi->x + bwidget->scrollx, - cbi->y + bwidget->scrolly); - break; - - case NSFB_KEY_MOUSE_3: - browser_window_mouse_click(bw, - BROWSER_MOUSE_CLICK_2, - cbi->x + bwidget->scrollx, - cbi->y + bwidget->scrolly); - break; - - default: - break; - - } + case NSFB_EVENT_KEY_UP: + switch (cbi->event->value.keycode) { + case NSFB_KEY_MOUSE_1: + browser_window_mouse_click(gw->bw, + BROWSER_MOUSE_CLICK_1, + cbi->x + bwidget->scrollx, + cbi->y + bwidget->scrolly); + break; + + case NSFB_KEY_MOUSE_3: + browser_window_mouse_click(gw->bw, + BROWSER_MOUSE_CLICK_2, + cbi->x + bwidget->scrollx, + cbi->y + bwidget->scrolly); + break; + + default: + break; + + } break; - default: - break; + default: + break; - } - return 1; + } + return 1; } /* called back when movement in browser window */ static int fb_browser_window_move(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - struct browser_window *bw = cbi->context; - struct browser_widget_s *bwidget = fbtk_get_userpw(widget); + struct gui_window *gw = cbi->context; + struct browser_widget_s *bwidget = fbtk_get_userpw(widget); - browser_window_mouse_track(bw, - 0, - cbi->x + bwidget->scrollx, - cbi->y + bwidget->scrolly); + browser_window_mouse_track(gw->bw, + 0, + cbi->x + bwidget->scrollx, + cbi->y + bwidget->scrolly); - return 0; + return 0; } static int fb_browser_window_input(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - struct gui_window *gw = cbi->context; - int res = 0; - static uint8_t modifier = 0; - int ucs4 = -1; - - LOG(("got value %d", cbi->event->value.keycode)); - - switch (cbi->event->type) { - case NSFB_EVENT_KEY_DOWN: - switch (cbi->event->value.keycode) { - - case NSFB_KEY_PAGEUP: - if (browser_window_key_press(gw->bw, KEY_PAGE_UP) == false) - fb_window_scroll(gw->browser, 0, -fbtk_get_height(gw->browser)); - break; - - case NSFB_KEY_PAGEDOWN: - if (browser_window_key_press(gw->bw, KEY_PAGE_DOWN) == false) - fb_window_scroll(gw->browser, 0, fbtk_get_height(gw->browser)); - break; - - case NSFB_KEY_RIGHT: - if (browser_window_key_press(gw->bw, KEY_RIGHT) == false) - fb_window_scroll(gw->browser, 100, 0); - break; - - case NSFB_KEY_LEFT: - if (browser_window_key_press(gw->bw, KEY_LEFT) == false) - fb_window_scroll(gw->browser, -100, 0); - break; - - case NSFB_KEY_UP: - if (browser_window_key_press(gw->bw, KEY_UP) == false) - fb_window_scroll(gw->browser, 0, -100); - break; - - case NSFB_KEY_DOWN: - if (browser_window_key_press(gw->bw, KEY_DOWN) == false) - fb_window_scroll(gw->browser, 0, 100); - break; - - case NSFB_KEY_RSHIFT: - modifier |= 1; - break; - - case NSFB_KEY_LSHIFT: - modifier |= 1<<1; - break; - - default: - ucs4 = fbtk_keycode_to_ucs4(cbi->event->value.keycode, + struct gui_window *gw = cbi->context; + int res = 0; + static uint8_t modifier = 0; + int ucs4 = -1; + + LOG(("got value %d", cbi->event->value.keycode)); + + switch (cbi->event->type) { + case NSFB_EVENT_KEY_DOWN: + switch (cbi->event->value.keycode) { + + case NSFB_KEY_PAGEUP: + if (browser_window_key_press(gw->bw, KEY_PAGE_UP) == false) + widget_scroll_y(gw, -fbtk_get_height(gw->browser), false); + break; + + case NSFB_KEY_PAGEDOWN: + if (browser_window_key_press(gw->bw, KEY_PAGE_DOWN) == false) + widget_scroll_y(gw, fbtk_get_height(gw->browser), false); + break; + + case NSFB_KEY_RIGHT: + if (browser_window_key_press(gw->bw, KEY_RIGHT) == false) + widget_scroll_x(gw, 100, false); + break; + + case NSFB_KEY_LEFT: + if (browser_window_key_press(gw->bw, KEY_LEFT) == false) + widget_scroll_x(gw, -100, false); + break; + + case NSFB_KEY_UP: + if (browser_window_key_press(gw->bw, KEY_UP) == false) + widget_scroll_y(gw, -100, false); + break; + + case NSFB_KEY_DOWN: + if (browser_window_key_press(gw->bw, KEY_DOWN) == false) + widget_scroll_y(gw, 100, false); + break; + + case NSFB_KEY_RSHIFT: + modifier |= 1; + break; + + case NSFB_KEY_LSHIFT: + modifier |= 1<<1; + break; + + default: + ucs4 = fbtk_keycode_to_ucs4(cbi->event->value.keycode, modifier); - if (ucs4 != -1) - res = browser_window_key_press(gw->bw, ucs4); - break; - } - break; + if (ucs4 != -1) + res = browser_window_key_press(gw->bw, ucs4); + break; + } + break; - case NSFB_EVENT_KEY_UP: - switch (cbi->event->value.keycode) { - case NSFB_KEY_RSHIFT: - modifier &= ~1; - break; + case NSFB_EVENT_KEY_UP: + switch (cbi->event->value.keycode) { + case NSFB_KEY_RSHIFT: + modifier &= ~1; + break; - case NSFB_KEY_LSHIFT: - modifier &= ~(1<<1); - break; + case NSFB_KEY_LSHIFT: + modifier &= ~(1<<1); + break; - default: - break; - } - break; + default: + break; + } + break; - default: - break; - } + default: + break; + } - return 0; + return 0; } static void @@ -686,79 +745,91 @@ fb_update_back_forward(struct gui_window *gw) /* left icon click routine */ static int -fb_leftarrow_click(fbtk_widget_t *widget,fbtk_callback_info *cbi) +fb_leftarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - struct gui_window *gw = cbi->context; - struct browser_window *bw = gw->bw; + struct gui_window *gw = cbi->context; + struct browser_window *bw = gw->bw; - if (cbi->event->type != NSFB_EVENT_KEY_DOWN) - return 0; + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; - if (history_back_available(bw->history)) - history_back(bw, bw->history); + if (history_back_available(bw->history)) + history_back(bw, bw->history); - fb_update_back_forward(gw); + fb_update_back_forward(gw); - return 1; + return 1; } /* right arrow icon click routine */ static int -fb_rightarrow_click(fbtk_widget_t *widget,fbtk_callback_info *cbi) +fb_rightarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - struct gui_window *gw = cbi->context; - struct browser_window *bw = gw->bw; + struct gui_window *gw = cbi->context; + struct browser_window *bw = gw->bw; - if (cbi->event->type != NSFB_EVENT_KEY_DOWN) - return 0; + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; - if (history_forward_available(bw->history)) - history_forward(bw, bw->history); + if (history_forward_available(bw->history)) + history_forward(bw, bw->history); - fb_update_back_forward(gw); - return 1; + fb_update_back_forward(gw); + return 1; } /* reload icon click routine */ static int -fb_reload_click(fbtk_widget_t *widget,fbtk_callback_info *cbi) +fb_reload_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - struct browser_window *bw = cbi->context; + struct browser_window *bw = cbi->context; - if (cbi->event->type != NSFB_EVENT_KEY_DOWN) - return 0; + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; - browser_window_reload(bw, true); - return 1; + browser_window_reload(bw, true); + return 1; } /* stop icon click routine */ static int -fb_stop_click(fbtk_widget_t *widget,fbtk_callback_info *cbi) +fb_stop_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - struct browser_window *bw = cbi->context; + struct browser_window *bw = cbi->context; - if (cbi->event->type != NSFB_EVENT_KEY_DOWN) - return 0; + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; browser_window_stop(bw); - return 0; + return 0; +} + +static int +fb_osk_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; + + map_osk(); + + return 0; } static int fb_scroll_callback(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - struct gui_window *gw = cbi->context; + struct gui_window *gw = cbi->context; switch (cbi->type) { case FBTK_CBT_SCROLLY: - fb_window_scroll(gw->browser, 0, 100 * cbi->y); + widget_scroll_y(gw, cbi->y, true); break; - + case FBTK_CBT_SCROLLX: - fb_window_scroll(gw->browser, 100 * cbi->x, 0); + widget_scroll_x(gw, cbi->x, true); break; default: @@ -770,470 +841,554 @@ fb_scroll_callback(fbtk_widget_t *widget, fbtk_callback_info *cbi) static int fb_url_enter(void *pw, char *text) { - struct browser_window *bw = pw; - browser_window_go(bw, text, 0, true); - return 0; + struct browser_window *bw = pw; + browser_window_go(bw, text, 0, true); + return 0; } static int fb_url_move(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - framebuffer_set_cursor(&caret_image); - return 0; + framebuffer_set_cursor(&caret_image); + return 0; } static int set_ptr_default_move(fbtk_widget_t *widget, fbtk_callback_info *cbi) { - framebuffer_set_cursor(&pointer_image); - return 0; + framebuffer_set_cursor(&pointer_image); + return 0; } -struct gui_window * -gui_create_browser_window(struct browser_window *bw, - struct browser_window *clone, - bool new_tab) +static int +fb_localhistory_btn_clik(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + struct gui_window *gw = cbi->context; + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; + + fb_localhistory_map(gw->localhistory); + + return 0; +} + + + +static void +create_toolbar(struct gui_window *gw, int toolbar_height) +{ + fbtk_widget_t *toolbar; + fbtk_widget_t *widget; + int url_bar_height = 0; + int xpos = 0; + int spacing_width = 0; + + spacing_width = 2; + + xpos = spacing_width; + + url_bar_height = toolbar_height - 6; + + toolbar = fbtk_create_window(gw->window, 0, 0, 0, toolbar_height, FB_FRAME_COLOUR); + fbtk_set_handler(toolbar, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL); + + /* back button */ + gw->back = fbtk_create_button(toolbar, xpos, spacing_width, left_arrow.width, -spacing_width, FB_FRAME_COLOUR, &left_arrow, fb_leftarrow_click, gw); + xpos += left_arrow.width + spacing_width; + + /* history window */ + widget = fbtk_create_button(toolbar, + xpos, + spacing_width, + history_image.width, + -spacing_width, + FB_FRAME_COLOUR, + &history_image, + fb_localhistory_btn_clik, + gw); + xpos += fbtk_get_width(widget) + spacing_width; + + /* forward button */ + gw->forward = fbtk_create_button(toolbar, + xpos, + spacing_width, + right_arrow.width, + -spacing_width, + FB_FRAME_COLOUR, + &right_arrow, + fb_rightarrow_click, + gw); + xpos += right_arrow.width + spacing_width; + + /* stop button */ + widget = fbtk_create_button(toolbar, + xpos, + spacing_width, + stop_image.width, + -spacing_width, + FB_FRAME_COLOUR, + &stop_image, + fb_stop_click, + gw->bw); + xpos += stop_image.width + spacing_width; + + /* reload button */ + widget = fbtk_create_button(toolbar, + xpos, + spacing_width, + reload.width, + -spacing_width, + FB_FRAME_COLOUR, + &reload, + fb_reload_click, + gw->bw); + xpos += reload.width + spacing_width; + + /* url widget */ + xpos += spacing_width; /* extra spacing for url bar */ + gw->url = fbtk_create_writable_text(toolbar, + xpos, + spacing_width, + -(spacing_width + throbber0.width), + -spacing_width, + FB_COLOUR_WHITE, + FB_COLOUR_BLACK, + true, + fb_url_enter, + gw->bw); + fbtk_set_handler(gw->url, FBTK_CBT_POINTERENTER, fb_url_move, gw->bw); + xpos += fbtk_get_width(gw->url) + spacing_width; + + /* throbber */ + gw->throbber = fbtk_create_bitmap(toolbar, + xpos, + spacing_width, + throbber0.width, + -spacing_width, + FB_FRAME_COLOUR, &throbber0); + + fbtk_set_mapping(toolbar, true); + +} + +static void +create_normal_browser_window(struct gui_window *gw, + int furniture_width, + int toolbar_height) { - struct gui_window *gw; - struct browser_widget_s *browser_widget; - fbtk_widget_t *widget; - int toolbar_height = 0; - int furniture_width = 0; - int spacing_width = 0; - int url_bar_height = 0; - int statusbar_width = 0; - int xpos = 0; + fbtk_widget_t *widget; + int statusbar_width = 0; - gw = calloc(1, sizeof(struct gui_window)); + gw->window = fbtk_create_window(fbtk, 0, 0, 0, 0, 0); - if (gw == NULL) - return NULL; + statusbar_width = option_toolbar_status_width * + fbtk_get_width(gw->window) / 10000; - /* seems we need to associate the gui window with the underlying - * browser window - */ - gw->bw = bw; + LOG(("Normal window")); - switch(bw->browser_window_type) { - case BROWSER_WINDOW_NORMAL: - gw->window = fbtk_create_window(fbtk, 0, 0, 0, 0); - - /* area and widget dimensions */ - toolbar_height = 30; - furniture_width = 18; - spacing_width = 2; - url_bar_height = 24; - - statusbar_width = option_toolbar_status_width * - fbtk_get_width(gw->window) / 10000; - - xpos = spacing_width; - - LOG(("Normal window")); - - /* fill toolbar background */ - widget = fbtk_create_fill(gw->window, - 0, 0, 0, toolbar_height, - FB_FRAME_COLOUR); - fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, set_ptr_default_move, bw); - - /* back button */ - gw->back = fbtk_create_button(gw->window, - xpos, (toolbar_height - left_arrow.height) / 2, - FB_FRAME_COLOUR, &left_arrow, - fb_leftarrow_click, gw); - xpos += left_arrow.width + spacing_width; - - /* forward button */ - gw->forward = fbtk_create_button(gw->window, - xpos, (toolbar_height - right_arrow.height) / 2, - FB_FRAME_COLOUR, &right_arrow, - fb_rightarrow_click, gw); - xpos += right_arrow.width + spacing_width; - - /* reload button */ - widget = fbtk_create_button(gw->window, - xpos, (toolbar_height - stop_image.height) / 2, - FB_FRAME_COLOUR, &stop_image, - fb_stop_click, bw); - xpos += stop_image.width + spacing_width; - - /* reload button */ - widget = fbtk_create_button(gw->window, - xpos, (toolbar_height - reload.height) / 2, - FB_FRAME_COLOUR, &reload, - fb_reload_click, bw); - xpos += reload.width + spacing_width; - - /* url widget */ - xpos += 1; /* extra spacing for url bar */ - gw->url = fbtk_create_writable_text(gw->window, - xpos, (toolbar_height - url_bar_height) / 2, - fbtk_get_width(gw->window) - xpos - - spacing_width - spacing_width - - throbber0.width, - url_bar_height, - FB_COLOUR_WHITE, FB_COLOUR_BLACK, - true, fb_url_enter, bw); - fbtk_set_handler(gw->url, FBTK_CBT_POINTERMOVE, fb_url_move, bw); - xpos += fbtk_get_width(gw->window) - xpos - - spacing_width - throbber0.width; - - /* throbber */ - gw->throbber = fbtk_create_bitmap(gw->window, - xpos, (toolbar_height - throbber0.height) / 2, - FB_FRAME_COLOUR, &throbber0); - - - - /* status bar */ - xpos = 0; - gw->status = fbtk_create_text(gw->window, - xpos, - fbtk_get_height(gw->window) - furniture_width, - statusbar_width, furniture_width, - FB_FRAME_COLOUR, FB_COLOUR_BLACK, - false); - fbtk_set_handler(gw->status, FBTK_CBT_POINTERMOVE, set_ptr_default_move, bw); - - /* create horizontal scrollbar */ - gw->hscroll = fbtk_create_hscroll(gw->window, - statusbar_width, - fbtk_get_height(gw->window) - furniture_width, - fbtk_get_width(gw->window) - statusbar_width - furniture_width, - furniture_width, - FB_SCROLL_COLOUR, - FB_FRAME_COLOUR, - fb_scroll_callback, - gw); - - /* fill bottom right area */ - widget = fbtk_create_fill(gw->window, - fbtk_get_width(gw->window) - furniture_width, - fbtk_get_height(gw->window) - furniture_width, - furniture_width, - furniture_width, - FB_FRAME_COLOUR); - fbtk_set_handler(widget, FBTK_CBT_POINTERMOVE, set_ptr_default_move, bw); + create_toolbar(gw, toolbar_height); - /* create vertical scrollbar */ - gw->vscroll = fbtk_create_vscroll(gw->window, - fbtk_get_width(gw->window) - furniture_width, - toolbar_height, - furniture_width, - fbtk_get_height(gw->window) - toolbar_height - furniture_width, - FB_SCROLL_COLOUR, - FB_FRAME_COLOUR, - fb_scroll_callback, - gw); + /* status bar */ + gw->status = fbtk_create_text(gw->window, + 0, + fbtk_get_height(gw->window) - furniture_width, + statusbar_width, furniture_width, + FB_FRAME_COLOUR, FB_COLOUR_BLACK, + false); + fbtk_set_handler(gw->status, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL); + LOG(("status bar %p at %d,%d", gw->status, fbtk_get_absx(gw->status), fbtk_get_absy(gw->status))); - break; + /* create horizontal scrollbar */ + gw->hscroll = fbtk_create_hscroll(gw->window, + statusbar_width, + fbtk_get_height(gw->window) - furniture_width, + fbtk_get_width(gw->window) - statusbar_width - furniture_width, + furniture_width, + FB_SCROLL_COLOUR, + FB_FRAME_COLOUR, + fb_scroll_callback, + gw); + + /* fill bottom right area */ + + if (option_fb_osk == true) { + widget = fbtk_create_text_button(gw->window, + fbtk_get_width(gw->window) - furniture_width, + fbtk_get_height(gw->window) - furniture_width, + furniture_width, + furniture_width, + FB_FRAME_COLOUR, FB_COLOUR_BLACK, + fb_osk_click, + NULL); + fbtk_set_text(widget, "\xe2\x8c\xa8"); + } else { + widget = fbtk_create_fill(gw->window, + fbtk_get_width(gw->window) - furniture_width, + fbtk_get_height(gw->window) - furniture_width, + furniture_width, + furniture_width, + FB_FRAME_COLOUR); + + fbtk_set_handler(widget, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL); + } - case BROWSER_WINDOW_FRAME: - gw->window = fbtk_create_window(bw->parent->window->window, 0, 0, 0, 0); - LOG(("create frame")); - break; + /* create vertical scrollbar */ + gw->vscroll = fbtk_create_vscroll(gw->window, + fbtk_get_width(gw->window) - furniture_width, + toolbar_height, + furniture_width, + fbtk_get_height(gw->window) - toolbar_height - furniture_width, + FB_SCROLL_COLOUR, + FB_FRAME_COLOUR, + fb_scroll_callback, + gw); - default: - gw->window = fbtk_create_window(bw->parent->window->window, 0, 0, 0, 0); - LOG(("unhandled type")); - } +} - browser_widget = calloc(1, sizeof(struct browser_widget_s)); +static void +create_browser_widget(struct gui_window *gw, int toolbar_height, int furniture_width) +{ + struct browser_widget_s *browser_widget; + browser_widget = calloc(1, sizeof(struct browser_widget_s)); - gw->browser = fbtk_create_user(gw->window, 0, toolbar_height, -furniture_width, - (furniture_width + toolbar_height), browser_widget); + gw->browser = fbtk_create_user(gw->window, + 0, + toolbar_height, + -furniture_width, + -furniture_width, + browser_widget); fbtk_set_handler(gw->browser, FBTK_CBT_REDRAW, fb_browser_window_redraw, gw); fbtk_set_handler(gw->browser, FBTK_CBT_INPUT, fb_browser_window_input, gw); - fbtk_set_handler(gw->browser, FBTK_CBT_CLICK, fb_browser_window_click, bw); - fbtk_set_handler(gw->browser, FBTK_CBT_POINTERMOVE, fb_browser_window_move, bw); - - return gw; + fbtk_set_handler(gw->browser, FBTK_CBT_CLICK, fb_browser_window_click, gw); + fbtk_set_handler(gw->browser, FBTK_CBT_POINTERMOVE, fb_browser_window_move, gw); } -void gui_window_destroy(struct gui_window *gw) +struct gui_window * +gui_create_browser_window(struct browser_window *bw, + struct browser_window *clone, + bool new_tab) { - fbtk_destroy_widget(gw->window); + struct gui_window *gw; + + gw = calloc(1, sizeof(struct gui_window)); + + if (gw == NULL) + return NULL; + + /* seems we need to associate the gui window with the underlying + * browser window + */ + gw->bw = bw; + - free(gw); + switch(bw->browser_window_type) { + case BROWSER_WINDOW_NORMAL: + create_normal_browser_window(gw, option_fb_furniture_size, option_fb_toolbar_size); + gw->localhistory = fb_create_localhistory(bw, fbtk, option_fb_furniture_size); + create_browser_widget(gw, option_fb_toolbar_size, option_fb_furniture_size); + + /* map and request redraw of gui window */ + fbtk_set_mapping(gw->window, true); + + break; + + case BROWSER_WINDOW_FRAME: + gw->window = fbtk_create_window(bw->parent->window->window, 0, 0, 0, 0, 0); + create_browser_widget(gw, 0, 0); + LOG(("create frame")); + break; + + default: + gw->window = fbtk_create_window(bw->parent->window->window, 0, 0, 0, 0, 0); + create_browser_widget(gw, 0, 0); + LOG(("unhandled type")); + } + return gw; } -void gui_window_set_title(struct gui_window *g, const char *title) +void +gui_window_destroy(struct gui_window *gw) { - LOG(("%p, %s", g, title)); -} + fbtk_destroy_widget(gw->window); + free(gw); -void fb_window_scroll(struct fbtk_widget_s *browser, int x, int y) -{ - struct browser_widget_s *bwidget = fbtk_get_userpw(browser); - LOG(("window scroll")); - bwidget->panx += x; - bwidget->pany += y; - bwidget->pan_required = true; +} - fbtk_request_redraw(browser); +void +gui_window_set_title(struct gui_window *g, const char *title) +{ + LOG(("%p, %s", g, title)); } -void gui_window_redraw(struct gui_window *g, int x0, int y0, int x1, int y1) +void +gui_window_redraw(struct gui_window *g, int x0, int y0, int x1, int y1) { - fb_queue_redraw(g->browser, x0, y0, x1, y1); + fb_queue_redraw(g->browser, x0, y0, x1, y1); } -void gui_window_redraw_window(struct gui_window *g) +void +gui_window_redraw_window(struct gui_window *g) { - fb_queue_redraw(g->browser, 0, 0, fbtk_get_width(g->browser),fbtk_get_height(g->browser) ); + fb_queue_redraw(g->browser, 0, 0, fbtk_get_width(g->browser), fbtk_get_height(g->browser) ); } -void gui_window_update_box(struct gui_window *g, - const union content_msg_data *data) +void +gui_window_update_box(struct gui_window *g, const union content_msg_data *data) { - struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser); - fb_queue_redraw(g->browser, - data->redraw.x - bwidget->scrollx, - data->redraw.y - bwidget->scrolly, - data->redraw.x - bwidget->scrollx + - data->redraw.width, - data->redraw.y - bwidget->scrolly + - data->redraw.height); + struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser); + fb_queue_redraw(g->browser, + data->redraw.x - bwidget->scrollx, + data->redraw.y - bwidget->scrolly, + data->redraw.x - bwidget->scrollx + + data->redraw.width, + data->redraw.y - bwidget->scrolly + + data->redraw.height); } -bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy) +bool +gui_window_get_scroll(struct gui_window *g, int *sx, int *sy) { - struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser); + struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser); - *sx = bwidget->scrollx; - *sy = bwidget->scrolly; + *sx = bwidget->scrollx; + *sy = bwidget->scrolly; - return true; + return true; } -void gui_window_set_scroll(struct gui_window *g, int sx, int sy) +void +gui_window_set_scroll(struct gui_window *gw, int sx, int sy) { - struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser); + struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser); assert(bwidget); - bwidget->panx = sx - bwidget->scrollx; - bwidget->pany = sy - bwidget->scrolly; - - bwidget->pan_required = true; - - fbtk_request_redraw(g->browser); + widget_scroll_x(gw, sx, true); + widget_scroll_y(gw, sy, true); } -void gui_window_scroll_visible(struct gui_window *g, int x0, int y0, - int x1, int y1) +void +gui_window_scroll_visible(struct gui_window *g, int x0, int y0, + int x1, int y1) { - LOG(("%s:(%p, %d, %d, %d, %d)", __func__, g, x0, y0, x1, y1)); + LOG(("%s:(%p, %d, %d, %d, %d)", __func__, g, x0, y0, x1, y1)); } -void gui_window_position_frame(struct gui_window *g, int x0, int y0, - int x1, int y1) +void +gui_window_position_frame(struct gui_window *g, int x0, int y0, int x1, int y1) { - struct gui_window *parent; - int px, py; - int w, h; - LOG(("%s: %d, %d, %d, %d", g->bw->name, x0, y0, x1, y1)); - parent = g->bw->parent->window; + struct gui_window *parent; + int px, py; + int w, h; + LOG(("%s: %d, %d, %d, %d", g->bw->name, x0, y0, x1, y1)); + parent = g->bw->parent->window; - if (parent->window == NULL) - return; /* doesnt have an fbtk widget */ + if (parent->window == NULL) + return; /* doesnt have an fbtk widget */ - px = fbtk_get_x(parent->browser) + x0; - py = fbtk_get_y(parent->browser) + y0; - w = x1 - x0; - h = y1 - y0; - if (w > (fbtk_get_width(parent->browser) - px)) - w = fbtk_get_width(parent->browser) - px; + px = fbtk_get_absx(parent->browser) + x0; + py = fbtk_get_absy(parent->browser) + y0; + w = x1 - x0; + h = y1 - y0; + if (w > (fbtk_get_width(parent->browser) - px)) + w = fbtk_get_width(parent->browser) - px; - if (h > (fbtk_get_height(parent->browser) - py)) - h = fbtk_get_height(parent->browser) - py; + if (h > (fbtk_get_height(parent->browser) - py)) + h = fbtk_get_height(parent->browser) - py; - fbtk_set_pos_and_size(g->window, px, py , w , h); + fbtk_set_pos_and_size(g->window, px, py , w , h); - fbtk_request_redraw(parent->browser); + fbtk_request_redraw(parent->browser); } -void gui_window_get_dimensions(struct gui_window *g, int *width, int *height, - bool scaled) +void +gui_window_get_dimensions(struct gui_window *g, + int *width, + int *height, + bool scaled) { - *width = fbtk_get_width(g->browser); - *height = fbtk_get_height(g->browser); + *width = fbtk_get_width(g->browser); + *height = fbtk_get_height(g->browser); } -void gui_window_update_extent(struct gui_window *gw) +void +gui_window_update_extent(struct gui_window *gw) { - int pct; - int width; - int height; + fbtk_set_scroll_parameters(gw->hscroll, 0, content_get_width(gw->bw->current_content), fbtk_get_width(gw->browser), 100); - width = content_get_width(gw->bw->current_content); - if (width != 0) { - pct = (fbtk_get_width(gw->browser) * 100) / width; - fbtk_set_scroll(gw->hscroll, pct); - } + fbtk_set_scroll_parameters(gw->vscroll, 0, content_get_height(gw->bw->current_content), fbtk_get_height(gw->browser), 100); - height = content_get_height(gw->bw->current_content); - if (height != 0) { - pct = (fbtk_get_height(gw->browser) * 100) / height; - fbtk_set_scroll(gw->vscroll, pct); - } } -void gui_window_set_status(struct gui_window *g, const char *text) +void +gui_window_set_status(struct gui_window *g, const char *text) { - fbtk_set_text(g->status, text); + fbtk_set_text(g->status, text); } -void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape) +void +gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape) { - switch (shape) { - case GUI_POINTER_POINT: - framebuffer_set_cursor(&hand_image); - break; + switch (shape) { + case GUI_POINTER_POINT: + framebuffer_set_cursor(&hand_image); + break; - case GUI_POINTER_CARET: - framebuffer_set_cursor(&caret_image); - break; + case GUI_POINTER_CARET: + framebuffer_set_cursor(&caret_image); + break; - case GUI_POINTER_MENU: - framebuffer_set_cursor(&menu_image); - break; + case GUI_POINTER_MENU: + framebuffer_set_cursor(&menu_image); + break; - case GUI_POINTER_PROGRESS: - framebuffer_set_cursor(&progress_image); - break; + case GUI_POINTER_PROGRESS: + framebuffer_set_cursor(&progress_image); + break; - default: - framebuffer_set_cursor(&pointer_image); - break; - } + default: + framebuffer_set_cursor(&pointer_image); + break; + } } -void gui_window_hide_pointer(struct gui_window *g) +void +gui_window_hide_pointer(struct gui_window *g) { } -void gui_window_set_url(struct gui_window *g, const char *url) +void +gui_window_set_url(struct gui_window *g, const char *url) { - fbtk_set_text(g->url, url); + fbtk_set_text(g->url, url); } static void throbber_advance(void *pw) { - struct gui_window *g = pw; - struct bitmap *image; - - switch (g->throbber_index) { - case 0: - image = &throbber1; - g->throbber_index = 1; - break; - - case 1: - image = &throbber2; - g->throbber_index = 2; - break; - - case 2: - image = &throbber3; - g->throbber_index = 3; - break; - - case 3: - image = &throbber4; - g->throbber_index = 4; - break; - - case 4: - image = &throbber5; - g->throbber_index = 5; - break; - - case 5: - image = &throbber6; - g->throbber_index = 6; - break; - - case 6: - image = &throbber7; - g->throbber_index = 7; - break; - - case 7: - image = &throbber8; - g->throbber_index = 0; - break; + struct gui_window *g = pw; + struct bitmap *image; + + switch (g->throbber_index) { + case 0: + image = &throbber1; + g->throbber_index = 1; + break; + + case 1: + image = &throbber2; + g->throbber_index = 2; + break; + + case 2: + image = &throbber3; + g->throbber_index = 3; + break; + + case 3: + image = &throbber4; + g->throbber_index = 4; + break; + + case 4: + image = &throbber5; + g->throbber_index = 5; + break; + + case 5: + image = &throbber6; + g->throbber_index = 6; + break; + + case 6: + image = &throbber7; + g->throbber_index = 7; + break; + + case 7: + image = &throbber8; + g->throbber_index = 0; + break; default: return; - } + } - if (g->throbber_index >= 0) { - fbtk_set_bitmap(g->throbber, image); - schedule(10, throbber_advance, g); - } + if (g->throbber_index >= 0) { + fbtk_set_bitmap(g->throbber, image); + schedule(10, throbber_advance, g); + } } -void gui_window_start_throbber(struct gui_window *g) +void +gui_window_start_throbber(struct gui_window *g) { - g->throbber_index = 0; - schedule(10, throbber_advance, g); + g->throbber_index = 0; + schedule(10, throbber_advance, g); } -void gui_window_stop_throbber(struct gui_window *gw) +void +gui_window_stop_throbber(struct gui_window *gw) { - gw->throbber_index = -1; - fbtk_set_bitmap(gw->throbber, &throbber0); + gw->throbber_index = -1; + fbtk_set_bitmap(gw->throbber, &throbber0); - fb_update_back_forward(gw); + fb_update_back_forward(gw); } -void gui_window_place_caret(struct gui_window *g, int x, int y, int height) +void +gui_window_place_caret(struct gui_window *g, int x, int y, int height) { } -void gui_window_remove_caret(struct gui_window *g) +void +gui_window_remove_caret(struct gui_window *g) { } -void gui_window_new_content(struct gui_window *g) +void +gui_window_new_content(struct gui_window *g) { } -bool gui_window_scroll_start(struct gui_window *g) +bool +gui_window_scroll_start(struct gui_window *g) { return true; } -bool gui_window_box_scroll_start(struct gui_window *g, - int x0, int y0, int x1, int y1) +bool +gui_window_box_scroll_start(struct gui_window *g, + int x0, int y0, int x1, int y1) { return true; } -bool gui_window_frame_resize_start(struct gui_window *g) +bool +gui_window_frame_resize_start(struct gui_window *g) { LOG(("resize frame\n")); return true; } -void +void gui_window_save_link(struct gui_window *g, const char *url, const char *title) { } -void gui_window_set_scale(struct gui_window *g, float scale) +void +gui_window_set_scale(struct gui_window *g, float scale) { LOG(("set scale\n")); } @@ -1247,85 +1402,103 @@ gui_window_set_icon(struct gui_window *g, hlcache_handle *icon) } /** -* set gui display of a retrieved favicon representing the search provider -* \param ico may be NULL for local calls; then access current cache from -* search_web_ico() -*/ + * set gui display of a retrieved favicon representing the search provider + * \param ico may be NULL for local calls; then access current cache from + * search_web_ico() + */ void gui_window_set_search_ico(hlcache_handle *ico) { } -struct gui_download_window *gui_download_window_create(download_context *ctx, - struct gui_window *parent) +struct gui_download_window * +gui_download_window_create(download_context *ctx, struct gui_window *parent) { - return NULL; + return NULL; } -nserror gui_download_window_data(struct gui_download_window *dw, - const char *data, unsigned int size) +nserror +gui_download_window_data(struct gui_download_window *dw, + const char *data, + unsigned int size) { return NSERROR_OK; } -void gui_download_window_error(struct gui_download_window *dw, - const char *error_msg) +void +gui_download_window_error(struct gui_download_window *dw, + const char *error_msg) { } -void gui_download_window_done(struct gui_download_window *dw) +void +gui_download_window_done(struct gui_download_window *dw) { } -void gui_drag_save_object(gui_save_type type, hlcache_handle *c, - struct gui_window *w) +void +gui_drag_save_object(gui_save_type type, + hlcache_handle *c, + struct gui_window *w) { } -void gui_drag_save_selection(struct selection *s, struct gui_window *g) +void +gui_drag_save_selection(struct selection *s, struct gui_window *g) { } -void gui_start_selection(struct gui_window *g) +void +gui_start_selection(struct gui_window *g) { } -void gui_paste_from_clipboard(struct gui_window *g, int x, int y) +void +gui_paste_from_clipboard(struct gui_window *g, int x, int y) { } -bool gui_empty_clipboard(void) +bool +gui_empty_clipboard(void) { - return false; + return false; } -bool gui_add_to_clipboard(const char *text, size_t length, bool space) +bool +gui_add_to_clipboard(const char *text, size_t length, bool space) { - return false; + return false; } -bool gui_commit_clipboard(void) +bool +gui_commit_clipboard(void) { - return false; + return false; } -bool gui_copy_to_clipboard(struct selection *s) +bool +gui_copy_to_clipboard(struct selection *s) { - return false; + return false; } -void gui_create_form_select_menu(struct browser_window *bw, - struct form_control *control) +void +gui_create_form_select_menu(struct browser_window *bw, + struct form_control *control) { } -void gui_launch_url(const char *url) +void +gui_launch_url(const char *url) { } -void gui_cert_verify(const char *url, const struct ssl_cert_info *certs, - unsigned long num, - nserror (*cb)(bool proceed, void *pw), void *cbpw) +void +gui_cert_verify(const char *url, + const struct ssl_cert_info *certs, + unsigned long num, + nserror (*cb)(bool proceed, void *pw), + void *cbpw) { cb(false, cbpw); } diff --git a/framebuffer/gui.h b/framebuffer/gui.h index 98110ac6c..c1fa3cc1d 100644 --- a/framebuffer/gui.h +++ b/framebuffer/gui.h @@ -24,26 +24,41 @@ typedef struct fb_cursor_s fb_cursor_t; /* bounding box */ typedef struct nsfb_bbox_s bbox_t; +struct gui_localhistory { + struct browser_window *bw; + + struct fbtk_widget_s *window; + struct fbtk_widget_s *hscroll; + struct fbtk_widget_s *vscroll; + struct fbtk_widget_s *history; + + int scrollx, scrolly; /**< scroll offsets. */ +}; + struct gui_window { - struct browser_window *bw; - - struct fbtk_widget_s *window; - struct fbtk_widget_s *back; - struct fbtk_widget_s *forward; - struct fbtk_widget_s *url; - struct fbtk_widget_s *status; - struct fbtk_widget_s *throbber; - struct fbtk_widget_s *hscroll; - struct fbtk_widget_s *vscroll; - struct fbtk_widget_s *browser; - int throbber_index; + struct browser_window *bw; + + struct fbtk_widget_s *window; + struct fbtk_widget_s *back; + struct fbtk_widget_s *forward; + struct fbtk_widget_s *url; + struct fbtk_widget_s *status; + struct fbtk_widget_s *throbber; + struct fbtk_widget_s *hscroll; + struct fbtk_widget_s *vscroll; + struct fbtk_widget_s *browser; + + int throbber_index; + + struct gui_localhistory *localhistory; }; extern struct gui_window *window_list; -/* scroll a window */ -void fb_window_scroll(struct fbtk_widget_s *browser, int x, int y); +struct gui_localhistory *fb_create_localhistory(struct browser_window *bw, struct fbtk_widget_s *parent, int furniture_width); +void fb_localhistory_map(struct gui_localhistory * glh); + #endif /* NETSURF_FB_GUI_H */ @@ -52,5 +67,3 @@ void fb_window_scroll(struct fbtk_widget_s *browser, int x, int y); * c-basic-offset:8 * End: */ - - diff --git a/framebuffer/image_data.h b/framebuffer/image_data.h index fcf1c366f..42c9900fd 100644 --- a/framebuffer/image_data.h +++ b/framebuffer/image_data.h @@ -25,10 +25,13 @@ extern struct bitmap left_arrow; extern struct bitmap right_arrow; extern struct bitmap reload; extern struct bitmap stop_image; +extern struct bitmap history_image; + extern struct bitmap left_arrow_g; extern struct bitmap right_arrow_g; extern struct bitmap reload_g; extern struct bitmap stop_image_g; +extern struct bitmap history_image_g; extern struct bitmap scrolll; extern struct bitmap scrollr; diff --git a/framebuffer/localhistory.c b/framebuffer/localhistory.c new file mode 100644 index 000000000..76e4bd989 --- /dev/null +++ b/framebuffer/localhistory.c @@ -0,0 +1,162 @@ +/* + * Copyright 2010 Vincent Sanders + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "desktop/gui.h" +#include "desktop/plotters.h" +#include "desktop/netsurf.h" +#include "desktop/options.h" +#include "utils/log.h" +#include "utils/url.h" +#include "utils/messages.h" +#include "utils/utils.h" +#include "desktop/textinput.h" +#include "render/form.h" + +#include "framebuffer/gui.h" +#include "framebuffer/fbtk.h" +#include "framebuffer/framebuffer.h" +#include "framebuffer/bitmap.h" +#include "framebuffer/schedule.h" +#include "framebuffer/findfile.h" +#include "framebuffer/image_data.h" +#include "framebuffer/font.h" + +#include "content/urldb.h" +#include "desktop/history_core.h" +#include "content/fetch.h" + +static int +localhistory_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + struct gui_localhistory *glh = cbi->context; + nsfb_bbox_t rbox; + + rbox.x0 = fbtk_get_absx(widget); + rbox.y0 = fbtk_get_absy(widget); + + rbox.x1 = rbox.x0 + fbtk_get_width(widget); + rbox.y1 = rbox.y0 + fbtk_get_height(widget); + + nsfb_claim(fbtk_get_nsfb(widget), &rbox); + + nsfb_plot_rectangle_fill(fbtk_get_nsfb(widget), &rbox, 0xffffffff); + + history_redraw_rectangle(glh->bw->history, + glh->scrollx, + glh->scrolly, + fbtk_get_width(widget) + glh->scrollx, + fbtk_get_height(widget) + glh->scrolly, + 0, 0); + + nsfb_update(fbtk_get_nsfb(widget), &rbox); + + return 0; +} + +static int +localhistory_click(fbtk_widget_t *widget, fbtk_callback_info *cbi) +{ + struct gui_localhistory *glh = cbi->context; + + if (cbi->event->type != NSFB_EVENT_KEY_DOWN) + return 0; + + history_click(glh->bw, glh->bw->history, cbi->x, cbi->y, false); + + fbtk_set_mapping(glh->window, false); + + return 1; +} + +struct gui_localhistory * +fb_create_localhistory(struct browser_window *bw, + fbtk_widget_t *parent, + int furniture_width) +{ + struct gui_localhistory *glh; + glh = calloc(1, sizeof(struct gui_localhistory)); + + if (glh == NULL) + return NULL; + + glh->bw = bw; + + /* container window */ + glh->window = fbtk_create_window(parent, 0, 0, 0, 0, 0); + + glh->history = fbtk_create_user(glh->window, 0, 0, -furniture_width, -furniture_width, glh); + + fbtk_set_handler(glh->history, FBTK_CBT_REDRAW, localhistory_redraw, glh); + fbtk_set_handler(glh->history, FBTK_CBT_CLICK, localhistory_click, glh); + /* + fbtk_set_handler(gw->localhistory, FBTK_CBT_INPUT, fb_browser_window_input, gw); + fbtk_set_handler(gw->localhistory, FBTK_CBT_POINTERMOVE, fb_browser_window_move, bw); + */ + + /* create horizontal scrollbar */ + glh->hscroll = fbtk_create_hscroll(glh->window, + 0, + fbtk_get_height(glh->window) - furniture_width, + fbtk_get_width(glh->window) - furniture_width, + furniture_width, + FB_SCROLL_COLOUR, + FB_FRAME_COLOUR, + NULL, + NULL); + + glh->vscroll = fbtk_create_vscroll(glh->window, + fbtk_get_width(glh->window) - furniture_width, + 0, + furniture_width, + fbtk_get_height(glh->window) - furniture_width, + FB_SCROLL_COLOUR, + FB_FRAME_COLOUR, + NULL, + NULL); + + fbtk_create_fill(glh->window, + fbtk_get_width(glh->window) - furniture_width, + fbtk_get_height(glh->window) - furniture_width, + furniture_width, + furniture_width, + FB_FRAME_COLOUR); + + return glh; +} + +void +fb_localhistory_map(struct gui_localhistory * glh) +{ + fbtk_set_zorder(glh->window, INT_MIN); + fbtk_set_mapping(glh->window, true); +} diff --git a/framebuffer/options.h b/framebuffer/options.h index f2f52ae49..fff5fd192 100644 --- a/framebuffer/options.h +++ b/framebuffer/options.h @@ -1,5 +1,5 @@ /* - * Copyright 2008 Daniel Silverstone + * Copyright 2008, 2010 Daniel Silverstone * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -23,10 +23,14 @@ extern int option_fb_depth; extern int option_fb_refresh; -extern bool option_fb_font_monochrome; /* render font monochrome */ extern char *option_fb_device; extern char *option_fb_input_devpath; extern char *option_fb_input_glob; +extern int option_fb_furniture_size; /* toolkit furniture size */ +extern int option_fb_toolbar_size; /* toolbar furniture size */ +extern bool option_fb_osk; /* enable on screen keyboard */ + +extern bool option_fb_font_monochrome; /* render font monochrome */ extern char *option_fb_face_sans_serif; /* default sans face */ extern char *option_fb_face_sans_serif_bold; /* bold sans face */ extern char *option_fb_face_sans_serif_italic; /* bold sans face */ @@ -35,27 +39,33 @@ extern char *option_fb_face_monospace; /* monospace face */ extern char *option_fb_face_serif; /* serif face */ extern char *option_fb_face_serif_bold; /* bold serif face */ -#define EXTRA_OPTION_DEFINE \ - int option_fb_depth = 32; \ - int option_fb_refresh = 70; \ - bool option_fb_font_monochrome = false; \ - char *option_fb_device = 0; \ - char *option_fb_input_devpath = 0; \ - char *option_fb_input_glob = 0; \ - char *option_fb_face_sans_serif; \ - char *option_fb_face_sans_serif_bold; \ - char *option_fb_face_sans_serif_italic; \ - char *option_fb_face_sans_serif_italic_bold; \ - char *option_fb_face_monospace; \ - char *option_fb_face_serif; \ - char *option_fb_face_serif_bold; +#define EXTRA_OPTION_DEFINE \ + int option_fb_depth = 32; \ + int option_fb_refresh = 70; \ + char *option_fb_device = 0; \ + char *option_fb_input_devpath = 0; \ + char *option_fb_input_glob = 0; \ + int option_fb_furniture_size = 18; \ + int option_fb_toolbar_size = 30; \ + bool option_fb_osk = false; \ + bool option_fb_font_monochrome = false; \ + char *option_fb_face_sans_serif; \ + char *option_fb_face_sans_serif_bold; \ + char *option_fb_face_sans_serif_italic; \ + char *option_fb_face_sans_serif_italic_bold; \ + char *option_fb_face_monospace; \ + char *option_fb_face_serif; \ + char *option_fb_face_serif_bold; #define EXTRA_OPTION_TABLE \ - { "fb_depth", OPTION_INTEGER, &option_fb_depth }, \ - { "fb_refresh", OPTION_INTEGER, &option_fb_refresh }, \ + { "fb_depth", OPTION_INTEGER, &option_fb_depth }, \ + { "fb_refresh", OPTION_INTEGER, &option_fb_refresh }, \ { "fb_device", OPTION_STRING, &option_fb_device }, \ { "fb_input_devpath", OPTION_STRING, &option_fb_input_devpath }, \ { "fb_input_glob", OPTION_STRING, &option_fb_input_glob }, \ + { "fb_furniture_size", OPTION_INTEGER, &option_fb_furniture_size }, \ + { "fb_toolbar_size", OPTION_INTEGER, &option_fb_toolbar_size }, \ + { "fb_font_osk", OPTION_BOOL, &option_fb_osk }, \ { "fb_font_monochrome", OPTION_BOOL, &option_fb_font_monochrome }, \ { "fb_face_sans_serif", OPTION_STRING, &option_fb_face_sans_serif }, \ { "fb_face_sans_serif_bold", OPTION_STRING, &option_fb_face_sans_serif_bold }, \ @@ -63,6 +73,12 @@ extern char *option_fb_face_serif_bold; /* bold serif face */ { "fb_face_sans_serif_italic_bold", OPTION_STRING, &option_fb_face_sans_serif_italic_bold }, \ { "fb_face_monospace", OPTION_STRING, &option_fb_face_monospace }, \ { "fb_face_serif", OPTION_STRING, &option_fb_face_serif }, \ - { "fb_serif_bold", OPTION_STRING, &option_fb_face_serif_bold } + { "fb_serif_bold", OPTION_STRING, &option_fb_face_serif_bold } #endif + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/framebuffer/res/icons/history.png b/framebuffer/res/icons/history.png new file mode 100644 index 000000000..b124db7bf Binary files /dev/null and b/framebuffer/res/icons/history.png differ diff --git a/framebuffer/res/icons/history_g.png b/framebuffer/res/icons/history_g.png new file mode 100644 index 000000000..1597d54e7 Binary files /dev/null and b/framebuffer/res/icons/history_g.png differ diff --git a/framebuffer/thumbnail.c b/framebuffer/thumbnail.c index 81419d282..47340fd6c 100644 --- a/framebuffer/thumbnail.c +++ b/framebuffer/thumbnail.c @@ -17,9 +17,16 @@ */ #include "desktop/browser.h" +#include "content/urldb.h" -bool thumbnail_create(struct hlcache_handle *content, struct bitmap *bitmap, - const char *url) +bool +thumbnail_create(struct hlcache_handle *content, + struct bitmap *bitmap, + const char *url) { - return false; + /* register the thumbnail with the URL */ + if (url != NULL) + urldb_set_thumbnail(url, bitmap); + + return true; } -- cgit v1.2.3