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 case 8: /* Back button */
357 break;
358
359 case 9: /* Forward button */
361 break;
362
363 default:
364 return FALSE;
365 }
366
367 /* Modify for double & triple clicks */
368 if (event->type == GDK_3BUTTON_PRESS)
370 else if (event->type == GDK_2BUTTON_PRESS)
372
373 /* Handle the modifiers too */
374 if (event->state & GDK_SHIFT_MASK)
376 if (event->state & GDK_CONTROL_MASK)
378 if (event->state & GDK_MOD1_MASK)
380
381 /* Record where we pressed, for use when determining whether to start
382 * a drag in motion notify events. */
383 g->last_x = event->x;
384 g->last_y = event->y;
385
387 g->mouse.state,
388 g->mouse.pressed_x,
389 g->mouse.pressed_y);
390
391 return TRUE;
392}
393
394
395static gboolean
397 GdkEventButton *event,
398 gpointer data)
399{
400 struct gui_window *g = data;
401
402 /* If the mouse state is PRESS then we are waiting for a release to emit
403 * a click event, otherwise just reset the state to nothing */
406 } else if (g->mouse.state & BROWSER_MOUSE_PRESS_2) {
408 } else if (g->mouse.state & BROWSER_MOUSE_PRESS_3) {
410 } else if (g->mouse.state & BROWSER_MOUSE_PRESS_4) {
412 } else if (g->mouse.state & BROWSER_MOUSE_PRESS_5) {
414 }
415
416 /* Handle modifiers being removed */
418 !(event->state & GDK_SHIFT_MASK)) {
420 }
422 !(event->state & GDK_CONTROL_MASK)) {
424 }
426 !(event->state & GDK_MOD1_MASK)) {
428 }
429
435 browser_window_mouse_click(g->bw, g->mouse.state, event->x, event->y);
436 } else {
437 browser_window_mouse_track(g->bw, 0, event->x, event->y);
438 }
439
440 g->mouse.state = 0;
441 return TRUE;
442}
443
444
445static gboolean
447 GdkEventScroll *event,
448 gpointer data)
449{
450 struct gui_window *g = data;
451 double value;
452 double deltax = 0;
453 double deltay = 0;
454 GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(g->layout);
455 GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(g->layout);
456 GtkAllocation alloc;
457
458 switch (event->direction) {
459 case GDK_SCROLL_LEFT:
460 deltax = -1.0;
461 break;
462
463 case GDK_SCROLL_UP:
464 deltay = -1.0;
465 break;
466
467 case GDK_SCROLL_RIGHT:
468 deltax = 1.0;
469 break;
470
471 case GDK_SCROLL_DOWN:
472 deltay = 1.0;
473 break;
474
475#if GTK_CHECK_VERSION(3,4,0)
476 case GDK_SCROLL_SMOOTH:
477 gdk_event_get_scroll_deltas((GdkEvent *)event, &deltax, &deltay);
478 break;
479#endif
480 default:
481 NSLOG(netsurf, INFO, "Unhandled mouse scroll direction");
482 return TRUE;
483 }
484
487
489 event->x, event->y,
490 deltax, deltay) != true) {
491
492 /* core did not handle event so change adjustments */
493
494 /* Horizontal */
495 if (deltax != 0) {
496 value = gtk_adjustment_get_value(hscroll) + deltax;
497
498 /* @todo consider gtk_widget_get_allocated_width() */
499 nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);
500
501 if (value > nsgtk_adjustment_get_upper(hscroll) - alloc.width) {
502 value = nsgtk_adjustment_get_upper(hscroll) - alloc.width;
503 }
504 if (value < nsgtk_adjustment_get_lower(hscroll)) {
506 }
507
508 gtk_adjustment_set_value(hscroll, value);
509 }
510
511 /* Vertical */
512 if (deltay != 0) {
513 value = gtk_adjustment_get_value(vscroll) + deltay;
514
515 /* @todo consider gtk_widget_get_allocated_height */
516 nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);
517
518 if (value > (nsgtk_adjustment_get_upper(vscroll) - alloc.height)) {
519 value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;
520 }
521 if (value < nsgtk_adjustment_get_lower(vscroll)) {
523 }
524
525 gtk_adjustment_set_value(vscroll, value);
526 }
527 }
528
529 return TRUE;
530}
531
532
533static gboolean
535 GdkEventKey *event,
536 gpointer data)
537{
538 struct gui_window *g = data;
539 uint32_t nskey;
540
541 if (gtk_im_context_filter_keypress(g->input_method, event))
542 return TRUE;
543
544 nskey = gtk_gui_gdkkey_to_nskey(event);
545
546 if (browser_window_key_press(g->bw, nskey))
547 return TRUE;
548
549 if ((event->state & 0x7) != 0)
550 return TRUE;
551
552 double value;
553 GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(g->layout);
554 GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(g->layout);
555 GtkAllocation alloc;
556
557 /* @todo consider gtk_widget_get_allocated_width() */
558 nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);
559
560 switch (event->keyval) {
561
562 case GDK_KEY(Home):
563 case GDK_KEY(KP_Home):
565 gtk_adjustment_set_value(vscroll, value);
566 break;
567
568 case GDK_KEY(End):
569 case GDK_KEY(KP_End):
570 value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;
571
574
575 gtk_adjustment_set_value(vscroll, value);
576 break;
577
578 case GDK_KEY(Left):
579 case GDK_KEY(KP_Left):
580 value = gtk_adjustment_get_value(hscroll) -
582
585
586 gtk_adjustment_set_value(hscroll, value);
587 break;
588
589 case GDK_KEY(Up):
590 case GDK_KEY(KP_Up):
591 value = gtk_adjustment_get_value(vscroll) -
593
596
597 gtk_adjustment_set_value(vscroll, value);
598 break;
599
600 case GDK_KEY(Right):
601 case GDK_KEY(KP_Right):
602 value = gtk_adjustment_get_value(hscroll) +
604
605 if (value > nsgtk_adjustment_get_upper(hscroll) - alloc.width)
606 value = nsgtk_adjustment_get_upper(hscroll) - alloc.width;
607
608 gtk_adjustment_set_value(hscroll, value);
609 break;
610
611 case GDK_KEY(Down):
612 case GDK_KEY(KP_Down):
613 value = gtk_adjustment_get_value(vscroll) +
615
616 if (value > nsgtk_adjustment_get_upper(vscroll) - alloc.height)
617 value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;
618
619 gtk_adjustment_set_value(vscroll, value);
620 break;
621
622 case GDK_KEY(Page_Up):
623 case GDK_KEY(KP_Page_Up):
624 value = gtk_adjustment_get_value(vscroll) -
626
629
630 gtk_adjustment_set_value(vscroll, value);
631 break;
632
633 case GDK_KEY(Page_Down):
634 case GDK_KEY(KP_Page_Down):
635 value = gtk_adjustment_get_value(vscroll) +
637
638 if (value > nsgtk_adjustment_get_upper(vscroll) - alloc.height)
639 value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;
640
641 gtk_adjustment_set_value(vscroll, value);
642 break;
643
644 default:
645 break;
646
647 }
648
649 return TRUE;
650}
651
652
653static gboolean
655 GdkEventKey *event,
656 gpointer data)
657{
658 struct gui_window *g = data;
659
660 return gtk_im_context_filter_keypress(g->input_method, event);
661}
662
663
664static void
666 const gchar *str,
667 gpointer data)
668{
669 struct gui_window *g = data;
670 size_t len = strlen(str), offset = 0;
671
672 while (offset < len) {
673 uint32_t nskey = utf8_to_ucs4(str + offset, len - offset);
674
675 browser_window_key_press(g->bw, nskey);
676
677 offset = utf8_next(str, len, offset);
678 }
679}
680
681
682static gboolean
684 GtkAllocation *allocation,
685 gpointer data)
686{
687 struct gui_window *g = data;
688
690
691 return TRUE;
692}
693
694
695/**
696 * when the pane position is changed update the user option
697 *
698 * The slightly awkward implementation with the first allocation flag
699 * is necessary because the initial window creation does not cause an
700 * allocate-event signal so the position value in the pane is incorrect
701 * and we cannot know what it should be until after the allocation
702 * (which did not generate a signal) is done as the user position is a
703 * percentage of pane total width not an absolute value.
704 */
705static void
706nsgtk_paned_notify__position(GObject *gobject, GParamSpec *pspec, gpointer data)
707{
708 struct gui_window *g = data;
709 GtkAllocation pane_alloc;
710
711 gtk_widget_get_allocation(GTK_WIDGET(g->paned), &pane_alloc);
712
713 if (g->paned_sized == false)
714 {
715 g->paned_sized = true;
716 gtk_paned_set_position(g->paned,
717 (nsoption_int(toolbar_status_size) * pane_alloc.width) / 10000);
718 return;
719 }
720
721 nsoption_set_int(toolbar_status_size,
722 ((gtk_paned_get_position(g->paned) * 10000) / (pane_alloc.width - 1)));
723}
724
725
726/**
727 * Set status bar / scroll bar proportion according to user option
728 * when pane is resized.
729 */
730static gboolean
732 GtkAllocation *allocation,
733 gpointer data)
734{
735 gtk_paned_set_position(GTK_PANED(widget),
736 (nsoption_int(toolbar_status_size) * allocation->width) / 10000);
737
738 return TRUE;
739}
740
741
742/**
743 * handler for gtk destroy signal on window container
744 *
745 * destroy the browsing context as there is will be nothing to display it now
746 */
747static void window_destroy(GtkWidget *widget, gpointer data)
748{
749 struct gui_window *gw = data;
750
752
753 g_object_unref(gw->input_method);
754
755 /* free any existing icon */
756 if (gw->icon != NULL) {
757 g_object_unref(gw->icon);
758 gw->icon = NULL;
759 }
760
761 free(gw);
762}
763
764
765static struct browser_window *bw_from_gw(void *data)
766{
767 struct gui_window *gw = data;
768 return gw->bw;
769}
770
771
772static bool get_tool_bar_show(void)
773{
774 const char *cur_bar_show;
775
776 cur_bar_show = nsoption_charp(bar_show);
777 if (cur_bar_show != NULL) {
778 if (strcmp(cur_bar_show, "menu/tool") == 0) {
779 return true;
780 } else if (strcmp(cur_bar_show, "tool") == 0) {
781 return true;
782 }
783 }
784 return false;
785}
786
787
788/**
789 * Make the throbber advance to next frame.
790 *
791 * scheduled callback to update the throbber
792 *
793 * \param p The context passed when scheduled.
794 */
795static void next_throbber_frame(void *p)
796{
797 struct gui_window *gw = p;
798 nserror res;
799 GdkPixbuf *pixbuf;
800
801 gw->throb_frame++; /* advance to next frame */
802
803 res = nsgtk_throbber_get_frame(gw->throb_frame, &pixbuf);
804 if (res == NSERROR_BAD_SIZE) {
805 gw->throb_frame = 1;
806 res = nsgtk_throbber_get_frame(gw->throb_frame, &pixbuf);
807 }
808
809 if (res == NSERROR_OK) {
810 nsgtk_tab_set_icon(gw->container, pixbuf);
811 /* only schedule next frame if there are no errors */
813 }
814}
815
816
817/**
818 * Create and open a gtk container (window or tab) for a browsing context.
819 *
820 * \param bw The browsing context to create gui_window for.
821 * \param existing An existing gui_window, may be NULL
822 * \param flags flags to control the container creation
823 * \return gui window, or NULL on error
824 *
825 * If GW_CREATE_CLONE flag is set existing is non-NULL.
826 *
827 * Front end's gui_window must include a reference to the
828 * browser window passed in the bw param.
829 */
830static struct gui_window *
832 struct gui_window *existing,
834{
835 struct gui_window *g; /* what is being created to return */
836 bool open_in_background = !(flags & GW_CREATE_FOREGROUND);
837 GtkBuilder* tab_builder;
838 nserror res;
839
840 res = nsgtk_builder_new_from_resname("tabcontents", &tab_builder);
841 if (res != NSERROR_OK) {
842 NSLOG(netsurf, INFO, "Tab contents UI builder init failed");
843 return NULL;
844 }
845
846 gtk_builder_connect_signals(tab_builder, NULL);
847
848 g = calloc(1, sizeof(*g));
849 if (!g) {
850 nsgtk_warning("NoMemory", 0);
851 g_object_unref(tab_builder);
852 return NULL;
853 }
854
855 NSLOG(netsurf, INFO, "Creating gui window %p for browser window %p",
856 g, bw);
857
858 g->bw = bw;
859 g->mouse.state = 0;
861
862 /* attach scaffold */
863 if (flags & GW_CREATE_TAB) {
864 /* open in new tab, attach to existing scaffold */
865 if (existing != NULL) {
866 g->scaffold = existing->scaffold;
867 } else {
869 }
870 } else {
871 /* open in new window, create and attach to scaffold */
873 }
874 if (g->scaffold == NULL) {
875 nsgtk_warning("NoMemory", 0);
876 free(g);
877 g_object_unref(tab_builder);
878 return NULL;
879 }
880
881 /* Construct our primary elements */
882 g->container = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabBox"));
883 g->layout = GTK_LAYOUT(gtk_builder_get_object(tab_builder, "layout"));
884 g->grid = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabContents"));
885 g->status_bar = GTK_LABEL(gtk_builder_get_object(tab_builder, "status_bar"));
886 g->paned = GTK_PANED(gtk_builder_get_object(tab_builder, "hpaned1"));
887 g->input_method = gtk_im_multicontext_new();
888
889
890 /* create toolbar */
891 res = nsgtk_toolbar_create(tab_builder, bw_from_gw, g,
892 !!(flags & GW_CREATE_FOCUS_LOCATION),
893 &g->toolbar);
894 if (res != NSERROR_OK) {
895 free(g);
896 g_object_unref(tab_builder);
897 return NULL;
898 }
899
900 /* local page text search toolbar */
901 res = nsgtk_search_create(tab_builder, g->bw, &g->search);
902 if (res != NSERROR_OK) {
903 free(g);
904 g_object_unref(tab_builder);
905 return NULL;
906 }
907
908 /* set a default favicon */
909 g_object_ref(favicon_pixbuf);
910 g->icon = favicon_pixbuf;
911
912 /* add new gui window to global list (push_top) */
913 if (window_list) {
914 window_list->prev = g;
915 }
916 g->next = window_list;
917 g->prev = NULL;
918 window_list = g;
919
920 /* set the events we're interested in receiving from the browser's
921 * drawing area.
922 */
923 gtk_widget_add_events(GTK_WIDGET(g->layout),
924 GDK_EXPOSURE_MASK |
925 GDK_LEAVE_NOTIFY_MASK |
926 GDK_BUTTON_PRESS_MASK |
927 GDK_BUTTON_RELEASE_MASK |
928 GDK_POINTER_MOTION_MASK |
929 GDK_POINTER_MOTION_HINT_MASK |
930 GDK_KEY_PRESS_MASK |
931 GDK_KEY_RELEASE_MASK |
932 GDK_SCROLL_MASK);
933 nsgtk_widget_set_can_focus(GTK_WIDGET(g->layout), TRUE);
934
935 /* set the default background colour of the drawing area to white. */
938 0, 0xffff, 0xffff, 0xffff);
939
940 nsgtk_connect_draw_event(GTK_WIDGET(g->layout),
941 G_CALLBACK(nsgtk_window_draw_event), g);
942
943 /* helper macro to conect signals to callbacks */
944#define CONNECT(obj, sig, callback, ptr) \
945 g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
946
947 /* layout signals */
948 CONNECT(g->layout, "motion-notify-event",
950 CONNECT(g->layout, "button-press-event",
952 CONNECT(g->layout, "button-release-event",
954 CONNECT(g->layout, "key-press-event",
956 CONNECT(g->layout, "key-release-event",
958 CONNECT(g->layout, "size-allocate",
960 CONNECT(g->layout, "scroll-event",
962 CONNECT(g->layout, "focus-out-event",
964
965 /* status pane signals */
966 CONNECT(g->paned, "size-allocate",
968
969 CONNECT(g->paned, "notify::position",
971
972 /* gtk container destructor */
973 CONNECT(g->container, "destroy", window_destroy, g);
974
975 /* input method */
976 gtk_im_context_set_client_window(g->input_method,
978 gtk_im_context_set_use_preedit(g->input_method, FALSE);
979
980 /* input method signals */
981 CONNECT(g->input_method, "commit",
983
984 /* add the tab container to the scaffold notebook */
986 open_in_background,
987 messages_get("NewTab"), g->icon);
988
989 /* initialy should not be visible */
991
992 /* set toolbar visibility from user option */
994
995 /* safe to drop the reference to the tab_builder as the container is
996 * referenced by the notebook now.
997 */
998 g_object_unref(tab_builder);
999
1000 /* Finally we need to focus the location bar if requested */
1001 if (flags & GW_CREATE_FOCUS_LOCATION) {
1003 NSLOG(netsurf, WARNING, "Unable to focus location input");
1004 }
1005 }
1006
1007 return g;
1008}
1009
1010
1011static void gui_window_destroy(struct gui_window *gw)
1012{
1013 NSLOG(netsurf, INFO, "gui_window: %p", gw);
1014 assert(gw != NULL);
1015 assert(gw->bw != NULL);
1016 NSLOG(netsurf, INFO, "scaffolding: %p", gw->scaffold);
1017
1018 /* kill off any throbber that might be running */
1020
1021 /* remove from window list */
1022 if (gw->prev) {
1023 gw->prev->next = gw->next;
1024 } else {
1025 window_list = gw->next;
1026 }
1027
1028 if (gw->next) {
1029 gw->next->prev = gw->prev;
1030 }
1031
1032 NSLOG(netsurf, INFO, "window list head: %p", window_list);
1033}
1034
1035
1036/**
1037 * favicon setting for gtk gui window.
1038 *
1039 * \param gw gtk gui window to set favicon on.
1040 * \param icon A handle to the new favicon content.
1041 */
1042static void
1044{
1045 struct bitmap *icon_bitmap = NULL;
1046
1047 /* free any existing icon */
1048 if (gw->icon != NULL) {
1049 g_object_unref(gw->icon);
1050 gw->icon = NULL;
1051 }
1052
1053 if (icon != NULL) {
1054 icon_bitmap = content_get_bitmap(icon);
1055 if (icon_bitmap != NULL) {
1056 NSLOG(netsurf, INFO, "Using %p bitmap", icon_bitmap);
1057 gw->icon = nsgdk_pixbuf_get_from_surface(icon_bitmap->surface, 16, 16);
1058 }
1059 }
1060
1061 if (gw->icon == NULL) {
1062 NSLOG(netsurf, INFO, "Using default favicon");
1063 g_object_ref(favicon_pixbuf);
1064 gw->icon = favicon_pixbuf;
1065 }
1066
1067 /* only set icon if throbber not running */
1068 if (gw->throb_frame == 0) {
1070 }
1071}
1072
1073
1074static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
1075{
1076 GtkAdjustment *vadj = nsgtk_layout_get_vadjustment(g->layout);
1077 GtkAdjustment *hadj = nsgtk_layout_get_hadjustment(g->layout);
1078
1079 assert(vadj);
1080 assert(hadj);
1081
1082 *sy = (int)(gtk_adjustment_get_value(vadj));
1083 *sx = (int)(gtk_adjustment_get_value(hadj));
1084
1085 return true;
1086}
1087
1088
1089static void nsgtk_redraw_caret(struct gui_window *g)
1090{
1091 int sx, sy;
1092
1093 if (g->careth == 0)
1094 return;
1095
1096 gui_window_get_scroll(g, &sx, &sy);
1097
1098 gtk_widget_queue_draw_area(GTK_WIDGET(g->layout),
1099 g->caretx - sx, g->carety - sy, 1, g->careth + 1);
1100
1101}
1102
1103
1105{
1106 int sx, sy;
1107 int oh = g->careth;
1108
1109 if (oh == 0)
1110 return;
1111
1112 g->careth = 0;
1113
1114 gui_window_get_scroll(g, &sx, &sy);
1115
1116 gtk_widget_queue_draw_area(GTK_WIDGET(g->layout),
1117 g->caretx - sx, g->carety - sy, 1, oh + 1);
1118
1119}
1120
1121
1122/**
1123 * Invalidates an area of a GTK browser window
1124 *
1125 * \param g gui_window
1126 * \param rect area to redraw or NULL for the entire window area
1127 * \return NSERROR_OK on success or appropriate error code
1128 */
1129static nserror
1131{
1132 int sx, sy;
1133
1134 if (rect == NULL) {
1135 gtk_widget_queue_draw(GTK_WIDGET(g->layout));
1136 return NSERROR_OK;
1137 }
1138
1139 if (!browser_window_has_content(g->bw)) {
1140 return NSERROR_OK;
1141 }
1142
1143 gui_window_get_scroll(g, &sx, &sy);
1144
1145 gtk_widget_queue_draw_area(GTK_WIDGET(g->layout),
1146 rect->x0 - sx,
1147 rect->y0 - sy,
1148 rect->x1 - rect->x0,
1149 rect->y1 - rect->y0);
1150
1151 return NSERROR_OK;
1152}
1153
1154
1155static void gui_window_set_status(struct gui_window *g, const char *text)
1156{
1157 assert(g);
1158 assert(g->status_bar);
1159 gtk_label_set_text(g->status_bar, text);
1160}
1161
1162
1163/**
1164 * Set the scroll position of a gtk browser window.
1165 *
1166 * Scrolls the viewport to ensure the specified rectangle of the
1167 * content is shown. The GTK implementation scrolls the contents so
1168 * the specified point in the content is at the top of the viewport.
1169 *
1170 * \param g gui window to scroll
1171 * \param rect The rectangle to ensure is shown.
1172 * \return NSERROR_OK on success or apropriate error code.
1173 */
1174static nserror
1176{
1177 GtkAdjustment *vadj = nsgtk_layout_get_vadjustment(g->layout);
1178 GtkAdjustment *hadj = nsgtk_layout_get_hadjustment(g->layout);
1179 gdouble vlower, vpage, vupper, hlower, hpage, hupper;
1180 gdouble x = (gdouble)rect->x0;
1181 gdouble y = (gdouble)rect->y0;
1182
1183 assert(vadj);
1184 assert(hadj);
1185
1186 g_object_get(vadj, "page-size", &vpage, "lower", &vlower, "upper", &vupper, NULL);
1187 g_object_get(hadj, "page-size", &hpage, "lower", &hlower, "upper", &hupper, NULL);
1188
1189 if (x < hlower) {
1190 x = hlower;
1191 }
1192 if (x > (hupper - hpage)) {
1193 x = hupper - hpage;
1194 }
1195 if (y < vlower) {
1196 y = vlower;
1197 }
1198 if (y > (vupper - vpage)) {
1199 y = vupper - vpage;
1200 }
1201
1202 gtk_adjustment_set_value(vadj, y);
1203 gtk_adjustment_set_value(hadj, x);
1204
1205 return NSERROR_OK;
1206}
1207
1208
1210{
1211 int w, h;
1212
1213 if (browser_window_get_extents(g->bw, true, &w, &h) == NSERROR_OK) {
1214 gtk_layout_set_size(g->layout, w, h);
1215 gtk_widget_queue_resize(g->grid);
1216 }
1217}
1218
1219
1220static void
1222{
1223 GdkCursor *cursor = NULL;
1224 GdkCursorType cursortype;
1225 bool nullcursor = false;
1226
1227 if (g->current_pointer == shape)
1228 return;
1229
1230 g->current_pointer = shape;
1231
1232 switch (shape) {
1233 case GUI_POINTER_POINT:
1234 cursortype = GDK_HAND2;
1235 break;
1236 case GUI_POINTER_CARET:
1237 cursortype = GDK_XTERM;
1238 break;
1239 case GUI_POINTER_UP:
1240 cursortype = GDK_TOP_SIDE;
1241 break;
1242 case GUI_POINTER_DOWN:
1243 cursortype = GDK_BOTTOM_SIDE;
1244 break;
1245 case GUI_POINTER_LEFT:
1246 cursortype = GDK_LEFT_SIDE;
1247 break;
1248 case GUI_POINTER_RIGHT:
1249 cursortype = GDK_RIGHT_SIDE;
1250 break;
1251 case GUI_POINTER_LD:
1252 cursortype = GDK_BOTTOM_LEFT_CORNER;
1253 break;
1254 case GUI_POINTER_RD:
1255 cursortype = GDK_BOTTOM_RIGHT_CORNER;
1256 break;
1257 case GUI_POINTER_LU:
1258 cursortype = GDK_TOP_LEFT_CORNER;
1259 break;
1260 case GUI_POINTER_RU:
1261 cursortype = GDK_TOP_RIGHT_CORNER;
1262 break;
1263 case GUI_POINTER_CROSS:
1264 cursortype = GDK_CROSS;
1265 break;
1266 case GUI_POINTER_MOVE:
1267 cursortype = GDK_FLEUR;
1268 break;
1269 case GUI_POINTER_WAIT:
1270 cursortype = GDK_WATCH;
1271 break;
1272 case GUI_POINTER_HELP:
1273 cursortype = GDK_QUESTION_ARROW;
1274 break;
1275 case GUI_POINTER_MENU:
1276 cursor = nsgtk_create_menu_cursor();
1277 nullcursor = true;
1278 break;
1280 /* In reality, this needs to be the funky left_ptr_watch
1281 * which we can't do easily yet.
1282 */
1283 cursortype = GDK_WATCH;
1284 break;
1285 /* The following we're not sure about */
1289 default:
1290 nullcursor = true;
1291 }
1292
1293 if (!nullcursor)
1294 cursor = gdk_cursor_new_for_display(
1295 gtk_widget_get_display(
1296 GTK_WIDGET(g->layout)),
1297 cursortype);
1298 gdk_window_set_cursor(nsgtk_widget_get_window(GTK_WIDGET(g->layout)),
1299 cursor);
1300
1301 if (!nullcursor)
1302 nsgdk_cursor_unref(cursor);
1303}
1304
1305
1306static void
1308 int x, int y, int height,
1309 const struct rect *clip)
1310{
1312
1313 y += 1;
1314 height -= 1;
1315
1316 if (y < clip->y0) {
1317 height -= clip->y0 - y;
1318 y = clip->y0;
1319 }
1320
1321 if (y + height > clip->y1) {
1322 height = clip->y1 - y + 1;
1323 }
1324
1325 g->caretx = x;
1326 g->carety = y;
1327 g->careth = height;
1328
1330
1331 gtk_widget_grab_focus(GTK_WIDGET(g->layout));
1332}
1333
1334
1335/**
1336 * Find the current dimensions of a GTK browser window content area.
1337 *
1338 * \param gw The gui window to measure content area of.
1339 * \param width receives width of window
1340 * \param height receives height of window
1341 * \return NSERROR_OK on sucess and width and height updated
1342 * else error code.
1343 */
1344static nserror
1346{
1347 GtkAllocation alloc;
1348
1349 /** @todo consider gtk_widget_get_allocated_width() */
1350 nsgtk_widget_get_allocation(GTK_WIDGET(gw->layout), &alloc);
1351
1352 *width = alloc.width;
1353 *height = alloc.height;
1354
1355 return NSERROR_OK;
1356}
1357
1358
1360{
1361 gtk_widget_grab_focus(GTK_WIDGET(g->layout));
1362}
1363
1364
1365static void
1367 struct form_control *control)
1368{
1369 intptr_t item;
1370 struct form_option *option;
1371
1372 GtkWidget *menu_item;
1373
1374 /* control->data.select.multiple is true if multiple selections
1375 * are allowable. We ignore this, as the core handles it for us.
1376 * Yay. \o/
1377 */
1378
1379 if (select_menu != NULL) {
1380 gtk_widget_destroy(select_menu);
1381 }
1382
1383 select_menu = gtk_menu_new();
1384 select_menu_control = control;
1385
1386 item = 0;
1387 option = form_select_get_option(control, item);
1388 while (option != NULL) {
1389 NSLOG(netsurf, INFO, "Item %"PRIdPTR" option %p text %s",
1390 item, option, option->text);
1391 menu_item = gtk_check_menu_item_new_with_label(option->text);
1392 if (option->selected) {
1393 gtk_check_menu_item_set_active(
1394 GTK_CHECK_MENU_ITEM(menu_item), TRUE);
1395 }
1396
1397 /*
1398 * This casts the item index integer into an integer
1399 * the size of a pointer. This allows the callback
1400 * parameter to be passed avoiding allocating memory
1401 * for a context with a single integer in it.
1402 */
1403 g_signal_connect(menu_item, "toggled",
1404 G_CALLBACK(nsgtk_select_menu_clicked), (gpointer)item);
1405
1406 gtk_menu_shell_append(GTK_MENU_SHELL(select_menu), menu_item);
1407
1408 item++;
1409 option = form_select_get_option(control, item);
1410 }
1411
1412 gtk_widget_show_all(select_menu);
1413
1415}
1416
1417
1418/**
1419 * GTK window UI callback when core needs a file selection gadget
1420 *
1421 * \param g The gui window on which the gadget has been requested
1422 */
1423static void
1425 struct hlcache_handle *hl,
1426 struct form_control *gadget)
1427{
1428 GtkWidget *dialog;
1429
1430 dialog = gtk_file_chooser_dialog_new("Select File",
1432 GTK_FILE_CHOOSER_ACTION_OPEN,
1433 NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1434 NSGTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1435 NULL);
1436
1437 NSLOG(netsurf, INFO, "*** open dialog: %p", dialog);
1438
1439 int ret = gtk_dialog_run(GTK_DIALOG(dialog));
1440 NSLOG(netsurf, INFO, "*** return value: %d", ret);
1441 if (ret == GTK_RESPONSE_ACCEPT) {
1442 char *filename;
1443
1444 filename = gtk_file_chooser_get_filename(
1445 GTK_FILE_CHOOSER(dialog));
1446
1447 browser_window_set_gadget_filename(g->bw, gadget, filename);
1448
1449 g_free(filename);
1450 }
1451
1452 gtk_widget_destroy(dialog);
1453}
1454
1455
1456/**
1457 * handle throbber changing state
1458 */
1459static nserror throbber(struct gui_window *gw, bool active)
1460{
1461 nsgtk_toolbar_throbber(gw->toolbar, active);
1462 nsgtk_scaffolding_throbber(gw, active);
1463 if (active) {
1465 } else {
1467 gw->throb_frame = 0;
1468 /* set tab back to favicon */
1470 }
1471 return NSERROR_OK;
1472}
1473
1474
1475/**
1476 * handle page info changing
1477 */
1479{
1481 return NSERROR_OK;
1482}
1483
1484/**
1485 * GTK window UI callback to process miscellaneous events
1486 *
1487 * \param gw The window receiving the event.
1488 * \param event The event code.
1489 * \return NSERROR_OK when processed ok
1490 */
1491static nserror
1493{
1494 switch (event) {
1497 break;
1498
1501 break;
1502
1505 break;
1506
1508 throbber(gw, true);
1509 break;
1510
1512 throbber(gw, false);
1513 break;
1514
1516 page_info_change(gw);
1517 break;
1518
1519 default:
1520 break;
1521 }
1522 return NSERROR_OK;
1523}
1524
1525
1526/**
1527 * GTK window UI callback when core changes the current url
1528 *
1529 * \param gw The gui window on which the url has been set.
1530 * \param url The new url.
1531 */
1533{
1534 return nsgtk_toolbar_set_url(gw->toolbar, url);
1535}
1536
1537
1538/**
1539 * GTK window UI callback when core changes the current title
1540 *
1541 * \param gw The gui window on which the url has been set.
1542 * \param url The new url.
1543 */
1544static void gui_window_set_title(struct gui_window *gw, const char *title)
1545{
1546
1547 if ((title != NULL) && (title[0] != '\0')) {
1548 nsgtk_tab_set_title(gw->container, title);
1549 }
1550 nsgtk_scaffolding_set_title(gw, title);
1551}
1552
1553
1554/**
1555 * GTK UI callback when search provider details are updated.
1556 *
1557 * \param name The providers name.
1558 * \param bitmap The bitmap representing the provider.
1559 * \return NSERROR_OK on success else error code.
1560 */
1561static nserror
1563{
1564 struct gui_window *gw;
1565 GdkPixbuf *pixbuf = NULL;
1566
1567 if (bitmap != NULL) {
1568 pixbuf = nsgdk_pixbuf_get_from_surface(bitmap->surface, 32, 32);
1569 }
1570
1571 for (gw = window_list; gw != NULL; gw = gw->next) {
1573 }
1574
1575 if (pixbuf != NULL) {
1576 g_object_unref(pixbuf);
1577 }
1578
1579 return NSERROR_OK;
1580}
1581
1582
1583/**
1584 * GTK frontend web search operation table
1585 */
1588};
1589
1591
1592
1593/**
1594 * GTK frontend browser window operation table
1595 */
1598 .destroy = gui_window_destroy,
1599 .invalidate = nsgtk_window_invalidate_area,
1600 .get_scroll = gui_window_get_scroll,
1601 .set_scroll = gui_window_set_scroll,
1602 .get_dimensions = gui_window_get_dimensions,
1603 .event = gui_window_event,
1604
1605 .set_icon = gui_window_set_icon,
1606 .set_title = gui_window_set_title,
1607 .set_status = gui_window_set_status,
1608 .set_pointer = gui_window_set_pointer,
1609 .place_caret = gui_window_place_caret,
1610 .create_form_select_menu = gui_window_create_form_select_menu,
1611 .file_gadget_open = gui_window_file_gadget_open,
1612 .set_url = gui_window_set_url,
1613
1614
1615};
1616
1618
1619
1620/* exported interface documented in window.h */
1622{
1623 return g->scaffold;
1624}
1625
1626
1627/* exported interface documented in window.h */
1629{
1630 return g->bw;
1631}
1632
1633
1634/* exported interface documented in window.h */
1636{
1637 return g->layout;
1638}
1639
1640
1641/* exported interface documented in window.h */
1642nserror
1644{
1646}
1647
1648
1649/* exported interface documented in window.h */
1650nserror
1652{
1653 return nsgtk_toolbar_item_activate(gw->toolbar, itemid);
1654}
1655
1656
1657/* exported interface documented in window.h */
1659{
1660 /* remove tab */
1661 gtk_widget_destroy(gw->container);
1662}
1663
1664
1665/* exported interface documented in window.h */
1667{
1668 struct gui_window *gw;
1669 for (gw = window_list; gw != NULL; gw = gw->next) {
1674 }
1675 return NSERROR_OK;
1676}
1677
1678
1679/* exported interface documented in window.h */
1681{
1682 struct gui_window *gw;
1683 for (gw = window_list; gw != NULL; gw = gw->next) {
1684 if (gw->scaffold == gs) {
1685 nsgtk_toolbar_show(gw->toolbar, show);
1686 }
1687 }
1688 return NSERROR_OK;
1689}
1690
1691
1692/* exported interface documented in window.h */
1694{
1695 struct gui_window *gw;
1696 for (gw = window_list; gw != NULL; gw = gw->next) {
1698
1699 }
1700 return NSERROR_OK;
1701}
1702
1703/* exported interface documented in window.h */
1705 struct nsgtk_pi_window *win)
1706{
1708}
1709
1710/* exported interface documented in window.h */
1712{
1714}
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:96
GdkPixbuf * favicon_pixbuf
favicon default pixbuf
Definition: gui.c:84
uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
input conversion.
Definition: gui.c:122
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:1643
nserror nsgtk_window_position_local_history(struct gui_window *gw)
position local_history appropriately
Definition: window.c:1711
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:731
struct gui_window_table * nsgtk_window_table
Definition: window.c:1617
static void gui_window_start_selection(struct gui_window *g)
Definition: window.c:1359
static void gui_window_set_status(struct gui_window *g, const char *text)
Definition: window.c:1155
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:1492
static void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
Definition: window.c:1221
static void gui_window_remove_caret(struct gui_window *g)
Definition: window.c:1104
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:1345
static void gui_window_update_extent(struct gui_window *g)
Definition: window.c:1209
static gboolean nsgtk_window_keypress_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
Definition: window.c:534
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:706
static void gui_window_set_icon(struct gui_window *gw, struct hlcache_handle *icon)
favicon setting for gtk gui window.
Definition: window.c:1043
struct gui_search_web_table * nsgtk_search_web_table
Definition: window.c:1590
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:1658
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:1130
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:831
struct nsgtk_scaffolding * nsgtk_get_scaffold(struct gui_window *g)
get containing nsgtk scaffolding handle from gui window handle
Definition: window.c:1621
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:1532
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:1651
static struct gui_window_table window_table
GTK frontend browser window operation table.
Definition: window.c:1596
static void nsgtk_window_input_method_commit(GtkIMContext *ctx, const gchar *str, gpointer data)
Definition: window.c:665
static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
Definition: window.c:683
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:1666
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:1704
static nserror throbber(struct gui_window *gw, bool active)
handle throbber changing state
Definition: window.c:1459
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:1680
static gboolean nsgtk_window_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
Definition: window.c:396
GtkLayout * nsgtk_window_get_layout(struct gui_window *g)
get gtk layout from gui handle
Definition: window.c:1635
static void gui_window_place_caret(struct gui_window *g, int x, int y, int height, const struct rect *clip)
Definition: window.c:1307
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:1074
static gboolean nsgtk_window_keyrelease_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
Definition: window.c:654
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:1562
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:1175
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:1544
static struct gui_search_web_table search_web_table
GTK frontend web search operation table.
Definition: window.c:1586
struct gui_window * window_list
Definition: window.c:147
static void nsgtk_redraw_caret(struct gui_window *g)
Definition: window.c:1089
#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:1628
static struct browser_window * bw_from_gw(void *data)
Definition: window.c:765
#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:1478
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:1424
static bool get_tool_bar_show(void)
Definition: window.c:772
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:747
static void gui_window_create_form_select_menu(struct gui_window *g, struct form_control *control)
Definition: window.c:1366
static void gui_window_destroy(struct gui_window *gw)
Definition: window.c:1011
nserror nsgtk_window_toolbar_update(void)
every window will have its toolbar updated to reflect user settings
Definition: window.c:1693
static gboolean nsgtk_window_scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data)
Definition: window.c:446
static void next_throbber_frame(void *p)
Make the throbber advance to next frame.
Definition: window.c:795
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: 1 is primary mouse button.
Definition: mouse.h:52
@ BROWSER_MOUSE_CLICK_4
button 4 clicked.
Definition: mouse.h:76
@ BROWSER_MOUSE_PRESS_1
primary button pressed
Definition: mouse.h:59
@ BROWSER_MOUSE_CLICK_2
button 2 clicked.
Definition: mouse.h:72
@ BROWSER_MOUSE_PRESS_3
secondary button pressed
Definition: mouse.h:63
@ BROWSER_MOUSE_PRESS_4
fourth button pressed
Definition: mouse.h:65
@ BROWSER_MOUSE_PRESS_2
auxillary button pressed
Definition: mouse.h:61
@ BROWSER_MOUSE_PRESS_5
fifth button pressed
Definition: mouse.h:67
@ BROWSER_MOUSE_CLICK_3
button 3 clicked.
Definition: mouse.h:74
@ BROWSER_MOUSE_TRIPLE_CLICK
button triple clicked
Definition: mouse.h:83
@ BROWSER_MOUSE_CLICK_1
button 1 clicked.
Definition: mouse.h:70
@ BROWSER_MOUSE_MOD_2
2nd modifier key pressed (eg.
Definition: mouse.h:101
@ BROWSER_MOUSE_DOUBLE_CLICK
button double clicked
Definition: mouse.h:81
@ BROWSER_MOUSE_MOD_3
3rd modifier key pressed (eg.
Definition: mouse.h:103
@ BROWSER_MOUSE_MOD_1
1st modifier key pressed (eg.
Definition: mouse.h:99
@ BROWSER_MOUSE_DRAG_1
start of button 1 drag
Definition: mouse.h:86
@ BROWSER_MOUSE_HOLDING_2
during button 2 drag
Definition: mouse.h:96
@ BROWSER_MOUSE_HOLDING_1
during button 1 drag
Definition: mouse.h:94
@ BROWSER_MOUSE_DRAG_ON
a drag operation was started and a mouse button is still pressed
Definition: mouse.h:91
@ BROWSER_MOUSE_CLICK_5
button 5 clicked.
Definition: mouse.h:78
@ BROWSER_MOUSE_DRAG_2
start of button 2 drag
Definition: mouse.h:88
gui_pointer_shape
Definition: mouse.h:112
@ GUI_POINTER_WAIT
Definition: mouse.h:127
@ GUI_POINTER_RIGHT
Definition: mouse.h:120
@ GUI_POINTER_MOVE
Definition: mouse.h:126
@ GUI_POINTER_CARET
Definition: mouse.h:115
@ GUI_POINTER_PROGRESS
Definition: mouse.h:131
@ GUI_POINTER_RD
Definition: mouse.h:124
@ GUI_POINTER_LD
Definition: mouse.h:122
@ GUI_POINTER_NO_DROP
Definition: mouse.h:129
@ GUI_POINTER_DOWN
Definition: mouse.h:118
@ GUI_POINTER_UP
Definition: mouse.h:117
@ GUI_POINTER_RU
Definition: mouse.h:121
@ GUI_POINTER_DEFAULT
Definition: mouse.h:113
@ GUI_POINTER_HELP
Definition: mouse.h:128
@ GUI_POINTER_MENU
Definition: mouse.h:116
@ GUI_POINTER_POINT
Definition: mouse.h:114
@ GUI_POINTER_LEFT
Definition: mouse.h:119
@ GUI_POINTER_NOT_ALLOWED
Definition: mouse.h:130
@ GUI_POINTER_LU
Definition: mouse.h:123
@ GUI_POINTER_CROSS
Definition: mouse.h:125
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:160
int height
Definition: gui.c:161
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:298
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:316
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
@ OPENLOCATION_BUTTON
Definition: toolbar_items.h:69
Option reading and saving interface.
#define nsoption_charp(OPTION)
Get the value of a string option.
Definition: nsoption.h:331
#define nsoption_int(OPTION)
Get the value of an integer option.
Definition: nsoption.h:313
#define nsoption_set_int(OPTION, VALUE)
set an integer option in the default table
Definition: nsoption.h:348
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