1 /*
2 * Copyright 2010 Ole Loots <ole@monochrom.net>
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 * Implements the NetSurf Browser window, or passed functionality to
22 * the appropriate widget's.
23 *
24 */
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <limits.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <stdbool.h>
34 #include <assert.h>
35 #include <math.h>
36 #include <osbind.h>
37
38 #include <mt_gem.h>
39
40 #include "utils/log.h"
41 #include "utils/nsurl.h"
42 #include "netsurf/browser_window.h"
43 #include "netsurf/mouse.h"
44 #include "netsurf/plotters.h"
45 #include "netsurf/keypress.h"
46
47 #include "atari/res/netsurf.rsh"
48 #include "atari/gemtk/gemtk.h"
49 #include "atari/ctxmenu.h"
50 #include "atari/gui.h"
51 #include "atari/rootwin.h"
52 #include "atari/misc.h"
53 #include "atari/plot/plot.h"
54 #include "atari/toolbar.h"
55 #include "atari/statusbar.h"
56 #include "atari/search.h"
57 #include "atari/osspec.h"
58 #include "atari/encoding.h"
59 #include "atari/redrawslots.h"
60 #include "atari/toolbar.h"
61 #include "atari/findfile.h"
62 #include "atari/bitmap.h"
63
64 extern struct gui_window *input_window;
65 extern EVMULT_OUT aes_event_out;
66 extern GRECT desk_area;
67
68 struct rootwin_data_s {
69 struct s_gui_win_root *rootwin;
70 };
71
72 /* -------------------------------------------------------------------------- */
73 /* Static module event handlers */
74 /* -------------------------------------------------------------------------- */
75 static void on_redraw(ROOTWIN *rootwin, short msg[8]);
76 static void on_resized(ROOTWIN *rootwin);
77 static void on_file_dropped(ROOTWIN *rootwin, short msg[8]);
78 static short on_window_key_input(ROOTWIN * rootwin, unsigned short nkc);
79 static void on_content_mouse_click(ROOTWIN *rootwin);
80 static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area);
81 static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip);
82
83 bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);
84
85 static bool redraw_active = false;
86
87 static const struct redraw_context rootwin_rdrw_ctx = {
88 .interactive = true,
89 .background_images = true,
90 .plot = &atari_plotters
91 };
92
handle_event(GUIWIN * win,EVMULT_OUT * ev_out,short msg[8])93 static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
94 {
95 short retval = 0;
96 GRECT area;
97 static bool prev_url = false;
98 struct rootwin_data_s * data = gemtk_wm_get_user_data(win);
99 struct gui_window *tmp;
100
101
102 if ((ev_out->emo_events & MU_MESAG) != 0) {
103 // handle message
104 //printf("root win msg: %d\n", msg[0]);
105 switch (msg[0]) {
106
107 case WM_REDRAW:
108 NSLOG(netsurf, INFO, "WM_REDRAW");
109 on_redraw(data->rootwin, msg);
110 break;
111
112 case WM_REPOSED:
113 case WM_SIZED:
114 case WM_MOVED:
115 case WM_FULLED:
116 NSLOG(netsurf, INFO, "WM_SIZED");
117 on_resized(data->rootwin);
118 break;
119
120 case WM_ICONIFY:
121 // TODO: find next active gui window and schedule redraw for that.
122 tmp = window_list;
123 while(tmp != NULL){
124 if(tmp->root != data->rootwin){
125 gemtk_wm_send_msg(tmp->root->win, WM_TOPPED, 0, 0, 0, 0);
126 break;
127 }
128 tmp = tmp->next;
129 }
130 break;
131
132 case WM_TOPPED:
133 case WM_NEWTOP:
134 case WM_UNICONIFY:
135 NSLOG(netsurf, INFO, "WM_TOPPED");
136 gui_set_input_gui_window(data->rootwin->active_gui_window);
137 //window_restore_active_gui_window(data->rootwin);
138 // TODO: use something like "restore_active_gui_window_state()"
139
140 break;
141
142 case WM_CLOSED:
143 // TODO: this needs to iterate through all gui windows and
144 // check if the rootwin is this window...
145 if (data->rootwin->active_gui_window != NULL) {
146 NSLOG(netsurf, INFO, "WM_CLOSED initiated destroy for bw %p",
147 data->rootwin->active_gui_window->browser->bw);
148 browser_window_destroy(
149 data->rootwin->active_gui_window->browser->bw);
150 }
151 break;
152
153 case AP_DRAGDROP:
154 on_file_dropped(data->rootwin, msg);
155 break;
156
157 case WM_TOOLBAR:
158 toolbar_mouse_input(data->rootwin->toolbar, msg[4], msg[7]);
159 break;
160
161 default:
162 break;
163 }
164 }
165 if ((ev_out->emo_events & MU_KEYBD) != 0) {
166
167 // handle key
168 uint16_t nkc = gem_to_norm( (short)ev_out->emo_kmeta,
169 (short)ev_out->emo_kreturn);
170 NSLOG(netsurf, INFO, "rootwin MU_KEYBD input, nkc: %x\n", nkc);
171 retval = on_window_key_input(data->rootwin, nkc);
172 // printf("on_window_key_input: %d\n", retval);
173
174 }
175 if ((ev_out->emo_events & MU_BUTTON) != 0) {
176 NSLOG(netsurf, INFO,
177 "rootwin MU_BUTTON input, x: %d, y: %d\n",
178 ev_out->emo_mouse.p_x,
179 ev_out->emo_mouse.p_x);
180 window_get_grect(data->rootwin, BROWSER_AREA_CONTENT,
181 &area);
182 if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
183 area)) {
184 on_content_mouse_click(data->rootwin);
185 }
186 }
187 if ((ev_out->emo_events & (MU_M1)) != 0) {
188
189 short ghandle = wind_find(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y);
190
191 if (data->rootwin->aes_handle==ghandle) {
192 // The window found at x,y is an gui_window
193 // and it's the input window.
194 window_get_grect(data->rootwin, BROWSER_AREA_CONTENT,
195 &area);
196 if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
197 area)) {
198 on_content_mouse_move(data->rootwin, &area);
199 } else {
200 GRECT tb_area;
201 window_get_grect(data->rootwin, BROWSER_AREA_URL_INPUT, &tb_area);
202 if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
203 tb_area)) {
204 gem_set_cursor(&gem_cursors.ibeam);
205 prev_url = true;
206 } else {
207 if(prev_url) {
208 struct gui_window *gw;
209 gw = window_get_active_gui_window(data->rootwin);
210 gem_set_cursor(gw->cursor);
211 prev_url = false;
212 }
213 }
214 }
215 }
216 }
217
218 return(retval);
219 }
220
221 /* -------------------------------------------------------------------------- */
222 /* Module public functions: */
223 /* -------------------------------------------------------------------------- */
224
window_create(struct gui_window * gw,struct browser_window * bw,struct gui_window * existing,unsigned long inflags)225 int window_create(struct gui_window * gw,
226 struct browser_window * bw,
227 struct gui_window * existing,
228 unsigned long inflags)
229 {
230 int err = 0;
231 bool tb, sb;
232 int flags;
233 struct rootwin_data_s *data;
234 struct gemtk_wm_scroll_info_s *slid;
235
236 tb = (inflags & WIDGET_TOOLBAR);
237 sb = (inflags & WIDGET_STATUSBAR);
238
239 flags = CLOSER | MOVER | NAME | FULLER | SMALLER;
240 if( inflags & WIDGET_SCROLL ) {
241 flags |= (UPARROW | DNARROW | LFARROW | RTARROW | VSLIDE | HSLIDE);
242 }
243 if( inflags & WIDGET_RESIZE ) {
244 flags |= ( SIZER );
245 }
246 if( inflags & WIDGET_STATUSBAR ) {
247 flags |= ( INFO );
248 }
249
250 gw->root = malloc(sizeof(struct s_gui_win_root));
251 if (gw->root == NULL)
252 return(-1);
253 memset(gw->root, 0, sizeof(struct s_gui_win_root) );
254 gw->root->title = malloc(atari_sysinfo.aes_max_win_title_len+1);
255
256 redraw_slots_init(&gw->root->redraw_slots, 8);
257
258 gw->root->aes_handle = wind_create(flags, 40, 40, desk_area.g_w,
259 desk_area.g_h);
260 if(gw->root->aes_handle<0) {
261 free(gw->root->title);
262 free(gw->root);
263 return( -1 );
264 }
265 gw->root->win = gemtk_wm_add(gw->root->aes_handle,
266 GEMTK_WM_FLAG_PREPROC_WM | GEMTK_WM_FLAG_RECV_PREPROC_WM, handle_event);
267
268 data = malloc(sizeof(struct rootwin_data_s));
269 data->rootwin = gw->root;
270 gemtk_wm_set_user_data(gw->root->win, (void*)data);
271 slid = gemtk_wm_get_scroll_info(gw->root->win);
272 slid->y_unit_px = 32;
273 slid->x_unit_px = 32;
274
275 /* create */
276 if(tb) {
277 gw->root->toolbar = toolbar_create(gw->root);
278 assert(gw->root->toolbar);
279 gemtk_wm_set_toolbar(gw->root->win, gw->root->toolbar->form, 0, 0);
280 gemtk_wm_set_toolbar_redraw_func(gw->root->win, toolbar_redraw_cb);
281 } else {
282 gw->root->toolbar = NULL;
283 }
284
285 /* create browser component: */
286 gw->browser = (struct s_browser *)malloc( sizeof(struct s_browser));
287
288 assert(gw->browser);
289
290 gw->browser->bw = bw;
291
292 /* create statusbar component: */
293 if(sb) {
294 gw->root->statusbar = sb_create( gw );
295 } else {
296 gw->root->statusbar = NULL;
297 }
298
299 // Setup some window defaults:
300 wind_set_str(gw->root->aes_handle, WF_NAME, (char*)"NetSurf");
301 wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_FULLREDRAW, 0, 0);
302 wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_NOBLITW, 0, 0);
303 wind_set(gw->root->aes_handle, WF_OPTS, 1, WO0_NOBLITH, 0, 0);
304
305 if (inflags & WIN_TOP) {
306 window_set_focus(gw->root, BROWSER, gw->browser);
307 }
308
309 return (err);
310 }
311
window_unref_gui_window(ROOTWIN * rootwin,struct gui_window * gw)312 void window_unref_gui_window(ROOTWIN *rootwin, struct gui_window *gw)
313 {
314 struct gui_window *w;
315 input_window = NULL;
316
317 NSLOG(netsurf, INFO, "window: %p, gui_window: %p", rootwin, gw);
318
319 w = window_list;
320 // find the next active tab:
321 while( w != NULL ) {
322 if(w->root == rootwin && w != gw) {
323 NSLOG(netsurf, INFO, "activating next tab %p", w);
324 gui_set_input_gui_window(w);
325 break;
326 }
327 w = w->next;
328 }
329 if(input_window == NULL) {
330 // the last gui window for this rootwin was removed:
331 redraw_slots_free(&rootwin->redraw_slots);
332 window_destroy(rootwin);
333 }
334 }
335
window_destroy(ROOTWIN * rootwin)336 int window_destroy(ROOTWIN *rootwin)
337 {
338 int err = 0;
339 struct gui_window *w;
340
341 assert(rootwin != NULL);
342
343 NSLOG(netsurf, INFO, "%p", rootwin);
344
345 if (gemtk_wm_get_user_data(rootwin->win) != NULL) {
346 free(gemtk_wm_get_user_data(rootwin->win));
347 }
348
349 // make sure we do not destroy windows which have gui_windows attached:
350 w = window_list;
351 while( w != NULL ) {
352 if(w->root == rootwin) {
353 assert(rootwin == NULL);
354 }
355 w = w->next;
356 }
357
358 if (rootwin->toolbar)
359 toolbar_destroy(rootwin->toolbar);
360
361 if(rootwin->statusbar)
362 sb_destroy(rootwin->statusbar);
363
364 if(rootwin->title)
365 free(rootwin->title);
366
367 gemtk_wm_remove(rootwin->win);
368 wind_close(rootwin->aes_handle);
369 wind_delete(rootwin->aes_handle);
370 free(rootwin);
371 return(err);
372 }
373
374
window_open(ROOTWIN * rootwin,struct gui_window * gw,GRECT pos)375 void window_open(ROOTWIN *rootwin, struct gui_window *gw, GRECT pos)
376 {
377 GRECT g;
378
379 rootwin->active_gui_window = gw;
380
381 assert(rootwin->active_gui_window != NULL);
382
383 wind_open(rootwin->aes_handle, pos.g_x, pos.g_y, pos.g_w, pos.g_h );
384 wind_set_str(rootwin->aes_handle, WF_NAME, (char *)"");
385
386 rootwin->active_gui_window->browser->attached = true;
387 if(rootwin->statusbar != NULL) {
388 sb_attach(rootwin->statusbar, rootwin->active_gui_window);
389 }
390
391 /* Set initial size of the toolbar region: */
392 gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_TOOLBAR, &g);
393 toolbar_set_attached(rootwin->toolbar, true);
394 toolbar_set_dimensions(rootwin->toolbar, &g);
395
396 /* initially hide the search area of the toolbar: */
397 window_close_search(rootwin);
398
399 window_update_back_forward(rootwin);
400
401 window_set_focus(rootwin, BROWSER, rootwin->active_gui_window->browser);
402 }
403
window_restore_active_gui_window(ROOTWIN * rootwin)404 void window_restore_active_gui_window(ROOTWIN *rootwin)
405 {
406 GRECT tb_area;
407 struct gui_window *gw;
408
409 NSLOG(netsurf, INFO, "rootwin %p", rootwin);
410
411 assert(rootwin->active_gui_window);
412
413 gw = rootwin->active_gui_window;
414
415 window_set_icon(rootwin, gw->icon);
416 window_set_stauts(rootwin, gw->status);
417 window_set_title(rootwin, gw->title);
418
419 if (gw->search != NULL) {
420 // TODO: update search session (especially browser window)
421 }
422
423 toolbar_get_grect(rootwin->toolbar, 0, &tb_area);
424 gemtk_wm_set_toolbar_size(rootwin->win, tb_area.g_h);
425
426 window_update_back_forward(rootwin);
427
428 toolbar_set_url(rootwin->toolbar, gw->url);
429 }
430
431
432 /* update back forward buttons (see tb_update_buttons (bug) ) */
window_update_back_forward(struct s_gui_win_root * rootwin)433 void window_update_back_forward(struct s_gui_win_root *rootwin)
434 {
435 struct gui_window * active_gw = rootwin->active_gui_window;
436 toolbar_update_buttons(rootwin->toolbar, active_gw->browser->bw, -1);
437 }
438
window_set_stauts(struct s_gui_win_root * rootwin,char * text)439 void window_set_stauts(struct s_gui_win_root *rootwin, char * text)
440 {
441 assert(rootwin != NULL);
442
443 CMP_STATUSBAR sb = rootwin->statusbar;
444
445 if( sb == NULL)
446 return;
447
448 if(text != NULL)
449 sb_set_text(sb, text);
450 else
451 sb_set_text(sb, "");
452 }
453
window_set_title(struct s_gui_win_root * rootwin,char * title)454 void window_set_title(struct s_gui_win_root * rootwin, char *title)
455 {
456 wind_set_str(rootwin->aes_handle, WF_NAME, title);
457 }
458
window_scroll_by(ROOTWIN * root,int sx,int sy)459 void window_scroll_by(ROOTWIN *root, int sx, int sy)
460 {
461 struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(root->win);
462
463 if (sx < 0) {
464 sx = 0;
465 }
466 if (sy < 0) {
467 sy = 0;
468 }
469 int xunits = sx / slid->x_unit_px;
470 int yunits = sy / slid->y_unit_px;
471
472 gemtk_wm_scroll(root->win, GEMTK_WM_VSLIDER, yunits - slid->y_pos, false);
473 gemtk_wm_scroll(root->win, GEMTK_WM_HSLIDER, xunits - slid->x_pos, false);
474 gemtk_wm_update_slider(root->win, GEMTK_WM_VH_SLIDER);
475 }
476
477 /**
478 * Set the dimensions of the scrollable content.
479 *
480 */
window_set_content_size(ROOTWIN * rootwin,int width,int height)481 void window_set_content_size(ROOTWIN *rootwin, int width, int height)
482 {
483 GRECT area;
484 struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(rootwin->win);
485
486 window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area);
487
488 slid->x_units = (width/slid->x_unit_px);
489 slid->y_units = (height/slid->y_unit_px);
490 if(slid->x_units < slid->x_pos)
491 slid->x_pos = 0;
492 if(slid->y_units < slid->y_pos)
493 slid->y_pos = 0;
494 gemtk_wm_update_slider(rootwin->win, GEMTK_WM_VH_SLIDER);
495 }
496
497 /* set focus to an arbitary element */
window_set_focus(struct s_gui_win_root * rootwin,enum focus_element_type type,void * element)498 void window_set_focus(struct s_gui_win_root *rootwin,
499 enum focus_element_type type, void * element)
500 {
501 assert(rootwin != NULL);
502
503 if (rootwin->focus.type != type || rootwin->focus.element != element) {
504 NSLOG(netsurf, INFO, "Set focus: %p (%d)\n", element, type);
505 rootwin->focus.type = type;
506 rootwin->focus.element = element;
507 switch( type ) {
508
509 case URL_WIDGET:
510 // TODO: make something like: toolbar_text_select_all();
511 toolbar_key_input(rootwin->toolbar, (short)(NKF_CTRL | 'A') );
512 /*
513 ta = toolbar_get_textarea(rootwin->toolbar,
514 URL_INPUT_TEXT_AREA);
515 textarea_keypress(ta, NS_KEY_SELECT_ALL);
516 */
517 break;
518
519 case SEARCH_INPUT:
520 gemtk_wm_set_toolbar_edit_obj(rootwin->win, TOOLBAR_TB_SRCH, 0);
521 break;
522
523 default:
524 break;
525
526 }
527 }
528 }
529
530 /* check if the url widget has focus */
window_url_widget_has_focus(struct s_gui_win_root * rootwin)531 bool window_url_widget_has_focus(struct s_gui_win_root *rootwin)
532 {
533 assert(rootwin != NULL);
534
535 if (rootwin->focus.type == URL_WIDGET) {
536 return true;
537 }
538 return false;
539 }
540
541 /* check if an arbitary window widget / or frame has the focus */
window_widget_has_focus(struct s_gui_win_root * rootwin,enum focus_element_type t,void * element)542 bool window_widget_has_focus(struct s_gui_win_root *rootwin,
543 enum focus_element_type t, void * element)
544 {
545 assert(rootwin != NULL);
546 if( element == NULL ) {
547 return((rootwin->focus.type == t));
548 }
549
550 return((element == rootwin->focus.element && t == rootwin->focus.type));
551 }
552
window_set_icon(ROOTWIN * rootwin,struct bitmap * bmp)553 void window_set_icon(ROOTWIN *rootwin, struct bitmap * bmp )
554 {
555 rootwin->icon = bmp;
556 /* redraw window when it is iconyfied: */
557 if (rootwin->icon != NULL) {
558 if (gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED) {
559 window_redraw_favicon(rootwin, NULL);
560 }
561 }
562 }
563
window_set_active_gui_window(ROOTWIN * rootwin,struct gui_window * gw)564 void window_set_active_gui_window(ROOTWIN *rootwin, struct gui_window *gw)
565 {
566 struct gui_window *old_gw = rootwin->active_gui_window;
567
568 NSLOG(netsurf, INFO, "gw %p", gw);
569
570 if (rootwin->active_gui_window != NULL) {
571 if(rootwin->active_gui_window == gw) {
572 NSLOG(netsurf, INFO, "nothing to do...");
573 return;
574 }
575 }
576
577 // TODO: when the window isn't on top, initiate WM_TOPPED.
578
579 rootwin->active_gui_window = gw;
580 if (old_gw != NULL) {
581 NSLOG(netsurf, INFO, "restoring window...");
582 window_restore_active_gui_window(rootwin);
583 }
584 }
585
window_get_active_gui_window(ROOTWIN * rootwin)586 struct gui_window * window_get_active_gui_window(ROOTWIN * rootwin)
587 {
588 return(rootwin->active_gui_window);
589 }
590
window_get_scroll(ROOTWIN * rootwin,int * x,int * y)591 void window_get_scroll(ROOTWIN *rootwin, int *x, int *y)
592 {
593 struct gemtk_wm_scroll_info_s *slid;
594
595 slid = gemtk_wm_get_scroll_info(rootwin->win);
596
597 *x = slid->x_pos * slid->x_unit_px;
598 *y = slid->y_pos * slid->y_unit_px;
599 }
600
window_get_grect(ROOTWIN * rootwin,enum browser_area_e which,GRECT * d)601 void window_get_grect(ROOTWIN *rootwin, enum browser_area_e which, GRECT *d)
602 {
603
604 d->g_x = 0;
605 d->g_y = 0;
606 d->g_w = 0;
607 d->g_h = 0;
608
609 if (which == BROWSER_AREA_TOOLBAR) {
610 // gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_TOOLBAR, d);
611 toolbar_get_grect(rootwin->toolbar, 0, d);
612
613 } else if (which == BROWSER_AREA_CONTENT) {
614
615 GRECT tb_area;
616
617 gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, d);
618 toolbar_get_grect(rootwin->toolbar, 0, &tb_area);
619
620 d->g_y += tb_area.g_h;
621 d->g_h -= tb_area.g_h;
622
623 } else if (which == BROWSER_AREA_URL_INPUT) {
624
625 toolbar_get_grect(rootwin->toolbar, TOOLBAR_AREA_URL, d);
626
627 } else if (which == BROWSER_AREA_SEARCH) {
628 // todo: check if search is visible
629 toolbar_get_grect(rootwin->toolbar, TOOLBAR_AREA_SEARCH, d);
630 } else {
631
632 }
633
634
635 // sanitize the results
636 if (d->g_h < 0) {
637 d->g_h = 0;
638 }
639 if (d->g_w < 0) {
640 d->g_w = 0;
641 }
642
643 //printf("window_get_grect %d:", which);
644 //dbg_grect("", d);
645
646 }
647
648
window_open_search(ROOTWIN * rootwin,bool reformat)649 void window_open_search(ROOTWIN *rootwin, bool reformat)
650 {
651 struct browser_window *bw;
652 struct gui_window *gw;
653 GRECT area;
654 OBJECT *obj;
655
656 NSLOG(netsurf, INFO, "rootwin %p", rootwin);
657
658 gw = rootwin->active_gui_window;
659 bw = gw->browser->bw;
660 obj = toolbar_get_form(rootwin->toolbar);
661
662 if (gw->search == NULL) {
663 gw->search = nsatari_search_session_create(obj, gw);
664 }
665
666 toolbar_set_visible(rootwin->toolbar, TOOLBAR_AREA_SEARCH, true);
667 window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &area);
668 gemtk_wm_set_toolbar_size(rootwin->win, area.g_h);
669 window_get_grect(rootwin, BROWSER_AREA_SEARCH, &area);
670 window_schedule_redraw_grect(rootwin, &area);
671 window_process_redraws(rootwin);
672 window_set_focus(rootwin, SEARCH_INPUT, NULL);
673
674 window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area);
675 if (reformat) {
676 browser_window_reformat(bw, false, area.g_w, area.g_h);
677 }
678 }
679
window_close_search(ROOTWIN * rootwin)680 void window_close_search(ROOTWIN *rootwin)
681 {
682 struct browser_window *bw;
683 struct gui_window *gw;
684 GRECT area;
685 //OBJECT *obj;
686
687
688 gw = rootwin->active_gui_window;
689 bw = gw->browser->bw;
690 //obj = gemtk_obj_get_tree(TOOLBAR);
691
692 if (gw->search != NULL) {
693 nsatari_search_session_destroy(gw->search);
694 gw->search = NULL;
695 }
696
697 toolbar_set_visible(rootwin->toolbar, TOOLBAR_AREA_SEARCH, false);
698 window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &area);
699 gemtk_wm_set_toolbar_size(rootwin->win, area.g_h);
700 window_get_grect(rootwin, BROWSER_AREA_CONTENT, &area);
701 browser_window_reformat(bw, false, area.g_w, area.g_h);
702 }
703
704 /**
705 * Redraw the favicon
706 */
window_redraw_favicon(ROOTWIN * rootwin,GRECT * clip_ro)707 void window_redraw_favicon(ROOTWIN *rootwin, GRECT *clip_ro)
708 {
709 GRECT work, visible, clip;
710
711 assert(rootwin);
712
713 //printf("window_redraw_favicon: root: %p, win: %p\n", rootwin, rootwin->win);
714
715 gemtk_wm_clear(rootwin->win);
716 gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work);
717
718 if (clip_ro == NULL) {
719 clip = work;
720 } else {
721 clip = *clip_ro;
722 if(!rc_intersect(&work, &clip)) {
723 return;
724 }
725 }
726
727 //dbg_grect("favicon redrw area", clip);
728 //dbg_grect("favicon work area", &work);
729
730 if (rootwin->icon == NULL) {
731 //printf("window_redraw_favicon OBJCTREE\n");
732
733 OBJECT * tree = gemtk_obj_get_tree(ICONIFY);
734 tree->ob_x = work.g_x;
735 tree->ob_y = work.g_y;
736 tree->ob_width = work.g_w;
737 tree->ob_height = work.g_h;
738
739 wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible);
740 while (visible.g_h > 0 && visible.g_w > 0) {
741
742 if (rc_intersect(&clip, &visible)) {
743 //dbg_grect("redraw vis area", &visible);
744 objc_draw(tree, 0, 8, visible.g_x, visible.g_y, visible.g_w,
745 visible.g_h);
746 } else {
747 //dbg_grect("redraw vis area outside", &visible);
748 }
749
750 wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible);
751 }
752
753 } else {
754 //printf("window_redraw_favicon image %p\n", rootwin->icon);
755 VdiHdl plot_vdi_handle = plot_get_vdi_handle();
756 short pxy[4];
757 int xoff=0;
758
759 if (work.g_w > work.g_h) {
760 xoff = ((work.g_w-work.g_h)/2);
761 work.g_w = work.g_h;
762 }
763 plot_set_dimensions(&rootwin_rdrw_ctx,
764 work.g_x+xoff,
765 work.g_y,
766 work.g_w,
767 work.g_h);
768
769 wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible);
770 while (visible.g_h > 0 && visible.g_w > 0) {
771
772 if (rc_intersect(&clip, &visible)) {
773
774 //dbg_grect("redraw vis area", &visible);
775
776 // Manually clip drawing region:
777 pxy[0] = visible.g_x;
778 pxy[1] = visible.g_y;
779 pxy[2] = pxy[0] + visible.g_w-1;
780 pxy[3] = pxy[1] + visible.g_h-1;
781 vs_clip(plot_vdi_handle, 1, (short*)&pxy);
782 //dbg_pxy("vdi clip", (short*)&pxy);
783
784 rootwin_rdrw_ctx.plot->bitmap(&rootwin_rdrw_ctx,
785 rootwin->icon,
786 0,
787 0,
788 work.g_w,
789 work.g_h,
790 0xffffff,
791 0);
792 } else {
793 //dbg_grect("redraw vis area outside", &visible);
794 }
795
796 wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible);
797 }
798 }
799 }
800
801 /***
802 * Schedule an redraw area, redraw requests during redraw are
803 * not optimized (merged) into other areas, so that the redraw
804 * functions can spot the change.
805 *
806 */
window_schedule_redraw_grect(ROOTWIN * rootwin,GRECT * area)807 void window_schedule_redraw_grect(ROOTWIN *rootwin, GRECT *area)
808 {
809 GRECT work;
810
811
812 //dbg_grect("window_schedule_redraw_grect input ", area);
813
814 gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work);
815 if(!rc_intersect(area, &work))
816 return;
817
818 //dbg_grect("window_schedule_redraw_grect intersection ", &work);
819
820 redraw_slot_schedule_grect(&rootwin->redraw_slots, &work, redraw_active);
821 }
822
window_redraw_content(ROOTWIN * rootwin,GRECT * content_area,GRECT * clip,struct gemtk_wm_scroll_info_s * slid,struct browser_window * bw)823 static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area,
824 GRECT *clip,
825 struct gemtk_wm_scroll_info_s * slid,
826 struct browser_window *bw)
827 {
828
829 struct rect redraw_area;
830 GRECT content_area_rel;
831 float oldscale = 1.0;
832
833 //dbg_grect("browser redraw, content area", content_area);
834 //dbg_grect("browser redraw, content clip", clip);
835
836 plot_set_dimensions(&rootwin_rdrw_ctx,
837 content_area->g_x, content_area->g_y,
838 content_area->g_w, content_area->g_h);
839 oldscale = plot_set_scale(browser_window_get_scale(rootwin->active_gui_window->browser->bw));
840
841 /* first, we make the coords relative to the content area: */
842 content_area_rel.g_x = clip->g_x - content_area->g_x;
843 content_area_rel.g_y = clip->g_y - content_area->g_y;
844 content_area_rel.g_w = clip->g_w;
845 content_area_rel.g_h = clip->g_h;
846
847 if (content_area_rel.g_x < 0) {
848 content_area_rel.g_w += content_area_rel.g_x;
849 content_area_rel.g_x = 0;
850 }
851
852 if (content_area_rel.g_y < 0) {
853 content_area_rel.g_h += content_area_rel.g_y;
854 content_area_rel.g_y = 0;
855 }
856
857 //dbg_grect("browser redraw, relative plot coords:", &content_area_rel);
858
859 redraw_area.x0 = content_area_rel.g_x;
860 redraw_area.y0 = content_area_rel.g_y;
861 redraw_area.x1 = content_area_rel.g_x + content_area_rel.g_w;
862 redraw_area.y1 = content_area_rel.g_y + content_area_rel.g_h;
863
864 rootwin_rdrw_ctx.plot->clip(&rootwin_rdrw_ctx, &redraw_area);
865
866 //dbg_rect("rdrw area", &redraw_area);
867
868 browser_window_redraw( bw, -(slid->x_pos*slid->x_unit_px),
869 -(slid->y_pos*slid->y_unit_px), &redraw_area, &rootwin_rdrw_ctx);
870
871 plot_set_scale(oldscale);
872 }
873
874
window_place_caret(ROOTWIN * rootwin,short mode,int content_x,int content_y,int h,GRECT * work)875 void window_place_caret(ROOTWIN *rootwin, short mode, int content_x,
876 int content_y, int h, GRECT *work)
877 {
878 struct s_caret *caret = &rootwin->caret;
879 VdiHdl vh = gemtk_wm_get_vdi_handle(rootwin->win);
880 short pxy[8];
881 GRECT mywork, caret_pos;
882 MFDB screen;
883 int scroll_x, scroll_y;
884 uint16_t *fd_addr;
885 struct gemtk_wm_scroll_info_s *slid;
886 short colors[2] = {G_BLACK, G_WHITE};
887 bool render_required = false;
888
889 // avoid duplicate draw of the caret:
890 if (mode == 1 &&(caret->state&CARET_STATE_VISIBLE)!=0) {
891 if (caret->dimensions.g_x == content_x
892 && caret->dimensions.g_y == content_y
893 && caret->dimensions.g_h == h) {
894 return;
895 }
896 }
897
898 if(work == NULL) {
899 window_get_grect(rootwin, BROWSER_AREA_CONTENT, &mywork);
900 work = &mywork;
901 }
902 slid = gemtk_wm_get_scroll_info(rootwin->win);
903
904 scroll_x = slid->x_pos * slid->x_unit_px;
905 scroll_y = slid->y_pos * slid->y_unit_px;
906
907 init_mfdb(0, 1, h, 0, &screen);
908
909 // enable clipping:
910 pxy[0] = work->g_x;
911 pxy[1] = work->g_y;
912 pxy[2] = pxy[0] + work->g_w - 1;
913 pxy[3] = pxy[1] + work->g_h - 1;
914 vs_clip(vh, 1, pxy);
915
916 // when the caret is visible, undraw it:
917 if (caret->symbol.fd_addr != NULL
918 && (caret->state&CARET_STATE_VISIBLE)!=0) {
919
920 caret_pos.g_x = work->g_x + (caret->dimensions.g_x - scroll_x);
921 caret_pos.g_y = work->g_y + (caret->dimensions.g_y - scroll_y);
922 caret_pos.g_w = caret->dimensions.g_w;
923 caret_pos.g_h = caret->dimensions.g_h;
924
925 if (rc_intersect(work, &caret_pos)) {
926
927 pxy[0] = 0;
928 pxy[1] = 0;
929 pxy[2] = caret->dimensions.g_w-1;
930 pxy[3] = caret->dimensions.g_h-1;
931
932 pxy[4] = caret_pos.g_x;
933 pxy[5] = caret_pos.g_y;
934 pxy[6] = pxy[4] + caret_pos.g_w-1;
935 pxy[7] = pxy[5] + caret_pos.g_h-1;
936
937 vrt_cpyfm(vh, MD_XOR, pxy, &caret->symbol, &screen, colors);
938 }
939 }
940 if (mode == 0) {
941 // update state:
942 caret->state &= ~CARET_STATE_VISIBLE;
943 goto exit;
944 }
945
946 // when the caret isn't allocated, create it:
947 if (caret->symbol.fd_addr == NULL) {
948 caret->fd_size = init_mfdb(1, 16, h, MFDB_FLAG_ZEROMEM,
949 &caret->symbol);
950 render_required = true;
951 } else {
952 // the caret may need more memory:
953 if (caret->dimensions.g_h < h) {
954 caret->fd_size = init_mfdb(1, 16, h, MFDB_FLAG_NOALLOC,
955 &caret->symbol);
956 realloc(caret->symbol.fd_addr, caret->fd_size);
957 render_required = true;
958 }
959 }
960
961 // set new caret position:
962 caret->dimensions.g_x = content_x;
963 caret->dimensions.g_y = content_y;
964 caret->dimensions.g_w = 1;
965 caret->dimensions.g_h = h;
966
967 // draw the caret into the mfdb buffer:
968 if (render_required) {
969 int i;
970
971 assert(caret->symbol.fd_nplanes == 1);
972 assert(caret->symbol.fd_w == 16);
973
974 // draw an vertical line into the mfdb buffer
975 fd_addr = (uint16_t*)caret->symbol.fd_addr;
976 for(i = 0; i<caret->symbol.fd_h; i++) {
977 fd_addr[i] = 0xFFFF;
978 }
979 }
980
981 // convert content coords to screen coords:
982
983 caret_pos.g_x = work->g_x + (content_x - scroll_x);
984 caret_pos.g_y = work->g_y + (content_y - scroll_y);
985 caret_pos.g_w = caret->dimensions.g_w;
986 caret_pos.g_h = caret->dimensions.g_h;
987
988 if (rc_intersect(work, &caret_pos) && redraw_active == false) {
989
990 pxy[0] = 0;
991 pxy[1] = 0;
992 pxy[2] = caret->dimensions.g_w-1;
993 pxy[3] = caret->dimensions.g_h-1;
994
995 pxy[4] = caret_pos.g_x;
996 pxy[5] = caret_pos.g_y;
997 pxy[6] = pxy[4] + caret_pos.g_w-1;
998 pxy[7] = pxy[5] + caret_pos.g_h-1;
999
1000 //dbg_pxy("caret screen coords (md_repl)", &pxy[4]);
1001
1002 // TODO: walk rectangle list (use MD_REPLACE then)
1003 // draw caret to screen coords:
1004 vrt_cpyfm(vh, /*MD_REPLACE*/ MD_XOR, pxy, &caret->symbol, &screen, colors);
1005
1006 // update state:
1007 caret->state |= CARET_STATE_VISIBLE;
1008 }
1009
1010 exit:
1011 // disable clipping:
1012 vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 0, pxy);
1013 }
1014
window_process_redraws(ROOTWIN * rootwin)1015 void window_process_redraws(ROOTWIN * rootwin)
1016 {
1017 GRECT visible_ro, tb_area, content_area;
1018 short i;
1019 short scroll_x=0, scroll_y=0;
1020 bool caret_rdrw_required = false;
1021 struct gemtk_wm_scroll_info_s *slid =NULL;
1022 int caret_h = 0;
1023 struct s_caret *caret = &rootwin->caret;
1024
1025 redraw_active = true;
1026
1027 window_get_grect(rootwin, BROWSER_AREA_TOOLBAR, &tb_area);
1028 //gemtk_wm_set_toolbar_size(rootwin->win, tb_area.g_h);
1029 window_get_grect(rootwin, BROWSER_AREA_CONTENT, &content_area);
1030
1031 //dbg_grect("content area", &content_area);
1032 //dbg_grect("window_process_redraws toolbar area", &tb_area);
1033
1034 while(plot_lock() == false);
1035
1036 if (((rootwin->caret.state & CARET_STATE_ENABLED)!=0)
1037 && rootwin->caret.dimensions.g_h > 0) {
1038 // hide caret:
1039 window_place_caret(rootwin, 0, -1, -1, -1, &content_area);
1040 }
1041 /*
1042 short pxy_clip[4];
1043 pxy_clip[0] = tb_area.g_x;
1044 pxy_clip[0] = tb_area.g_y;
1045 pxy_clip[0] = pxy_clip[0] + tb_area.g_w + content_area.g_w - 1;
1046 pxy_clip[0] = pxy_clip[1] + tb_area.g_h + content_area.g_h - 1;
1047 vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 1, pxy_clip);
1048 //gemtk_wm_clear(rootwin->win);
1049 */
1050 wind_get_grect(rootwin->aes_handle, WF_FIRSTXYWH, &visible_ro);
1051 while (visible_ro.g_w > 0 && visible_ro.g_h > 0) {
1052 plot_set_abs_clipping(&visible_ro);
1053
1054 //dbg_grect("visible ", &visible_ro);
1055
1056 // TODO: optimze the rectangle list -
1057 // remove rectangles which were completly inside the visible area.
1058 // that way we don't have to loop over again...
1059 for(i=0; i<rootwin->redraw_slots.areas_used; i++) {
1060
1061 GRECT rdrw_area_ro = {
1062 rootwin->redraw_slots.areas[i].x0,
1063 rootwin->redraw_slots.areas[i].y0,
1064 rootwin->redraw_slots.areas[i].x1 -
1065 rootwin->redraw_slots.areas[i].x0,
1066 rootwin->redraw_slots.areas[i].y1 -
1067 rootwin->redraw_slots.areas[i].y0
1068 };
1069
1070 if (!rc_intersect(&visible_ro, &rdrw_area_ro)) {
1071 continue;
1072 }
1073 GRECT rdrw_area = rdrw_area_ro;
1074
1075 if (rc_intersect(&tb_area, &rdrw_area)) {
1076 toolbar_redraw(rootwin->toolbar, &rdrw_area);
1077 }
1078
1079 rdrw_area = rdrw_area_ro;
1080 if (rc_intersect(&content_area, &rdrw_area)) {
1081
1082 if(slid == NULL) {
1083 slid = gemtk_wm_get_scroll_info(rootwin->win);
1084
1085 scroll_x = slid->x_pos * slid->x_unit_px;
1086 scroll_y = slid->y_pos * slid->y_unit_px;
1087 }
1088
1089 window_redraw_content(rootwin, &content_area, &rdrw_area,
1090 slid,
1091 rootwin->active_gui_window->browser->bw);
1092 if (((rootwin->caret.state & CARET_STATE_ENABLED)!=0)) {
1093
1094 GRECT caret_pos;
1095
1096 caret_pos.g_x = content_area.g_x +
1097 (caret->dimensions.g_x - scroll_x);
1098 caret_pos.g_y = content_area.g_y +
1099 (caret->dimensions.g_y - scroll_y);
1100 caret_pos.g_w = caret->dimensions.g_w;
1101 caret_pos.g_h = caret->dimensions.g_h;
1102
1103 if (gemtk_rc_intersect_ro(&caret_pos, &content_area)) {
1104 caret_rdrw_required = true;
1105 }
1106 }
1107
1108 }
1109 }
1110 wind_get_grect(rootwin->aes_handle, WF_NEXTXYWH, &visible_ro);
1111 }
1112
1113
1114 // disable clipping:
1115 //vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 0, pxy_clip);
1116
1117 if (caret_rdrw_required && ((rootwin->caret.state & CARET_STATE_ENABLED)!=0)) {
1118
1119 // force redraw of caret:
1120 caret_h = rootwin->caret.dimensions.g_h;
1121 rootwin->caret.dimensions.g_h = 0;
1122 redraw_active = false;
1123 window_place_caret(rootwin, 1, rootwin->caret.dimensions.g_x,
1124 rootwin->caret.dimensions.g_y,
1125 caret_h, &content_area);
1126 }
1127
1128 rootwin->redraw_slots.areas_used = 0;
1129 redraw_active = false;
1130
1131 plot_unlock();
1132 }
1133
1134
1135 /* -------------------------------------------------------------------------- */
1136 /* Event Handlers: */
1137 /* -------------------------------------------------------------------------- */
on_content_mouse_move(ROOTWIN * rootwin,GRECT * content_area)1138 static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area)
1139 {
1140 int mx, my, sx, sy;
1141 struct gemtk_wm_scroll_info_s *slid;
1142 struct gui_window *gw;
1143 struct browser_window *bw;
1144
1145 // make relative mouse coords:
1146 mx = aes_event_out.emo_mouse.p_x - content_area->g_x;
1147 my = aes_event_out.emo_mouse.p_y - content_area->g_y;
1148
1149 slid = gemtk_wm_get_scroll_info(rootwin->win);
1150 gw = window_get_active_gui_window(rootwin);
1151 bw = gw->browser->bw;
1152
1153 // calculate scroll pos. in pixel:
1154 sx = slid->x_pos * slid->x_unit_px;
1155 sy = slid->y_pos * slid->y_unit_px;
1156
1157 browser_window_mouse_track(bw, 0, mx + sx, my + sy);
1158 }
1159
on_content_mouse_click(ROOTWIN * rootwin)1160 static void on_content_mouse_click(ROOTWIN *rootwin)
1161 {
1162 short dummy, mbut, mx, my;
1163 GRECT cwork;
1164 browser_mouse_state bmstate = 0;
1165 struct gui_window *gw;
1166 struct gemtk_wm_scroll_info_s *slid;
1167
1168 gw = window_get_active_gui_window(rootwin);
1169 if(input_window != gw) {
1170 gui_set_input_gui_window(gw);
1171 }
1172
1173 window_set_focus(gw->root, BROWSER, (void*)gw->browser );
1174 window_get_grect(gw->root, BROWSER_AREA_CONTENT, &cwork);
1175
1176 /* convert screen coords to component coords: */
1177 mx = aes_event_out.emo_mouse.p_x - cwork.g_x;
1178 my = aes_event_out.emo_mouse.p_y - cwork.g_y;
1179 //printf("content click at %d,%d\n", mx, my);
1180
1181 /* Translate GEM key state to netsurf mouse modifier */
1182 if ( aes_event_out.emo_kmeta & (K_RSHIFT | K_LSHIFT)) {
1183 bmstate |= BROWSER_MOUSE_MOD_1;
1184 } else {
1185 bmstate &= ~(BROWSER_MOUSE_MOD_1);
1186 }
1187 if ( (aes_event_out.emo_kmeta & K_CTRL) ) {
1188 bmstate |= BROWSER_MOUSE_MOD_2;
1189 } else {
1190 bmstate &= ~(BROWSER_MOUSE_MOD_2);
1191 }
1192 if ( (aes_event_out.emo_kmeta & K_ALT) ) {
1193 bmstate |= BROWSER_MOUSE_MOD_3;
1194 } else {
1195 bmstate &= ~(BROWSER_MOUSE_MOD_3);
1196 }
1197
1198 /* convert component coords to scrolled content coords: */
1199 slid = gemtk_wm_get_scroll_info(rootwin->win);
1200 int sx_origin = mx;
1201 int sy_origin = my;
1202
1203 short rel_cur_x, rel_cur_y;
1204 short prev_x=sx_origin, prev_y=sy_origin;
1205 bool dragmode = false;
1206
1207 /* Detect left mouse button state and compare with event state: */
1208 graf_mkstate(&rel_cur_x, &rel_cur_y, &mbut, &dummy);
1209 if( (mbut & 1) && (aes_event_out.emo_mbutton & 1) ) {
1210 /* Mouse still pressed, report drag */
1211 rel_cur_x = (rel_cur_x - cwork.g_x);
1212 rel_cur_y = (rel_cur_y - cwork.g_y);
1213 browser_window_mouse_click( gw->browser->bw,
1214 BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_DRAG_1,
1215 rel_cur_x + slid->x_pos * slid->x_unit_px,
1216 rel_cur_y + slid->y_pos * slid->y_unit_px);
1217 do {
1218 // only consider movements of 5px or more as drag...:
1219 if( abs(prev_x-rel_cur_x) > 5 || abs(prev_y-rel_cur_y) > 5 ) {
1220 browser_window_mouse_track( gw->browser->bw,
1221 BROWSER_MOUSE_DRAG_ON|BROWSER_MOUSE_DRAG_1,
1222 rel_cur_x + slid->x_pos * slid->x_unit_px,
1223 rel_cur_y + slid->y_pos * slid->y_unit_px);
1224 prev_x = rel_cur_x;
1225 prev_y = rel_cur_y;
1226 dragmode = true;
1227 } else {
1228 if( dragmode == false ) {
1229 browser_window_mouse_track( gw->browser->bw,BROWSER_MOUSE_PRESS_1,
1230 rel_cur_x + slid->x_pos * slid->x_unit_px,
1231 rel_cur_y + slid->y_pos * slid->y_unit_px);
1232 }
1233 }
1234
1235 // we may need to process scrolling:
1236 // TODO: this doesn't work, because gemtk schedules redraw via
1237 // AES window messages but we do not process them right here...
1238 if (rootwin->redraw_slots.areas_used > 0) {
1239 window_process_redraws(rootwin);
1240 }
1241 evnt_timer(150);
1242
1243 graf_mkstate(&rel_cur_x, &rel_cur_y, &mbut, &dummy);
1244 rel_cur_x = (rel_cur_x - cwork.g_x);
1245 rel_cur_y = (rel_cur_y - cwork.g_y);
1246 } while( mbut & 1 );
1247 browser_window_mouse_track(gw->browser->bw, 0,
1248 rel_cur_x + slid->x_pos * slid->x_unit_px,
1249 rel_cur_y + slid->y_pos * slid->y_unit_px);
1250 } else {
1251 /* Right button pressed? */
1252 if ((aes_event_out.emo_mbutton & 2 ) ) {
1253 context_popup(gw, aes_event_out.emo_mouse.p_x,
1254 aes_event_out.emo_mouse.p_y);
1255 } else {
1256 browser_window_mouse_click(gw->browser->bw,
1257 bmstate|BROWSER_MOUSE_PRESS_1,
1258 sx_origin + slid->x_pos * slid->x_unit_px,
1259 sy_origin + slid->y_pos * slid->y_unit_px);
1260 browser_window_mouse_click(gw->browser->bw,
1261 bmstate|BROWSER_MOUSE_CLICK_1,
1262 sx_origin + slid->x_pos * slid->x_unit_px,
1263 sy_origin + slid->y_pos * slid->y_unit_px);
1264 }
1265 }
1266 if (rootwin->redraw_slots.areas_used > 0) {
1267 window_process_redraws(rootwin);
1268 }
1269 }
1270
1271 /*
1272 Report keypress to browser component.
1273 parameter:
1274 - unsigned short nkc ( CFLIB normalised key code )
1275 */
on_content_keypress(struct gui_window * gw,unsigned short nkc)1276 static bool on_content_keypress(struct gui_window *gw, unsigned short nkc)
1277 {
1278 bool r = false;
1279 unsigned char ascii = (nkc & 0xFF);
1280 long ucs4;
1281 long ik = nkc_to_input_key( nkc, &ucs4 );
1282
1283 // pass event to specific control?
1284
1285 if (ik == 0) {
1286 if (ascii >= 9) {
1287 r = browser_window_key_press(gw->browser->bw, ucs4);
1288 }
1289 } else {
1290 r = browser_window_key_press(gw->browser->bw, ik);
1291 if (r == false) {
1292
1293 GRECT g;
1294 GUIWIN * w = gw->root->win;
1295 window_get_grect(gw->root, BROWSER_AREA_CONTENT, &g);
1296
1297 struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(w);
1298
1299 switch( ik ) {
1300 case NS_KEY_LINE_START:
1301 gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, -(g.g_w/slid->x_unit_px),
1302 false);
1303 r = true;
1304 break;
1305
1306 case NS_KEY_LINE_END:
1307 gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, (g.g_w/slid->x_unit_px),
1308 false);
1309 r = true;
1310 break;
1311
1312 case NS_KEY_PAGE_UP:
1313 gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, -(g.g_h/slid->y_unit_px),
1314 false);
1315 r = true;
1316 break;
1317
1318 case NS_KEY_PAGE_DOWN:
1319 gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, (g.g_h/slid->y_unit_px),
1320 false);
1321 r = true;
1322 break;
1323
1324 case NS_KEY_RIGHT:
1325 gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, -1, false);
1326 r = true;
1327 break;
1328
1329 case NS_KEY_LEFT:
1330 gemtk_wm_scroll(w, GEMTK_WM_HSLIDER, 1, false);
1331 r = true;
1332 break;
1333
1334 case NS_KEY_UP:
1335 gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, -1, false);
1336 r = true;
1337 break;
1338
1339 case NS_KEY_DOWN:
1340 gemtk_wm_scroll(w, GEMTK_WM_VSLIDER, 1, false);
1341 r = true;
1342 break;
1343
1344 case NS_KEY_TEXT_START:
1345 window_scroll_by(gw->root, 0, 0);
1346 r = true;
1347 break;
1348
1349 default:
1350 break;
1351 }
1352 gemtk_wm_update_slider(w, GEMTK_WM_VSLIDER|GEMTK_WM_HSLIDER);
1353 }
1354 }
1355
1356 return(r);
1357 }
1358
on_window_key_input(ROOTWIN * rootwin,unsigned short nkc)1359 static short on_window_key_input(ROOTWIN *rootwin, unsigned short nkc)
1360 {
1361 bool done = false;
1362 struct gui_window * gw = window_get_active_gui_window(rootwin);
1363
1364 if( gw == NULL )
1365 return(false);
1366
1367 if(window_url_widget_has_focus((void*)gw->root)) {
1368 /* make sure we report for the root window and report...: */
1369 done = toolbar_key_input(gw->root->toolbar, nkc);
1370 } else {
1371 if( window_widget_has_focus(input_window->root, BROWSER,
1372 (void*)input_window->browser)) {
1373 done = on_content_keypress(input_window, nkc);
1374 }
1375 else if(window_widget_has_focus(input_window->root, SEARCH_INPUT, NULL)) {
1376 OBJECT * obj;
1377 obj = toolbar_get_form(input_window->root->toolbar);
1378 obj[TOOLBAR_BT_SEARCH_FWD].ob_state &= ~OS_DISABLED;
1379 obj[TOOLBAR_BT_SEARCH_BACK].ob_state &= ~OS_DISABLED;
1380 window_schedule_redraw_grect(input_window->root,
1381 gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_FWD));
1382 window_schedule_redraw_grect(input_window->root,
1383 gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_BACK));
1384 }
1385 }
1386 return((done==true) ? 1 : 0);
1387 }
1388
1389
on_redraw(ROOTWIN * rootwin,short msg[8])1390 static void on_redraw(ROOTWIN *rootwin, short msg[8])
1391 {
1392 GRECT clip = {msg[4], msg[5], msg[6], msg[7]};
1393
1394 //dbg_grect("on_redraw", &clip);
1395
1396 if(gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED) {
1397 // TODO: remove asignment:
1398 window_redraw_favicon(rootwin, NULL);
1399 } else {
1400 window_schedule_redraw_grect(rootwin, &clip);
1401 }
1402 }
1403
on_resized(ROOTWIN * rootwin)1404 static void on_resized(ROOTWIN *rootwin)
1405 {
1406 GRECT g, work;
1407 struct gui_window *gw;
1408
1409 gw = window_get_active_gui_window(rootwin);
1410
1411 //printf("resized...\n");
1412
1413 assert(gw != NULL);
1414
1415 if(gw == NULL)
1416 return;
1417
1418 wind_get_grect(rootwin->aes_handle, WF_CURRXYWH, &g);
1419 gemtk_wm_get_grect(rootwin->win, GEMTK_WM_AREA_WORK, &work);
1420
1421 if (rootwin->loc.g_w != g.g_w || rootwin->loc.g_h != g.g_h) {
1422
1423 /* resized */
1424 toolbar_set_width(rootwin->toolbar, work.g_w);
1425
1426 if ( browser_window_has_content(gw->browser->bw) ) {
1427 browser_window_reformat(gw->browser->bw, true, work.g_w, work.g_h);
1428 }
1429 }
1430 if (rootwin->loc.g_x != g.g_x || rootwin->loc.g_y != g.g_y) {
1431 /* moved */
1432 toolbar_set_origin(rootwin->toolbar, work.g_x, work.g_y);
1433 }
1434
1435 rootwin->loc = g;
1436 }
1437
on_file_dropped(ROOTWIN * rootwin,short msg[8])1438 static void on_file_dropped(ROOTWIN *rootwin, short msg[8])
1439 {
1440 char file[DD_NAMEMAX];
1441 char name[DD_NAMEMAX];
1442 char *buff=NULL;
1443 int dd_hdl;
1444 int dd_msg; /* pipe-handle */
1445 long size;
1446 char ext[32];
1447 short mx,my,bmstat,mkstat;
1448 struct gui_window *gw;
1449
1450 graf_mkstate(&mx, &my, &bmstat, &mkstat);
1451
1452 gw = window_get_active_gui_window(rootwin);
1453
1454 if( gw == NULL )
1455 return;
1456
1457 if(gemtk_wm_get_state(rootwin->win) & GEMTK_WM_STATUS_ICONIFIED)
1458 return;
1459
1460 dd_hdl = gemtk_dd_open( msg[7], DD_OK);
1461 if( dd_hdl<0)
1462 return; /* pipe not open */
1463 memset( ext, 0, 32);
1464 strcpy( ext, "ARGS");
1465 dd_msg = gemtk_dd_sexts( dd_hdl, ext);
1466 if( dd_msg<0)
1467 goto error;
1468 dd_msg = gemtk_dd_rtry( dd_hdl, (char*)&name[0], (char*)&file[0], (char*)&ext[0], &size);
1469 if( size+1 >= PATH_MAX )
1470 goto error;
1471 if( !strncmp( ext, "ARGS", 4) && dd_msg > 0) {
1472 gemtk_dd_reply(dd_hdl, DD_OK);
1473 buff = (char*)malloc(sizeof(char)*(size+1));
1474 if (buff != NULL) {
1475 if (Fread(dd_hdl, size, buff ) == size) {
1476
1477 int sx, sy;
1478 bool processed = false;
1479 GRECT content_area;
1480
1481 buff[size] = 0;
1482
1483 NSLOG(netsurf, INFO,
1484 "file: %s, ext: %s, size: %ld dropped at: %d,%d\n",
1485 (char *)buff,
1486 (char *)&ext,
1487 size,
1488 mx,
1489 my);
1490
1491 gui_window_get_scroll(gw, &sx, &sy);
1492
1493 window_get_grect(rootwin, BROWSER_AREA_CONTENT, &content_area);
1494 mx = mx - content_area.g_x;
1495 my = my - content_area.g_y;
1496 if((mx < 0 || mx > content_area.g_w)
1497 || (my < 0 || my > content_area.g_h))
1498 return;
1499
1500 processed = browser_window_drop_file_at_point(gw->browser->bw,
1501 mx+sx, my+sy,
1502 NULL);
1503 if(processed == true) {
1504 nserror ret;
1505 char *utf8_fn;
1506
1507 ret = utf8_from_local_encoding(buff, 0, &utf8_fn);
1508 if (ret != NSERROR_OK) {
1509 free(buff);
1510 /* A bad encoding should never happen */
1511 NSLOG(netsurf, INFO,
1512 "utf8_from_local_encoding failed");
1513 assert(ret != NSERROR_BAD_ENCODING);
1514 /* no memory */
1515 goto error;
1516 }
1517 processed = browser_window_drop_file_at_point(gw->browser->bw,
1518 mx+sx, my+sy,
1519 utf8_fn);
1520 free(utf8_fn);
1521 }
1522
1523 if(processed == false) {
1524 // TODO: use localized string:
1525 if(gemtk_msg_box_show(GEMTK_MSG_BOX_CONFIRM, "Open File?") > 0) {
1526 nsurl * ns_url = NULL;
1527 char * tmp_url = local_file_to_url(buff);
1528 if ((tmp_url != NULL)
1529 && nsurl_create(tmp_url, &ns_url) == NSERROR_OK) {
1530 browser_window_navigate(gw->browser->bw, ns_url, NULL,
1531 BW_NAVIGATE_HISTORY,
1532 NULL, NULL, NULL);
1533 nsurl_unref(ns_url);
1534 }
1535 }
1536 }
1537 }
1538 }
1539 }
1540 error:
1541 if (buff) {
1542 free(buff);
1543 }
1544 gemtk_dd_close( dd_hdl);
1545 }
1546
toolbar_redraw_cb(GUIWIN * win,uint16_t msg,GRECT * clip)1547 static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip)
1548 {
1549 struct rootwin_data_s * ud;
1550
1551 if (msg != WM_REDRAW) {
1552 ud = gemtk_wm_get_user_data(win);
1553
1554 assert(ud);
1555
1556 toolbar_redraw(ud->rootwin->toolbar, clip);
1557 }
1558 }
1559