NetSurf
window.c
Go to the documentation of this file.
1/*
2 * Copyright 2006 Daniel Silverstone <dsilvers@digital-scurf.org>
3 * Copyright 2006 Rob Kendrick <rjek@rjek.com>
4 *
5 * This file is part of NetSurf, http://www.netsurf-browser.org/
6 *
7 * NetSurf is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * NetSurf is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/**
21 * \file
22 * Implementation of gtk windowing.
23 */
24
25#include <stdlib.h>
26#include <string.h>
27#include <limits.h>
28#include <assert.h>
29#include <math.h>
30#include <gtk/gtk.h>
31#include <gdk/gdkkeysyms.h>
32#include <gdk-pixbuf/gdk-pixdata.h>
33
34#include "utils/utils.h"
35#include "utils/log.h"
36#include "utils/utf8.h"
37#include "utils/nsoption.h"
38#include "utils/messages.h"
39#include "utils/nsurl.h"
40#include "netsurf/inttypes.h"
41#include "netsurf/content.h"
43#include "netsurf/mouse.h"
44#include "netsurf/window.h"
45#include "netsurf/plotters.h"
46#include "netsurf/form.h"
47#include "netsurf/keypress.h"
48#include "desktop/searchweb.h"
49#include "desktop/textinput.h"
50
51#include "gtk/selection.h"
52#include "gtk/warn.h"
53#include "gtk/compat.h"
54#include "gtk/gui.h"
55#include "gtk/scaffolding.h"
56#include "gtk/toolbar_items.h"
57#include "gtk/toolbar.h"
58#include "gtk/local_history.h"
59#include "gtk/plotters.h"
60#include "gtk/schedule.h"
61#include "gtk/tabs.h"
62#include "gtk/bitmap.h"
63#include "gtk/gdk.h"
64#include "gtk/resources.h"
65#include "gtk/search.h"
66#include "gtk/throbber.h"
67#include "gtk/window.h"
68
69/**
70 * time (in ms) between throbber animation frame updates
71 */
72#define THROBBER_FRAME_TIME (100)
73
74static GtkWidget *select_menu;
76
77struct gui_window {
78 /**
79 * The gtk scaffold object containing menu, buttons, url bar, [tabs],
80 * drawing area, etc that may contain one or more gui_windows.
81 */
83
84 /** The 'content' window that is rendered in the gui_window */
85 struct browser_window *bw;
86
87 /** mouse state and events. */
88 struct {
89 struct gui_window *gui;
90
91 gdouble pressed_x;
92 gdouble pressed_y;
93 gboolean waiting;
96
97 /** caret dimension and location for rendering */
98 int caretx, carety, careth;
99
100 /** caret shape for rendering */
102
103 /** previous event location */
104 int last_x, last_y;
105
106 /** controls toolbar context */
108
109 /** search toolbar context */
111
112 /** The top level container (tabBox) */
113 GtkWidget *container;
114
115 /** display widget for this page or frame */
116 GtkLayout *layout;
117
118 /** The container for the layout etc */
119 GtkWidget *grid;
120
121 /** handle to the the visible tab */
122 GtkWidget *tab;
123
124 /** statusbar */
125 GtkLabel *status_bar;
126
127 /** status pane */
128 GtkPaned *paned;
129
130 /** has the status pane had its first size operation yet? */
132
133 /** The icon this window should have */
134 GdkPixbuf *icon;
135
136 /** The input method to use with this window */
137 GtkIMContext *input_method;
138
139 /** current frame of throbber */
141
142 /** list for cleanup */
143 struct gui_window *next, *prev;
144};
145
146/**< first entry in window list */
147struct gui_window *window_list = NULL;
148
149static void
150nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem,
151 gpointer user_data)
152{
154 (intptr_t)user_data);
155}
156
157#if GTK_CHECK_VERSION(3,0,0)
158
159static gboolean
160nsgtk_window_draw_event(GtkWidget *widget, cairo_t *cr, gpointer data)
161{
162 struct gui_window *gw = data;
163 struct gui_window *z;
164 struct rect clip;
165 struct redraw_context ctx = {
166 .interactive = true,
167 .background_images = true,
168 .plot = &nsgtk_plotters
169 };
170
171 double x1;
172 double y1;
173 double x2;
174 double y2;
175
176 assert(gw);
177 assert(gw->bw);
178
179 for (z = window_list; z && z != gw; z = z->next)
180 continue;
181 assert(z);
182 assert(GTK_WIDGET(gw->layout) == widget);
183
184 current_cr = cr;
185
186 GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(gw->layout);
187 GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(gw->layout);
188
189 cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
190
191 clip.x0 = x1;
192 clip.y0 = y1;
193 clip.x1 = x2;
194 clip.y1 = y2;
195
197 -gtk_adjustment_get_value(hscroll),
198 -gtk_adjustment_get_value(vscroll),
199 &clip,
200 &ctx);
201
202 if (gw->careth != 0) {
203 nsgtk_plot_caret(gw->caretx, gw->carety, gw->careth);
204 }
205
206 return FALSE;
207}
208
209#else
210
211static gboolean
212nsgtk_window_draw_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
213{
214 struct gui_window *gw = data;
215 struct gui_window *z;
216 struct rect clip;
217 struct redraw_context ctx = {
218 .interactive = true,
219 .background_images = true,
220 .plot = &nsgtk_plotters
221 };
222
223 assert(gw);
224 assert(gw->bw);
225
226 for (z = window_list; z && z != gw; z = z->next)
227 continue;
228 assert(z);
229 assert(GTK_WIDGET(gw->layout) == widget);
230
231 current_cr = gdk_cairo_create(nsgtk_layout_get_bin_window(gw->layout));
232
233 clip.x0 = event->area.x;
234 clip.y0 = event->area.y;
235 clip.x1 = event->area.x + event->area.width;
236 clip.y1 = event->area.y + event->area.height;
237
238 browser_window_redraw(gw->bw, 0, 0, &clip, &ctx);
239
240 if (gw->careth != 0) {
241 nsgtk_plot_caret(gw->caretx, gw->carety, gw->careth);
242 }
243
244 cairo_destroy(current_cr);
245
246 return FALSE;
247}
248
249#endif
250
251static gboolean
253 GdkEventMotion *event,
254 gpointer data)
255{
256 struct gui_window *g = data;
257 bool shift = event->state & GDK_SHIFT_MASK;
258 bool ctrl = event->state & GDK_CONTROL_MASK;
259
260 if ((fabs(event->x - g->last_x) < 5.0) &&
261 (fabs(event->y - g->last_y) < 5.0)) {
262 /* Mouse hasn't moved far enough from press coordinate
263 * for this to be considered a drag.
264 */
265 return FALSE;
266 } else {
267 /* This is a drag, ensure it's always treated as such,
268 * even if we drag back over the press location.
269 */
270 g->last_x = INT_MIN;
271 g->last_y = INT_MIN;
272 }
273
275 /* Start button 1 drag */
278
279 /* Replace PRESS with HOLDING and declare drag in progress */
283 } else if (g->mouse.state & BROWSER_MOUSE_PRESS_2) {
284 /* Start button 2 drag */
287
288 /* Replace PRESS with HOLDING and declare drag in progress */
292 }
293
294 /* Handle modifiers being removed */
295 if (g->mouse.state & BROWSER_MOUSE_MOD_1 && !shift)
297 if (g->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl)
299
300 browser_window_mouse_track(g->bw, g->mouse.state, event->x, event->y);
301
302 return TRUE;
303}
304
305/**
306 * GTK signal handler for focus-out-event on layout
307 *
308 * when focus leaves the layout widget ensure the caret is cleared
309 */
310static gboolean
312 GdkEvent *event,
313 gpointer data)
314{
315 struct gui_window *g = data;
316
318 return FALSE;
319}
320
321/**
322 * GTK signal handler for button-press-event on layout
323 */
324static gboolean
326 GdkEventButton *event,
327 gpointer data)
328{
329 struct gui_window *g = data;
330
331 gtk_im_context_reset(g->input_method);
332 gtk_widget_grab_focus(GTK_WIDGET(g->layout));
334
335 g->mouse.pressed_x = event->x;
336 g->mouse.pressed_y = event->y;
337
338 switch (event->button) {
339 case 1: /* Left button, usually. Pass to core as BUTTON 1. */
341 break;
342
343 case 2: /* Middle button, usually. Pass to core as BUTTON 2 */
345 break;
346
347 case 3: /* Right button, usually. Action button, context menu. */
348 /** \todo determine if hiding the caret here is necessary */
351 g->mouse.pressed_x,
352 g->mouse.pressed_y);
353 return TRUE;
354
355 default:
356 return FALSE;
357 }
358
359 /* Modify for double & triple clicks */
360 if (event->type == GDK_3BUTTON_PRESS)
362 else if (event->type == GDK_2BUTTON_PRESS)
364
365 /* Handle the modifiers too */
366 if (event->state & GDK_SHIFT_MASK)
368 if (event->state & GDK_CONTROL_MASK)
370
371 /* Record where we pressed, for use when determining whether to start
372 * a drag in motion notify events. */
373 g->last_x = event->x;
374 g->last_y = event->y;
375
377 g->mouse.state,
378 g->mouse.pressed_x,
379 g->mouse.pressed_y);
380
381 return TRUE;
382}
383
384
385static gboolean
387 GdkEventButton *event,
388 gpointer data)
389{
390 struct gui_window *g = data;
391 bool shift = event->state & GDK_SHIFT_MASK;
392 bool ctrl = event->state & GDK_CONTROL_MASK;
393
394 switch (event->button) {
395 case 8:
397 break;
398 case 9:
400 break;
401 default:
402 NSLOG(netsurf, DEBUG, "event button %d", event->button);
403 break;
404 }
405
406 /* If the mouse state is PRESS then we are waiting for a release to emit
407 * a click event, otherwise just reset the state to nothing */
410 } else if (g->mouse.state & BROWSER_MOUSE_PRESS_2) {
412 }
413
414 /* Handle modifiers being removed */
415 if (g->mouse.state & BROWSER_MOUSE_MOD_1 && !shift)
417 if (g->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl)
419
421 browser_window_mouse_click(g->bw, g->mouse.state, event->x, event->y);
422 } else {
423 browser_window_mouse_track(g->bw, 0, event->x, event->y);
424 }
425
426 g->mouse.state = 0;
427 return TRUE;
428}
429
430
431static gboolean
433 GdkEventScroll *event,
434 gpointer data)
435{
436 struct gui_window *g = data;
437 double value;
438 double deltax = 0;
439 double deltay = 0;
440 GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(g->layout);
441 GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(g->layout);
442 GtkAllocation alloc;
443
444 switch (event->direction) {
445 case GDK_SCROLL_LEFT:
446 deltax = -1.0;
447 break;
448
449 case GDK_SCROLL_UP:
450 deltay = -1.0;
451 break;
452
453 case GDK_SCROLL_RIGHT:
454 deltax = 1.0;
455 break;
456
457 case GDK_SCROLL_DOWN:
458 deltay = 1.0;
459 break;
460
461#if GTK_CHECK_VERSION(3,4,0)
462 case GDK_SCROLL_SMOOTH:
463 gdk_event_get_scroll_deltas((GdkEvent *)event, &deltax, &deltay);
464 break;
465#endif
466 default:
467 NSLOG(netsurf, INFO, "Unhandled mouse scroll direction");
468 return TRUE;
469 }
470
473
475 event->x, event->y,
476 deltax, deltay) != true) {
477
478 /* core did not handle event so change adjustments */
479
480 /* Horizontal */
481 if (deltax != 0) {
482 value = gtk_adjustment_get_value(hscroll) + deltax;
483
484 /* @todo consider gtk_widget_get_allocated_width() */
485 nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);
486
487 if (value > nsgtk_adjustment_get_upper(hscroll) - alloc.width) {
488 value = nsgtk_adjustment_get_upper(hscroll) - alloc.width;
489 }
490 if (value < nsgtk_adjustment_get_lower(hscroll)) {
492 }
493
494 gtk_adjustment_set_value(hscroll, value);
495 }
496
497 /* Vertical */
498 if (deltay != 0) {
499 value = gtk_adjustment_get_value(vscroll) + deltay;
500
501 /* @todo consider gtk_widget_get_allocated_height */
502 nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);
503
504 if (value > (nsgtk_adjustment_get_upper(vscroll) - alloc.height)) {
505 value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;
506 }
507 if (value < nsgtk_adjustment_get_lower(vscroll)) {
509 }
510
511 gtk_adjustment_set_value(vscroll, value);
512 }
513 }
514
515 return TRUE;
516}
517
518
519static gboolean
521 GdkEventKey *event,
522 gpointer data)
523{
524 struct gui_window *g = data;
525 uint32_t nskey;
526
527 if (gtk_im_context_filter_keypress(g->input_method, event))
528 return TRUE;
529
530 nskey = gtk_gui_gdkkey_to_nskey(event);
531
532 if (browser_window_key_press(g->bw, nskey))
533 return TRUE;
534
535 if ((event->state & 0x7) != 0)
536 return TRUE;
537
538 double value;
539 GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(g->layout);
540 GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(g->layout);
541 GtkAllocation alloc;
542
543 /* @todo consider gtk_widget_get_allocated_width() */
544 nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);
545
546 switch (event->keyval) {
547
548 case GDK_KEY(Home):
549 case GDK_KEY(KP_Home):
551 gtk_adjustment_set_value(vscroll, value);
552 break;
553
554 case GDK_KEY(End):
555 case GDK_KEY(KP_End):
556 value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;
557
560
561 gtk_adjustment_set_value(vscroll, value);
562 break;
563
564 case GDK_KEY(Left):
565 case GDK_KEY(KP_Left):
566 value = gtk_adjustment_get_value(hscroll) -
568
571
572 gtk_adjustment_set_value(hscroll, value);
573 break;
574
575 case GDK_KEY(Up):
576 case GDK_KEY(KP_Up):
577 value = gtk_adjustment_get_value(vscroll) -
579
582
583 gtk_adjustment_set_value(vscroll, value);
584 break;
585
586 case GDK_KEY(Right):
587 case GDK_KEY(KP_Right):
588 value = gtk_adjustment_get_value(hscroll) +
590
591 if (value > nsgtk_adjustment_get_upper(hscroll) - alloc.width)
592 value = nsgtk_adjustment_get_upper(hscroll) - alloc.width;
593
594 gtk_adjustment_set_value(hscroll, value);
595 break;
596
597 case GDK_KEY(Down):
598 case GDK_KEY(KP_Down):
599 value = gtk_adjustment_get_value(vscroll) +
601
602 if (value > nsgtk_adjustment_get_upper(vscroll) - alloc.height)
603 value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;
604
605 gtk_adjustment_set_value(vscroll, value);
606 break;
607
608 case GDK_KEY(Page_Up):
609 case GDK_KEY(KP_Page_Up):
610 value = gtk_adjustment_get_value(vscroll) -
612
615
616 gtk_adjustment_set_value(vscroll, value);
617 break;
618
619 case GDK_KEY(Page_Down):
620 case GDK_KEY(KP_Page_Down):
621 value = gtk_adjustment_get_value(vscroll) +
623
624 if (value > nsgtk_adjustment_get_upper(vscroll) - alloc.height)
625 value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;
626
627 gtk_adjustment_set_value(vscroll, value);
628 break;
629
630 default:
631 break;
632
633 }
634
635 return TRUE;
636}
637
638
639static gboolean
641 GdkEventKey *event,
642 gpointer data)
643{
644 struct gui_window *g = data;
645
646 return gtk_im_context_filter_keypress(g->input_method, event);
647}
648
649
650static void
652 const gchar *str,
653 gpointer data)
654{
655 struct gui_window *g = data;
656 size_t len = strlen(str), offset = 0;
657
658 while (offset < len) {
659 uint32_t nskey = utf8_to_ucs4(str + offset, len - offset);
660
661 browser_window_key_press(g->bw, nskey);
662
663 offset = utf8_next(str, len, offset);
664 }
665}
666
667
668static gboolean
670 GtkAllocation *allocation,
671 gpointer data)
672{
673 struct gui_window *g = data;
674
676
677 return TRUE;
678}
679
680
681/**
682 * when the pane position is changed update the user option
683 *
684 * The slightly awkward implementation with the first allocation flag
685 * is necessary because the initial window creation does not cause an
686 * allocate-event signal so the position value in the pane is incorrect
687 * and we cannot know what it should be until after the allocation
688 * (which did not generate a signal) is done as the user position is a
689 * percentage of pane total width not an absolute value.
690 */
691static void
692nsgtk_paned_notify__position(GObject *gobject, GParamSpec *pspec, gpointer data)
693{
694 struct gui_window *g = data;
695 GtkAllocation pane_alloc;
696
697 gtk_widget_get_allocation(GTK_WIDGET(g->paned), &pane_alloc);
698
699 if (g->paned_sized == false)
700 {
701 g->paned_sized = true;
702 gtk_paned_set_position(g->paned,
703 (nsoption_int(toolbar_status_size) * pane_alloc.width) / 10000);
704 return;
705 }
706
707 nsoption_set_int(toolbar_status_size,
708 ((gtk_paned_get_position(g->paned) * 10000) / (pane_alloc.width - 1)));
709}
710
711
712/**
713 * Set status bar / scroll bar proportion according to user option
714 * when pane is resized.
715 */
716static gboolean
718 GtkAllocation *allocation,
719 gpointer data)
720{
721 gtk_paned_set_position(GTK_PANED(widget),
722 (nsoption_int(toolbar_status_size) * allocation->width) / 10000);
723
724 return TRUE;
725}
726
727
728/**
729 * handler for gtk destroy signal on window container
730 *
731 * destroy the browsing context as there is will be nothing to display it now
732 */
733static void window_destroy(GtkWidget *widget, gpointer data)
734{
735 struct gui_window *gw = data;
736
738
739 g_object_unref(gw->input_method);
740
741 /* free any existing icon */
742 if (gw->icon != NULL) {
743 g_object_unref(gw->icon);
744 gw->icon = NULL;
745 }
746
747 free(gw);
748}
749
750
751static struct browser_window *bw_from_gw(void *data)
752{
753 struct gui_window *gw = data;
754 return gw->bw;
755}
756
757
758static bool get_tool_bar_show(void)
759{
760 const char *cur_bar_show;
761
762 cur_bar_show = nsoption_charp(bar_show);
763 if (cur_bar_show != NULL) {
764 if (strcmp(cur_bar_show, "menu/tool") == 0) {
765 return true;
766 } else if (strcmp(cur_bar_show, "tool") == 0) {
767 return true;
768 }
769 }
770 return false;
771}
772
773
774/**
775 * Make the throbber advance to next frame.
776 *
777 * scheduled callback to update the throbber
778 *
779 * \param p The context passed when scheduled.
780 */
781static void next_throbber_frame(void *p)
782{
783 struct gui_window *gw = p;
784 nserror res;
785 GdkPixbuf *pixbuf;
786
787 gw->throb_frame++; /* advance to next frame */
788
789 res = nsgtk_throbber_get_frame(gw->throb_frame, &pixbuf);
790 if (res == NSERROR_BAD_SIZE) {
791 gw->throb_frame = 1;
792 res = nsgtk_throbber_get_frame(gw->throb_frame, &pixbuf);
793 }
794
795 if (res == NSERROR_OK) {
796 nsgtk_tab_set_icon(gw->container, pixbuf);
797 /* only schedule next frame if there are no errors */
799 }
800}
801
802
803/**
804 * Create and open a gtk container (window or tab) for a browsing context.
805 *
806 * \param bw The browsing context to create gui_window for.
807 * \param existing An existing gui_window, may be NULL
808 * \param flags flags to control the container creation
809 * \return gui window, or NULL on error
810 *
811 * If GW_CREATE_CLONE flag is set existing is non-NULL.
812 *
813 * Front end's gui_window must include a reference to the
814 * browser window passed in the bw param.
815 */
816static struct gui_window *
818 struct gui_window *existing,
820{
821 struct gui_window *g; /* what is being created to return */
822 bool open_in_background = !(nsoption_bool(focus_new));
823 GtkBuilder* tab_builder;
824
825 /* If there is a foreground request, override user preference */
826 if (flags & GW_CREATE_FOREGROUND)
827 open_in_background = false;
828
829 nserror res;
830
831 res = nsgtk_builder_new_from_resname("tabcontents", &tab_builder);
832 if (res != NSERROR_OK) {
833 NSLOG(netsurf, INFO, "Tab contents UI builder init failed");
834 return NULL;
835 }
836
837 gtk_builder_connect_signals(tab_builder, NULL);
838
839 g = calloc(1, sizeof(*g));
840 if (!g) {
841 nsgtk_warning("NoMemory", 0);
842 g_object_unref(tab_builder);
843 return NULL;
844 }
845
846 NSLOG(netsurf, INFO, "Creating gui window %p for browser window %p",
847 g, bw);
848
849 g->bw = bw;
850 g->mouse.state = 0;
852
853 /* attach scaffold */
854 if (flags & GW_CREATE_TAB) {
855 /* open in new tab, attach to existing scaffold */
856 if (existing != NULL) {
857 g->scaffold = existing->scaffold;
858 } else {
860 }
861 } else {
862 /* open in new window, create and attach to scaffold */
864 }
865 if (g->scaffold == NULL) {
866 nsgtk_warning("NoMemory", 0);
867 free(g);
868 g_object_unref(tab_builder);
869 return NULL;
870 }
871
872 /* Construct our primary elements */
873 g->container = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabBox"));
874 g->layout = GTK_LAYOUT(gtk_builder_get_object(tab_builder, "layout"));
875 g->grid = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabContents"));
876 g->status_bar = GTK_LABEL(gtk_builder_get_object(tab_builder, "status_bar"));
877 g->paned = GTK_PANED(gtk_builder_get_object(tab_builder, "hpaned1"));
878 g->input_method = gtk_im_multicontext_new();
879
880
881 /* create toolbar */
882 res = nsgtk_toolbar_create(tab_builder, bw_from_gw, g,
883 !!(flags & GW_CREATE_FOCUS_LOCATION),
884 &g->toolbar);
885 if (res != NSERROR_OK) {
886 free(g);
887 g_object_unref(tab_builder);
888 return NULL;
889 }
890
891 /* local page text search toolbar */
892 res = nsgtk_search_create(tab_builder, g->bw, &g->search);
893 if (res != NSERROR_OK) {
894 free(g);
895 g_object_unref(tab_builder);
896 return NULL;
897 }
898
899 /* set a default favicon */
900 g_object_ref(favicon_pixbuf);
901 g->icon = favicon_pixbuf;
902
903 /* add new gui window to global list (push_top) */
904 if (window_list) {
905 window_list->prev = g;
906 }
907 g->next = window_list;
908 g->prev = NULL;
909 window_list = g;
910
911 /* set the events we're interested in receiving from the browser's
912 * drawing area.
913 */
914 gtk_widget_add_events(GTK_WIDGET(g->layout),
915 GDK_EXPOSURE_MASK |
916 GDK_LEAVE_NOTIFY_MASK |
917 GDK_BUTTON_PRESS_MASK |
918 GDK_BUTTON_RELEASE_MASK |
919 GDK_POINTER_MOTION_MASK |
920 GDK_POINTER_MOTION_HINT_MASK |
921 GDK_KEY_PRESS_MASK |
922 GDK_KEY_RELEASE_MASK |
923 GDK_SCROLL_MASK);
924 nsgtk_widget_set_can_focus(GTK_WIDGET(g->layout), TRUE);
925
926 /* set the default background colour of the drawing area to white. */
929 0, 0xffff, 0xffff, 0xffff);
930
931 nsgtk_connect_draw_event(GTK_WIDGET(g->layout),
932 G_CALLBACK(nsgtk_window_draw_event), g);
933
934 /* helper macro to conect signals to callbacks */
935#define CONNECT(obj, sig, callback, ptr) \
936 g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
937
938 /* layout signals */
939 CONNECT(g->layout, "motion-notify-event",
941 CONNECT(g->layout, "button-press-event",
943 CONNECT(g->layout, "button-release-event",
945 CONNECT(g->layout, "key-press-event",
947 CONNECT(g->layout, "key-release-event",
949 CONNECT(g->layout, "size-allocate",
951 CONNECT(g->layout, "scroll-event",
953 CONNECT(g->layout, "focus-out-event",
955
956 /* status pane signals */
957 CONNECT(g->paned, "size-allocate",
959
960 CONNECT(g->paned, "notify::position",
962
963 /* gtk container destructor */
964 CONNECT(g->container, "destroy", window_destroy, g);
965
966 /* input method */
967 gtk_im_context_set_client_window(g->input_method,
969 gtk_im_context_set_use_preedit(g->input_method, FALSE);
970
971 /* input method signals */
972 CONNECT(g->input_method, "commit",
974
975 /* add the tab container to the scaffold notebook */
977 open_in_background,
978 messages_get("NewTab"), g->icon);
979
980 /* initialy should not be visible */
982
983 /* set toolbar visibility from user option */
985
986 /* safe to drop the reference to the tab_builder as the container is
987 * referenced by the notebook now.
988 */
989 g_object_unref(tab_builder);
990
991 /* Finally we need to focus the location bar if requested */
992 if (flags & GW_CREATE_FOCUS_LOCATION) {
994 NSLOG(netsurf, WARNING, "Unable to focus location input");
995 }
996 }
997
998 return g;
999}
1000
1001
1002static void gui_window_destroy(struct gui_window *gw)
1003{
1004 NSLOG(netsurf, INFO, "gui_window: %p", gw);
1005 assert(gw != NULL);
1006 assert(gw->bw != NULL);
1007 NSLOG(netsurf, INFO, "scaffolding: %p", gw->scaffold);
1008
1009 /* kill off any throbber that might be running */
1011
1012 /* remove from window list */
1013 if (gw->prev) {
1014 gw->prev->next = gw->next;
1015 } else {
1016 window_list = gw->next;
1017 }
1018
1019 if (gw->next) {
1020 gw->next->prev = gw->prev;
1021 }
1022
1023 NSLOG(netsurf, INFO, "window list head: %p", window_list);
1024}
1025
1026
1027/**
1028 * favicon setting for gtk gui window.
1029 *
1030 * \param gw gtk gui window to set favicon on.
1031 * \param icon A handle to the new favicon content.
1032 */
1033static void
1035{
1036 struct bitmap *icon_bitmap = NULL;
1037
1038 /* free any existing icon */
1039 if (gw->icon != NULL) {
1040 g_object_unref(gw->icon);
1041 gw->icon = NULL;
1042 }
1043
1044 if (icon != NULL) {
1045 icon_bitmap = content_get_bitmap(icon);
1046 if (icon_bitmap != NULL) {
1047 NSLOG(netsurf, INFO, "Using %p bitmap", icon_bitmap);
1048 gw->icon = nsgdk_pixbuf_get_from_surface(icon_bitmap->surface, 16, 16);
1049 }
1050 }
1051
1052 if (gw->icon == NULL) {
1053 NSLOG(netsurf, INFO, "Using default favicon");
1054 g_object_ref(favicon_pixbuf);
1055 gw->icon = favicon_pixbuf;
1056 }
1057
1058 /* only set icon if throbber not running */
1059 if (gw->throb_frame == 0) {
1061 }
1062}
1063
1064
1065static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
1066{
1067 GtkAdjustment *vadj = nsgtk_layout_get_vadjustment(g->layout);
1068 GtkAdjustment *hadj = nsgtk_layout_get_hadjustment(g->layout);
1069
1070 assert(vadj);
1071 assert(hadj);
1072
1073 *sy = (int)(gtk_adjustment_get_value(vadj));
1074 *sx = (int)(gtk_adjustment_get_value(hadj));
1075
1076 return true;
1077}
1078
1079
1080static void nsgtk_redraw_caret(struct gui_window *g)
1081{
1082 int sx, sy;
1083
1084 if (g->careth == 0)
1085 return;
1086
1087 gui_window_get_scroll(g, &sx, &sy);
1088
1089 gtk_widget_queue_draw_area(GTK_WIDGET(g->layout),
1090 g->caretx - sx, g->carety - sy, 1, g->careth + 1);
1091
1092}
1093
1094
1096{
1097 int sx, sy;
1098 int oh = g->careth;
1099
1100 if (oh == 0)
1101 return;
1102
1103 g->careth = 0;
1104
1105 gui_window_get_scroll(g, &sx, &sy);
1106
1107 gtk_widget_queue_draw_area(GTK_WIDGET(g->layout),
1108 g->caretx - sx, g->carety - sy, 1, oh + 1);
1109
1110}
1111
1112
1113/**
1114 * Invalidates an area of a GTK browser window
1115 *
1116 * \param g gui_window
1117 * \param rect area to redraw or NULL for the entire window area
1118 * \return NSERROR_OK on success or appropriate error code
1119 */
1120static nserror
1122{
1123 int sx, sy;
1124
1125 if (rect == NULL) {
1126 gtk_widget_queue_draw(GTK_WIDGET(g->layout));
1127 return NSERROR_OK;
1128 }
1129
1130 if (!browser_window_has_content(g->bw)) {
1131 return NSERROR_OK;
1132 }
1133
1134 gui_window_get_scroll(g, &sx, &sy);
1135
1136 gtk_widget_queue_draw_area(GTK_WIDGET(g->layout),
1137 rect->x0 - sx,
1138 rect->y0 - sy,
1139 rect->x1 - rect->x0,
1140 rect->y1 - rect->y0);
1141
1142 return NSERROR_OK;
1143}
1144
1145
1146static void gui_window_set_status(struct gui_window *g, const char *text)
1147{
1148 assert(g);
1149 assert(g->status_bar);
1150 gtk_label_set_text(g->status_bar, text);
1151}
1152
1153
1154/**
1155 * Set the scroll position of a gtk browser window.
1156 *
1157 * Scrolls the viewport to ensure the specified rectangle of the
1158 * content is shown. The GTK implementation scrolls the contents so
1159 * the specified point in the content is at the top of the viewport.
1160 *
1161 * \param g gui window to scroll
1162 * \param rect The rectangle to ensure is shown.
1163 * \return NSERROR_OK on success or apropriate error code.
1164 */
1165static nserror
1167{
1168 GtkAdjustment *vadj = nsgtk_layout_get_vadjustment(g->layout);
1169 GtkAdjustment *hadj = nsgtk_layout_get_hadjustment(g->layout);
1170 gdouble vlower, vpage, vupper, hlower, hpage, hupper;
1171 gdouble x = (gdouble)rect->x0;
1172 gdouble y = (gdouble)rect->y0;
1173
1174 assert(vadj);
1175 assert(hadj);
1176
1177 g_object_get(vadj, "page-size", &vpage, "lower", &vlower, "upper", &vupper, NULL);
1178 g_object_get(hadj, "page-size", &hpage, "lower", &hlower, "upper", &hupper, NULL);
1179
1180 if (x < hlower) {
1181 x = hlower;
1182 }
1183 if (x > (hupper - hpage)) {
1184 x = hupper - hpage;
1185 }
1186 if (y < vlower) {
1187 y = vlower;
1188 }
1189 if (y > (vupper - vpage)) {
1190 y = vupper - vpage;
1191 }
1192
1193 gtk_adjustment_set_value(vadj, y);
1194 gtk_adjustment_set_value(hadj, x);
1195
1196 return NSERROR_OK;
1197}
1198
1199
1201{
1202 int w, h;
1203
1204 if (browser_window_get_extents(g->bw, true, &w, &h) == NSERROR_OK) {
1205 gtk_layout_set_size(g->layout, w, h);
1206 gtk_widget_queue_resize(g->grid);
1207 }
1208}
1209
1210
1211static void
1213{
1214 GdkCursor *cursor = NULL;
1215 GdkCursorType cursortype;
1216 bool nullcursor = false;
1217
1218 if (g->current_pointer == shape)
1219 return;
1220
1221 g->current_pointer = shape;
1222
1223 switch (shape) {
1224 case GUI_POINTER_POINT:
1225 cursortype = GDK_HAND2;
1226 break;
1227 case GUI_POINTER_CARET:
1228 cursortype = GDK_XTERM;
1229 break;
1230 case GUI_POINTER_UP:
1231 cursortype = GDK_TOP_SIDE;
1232 break;
1233 case GUI_POINTER_DOWN:
1234 cursortype = GDK_BOTTOM_SIDE;
1235 break;
1236 case GUI_POINTER_LEFT:
1237 cursortype = GDK_LEFT_SIDE;
1238 break;
1239 case GUI_POINTER_RIGHT:
1240 cursortype = GDK_RIGHT_SIDE;
1241 break;
1242 case GUI_POINTER_LD:
1243 cursortype = GDK_BOTTOM_LEFT_CORNER;
1244 break;
1245 case GUI_POINTER_RD:
1246 cursortype = GDK_BOTTOM_RIGHT_CORNER;
1247 break;
1248 case GUI_POINTER_LU:
1249 cursortype = GDK_TOP_LEFT_CORNER;
1250 break;
1251 case GUI_POINTER_RU:
1252 cursortype = GDK_TOP_RIGHT_CORNER;
1253 break;
1254 case GUI_POINTER_CROSS:
1255 cursortype = GDK_CROSS;
1256 break;
1257 case GUI_POINTER_MOVE:
1258 cursortype = GDK_FLEUR;
1259 break;
1260 case GUI_POINTER_WAIT:
1261 cursortype = GDK_WATCH;
1262 break;
1263 case GUI_POINTER_HELP:
1264 cursortype = GDK_QUESTION_ARROW;
1265 break;
1266 case GUI_POINTER_MENU:
1267 cursor = nsgtk_create_menu_cursor();
1268 nullcursor = true;
1269 break;
1271 /* In reality, this needs to be the funky left_ptr_watch
1272 * which we can't do easily yet.
1273 */
1274 cursortype = GDK_WATCH;
1275 break;
1276 /* The following we're not sure about */
1280 default:
1281 nullcursor = true;
1282 }
1283
1284 if (!nullcursor)
1285 cursor = gdk_cursor_new_for_display(
1286 gtk_widget_get_display(
1287 GTK_WIDGET(g->layout)),
1288 cursortype);
1289 gdk_window_set_cursor(nsgtk_widget_get_window(GTK_WIDGET(g->layout)),
1290 cursor);
1291
1292 if (!nullcursor)
1293 nsgdk_cursor_unref(cursor);
1294}
1295
1296
1297static void
1299 int x, int y, int height,
1300 const struct rect *clip)
1301{
1303
1304 y += 1;
1305 height -= 1;
1306
1307 if (y < clip->y0) {
1308 height -= clip->y0 - y;
1309 y = clip->y0;
1310 }
1311
1312 if (y + height > clip->y1) {
1313 height = clip->y1 - y + 1;
1314 }
1315
1316 g->caretx = x;
1317 g->carety = y;
1318 g->careth = height;
1319
1321
1322 gtk_widget_grab_focus(GTK_WIDGET(g->layout));
1323}
1324
1325
1326/**
1327 * Find the current dimensions of a GTK browser window content area.
1328 *
1329 * \param gw The gui window to measure content area of.
1330 * \param width receives width of window
1331 * \param height receives height of window
1332 * \return NSERROR_OK on sucess and width and height updated
1333 * else error code.
1334 */
1335static nserror
1337{
1338 GtkAllocation alloc;
1339
1340 /** @todo consider gtk_widget_get_allocated_width() */
1341 nsgtk_widget_get_allocation(GTK_WIDGET(gw->layout), &alloc);
1342
1343 *width = alloc.width;
1344 *height = alloc.height;
1345
1346 return NSERROR_OK;
1347}
1348
1349
1351{
1352 gtk_widget_grab_focus(GTK_WIDGET(g->layout));
1353}
1354
1355
1356static void
1358 struct form_control *control)
1359{
1360 intptr_t item;
1361 struct form_option *option;
1362
1363 GtkWidget *menu_item;
1364
1365 /* control->data.select.multiple is true if multiple selections
1366 * are allowable. We ignore this, as the core handles it for us.
1367 * Yay. \o/
1368 */
1369
1370 if (select_menu != NULL) {
1371 gtk_widget_destroy(select_menu);
1372 }
1373
1374 select_menu = gtk_menu_new();
1375 select_menu_control = control;
1376
1377 item = 0;
1378 option = form_select_get_option(control, item);
1379 while (option != NULL) {
1380 NSLOG(netsurf, INFO, "Item %"PRIdPTR" option %p text %s",
1381 item, option, option->text);
1382 menu_item = gtk_check_menu_item_new_with_label(option->text);
1383 if (option->selected) {
1384 gtk_check_menu_item_set_active(
1385 GTK_CHECK_MENU_ITEM(menu_item), TRUE);
1386 }
1387
1388 /*
1389 * This casts the item index integer into an integer
1390 * the size of a pointer. This allows the callback
1391 * parameter to be passed avoiding allocating memory
1392 * for a context with a single integer in it.
1393 */
1394 g_signal_connect(menu_item, "toggled",
1395 G_CALLBACK(nsgtk_select_menu_clicked), (gpointer)item);
1396
1397 gtk_menu_shell_append(GTK_MENU_SHELL(select_menu), menu_item);
1398
1399 item++;
1400 option = form_select_get_option(control, item);
1401 }
1402
1403 gtk_widget_show_all(select_menu);
1404
1406}
1407
1408
1409/**
1410 * GTK window UI callback when core needs a file selection gadget
1411 *
1412 * \param g The gui window on which the gadget has been requested
1413 */
1414static void
1416 struct hlcache_handle *hl,
1417 struct form_control *gadget)
1418{
1419 GtkWidget *dialog;
1420
1421 dialog = gtk_file_chooser_dialog_new("Select File",
1423 GTK_FILE_CHOOSER_ACTION_OPEN,
1424 NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1425 NSGTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1426 NULL);
1427
1428 NSLOG(netsurf, INFO, "*** open dialog: %p", dialog);
1429
1430 int ret = gtk_dialog_run(GTK_DIALOG(dialog));
1431 NSLOG(netsurf, INFO, "*** return value: %d", ret);
1432 if (ret == GTK_RESPONSE_ACCEPT) {
1433 char *filename;
1434
1435 filename = gtk_file_chooser_get_filename(
1436 GTK_FILE_CHOOSER(dialog));
1437
1438 browser_window_set_gadget_filename(g->bw, gadget, filename);
1439
1440 g_free(filename);
1441 }
1442
1443 gtk_widget_destroy(dialog);
1444}
1445
1446
1447/**
1448 * handle throbber changing state
1449 */
1450static nserror throbber(struct gui_window *gw, bool active)
1451{
1452 nsgtk_toolbar_throbber(gw->toolbar, active);
1453 nsgtk_scaffolding_throbber(gw, active);
1454 if (active) {
1456 } else {
1458 gw->throb_frame = 0;
1459 /* set tab back to favicon */
1461 }
1462 return NSERROR_OK;
1463}
1464
1465
1466/**
1467 * handle page info changing
1468 */
1470{
1472 return NSERROR_OK;
1473}
1474
1475/**
1476 * GTK window UI callback to process miscellaneous events
1477 *
1478 * \param gw The window receiving the event.
1479 * \param event The event code.
1480 * \return NSERROR_OK when processed ok
1481 */
1482static nserror
1484{
1485 switch (event) {
1488 break;
1489
1492 break;
1493
1496 break;
1497
1499 throbber(gw, true);
1500 break;
1501
1503 throbber(gw, false);
1504 break;
1505
1507 page_info_change(gw);
1508 break;
1509
1510 default:
1511 break;
1512 }
1513 return NSERROR_OK;
1514}
1515
1516
1517/**
1518 * GTK window UI callback when core changes the current url
1519 *
1520 * \param gw The gui window on which the url has been set.
1521 * \param url The new url.
1522 */
1524{
1525 return nsgtk_toolbar_set_url(gw->toolbar, url);
1526}
1527
1528
1529/**
1530 * GTK window UI callback when core changes the current title
1531 *
1532 * \param gw The gui window on which the url has been set.
1533 * \param url The new url.
1534 */
1535static void gui_window_set_title(struct gui_window *gw, const char *title)
1536{
1537
1538 if ((title != NULL) && (title[0] != '\0')) {
1539 nsgtk_tab_set_title(gw->container, title);
1540 }
1541 nsgtk_scaffolding_set_title(gw, title);
1542}
1543
1544
1545/**
1546 * GTK UI callback when search provider details are updated.
1547 *
1548 * \param name The providers name.
1549 * \param bitmap The bitmap representing the provider.
1550 * \return NSERROR_OK on success else error code.
1551 */
1552static nserror
1554{
1555 struct gui_window *gw;
1556 GdkPixbuf *pixbuf = NULL;
1557
1558 if (bitmap != NULL) {
1559 pixbuf = nsgdk_pixbuf_get_from_surface(bitmap->surface, 32, 32);
1560 }
1561
1562 for (gw = window_list; gw != NULL; gw = gw->next) {
1564 }
1565
1566 if (pixbuf != NULL) {
1567 g_object_unref(pixbuf);
1568 }
1569
1570 return NSERROR_OK;
1571}
1572
1573
1574/**
1575 * GTK frontend web search operation table
1576 */
1579};
1580
1582
1583
1584/**
1585 * GTK frontend browser window operation table
1586 */
1589 .destroy = gui_window_destroy,
1590 .invalidate = nsgtk_window_invalidate_area,
1591 .get_scroll = gui_window_get_scroll,
1592 .set_scroll = gui_window_set_scroll,
1593 .get_dimensions = gui_window_get_dimensions,
1594 .event = gui_window_event,
1595
1596 .set_icon = gui_window_set_icon,
1597 .set_title = gui_window_set_title,
1598 .set_status = gui_window_set_status,
1599 .set_pointer = gui_window_set_pointer,
1600 .place_caret = gui_window_place_caret,
1601 .create_form_select_menu = gui_window_create_form_select_menu,
1602 .file_gadget_open = gui_window_file_gadget_open,
1603 .set_url = gui_window_set_url,
1604
1605
1606};
1607
1609
1610
1611/* exported interface documented in window.h */
1613{
1614 return g->scaffold;
1615}
1616
1617
1618/* exported interface documented in window.h */
1620{
1621 return g->bw;
1622}
1623
1624
1625/* exported interface documented in window.h */
1627{
1628 return g->layout;
1629}
1630
1631
1632/* exported interface documented in window.h */
1633nserror
1635{
1637}
1638
1639
1640/* exported interface documented in window.h */
1641nserror
1643{
1644 return nsgtk_toolbar_item_activate(gw->toolbar, itemid);
1645}
1646
1647
1648/* exported interface documented in window.h */
1650{
1651 /* remove tab */
1652 gtk_widget_destroy(gw->container);
1653}
1654
1655
1656/* exported interface documented in window.h */
1658{
1659 struct gui_window *gw;
1660 for (gw = window_list; gw != NULL; gw = gw->next) {
1665 }
1666 return NSERROR_OK;
1667}
1668
1669
1670/* exported interface documented in window.h */
1672{
1673 struct gui_window *gw;
1674 for (gw = window_list; gw != NULL; gw = gw->next) {
1675 if (gw->scaffold == gs) {
1676 nsgtk_toolbar_show(gw->toolbar, show);
1677 }
1678 }
1679 return NSERROR_OK;
1680}
1681
1682
1683/* exported interface documented in window.h */
1685{
1686 struct gui_window *gw;
1687 for (gw = window_list; gw != NULL; gw = gw->next) {
1689
1690 }
1691 return NSERROR_OK;
1692}
1693
1694/* exported interface documented in window.h */
1696 struct nsgtk_pi_window *win)
1697{
1699}
1700
1701/* exported interface documented in window.h */
1703{
1705}
Browser window creation and manipulation interface.
nserror browser_window_schedule_reformat(struct browser_window *bw)
Reformat the browser window contents in a safe context.
bool browser_window_redraw(struct browser_window *bw, int x, int y, const struct rect *clip, const struct redraw_context *ctx)
Redraw an area of a window.
bool browser_window_has_content(struct browser_window *bw)
Find out if a browser window is currently showing a content.
void browser_window_mouse_click(struct browser_window *bw, browser_mouse_state mouse, int x, int y)
Handle mouse clicks in a browser window.
bool browser_window_scroll_at_point(struct browser_window *bw, int x, int y, int scrx, int scry)
Send a scroll request to a browser window at a particular point.
void browser_window_destroy(struct browser_window *bw)
Close and destroy a browser window.
nserror browser_window_get_extents(struct browser_window *bw, bool scaled, int *width, int *height)
Get a browser window's content extents.
void browser_window_mouse_track(struct browser_window *bw, browser_mouse_state mouse, int x, int y)
Handle non-click mouse action in a browser window.
void browser_window_set_gadget_filename(struct browser_window *bw, struct form_control *gadget, const char *fn)
set filename on form control.
void nsgtk_widget_get_allocation(GtkWidget *widget, GtkAllocation *allocation)
Definition: compat.c:489
void nsgtk_widget_override_background_color(GtkWidget *widget, GtkStateFlags state, uint16_t a, uint16_t r, uint16_t g, uint16_t b)
Definition: compat.c:240
GdkWindow * nsgtk_widget_get_window(GtkWidget *widget)
Definition: compat.c:404
gulong nsgtk_connect_draw_event(GtkWidget *widget, GCallback callback, gpointer g)
Definition: compat.c:373
void nsgdk_cursor_unref(GdkCursor *cursor)
Definition: compat.c:384
gdouble nsgtk_adjustment_get_page_increment(GtkAdjustment *adjustment)
Definition: compat.c:480
void nsgtk_widget_set_can_focus(GtkWidget *widget, gboolean can_focus)
Definition: compat.c:48
gdouble nsgtk_adjustment_get_upper(GtkAdjustment *adjustment)
Definition: compat.c:462
gdouble nsgtk_adjustment_get_lower(GtkAdjustment *adjustment)
Definition: compat.c:471
GtkAdjustment * nsgtk_layout_get_vadjustment(GtkLayout *layout)
Definition: compat.c:269
GtkAdjustment * nsgtk_layout_get_hadjustment(GtkLayout *layout)
Definition: compat.c:278
GdkWindow * nsgtk_layout_get_bin_window(GtkLayout *layout)
Definition: compat.c:444
gdouble nsgtk_adjustment_get_step_increment(GtkAdjustment *adjustment)
Definition: compat.c:453
void nsgtk_menu_popup_at_pointer(GtkMenu *menu, const GdkEvent *trigger_event)
Displays menu and makes it available for selection.
Definition: compat.c:561
Compatibility functions for older GTK versions (interface)
#define GDK_KEY(symbol)
Definition: compat.h:152
#define NSGTK_STOCK_OPEN
Definition: compat.h:65
#define GTK_STATE_FLAG_NORMAL
Definition: compat.h:160
#define NSGTK_STOCK_CANCEL
Definition: compat.h:55
wimp_w dialog
Definition: dialog.c:87
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_BAD_SIZE
Bad size.
Definition: errors.h:60
@ NSERROR_OK
No error.
Definition: errors.h:30
Form handling public interface.
struct form_option * form_select_get_option(struct form_control *control, int item)
get a form select menus option.
Definition: form.c:1844
nserror form_select_process_selection(struct form_control *control, int item)
Process a selection from a form select menu.
Definition: form.c:1834
struct atari_hotlist hl
Definition: hotlist.c:47
nserror nsgtk_local_history_hide(void)
hide the local history window from being visible.
Interface to GTK local history manager.
Target independent plotting GTK+ interface.
nserror nsgtk_search_create(GtkBuilder *builder, struct browser_window *bw, struct gtk_search **search_out)
create text search context
Definition: search.c:284
nserror nsgtk_search_restyle(struct gtk_search *search)
update search toolbar size and style
Definition: search.c:245
nserror nsgtk_search_toggle_visibility(struct gtk_search *search)
toggle search bar visibility
Definition: search.c:225
free text page search for gtk interface
GdkPixbuf * nsgdk_pixbuf_get_from_surface(cairo_surface_t *surface, int scwidth, int scheight)
obtain a pixbuf of the specified size from a cairo surface.
Definition: gdk.c:61
GDK support functions for missing interfaces.
nserror nsgtk_warning(const char *warning, const char *detail)
Warn the user of an event.
Definition: gui.c:95
GdkPixbuf * favicon_pixbuf
favicon default pixbuf
Definition: gui.c:83
uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
input conversion.
Definition: gui.c:121
const struct plotter_table nsgtk_plotters
GTK plotter table.
Definition: plotters.c:647
void nsgtk_plot_caret(int x, int y, int h)
Plot a caret.
Definition: plotters.c:278
cairo_t * current_cr
Definition: plotters.c:42
nserror nsgtk_schedule(int t, void(*callback)(void *p), void *cbctx)
Definition: schedule.c:103
nserror nsgtk_throbber_get_frame(int frame, GdkPixbuf **pixbuf)
get the pixbuf of a given frame of the throbber
Definition: throbber.c:103
nserror nsgtk_toolbar_item_activate(struct nsgtk_toolbar *tb, nsgtk_toolbar_button itemid)
activate the handler for a toolbar item
Definition: toolbar.c:3740
nserror nsgtk_toolbar_restyle(struct nsgtk_toolbar *tb)
Update toolbar style and size based on current settings.
Definition: toolbar.c:3505
nserror nsgtk_toolbar_set_websearch_image(struct nsgtk_toolbar *tb, GdkPixbuf *pixbuf)
set the websearch image
Definition: toolbar.c:3713
nserror nsgtk_toolbar_set_url(struct nsgtk_toolbar *tb, nsurl *url)
Update the toolbar url entry.
Definition: toolbar.c:3662
nserror nsgtk_toolbar_position_page_info(struct nsgtk_toolbar *tb, struct nsgtk_pi_window *win)
position the page info window appropriately
Definition: toolbar.c:3857
nserror nsgtk_toolbar_position_local_history(struct nsgtk_toolbar *tb)
position the local history window appropriately
Definition: toolbar.c:3874
nserror nsgtk_toolbar_create(GtkBuilder *builder, struct browser_window *(*get_bw)(void *ctx), void *get_ctx, bool want_location_focus, struct nsgtk_toolbar **tb_out)
create a control toolbar
Definition: toolbar.c:3447
nserror nsgtk_toolbar_page_info_change(struct nsgtk_toolbar *tb)
Page info has changed state.
Definition: toolbar.c:3607
nserror nsgtk_toolbar_show(struct nsgtk_toolbar *tb, bool show)
set the toolbar to be shown or hidden
Definition: toolbar.c:3771
nserror nsgtk_toolbar_update(struct nsgtk_toolbar *tb)
Update the toolbar items being shown based on current settings.
Definition: toolbar.c:3783
nserror nsgtk_toolbar_throbber(struct nsgtk_toolbar *tb, bool active)
Start or stop a throbber in a toolbar.
Definition: toolbar.c:3550
nserror nsgtk_window_search_toggle(struct gui_window *gw)
toggle search visibility
Definition: window.c:1634
nserror nsgtk_window_position_local_history(struct gui_window *gw)
position local_history appropriately
Definition: window.c:1702
static gboolean nsgtk_paned_size_allocate_event(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
Set status bar / scroll bar proportion according to user option when pane is resized.
Definition: window.c:717
struct gui_window_table * nsgtk_window_table
Definition: window.c:1608
static void gui_window_start_selection(struct gui_window *g)
Definition: window.c:1350
static void gui_window_set_status(struct gui_window *g, const char *text)
Definition: window.c:1146
static nserror gui_window_event(struct gui_window *gw, enum gui_window_event event)
GTK window UI callback to process miscellaneous events.
Definition: window.c:1483
static void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
Definition: window.c:1212
static void gui_window_remove_caret(struct gui_window *g)
Definition: window.c:1095
static nserror gui_window_get_dimensions(struct gui_window *gw, int *width, int *height)
Find the current dimensions of a GTK browser window content area.
Definition: window.c:1336
static void gui_window_update_extent(struct gui_window *g)
Definition: window.c:1200
static gboolean nsgtk_window_keypress_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
Definition: window.c:520
static void nsgtk_paned_notify__position(GObject *gobject, GParamSpec *pspec, gpointer data)
when the pane position is changed update the user option
Definition: window.c:692
static void gui_window_set_icon(struct gui_window *gw, struct hlcache_handle *icon)
favicon setting for gtk gui window.
Definition: window.c:1034
struct gui_search_web_table * nsgtk_search_web_table
Definition: window.c:1581
static void nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem, gpointer user_data)
Definition: window.c:150
void nsgtk_window_destroy_browser(struct gui_window *gw)
destroy browsing context
Definition: window.c:1649
static nserror nsgtk_window_invalidate_area(struct gui_window *g, const struct rect *rect)
Invalidates an area of a GTK browser window.
Definition: window.c:1121
static struct gui_window * gui_window_create(struct browser_window *bw, struct gui_window *existing, gui_window_create_flags flags)
Create and open a gtk container (window or tab) for a browsing context.
Definition: window.c:817
struct nsgtk_scaffolding * nsgtk_get_scaffold(struct gui_window *g)
get containing nsgtk scaffolding handle from gui window handle
Definition: window.c:1612
static GtkWidget * select_menu
Definition: window.c:74
static nserror gui_window_set_url(struct gui_window *gw, nsurl *url)
GTK window UI callback when core changes the current url.
Definition: window.c:1523
nserror nsgtk_window_item_activate(struct gui_window *gw, nsgtk_toolbar_button itemid)
activate the handler for a item in a toolbar of a gui window
Definition: window.c:1642
static struct gui_window_table window_table
GTK frontend browser window operation table.
Definition: window.c:1587
static void nsgtk_window_input_method_commit(GtkIMContext *ctx, const gchar *str, gpointer data)
Definition: window.c:651
static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
Definition: window.c:669
static gboolean nsgtk_window_draw_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
Definition: window.c:212
nserror nsgtk_window_update_all(void)
Every window will have its tab, toolbar and drawing area updated.
Definition: window.c:1657
static gboolean nsgtk_window_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
GTK signal handler for button-press-event on layout.
Definition: window.c:325
static struct form_control * select_menu_control
Definition: window.c:75
nserror nsgtk_window_position_page_info(struct gui_window *gw, struct nsgtk_pi_window *win)
position page_info appropriately
Definition: window.c:1695
static nserror throbber(struct gui_window *gw, bool active)
handle throbber changing state
Definition: window.c:1450
nserror nsgtk_window_toolbar_show(struct nsgtk_scaffolding *gs, bool show)
Windows associated with a scaffold will have their toolbar show state set.
Definition: window.c:1671
static gboolean nsgtk_window_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
Definition: window.c:386
GtkLayout * nsgtk_window_get_layout(struct gui_window *g)
get gtk layout from gui handle
Definition: window.c:1626
static void gui_window_place_caret(struct gui_window *g, int x, int y, int height, const struct rect *clip)
Definition: window.c:1298
static gboolean nsgtk_window_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
Definition: window.c:252
static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
Definition: window.c:1065
static gboolean nsgtk_window_keyrelease_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
Definition: window.c:640
static nserror gui_search_web_provider_update(const char *name, struct bitmap *bitmap)
GTK UI callback when search provider details are updated.
Definition: window.c:1553
static nserror gui_window_set_scroll(struct gui_window *g, const struct rect *rect)
Set the scroll position of a gtk browser window.
Definition: window.c:1166
static void gui_window_set_title(struct gui_window *gw, const char *title)
GTK window UI callback when core changes the current title.
Definition: window.c:1535
static struct gui_search_web_table search_web_table
GTK frontend web search operation table.
Definition: window.c:1577
struct gui_window * window_list
Definition: window.c:147
static void nsgtk_redraw_caret(struct gui_window *g)
Definition: window.c:1080
#define CONNECT(obj, sig, callback, ptr)
struct browser_window * nsgtk_get_browser_window(struct gui_window *g)
get core browsing context from gui window handle
Definition: window.c:1619
static struct browser_window * bw_from_gw(void *data)
Definition: window.c:751
#define THROBBER_FRAME_TIME
time (in ms) between throbber animation frame updates
Definition: window.c:72
static nserror page_info_change(struct gui_window *gw)
handle page info changing
Definition: window.c:1469
static void gui_window_file_gadget_open(struct gui_window *g, struct hlcache_handle *hl, struct form_control *gadget)
GTK window UI callback when core needs a file selection gadget.
Definition: window.c:1415
static bool get_tool_bar_show(void)
Definition: window.c:758
static gboolean nsgtk_window_focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer data)
GTK signal handler for focus-out-event on layout.
Definition: window.c:311
static void window_destroy(GtkWidget *widget, gpointer data)
handler for gtk destroy signal on window container
Definition: window.c:733
static void gui_window_create_form_select_menu(struct gui_window *g, struct form_control *control)
Definition: window.c:1357
static void gui_window_destroy(struct gui_window *gw)
Definition: window.c:1002
nserror nsgtk_window_toolbar_update(void)
every window will have its toolbar updated to reflect user settings
Definition: window.c:1684
static gboolean nsgtk_window_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data)
Definition: window.c:432
static void next_throbber_frame(void *p)
Make the throbber advance to next frame.
Definition: window.c:781
Public content interface.
struct bitmap * content_get_bitmap(struct hlcache_handle *h)
Retrieve the bitmap contained in an image content.
Definition: content.c:1264
Core mouse and pointer states.
browser_mouse_state
Mouse state.
Definition: mouse.h:43
@ BROWSER_MOUSE_PRESS_1
button 1 pressed
Definition: mouse.h:50
@ BROWSER_MOUSE_CLICK_2
button 2 clicked.
Definition: mouse.h:57
@ BROWSER_MOUSE_PRESS_2
button 2 pressed
Definition: mouse.h:52
@ BROWSER_MOUSE_TRIPLE_CLICK
button triple clicked
Definition: mouse.h:62
@ BROWSER_MOUSE_CLICK_1
button 1 clicked.
Definition: mouse.h:55
@ BROWSER_MOUSE_MOD_2
2nd modifier key pressed (eg.
Definition: mouse.h:80
@ BROWSER_MOUSE_DOUBLE_CLICK
button double clicked
Definition: mouse.h:60
@ BROWSER_MOUSE_MOD_1
1st modifier key pressed (eg.
Definition: mouse.h:78
@ BROWSER_MOUSE_DRAG_1
start of button 1 drag
Definition: mouse.h:65
@ BROWSER_MOUSE_HOLDING_2
during button 2 drag
Definition: mouse.h:75
@ BROWSER_MOUSE_HOLDING_1
during button 1 drag
Definition: mouse.h:73
@ BROWSER_MOUSE_DRAG_ON
a drag operation was started and a mouse button is still pressed
Definition: mouse.h:70
@ BROWSER_MOUSE_DRAG_2
start of button 2 drag
Definition: mouse.h:67
gui_pointer_shape
Definition: mouse.h:89
@ GUI_POINTER_WAIT
Definition: mouse.h:104
@ GUI_POINTER_RIGHT
Definition: mouse.h:97
@ GUI_POINTER_MOVE
Definition: mouse.h:103
@ GUI_POINTER_CARET
Definition: mouse.h:92
@ GUI_POINTER_PROGRESS
Definition: mouse.h:108
@ GUI_POINTER_RD
Definition: mouse.h:101
@ GUI_POINTER_LD
Definition: mouse.h:99
@ GUI_POINTER_NO_DROP
Definition: mouse.h:106
@ GUI_POINTER_DOWN
Definition: mouse.h:95
@ GUI_POINTER_UP
Definition: mouse.h:94
@ GUI_POINTER_RU
Definition: mouse.h:98
@ GUI_POINTER_DEFAULT
Definition: mouse.h:90
@ GUI_POINTER_HELP
Definition: mouse.h:105
@ GUI_POINTER_MENU
Definition: mouse.h:93
@ GUI_POINTER_POINT
Definition: mouse.h:91
@ GUI_POINTER_LEFT
Definition: mouse.h:96
@ GUI_POINTER_NOT_ALLOWED
Definition: mouse.h:107
@ GUI_POINTER_LU
Definition: mouse.h:100
@ GUI_POINTER_CROSS
Definition: mouse.h:102
Target independent plotting interface.
Interface to platform-specific graphical user interface window operations.
gui_window_create_flags
Window creation control flags.
Definition: window.h:66
@ GW_CREATE_TAB
Create tab in same window as existing.
Definition: window.h:69
@ GW_CREATE_FOREGROUND
Request this window/tab is foregrounded.
Definition: window.h:70
@ GW_CREATE_FOCUS_LOCATION
Definition: window.h:71
gui_window_event
Window events.
Definition: window.h:80
@ GW_EVENT_PAGE_INFO_CHANGE
Page status has changed and so the padlock should be updated.
Definition: window.h:129
@ GW_EVENT_REMOVE_CARET
Remove the caret, if present.
Definition: window.h:98
@ GW_EVENT_STOP_THROBBER
stop the navigation throbber.
Definition: window.h:108
@ GW_EVENT_UPDATE_EXTENT
Update the extent of the inside of a browser window to that of the current content.
Definition: window.h:93
@ GW_EVENT_START_SELECTION
selection started
Definition: window.h:123
@ GW_EVENT_START_THROBBER
start the navigation throbber.
Definition: window.h:103
Netsurf additional integer type formatting macros.
Interface to key press operations.
bool browser_window_key_press(struct browser_window *bw, uint32_t key)
Handle key presses in a browser window.
Definition: textinput.c:107
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
NetSurf URL handling (interface).
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
GdkCursor * nsgtk_create_menu_cursor(void)
Creates a menu cursor from internal resources.
Definition: resources.c:148
nserror nsgtk_builder_new_from_resname(const char *resname, GtkBuilder **builder_out)
Create gtk builder object for the named ui resource.
Definition: resources.c:526
Interface to gtk builtin resource handling.
int width
Definition: gui.c:159
int height
Definition: gui.c:160
void nsgtk_scaffolding_set_title(struct gui_window *gw, const char *title)
set the title in the window
Definition: scaffolding.c:1239
struct nsgtk_scaffolding * nsgtk_new_scaffolding(struct gui_window *toplevel)
create a new scaffolding for a window.
Definition: scaffolding.c:1496
GtkNotebook * nsgtk_scaffolding_notebook(struct nsgtk_scaffolding *g)
Get the gtk notebook from a scaffold.
Definition: scaffolding.c:1316
nserror nsgtk_scaffolding_throbber(struct gui_window *gw, bool active)
Update scaffolding window when throbber state changes.
Definition: scaffolding.c:1271
GtkWindow * nsgtk_scaffolding_window(struct nsgtk_scaffolding *g)
Get the gtk window for a scaffolding.
Definition: scaffolding.c:1310
void nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g, gdouble x, gdouble y)
Open a context sensitive menu.
Definition: scaffolding.c:1429
struct nsgtk_scaffolding * nsgtk_current_scaffolding(void)
Obtain the most recently used scaffolding element.
Definition: scaffolding.c:1473
core web search facilities interface.
Interface to utility string handling.
RISC OS wimp toolkit bitmap.
Definition: bitmap.c:68
cairo_surface_t * surface
Definition: bitmap.h:27
Browser window data.
int x
Window dimensions.
Form control.
Definition: form_internal.h:73
Option in a select.
Definition: form.h:33
bool selected
Definition: form.h:35
char * text
NUL terminated.
Definition: form.h:38
Graphical user interface browser web search function table.
Definition: searchweb.h:34
nserror(* provider_update)(const char *provider_name, struct bitmap *ico_bitmap)
called when the search provider details are updated.
Definition: searchweb.h:42
Graphical user interface window function table.
Definition: window.h:137
struct gui_window *(* create)(struct browser_window *bw, struct gui_window *existing, gui_window_create_flags flags)
Create and open a gui window for a browsing context.
Definition: window.h:164
first entry in window list
Definition: gui.c:296
struct gui_window * prev
Previous in linked list.
Definition: gui.h:159
gdouble pressed_y
Definition: window.c:92
GtkIMContext * input_method
The input method to use with this window.
Definition: window.c:137
GtkLabel * status_bar
statusbar
Definition: window.c:125
GtkLayout * layout
display widget for this page or frame
Definition: window.c:116
int throb_frame
current frame of throbber
Definition: window.c:140
gdouble pressed_x
Definition: window.c:91
struct fbtk_widget_s * toolbar
Definition: gui.h:46
struct gui_window * next
list for cleanup
Definition: gui.h:159
int state
Definition: window.cpp:73
gui_pointer_shape current_pointer
caret shape for rendering
Definition: window.cpp:78
int last_y
Definition: window.cpp:79
GtkWidget * grid
The container for the layout etc.
Definition: window.c:119
struct gui_window * gui
Definition: window.c:89
gboolean waiting
Definition: window.c:93
nsbeos_scaffolding * scaffold
Definition: window.cpp:65
struct gtk_search * search
search toolbar context
Definition: window.c:110
browser_mouse_state state
Definition: window.c:94
int last_x
previous event location
Definition: window.cpp:79
int pressed_y
Definition: window.cpp:72
struct s_search_form_session * search
Definition: gui.h:158
int carety
Definition: window.cpp:77
int pressed_x
Definition: window.cpp:71
struct nsgtk_scaffolding * scaffold
The gtk scaffold object containing menu, buttons, url bar, [tabs], drawing area, etc that may contain...
Definition: window.c:82
GtkWidget * tab
handle to the the visible tab
Definition: window.c:122
struct fbtk_widget_s * hscroll
Definition: gui.h:43
struct fbtk_widget_s * vscroll
Definition: gui.h:44
struct bitmap * icon
Definition: gui.h:156
struct nsgtk_toolbar * toolbar
controls toolbar context
Definition: window.c:107
GtkPaned * paned
status pane
Definition: window.c:128
int caretx
caret dimension and location for rendering
Definition: window.cpp:77
GtkWidget * container
The top level container (tabBox)
Definition: window.c:113
struct gui_window::@32 mouse
GdkPixbuf * icon
The icon this window should have.
Definition: window.c:134
int careth
Definition: window.cpp:77
bool paned_sized
has the status pane had its first size operation yet?
Definition: window.c:131
struct browser_window * bw
The 'content' window that is rendered in the gui_window.
Definition: gui.c:314
High-level cache handle.
Definition: hlcache.c:66
GTK certificate viewing window context.
Definition: page_info.c:47
Core scaffolding structure.
Definition: scaffolding.c:64
control toolbar context
Definition: toolbar.c:170
Rectangle coordinates.
Definition: types.h:40
int x0
Definition: types.h:41
int y0
Top left.
Definition: types.h:41
int x1
Definition: types.h:42
int y1
Bottom right.
Definition: types.h:42
Redraw context.
Definition: plotters.h:51
bool interactive
Redraw to show interactive features.
Definition: plotters.h:59
nserror nsgtk_tab_set_title(GtkWidget *page, const char *title)
set the tab title
Definition: tabs.c:498
nserror nsgtk_tab_set_icon(GtkWidget *page, GdkPixbuf *pixbuf)
set the tab icon
Definition: tabs.c:470
void nsgtk_tab_options_changed(GtkNotebook *notebook)
Definition: tabs.c:372
void nsgtk_tab_add(struct gui_window *gw, GtkWidget *tab_contents, bool background, const char *title, GdkPixbuf *icon_pixbuf)
Add new gui window page to notebook.
Definition: tabs.c:452
void browser_window_remove_caret(struct browser_window *bw, bool only_hide)
Removes the caret and callback for key process.
Definition: textinput.c:88
Textual input handling interface.
nsgtk_toolbar_button
Definition: toolbar_items.h:22
@ BACK_BUTTON
Definition: toolbar_items.h:23
@ OPENLOCATION_BUTTON
Definition: toolbar_items.h:69
@ FORWARD_BUTTON
Definition: toolbar_items.h:25
Option reading and saving interface.
#define nsoption_charp(OPTION)
Get the value of a string option.
Definition: nsoption.h:297
#define nsoption_int(OPTION)
Get the value of an integer option.
Definition: nsoption.h:279
#define nsoption_set_int(OPTION, VALUE)
set an integer option in the default table
Definition: nsoption.h:314
#define nsoption_bool(OPTION)
Get the value of a boolean option.
Definition: nsoption.h:270
uint32_t utf8_to_ucs4(const char *s_in, size_t l)
Convert a UTF-8 multibyte sequence into a single UCS4 character.
Definition: utf8.c:41
size_t utf8_next(const char *s, size_t l, size_t o)
Find next legal UTF-8 char in string.
Definition: utf8.c:129
UTF-8 manipulation functions (interface).
Interface to a number of general purpose functionality.
static nserror text(const struct redraw_context *ctx, const struct plot_font_style *fstyle, int x, int y, const char *text, size_t length)
Text plotting.
Definition: plot.c:978
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357