NetSurf
rootwin.c
Go to the documentation of this file.
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"
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
64extern struct gui_window *input_window;
65extern EVMULT_OUT aes_event_out;
66extern GRECT desk_area;
67
70};
71
72/* -------------------------------------------------------------------------- */
73/* Static module event handlers */
74/* -------------------------------------------------------------------------- */
75static void on_redraw(ROOTWIN *rootwin, short msg[8]);
76static void on_resized(ROOTWIN *rootwin);
77static void on_file_dropped(ROOTWIN *rootwin, short msg[8]);
78static short on_window_key_input(ROOTWIN * rootwin, unsigned short nkc);
79static void on_content_mouse_click(ROOTWIN *rootwin);
80static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area);
81static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip);
82
83bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy);
84
85static bool redraw_active = false;
86
87static const struct redraw_context rootwin_rdrw_ctx = {
88 .interactive = true,
89 .background_images = true,
90 .plot = &atari_plotters
91};
92
93static 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");
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",
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);
181 &area);
182 if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
183 area)) {
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.
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;
202 if (POINT_WITHIN(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y,
203 tb_area)) {
205 prev_url = true;
206 } else {
207 if(prev_url) {
208 struct gui_window *gw;
211 prev_url = false;
212 }
213 }
214 }
215 }
216 }
217
218 return(retval);
219}
220
221/* -------------------------------------------------------------------------- */
222/* Module public functions: */
223/* -------------------------------------------------------------------------- */
224
225int 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) );
255
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) {
307 }
308
309 return (err);
310}
311
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);
325 break;
326 }
327 w = w->next;
328 }
329 if(input_window == NULL) {
330 // the last gui window for this rootwin was removed:
332 window_destroy(rootwin);
333 }
334}
335
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
375void 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
400
402}
403
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
427
428 toolbar_set_url(rootwin->toolbar, gw->url);
429}
430
431
432/* update back forward buttons (see tb_update_buttons (bug) ) */
434{
435 struct gui_window * active_gw = rootwin->active_gui_window;
436 toolbar_update_buttons(rootwin->toolbar, active_gw->browser->bw, -1);
437}
438
439void 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
454void window_set_title(struct s_gui_win_root * rootwin, char *title)
455{
456 wind_set_str(rootwin->aes_handle, WF_NAME, title);
457}
458
459void 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*/
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 */
498void 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 */
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 */
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
553void 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
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...");
583 }
584}
585
587{
588 return(rootwin->active_gui_window);
589}
590
591void 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
601void 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
649void 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) {
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
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) {
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*/
707void 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 }
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
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*/
807void 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
821}
822
823static 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
837 content_area->g_x, content_area->g_y,
838 content_area->g_w, content_area->g_h);
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
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
875void 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
1010exit:
1011 // disable clipping:
1012 vs_clip(gemtk_wm_get_vdi_handle(rootwin->win), 0, pxy);
1013}
1014
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/* -------------------------------------------------------------------------- */
1138static 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
1160static 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) {
1171 }
1172
1173 window_set_focus(gw->root, BROWSER, (void*)gw->browser );
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);
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 ) {
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 ) {
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 );
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 {
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);
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*/
1276static 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;
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
1359static 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 {
1372 (void*)input_window->browser)) {
1373 done = on_content_keypress(input_window, nkc);
1374 }
1376 OBJECT * obj;
1378 obj[TOOLBAR_BT_SEARCH_FWD].ob_state &= ~OS_DISABLED;
1379 obj[TOOLBAR_BT_SEARCH_BACK].ob_state &= ~OS_DISABLED;
1381 gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_FWD));
1383 gemtk_obj_screen_rect(obj, TOOLBAR_BT_SEARCH_BACK));
1384 }
1385 }
1386 return((done==true) ? 1 : 0);
1387}
1388
1389
1390static 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 {
1401 }
1402}
1403
1404static 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
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
1438static 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
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 }
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,
1532 NULL, NULL, NULL);
1533 nsurl_unref(ns_url);
1534 }
1535 }
1536 }
1537 }
1538 }
1539 }
1540error:
1541 if (buff) {
1542 free(buff);
1543 }
1544 gemtk_dd_close( dd_hdl);
1545}
1546
1547static 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
1557 }
1558}
static struct MinList * window_list
Definition: gui.c:325
void context_popup(struct gui_window *gw, short x, short y)
Definition: ctxmenu.c:134
char * local_file_to_url(const char *filename)
Definition: findfile.c:29
void gui_set_input_gui_window(struct gui_window *gw)
Definition: gui.c:764
#define CARET_STATE_VISIBLE
Definition: gui.h:34
focus_element_type
Definition: gui.h:80
@ URL_WIDGET
Definition: gui.h:82
@ BROWSER
Definition: gui.h:84
@ SEARCH_INPUT
Definition: gui.h:83
#define CARET_STATE_ENABLED
Definition: gui.h:35
struct s_gem_cursors gem_cursors
#define PATH_MAX
Definition: gui.h:31
void gem_set_cursor(MFORM_EX *cursor)
Definition: misc.c:196
long nkc_to_input_key(short nkc, long *ucs4_out)
Convert NKC to netsurf input key code and/or to ucs4 (depends on keycode).
Definition: misc.c:213
const struct plotter_table atari_plotters
atari plottr operation table
Definition: plot.c:2507
bool plot_lock(void)
Definition: plot.c:1775
float plot_set_scale(float scale)
set scale of plotter.
Definition: plot.c:1854
VdiHdl plot_get_vdi_handle(void)
Definition: plot.c:1918
void plot_set_abs_clipping(const GRECT *area)
Subsequent calls to plot_clip will be clipped by the absolute clip.
Definition: plot.c:1875
bool plot_set_dimensions(const struct redraw_context *ctx, int x, int y, int w, int h)
Set plot origin and canvas size.
Definition: plot.c:1806
bool plot_unlock(void)
Definition: plot.c:1791
void toolbar_set_url(struct s_toolbar *tb, const char *text)
Definition: toolbar.c:584
OBJECT * toolbar_get_form(struct s_toolbar *tb)
Definition: toolbar.c:910
void toolbar_redraw(struct s_toolbar *tb, GRECT *clip)
Definition: toolbar.c:416
struct s_toolbar * toolbar_create(struct s_gui_win_root *owner)
Definition: toolbar.c:267
void toolbar_set_attached(struct s_toolbar *tb, bool attached)
Definition: toolbar.c:643
void toolbar_get_grect(struct s_toolbar *tb, short which, GRECT *dst)
Receive a specific region of the toolbar.
Definition: toolbar.c:854
void toolbar_set_visible(struct s_toolbar *tb, short area, bool visible)
Definition: toolbar.c:616
void toolbar_set_width(struct s_toolbar *tb, short w)
Definition: toolbar.c:528
void toolbar_destroy(struct s_toolbar *tb)
Definition: toolbar.c:337
void toolbar_update_buttons(struct s_toolbar *tb, struct browser_window *bw, short button)
Definition: toolbar.c:458
void toolbar_set_dimensions(struct s_toolbar *tb, GRECT *area)
Definition: toolbar.c:561
bool toolbar_key_input(struct s_toolbar *tb, short nkc)
Definition: toolbar.c:677
void toolbar_mouse_input(struct s_toolbar *tb, short obj, short button)
Definition: toolbar.c:755
void toolbar_set_origin(struct s_toolbar *tb, short x, short y)
Definition: toolbar.c:548
Browser window creation and manipulation interface.
nserror browser_window_navigate(struct browser_window *bw, struct nsurl *url, struct nsurl *referrer, enum browser_window_nav_flags flags, char *post_urlenc, struct fetch_multipart_data *post_multipart, struct hlcache_handle *parent)
Start fetching a page in a browser window.
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.
float browser_window_get_scale(struct browser_window *bw)
Gets the scale of a browser 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.
void browser_window_destroy(struct browser_window *bw)
Close and destroy a browser window.
void browser_window_reformat(struct browser_window *bw, bool background, int width, int height)
Reformat a browser window contents to a new width or height.
bool browser_window_drop_file_at_point(struct browser_window *bw, int x, int y, char *file)
Drop a file onto a browser window at a particular point, or determine if a file may be dropped onto t...
@ BW_NAVIGATE_HISTORY
this will form a new history node (don't set for back/reload/etc)
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.
static os_mode mode
The current sprite mode.
Definition: buffer.c:72
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_BAD_ENCODING
The character set is unknown.
Definition: errors.h:45
@ NSERROR_OK
No error.
Definition: errors.h:30
static struct directory * root
Definition: filename.c:55
const char * type
Definition: filetype.cpp:44
nserror utf8_from_local_encoding(const char *string, size_t len, char **result)
Definition: utf8.c:80
int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB *out)
setup an MFDB struct and allocate memory for it when it is needed.
Definition: bitmap.c:41
Atari bitmap handling implementation.
#define MFDB_FLAG_ZEROMEM
Definition: bitmap.h:34
#define MFDB_FLAG_NOALLOC
Definition: bitmap.h:35
struct s_search_form_session * nsatari_search_session_create(OBJECT *obj, struct gui_window *gw)
Definition: search.c:286
void nsatari_search_session_destroy(struct s_search_form_session *s)
Definition: search.c:224
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_1
button 1 clicked.
Definition: mouse.h:55
@ BROWSER_MOUSE_MOD_2
2nd modifier key pressed (eg.
Definition: mouse.h:80
@ 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_DRAG_ON
a drag operation was started and a mouse button is still pressed
Definition: mouse.h:70
Target independent plotting interface.
Interface to key press operations.
@ NS_KEY_LINE_START
Definition: keypress.h:57
@ 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_LINE_END
Definition: keypress.h:58
@ NS_KEY_UP
Definition: keypress.h:52
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
NetSurf URL handling (interface).
nserror nsurl_create(const char *const url_s, nsurl **url)
Create a NetSurf URL object from a URL string.
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
NS_ATARI_SYSINFO atari_sysinfo
Definition: osspec.c:38
void redraw_slots_init(struct s_redrw_slots *slots, short size)
Definition: redrawslots.c:26
void redraw_slots_free(struct s_redrw_slots *slots)
Definition: redrawslots.c:33
void redraw_slot_schedule_grect(struct s_redrw_slots *slots, GRECT *area, bool force)
Definition: redrawslots.c:57
int width
Definition: gui.c:159
int height
Definition: gui.c:160
EVMULT_OUT aes_event_out
Definition: gui.c:104
static bool on_content_keypress(struct gui_window *gw, unsigned short nkc)
Definition: rootwin.c:1276
void window_get_scroll(ROOTWIN *rootwin, int *x, int *y)
Definition: rootwin.c:591
void window_restore_active_gui_window(ROOTWIN *rootwin)
Definition: rootwin.c:404
void window_update_back_forward(struct s_gui_win_root *rootwin)
Definition: rootwin.c:433
GRECT desk_area
Definition: gui.c:78
void window_set_active_gui_window(ROOTWIN *rootwin, struct gui_window *gw)
Definition: rootwin.c:564
static void on_redraw(ROOTWIN *rootwin, short msg[8])
Definition: rootwin.c:1390
struct gui_window * input_window
Definition: gui.c:73
void window_set_icon(ROOTWIN *rootwin, struct bitmap *bmp)
Definition: rootwin.c:553
static void on_content_mouse_move(ROOTWIN *rootwin, GRECT *content_area)
Definition: rootwin.c:1138
struct gui_window * window_get_active_gui_window(ROOTWIN *rootwin)
Definition: rootwin.c:586
void window_set_focus(struct s_gui_win_root *rootwin, enum focus_element_type type, void *element)
Definition: rootwin.c:498
void window_schedule_redraw_grect(ROOTWIN *rootwin, GRECT *area)
Definition: rootwin.c:807
static bool redraw_active
Definition: rootwin.c:85
void window_scroll_by(ROOTWIN *root, int sx, int sy)
Definition: rootwin.c:459
static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
Definition: rootwin.c:93
static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area, GRECT *clip, struct gemtk_wm_scroll_info_s *slid, struct browser_window *bw)
Definition: rootwin.c:823
void window_unref_gui_window(ROOTWIN *rootwin, struct gui_window *gw)
Definition: rootwin.c:312
static void toolbar_redraw_cb(GUIWIN *win, uint16_t msg, GRECT *clip)
Definition: rootwin.c:1547
void window_redraw_favicon(ROOTWIN *rootwin, GRECT *clip_ro)
Redraw the favicon.
Definition: rootwin.c:707
void window_set_title(struct s_gui_win_root *rootwin, char *title)
Definition: rootwin.c:454
void window_set_content_size(ROOTWIN *rootwin, int width, int height)
Set the dimensions of the scrollable content.
Definition: rootwin.c:481
int window_create(struct gui_window *gw, struct browser_window *bw, struct gui_window *existing, unsigned long inflags)
Definition: rootwin.c:225
static const struct redraw_context rootwin_rdrw_ctx
Definition: rootwin.c:87
bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy)
Definition: gui.c:413
void window_open_search(ROOTWIN *rootwin, bool reformat)
Definition: rootwin.c:649
void window_close_search(ROOTWIN *rootwin)
Definition: rootwin.c:680
void window_get_grect(ROOTWIN *rootwin, enum browser_area_e which, GRECT *d)
Definition: rootwin.c:601
static void on_resized(ROOTWIN *rootwin)
Definition: rootwin.c:1404
void window_place_caret(ROOTWIN *rootwin, short mode, int content_x, int content_y, int h, GRECT *work)
Definition: rootwin.c:875
static short on_window_key_input(ROOTWIN *rootwin, unsigned short nkc)
Definition: rootwin.c:1359
bool window_url_widget_has_focus(struct s_gui_win_root *rootwin)
Definition: rootwin.c:531
static void on_file_dropped(ROOTWIN *rootwin, short msg[8])
Definition: rootwin.c:1438
void window_open(ROOTWIN *rootwin, struct gui_window *gw, GRECT pos)
show the window at specified position and make gw the active tab.
Definition: rootwin.c:375
void window_set_stauts(struct s_gui_win_root *rootwin, char *text)
Definition: rootwin.c:439
bool window_widget_has_focus(struct s_gui_win_root *rootwin, enum focus_element_type t, void *element)
Definition: rootwin.c:542
int window_destroy(ROOTWIN *rootwin)
Definition: rootwin.c:336
void window_process_redraws(ROOTWIN *rootwin)
Definition: rootwin.c:1015
static void on_content_mouse_click(ROOTWIN *rootwin)
Definition: rootwin.c:1160
#define WIDGET_STATUSBAR
Definition: rootwin.h:27
browser_area_e
Definition: rootwin.h:33
@ BROWSER_AREA_CONTENT
Definition: rootwin.h:34
@ BROWSER_AREA_URL_INPUT
Definition: rootwin.h:37
@ BROWSER_AREA_TOOLBAR
Definition: rootwin.h:36
@ BROWSER_AREA_SEARCH
Definition: rootwin.h:38
#define WIDGET_TOOLBAR
Definition: rootwin.h:28
#define WIDGET_RESIZE
Definition: rootwin.h:30
#define WIDGET_SCROLL
Definition: rootwin.h:29
#define WIN_TOP
Definition: rootwin.h:31
void sb_set_text(CMP_STATUSBAR sb, const char *text)
Definition: statusbar.c:221
CMP_STATUSBAR sb_create(struct gui_window *gw)
Definition: statusbar.c:199
void sb_attach(CMP_STATUSBAR sb, struct gui_window *gw)
Definition: statusbar.c:215
void sb_destroy(CMP_STATUSBAR s)
Definition: statusbar.c:207
Interface to utility string handling.
short aes_max_win_title_len
Definition: osspec.h:35
RISC OS wimp toolkit bitmap.
Definition: bitmap.c:68
Browser window data.
struct browser_window * bw
first entry in window list
Definition: gui.c:296
MFORM_EX * cursor
Definition: gui.h:150
struct gui_window * next
list for cleanup
Definition: gui.h:159
char * url
Definition: gui.h:154
struct s_search_form_session * search
Definition: gui.h:158
char * status
Definition: gui.h:152
struct bitmap * icon
Definition: gui.h:156
struct s_gui_win_root * root
Definition: gui.h:148
char * title
Definition: gui.h:153
struct s_browser * browser
Definition: gui.h:149
struct browser_window * bw
The 'content' window that is rendered in the gui_window.
Definition: gui.c:314
nserror(* clip)(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plotters.h:111
nserror(* bitmap)(const struct redraw_context *ctx, struct bitmap *bitmap, int x, int y, int width, int height, colour bg, bitmap_flags_t flags)
Plot a bitmap.
Definition: plotters.h:257
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
const struct plotter_table * plot
Current plot operation table.
Definition: plotters.h:73
bool interactive
Redraw to show interactive features.
Definition: plotters.h:59
struct s_gui_win_root * rootwin
Definition: rootwin.c:69
Definition: gui.h:136
bool attached
Definition: gui.h:138
struct browser_window * bw
Definition: gui.h:137
Definition: gui.h:37
int fd_size
Definition: gui.h:40
unsigned short state
Definition: gui.h:41
MFDB symbol
Definition: gui.h:39
GRECT dimensions
Definition: gui.h:38
void * element
Definition: gui.h:91
enum focus_element_type type
Definition: gui.h:90
MFORM_EX ibeam
Definition: gui.h:64
struct bitmap * icon
Definition: gui.h:126
char * title
Definition: gui.h:125
CMP_TOOLBAR toolbar
Definition: gui.h:122
GUIWIN * win
Definition: gui.h:121
struct s_redrw_slots redraw_slots
Definition: gui.h:128
GRECT loc
Definition: gui.h:131
CMP_STATUSBAR statusbar
Definition: gui.h:123
short aes_handle
Definition: gui.h:120
struct s_caret caret
Definition: gui.h:129
struct s_focus_info focus
Definition: gui.h:124
struct gui_window * active_gui_window
Definition: gui.h:127
struct rect areas[MAX_REDRW_SLOTS]
Definition: redrawslots.h:39
short volatile areas_used
Definition: redrawslots.h:41
OBJECT * form
Definition: toolbar.h:47
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