/* 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) { fbtk_set_focus(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); }
/** * handler for toolkit window redraw event */ static int fb_cw_draw_event(fbtk_widget_t *widget, fbtk_callback_info *cbi) { struct fb_corewindow *fb_cw; nsfb_bbox_t rbox; struct rect clip; fb_cw = (struct fb_corewindow *)cbi->context; 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); clip.x0 = fb_cw->scrollx; clip.y0 = fb_cw->scrolly; clip.x1 = fbtk_get_width(widget) + fb_cw->scrollx; clip.y1 = fbtk_get_height(widget) + fb_cw->scrolly; fb_cw->draw(fb_cw, &clip); nsfb_update(fbtk_get_nsfb(widget), &rbox); return 0; }
static int do_redraw(nsfb_t *nsfb, fbtk_widget_t *widget) { nsfb_bbox_t plot_ctx; fbtk_widget_t *cwidget; /* child widget */ LOG(("DO REDRAW")); //__menuet__debug_out("\n***********\nDO REDRAW\n********\n"); /* 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) { LOG(("POST CALLBACK")); //__menuet__debug_out("\n***********\nPOST CALLBACK\n********\n"); fbtk_post_callback(widget, FBTK_CBT_REDRAW); } widget->redraw.needed = false; } LOG(("DO CHILD")); //__menuet__debug_out("\n***********\nDO CHILD\n********\n"); /* walk the widgets children if child flag is set */ if (widget->redraw.child) { LOG(("DO CHILD 2")); //__menuet__debug_out("\n***********\nDO CHILD 2\n********\n"); cwidget = widget->last_child; while (cwidget != NULL) { LOG(("DO CHILD 3 ZZZ")); //__menuet__debug_out("\n***********\nDO CHILD 3 ZZZ\n********\n"); do_redraw(nsfb, cwidget); cwidget = cwidget->prev; } LOG(("DO CHILD 4")); //__menuet__debug_out("\n***********\nDO CHILD 4\n********\n"); widget->redraw.child = false; } LOG(("SUP")); //__menuet__debug_out("\n***********\nFIN REDRAW\n********\n"); return 1; }
static int localhistory_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi) { struct gui_localhistory *glh = cbi->context; nsfb_bbox_t rbox; struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &fb_plotters }; 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, &ctx); 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_UP) 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); }
/* 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; } /* ensure cursor location lies within the root widget */ if (cloc.x0 < root->x) cloc.x0 = root->x; if (cloc.x0 >= (root->x + root->width)) cloc.x0 = (root->x + root->width) - 1; if (cloc.y0 < root->y) cloc.y0 = root->y; if (cloc.y0 >= (root->y + root->height)) cloc.y0 = (root->y + root->height) - 1; 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); }
static void fb_redraw(fbtk_widget_t *widget, struct browser_widget_s *bwidget, struct browser_window *bw) { int x; int y; int caret_x, caret_y, caret_h; struct rect clip; struct redraw_context ctx = { .interactive = true, .background_images = true, .plot = &fb_plotters }; nsfb_t *nsfb = fbtk_get_nsfb(widget); float scale = browser_window_get_scale(bw); LOG(("%d,%d to %d,%d", bwidget->redraw_box.x0, bwidget->redraw_box.y0, bwidget->redraw_box.x1, bwidget->redraw_box.y1)); 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; nsfb_claim(nsfb, &bwidget->redraw_box); /* redraw bounding box is relative to window */ clip.x0 = bwidget->redraw_box.x0; clip.y0 = bwidget->redraw_box.y0; clip.x1 = bwidget->redraw_box.x1; clip.y1 = bwidget->redraw_box.y1; browser_window_redraw(bw, (x - bwidget->scrollx) / scale, (y - bwidget->scrolly) / scale, &clip, &ctx); if (fbtk_get_caret(widget, &caret_x, &caret_y, &caret_h)) { /* This widget has caret, so render it */ nsfb_bbox_t line; nsfb_plot_pen_t pen; line.x0 = x - bwidget->scrollx + caret_x; line.y0 = y - bwidget->scrolly + caret_y; line.x1 = x - bwidget->scrollx + caret_x; line.y1 = y - bwidget->scrolly + caret_y + caret_h; pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID; pen.stroke_width = 1; pen.stroke_colour = 0xFF0000FF; nsfb_plot_line(nsfb, &line, &pen); } 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_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; } if (bwidget->pan_required) { fb_pan(widget, bwidget, gw->bw); } 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 int fb_browser_window_destroy(fbtk_widget_t *widget, fbtk_callback_info *cbi) { struct browser_widget_s *browser_widget; if (widget == NULL) { return 0; } /* Free private data */ browser_widget = fbtk_get_userpw(widget); free(browser_widget); 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) { int opt; LOG(("argc %d, argv %p", argc, argv)); fename = "mtl"; febpp = 32; fewidth = nsoption_int(window_width); if (fewidth <= 0) { fewidth = 800; } feheight = nsoption_int(window_height); if (feheight <= 0) { feheight = 480; } if ((nsoption_charp(homepage_url) != NULL) && (nsoption_charp(homepage_url)[0] != '\0')) { feurl = nsoption_charp(homepage_url); } else { feurl = NETSURF_HOMEPAGE; } while((opt = getopt(argc, argv, "f:b:w:h:")) != -1) { switch (opt) { case 'f': fename = optarg; break; case 'b': febpp = atoi(optarg); break; case 'w': fewidth = atoi(optarg); break; case 'h': feheight = atoi(optarg); break; default: fprintf(stderr, "Usage: %s [-f frontend] [-b bpp] url\n", argv[0]); return false; } } if (optind < argc) { feurl = argv[optind]; } return true; }
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); /* 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->scrolly += bwidget->pany; bwidget->scrollx += bwidget->panx; fb_queue_redraw(widget, 0, 0, width, height); /* ensure we don't try to scroll again */ bwidget->panx = 0; bwidget->pany = 0; bwidget->pan_required = false; return; } if (bwidget->pany < 0) { /* pan up by less then viewport height */ srcbox.x0 = x; srcbox.y0 = y; srcbox.x1 = srcbox.x0 + width; srcbox.y1 = srcbox.y0 + height + bwidget->pany; dstbox.x0 = x; dstbox.y0 = y - bwidget->pany; dstbox.x1 = dstbox.x0 + width; dstbox.y1 = dstbox.y0 + height + bwidget->pany; /* move part that remains visible up */ nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox); /* redraw newly exposed area */ bwidget->scrolly += bwidget->pany; fb_queue_redraw(widget, 0, 0, width, - bwidget->pany); } else if (bwidget->pany > 0) { /* pan down by less then viewport height */ srcbox.x0 = x; srcbox.y0 = y + bwidget->pany; srcbox.x1 = srcbox.x0 + width; srcbox.y1 = srcbox.y0 + height - bwidget->pany; dstbox.x0 = x; dstbox.y0 = y; dstbox.x1 = dstbox.x0 + width; dstbox.y1 = dstbox.y0 + height - bwidget->pany; /* move part that remains visible down */ nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox); /* redraw newly exposed area */ bwidget->scrolly += bwidget->pany; 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; srcbox.y1 = srcbox.y0 + height; dstbox.x0 = x - bwidget->panx; dstbox.y0 = y; dstbox.x1 = dstbox.x0 + width + bwidget->panx; dstbox.y1 = dstbox.y0 + height; /* move part that remains visible left */ nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox); /* redraw newly exposed area */ bwidget->scrollx += bwidget->panx; fb_queue_redraw(widget, 0, 0, -bwidget->panx, height); } else if (bwidget->panx > 0) { /* pan right by less then viewport width */ srcbox.x0 = x + bwidget->panx; srcbox.y0 = y; srcbox.x1 = srcbox.x0 + width - bwidget->panx; srcbox.y1 = srcbox.y0 + height; dstbox.x0 = x; dstbox.y0 = y; dstbox.x1 = dstbox.x0 + width - bwidget->panx; dstbox.y1 = dstbox.y0 + height; /* move part that remains visible right */ nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox); /* redraw newly exposed area */ bwidget->scrollx += bwidget->panx; fb_queue_redraw(widget, width - bwidget->panx, 0, width, height); } bwidget->pan_required = false; bwidget->panx = 0; bwidget->pany = 0; }
static void create_normal_browser_window(struct gui_window *gw, int furniture_width) { fbtk_widget_t *widget; fbtk_widget_t *toolbar; int statusbar_width = 0; int toolbar_height = nsoption_int(fb_toolbar_size); LOG(("Normal window")); gw->window = fbtk_create_window(fbtk, 0, 0, 0, 0, 0); statusbar_width = nsoption_int(toolbar_status_size) * fbtk_get_width(gw->window) / 10000; /* toolbar */ toolbar = create_toolbar(gw, toolbar_height, 2, FB_FRAME_COLOUR, nsoption_charp(fb_toolbar_layout)); /* set the actually created toolbar height */ if (toolbar != NULL) { toolbar_height = fbtk_get_height(toolbar); } else { toolbar_height = 0; } /* 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))); /* 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 (nsoption_bool(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); widget = fbtk_create_button(gw->window, fbtk_get_width(gw->window) - furniture_width, fbtk_get_height(gw->window) - furniture_width, furniture_width, furniture_width, FB_FRAME_COLOUR, &osk_image, fb_osk_click, NULL); } 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); } /* 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); /* browser widget */ create_browser_widget(gw, toolbar_height, nsoption_int(fb_furniture_size)); /* Give browser_window's user widget input focus */ fbtk_set_focus(gw->browser); }