NetSurf
corewindow.c
Go to the documentation of this file.
1/*
2 * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * GTK generic core window interface.
22 *
23 * Provides interface for core renderers to the gtk toolkit drawable area.
24 * \todo should the interface really be called coredrawable?
25 *
26 * This module is an object that must be encapsulated. Client users
27 * should embed a struct nsgtk_corewindow at the beginning of their
28 * context for this display surface, fill in relevant data and then
29 * call nsgtk_corewindow_init()
30 *
31 * The nsgtk core window structure requires the drawing area and
32 * scrollable widgets are present and the callback for draw, key and
33 * mouse operations.
34 */
35
36#include <assert.h>
37#include <string.h>
38#include <math.h>
39#include <gtk/gtk.h>
40
41#include "utils/log.h"
42#include "utils/messages.h"
43#include "utils/utf8.h"
44#include "netsurf/types.h"
45#include "netsurf/keypress.h"
46#include "netsurf/mouse.h"
47
48#include "gtk/compat.h"
49#include "gtk/gui.h" /* just for gtk_gui_gdkkey_to_nskey */
50#include "gtk/plotters.h"
51#include "gtk/corewindow.h"
52
53/**
54 * Convert GDK mouse event to netsurf mouse state
55 *
56 * \param event The GDK mouse event to convert.
57 * \return The netsurf mouse state.
58 */
60{
62
63 if (event->type == GDK_2BUTTON_PRESS) {
65 } else {
67 }
68
69 /* button state */
70 switch (event->button) {
71 case 1:
73 break;
74
75 case 2:
77 break;
78 }
79
80 /* Handle the modifiers too */
81 if (event->state & GDK_SHIFT_MASK) {
83 }
84
85 if (event->state & GDK_CONTROL_MASK) {
87 }
88
89 if (event->state & GDK_MOD1_MASK) {
90 /* usually alt */
92 }
93
94 return ms;
95}
96
97
98/**
99 * gtk event on mouse button press.
100 *
101 * Service gtk event for a mouse button transition to pressed from
102 * released state.
103 *
104 * \param widget The gtk widget the event occurred for.
105 * \param event The event that occurred.
106 * \param g The context pointer passed when the event was registered.
107 */
108static gboolean
110 GdkEventButton *event,
111 gpointer g)
112{
113 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
114 struct nsgtk_corewindow_mouse *mouse = &nsgtk_cw->mouse_state;
115
116 gtk_im_context_reset(nsgtk_cw->input_method);
117 gtk_widget_grab_focus(GTK_WIDGET(nsgtk_cw->drawing_area));
118
119 /* record event information for potentially starting a drag. */
120 mouse->pressed_x = mouse->last_x = event->x;
121 mouse->pressed_y = mouse->last_y = event->y;
122 mouse->pressed = true;
123
124 mouse->state = nsgtk_cw_gdkbutton_to_nsstate(event);
125
126 nsgtk_cw->mouse(nsgtk_cw, mouse->state, event->x, event->y);
127
128 return TRUE;
129}
130
131
132/**
133 * gtk event on mouse button release.
134 *
135 * Service gtk event for a mouse button transition from pressed to
136 * released state.
137 *
138 * \param widget The gtk widget the event occurred for.
139 * \param event The event that occurred.
140 * \param g The context pointer passed when the event was registered.
141 */
142static gboolean
144 GdkEventButton *event,
145 gpointer g)
146{
147 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
148 struct nsgtk_corewindow_mouse *mouse = &nsgtk_cw->mouse_state;
149 bool was_drag = false;
150
151 /* only button 1 clicks are considered double clicks. If the
152 * mouse state is PRESS then we are waiting for a release to
153 * emit a click event, otherwise just reset the state to nothing.
154 */
155 if (mouse->state & BROWSER_MOUSE_DOUBLE_CLICK) {
156 if (mouse->state & BROWSER_MOUSE_PRESS_1) {
157 mouse->state ^= BROWSER_MOUSE_PRESS_1 |
159 } else if (mouse->state & BROWSER_MOUSE_PRESS_2) {
160 mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
163 }
164 } else if (mouse->state & BROWSER_MOUSE_PRESS_1) {
165 mouse->state ^= (BROWSER_MOUSE_PRESS_1 |
167 } else if (mouse->state & BROWSER_MOUSE_PRESS_2) {
168 mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
170 } else if (mouse->state & BROWSER_MOUSE_HOLDING_1) {
171 mouse->state ^= (BROWSER_MOUSE_HOLDING_1 |
173 was_drag = true;
174 } else if (mouse->state & BROWSER_MOUSE_HOLDING_2) {
175 mouse->state ^= (BROWSER_MOUSE_HOLDING_2 |
177 was_drag = true;
178 }
179
180 /* Handle modifiers being removed */
181 if ((mouse->state & BROWSER_MOUSE_MOD_1) &&
182 !(event->state & GDK_SHIFT_MASK)) {
183 mouse->state ^= BROWSER_MOUSE_MOD_1;
184 }
185 if ((mouse->state & BROWSER_MOUSE_MOD_2) &&
186 !(event->state & GDK_CONTROL_MASK)) {
187 mouse->state ^= BROWSER_MOUSE_MOD_2;
188 }
189 if ((mouse->state & BROWSER_MOUSE_MOD_3) &&
190 !(event->state & GDK_MOD1_MASK)) {
191 mouse->state ^= BROWSER_MOUSE_MOD_3;
192 }
193
194 /* end drag with modifiers */
195 if (was_drag && (mouse->state & (
199 mouse->state = BROWSER_MOUSE_HOVER;
200 }
201
202 nsgtk_cw->mouse(nsgtk_cw, mouse->state, event->x, event->y);
203
204 mouse->pressed = false;
205
206 return TRUE;
207}
208
209
210/**
211 * gtk event on mouse movement.
212 *
213 * Service gtk motion-notify-event for mouse movement above a widget.
214 *
215 * \param widget The gtk widget the event occurred for.
216 * \param event The motion event that occurred.
217 * \param g The context pointer passed when the event was registered.
218 */
219static gboolean
221 GdkEventMotion *event,
222 gpointer g)
223{
224 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
225 struct nsgtk_corewindow_mouse *mouse = &nsgtk_cw->mouse_state;
226
227 if (mouse->pressed == false) {
228 nsgtk_cw->mouse(nsgtk_cw,
230 event->x,
231 event->y);
232 return TRUE;
233 }
234
235 if ((fabs(event->x - mouse->last_x) < 5.0) &&
236 (fabs(event->y - mouse->last_y) < 5.0)) {
237 /* Mouse hasn't moved far enough from press coordinate
238 * for this to be considered a drag.
239 */
240 return FALSE;
241 }
242
243 /* This is a drag, ensure it's always treated as such, even if
244 * we drag back over the press location.
245 */
246 mouse->last_x = INT_MIN;
247 mouse->last_y = INT_MIN;
248
249
250 if (mouse->state & BROWSER_MOUSE_PRESS_1) {
251 /* Start button 1 drag */
252 nsgtk_cw->mouse(nsgtk_cw,
254 mouse->pressed_x,
255 mouse->pressed_y);
256
257 /* Replace PRESS with HOLDING and declare drag in progress */
258 mouse->state ^= (BROWSER_MOUSE_PRESS_1 |
261
262 } else if (mouse->state & BROWSER_MOUSE_PRESS_2) {
263 /* Start button 2s drag */
264 nsgtk_cw->mouse(nsgtk_cw,
266 mouse->pressed_x,
267 mouse->pressed_y);
268
269 /* Replace PRESS with HOLDING and declare drag in progress */
270 mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
273
274 } else {
275 /* continue drag */
276
277 /* Handle modifiers being removed */
278 if ((mouse->state & BROWSER_MOUSE_MOD_1) &&
279 !(event->state & GDK_SHIFT_MASK)) {
280 mouse->state ^= BROWSER_MOUSE_MOD_1;
281 }
282 if ((mouse->state & BROWSER_MOUSE_MOD_2) &&
283 !(event->state & GDK_CONTROL_MASK)) {
284 mouse->state ^= BROWSER_MOUSE_MOD_2;
285 }
286 if ((mouse->state & BROWSER_MOUSE_MOD_3) &&
287 !(event->state & GDK_MOD1_MASK)) {
288 mouse->state ^= BROWSER_MOUSE_MOD_3;
289 }
290
291 if (mouse->state &
293 nsgtk_cw->mouse(nsgtk_cw,
294 mouse->state,
295 event->x, event->y);
296 }
297 }
298
299 return TRUE;
300}
301
302
303/**
304 * Deal with keypress events not handled buy input method or callback
305 *
306 * \param nsgtk_cw nsgtk core window key event happened in.
307 * \param nskey The netsurf keycode of the event.
308 * \return NSERROR_OK on success otherwise an error code.
309 */
310static nserror nsgtk_cw_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
311{
312 double value = 0;
313 GtkAdjustment *vscroll;
314 GtkAdjustment *hscroll;
315 GtkAdjustment *scroll = NULL;
316 gdouble hpage, vpage;
317
318 vscroll = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
319 hscroll = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
320 g_object_get(vscroll, "page-size", &vpage, NULL);
321 g_object_get(hscroll, "page-size", &hpage, NULL);
322
323 switch(nskey) {
325 scroll = vscroll;
326 value = nsgtk_adjustment_get_lower(scroll);
327 break;
328
329 case NS_KEY_TEXT_END:
330 scroll = vscroll;
331 value = nsgtk_adjustment_get_upper(scroll) - vpage;
332 if (value < nsgtk_adjustment_get_lower(scroll))
333 value = nsgtk_adjustment_get_lower(scroll);
334 break;
335
336 case NS_KEY_LEFT:
337 scroll = hscroll;
338 value = gtk_adjustment_get_value(scroll) -
340 if (value < nsgtk_adjustment_get_lower(scroll))
341 value = nsgtk_adjustment_get_lower(scroll);
342 break;
343
344 case NS_KEY_RIGHT:
345 scroll = hscroll;
346 value = gtk_adjustment_get_value(scroll) +
348 if (value > nsgtk_adjustment_get_upper(scroll) - hpage)
349 value = nsgtk_adjustment_get_upper(scroll) - hpage;
350 break;
351 case NS_KEY_UP:
352 scroll = vscroll;
353 value = gtk_adjustment_get_value(scroll) -
355 if (value < nsgtk_adjustment_get_lower(scroll))
356 value = nsgtk_adjustment_get_lower(scroll);
357 break;
358
359 case NS_KEY_DOWN:
360 scroll = vscroll;
361 value = gtk_adjustment_get_value(scroll) +
363 if (value > nsgtk_adjustment_get_upper(scroll) - vpage)
364 value = nsgtk_adjustment_get_upper(scroll) - vpage;
365 break;
366
367 case NS_KEY_PAGE_UP:
368 scroll = vscroll;
369 value = gtk_adjustment_get_value(scroll) -
371
372 if (value < nsgtk_adjustment_get_lower(scroll))
373 value = nsgtk_adjustment_get_lower(scroll);
374
375 break;
376
377 case NS_KEY_PAGE_DOWN:
378 scroll = vscroll;
379 value = gtk_adjustment_get_value(scroll) +
381
382 if (value > nsgtk_adjustment_get_upper(scroll) - vpage)
383 value = nsgtk_adjustment_get_upper(scroll) - vpage;
384 break;
385
386 }
387
388 if (scroll != NULL) {
389 gtk_adjustment_set_value(scroll, value);
390 }
391
392 return NSERROR_OK;
393}
394
395/**
396 * gtk event on key press.
397 *
398 * Service gtk key-press-event for key transition on a widget from
399 * released to pressed.
400 *
401 * \param widget The gtk widget the event occurred for.
402 * \param event The event that occurred.
403 * \param g The context pointer passed when the event was registered.
404 */
405static gboolean
406nsgtk_cw_keypress_event(GtkWidget *widget, GdkEventKey *event, gpointer g)
407{
408 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
409 nserror res;
410 uint32_t nskey;
411
412 /* check to see if gtk input method swallowed the keypress */
413 if (gtk_im_context_filter_keypress(nsgtk_cw->input_method, event)) {
414 return TRUE;
415 }
416
417 /* convert gtk event to nskey */
418 nskey = gtk_gui_gdkkey_to_nskey(event);
419
420 /* attempt to handle keypress in caller */
421 res = nsgtk_cw->key(nsgtk_cw, nskey);
422 if (res == NSERROR_OK) {
423 return TRUE;
424 } else if (res != NSERROR_NOT_IMPLEMENTED) {
425 NSLOG(netsurf, INFO, "%s", messages_get_errorcode(res));
426 return FALSE;
427 }
428
429 /* deal with unprocessed keypress */
430 res = nsgtk_cw_key(nsgtk_cw, nskey);
431 if (res != NSERROR_OK) {
432 NSLOG(netsurf, INFO, "%s", messages_get_errorcode(res));
433 return FALSE;
434 }
435 return TRUE;
436}
437
438
439/**
440 * gtk event on key release.
441 *
442 * Service gtk key-release-event for key transition on a widget from
443 * pressed to released.
444 *
445 * \param widget The gtk widget the event occurred for.
446 * \param event The event that occurred.
447 * \param g The context pointer passed when the event was registered.
448 */
449static gboolean
450nsgtk_cw_keyrelease_event(GtkWidget *widget, GdkEventKey *event, gpointer g)
451{
452 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
453
454 return gtk_im_context_filter_keypress(nsgtk_cw->input_method, event);
455}
456
457
458/**
459 * gtk event handler for input method commit.
460 *
461 * Service gtk commit for input method commit action.
462 *
463 * \param ctx The gtk input method context the event occurred for.
464 * \param str The resulting string from the input method.
465 * \param g The context pointer passed when the event was registered.
466 */
467static void
468nsgtk_cw_input_method_commit(GtkIMContext *ctx, const gchar *str, gpointer g)
469{
470 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
471 size_t len;
472 size_t offset = 0;
473 uint32_t nskey;
474
475 len = strlen(str);
476
477 while (offset < len) {
478 nskey = utf8_to_ucs4(str + offset, len - offset);
479
480 nsgtk_cw->key(nsgtk_cw, nskey);
481
482 offset = utf8_next(str, len, offset);
483 }
484}
485
486
487#if GTK_CHECK_VERSION(3,0,0)
488
489
490/**
491 * handler for gtk draw event on a nsgtk core window for GTK 3
492 *
493 * \param widget The GTK widget to redraw.
494 * \param cr The cairo drawing context of the widget
495 * \param data The context pointer passed when the event was registered.
496 * \return FALSE indicating no error.
497 */
498static gboolean
499nsgtk_cw_draw_event(GtkWidget *widget, cairo_t *cr, gpointer data)
500{
501 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)data;
502 double x1;
503 double y1;
504 double x2;
505 double y2;
506 struct rect clip;
507
508 current_cr = cr;
509
510 cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
511
512 clip.x0 = x1;
513 clip.y0 = y1;
514 clip.x1 = x2;
515 clip.y1 = y2;
516
517 nsgtk_cw->draw(nsgtk_cw, &clip);
518
519 return FALSE;
520}
521
522#else
523
524
525/**
526 * handler for gtk draw event on a nsgtk core window for GTK 2
527 *
528 * \param widget The GTK widget to redraw.
529 * \param event The GDK expose event
530 * \param g The context pointer passed when the event was registered.
531 * \return FALSE indicating no error.
532 */
533static gboolean
534nsgtk_cw_draw_event(GtkWidget *widget,
535 GdkEventExpose *event,
536 gpointer g)
537{
538 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)g;
539 struct rect clip;
540
541 clip.x0 = event->area.x;
542 clip.y0 = event->area.y;
543 clip.x1 = event->area.x + event->area.width;
544 clip.y1 = event->area.y + event->area.height;
545
546 current_cr = gdk_cairo_create(nsgtk_widget_get_window(widget));
547
548 nsgtk_cw->draw(nsgtk_cw, &clip);
549
550 cairo_destroy(current_cr);
551
552 return FALSE;
553}
554
555#endif
556
557
558/**
559 * callback from core to request an invalidation of a GTK core window area.
560 *
561 * The specified area of the window should now be considered
562 * out of date. If the area is NULL the entire window must be
563 * invalidated.
564 *
565 * \param[in] cw The core window to invalidate.
566 * \param[in] rect area to redraw or NULL for the entire window area.
567 * \return NSERROR_OK on success or appropriate error code.
568 */
569static nserror
570nsgtk_cw_invalidate_area(struct core_window *cw, const struct rect *rect)
571{
572 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
573
574 if (rect == NULL) {
575 gtk_widget_queue_draw(GTK_WIDGET(nsgtk_cw->drawing_area));
576 return NSERROR_OK;
577 }
578
579 gtk_widget_queue_draw_area(GTK_WIDGET(nsgtk_cw->drawing_area),
580 rect->x0,
581 rect->y0,
582 rect->x1 - rect->x0,
583 rect->y1 - rect->y0);
584
585 return NSERROR_OK;
586}
587
588
589/**
590 * update window size core window callback
591 *
592 * \param cw core window handle.
593 * \param width New widget width.
594 * \param height New widget height.
595 */
596static nserror
597nsgtk_cw_update_size(struct core_window *cw, int width, int height)
598{
599 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
600
601 gtk_widget_set_size_request(GTK_WIDGET(nsgtk_cw->drawing_area),
602 width, height);
603
604 return NSERROR_OK;
605}
606
607
608/**
609 * scroll window core window callback
610 *
611 * \param cw core window handle.
612 * \param r rectangle that needs scrolling.
613 */
614static nserror
615nsgtk_cw_set_scroll(struct core_window *cw, int x, int y)
616{
617 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
618
619 if (nsgtk_cw->scrolled != NULL) {
620 GtkAdjustment *vadj;
621 GtkAdjustment *hadj;
622
623 vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
624 hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
625
626 assert(vadj != NULL);
627 assert(hadj != NULL);
628
629 gtk_adjustment_set_value(vadj, y);
630 gtk_adjustment_set_value(hadj, x);
631 }
632 return NSERROR_OK;
633}
634
635
636/**
637 * scroll window core window callback
638 *
639 * \param cw core window handle.
640 * \param r rectangle that needs scrolling.
641 */
642static nserror
643nsgtk_cw_get_scroll(const struct core_window *cw, int *x, int *y)
644{
645 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
646
647 if (nsgtk_cw->scrolled != NULL) {
648 GtkAdjustment *vadj;
649 GtkAdjustment *hadj;
650
651 vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
652 hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
653
654 assert(vadj != NULL);
655 assert(hadj != NULL);
656
657 *y = (int)(gtk_adjustment_get_value(vadj));
658 *x = (int)(gtk_adjustment_get_value(hadj));
659 } else {
660 *x = 0;
661 *y = 0;
662 }
663 return NSERROR_OK;
664}
665
666
667/**
668 * Callback from the core to obtain the window viewport dimensions
669 *
670 * \param[in] cw the core window object
671 * \param[out] width to be set to viewport width in px
672 * \param[out] height to be set to viewport height in px
673 */
674static nserror
675nsgtk_cw_get_window_dimensions(const struct core_window *cw,
676 int *width, int *height)
677{
678 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
679 if (nsgtk_cw->scrolled != NULL) {
680 GtkAdjustment *vadj;
681 GtkAdjustment *hadj;
682 gdouble page;
683
684 hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
685 g_object_get(hadj, "page-size", &page, NULL);
686 *width = page;
687
688 vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
689 g_object_get(vadj, "page-size", &page, NULL);
690 *height = page;
691 } else {
692 GtkAllocation allocation;
693 gtk_widget_get_allocation(GTK_WIDGET(nsgtk_cw->drawing_area),
694 &allocation);
695 *width = allocation.width;
696 *height = allocation.height;
697 }
698 return NSERROR_OK;
699}
700
701
702/**
703 * update window drag status core window callback
704 *
705 * \param cw core window handle.
706 * \param ds The new drag status.
707 */
708static nserror
710{
711 struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
712 nsgtk_cw->drag_status = ds;
713
714 return NSERROR_OK;
715}
716
717
718/**
719 * core window callback table for nsgtk
720 */
723 .update_size = nsgtk_cw_update_size,
724 .set_scroll = nsgtk_cw_set_scroll,
725 .get_scroll = nsgtk_cw_get_scroll,
726 .get_window_dimensions = nsgtk_cw_get_window_dimensions,
727 .drag_status = nsgtk_cw_drag_status
728};
729
730
731/* exported function documented gtk/corewindow.h */
733{
734 nsgtk_cw->cb_table = &nsgtk_cw_cb_table;
736
737 /* input method setup */
738 nsgtk_cw->input_method = gtk_im_multicontext_new();
739 gtk_im_context_set_client_window(nsgtk_cw->input_method,
740 gtk_widget_get_parent_window(GTK_WIDGET(nsgtk_cw->drawing_area)));
741 gtk_im_context_set_use_preedit(nsgtk_cw->input_method, FALSE);
742
743 g_signal_connect(G_OBJECT(nsgtk_cw->input_method),
744 "commit",
746 nsgtk_cw);
747
748 nsgtk_connect_draw_event(GTK_WIDGET(nsgtk_cw->drawing_area),
749 G_CALLBACK(nsgtk_cw_draw_event),
750 nsgtk_cw);
751
752 g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
753 "button-press-event",
754 G_CALLBACK(nsgtk_cw_button_press_event),
755 nsgtk_cw);
756
757 g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
758 "button-release-event",
760 nsgtk_cw);
761
762 g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
763 "motion-notify-event",
765 nsgtk_cw);
766
767 g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
768 "key-press-event",
769 G_CALLBACK(nsgtk_cw_keypress_event),
770 nsgtk_cw);
771
772 g_signal_connect(G_OBJECT(nsgtk_cw->drawing_area),
773 "key-release-event",
774 G_CALLBACK(nsgtk_cw_keyrelease_event),
775 nsgtk_cw);
776
778 GTK_WIDGET(nsgtk_cw->drawing_area),
780 0, 0xffff, 0xffff, 0xffff);
781
782 return NSERROR_OK;
783}
784
785/* exported interface documented in gtk/corewindow.h */
787{
788 g_object_unref(nsgtk_cw->input_method);
789
790 return NSERROR_OK;
791}
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
gdouble nsgtk_adjustment_get_page_increment(GtkAdjustment *adjustment)
Definition: compat.c:480
gdouble nsgtk_adjustment_get_upper(GtkAdjustment *adjustment)
Definition: compat.c:462
gdouble nsgtk_adjustment_get_lower(GtkAdjustment *adjustment)
Definition: compat.c:471
gdouble nsgtk_adjustment_get_step_increment(GtkAdjustment *adjustment)
Definition: compat.c:453
Compatibility functions for older GTK versions (interface)
#define GTK_STATE_FLAG_NORMAL
Definition: compat.h:160
core_window_drag_status
drag status passed to drag_status callback
Definition: core_window.h:41
@ CORE_WINDOW_DRAG_NONE
Definition: core_window.h:42
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOT_IMPLEMENTED
Functionality is not implemented.
Definition: errors.h:61
@ NSERROR_OK
No error.
Definition: errors.h:30
Target independent plotting GTK+ interface.
nserror nsgtk_corewindow_init(struct nsgtk_corewindow *nsgtk_cw)
initialise elements of gtk core window.
Definition: corewindow.c:732
static gboolean nsgtk_cw_keypress_event(GtkWidget *widget, GdkEventKey *event, gpointer g)
gtk event on key press.
Definition: corewindow.c:406
static gboolean nsgtk_cw_keyrelease_event(GtkWidget *widget, GdkEventKey *event, gpointer g)
gtk event on key release.
Definition: corewindow.c:450
static gboolean nsgtk_cw_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer g)
gtk event on mouse button release.
Definition: corewindow.c:143
static gboolean nsgtk_cw_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer g)
gtk event on mouse movement.
Definition: corewindow.c:220
static nserror nsgtk_cw_update_size(struct core_window *cw, int width, int height)
update window size core window callback
Definition: corewindow.c:597
static void nsgtk_cw_input_method_commit(GtkIMContext *ctx, const gchar *str, gpointer g)
gtk event handler for input method commit.
Definition: corewindow.c:468
static browser_mouse_state nsgtk_cw_gdkbutton_to_nsstate(GdkEventButton *event)
Convert GDK mouse event to netsurf mouse state.
Definition: corewindow.c:59
static nserror nsgtk_cw_get_window_dimensions(const struct core_window *cw, int *width, int *height)
Callback from the core to obtain the window viewport dimensions.
Definition: corewindow.c:675
static nserror nsgtk_cw_get_scroll(const struct core_window *cw, int *x, int *y)
scroll window core window callback
Definition: corewindow.c:643
static nserror nsgtk_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
update window drag status core window callback
Definition: corewindow.c:709
static nserror nsgtk_cw_set_scroll(struct core_window *cw, int x, int y)
scroll window core window callback
Definition: corewindow.c:615
nserror nsgtk_corewindow_fini(struct nsgtk_corewindow *nsgtk_cw)
finalise elements of gtk core window.
Definition: corewindow.c:786
static gboolean nsgtk_cw_draw_event(GtkWidget *widget, GdkEventExpose *event, gpointer g)
handler for gtk draw event on a nsgtk core window for GTK 2
Definition: corewindow.c:534
static gboolean nsgtk_cw_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer g)
gtk event on mouse button press.
Definition: corewindow.c:109
static nserror nsgtk_cw_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
Deal with keypress events not handled buy input method or callback.
Definition: corewindow.c:310
static nserror nsgtk_cw_invalidate_area(struct core_window *cw, const struct rect *rect)
callback from core to request an invalidation of a GTK core window area.
Definition: corewindow.c:570
static struct core_window_callback_table nsgtk_cw_cb_table
core window callback table for nsgtk
Definition: corewindow.c:721
uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
input conversion.
Definition: gui.c:121
cairo_t * current_cr
Definition: plotters.c:42
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_HOVER
No mouse buttons pressed, May be used to indicate hover or end of drag.
Definition: mouse.h:47
@ 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_3
3rd modifier key pressed (eg.
Definition: mouse.h:82
@ 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
Interface to key press operations.
@ NS_KEY_RIGHT
Definition: keypress.h:51
@ NS_KEY_LEFT
Definition: keypress.h:50
@ NS_KEY_DOWN
Definition: keypress.h:53
@ NS_KEY_PAGE_UP
Definition: keypress.h:65
@ NS_KEY_PAGE_DOWN
Definition: keypress.h:66
@ NS_KEY_TEXT_START
Definition: keypress.h:59
@ NS_KEY_TEXT_END
Definition: keypress.h:60
@ NS_KEY_UP
Definition: keypress.h:52
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get_errorcode(nserror code)
lookup of a message by errorcode from the standard Messages hash.
Definition: messages.c:248
Localised message support (interface).
int width
Definition: gui.c:159
int height
Definition: gui.c:160
Interface to utility string handling.
Callbacks to achieve various core window functionality.
Definition: core_window.h:51
nserror(* invalidate)(struct core_window *cw, const struct rect *rect)
Invalidate an area of a window.
Definition: core_window.h:69
nsgtk core window mouse state
Definition: corewindow.h:27
browser_mouse_state state
last event status
Definition: corewindow.h:28
nsgtk core window state
Definition: corewindow.h:39
nserror(* key)(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
callback for keypress on nsgtk core window
Definition: corewindow.h:74
nserror(* draw)(struct nsgtk_corewindow *nsgtk_cw, struct rect *r)
callback to draw on drawable area of nsgtk core window
Definition: corewindow.h:63
struct core_window_callback_table * cb_table
table of callbacks for core window operations
Definition: corewindow.h:50
GtkScrolledWindow * scrolled
scrollable area drawing area is within
Definition: corewindow.h:44
nserror(* mouse)(struct nsgtk_corewindow *nsgtk_cw, browser_mouse_state mouse_state, int x, int y)
callback for mouse event on nsgtk core window
Definition: corewindow.h:85
core_window_drag_status drag_status
drag status set by core
Definition: corewindow.h:54
GtkDrawingArea * drawing_area
GTK drawable widget.
Definition: corewindow.h:42
GtkIMContext * input_method
Input method.
Definition: corewindow.h:48
struct nsgtk_corewindow_mouse mouse_state
mouse state
Definition: corewindow.h:52
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
NetSurf types.
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).
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357