Bug Summary

File:frontends/framebuffer/gui.c
Warning:line 1699, column 3
Value stored to 'widget' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name gui.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -I . -I include -I build/Linux-framebuffer -I frontends -I content/handlers -D WITH_JPEG -U WITH_PDF_EXPORT -D LIBICONV_PLUG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /usr/include/x86_64-linux-gnu -D WITH_CURL -D WITH_OPENSSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D UTF8PROC_EXPORTS -D WITH_UTF8PROC -D WITH_WEBP -I /usr/include/libpng16 -D WITH_PNG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include/ -D WITH_BMP -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_GIF -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NS_SVG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSSPRITE -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSPSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSLOG -D NETSURF_UA_FORMAT_STRING="Mozilla/5.0 (%s) NetSurf/%d.%d" -D NETSURF_HOMEPAGE="about:welcome" -D NETSURF_LOG_LEVEL=VERBOSE -D NETSURF_BUILTIN_LOG_FILTER="(level:WARNING || cat:jserrors)" -D NETSURF_BUILTIN_VERBOSE_FILTER="(level:VERBOSE || cat:jserrors)" -D STMTEXPR=1 -D nsframebuffer -D small -D NETSURF_FB_RESPATH="${HOME}/.netsurf/:${NETSURFRES}:/var/lib/jenkins/artifacts-x86_64-linux-gnu/share/netsurf:./frontends/framebuffer/res" -D NETSURF_FB_FONTPATH="/usr/share/fonts/truetype/dejavu:/usr/share/fonts/truetype/msttcorefonts" -D NETSURF_FB_FONT_SANS_SERIF="DejaVuSans.ttf" -D NETSURF_FB_FONT_SANS_SERIF_BOLD="DejaVuSans-Bold.ttf" -D NETSURF_FB_FONT_SANS_SERIF_ITALIC="DejaVuSans-Oblique.ttf" -D NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD="DejaVuSans-BoldOblique.ttf" -D NETSURF_FB_FONT_SERIF="DejaVuSerif.ttf" -D NETSURF_FB_FONT_SERIF_BOLD="DejaVuSerif-Bold.ttf" -D NETSURF_FB_FONT_MONOSPACE="DejaVuSansMono.ttf" -D NETSURF_FB_FONT_MONOSPACE_BOLD="DejaVuSansMono-Bold.ttf" -D NETSURF_FB_FONT_CURSIVE="Comic_Sans_MS.ttf" -D NETSURF_FB_FONT_FANTASY="Impact.ttf" -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D _POSIX_C_SOURCE=200809L -D _XOPEN_SOURCE=700 -D _BSD_SOURCE -D _DEFAULT_SOURCE -D _NETBSD_SOURCE -D DUK_OPT_HAVE_CUSTOM_H -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wwrite-strings -Wno-unused-parameter -Wno-unused-but-set-variable -std=c99 -fconst-strings -fdebug-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-display-progress -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/lib/jenkins/workspace/scan-build-netsurf/clangScanBuildReports/2024-12-17-120558-2788052-1 -x c frontends/framebuffer/gui.c
1/*
2 * Copyright 2008, 2014 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdint.h>
20#include <limits.h>
21#include <getopt.h>
22#include <assert.h>
23#include <string.h>
24#include <stdbool.h>
25#include <stdlib.h>
26#include <nsutils/time.h>
27
28#include <libnsfb.h>
29#include <libnsfb_plot.h>
30#include <libnsfb_event.h>
31
32#include "utils/utils.h"
33#include "utils/nsoption.h"
34#include "utils/filepath.h"
35#include "utils/log.h"
36#include "utils/messages.h"
37#include "netsurf/browser_window.h"
38#include "netsurf/keypress.h"
39#include "desktop/browser_history.h"
40#include "netsurf/plotters.h"
41#include "netsurf/window.h"
42#include "netsurf/misc.h"
43#include "netsurf/netsurf.h"
44#include "netsurf/cookie_db.h"
45#include "content/fetch.h"
46
47#include "framebuffer/gui.h"
48#include "framebuffer/fbtk.h"
49#include "framebuffer/framebuffer.h"
50#include "framebuffer/schedule.h"
51#include "framebuffer/findfile.h"
52#include "framebuffer/image_data.h"
53#include "framebuffer/font.h"
54#include "framebuffer/clipboard.h"
55#include "framebuffer/fetch.h"
56#include "framebuffer/bitmap.h"
57#include "framebuffer/local_history.h"
58#include "framebuffer/corewindow.h"
59
60
61#define NSFB_TOOLBAR_DEFAULT_LAYOUT"blfsrutc" "blfsrutc"
62
63fbtk_widget_t *fbtk;
64
65static bool_Bool fb_complete = false0;
66
67struct gui_window *input_window = NULL((void*)0);
68struct gui_window *search_current_window;
69struct gui_window *window_list = NULL((void*)0);
70
71/* private data for browser user widget */
72struct browser_widget_s {
73 struct browser_window *bw; /**< The browser window connected to this gui window */
74 int scrollx, scrolly; /**< scroll offsets. */
75
76 /* Pending window redraw state. */
77 bool_Bool redraw_required; /**< flag indicating the foreground loop
78 * needs to redraw the browser widget.
79 */
80 bbox_t redraw_box; /**< Area requiring redraw. */
81 bool_Bool pan_required; /**< flag indicating the foreground loop
82 * needs to pan the window.
83 */
84 int panx, pany; /**< Panning required. */
85};
86
87static struct gui_drag {
88 enum state {
89 GUI_DRAG_NONE,
90 GUI_DRAG_PRESSED,
91 GUI_DRAG_DRAG
92 } state;
93 int button;
94 int x;
95 int y;
96 bool_Bool grabbed_pointer;
97} gui_drag;
98
99
100/**
101 * Cause an abnormal program termination.
102 *
103 * \note This never returns and is intended to terminate without any cleanup.
104 *
105 * \param error The message to display to the user.
106 */
107static void die(const char *error)
108{
109 fprintf(stderrstderr, "%s\n", error);
110 exit(1);
111}
112
113
114/**
115 * Warn the user of an event.
116 *
117 * \param[in] warning A warning looked up in the message translation table
118 * \param[in] detail Additional text to be displayed or NULL.
119 * \return NSERROR_OK on success or error code if there was a
120 * faliure displaying the message to the user.
121 */
122static nserror fb_warn_user(const char *warning, const char *detail)
123{
124 NSLOG(netsurf, INFO, "%s %s", warning, detail)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 124
, }; nslog__log(&_nslog_ctx, "%s %s", warning, detail); }
} while(0)
;
125 return NSERROR_OK;
126}
127
128/* queue a redraw operation, co-ordinates are relative to the window */
129static void
130fb_queue_redraw(struct fbtk_widget_s *widget, int x0, int y0, int x1, int y1)
131{
132 struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
133
134 bwidget->redraw_box.x0 = min(bwidget->redraw_box.x0, x0)(((bwidget->redraw_box.x0)<(x0))?(bwidget->redraw_box
.x0):(x0))
;
135 bwidget->redraw_box.y0 = min(bwidget->redraw_box.y0, y0)(((bwidget->redraw_box.y0)<(y0))?(bwidget->redraw_box
.y0):(y0))
;
136 bwidget->redraw_box.x1 = max(bwidget->redraw_box.x1, x1)(((bwidget->redraw_box.x1)>(x1))?(bwidget->redraw_box
.x1):(x1))
;
137 bwidget->redraw_box.y1 = max(bwidget->redraw_box.y1, y1)(((bwidget->redraw_box.y1)>(y1))?(bwidget->redraw_box
.y1):(y1))
;
138
139 if (fbtk_clip_to_widget(widget, &bwidget->redraw_box)) {
140 bwidget->redraw_required = true1;
141 fbtk_request_redraw(widget);
142 } else {
143 bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX2147483647;
144 bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = -(INT_MAX2147483647);
145 bwidget->redraw_required = false0;
146 }
147}
148
149/* queue a window scroll */
150static void
151widget_scroll_y(struct gui_window *gw, int y, bool_Bool abs)
152{
153 struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
154 int content_width, content_height;
155 int height;
156
157 NSLOG(netsurf, DEEPDEBUG, "window scroll")do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 157, }; nslog__log(&_nslog_ctx
, "window scroll"); } } while(0)
;
158 if (abs) {
159 bwidget->pany = y - bwidget->scrolly;
160 } else {
161 bwidget->pany += y;
162 }
163
164 browser_window_get_extents(gw->bw, true1,
165 &content_width, &content_height);
166
167 height = fbtk_get_height(gw->browser);
168
169 /* dont pan off the top */
170 if ((bwidget->scrolly + bwidget->pany) < 0)
171 bwidget->pany = -bwidget->scrolly;
172
173 /* do not pan off the bottom of the content */
174 if ((bwidget->scrolly + bwidget->pany) > (content_height - height))
175 bwidget->pany = (content_height - height) - bwidget->scrolly;
176
177 if (bwidget->pany == 0)
178 return;
179
180 bwidget->pan_required = true1;
181
182 fbtk_request_redraw(gw->browser);
183
184 fbtk_set_scroll_position(gw->vscroll, bwidget->scrolly + bwidget->pany);
185}
186
187/* queue a window scroll */
188static void
189widget_scroll_x(struct gui_window *gw, int x, bool_Bool abs)
190{
191 struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
192 int content_width, content_height;
193 int width;
194
195 if (abs) {
196 bwidget->panx = x - bwidget->scrollx;
197 } else {
198 bwidget->panx += x;
199 }
200
201 browser_window_get_extents(gw->bw, true1,
202 &content_width, &content_height);
203
204 width = fbtk_get_width(gw->browser);
205
206 /* dont pan off the left */
207 if ((bwidget->scrollx + bwidget->panx) < 0)
208 bwidget->panx = - bwidget->scrollx;
209
210 /* do not pan off the right of the content */
211 if ((bwidget->scrollx + bwidget->panx) > (content_width - width))
212 bwidget->panx = (content_width - width) - bwidget->scrollx;
213
214 if (bwidget->panx == 0)
215 return;
216
217 bwidget->pan_required = true1;
218
219 fbtk_request_redraw(gw->browser);
220
221 fbtk_set_scroll_position(gw->hscroll, bwidget->scrollx + bwidget->panx);
222}
223
224static void
225fb_pan(fbtk_widget_t *widget,
226 struct browser_widget_s *bwidget,
227 struct browser_window *bw)
228{
229 int x;
230 int y;
231 int width;
232 int height;
233 nsfb_bbox_t srcbox;
234 nsfb_bbox_t dstbox;
235
236 nsfb_t *nsfb = fbtk_get_nsfb(widget);
237
238 height = fbtk_get_height(widget);
239 width = fbtk_get_width(widget);
240
241 NSLOG(netsurf, DEEPDEBUG, "panning %d, %d",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 242, }; nslog__log(&_nslog_ctx
, "panning %d, %d", bwidget->panx, bwidget->pany); } } while
(0)
242 bwidget->panx, bwidget->pany)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 242, }; nslog__log(&_nslog_ctx
, "panning %d, %d", bwidget->panx, bwidget->pany); } } while
(0)
;
243
244 x = fbtk_get_absx(widget);
245 y = fbtk_get_absy(widget);
246
247 /* if the pan exceeds the viewport size just redraw the whole area */
248 if (bwidget->pany >= height || bwidget->pany <= -height ||
249 bwidget->panx >= width || bwidget->panx <= -width) {
250
251 bwidget->scrolly += bwidget->pany;
252 bwidget->scrollx += bwidget->panx;
253 fb_queue_redraw(widget, 0, 0, width, height);
254
255 /* ensure we don't try to scroll again */
256 bwidget->panx = 0;
257 bwidget->pany = 0;
258 bwidget->pan_required = false0;
259 return;
260 }
261
262 if (bwidget->pany < 0) {
263 /* pan up by less then viewport height */
264 srcbox.x0 = x;
265 srcbox.y0 = y;
266 srcbox.x1 = srcbox.x0 + width;
267 srcbox.y1 = srcbox.y0 + height + bwidget->pany;
268
269 dstbox.x0 = x;
270 dstbox.y0 = y - bwidget->pany;
271 dstbox.x1 = dstbox.x0 + width;
272 dstbox.y1 = dstbox.y0 + height + bwidget->pany;
273
274 /* move part that remains visible up */
275 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
276
277 /* redraw newly exposed area */
278 bwidget->scrolly += bwidget->pany;
279 fb_queue_redraw(widget, 0, 0, width, - bwidget->pany);
280
281 } else if (bwidget->pany > 0) {
282 /* pan down by less then viewport height */
283 srcbox.x0 = x;
284 srcbox.y0 = y + bwidget->pany;
285 srcbox.x1 = srcbox.x0 + width;
286 srcbox.y1 = srcbox.y0 + height - bwidget->pany;
287
288 dstbox.x0 = x;
289 dstbox.y0 = y;
290 dstbox.x1 = dstbox.x0 + width;
291 dstbox.y1 = dstbox.y0 + height - bwidget->pany;
292
293 /* move part that remains visible down */
294 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
295
296 /* redraw newly exposed area */
297 bwidget->scrolly += bwidget->pany;
298 fb_queue_redraw(widget, 0, height - bwidget->pany,
299 width, height);
300 }
301
302 if (bwidget->panx < 0) {
303 /* pan left by less then viewport width */
304 srcbox.x0 = x;
305 srcbox.y0 = y;
306 srcbox.x1 = srcbox.x0 + width + bwidget->panx;
307 srcbox.y1 = srcbox.y0 + height;
308
309 dstbox.x0 = x - bwidget->panx;
310 dstbox.y0 = y;
311 dstbox.x1 = dstbox.x0 + width + bwidget->panx;
312 dstbox.y1 = dstbox.y0 + height;
313
314 /* move part that remains visible left */
315 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
316
317 /* redraw newly exposed area */
318 bwidget->scrollx += bwidget->panx;
319 fb_queue_redraw(widget, 0, 0, -bwidget->panx, height);
320
321 } else if (bwidget->panx > 0) {
322 /* pan right by less then viewport width */
323 srcbox.x0 = x + bwidget->panx;
324 srcbox.y0 = y;
325 srcbox.x1 = srcbox.x0 + width - bwidget->panx;
326 srcbox.y1 = srcbox.y0 + height;
327
328 dstbox.x0 = x;
329 dstbox.y0 = y;
330 dstbox.x1 = dstbox.x0 + width - bwidget->panx;
331 dstbox.y1 = dstbox.y0 + height;
332
333 /* move part that remains visible right */
334 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
335
336 /* redraw newly exposed area */
337 bwidget->scrollx += bwidget->panx;
338 fb_queue_redraw(widget, width - bwidget->panx, 0,
339 width, height);
340 }
341
342 bwidget->pan_required = false0;
343 bwidget->panx = 0;
344 bwidget->pany = 0;
345}
346
347static void
348fb_redraw(fbtk_widget_t *widget,
349 struct browser_widget_s *bwidget,
350 struct browser_window *bw)
351{
352 int x;
353 int y;
354 int caret_x, caret_y, caret_h;
355 struct rect clip;
356 struct redraw_context ctx = {
357 .interactive = true1,
358 .background_images = true1,
359 .plot = &fb_plotters
360 };
361 nsfb_t *nsfb = fbtk_get_nsfb(widget);
362
363 x = fbtk_get_absx(widget);
364 y = fbtk_get_absy(widget);
365
366 /* adjust clipping co-ordinates according to window location */
367 bwidget->redraw_box.y0 += y;
368 bwidget->redraw_box.y1 += y;
369 bwidget->redraw_box.x0 += x;
370 bwidget->redraw_box.x1 += x;
371
372 nsfb_claim(nsfb, &bwidget->redraw_box);
373
374 /* redraw bounding box is relative to window */
375 clip.x0 = bwidget->redraw_box.x0;
376 clip.y0 = bwidget->redraw_box.y0;
377 clip.x1 = bwidget->redraw_box.x1;
378 clip.y1 = bwidget->redraw_box.y1;
379
380 browser_window_redraw(bw,
381 x - bwidget->scrollx,
382 y - bwidget->scrolly,
383 &clip, &ctx);
384
385 if (fbtk_get_caret(widget, &caret_x, &caret_y, &caret_h)) {
386 /* This widget has caret, so render it */
387 nsfb_bbox_t line;
388 nsfb_plot_pen_t pen;
389
390 line.x0 = x - bwidget->scrollx + caret_x;
391 line.y0 = y - bwidget->scrolly + caret_y;
392 line.x1 = x - bwidget->scrollx + caret_x;
393 line.y1 = y - bwidget->scrolly + caret_y + caret_h;
394
395 pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
396 pen.stroke_width = 1;
397 pen.stroke_colour = 0xFF0000FF;
398
399 nsfb_plot_line(nsfb, &line, &pen);
400 }
401
402 nsfb_update(fbtk_get_nsfb(widget), &bwidget->redraw_box);
403
404 bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX2147483647;
405 bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = INT_MIN(-2147483647 -1);
406 bwidget->redraw_required = false0;
407}
408
409static int
410fb_browser_window_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
411{
412 struct gui_window *gw = cbi->context;
413 struct browser_widget_s *bwidget;
414
415 bwidget = fbtk_get_userpw(widget);
416 if (bwidget == NULL((void*)0)) {
417 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 418
, }; nslog__log(&_nslog_ctx, "browser widget from widget %p was null"
, widget); } } while(0)
418 "browser widget from widget %p was null", widget)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 418
, }; nslog__log(&_nslog_ctx, "browser widget from widget %p was null"
, widget); } } while(0)
;
419 return -1;
420 }
421
422 if (bwidget->pan_required) {
423 fb_pan(widget, bwidget, gw->bw);
424 }
425
426 if (bwidget->redraw_required) {
427 fb_redraw(widget, bwidget, gw->bw);
428 } else {
429 bwidget->redraw_box.x0 = 0;
430 bwidget->redraw_box.y0 = 0;
431 bwidget->redraw_box.x1 = fbtk_get_width(widget);
432 bwidget->redraw_box.y1 = fbtk_get_height(widget);
433 fb_redraw(widget, bwidget, gw->bw);
434 }
435 return 0;
436}
437
438static int fb_browser_window_destroy(fbtk_widget_t *widget,
439 fbtk_callback_info *cbi)
440{
441 struct browser_widget_s *browser_widget;
442
443 if (widget == NULL((void*)0)) {
444 return 0;
445 }
446
447 /* Free private data */
448 browser_widget = fbtk_get_userpw(widget);
449 free(browser_widget);
450
451 return 0;
452}
453
454static void
455framebuffer_surface_iterator(void *ctx, const char *name, enum nsfb_type_e type)
456{
457 const char *arg0 = ctx;
458
459 fprintf(stderrstderr, "%s: %s\n", arg0, name);
460}
461
462static enum nsfb_type_e fetype = NSFB_SURFACE_COUNT;
463static const char *fename;
464static int febpp;
465static int fewidth;
466static int feheight;
467static const char *feurl;
468
469static void
470framebuffer_pick_default_fename(void *ctx, const char *name, enum nsfb_type_e type)
471{
472 if (type < fetype) {
473 fename = name;
474 }
475}
476
477static bool_Bool
478process_cmdline(int argc, char** argv)
479{
480 int opt;
481 int option_index;
482 static struct option long_options[] = {
483 {0, 0, 0, 0 }
484 }; /* no long options */
485
486 NSLOG(netsurf, INFO, "argc %d, argv %p", argc, argv)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 486
, }; nslog__log(&_nslog_ctx, "argc %d, argv %p", argc, argv
); } } while(0)
;
487
488 nsfb_enumerate_surface_types(framebuffer_pick_default_fename, NULL((void*)0));
489
490 febpp = 32;
491
492 fewidth = nsoption_int(window_width)(nsoptions[NSOPTION_window_width].value.i);
493 if (fewidth <= 0) {
494 fewidth = 800;
495 }
496 feheight = nsoption_int(window_height)(nsoptions[NSOPTION_window_height].value.i);
497 if (feheight <= 0) {
498 feheight = 600;
499 }
500
501 if ((nsoption_charp(homepage_url)(nsoptions[NSOPTION_homepage_url].value.s) != NULL((void*)0)) &&
502 (nsoption_charp(homepage_url)(nsoptions[NSOPTION_homepage_url].value.s)[0] != '\0')) {
503 feurl = nsoption_charp(homepage_url)(nsoptions[NSOPTION_homepage_url].value.s);
504 } else {
505 feurl = NETSURF_HOMEPAGE"about:welcome";
506 }
507
508 while((opt = getopt_long(argc, argv, "f:b:w:h:",
509 long_options, &option_index)) != -1) {
510 switch (opt) {
511 case 'f':
512 fename = optarg;
513 break;
514
515 case 'b':
516 febpp = atoi(optarg);
517 break;
518
519 case 'w':
520 fewidth = atoi(optarg);
521 break;
522
523 case 'h':
524 feheight = atoi(optarg);
525 break;
526
527 default:
528 fprintf(stderrstderr,
529 "Usage: %s [-f frontend] [-b bpp] [-w width] [-h height] <url>\n",
530 argv[0]);
531 return false0;
532 }
533 }
534
535 if (optind < argc) {
536 feurl = argv[optind];
537 }
538
539 if (nsfb_type_from_name(fename) == NSFB_SURFACE_NONE) {
540 if (strcmp(fename, "?") != 0) {
541 fprintf(stderrstderr,
542 "%s: Unknown surface `%s`\n", argv[0], fename);
543 }
544 fprintf(stderrstderr, "%s: Valid surface names are:\n", argv[0]);
545 nsfb_enumerate_surface_types(framebuffer_surface_iterator, argv[0]);
546 return false0;
547 }
548
549 return true1;
550}
551
552/**
553 * Set option defaults for framebuffer frontend
554 *
555 * @param defaults The option table to update.
556 * @return error status.
557 */
558static nserror set_defaults(struct nsoption_s *defaults)
559{
560 /* Set defaults for absent option strings */
561 nsoption_setnull_charp(cookie_file, strdup("~/.netsurf/Cookies"))do { if (nsoptions[NSOPTION_cookie_file].value.s == ((void*)0
)) { nsoption_set_tbl_charp(nsoptions, NSOPTION_cookie_file, strdup
("~/.netsurf/Cookies")); } else { free(strdup("~/.netsurf/Cookies"
)); } } while (0)
;
562 nsoption_setnull_charp(cookie_jar, strdup("~/.netsurf/Cookies"))do { if (nsoptions[NSOPTION_cookie_jar].value.s == ((void*)0)
) { nsoption_set_tbl_charp(nsoptions, NSOPTION_cookie_jar, strdup
("~/.netsurf/Cookies")); } else { free(strdup("~/.netsurf/Cookies"
)); } } while (0)
;
563
564 if (nsoption_charp(cookie_file)(nsoptions[NSOPTION_cookie_file].value.s) == NULL((void*)0) ||
565 nsoption_charp(cookie_jar)(nsoptions[NSOPTION_cookie_jar].value.s) == NULL((void*)0)) {
566 NSLOG(netsurf, INFO, "Failed initialising cookie options")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 566
, }; nslog__log(&_nslog_ctx, "Failed initialising cookie options"
); } } while(0)
;
567 return NSERROR_BAD_PARAMETER;
568 }
569
570 /* set system colours for framebuffer ui */
571 nsoption_set_colour(sys_colour_ActiveBorder, 0x00000000)nsoptions[NSOPTION_sys_colour_ActiveBorder].value.c = 0x00000000;
572 nsoption_set_colour(sys_colour_ActiveCaption, 0x00ddddcc)nsoptions[NSOPTION_sys_colour_ActiveCaption].value.c = 0x00ddddcc;
573 nsoption_set_colour(sys_colour_AppWorkspace, 0x00eeeeee)nsoptions[NSOPTION_sys_colour_AppWorkspace].value.c = 0x00eeeeee;
574 nsoption_set_colour(sys_colour_Background, 0x00aa0000)nsoptions[NSOPTION_sys_colour_Background].value.c = 0x00aa0000;
575 nsoption_set_colour(sys_colour_ButtonFace, 0x00dddddd)nsoptions[NSOPTION_sys_colour_ButtonFace].value.c = 0x00dddddd;
576 nsoption_set_colour(sys_colour_ButtonHighlight, 0x00cccccc)nsoptions[NSOPTION_sys_colour_ButtonHighlight].value.c = 0x00cccccc;
577 nsoption_set_colour(sys_colour_ButtonShadow, 0x00bbbbbb)nsoptions[NSOPTION_sys_colour_ButtonShadow].value.c = 0x00bbbbbb;
578 nsoption_set_colour(sys_colour_ButtonText, 0x00000000)nsoptions[NSOPTION_sys_colour_ButtonText].value.c = 0x00000000;
579 nsoption_set_colour(sys_colour_CaptionText, 0x00000000)nsoptions[NSOPTION_sys_colour_CaptionText].value.c = 0x00000000;
580 nsoption_set_colour(sys_colour_GrayText, 0x00777777)nsoptions[NSOPTION_sys_colour_GrayText].value.c = 0x00777777;
581 nsoption_set_colour(sys_colour_Highlight, 0x00ee0000)nsoptions[NSOPTION_sys_colour_Highlight].value.c = 0x00ee0000;
582 nsoption_set_colour(sys_colour_HighlightText, 0x00000000)nsoptions[NSOPTION_sys_colour_HighlightText].value.c = 0x00000000;
583 nsoption_set_colour(sys_colour_InactiveBorder, 0x00000000)nsoptions[NSOPTION_sys_colour_InactiveBorder].value.c = 0x00000000;
584 nsoption_set_colour(sys_colour_InactiveCaption, 0x00ffffff)nsoptions[NSOPTION_sys_colour_InactiveCaption].value.c = 0x00ffffff;
585 nsoption_set_colour(sys_colour_InactiveCaptionText, 0x00cccccc)nsoptions[NSOPTION_sys_colour_InactiveCaptionText].value.c = 0x00cccccc;
586 nsoption_set_colour(sys_colour_InfoBackground, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_InfoBackground].value.c = 0x00aaaaaa;
587 nsoption_set_colour(sys_colour_InfoText, 0x00000000)nsoptions[NSOPTION_sys_colour_InfoText].value.c = 0x00000000;
588 nsoption_set_colour(sys_colour_Menu, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_Menu].value.c = 0x00aaaaaa;
589 nsoption_set_colour(sys_colour_MenuText, 0x00000000)nsoptions[NSOPTION_sys_colour_MenuText].value.c = 0x00000000;
590 nsoption_set_colour(sys_colour_Scrollbar, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_Scrollbar].value.c = 0x00aaaaaa;
591 nsoption_set_colour(sys_colour_ThreeDDarkShadow, 0x00555555)nsoptions[NSOPTION_sys_colour_ThreeDDarkShadow].value.c = 0x00555555;
592 nsoption_set_colour(sys_colour_ThreeDFace, 0x00dddddd)nsoptions[NSOPTION_sys_colour_ThreeDFace].value.c = 0x00dddddd;
593 nsoption_set_colour(sys_colour_ThreeDHighlight, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_ThreeDHighlight].value.c = 0x00aaaaaa;
594 nsoption_set_colour(sys_colour_ThreeDLightShadow, 0x00999999)nsoptions[NSOPTION_sys_colour_ThreeDLightShadow].value.c = 0x00999999;
595 nsoption_set_colour(sys_colour_ThreeDShadow, 0x00777777)nsoptions[NSOPTION_sys_colour_ThreeDShadow].value.c = 0x00777777;
596 nsoption_set_colour(sys_colour_Window, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_Window].value.c = 0x00aaaaaa;
597 nsoption_set_colour(sys_colour_WindowFrame, 0x00000000)nsoptions[NSOPTION_sys_colour_WindowFrame].value.c = 0x00000000;
598 nsoption_set_colour(sys_colour_WindowText, 0x00000000)nsoptions[NSOPTION_sys_colour_WindowText].value.c = 0x00000000;
599
600 return NSERROR_OK;
601}
602
603
604/**
605 * Ensures output logging stream is correctly configured
606 */
607static bool_Bool nslog_stream_configure(FILE *fptr)
608{
609 /* set log stream to be non-buffering */
610 setbuf(fptr, NULL((void*)0));
611
612 return true1;
613}
614
615static void framebuffer_run(void)
616{
617 nsfb_event_t event;
618 int timeout; /* timeout in miliseconds */
619
620 while (fb_complete != true1) {
621 /* run the scheduler and discover how long to wait for
622 * the next event.
623 */
624 timeout = schedule_run();
625
626 /* if redraws are pending do not wait for event,
627 * return immediately
628 */
629 if (fbtk_get_redraw_pending(fbtk))
630 timeout = 0;
631
632 if (fbtk_event(fbtk, &event, timeout)) {
633 if ((event.type == NSFB_EVENT_CONTROL) &&
634 (event.value.controlcode == NSFB_CONTROL_QUIT))
635 fb_complete = true1;
636 }
637
638 fbtk_redraw(fbtk);
639 }
640}
641
642static void gui_quit(void)
643{
644 NSLOG(netsurf, INFO, "gui_quit")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 644
, }; nslog__log(&_nslog_ctx, "gui_quit"); } } while(0)
;
645
646 urldb_save_cookies(nsoption_charp(cookie_jar)(nsoptions[NSOPTION_cookie_jar].value.s));
647
648 framebuffer_finalise();
649}
650
651/* called back when click in browser window */
652static int
653fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
654{
655 struct gui_window *gw = cbi->context;
656 struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
657 browser_mouse_state mouse;
658 int x = cbi->x + bwidget->scrollx;
659 int y = cbi->y + bwidget->scrolly;
660 uint64_t time_now;
661 static struct {
662 enum { CLICK_SINGLE, CLICK_DOUBLE, CLICK_TRIPLE } type;
663 uint64_t time;
664 } last_click;
665
666 if (cbi->event->type != NSFB_EVENT_KEY_DOWN &&
667 cbi->event->type != NSFB_EVENT_KEY_UP)
668 return 0;
669
670 NSLOG(netsurf, DEEPDEBUG, "browser window clicked at %d,%d",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 671, }; nslog__log(&_nslog_ctx
, "browser window clicked at %d,%d", cbi->x, cbi->y); }
} while(0)
671 cbi->x, cbi->y)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 671, }; nslog__log(&_nslog_ctx
, "browser window clicked at %d,%d", cbi->x, cbi->y); }
} while(0)
;
672
673 switch (cbi->event->type) {
674 case NSFB_EVENT_KEY_DOWN:
675 switch (cbi->event->value.keycode) {
676 case NSFB_KEY_MOUSE_1:
677 browser_window_mouse_click(gw->bw,
678 BROWSER_MOUSE_PRESS_1, x, y);
679 gui_drag.state = GUI_DRAG_PRESSED;
680 gui_drag.button = 1;
681 gui_drag.x = x;
682 gui_drag.y = y;
683 break;
684
685 case NSFB_KEY_MOUSE_3:
686 browser_window_mouse_click(gw->bw,
687 BROWSER_MOUSE_PRESS_2, x, y);
688 gui_drag.state = GUI_DRAG_PRESSED;
689 gui_drag.button = 2;
690 gui_drag.x = x;
691 gui_drag.y = y;
692 break;
693
694 case NSFB_KEY_MOUSE_4:
695 /* scroll up */
696 if (browser_window_scroll_at_point(gw->bw,
697 x, y,
698 0, -100) == false0)
699 widget_scroll_y(gw, -100, false0);
700 break;
701
702 case NSFB_KEY_MOUSE_5:
703 /* scroll down */
704 if (browser_window_scroll_at_point(gw->bw,
705 x, y,
706 0, 100) == false0)
707 widget_scroll_y(gw, 100, false0);
708 break;
709
710 default:
711 break;
712
713 }
714
715 break;
716 case NSFB_EVENT_KEY_UP:
717
718 mouse = 0;
719 nsu_getmonotonic_ms(&time_now);
720
721 switch (cbi->event->value.keycode) {
722 case NSFB_KEY_MOUSE_1:
723 if (gui_drag.state == GUI_DRAG_DRAG) {
724 /* End of a drag, rather than click */
725
726 if (gui_drag.grabbed_pointer) {
727 /* need to ungrab pointer */
728 fbtk_tgrab_pointer(widget);
729 gui_drag.grabbed_pointer = false0;
730 }
731
732 gui_drag.state = GUI_DRAG_NONE;
733
734 /* Tell core */
735 browser_window_mouse_track(gw->bw, 0, x, y);
736 break;
737 }
738 /* This is a click;
739 * clear PRESSED state and pass to core */
740 gui_drag.state = GUI_DRAG_NONE;
741 mouse = BROWSER_MOUSE_CLICK_1;
742 break;
743
744 case NSFB_KEY_MOUSE_3:
745 if (gui_drag.state == GUI_DRAG_DRAG) {
746 /* End of a drag, rather than click */
747 gui_drag.state = GUI_DRAG_NONE;
748
749 if (gui_drag.grabbed_pointer) {
750 /* need to ungrab pointer */
751 fbtk_tgrab_pointer(widget);
752 gui_drag.grabbed_pointer = false0;
753 }
754
755 /* Tell core */
756 browser_window_mouse_track(gw->bw, 0, x, y);
757 break;
758 }
759 /* This is a click;
760 * clear PRESSED state and pass to core */
761 gui_drag.state = GUI_DRAG_NONE;
762 mouse = BROWSER_MOUSE_CLICK_2;
763 break;
764
765 default:
766 break;
767
768 }
769
770 /* Determine if it's a double or triple click, allowing
771 * 0.5 seconds (500ms) between clicks
772 */
773 if ((time_now < (last_click.time + 500)) &&
774 (cbi->event->value.keycode != NSFB_KEY_MOUSE_4) &&
775 (cbi->event->value.keycode != NSFB_KEY_MOUSE_5)) {
776 if (last_click.type == CLICK_SINGLE) {
777 /* Set double click */
778 mouse |= BROWSER_MOUSE_DOUBLE_CLICK;
779 last_click.type = CLICK_DOUBLE;
780
781 } else if (last_click.type == CLICK_DOUBLE) {
782 /* Set triple click */
783 mouse |= BROWSER_MOUSE_TRIPLE_CLICK;
784 last_click.type = CLICK_TRIPLE;
785 } else {
786 /* Set normal click */
787 last_click.type = CLICK_SINGLE;
788 }
789 } else {
790 last_click.type = CLICK_SINGLE;
791 }
792
793 if (mouse) {
794 browser_window_mouse_click(gw->bw, mouse, x, y);
795 }
796
797 last_click.time = time_now;
798
799 break;
800 default:
801 break;
802
803 }
804 return 1;
805}
806
807/* called back when movement in browser window */
808static int
809fb_browser_window_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
810{
811 browser_mouse_state mouse = 0;
812 struct gui_window *gw = cbi->context;
813 struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
814 int x = cbi->x + bwidget->scrollx;
815 int y = cbi->y + bwidget->scrolly;
816
817 if (gui_drag.state == GUI_DRAG_PRESSED &&
818 (abs(x - gui_drag.x) > 5 ||
819 abs(y - gui_drag.y) > 5)) {
820 /* Drag started */
821 if (gui_drag.button == 1) {
822 browser_window_mouse_click(gw->bw,
823 BROWSER_MOUSE_DRAG_1,
824 gui_drag.x, gui_drag.y);
825 } else {
826 browser_window_mouse_click(gw->bw,
827 BROWSER_MOUSE_DRAG_2,
828 gui_drag.x, gui_drag.y);
829 }
830 gui_drag.grabbed_pointer = fbtk_tgrab_pointer(widget);
831 gui_drag.state = GUI_DRAG_DRAG;
832 }
833
834 if (gui_drag.state == GUI_DRAG_DRAG) {
835 /* set up mouse state */
836 mouse |= BROWSER_MOUSE_DRAG_ON;
837
838 if (gui_drag.button == 1)
839 mouse |= BROWSER_MOUSE_HOLDING_1;
840 else
841 mouse |= BROWSER_MOUSE_HOLDING_2;
842 }
843
844 browser_window_mouse_track(gw->bw, mouse, x, y);
845
846 return 0;
847}
848
849
850static int
851fb_browser_window_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
852{
853 struct gui_window *gw = cbi->context;
854 static fbtk_modifier_type modifier = FBTK_MOD_CLEAR;
855 int ucs4 = -1;
856
857 NSLOG(netsurf, INFO, "got value %d", cbi->event->value.keycode)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 857
, }; nslog__log(&_nslog_ctx, "got value %d", cbi->event
->value.keycode); } } while(0)
;
858
859 switch (cbi->event->type) {
860 case NSFB_EVENT_KEY_DOWN:
861 switch (cbi->event->value.keycode) {
862
863 case NSFB_KEY_DELETE:
864 browser_window_key_press(gw->bw, NS_KEY_DELETE_RIGHT);
865 break;
866
867 case NSFB_KEY_PAGEUP:
868 if (browser_window_key_press(gw->bw,
869 NS_KEY_PAGE_UP) == false0)
870 widget_scroll_y(gw, -fbtk_get_height(
871 gw->browser), false0);
872 break;
873
874 case NSFB_KEY_PAGEDOWN:
875 if (browser_window_key_press(gw->bw,
876 NS_KEY_PAGE_DOWN) == false0)
877 widget_scroll_y(gw, fbtk_get_height(
878 gw->browser), false0);
879 break;
880
881 case NSFB_KEY_RIGHT:
882 if (modifier & FBTK_MOD_RCTRL ||
883 modifier & FBTK_MOD_LCTRL) {
884 /* CTRL held */
885 if (browser_window_key_press(gw->bw,
886 NS_KEY_LINE_END) == false0)
887 widget_scroll_x(gw, INT_MAX2147483647, true1);
888
889 } else if (modifier & FBTK_MOD_RSHIFT ||
890 modifier & FBTK_MOD_LSHIFT) {
891 /* SHIFT held */
892 if (browser_window_key_press(gw->bw,
893 NS_KEY_WORD_RIGHT) == false0)
894 widget_scroll_x(gw, fbtk_get_width(
895 gw->browser), false0);
896
897 } else {
898 /* no modifier */
899 if (browser_window_key_press(gw->bw,
900 NS_KEY_RIGHT) == false0)
901 widget_scroll_x(gw, 100, false0);
902 }
903 break;
904
905 case NSFB_KEY_LEFT:
906 if (modifier & FBTK_MOD_RCTRL ||
907 modifier & FBTK_MOD_LCTRL) {
908 /* CTRL held */
909 if (browser_window_key_press(gw->bw,
910 NS_KEY_LINE_START) == false0)
911 widget_scroll_x(gw, 0, true1);
912
913 } else if (modifier & FBTK_MOD_RSHIFT ||
914 modifier & FBTK_MOD_LSHIFT) {
915 /* SHIFT held */
916 if (browser_window_key_press(gw->bw,
917 NS_KEY_WORD_LEFT) == false0)
918 widget_scroll_x(gw, -fbtk_get_width(
919 gw->browser), false0);
920
921 } else {
922 /* no modifier */
923 if (browser_window_key_press(gw->bw,
924 NS_KEY_LEFT) == false0)
925 widget_scroll_x(gw, -100, false0);
926 }
927 break;
928
929 case NSFB_KEY_UP:
930 if (browser_window_key_press(gw->bw,
931 NS_KEY_UP) == false0)
932 widget_scroll_y(gw, -100, false0);
933 break;
934
935 case NSFB_KEY_DOWN:
936 if (browser_window_key_press(gw->bw,
937 NS_KEY_DOWN) == false0)
938 widget_scroll_y(gw, 100, false0);
939 break;
940
941 case NSFB_KEY_MINUS:
942 if (modifier & FBTK_MOD_RCTRL ||
943 modifier & FBTK_MOD_LCTRL) {
944 browser_window_set_scale(gw->bw, -0.1, false0);
945 }
946 break;
947
948 case NSFB_KEY_EQUALS: /* PLUS */
949 if (modifier & FBTK_MOD_RCTRL ||
950 modifier & FBTK_MOD_LCTRL) {
951 browser_window_set_scale(gw->bw, 0.1, false0);
952 }
953 break;
954
955 case NSFB_KEY_0:
956 if (modifier & FBTK_MOD_RCTRL ||
957 modifier & FBTK_MOD_LCTRL) {
958 browser_window_set_scale(gw->bw, 1.0, true1);
959 }
960 break;
961
962 case NSFB_KEY_RSHIFT:
963 modifier |= FBTK_MOD_RSHIFT;
964 break;
965
966 case NSFB_KEY_LSHIFT:
967 modifier |= FBTK_MOD_LSHIFT;
968 break;
969
970 case NSFB_KEY_RCTRL:
971 modifier |= FBTK_MOD_RCTRL;
972 break;
973
974 case NSFB_KEY_LCTRL:
975 modifier |= FBTK_MOD_LCTRL;
976 break;
977
978 case NSFB_KEY_y:
979 case NSFB_KEY_z:
980 if (cbi->event->value.keycode == NSFB_KEY_z &&
981 (modifier & FBTK_MOD_RCTRL ||
982 modifier & FBTK_MOD_LCTRL) &&
983 (modifier & FBTK_MOD_RSHIFT ||
984 modifier & FBTK_MOD_LSHIFT)) {
985 /* Z pressed with CTRL and SHIFT held */
986 browser_window_key_press(gw->bw, NS_KEY_REDO);
987 break;
988
989 } else if (cbi->event->value.keycode == NSFB_KEY_z &&
990 (modifier & FBTK_MOD_RCTRL ||
991 modifier & FBTK_MOD_LCTRL)) {
992 /* Z pressed with CTRL held */
993 browser_window_key_press(gw->bw, NS_KEY_UNDO);
994 break;
995
996 } else if (cbi->event->value.keycode == NSFB_KEY_y &&
997 (modifier & FBTK_MOD_RCTRL ||
998 modifier & FBTK_MOD_LCTRL)) {
999 /* Y pressed with CTRL held */
1000 browser_window_key_press(gw->bw, NS_KEY_REDO);
1001 break;
1002 }
1003 /* Z or Y pressed but not undo or redo; */
1004 fallthrough__attribute__((__fallthrough__));
1005
1006 default:
1007 ucs4 = fbtk_keycode_to_ucs4(cbi->event->value.keycode,
1008 modifier);
1009 if (ucs4 != -1)
1010 browser_window_key_press(gw->bw, ucs4);
1011 break;
1012 }
1013 break;
1014
1015 case NSFB_EVENT_KEY_UP:
1016 switch (cbi->event->value.keycode) {
1017 case NSFB_KEY_RSHIFT:
1018 modifier &= ~FBTK_MOD_RSHIFT;
1019 break;
1020
1021 case NSFB_KEY_LSHIFT:
1022 modifier &= ~FBTK_MOD_LSHIFT;
1023 break;
1024
1025 case NSFB_KEY_RCTRL:
1026 modifier &= ~FBTK_MOD_RCTRL;
1027 break;
1028
1029 case NSFB_KEY_LCTRL:
1030 modifier &= ~FBTK_MOD_LCTRL;
1031 break;
1032
1033 default:
1034 break;
1035 }
1036 break;
1037
1038 default:
1039 break;
1040 }
1041
1042 return 0;
1043}
1044
1045static void
1046fb_update_back_forward(struct gui_window *gw)
1047{
1048 struct browser_window *bw = gw->bw;
1049
1050 fbtk_set_bitmap(gw->back,
1051 (browser_window_back_available(bw)) ?
1052 &left_arrow : &left_arrow_g);
1053 fbtk_set_bitmap(gw->forward,
1054 (browser_window_forward_available(bw)) ?
1055 &right_arrow : &right_arrow_g);
1056}
1057
1058/* left icon click routine */
1059static int
1060fb_leftarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1061{
1062 struct gui_window *gw = cbi->context;
1063 struct browser_window *bw = gw->bw;
1064
1065 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1066 return 0;
1067
1068 if (browser_window_back_available(bw))
1069 browser_window_history_back(bw, false0);
1070
1071 fb_update_back_forward(gw);
1072
1073 return 1;
1074}
1075
1076/* right arrow icon click routine */
1077static int
1078fb_rightarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1079{
1080 struct gui_window *gw = cbi->context;
1081 struct browser_window *bw = gw->bw;
1082
1083 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1084 return 0;
1085
1086 if (browser_window_forward_available(bw))
1087 browser_window_history_forward(bw, false0);
1088
1089 fb_update_back_forward(gw);
1090 return 1;
1091
1092}
1093
1094/* reload icon click routine */
1095static int
1096fb_reload_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1097{
1098 struct browser_window *bw = cbi->context;
1099
1100 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1101 return 0;
1102
1103 browser_window_reload(bw, true1);
1104 return 1;
1105}
1106
1107/* stop icon click routine */
1108static int
1109fb_stop_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1110{
1111 struct browser_window *bw = cbi->context;
1112
1113 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1114 return 0;
1115
1116 browser_window_stop(bw);
1117 return 0;
1118}
1119
1120static int
1121fb_osk_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1122{
1123
1124 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1125 return 0;
1126
1127 map_osk();
1128
1129 return 0;
1130}
1131
1132/* close browser window icon click routine */
1133static int
1134fb_close_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1135{
1136 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1137 return 0;
1138
1139 fb_complete = true1;
1140
1141 return 0;
1142}
1143
1144static int
1145fb_scroll_callback(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1146{
1147 struct gui_window *gw = cbi->context;
1148
1149 switch (cbi->type) {
1150 case FBTK_CBT_SCROLLY:
1151 widget_scroll_y(gw, cbi->y, true1);
1152 break;
1153
1154 case FBTK_CBT_SCROLLX:
1155 widget_scroll_x(gw, cbi->x, true1);
1156 break;
1157
1158 default:
1159 break;
1160 }
1161 return 0;
1162}
1163
1164static int
1165fb_url_enter(void *pw, char *text)
1166{
1167 struct browser_window *bw = pw;
1168 nsurl *url;
1169 nserror error;
1170
1171 error = nsurl_create(text, &url);
1172 if (error != NSERROR_OK) {
1173 fb_warn_user("Errorcode:", messages_get_errorcode(error));
1174 } else {
1175 browser_window_navigate(bw, url, NULL((void*)0), BW_NAVIGATE_HISTORY,
1176 NULL((void*)0), NULL((void*)0), NULL((void*)0));
1177 nsurl_unref(url);
1178 }
1179
1180 return 0;
1181}
1182
1183static int
1184fb_url_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1185{
1186 framebuffer_set_cursor(&caret_image);
1187 return 0;
1188}
1189
1190static int
1191set_ptr_default_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1192{
1193 framebuffer_set_cursor(&pointer_image);
1194 return 0;
1195}
1196
1197static int
1198fb_localhistory_btn_clik(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1199{
1200 struct gui_window *gw = cbi->context;
1201
1202 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1203 return 0;
1204
1205 fb_local_history_present(fbtk, gw->bw);
1206
1207 return 0;
1208}
1209
1210
1211/** Create a toolbar window and populate it with buttons.
1212 *
1213 * The toolbar layout uses a character to define buttons type and position:
1214 * b - back
1215 * l - local history
1216 * f - forward
1217 * s - stop
1218 * r - refresh
1219 * u - url bar expands to fit remaining space
1220 * t - throbber/activity indicator
1221 * c - close the current window
1222 *
1223 * The default layout is "blfsrut" there should be no more than a
1224 * single url bar entry or behaviour will be undefined.
1225 *
1226 * @param gw Parent window
1227 * @param toolbar_height The height in pixels of the toolbar
1228 * @param padding The padding in pixels round each element of the toolbar
1229 * @param frame_col Frame colour.
1230 * @param toolbar_layout A string defining which buttons and controls
1231 * should be added to the toolbar. May be empty
1232 * string to disable the bar..
1233 *
1234 */
1235static fbtk_widget_t *
1236create_toolbar(struct gui_window *gw,
1237 int toolbar_height,
1238 int padding,
1239 colour frame_col,
1240 const char *toolbar_layout)
1241{
1242 fbtk_widget_t *toolbar;
1243 fbtk_widget_t *widget;
1244
1245 int xpos; /* The position of the next widget. */
1246 int xlhs = 0; /* extent of the left hand side widgets */
1247 int xdir = 1; /* the direction of movement + or - 1 */
1248 const char *itmtype; /* type of the next item */
1249
1250 if (toolbar_layout == NULL((void*)0)) {
1251 toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT"blfsrutc";
1252 }
1253
1254 NSLOG(netsurf, INFO, "Using toolbar layout %s", toolbar_layout)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1254
, }; nslog__log(&_nslog_ctx, "Using toolbar layout %s", toolbar_layout
); } } while(0)
;
1255
1256 itmtype = toolbar_layout;
1257
1258 /* check for the toolbar being disabled */
1259 if ((*itmtype == 0) || (*itmtype == 'q')) {
1260 return NULL((void*)0);
1261 }
1262
1263 toolbar = fbtk_create_window(gw->window, 0, 0, 0,
1264 toolbar_height,
1265 frame_col);
1266
1267 if (toolbar == NULL((void*)0)) {
1268 return NULL((void*)0);
1269 }
1270
1271 fbtk_set_handler(toolbar,
1272 FBTK_CBT_POINTERENTER,
1273 set_ptr_default_move,
1274 NULL((void*)0));
1275
1276
1277 xpos = padding;
1278
1279 /* loop proceeds creating widget on the left hand side until
1280 * it runs out of layout or encounters a url bar declaration
1281 * wherupon it works backwards from the end of the layout
1282 * untill the space left is for the url bar
1283 */
1284 while ((itmtype >= toolbar_layout) &&
1285 (*itmtype != 0) &&
1286 (xdir !=0)) {
1287
1288 NSLOG(netsurf, INFO, "toolbar adding %c", *itmtype)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1288
, }; nslog__log(&_nslog_ctx, "toolbar adding %c", *itmtype
); } } while(0)
;
1289
1290
1291 switch (*itmtype) {
1292
1293 case 'b': /* back */
1294 widget = fbtk_create_button(toolbar,
1295 (xdir == 1) ? xpos :
1296 xpos - left_arrow.width,
1297 padding,
1298 left_arrow.width,
1299 -padding,
1300 frame_col,
1301 &left_arrow,
1302 fb_leftarrow_click,
1303 gw);
1304 gw->back = widget; /* keep reference */
1305 break;
1306
1307 case 'l': /* local history */
1308 widget = fbtk_create_button(toolbar,
1309 (xdir == 1) ? xpos :
1310 xpos - history_image.width,
1311 padding,
1312 history_image.width,
1313 -padding,
1314 frame_col,
1315 &history_image,
1316 fb_localhistory_btn_clik,
1317 gw);
1318 gw->history = widget;
1319 break;
1320
1321 case 'f': /* forward */
1322 widget = fbtk_create_button(toolbar,
1323 (xdir == 1)?xpos :
1324 xpos - right_arrow.width,
1325 padding,
1326 right_arrow.width,
1327 -padding,
1328 frame_col,
1329 &right_arrow,
1330 fb_rightarrow_click,
1331 gw);
1332 gw->forward = widget;
1333 break;
1334
1335 case 'c': /* close the current window */
1336 widget = fbtk_create_button(toolbar,
1337 (xdir == 1)?xpos :
1338 xpos - stop_image_g.width,
1339 padding,
1340 stop_image_g.width,
1341 -padding,
1342 frame_col,
1343 &stop_image_g,
1344 fb_close_click,
1345 gw->bw);
1346 gw->close = widget;
1347 break;
1348
1349 case 's': /* stop */
1350 widget = fbtk_create_button(toolbar,
1351 (xdir == 1)?xpos :
1352 xpos - stop_image.width,
1353 padding,
1354 stop_image.width,
1355 -padding,
1356 frame_col,
1357 &stop_image,
1358 fb_stop_click,
1359 gw->bw);
1360 gw->stop = widget;
1361 break;
1362
1363 case 'r': /* reload */
1364 widget = fbtk_create_button(toolbar,
1365 (xdir == 1)?xpos :
1366 xpos - reload.width,
1367 padding,
1368 reload.width,
1369 -padding,
1370 frame_col,
1371 &reload,
1372 fb_reload_click,
1373 gw->bw);
1374 gw->reload = widget;
1375 break;
1376
1377 case 't': /* throbber/activity indicator */
1378 widget = fbtk_create_bitmap(toolbar,
1379 (xdir == 1)?xpos :
1380 xpos - throbber0.width,
1381 padding,
1382 throbber0.width,
1383 -padding,
1384 frame_col,
1385 &throbber0);
1386 gw->throbber = widget;
1387 break;
1388
1389
1390 case 'u': /* url bar*/
1391 if (xdir == -1) {
1392 /* met the u going backwards add url
1393 * now we know available extent
1394 */
1395
1396 widget = fbtk_create_writable_text(toolbar,
1397 xlhs,
1398 padding,
1399 xpos - xlhs,
1400 -padding,
1401 FB_COLOUR_WHITE0xFFFFFFFF,
1402 FB_COLOUR_BLACK0xFF000000,
1403 true1,
1404 fb_url_enter,
1405 gw->bw);
1406
1407 fbtk_set_handler(widget,
1408 FBTK_CBT_POINTERENTER,
1409 fb_url_move, gw->bw);
1410
1411 gw->url = widget; /* keep reference */
1412
1413 /* toolbar is complete */
1414 xdir = 0;
1415 break;
1416 }
1417 /* met url going forwards, note position and
1418 * reverse direction
1419 */
1420 itmtype = toolbar_layout + strlen(toolbar_layout);
1421 xdir = -1;
1422 xlhs = xpos;
1423 xpos = (2 * fbtk_get_width(toolbar));
1424 widget = toolbar;
1425 break;
1426
1427 default:
1428 widget = NULL((void*)0);
1429 xdir = 0;
1430 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1432
, }; nslog__log(&_nslog_ctx, "Unknown element %c in toolbar layout"
, *itmtype); } } while(0)
1431 "Unknown element %c in toolbar layout",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1432
, }; nslog__log(&_nslog_ctx, "Unknown element %c in toolbar layout"
, *itmtype); } } while(0)
1432 *itmtype)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1432
, }; nslog__log(&_nslog_ctx, "Unknown element %c in toolbar layout"
, *itmtype); } } while(0)
;
1433 break;
1434
1435 }
1436
1437 if (widget != NULL((void*)0)) {
1438 xpos += (xdir * (fbtk_get_width(widget) + padding));
1439 }
1440
1441 NSLOG(netsurf, INFO, "xpos is %d", xpos)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1441
, }; nslog__log(&_nslog_ctx, "xpos is %d", xpos); } } while
(0)
;
1442
1443 itmtype += xdir;
1444 }
1445
1446 fbtk_set_mapping(toolbar, true1);
1447
1448 return toolbar;
1449}
1450
1451
1452/** Resize a toolbar.
1453 *
1454 * @param gw Parent window
1455 * @param toolbar_height The height in pixels of the toolbar
1456 * @param padding The padding in pixels round each element of the toolbar
1457 * @param toolbar_layout A string defining which buttons and controls
1458 * should be added to the toolbar. May be empty
1459 * string to disable the bar.
1460 */
1461static void
1462resize_toolbar(struct gui_window *gw,
1463 int toolbar_height,
1464 int padding,
1465 const char *toolbar_layout)
1466{
1467 fbtk_widget_t *widget;
1468
1469 int xpos; /* The position of the next widget. */
1470 int xlhs = 0; /* extent of the left hand side widgets */
1471 int xdir = 1; /* the direction of movement + or - 1 */
1472 const char *itmtype; /* type of the next item */
1473 int x = 0, y = 0, w = 0, h = 0;
1474
1475 if (gw->toolbar == NULL((void*)0)) {
1476 return;
1477 }
1478
1479 if (toolbar_layout == NULL((void*)0)) {
1480 toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT"blfsrutc";
1481 }
1482
1483 itmtype = toolbar_layout;
1484
1485 if (*itmtype == 0) {
1486 return;
1487 }
1488
1489 fbtk_set_pos_and_size(gw->toolbar, 0, 0, 0, toolbar_height);
1490
1491 xpos = padding;
1492
1493 /* loop proceeds creating widget on the left hand side until
1494 * it runs out of layout or encounters a url bar declaration
1495 * wherupon it works backwards from the end of the layout
1496 * untill the space left is for the url bar
1497 */
1498 while (itmtype >= toolbar_layout && xdir != 0) {
1499
1500 switch (*itmtype) {
1501 case 'b': /* back */
1502 widget = gw->back;
1503 x = (xdir == 1) ? xpos : xpos - left_arrow.width;
1504 y = padding;
1505 w = left_arrow.width;
1506 h = -padding;
1507 break;
1508
1509 case 'l': /* local history */
1510 widget = gw->history;
1511 x = (xdir == 1) ? xpos : xpos - history_image.width;
1512 y = padding;
1513 w = history_image.width;
1514 h = -padding;
1515 break;
1516
1517 case 'f': /* forward */
1518 widget = gw->forward;
1519 x = (xdir == 1) ? xpos : xpos - right_arrow.width;
1520 y = padding;
1521 w = right_arrow.width;
1522 h = -padding;
1523 break;
1524
1525 case 'c': /* close the current window */
1526 widget = gw->close;
1527 x = (xdir == 1) ? xpos : xpos - stop_image_g.width;
1528 y = padding;
1529 w = stop_image_g.width;
1530 h = -padding;
1531 break;
1532
1533 case 's': /* stop */
1534 widget = gw->stop;
1535 x = (xdir == 1) ? xpos : xpos - stop_image.width;
1536 y = padding;
1537 w = stop_image.width;
1538 h = -padding;
1539 break;
1540
1541 case 'r': /* reload */
1542 widget = gw->reload;
1543 x = (xdir == 1) ? xpos : xpos - reload.width;
1544 y = padding;
1545 w = reload.width;
1546 h = -padding;
1547 break;
1548
1549 case 't': /* throbber/activity indicator */
1550 widget = gw->throbber;
1551 x = (xdir == 1) ? xpos : xpos - throbber0.width;
1552 y = padding;
1553 w = throbber0.width;
1554 h = -padding;
1555 break;
1556
1557
1558 case 'u': /* url bar*/
1559 if (xdir == -1) {
1560 /* met the u going backwards add url
1561 * now we know available extent
1562 */
1563 widget = gw->url;
1564 x = xlhs;
1565 y = padding;
1566 w = xpos - xlhs;
1567 h = -padding;
1568
1569 /* toolbar is complete */
1570 xdir = 0;
1571 break;
1572 }
1573 /* met url going forwards, note position and
1574 * reverse direction
1575 */
1576 itmtype = toolbar_layout + strlen(toolbar_layout);
1577 xdir = -1;
1578 xlhs = xpos;
1579 w = fbtk_get_width(gw->toolbar);
1580 xpos = 2 * w;
1581 widget = gw->toolbar;
1582 break;
1583
1584 default:
1585 widget = NULL((void*)0);
1586 break;
1587
1588 }
1589
1590 if (widget != NULL((void*)0)) {
1591 if (widget != gw->toolbar)
1592 fbtk_set_pos_and_size(widget, x, y, w, h);
1593 xpos += xdir * (w + padding);
1594 }
1595
1596 itmtype += xdir;
1597 }
1598}
1599
1600/** Routine called when "stripped of focus" event occours for browser widget.
1601 *
1602 * @param widget The widget reciving "stripped of focus" event.
1603 * @param cbi The callback parameters.
1604 * @return The callback result.
1605 */
1606static int
1607fb_browser_window_strip_focus(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1608{
1609 fbtk_set_caret(widget, false0, 0, 0, 0, NULL((void*)0));
1610
1611 return 0;
1612}
1613
1614static void
1615create_browser_widget(struct gui_window *gw, int toolbar_height, int furniture_width)
1616{
1617 struct browser_widget_s *browser_widget;
1618 browser_widget = calloc(1, sizeof(struct browser_widget_s));
1619
1620 gw->browser = fbtk_create_user(gw->window,
1621 0,
1622 toolbar_height,
1623 -furniture_width,
1624 -furniture_width,
1625 browser_widget);
1626
1627 fbtk_set_handler(gw->browser, FBTK_CBT_REDRAW, fb_browser_window_redraw, gw);
1628 fbtk_set_handler(gw->browser, FBTK_CBT_DESTROY, fb_browser_window_destroy, gw);
1629 fbtk_set_handler(gw->browser, FBTK_CBT_INPUT, fb_browser_window_input, gw);
1630 fbtk_set_handler(gw->browser, FBTK_CBT_CLICK, fb_browser_window_click, gw);
1631 fbtk_set_handler(gw->browser, FBTK_CBT_STRIP_FOCUS, fb_browser_window_strip_focus, gw);
1632 fbtk_set_handler(gw->browser, FBTK_CBT_POINTERMOVE, fb_browser_window_move, gw);
1633}
1634
1635static void
1636resize_browser_widget(struct gui_window *gw, int x, int y,
1637 int width, int height)
1638{
1639 fbtk_set_pos_and_size(gw->browser, x, y, width, height);
1640 browser_window_schedule_reformat(gw->bw);
1641}
1642
1643static void
1644create_normal_browser_window(struct gui_window *gw, int furniture_width)
1645{
1646 fbtk_widget_t *widget;
1647 fbtk_widget_t *toolbar;
1648 int statusbar_width = 0;
1649 int toolbar_height = nsoption_int(fb_toolbar_size)(nsoptions[NSOPTION_fb_toolbar_size].value.i);
1650
1651 NSLOG(netsurf, INFO, "Normal window")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1651
, }; nslog__log(&_nslog_ctx, "Normal window"); } } while(
0)
;
1652
1653 gw->window = fbtk_create_window(fbtk, 0, 0, 0, 0, 0);
1654
1655 statusbar_width = nsoption_int(toolbar_status_size)(nsoptions[NSOPTION_toolbar_status_size].value.i) *
1656 fbtk_get_width(gw->window) / 10000;
1657
1658 /* toolbar */
1659 toolbar = create_toolbar(gw,
1660 toolbar_height,
1661 2,
1662 FB_FRAME_COLOUR0xFFDDDDDD,
1663 nsoption_charp(fb_toolbar_layout)(nsoptions[NSOPTION_fb_toolbar_layout].value.s));
1664 gw->toolbar = toolbar;
1665
1666 /* set the actually created toolbar height */
1667 if (toolbar != NULL((void*)0)) {
1668 toolbar_height = fbtk_get_height(toolbar);
1669 } else {
1670 toolbar_height = 0;
1671 }
1672
1673 /* status bar */
1674 gw->status = fbtk_create_text(gw->window,
1675 0,
1676 fbtk_get_height(gw->window) - furniture_width,
1677 statusbar_width, furniture_width,
1678 FB_FRAME_COLOUR0xFFDDDDDD, FB_COLOUR_BLACK0xFF000000,
1679 false0);
1680 fbtk_set_handler(gw->status, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL((void*)0));
1681
1682 NSLOG(netsurf, INFO, "status bar %p at %d,%d", gw->status,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1683
, }; nslog__log(&_nslog_ctx, "status bar %p at %d,%d", gw
->status, fbtk_get_absx(gw->status), fbtk_get_absy(gw->
status)); } } while(0)
1683 fbtk_get_absx(gw->status), fbtk_get_absy(gw->status))do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1683
, }; nslog__log(&_nslog_ctx, "status bar %p at %d,%d", gw
->status, fbtk_get_absx(gw->status), fbtk_get_absy(gw->
status)); } } while(0)
;
1684
1685 /* create horizontal scrollbar */
1686 gw->hscroll = fbtk_create_hscroll(gw->window,
1687 statusbar_width,
1688 fbtk_get_height(gw->window) - furniture_width,
1689 fbtk_get_width(gw->window) - statusbar_width - furniture_width,
1690 furniture_width,
1691 FB_SCROLL_COLOUR0xFFAAAAAA,
1692 FB_FRAME_COLOUR0xFFDDDDDD,
1693 fb_scroll_callback,
1694 gw);
1695
1696 /* fill bottom right area */
1697
1698 if (nsoption_bool(fb_osk)(nsoptions[NSOPTION_fb_osk].value.b) == true1) {
1699 widget = fbtk_create_text_button(gw->window,
Value stored to 'widget' is never read
1700 fbtk_get_width(gw->window) - furniture_width,
1701 fbtk_get_height(gw->window) - furniture_width,
1702 furniture_width,
1703 furniture_width,
1704 FB_FRAME_COLOUR0xFFDDDDDD, FB_COLOUR_BLACK0xFF000000,
1705 fb_osk_click,
1706 NULL((void*)0));
1707 widget = fbtk_create_button(gw->window,
1708 fbtk_get_width(gw->window) - furniture_width,
1709 fbtk_get_height(gw->window) - furniture_width,
1710 furniture_width,
1711 furniture_width,
1712 FB_FRAME_COLOUR0xFFDDDDDD,
1713 &osk_image,
1714 fb_osk_click,
1715 NULL((void*)0));
1716 } else {
1717 widget = fbtk_create_fill(gw->window,
1718 fbtk_get_width(gw->window) - furniture_width,
1719 fbtk_get_height(gw->window) - furniture_width,
1720 furniture_width,
1721 furniture_width,
1722 FB_FRAME_COLOUR0xFFDDDDDD);
1723
1724 fbtk_set_handler(widget, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL((void*)0));
1725 }
1726
1727 gw->bottom_right = widget;
1728
1729 /* create vertical scrollbar */
1730 gw->vscroll = fbtk_create_vscroll(gw->window,
1731 fbtk_get_width(gw->window) - furniture_width,
1732 toolbar_height,
1733 furniture_width,
1734 fbtk_get_height(gw->window) - toolbar_height - furniture_width,
1735 FB_SCROLL_COLOUR0xFFAAAAAA,
1736 FB_FRAME_COLOUR0xFFDDDDDD,
1737 fb_scroll_callback,
1738 gw);
1739
1740 /* browser widget */
1741 create_browser_widget(gw, toolbar_height, nsoption_int(fb_furniture_size)(nsoptions[NSOPTION_fb_furniture_size].value.i));
1742
1743 /* Give browser_window's user widget input focus */
1744 fbtk_set_focus(gw->browser);
1745}
1746
1747static void
1748resize_normal_browser_window(struct gui_window *gw, int furniture_width)
1749{
1750 bool_Bool resized;
1751 int width, height;
1752 int statusbar_width;
1753 int toolbar_height = fbtk_get_height(gw->toolbar);
1754
1755 /* Resize the main window widget */
1756 resized = fbtk_set_pos_and_size(gw->window, 0, 0, 0, 0);
1757 if (!resized)
1758 return;
1759
1760 width = fbtk_get_width(gw->window);
1761 height = fbtk_get_height(gw->window);
1762 statusbar_width = nsoption_int(toolbar_status_size)(nsoptions[NSOPTION_toolbar_status_size].value.i) * width / 10000;
1763
1764 resize_toolbar(gw, toolbar_height, 2,
1765 nsoption_charp(fb_toolbar_layout)(nsoptions[NSOPTION_fb_toolbar_layout].value.s));
1766 fbtk_set_pos_and_size(gw->status,
1767 0, height - furniture_width,
1768 statusbar_width, furniture_width);
1769 fbtk_reposition_hscroll(gw->hscroll,
1770 statusbar_width, height - furniture_width,
1771 width - statusbar_width - furniture_width,
1772 furniture_width);
1773 fbtk_set_pos_and_size(gw->bottom_right,
1774 width - furniture_width, height - furniture_width,
1775 furniture_width, furniture_width);
1776 fbtk_reposition_vscroll(gw->vscroll,
1777 width - furniture_width,
1778 toolbar_height, furniture_width,
1779 height - toolbar_height - furniture_width);
1780 resize_browser_widget(gw,
1781 0, toolbar_height,
1782 width - furniture_width,
1783 height - furniture_width - toolbar_height);
1784}
1785
1786static void gui_window_add_to_window_list(struct gui_window *gw)
1787{
1788 gw->next = NULL((void*)0);
1789 gw->prev = NULL((void*)0);
1790
1791 if (window_list == NULL((void*)0)) {
1792 window_list = gw;
1793 } else {
1794 window_list->prev = gw;
1795 gw->next = window_list;
1796 window_list = gw;
1797 }
1798}
1799
1800static void gui_window_remove_from_window_list(struct gui_window *gw)
1801{
1802 struct gui_window *list;
1803
1804 for (list = window_list; list != NULL((void*)0); list = list->next) {
1805 if (list != gw)
1806 continue;
1807
1808 if (list == window_list) {
1809 window_list = list->next;
1810 if (window_list != NULL((void*)0))
1811 window_list->prev = NULL((void*)0);
1812 } else {
1813 list->prev->next = list->next;
1814 if (list->next != NULL((void*)0)) {
1815 list->next->prev = list->prev;
1816 }
1817 }
1818 break;
1819 }
1820}
1821
1822
1823static struct gui_window *
1824gui_window_create(struct browser_window *bw,
1825 struct gui_window *existing,
1826 gui_window_create_flags flags)
1827{
1828 struct gui_window *gw;
1829
1830 gw = calloc(1, sizeof(struct gui_window));
1831
1832 if (gw == NULL((void*)0))
1833 return NULL((void*)0);
1834
1835 /* associate the gui window with the underlying browser window
1836 */
1837 gw->bw = bw;
1838
1839 create_normal_browser_window(gw, nsoption_int(fb_furniture_size)(nsoptions[NSOPTION_fb_furniture_size].value.i));
1840
1841 /* map and request redraw of gui window */
1842 fbtk_set_mapping(gw->window, true1);
1843
1844 /* Add it to the window list */
1845 gui_window_add_to_window_list(gw);
1846
1847 return gw;
1848}
1849
1850static void
1851gui_window_destroy(struct gui_window *gw)
1852{
1853 gui_window_remove_from_window_list(gw);
1854
1855 fbtk_destroy_widget(gw->window);
1856
1857 free(gw);
1858}
1859
1860
1861/**
1862 * Invalidates an area of a framebuffer browser window
1863 *
1864 * \param g The netsurf window being invalidated.
1865 * \param rect area to redraw or NULL for the entire window area
1866 * \return NSERROR_OK on success or appropriate error code
1867 */
1868static nserror
1869fb_window_invalidate_area(struct gui_window *g, const struct rect *rect)
1870{
1871 struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
1872
1873 if (rect != NULL((void*)0)) {
1874 fb_queue_redraw(g->browser,
1875 rect->x0 - bwidget->scrollx,
1876 rect->y0 - bwidget->scrolly,
1877 rect->x1 - bwidget->scrollx,
1878 rect->y1 - bwidget->scrolly);
1879 } else {
1880 fb_queue_redraw(g->browser,
1881 0,
1882 0,
1883 fbtk_get_width(g->browser),
1884 fbtk_get_height(g->browser));
1885 }
1886 return NSERROR_OK;
1887}
1888
1889static bool_Bool
1890gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
1891{
1892 struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
1893
1894 *sx = bwidget->scrollx;
1895 *sy = bwidget->scrolly;
1896
1897 return true1;
1898}
1899
1900/**
1901 * Set the scroll position of a framebuffer browser window.
1902 *
1903 * Scrolls the viewport to ensure the specified rectangle of the
1904 * content is shown. The framebuffer implementation scrolls the contents so
1905 * the specified point in the content is at the top of the viewport.
1906 *
1907 * \param gw gui_window to scroll
1908 * \param rect The rectangle to ensure is shown.
1909 * \return NSERROR_OK on success or apropriate error code.
1910 */
1911static nserror
1912gui_window_set_scroll(struct gui_window *gw, const struct rect *rect)
1913{
1914 struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
1915
1916 assert(bwidget)((bwidget) ? (void) (0) : __assert_fail ("bwidget", "frontends/framebuffer/gui.c"
, 1916, __extension__ __PRETTY_FUNCTION__))
;
1917
1918 widget_scroll_x(gw, rect->x0, true1);
1919 widget_scroll_y(gw, rect->y0, true1);
1920
1921 return NSERROR_OK;
1922}
1923
1924
1925/**
1926 * Find the current dimensions of a framebuffer browser window content area.
1927 *
1928 * \param gw The gui window to measure content area of.
1929 * \param width receives width of window
1930 * \param height receives height of window
1931 * \return NSERROR_OK on sucess and width and height updated.
1932 */
1933static nserror
1934gui_window_get_dimensions(struct gui_window *gw, int *width, int *height)
1935{
1936 *width = fbtk_get_width(gw->browser);
1937 *height = fbtk_get_height(gw->browser);
1938
1939 return NSERROR_OK;
1940}
1941
1942static void
1943gui_window_update_extent(struct gui_window *gw)
1944{
1945 int w, h;
1946 browser_window_get_extents(gw->bw, true1, &w, &h);
1947
1948 fbtk_set_scroll_parameters(gw->hscroll, 0, w,
1949 fbtk_get_width(gw->browser), 100);
1950
1951 fbtk_set_scroll_parameters(gw->vscroll, 0, h,
1952 fbtk_get_height(gw->browser), 100);
1953}
1954
1955static void
1956gui_window_set_status(struct gui_window *g, const char *text)
1957{
1958 fbtk_set_text(g->status, text);
1959}
1960
1961static void
1962gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
1963{
1964 switch (shape) {
1965 case GUI_POINTER_POINT:
1966 framebuffer_set_cursor(&hand_image);
1967 break;
1968
1969 case GUI_POINTER_CARET:
1970 framebuffer_set_cursor(&caret_image);
1971 break;
1972
1973 case GUI_POINTER_MENU:
1974 framebuffer_set_cursor(&menu_image);
1975 break;
1976
1977 case GUI_POINTER_PROGRESS:
1978 framebuffer_set_cursor(&progress_image);
1979 break;
1980
1981 case GUI_POINTER_MOVE:
1982 framebuffer_set_cursor(&move_image);
1983 break;
1984
1985 default:
1986 framebuffer_set_cursor(&pointer_image);
1987 break;
1988 }
1989}
1990
1991static nserror
1992gui_window_set_url(struct gui_window *g, nsurl *url)
1993{
1994 fbtk_set_text(g->url, nsurl_access(url));
1995 return NSERROR_OK;
1996}
1997
1998static void
1999throbber_advance(void *pw)
2000{
2001 struct gui_window *g = pw;
2002 struct fbtk_bitmap *image;
2003
2004 switch (g->throbber_index) {
2005 case 0:
2006 image = &throbber1;
2007 g->throbber_index = 1;
2008 break;
2009
2010 case 1:
2011 image = &throbber2;
2012 g->throbber_index = 2;
2013 break;
2014
2015 case 2:
2016 image = &throbber3;
2017 g->throbber_index = 3;
2018 break;
2019
2020 case 3:
2021 image = &throbber4;
2022 g->throbber_index = 4;
2023 break;
2024
2025 case 4:
2026 image = &throbber5;
2027 g->throbber_index = 5;
2028 break;
2029
2030 case 5:
2031 image = &throbber6;
2032 g->throbber_index = 6;
2033 break;
2034
2035 case 6:
2036 image = &throbber7;
2037 g->throbber_index = 7;
2038 break;
2039
2040 case 7:
2041 image = &throbber8;
2042 g->throbber_index = 0;
2043 break;
2044
2045 default:
2046 return;
2047 }
2048
2049 if (g->throbber_index >= 0) {
2050 fbtk_set_bitmap(g->throbber, image);
2051 framebuffer_schedule(100, throbber_advance, g);
2052 }
2053}
2054
2055static void
2056gui_window_start_throbber(struct gui_window *g)
2057{
2058 g->throbber_index = 0;
2059 framebuffer_schedule(100, throbber_advance, g);
2060}
2061
2062static void
2063gui_window_stop_throbber(struct gui_window *gw)
2064{
2065 gw->throbber_index = -1;
2066 fbtk_set_bitmap(gw->throbber, &throbber0);
2067
2068 fb_update_back_forward(gw);
2069
2070}
2071
2072static void
2073gui_window_remove_caret_cb(fbtk_widget_t *widget)
2074{
2075 struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
2076 int c_x, c_y, c_h;
2077
2078 if (fbtk_get_caret(widget, &c_x, &c_y, &c_h)) {
2079 /* browser window already had caret:
2080 * redraw its area to remove it first */
2081 fb_queue_redraw(widget,
2082 c_x - bwidget->scrollx,
2083 c_y - bwidget->scrolly,
2084 c_x + 1 - bwidget->scrollx,
2085 c_y + c_h - bwidget->scrolly);
2086 }
2087}
2088
2089static void
2090gui_window_place_caret(struct gui_window *g, int x, int y, int height,
2091 const struct rect *clip)
2092{
2093 struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
2094
2095 /* set new pos */
2096 fbtk_set_caret(g->browser, true1, x, y, height,
2097 gui_window_remove_caret_cb);
2098
2099 /* redraw new caret pos */
2100 fb_queue_redraw(g->browser,
2101 x - bwidget->scrollx,
2102 y - bwidget->scrolly,
2103 x + 1 - bwidget->scrollx,
2104 y + height - bwidget->scrolly);
2105}
2106
2107static void
2108gui_window_remove_caret(struct gui_window *g)
2109{
2110 int c_x, c_y, c_h;
2111
2112 if (fbtk_get_caret(g->browser, &c_x, &c_y, &c_h)) {
2113 /* browser window owns the caret, so can remove it */
2114 fbtk_set_caret(g->browser, false0, 0, 0, 0, NULL((void*)0));
2115 }
2116}
2117
2118/**
2119 * process miscellaneous window events
2120 *
2121 * \param gw The window receiving the event.
2122 * \param event The event code.
2123 * \return NSERROR_OK when processed ok
2124 */
2125static nserror
2126gui_window_event(struct gui_window *gw, enum gui_window_event event)
2127{
2128 switch (event) {
2129 case GW_EVENT_UPDATE_EXTENT:
2130 gui_window_update_extent(gw);
2131 break;
2132
2133 case GW_EVENT_REMOVE_CARET:
2134 gui_window_remove_caret(gw);
2135 break;
2136
2137 case GW_EVENT_START_THROBBER:
2138 gui_window_start_throbber(gw);
2139 break;
2140
2141 case GW_EVENT_STOP_THROBBER:
2142 gui_window_stop_throbber(gw);
2143 break;
2144
2145 default:
2146 break;
2147 }
2148 return NSERROR_OK;
2149}
2150
2151static struct gui_window_table framebuffer_window_table = {
2152 .create = gui_window_create,
2153 .destroy = gui_window_destroy,
2154 .invalidate = fb_window_invalidate_area,
2155 .get_scroll = gui_window_get_scroll,
2156 .set_scroll = gui_window_set_scroll,
2157 .get_dimensions = gui_window_get_dimensions,
2158 .event = gui_window_event,
2159
2160 .set_url = gui_window_set_url,
2161 .set_status = gui_window_set_status,
2162 .set_pointer = gui_window_set_pointer,
2163 .place_caret = gui_window_place_caret,
2164};
2165
2166
2167static struct gui_misc_table framebuffer_misc_table = {
2168 .schedule = framebuffer_schedule,
2169
2170 .quit = gui_quit,
2171};
2172
2173/**
2174 * Entry point from OS.
2175 *
2176 * /param argc The number of arguments in the string vector.
2177 * /param argv The argument string vector.
2178 * /return The return code to the OS
2179 */
2180int
2181main(int argc, char** argv)
2182{
2183 struct browser_window *bw;
2184 char *options;
2185 char *messages;
2186 nsurl *url;
2187 nserror ret;
2188 nsfb_t *nsfb;
2189 struct netsurf_table framebuffer_table = {
2190 .misc = &framebuffer_misc_table,
2191 .window = &framebuffer_window_table,
2192 .corewindow = framebuffer_core_window_table,
2193 .clipboard = framebuffer_clipboard_table,
2194 .fetch = framebuffer_fetch_table,
2195 .utf8 = framebuffer_utf8_table,
2196 .bitmap = framebuffer_bitmap_table,
2197 .layout = framebuffer_layout_table,
2198 };
2199
2200 ret = netsurf_register(&framebuffer_table);
2201 if (ret != NSERROR_OK) {
2202 die("NetSurf operation table failed registration");
2203 }
2204
2205 respaths = fb_init_resource_path(NETSURF_FB_RESPATH"${HOME}/.netsurf/:${NETSURFRES}:/var/lib/jenkins/artifacts-x86_64-linux-gnu/share/netsurf:./frontends/framebuffer/res"":"NETSURF_FB_FONTPATH"/usr/share/fonts/truetype/dejavu:/usr/share/fonts/truetype/msttcorefonts");
2206
2207 /* initialise logging. Not fatal if it fails but not much we
2208 * can do about it either.
2209 */
2210 nslog_init(nslog_stream_configure, &argc, argv);
2211
2212 /* user options setup */
2213 ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
2214 if (ret != NSERROR_OK) {
2215 die("Options failed to initialise");
2216 }
2217 options = filepath_find(respaths, "Choices");
2218 nsoption_read(options, nsoptions);
2219 free(options);
2220 nsoption_commandline(&argc, argv, nsoptions);
2221
2222 /* message init */
2223 messages = filepath_find(respaths, "Messages");
2224 ret = messages_add_from_file(messages);
2225 free(messages);
2226 if (ret != NSERROR_OK) {
2227 fprintf(stderrstderr, "Message translations failed to load\n");
2228 }
2229
2230 /* common initialisation */
2231 ret = netsurf_init(NULL((void*)0));
2232 if (ret != NSERROR_OK) {
2233 die("NetSurf failed to initialise");
2234 }
2235
2236 /* Override, since we have no support for non-core SELECT menu */
2237 nsoption_set_bool(core_select_menu, true)nsoptions[NSOPTION_core_select_menu].value.b = 1;
2238
2239 if (process_cmdline(argc,argv) != true1)
2240 die("unable to process command line.\n");
2241
2242 nsfb = framebuffer_initialise(fename, fewidth, feheight, febpp);
2243 if (nsfb == NULL((void*)0))
2244 die("Unable to initialise framebuffer");
2245
2246 framebuffer_set_cursor(&pointer_image);
2247
2248 if (fb_font_init() == false0)
2249 die("Unable to initialise the font system");
2250
2251 fbtk = fbtk_init(nsfb);
2252
2253 fbtk_enable_oskb(fbtk);
2254
2255 urldb_load_cookies(nsoption_charp(cookie_file)(nsoptions[NSOPTION_cookie_file].value.s));
2256
2257 /* create an initial browser window */
2258
2259 NSLOG(netsurf, INFO, "calling browser_window_create")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 2259
, }; nslog__log(&_nslog_ctx, "calling browser_window_create"
); } } while(0)
;
2260
2261 ret = nsurl_create(feurl, &url);
2262 if (ret == NSERROR_OK) {
2263 ret = browser_window_create(BW_CREATE_HISTORY,
2264 url,
2265 NULL((void*)0),
2266 NULL((void*)0),
2267 &bw);
2268 nsurl_unref(url);
2269 }
2270 if (ret != NSERROR_OK) {
2271 fb_warn_user("Errorcode:", messages_get_errorcode(ret));
2272 } else {
2273 framebuffer_run();
2274
2275 browser_window_destroy(bw);
2276 }
2277
2278 netsurf_exit();
2279
2280 if (fb_font_finalise() == false0)
2281 NSLOG(netsurf, INFO, "Font finalisation failed.")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 2281
, }; nslog__log(&_nslog_ctx, "Font finalisation failed.")
; } } while(0)
;
2282
2283 /* finalise options */
2284 nsoption_finalise(nsoptions, nsoptions_default);
2285
2286 /* finalise logging */
2287 nslog_finalise();
2288
2289 return 0;
2290}
2291
2292void gui_resize(fbtk_widget_t *root, int width, int height)
2293{
2294 struct gui_window *gw;
2295 nsfb_t *nsfb = fbtk_get_nsfb(root);
2296
2297 /* Enforce a minimum */
2298 if (width < 300)
2299 width = 300;
2300 if (height < 200)
2301 height = 200;
2302
2303 if (framebuffer_resize(nsfb, width, height, febpp) == false0) {
2304 return;
2305 }
2306
2307 fbtk_set_pos_and_size(root, 0, 0, width, height);
2308
2309 fewidth = width;
2310 feheight = height;
2311
2312 for (gw = window_list; gw != NULL((void*)0); gw = gw->next) {
2313 resize_normal_browser_window(gw,
2314 nsoption_int(fb_furniture_size)(nsoptions[NSOPTION_fb_furniture_size].value.i));
2315 }
2316
2317 fbtk_request_redraw(root);
2318}
2319
2320
2321/*
2322 * Local Variables:
2323 * c-basic-offset:8
2324 * End:
2325 */