NetSurf
event.c
Go to the documentation of this file.
1/*
2 * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
3 *
4 * Framebuffer windowing toolkit event processing.
5 *
6 * This file is part of NetSurf, http://www.netsurf-browser.org/
7 *
8 * NetSurf is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * NetSurf is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <sys/types.h>
22#include <stdint.h>
23#include <string.h>
24#include <stdbool.h>
25
26#include <libnsfb.h>
27#include <libnsfb_plot.h>
28#include <libnsfb_plot_util.h>
29#include <libnsfb_event.h>
30#include <libnsfb_cursor.h>
31
32#include "utils/utils.h"
33#include "utils/log.h"
35#include "netsurf/keypress.h"
36
37#include "framebuffer/gui.h"
38#include "framebuffer/fbtk.h"
40
41#include "widget.h"
42
43/* exported function documented in fbtk.h */
44void
45fbtk_input(fbtk_widget_t *root, nsfb_event_t *event)
46{
47 fbtk_widget_t *input;
48
50
51 /* obtain widget with input focus */
52 input = root->u.root.input;
53 if (input == NULL) {
54 NSLOG(netsurf, INFO, "No widget has input focus.");
55 return; /* no widget with input */
56 }
57
59}
60
61/* exported function documented in fbtk.h */
62void
63fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event)
64{
66 fbtk_widget_t *clicked;
67 nsfb_bbox_t cloc;
68 int x, y;
69
70 /* ensure we have the root widget */
71 root = fbtk_get_root_widget(widget);
72
73 nsfb_cursor_loc_get(root->u.root.fb, &cloc);
74
75 clicked = fbtk_get_widget_at(root, cloc.x0, cloc.y0);
76
77 if (clicked == NULL)
78 return;
79
80 if (fbtk_get_handler(clicked, FBTK_CBT_INPUT) != NULL) {
81 fbtk_set_focus(clicked);
82 }
83
84 x = fbtk_get_absx(clicked);
85 y = fbtk_get_absy(clicked);
86
87 NSLOG(netsurf, DEEPDEBUG, "clicked %p at %d,%d", clicked, x, y);
88
89 /* post the click */
90 fbtk_post_callback(clicked, FBTK_CBT_CLICK, event, cloc.x0 - x, cloc.y0 - y);
91}
92
93/* exported function documented in fbtk.h */
94bool
96{
98
99 /* ensure we have the root widget */
100 root = fbtk_get_root_widget(widget);
101
102 if (root->u.root.grabbed == widget) {
103 /* release pointer grab */
104 root->u.root.grabbed = NULL;
105 return true;
106 } else if (root->u.root.grabbed == NULL) {
107 /* set pointer grab */
108 root->u.root.grabbed = widget;
109 return true;
110 }
111 /* pointer was already grabbed */
112 return false;
113}
114
115/* exported function documented in fbtk.h */
116void
117fbtk_warp_pointer(fbtk_widget_t *widget, int x, int y, bool relative)
118{
120 fbtk_widget_t *moved;
121 nsfb_bbox_t cloc;
122
123 /* ensure we have the root widget */
124 root = fbtk_get_root_widget(widget);
125
126 if (relative) {
127 nsfb_cursor_loc_get(root->u.root.fb, &cloc);
128 cloc.x0 += x;
129 cloc.y0 += y;
130 } else {
131 cloc.x0 = x;
132 cloc.y0 = y;
133 }
134
135 /* ensure cursor location lies within the root widget */
136 if (cloc.x0 < root->x)
137 cloc.x0 = root->x;
138 if (cloc.x0 >= (root->x + root->width))
139 cloc.x0 = (root->x + root->width) - 1;
140 if (cloc.y0 < root->y)
141 cloc.y0 = root->y;
142 if (cloc.y0 >= (root->y + root->height))
143 cloc.y0 = (root->y + root->height) - 1;
144
145 if (root->u.root.grabbed == NULL) {
146 /* update the pointer cursor */
147 nsfb_cursor_loc_set(root->u.root.fb, &cloc);
148
149 moved = fbtk_get_widget_at(root, cloc.x0, cloc.y0);
150
151 x = fbtk_get_absx(moved);
152 y = fbtk_get_absy(moved);
153
154 /* post enter and leaving messages */
155 if (moved != root->u.root.prev) {
157 root->u.root.prev = moved;
159 }
160 } else {
161 /* pointer movement has been grabbed by a widget */
162 moved = root->u.root.grabbed;
163
164 /* ensure pointer remains within widget boundary */
165 x = fbtk_get_absx(moved);
166 y = fbtk_get_absy(moved);
167
168 if (cloc.x0 < x)
169 cloc.x0 = x;
170 if (cloc.y0 < y)
171 cloc.y0 = y;
172 if (cloc.x0 > (x + moved->width))
173 cloc.x0 = (x + moved->width);
174 if (cloc.y0 > (y + moved->height))
175 cloc.y0 = (y + moved->height);
176
177 /* update the pointer cursor */
178 nsfb_cursor_loc_set(root->u.root.fb, &cloc);
179 }
180
181 /* post the movement */
182 fbtk_post_callback(moved, FBTK_CBT_POINTERMOVE, cloc.x0 - x, cloc.y0 - y);
183
184}
185
186/* exported function documented in fbtk.h */
187bool
188fbtk_event(fbtk_widget_t *root, nsfb_event_t *event, int timeout)
189{
190 nsfb_bbox_t cloc;
191 bool unused = false; /* is the event available */
192 bool move_pointer = false; /* whether pointer move events occured */
193
194 /* ensure we have the root widget */
196
197 do {
198 if (nsfb_event(root->u.root.fb, event, timeout) == false) {
199 if (move_pointer)
200 fbtk_warp_pointer(root, cloc.x0, cloc.y0,
201 false);
202 return false;
203 }
204
205 if (move_pointer && event->type != NSFB_EVENT_MOVE_RELATIVE &&
206 event->type != NSFB_EVENT_MOVE_ABSOLUTE) {
207 /* Flush the movements */
208 fbtk_warp_pointer(root, cloc.x0, cloc.y0, false);
209
210 } else if (!move_pointer &&
211 event->type == NSFB_EVENT_MOVE_RELATIVE) {
212 /* Get current pointer coords */
213 nsfb_cursor_loc_get(root->u.root.fb, &cloc);
214 }
215
216 switch (event->type) {
217 case NSFB_EVENT_KEY_DOWN:
218 case NSFB_EVENT_KEY_UP:
219 if ((event->value.keycode >= NSFB_KEY_MOUSE_1) &&
220 (event->value.keycode <= NSFB_KEY_MOUSE_5)) {
221 fbtk_click(root, event);
222 } else {
223 fbtk_input(root, event);
224 }
225 break;
226
227 case NSFB_EVENT_CONTROL:
228 unused = true;
229 break;
230
231 case NSFB_EVENT_MOVE_RELATIVE:
232 /* Consecutive move events are consolidated into a
233 * single pointer warp */
234 move_pointer = true;
235 cloc.x0 += event->value.vector.x;
236 cloc.y0 += event->value.vector.y;
237 timeout = 0;
238 break;
239
240 case NSFB_EVENT_MOVE_ABSOLUTE:
241 /* Consecutive move events are consolidated into a
242 * single pointer warp */
243 move_pointer = true;
244 cloc.x0 = event->value.vector.x;
245 cloc.y0 = event->value.vector.y;
246 timeout = 0;
247 break;
248
249 case NSFB_EVENT_RESIZE:
250 /* Try to resize framebuffer */
252 event->value.resize.w,
253 event->value.resize.h);
254 break;
255
256 default:
257 break;
258 }
259 } while (event->type == NSFB_EVENT_MOVE_RELATIVE ||
260 event->type == NSFB_EVENT_MOVE_ABSOLUTE);
261 return unused;
262}
263
264static int keymap[] = {
265 /* 0 1 2 3 4 5 6 7 8 9 */
266 -1, -1, -1, -1, -1, -1, -1, -1, 8, 9, /* 0 - 9 */
267 -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, /* 10 - 19 */
268 -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, /* 20 - 29 */
269 -1, -1, ' ', '!', '"', '#', '$', -1, '&','\'', /* 30 - 39 */
270 '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', /* 40 - 49 */
271 '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', /* 50 - 59 */
272 '<', '=', '>', '?', '@', -1, -1, -1, -1, -1, /* 60 - 69 */
273 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */
274 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */
275 -1, '[','\\', ']', '~', '_', '`', 'a', 'b', 'c', /* 90 - 99 */
276 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', /* 100 - 109 */
277 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 110 - 119 */
278 'x', 'y', 'z', -1, -1, -1, -1, -1, -1, -1, /* 120 - 129 */
279};
280
281static int sh_keymap[] = {
282 /* 0 1 2 3 4 5 6 7 8 9 */
283 -1, -1, -1, -1, -1, -1, -1, -1, 8, 9, /* 0 - 9 */
284 -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, /* 10 - 19 */
285 -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, /* 20 - 29 */
286 -1, -1, ' ', '!', '"', '~', '$', -1, '&', '@', /* 30 - 39 */
287 '(', ')', '*', '+', '<', '_', '>', '?', ')', '!', /* 40 - 49 */
288 '"', 243, '$', '%', '^', '&', '*', '(', ';', ':', /* 50 - 59 */
289 '<', '+', '>', '?', '@', -1, -1, -1, -1, -1, /* 60 - 69 */
290 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */
291 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */
292 -1, '{', '|', '}', '~', '_', 254, 'A', 'B', 'C', /* 90 - 99 */
293 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', /* 100 - 109 */
294 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 110 - 119 */
295 'X', 'Y', 'Z', -1, -1, -1, -1, -1, -1, -1, /* 120 - 129 */
296};
297
298
299/* exported function documented in fbtk.h */
300int
302{
303 int ucs4 = -1;
304
305 if (mods & FBTK_MOD_LSHIFT || mods & FBTK_MOD_RSHIFT) {
306 if ((code >= 0) && (code < (int) NOF_ELEMENTS(sh_keymap)))
307 ucs4 = sh_keymap[code];
308
309 } else if (mods == FBTK_MOD_CLEAR) {
310 if ((code >= 0) && (code < (int) NOF_ELEMENTS(keymap)))
311 ucs4 = keymap[code];
312
313 } else if (mods & FBTK_MOD_LCTRL || mods & FBTK_MOD_RCTRL) {
314 switch (code) {
315 case NSFB_KEY_a:
316 ucs4 = NS_KEY_SELECT_ALL;
317 break;
318
319 case NSFB_KEY_c:
321 break;
322
323 case NSFB_KEY_u:
324 ucs4 = NS_KEY_DELETE_LINE;
325 break;
326
327 case NSFB_KEY_v:
328 ucs4 = NS_KEY_PASTE;
329 break;
330
331 case NSFB_KEY_x:
333 break;
334
335 case NSFB_KEY_z:
337 break;
338 default:
339 break;
340 }
341 }
342 return ucs4;
343}
344
345/*
346 * Local Variables:
347 * c-basic-offset:8
348 * End:
349 */
Browser window creation and manipulation interface.
static int sh_keymap[]
Definition: event.c:281
static int keymap[]
Definition: event.c:264
void fbtk_warp_pointer(fbtk_widget_t *widget, int x, int y, bool relative)
Move pointer.
Definition: event.c:117
bool fbtk_tgrab_pointer(fbtk_widget_t *widget)
Toggle pointer grab.
Definition: event.c:95
void fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event)
Insert mouse button press into toolkit.
Definition: event.c:63
bool fbtk_event(fbtk_widget_t *root, nsfb_event_t *event, int timeout)
Retrive events from the framebuffer input.
Definition: event.c:188
int fbtk_keycode_to_ucs4(int code, fbtk_modifier_type mods)
Convert a framebuffer keycode to ucs4.
Definition: event.c:301
void fbtk_input(fbtk_widget_t *root, nsfb_event_t *event)
Insert input into toolkit.
Definition: event.c:45
fbtk_widget_t * fbtk_get_root_widget(fbtk_widget_t *widget)
find the root widget from any widget in the toolkit hierarchy.
Definition: fbtk.c:412
@ FBTK_CBT_POINTERMOVE
Definition: fbtk.h:41
@ FBTK_CBT_INPUT
Definition: fbtk.h:40
@ FBTK_CBT_POINTERENTER
Definition: fbtk.h:43
@ FBTK_CBT_POINTERLEAVE
Definition: fbtk.h:42
@ FBTK_CBT_CLICK
Definition: fbtk.h:39
fbtk_widget_t * fbtk_get_widget_at(fbtk_widget_t *widget, int x, int y)
Obtain the widget at a point on screen.
Definition: fbtk.c:516
int fbtk_get_absx(fbtk_widget_t *widget)
Get a widget's absolute horizontal screen co-ordinate.
Definition: fbtk.c:430
fbtk_callback fbtk_get_handler(fbtk_widget_t *widget, fbtk_callback_type cbt)
Get a callback handler.
Definition: fbtk.c:681
fbtk_modifier_type
Key modifier status.
Definition: fbtk.h:75
@ FBTK_MOD_LSHIFT
Definition: fbtk.h:77
@ FBTK_MOD_RCTRL
Definition: fbtk.h:80
@ FBTK_MOD_RSHIFT
Definition: fbtk.h:78
@ FBTK_MOD_LCTRL
Definition: fbtk.h:79
@ FBTK_MOD_CLEAR
Definition: fbtk.h:76
void fbtk_set_focus(fbtk_widget_t *widget)
Give widget input focus.
Definition: fbtk.c:781
int fbtk_post_callback(fbtk_widget_t *widget, fbtk_callback_type cbt,...)
Helper function to allow simple calling of callbacks with parameters.
Definition: fbtk.c:715
int fbtk_get_absy(fbtk_widget_t *widget)
Get a widget's absolute vertical screen co-ordinate.
Definition: fbtk.c:445
static struct directory * root
Definition: filename.c:55
void gui_resize(fbtk_widget_t *root, int width, int height)
Definition: gui.c:2290
#define NOF_ELEMENTS(array)
Definition: search.c:67
Interface to key press operations.
@ NS_KEY_SELECT_ALL
Definition: keypress.h:32
@ NS_KEY_PASTE
Definition: keypress.h:43
@ NS_KEY_COPY_SELECTION
Definition: keypress.h:33
@ NS_KEY_CUT_SELECTION
Definition: keypress.h:44
@ NS_KEY_CLEAR_SELECTION
Definition: keypress.h:45
@ NS_KEY_DELETE_LINE
Definition: keypress.h:42
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
Interface to utility string handling.
Widget description.
Definition: widget.h:120
int height
Definition: widget.h:136
Interface to a number of general purpose functionality.