NetSurf
corewindow.c
Go to the documentation of this file.
1/*
2 * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * RISC OS generic core window implementation.
22 *
23 * Provides interface for core renderers to a risc os drawing area.
24 *
25 * This module is an object that must be encapsulated. Client users
26 * should embed a struct ro_corewindow at the beginning of their
27 * context for this display surface, fill in relevant data and then
28 * call ro_corewindow_init()
29 *
30 * The ro core window structure requires the callback for draw, key
31 * and mouse operations.
32 */
33
34#include <stdint.h>
35#include <oslib/wimp.h>
36
37#include "utils/log.h"
38#include "netsurf/types.h"
39#include "netsurf/mouse.h"
40#include "netsurf/keypress.h"
41
42#include "riscos/wimp_event.h"
43#include "riscos/dialog.h"
44#include "riscos/gui.h"
45#include "riscos/window.h"
46#include "riscos/toolbar.h"
47#include "riscos/mouse.h"
48#include "riscos/wimputils.h"
49#include "riscos/corewindow.h"
50
51#ifndef wimp_KEY_END
52#define wimp_KEY_END wimp_KEY_COPY
53#endif
54
56
57/**
58 * Update a windows scrollbars.
59 *
60 * in the wimp this is done by setting the extent and calling window open
61 */
62static void update_scrollbars(struct ro_corewindow *ro_cw, wimp_open *open)
63{
64 os_error *error;
65 int extent_width;
66 int extent_height;
67 os_box extent;
68
69 NSLOG(netsurf, INFO, "RO corewindow context %p", ro_cw);
70
71 /* extent of content in not smaller than window so start there */
72 extent_width = open->visible.x1 - open->visible.x0;
73 extent_height = open->visible.y0 - open->visible.y1;
74 NSLOG(netsurf, INFO,
75 "extent w:%d h:%d content w:%d h:%d origin h:%d", extent_width,
76 extent_height, ro_cw->content_width, ro_cw->content_height,
77 ro_cw->origin_y);
78 if (ro_cw->content_width > extent_width) {
79 extent_width = ro_cw->content_width;
80 }
81 if (extent_height > (ro_cw->origin_y + ro_cw->content_height)) {
82 extent_height = ro_cw->origin_y + ro_cw->content_height;
83 }
84 NSLOG(netsurf, INFO, "extent w:%d h:%d", extent_width, extent_height);
85 extent.x0 = 0;
86 extent.y0 = extent_height;
87 extent.x1 = extent_width;
88 extent.y1 = 0;
89
90 error = xwimp_set_extent(ro_cw->wh, &extent);
91 if (error) {
92 NSLOG(netsurf, INFO, "xwimp_set_extent: 0x%x: %s",
93 error->errnum, error->errmess);
94 return;
95 }
96
97 error = xwimp_open_window(open);
98 if (error) {
99 NSLOG(netsurf, INFO, "xwimp_open_window: 0x%x: %s",
100 error->errnum, error->errmess);
101 }
102}
103
104
105/**
106 * wimp callback on redraw event
107 */
108static void ro_cw_redraw(wimp_draw *redraw)
109{
110 struct ro_corewindow *ro_cw;
111 osbool more;
112 os_error *error;
113 struct rect r;
114 int origin_x;
115 int origin_y;
116
117 ro_cw = (struct ro_corewindow *)ro_gui_wimp_event_get_user_data(redraw->w);
118
119 error = xwimp_redraw_window(redraw, &more);
120 while ((error == NULL) && (more)) {
121 /* compute rectangle to redraw */
122 origin_x = redraw->box.x0 - redraw->xscroll;
123 origin_y = redraw->box.y1 + ro_cw->origin_y - redraw->yscroll;
124
125 ro_plot_clip_rect.x0 = redraw->clip.x0 - origin_x;
126 ro_plot_clip_rect.y0 = origin_y - redraw->clip.y0;
127 ro_plot_clip_rect.x1 = redraw->clip.x1 - origin_x;
128 ro_plot_clip_rect.y1 = origin_y - redraw->clip.y1;
129
130 r.x0 = (ro_plot_clip_rect.x0 ) / 2; /* left */
131 r.y0 = (ro_plot_clip_rect.y1 ) / 2; /* top */
132 r.x1 = (ro_plot_clip_rect.x1 + 1) / 2; /* right */
133 r.y1 = (ro_plot_clip_rect.y0 + 1) / 2; /* bottom */
134
135 /* call the draw callback */
136 ro_cw->draw(ro_cw, origin_x, origin_y, &r);
137
138 error = xwimp_get_rectangle(redraw, &more);
139 }
140 if (error != NULL) {
141 NSLOG(netsurf, INFO, "xwimp_redraw_window: 0x%x: %s",
142 error->errnum, error->errmess);
143 }
144
145}
146
147static void ro_cw_scroll(wimp_scroll *scroll)
148{
149 os_error *error;
150 int page_x;
151 int page_y;
152 struct ro_corewindow *ro_cw;
153 wimp_open open;
154 wimp_window_state state;
155
156 ro_cw = (struct ro_corewindow *)ro_gui_wimp_event_get_user_data(scroll->w);
157 NSLOG(netsurf, INFO, "RO corewindow context %p", ro_cw);
158
159 state.w = ro_cw->wh;
160 error = xwimp_get_window_state(&state);
161 if (error) {
162 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
163 error->errnum, error->errmess);
164 return;
165 }
166
167 /* Don't try to update window if it's closed */
168 if (!(state.flags & wimp_WINDOW_OPEN)) {
169 return;
170 }
171
172 page_x = scroll->visible.x1 - scroll->visible.x0 - 32;
173 page_y = scroll->visible.y1 - scroll->visible.y0 - 32;
174
175 page_y += ro_cw->origin_y;
176
177 open.w = scroll->w;
178 open.visible = scroll->visible;
179 open.next = scroll->next;
180
181 switch (scroll->xmin) {
182 case wimp_SCROLL_PAGE_LEFT:
183 open.xscroll = scroll->xscroll - page_x;
184 break;
185
186 case wimp_SCROLL_COLUMN_LEFT:
187 open.xscroll = scroll->xscroll - 32;
188 break;
189
190 case wimp_SCROLL_COLUMN_RIGHT:
191 open.xscroll = scroll->xscroll + 32;
192 break;
193
194 case wimp_SCROLL_PAGE_RIGHT:
195 open.xscroll = scroll->xscroll + page_x;
196 break;
197
198 default:
199 open.xscroll = scroll->xscroll + ((page_x * (scroll->xmin>>2)) >> 2);
200 break;
201 }
202
203 switch (scroll->ymin) {
204 case wimp_SCROLL_PAGE_UP:
205 open.yscroll = scroll->yscroll + page_y;
206 break;
207
208 case wimp_SCROLL_LINE_UP:
209 open.yscroll = scroll->yscroll + 32;
210 break;
211
212 case wimp_SCROLL_LINE_DOWN:
213 open.yscroll = scroll->yscroll - 32;
214 break;
215
216 case wimp_SCROLL_PAGE_DOWN:
217 open.yscroll = scroll->yscroll - page_y;
218 break;
219
220 default:
221 open.yscroll = scroll->yscroll + ((page_y * (scroll->ymin>>2)) >> 2);
222 break;
223 }
224
225 error = xwimp_open_window(&open);
226 if (error) {
227 NSLOG(netsurf, INFO, "xwimp_open_window: 0x%x: %s",
228 error->errnum, error->errmess);
229 }
230
231}
232
233
234
235/**
236 * Track the mouse under Null Polls from the wimp, to support dragging.
237 *
238 * \param pointer Pointer to a Wimp Pointer block.
239 * \param data NULL to allow use as a ro_mouse callback.
240 */
241static void ro_cw_mouse_at(wimp_pointer *pointer, void *data)
242{
243 os_error *error;
244 struct ro_corewindow *ro_cw;
245 wimp_window_state state;
246 int xpos, ypos;
248
249 /* ignore menu clicks */
250 if (pointer->buttons & (wimp_CLICK_MENU)) {
251 return;
252 }
253
254 ro_cw = (struct ro_corewindow *)ro_gui_wimp_event_get_user_data(pointer->w);
255 if (ro_cw == NULL) {
256 NSLOG(netsurf, INFO, "no corewindow conext for window: 0x%x",
257 (unsigned int)pointer->w);
258 return;
259 }
260 if (ro_cw != ro_cw_drag_cw) {
261 NSLOG(netsurf, DEEPDEBUG, "Called without drag window: %p",
262 ro_cw);
263 return;
264 }
265 NSLOG(netsurf, INFO, "RO corewindow context %p", ro_cw);
266
267 /* Not a Menu click. */
268 state.w = pointer->w;
269 error = xwimp_get_window_state(&state);
270 if (error) {
271 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
272 error->errnum, error->errmess);
273 return;
274 }
275
276 /* Convert the returned mouse coordinates into
277 * NetSurf's internal units.
278 */
279 xpos = ((pointer->pos.x - state.visible.x0) + state.xscroll) / 2;
280 ypos = ((state.visible.y1 - pointer->pos.y) -
281 state.yscroll + ro_cw->origin_y) / 2;
282
283 /* if no drag in progress report hover */
284 if (ro_cw->drag_status == CORE_WINDOW_DRAG_NONE) {
286 } else {
287 /* Start to process the mouse click. */
288 mouse = ro_gui_mouse_drag_state(pointer->buttons,
289 wimp_BUTTON_DOUBLE_CLICK_DRAG);
290
291 ro_cw->mouse(ro_cw, mouse, xpos, ypos);
292 }
293
294 if (!(mouse & BROWSER_MOUSE_DRAG_ON)) {
295 ro_cw->mouse(ro_cw, BROWSER_MOUSE_HOVER, xpos, ypos);
297 }
298
299 ro_cw->toolbar_update(ro_cw);
300}
301
302/**
303 * Process RISC OS User Drag Box events which relate to us: in effect, drags
304 * started by ro_cw_drag_start().
305 *
306 * \param drag Pointer to the User Drag Box Event block.
307 * \param data NULL to allow use as a ro_mouse callback.
308 */
309static void ro_cw_drag_end(wimp_dragged *drag, void *data)
310{
311 os_error *error;
312
313 error = xwimp_drag_box((wimp_drag *) -1);
314 if (error) {
315 NSLOG(netsurf, INFO, "xwimp_drag_box: 0x%x: %s",
316 error->errnum, error->errmess);
317 ro_warn_user("WimpError", error->errmess);
318 }
319
320 error = xwimp_auto_scroll(0, NULL, NULL);
321 if (error) {
322 NSLOG(netsurf, INFO, "xwimp_auto_scroll: 0x%x: %s",
323 error->errnum, error->errmess);
324 ro_warn_user("WimpError", error->errmess);
325 }
326}
327
328
329/**
330 * Start a RISC OS drag event to reflect on screen what is happening
331 * during the core tree drag.
332 *
333 * \param ro_cw The RO corewindow to which the drag is attached.
334 * \param pointer The RO pointer event data block starting the drag.
335 * \param state The RO window state block for the treeview window.
336 */
337static void
339 wimp_pointer *pointer,
340 wimp_window_state *state)
341{
342 os_error *error;
343 wimp_drag drag;
344 wimp_auto_scroll_info auto_scroll;
345
346 drag.w = ro_cw->wh;
347 drag.bbox.x0 = state->visible.x0;
348 drag.bbox.y0 = state->visible.y0;
349 drag.bbox.x1 = state->visible.x1;
350 drag.bbox.y1 = state->visible.y1 - ro_toolbar_height(ro_cw->toolbar) - 2;
351
352 switch (ro_cw->drag_status) {
354 drag.type = wimp_DRAG_USER_RUBBER;
355
356 drag.initial.x0 = pointer->pos.x;
357 drag.initial.y0 = pointer->pos.y;
358 drag.initial.x1 = pointer->pos.x;
359 drag.initial.y1 = pointer->pos.y;
360 break;
361
363 drag.type = wimp_DRAG_USER_POINT;
364
365 drag.initial.x0 = pointer->pos.x - 4;
366 drag.initial.y0 = pointer->pos.y - 48;
367 drag.initial.x1 = pointer->pos.x + 48;
368 drag.initial.y1 = pointer->pos.y + 4;
369 break;
370
371 default:
372 /* No other drag types are supported. */
373 break;
374 }
375
376 NSLOG(netsurf, INFO, "Drag start...");
377
378 error = xwimp_drag_box_with_flags(&drag,
379 wimp_DRAG_BOX_KEEP_IN_LINE | wimp_DRAG_BOX_CLIP);
380 if (error) {
381 NSLOG(netsurf, INFO, "xwimp_drag_box: 0x%x: %s",
382 error->errnum, error->errmess);
383 ro_warn_user("WimpError", error->errmess);
384 } else {
385 auto_scroll.w = ro_cw->wh;
386 auto_scroll.pause_zone_sizes.x0 = 80;
387 auto_scroll.pause_zone_sizes.y0 = 80;
388 auto_scroll.pause_zone_sizes.x1 = 80;
389 auto_scroll.pause_zone_sizes.y1 = 80 + ro_toolbar_height(ro_cw->toolbar);
390 auto_scroll.pause_duration = 0;
391 auto_scroll.state_change = (void *) 1;
392
393 error = xwimp_auto_scroll(wimp_AUTO_SCROLL_ENABLE_VERTICAL,
394 &auto_scroll, NULL);
395 if (error) {
396 NSLOG(netsurf, INFO, "xwimp_auto_scroll: 0x%x: %s",
397 error->errnum, error->errmess);
398 ro_warn_user("WimpError", error->errmess);
399 }
400
401 ro_cw_drag_cw = ro_cw;
403 }
404}
405
406
407/**
408 * Handle Pointer Leaving Window events.
409 *
410 * These events are delivered as the termination callback handler from
411 * ro_mouse's mouse tracking.
412 *
413 * \param leaving The Wimp_PointerLeavingWindow block.
414 * \param data NULL data pointer.
415 */
416static void ro_cw_pointer_leaving(wimp_leaving *leaving, void *data)
417{
418 struct ro_corewindow *ro_cw;
419
420 ro_cw = (struct ro_corewindow *)ro_gui_wimp_event_get_user_data(leaving->w);
421 if (ro_cw == NULL) {
422 NSLOG(netsurf, INFO, "no corewindow conext for window: 0x%x",
423 (unsigned int)leaving->w);
424 return;
425 }
426
427 ro_cw->mouse(ro_cw, BROWSER_MOUSE_LEAVE, 0, 0);
428}
429
430
431/**
432 * Wimp callback on pointer entering window.
433 *
434 * The wimp has issued an event to the window because the pointer has
435 * entered it.
436 *
437 * \param entering The entering event to be processed
438 */
439static void ro_cw_pointer_entering(wimp_entering *entering)
440{
442}
443
444
445/**
446 * Wimp callback on window open event.
447 *
448 * The wimp has issued an event to the window because an attempt has
449 * been made to open or resize it. This requires the new dimensions to
450 * be calculated and set within the wimp.
451 *
452 * \param open The open event to be processed
453 */
454static void ro_cw_open(wimp_open *open)
455{
456 struct ro_corewindow *ro_cw;
457
458 ro_cw = (struct ro_corewindow *)ro_gui_wimp_event_get_user_data(open->w);
459
460 update_scrollbars(ro_cw, open);
461}
462
463static bool ro_cw_mouse_click(wimp_pointer *pointer)
464{
465 os_error *error;
466 wimp_window_state state;
467 int xpos, ypos;
469 bool handled = false;
470 struct ro_corewindow *ro_cw;
471
472 ro_cw = (struct ro_corewindow *)ro_gui_wimp_event_get_user_data(pointer->w);
473 NSLOG(netsurf, INFO, "RO corewindow context %p", ro_cw);
474
475
476 state.w = ro_cw->wh;
477 error = xwimp_get_window_state(&state);
478 if (error) {
479 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
480 error->errnum, error->errmess);
481 return false;
482 }
483
484 /* Convert the returned mouse coordinates into NetSurf's internal
485 * units.
486 */
487 xpos = ((pointer->pos.x - state.visible.x0) + state.xscroll) / 2;
488 ypos = ((state.visible.y1 - pointer->pos.y) -
489 state.yscroll + ro_cw->origin_y) / 2;
490
491 if (pointer->buttons != wimp_CLICK_MENU) {
492 mouse = ro_gui_mouse_click_state(pointer->buttons,
493 wimp_BUTTON_DOUBLE_CLICK_DRAG);
494
495 /* Give the window input focus on Select-clicks. This wouldn't
496 * be necessary if the core used the RISC OS caret.
497 */
499 xwimp_set_caret_position(ro_cw->wh,
500 -1, -100, -100, 32, -1);
501 }
502 }
503
504 /* call the mouse callback */
505 if (mouse != 0) {
506 ro_cw->mouse(ro_cw, mouse, xpos, ypos);
507
508 /* If it's a visible drag, start the RO side of the visible
509 * effects.
510 */
511 if ((ro_cw->drag_status == CORE_WINDOW_DRAG_SELECTION) ||
513 ro_cw_drag_start(ro_cw, pointer, &state);
514 }
515
516 ro_cw->toolbar_update(ro_cw);
517 }
518
519 /* Special actions for some mouse buttons. Adjust closes the dialog;
520 * Menu opens a menu. For the latter, we assume that the owning module
521 * will have attached a window menu to our parent window with the auto
522 * flag unset (so that we can fudge the selection above). If it hasn't,
523 * the call will quietly fail.
524 *
525 * \TODO -- Adjust-click close isn't a perfect copy of what the RO
526 * version did: adjust clicks anywhere close the tree, and
527 * selections persist.
528 */
529 switch(pointer->buttons) {
530 case wimp_CLICK_ADJUST:
531 if (handled) {
532 ro_gui_dialog_close(ro_cw->wh);
533 }
534 break;
535
536 case wimp_CLICK_MENU:
538 break;
539 }
540
541 return true;
542}
543
544static bool ro_cw_keypress(wimp_key *key)
545{
546 uint32_t c;
547 struct ro_corewindow *ro_cw;
548 nserror res;
549
551 NSLOG(netsurf, INFO, "RO corewindow context %p", ro_cw);
552
553 c = (uint32_t) key->c;
554
555 if ((unsigned)c < 0x20 ||
556 (0x7f <= c && c <= 0x9f) ||
557 (c & IS_WIMP_KEY)) {
558 /* Munge control keys into unused control chars */
559 /* We can't map onto 1->26 (reserved for ctrl+<qwerty>
560 That leaves 27->31 and 128->159 */
561 switch (c & ~IS_WIMP_KEY) {
562 case wimp_KEY_TAB:
563 c = 9;
564 break;
565
566 case wimp_KEY_SHIFT | wimp_KEY_TAB:
567 c = 11;
568 break;
569
570 /* cursor movement keys */
571 case wimp_KEY_HOME:
572 case wimp_KEY_CONTROL | wimp_KEY_LEFT:
574 break;
575
576 case wimp_KEY_END:
577 if (os_version >= RISCOS5)
578 c = NS_KEY_LINE_END;
579 else
581 break;
582
583 case wimp_KEY_CONTROL | wimp_KEY_RIGHT:
584 c = NS_KEY_LINE_END;
585 break;
586
587 case wimp_KEY_CONTROL | wimp_KEY_UP:
589 break;
590
591 case wimp_KEY_CONTROL | wimp_KEY_DOWN:
592 c = NS_KEY_TEXT_END;
593 break;
594
595 case wimp_KEY_SHIFT | wimp_KEY_LEFT:
597 break;
598
599 case wimp_KEY_SHIFT | wimp_KEY_RIGHT:
601 break;
602
603 case wimp_KEY_SHIFT | wimp_KEY_UP:
604 c = NS_KEY_PAGE_UP;
605 break;
606
607 case wimp_KEY_SHIFT | wimp_KEY_DOWN:
609 break;
610
611 case wimp_KEY_LEFT:
612 c = NS_KEY_LEFT;
613 break;
614
615 case wimp_KEY_RIGHT:
616 c = NS_KEY_RIGHT;
617 break;
618
619 case wimp_KEY_UP:
620 c = NS_KEY_UP;
621 break;
622
623 case wimp_KEY_DOWN:
624 c = NS_KEY_DOWN;
625 break;
626
627 /* editing */
628 case wimp_KEY_CONTROL | wimp_KEY_END:
630 break;
631
632 case wimp_KEY_DELETE:
635 else if (os_version < RISCOS5)
637 break;
638
639 default:
640 break;
641 }
642 }
643
644 if (!(c & IS_WIMP_KEY)) {
645 res = ro_cw->key(ro_cw, c);
646 if (res == NSERROR_OK) {
647 ro_cw->toolbar_update(ro_cw);
648 return true;
649 }
650 }
651
652 return false;
653}
654
655
656/**
657 * Update a corewindow toolbar to a new size.
658 *
659 * \param ctx Context as passed to toolbar creation.
660 */
661static void cw_tb_size(void *ctx)
662{
663 struct ro_corewindow *ro_cw;
664 wimp_window_state state;
665 os_error *error;
666
667 ro_cw = (struct ro_corewindow *)ctx;
668
669 ro_cw->origin_y = -(ro_toolbar_height(ro_cw->toolbar));
670
671 state.w = ro_cw->wh;
672 error = xwimp_get_window_state(&state);
673 if (error) {
674 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
675 error->errnum, error->errmess);
676 return;
677 }
678
679 error = xwimp_force_redraw(ro_cw->wh,
680 0, state.visible.y0 - state.visible.y1,
681 state.visible.x1 - state.visible.x0, 0);
682 if (error) {
683 NSLOG(netsurf, INFO, "xwimp_force_redraw: 0x%x: %s",
684 error->errnum, error->errmess);
685 return;
686 }
687}
688
689
690/**
691 * Update a corewindow toolbar to use a new theme.
692 *
693 * \param ctx Context as passed to toolbar creation.
694 * \param exists true if the bar still exists; else false.
695 */
696static void cw_tb_theme(void *ctx, bool exists)
697{
698 if (exists) {
699 cw_tb_size(ctx);
700 }
701}
702
703
704/**
705 * Allow a corewindow toolbar button state to be updated.
706 *
707 * \param ctx Context as passed to toolbar creation.
708 */
709static void cw_tb_update(void *ctx)
710{
711 struct ro_corewindow *ro_cw;
712
713 ro_cw = (struct ro_corewindow *)ctx;
714
715 ro_cw->toolbar_update(ro_cw);
716}
717
718
719/**
720 * Respond to user actions (click) in a corewindow.
721 *
722 * \param ctx Context as passed to toolbar creation.
723 * \param action_type type of action on toolbar
724 * \param action data for action.
725 */
726static void
727cw_tb_click(void *ctx,
728 toolbar_action_type action_type,
729 union toolbar_action action)
730{
731 struct ro_corewindow *ro_cw;
732
733 ro_cw = (struct ro_corewindow *)ctx;
734
735 if (action_type == TOOLBAR_ACTION_BUTTON) {
736 ro_cw->toolbar_click(ro_cw, action.button);
737 ro_cw->toolbar_update(ro_cw);
738 }
739}
740
741
742/**
743 * Save positions of core window toolbar buttons.
744 *
745 * \param ctx Context as passed to toolbar creation.
746 * \param config The new button config string.
747 */
748static void cw_tb_save(void *ctx, char *config)
749{
750 struct ro_corewindow *ro_cw;
751
752 ro_cw = (struct ro_corewindow *)ctx;
753
754 ro_cw->toolbar_save(ro_cw, config);
755}
756
757
758
759/**
760 * riscos core window toolbar callbacks
761 */
764 .change_size = cw_tb_size,
765 .update_buttons = cw_tb_update,
766 .user_action = cw_tb_click,
767 .save_buttons = cw_tb_save,
768};
769
770
771/**
772 * callback from core to request an invalidation of a window area.
773 *
774 * The specified area of the window should now be considered
775 * out of date. If the area is NULL the entire window must be
776 * invalidated.
777 *
778 * \param[in] cw The core window to invalidate.
779 * \param[in] r area to redraw or NULL for the entire window area.
780 * \return NSERROR_OK on success or appropriate error code.
781 */
782static nserror
783ro_cw_invalidate(struct core_window *cw, const struct rect *r)
784{
785 struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
786 os_error *error;
787 wimp_window_info info;
788
789 if (r == NULL) {
790 info.w = ro_cw->wh;
791 error = xwimp_get_window_info_header_only(&info);
792 if (error) {
793 NSLOG(netsurf, INFO,
794 "xwimp_get_window_info_header_only: 0x%x: %s",
795 error->errnum,
796 error->errmess);
797 return NSERROR_INVALID;
798 }
799 } else {
800 /* convert the passed rectangle into RO window dimensions */
801 info.extent.x0 = 2 * r->x0;
802 info.extent.y0 = (-2 * (r->y0 + (r->y1 - r->y0))) + ro_cw->origin_y;
803 info.extent.x1 = 2 * (r->x0 + (r->x1 - r->x0));
804 info.extent.y1 = (-2 * r->y0) + ro_cw->origin_y;
805 }
806
807 error = xwimp_force_redraw(ro_cw->wh,
808 info.extent.x0, info.extent.y0,
809 info.extent.x1, info.extent.y1);
810 if (error) {
811 NSLOG(netsurf, INFO, "xwimp_force_redraw: 0x%x: %s",
812 error->errnum, error->errmess);
813 return NSERROR_INVALID;
814 }
815 return NSERROR_OK;
816}
817
818
819/**
820 * Callback from the core to update the content area size.
821 */
822static nserror
823ro_cw_update_size(struct core_window *cw, int width, int height)
824{
825 struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
826 wimp_open open;
827 wimp_window_state state;
828 os_error *error;
829
830 NSLOG(netsurf, INFO, "content resize from w:%d h:%d to w:%d h:%d",
831 ro_cw->content_width, ro_cw->content_height, width, height);
832
833 ro_cw->content_width = width * 2;
834 ro_cw->content_height = -(2 * height);
835
836 state.w = ro_cw->wh;
837 error = xwimp_get_window_state(&state);
838 if (error) {
839 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
840 error->errnum, error->errmess);
841 return NSERROR_INVALID;
842 }
843
844 /* only update the window if it is open */
845 if (state.flags & wimp_WINDOW_OPEN) {
846 open.w = ro_cw->wh;
847 open.visible = state.visible;
848 open.xscroll = state.xscroll;
849 open.yscroll = state.yscroll;
850 open.next = state.next;
851
852 update_scrollbars(ro_cw, &open);
853 }
854 return NSERROR_OK;
855}
856
857
858/**
859 * Callback from the core to scroll the visible content.
860 */
861static nserror
862ro_cw_get_scroll(const struct core_window *cw, int *x, int *y)
863{
864 struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
865 wimp_window_state state = {
866 .w = ro_cw->wh,
867 };
868 os_error *error;
869
870 error = xwimp_get_window_state(&state);
871 if (error) {
872 NSLOG(netsurf, ERROR, "xwimp_get_window_state: 0x%x: %s",
873 error->errnum, error->errmess);
874 return NSERROR_INVALID;
875 }
876
877 *x = state.xscroll / 2;
878 *y = -state.yscroll / 2;
879 return NSERROR_OK;
880}
881
882
883/**
884 * Callback from the core to scroll the visible content.
885 */
886static nserror
887ro_cw_set_scroll(struct core_window *cw, int x, int y)
888{
889 struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
890 wimp_window_state state = {
891 .w = ro_cw->wh,
892 };
893 os_error *error;
894
895 error = xwimp_get_window_state(&state);
896 if (error) {
897 NSLOG(netsurf, ERROR, "xwimp_get_window_state: 0x%x: %s",
898 error->errnum, error->errmess);
899 return NSERROR_INVALID;
900 }
901
902 state.xscroll = x * 2;
903 state.yscroll = -y * 2;
904
905 /* only update the window if it is open */
906 if (state.flags & wimp_WINDOW_OPEN) {
907 update_scrollbars(ro_cw, PTR_WIMP_OPEN(&state));
908 }
909
910 return NSERROR_OK;
911}
912
913
914/**
915 * Callback from the core to obtain the window viewport dimensions
916 *
917 * \param[in] cw the core window object
918 * \param[out] width to be set to viewport width in px
919 * \param[out] height to be set to viewport height in px
920 */
921static nserror
922ro_cw_get_window_dimensions(const struct core_window *cw,
923 int *width, int *height)
924{
925 struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
926 os_error *error;
927 wimp_window_state state;
928
929 state.w = ro_cw->wh;
930 error = xwimp_get_window_state(&state);
931 if (error) {
932 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
933 error->errnum, error->errmess);
934 return NSERROR_INVALID;
935 }
936
937 *width = (state.visible.x1 - state.visible.x0) / 2;
938 *height = (state.visible.y1 - state.visible.y0) / 2;
939
940 /* Account for toolbar height, if present */
941 if (ro_cw->toolbar != NULL) {
942 *height -= ro_toolbar_full_height(ro_cw->toolbar) / 2;
943 }
944 if (*height < 0) {
945 *height = 0;
946 }
947
948 return NSERROR_OK;
949}
950
951
952/**
953 * Callback from the core to update the drag status.
954 */
955static nserror
957{
958 struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
959 ro_cw->drag_status = ds;
960
961 return NSERROR_OK;
962}
963
964
967 .update_size = ro_cw_update_size,
968 .set_scroll = ro_cw_set_scroll,
969 .get_scroll = ro_cw_get_scroll,
970 .get_window_dimensions = ro_cw_get_window_dimensions,
971 .drag_status = ro_cw_drag_status
972};
973
974/**
975 * dummy toolbar click callback
976 *
977 */
979{
980 return NSERROR_OK;
981}
982
983/**
984 * dummy toolbar update callback
985 */
987{
988 return NSERROR_OK;
989}
990
991/**
992 * dummy toolbar save callback
993 */
994static nserror dummy_toolbar_save(struct ro_corewindow *ro_cw, char *config)
995{
996 return NSERROR_OK;
997}
998
999/* exported function documented ro/corewindow.h */
1000nserror
1002 const struct button_bar_buttons *tb_buttons,
1003 char *tb_order,
1004 theme_style tb_style,
1005 const char *tb_help)
1006{
1007 /* setup the core window callback table */
1008 ro_cw->cb_table = &ro_cw_cb_table;
1009
1010 /* start with the content area being as small as possible */
1011 ro_cw->content_width = -1;
1012 ro_cw->content_height = -1;
1013 ro_cw->origin_y = 0; /* no offset */
1014 ro_cw->drag_status = CORE_WINDOW_DRAG_NONE; /* no drag */
1015
1016 /* Create toolbar. */
1017 if (tb_buttons != NULL) {
1018 /* ensure toolbar callbacks are always valid so calls
1019 * do not have to be conditional
1020 */
1021 if (ro_cw->toolbar_click == NULL) {
1023 }
1024 if (ro_cw->toolbar_save == NULL) {
1026 }
1027 if (ro_cw->toolbar_update == NULL) {
1029 }
1030
1031 ro_cw->toolbar = ro_toolbar_create(NULL,
1032 ro_cw->wh,
1033 tb_style,
1036 ro_cw,
1037 tb_help);
1038 if (ro_cw->toolbar == NULL) {
1039 return NSERROR_INIT_FAILED;
1040 }
1041
1042 ro_toolbar_add_buttons(ro_cw->toolbar, tb_buttons, tb_order);
1044 ro_cw->origin_y = -(ro_toolbar_height(ro_cw->toolbar));
1045 } else {
1046 ro_cw->toolbar = NULL; /* no toolbar */
1047
1048 /* ensure callback functions are set to defaults when
1049 * no toolbar
1050 */
1054 }
1055
1056 /* setup context for event handlers */
1057 NSLOG(netsurf, INFO, "Setting corewindow %p for window handle %p",
1058 ro_cw, ro_cw->wh);
1059 ro_gui_wimp_event_set_user_data(ro_cw->wh, ro_cw);
1060
1061 /* register wimp events. */
1063 ro_cw_redraw);
1065 ro_cw_scroll);
1069 ro_cw_open);
1074
1075 return NSERROR_OK;
1076}
1077
1078/* exported interface documented in ro/corewindow.h */
1080{
1082
1083 /** \todo need to consider freeing of toolbar */
1084
1085 return NSERROR_OK;
1086}
static struct s_tb_button tb_buttons[]
Definition: toolbar.c:107
button_bar_action
Definition: button_bar.h:32
core_window_drag_status
drag status passed to drag_status callback
Definition: core_window.h:41
@ CORE_WINDOW_DRAG_NONE
Definition: core_window.h:42
@ CORE_WINDOW_DRAG_MOVE
Definition: core_window.h:45
@ CORE_WINDOW_DRAG_SELECTION
Definition: core_window.h:43
void ro_gui_dialog_close(wimp_w close)
Close a dialog box.
Definition: dialog.c:335
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_INIT_FAILED
Initialisation failed.
Definition: errors.h:38
@ NSERROR_INVALID
Invalid data.
Definition: errors.h:49
@ NSERROR_OK
No error.
Definition: errors.h:30
void ro_mouse_drag_start(void(*drag_end)(wimp_dragged *dragged, void *data), void(*drag_track)(wimp_pointer *pointer, void *data), void(*drag_cancel)(void *data), void *data)
Start a drag, providing a function to be called when the Wimp_DragEnd event is received and optionall...
Definition: mouse.c:115
void ro_mouse_track_start(void(*poll_end)(wimp_leaving *leaving, void *data), void(*poll_track)(wimp_pointer *pointer, void *data), void *data)
Start tracking the mouse in a window, providing a function to be called on null polls and optionally ...
Definition: mouse.c:177
Mouse dragging and tracking support interface for RISC OS.
theme_style
Theme styles, collecting groups of attributes for different locations.
Definition: theme.h:31
Browser window handling (interface).
Core mouse and pointer states.
browser_mouse_state
Mouse state.
Definition: mouse.h:43
@ BROWSER_MOUSE_HOVER
No mouse buttons pressed, May be used to indicate hover or end of drag.
Definition: mouse.h:47
@ BROWSER_MOUSE_CLICK_1
button 1 clicked.
Definition: mouse.h:55
@ BROWSER_MOUSE_LEAVE
pointer leaving window
Definition: mouse.h:85
@ BROWSER_MOUSE_DRAG_ON
a drag operation was started and a mouse button is still pressed
Definition: mouse.h:70
Interface to key press operations.
@ NS_KEY_DELETE_LINE_START
Definition: keypress.h:68
@ 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_WORD_LEFT
Definition: keypress.h:61
@ NS_KEY_DELETE_LINE_END
Definition: keypress.h:67
@ 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_TEXT_END
Definition: keypress.h:60
@ NS_KEY_DELETE_RIGHT
Definition: keypress.h:55
@ NS_KEY_WORD_RIGHT
Definition: keypress.h:63
@ NS_KEY_DELETE_LEFT
Definition: keypress.h:35
@ NS_KEY_UP
Definition: keypress.h:52
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
static const struct toolbar_callbacks corewindow_toolbar_callbacks
riscos core window toolbar callbacks
Definition: corewindow.c:762
static nserror ro_cw_get_scroll(const struct core_window *cw, int *x, int *y)
Callback from the core to scroll the visible content.
Definition: corewindow.c:862
#define wimp_KEY_END
Definition: corewindow.c:52
struct core_window_callback_table ro_cw_cb_table
Definition: corewindow.c:965
static void ro_cw_drag_start(struct ro_corewindow *ro_cw, wimp_pointer *pointer, wimp_window_state *state)
Start a RISC OS drag event to reflect on screen what is happening during the core tree drag.
Definition: corewindow.c:338
static void ro_cw_drag_end(wimp_dragged *drag, void *data)
Process RISC OS User Drag Box events which relate to us: in effect, drags started by ro_cw_drag_start...
Definition: corewindow.c:309
static void cw_tb_size(void *ctx)
Update a corewindow toolbar to a new size.
Definition: corewindow.c:661
static void update_scrollbars(struct ro_corewindow *ro_cw, wimp_open *open)
Update a windows scrollbars.
Definition: corewindow.c:62
static nserror ro_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
Callback from the core to update the drag status.
Definition: corewindow.c:956
static nserror dummy_toolbar_click(struct ro_corewindow *ro_cw, button_bar_action action)
dummy toolbar click callback
Definition: corewindow.c:978
static void ro_cw_pointer_entering(wimp_entering *entering)
Wimp callback on pointer entering window.
Definition: corewindow.c:439
static bool ro_cw_keypress(wimp_key *key)
Definition: corewindow.c:544
static nserror ro_cw_update_size(struct core_window *cw, int width, int height)
Callback from the core to update the content area size.
Definition: corewindow.c:823
static void ro_cw_pointer_leaving(wimp_leaving *leaving, void *data)
Handle Pointer Leaving Window events.
Definition: corewindow.c:416
static void cw_tb_save(void *ctx, char *config)
Save positions of core window toolbar buttons.
Definition: corewindow.c:748
static void cw_tb_update(void *ctx)
Allow a corewindow toolbar button state to be updated.
Definition: corewindow.c:709
static bool ro_cw_mouse_click(wimp_pointer *pointer)
Definition: corewindow.c:463
static nserror ro_cw_set_scroll(struct core_window *cw, int x, int y)
Callback from the core to scroll the visible content.
Definition: corewindow.c:887
static void ro_cw_redraw(wimp_draw *redraw)
wimp callback on redraw event
Definition: corewindow.c:108
nserror ro_corewindow_fini(struct ro_corewindow *ro_cw)
finalise elements of ro core window.
Definition: corewindow.c:1079
static nserror dummy_toolbar_save(struct ro_corewindow *ro_cw, char *config)
dummy toolbar save callback
Definition: corewindow.c:994
nserror ro_corewindow_init(struct ro_corewindow *ro_cw, const struct button_bar_buttons *tb_buttons, char *tb_order, theme_style tb_style, const char *tb_help)
initialise elements of riscos core window.
Definition: corewindow.c:1001
static void cw_tb_theme(void *ctx, bool exists)
Update a corewindow toolbar to use a new theme.
Definition: corewindow.c:696
static void ro_cw_scroll(wimp_scroll *scroll)
Definition: corewindow.c:147
static nserror ro_cw_get_window_dimensions(const struct core_window *cw, int *width, int *height)
Callback from the core to obtain the window viewport dimensions.
Definition: corewindow.c:922
static void cw_tb_click(void *ctx, toolbar_action_type action_type, union toolbar_action action)
Respond to user actions (click) in a corewindow.
Definition: corewindow.c:727
static void ro_cw_mouse_at(wimp_pointer *pointer, void *data)
Track the mouse under Null Polls from the wimp, to support dragging.
Definition: corewindow.c:241
static struct ro_corewindow * ro_cw_drag_cw
Definition: corewindow.c:55
static nserror ro_cw_invalidate(struct core_window *cw, const struct rect *r)
callback from core to request an invalidation of a window area.
Definition: corewindow.c:783
static void ro_cw_open(wimp_open *open)
Wimp callback on window open event.
Definition: corewindow.c:454
static nserror dummy_toolbar_update(struct ro_corewindow *ro_cw)
dummy toolbar update callback
Definition: corewindow.c:986
RISC OS core window interface.
int width
Definition: gui.c:159
nserror ro_warn_user(const char *warning, const char *detail)
Display a warning for a serious problem (eg memory exhaustion).
Definition: gui.c:2076
int height
Definition: gui.c:160
int os_version
Definition: gui.c:96
struct rect ro_plot_clip_rect
Definition: plotters.c:42
#define RISCOS5
Definition: gui.h:26
bool ro_toolbar_add_buttons(struct toolbar *toolbar, const struct button_bar_buttons buttons[], char *button_order)
Add a button bar to a toolbar, and configure the buttons.
Definition: toolbar.c:273
int ro_toolbar_height(struct toolbar *toolbar)
Return the current height of a toolbar, allowing for available window space.
Definition: toolbar.c:1519
int ro_toolbar_full_height(struct toolbar *toolbar)
Return the full height that a toolbar could grow to, if space is available.
Definition: toolbar.c:1527
bool ro_toolbar_rebuild(struct toolbar *toolbar)
(Re-)build a toolbar to use the specified (or current) theme.
Definition: toolbar.c:346
struct toolbar * ro_toolbar_create(struct theme_descriptor *descriptor, wimp_w parent, theme_style style, toolbar_flags bar_flags, const struct toolbar_callbacks *callbacks, void *client_data, const char *help)
Create a new toolbar, ready to have widgets added and to be attached to a window.
Definition: toolbar.c:219
Window toolbars (interface).
toolbar_action_type
Widget action types that the toolbar can pass on to clients.
Definition: toolbar.h:43
@ TOOLBAR_ACTION_BUTTON
Definition: toolbar.h:45
@ TOOLBAR_FLAGS_NONE
Definition: toolbar.h:34
enum browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons, wimp_icon_flags type)
Returns the state of the mouse buttons and modifiers keys for a mouse action, suitable for passing to...
Definition: window.c:4878
browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons, wimp_icon_flags type)
Returns the state of the mouse buttons and modifiers keys whilst dragging, for passing to the OS-inde...
Definition: window.c:4995
bool ro_gui_ctrl_pressed(void)
Returns true iff one or more Ctrl keys is held down.
Definition: window.c:5033
Callbacks to achieve various core window functionality.
Definition: core_window.h:51
nserror(* invalidate)(struct core_window *cw, const struct rect *rect)
Invalidate an area of a window.
Definition: core_window.h:69
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
ro core window state
Definition: corewindow.h:37
int origin_y
content plot origin y relative to window
Definition: corewindow.h:45
nserror(* toolbar_click)(struct ro_corewindow *ro_cw, button_bar_action action)
callback for clicks in ro core window toolbar.
Definition: corewindow.h:99
struct core_window_callback_table * cb_table
table of callbacks for core window operations
Definition: corewindow.h:57
nserror(* mouse)(struct ro_corewindow *ro_cw, browser_mouse_state mouse_state, int x, int y)
callback for mouse event on ro core window
Definition: corewindow.h:90
nserror(* toolbar_save)(struct ro_corewindow *ro_cw, char *config)
callback for saving ro core window toolbar state.
Definition: corewindow.h:116
wimp_w wh
window handle
Definition: corewindow.h:39
nserror(* key)(struct ro_corewindow *ro_cw, uint32_t nskey)
callback for keypress on ro core window
Definition: corewindow.h:79
nserror(* draw)(struct ro_corewindow *ro_cw, int originx, int originy, struct rect *r)
callback to draw on drawable area of ro core window
Definition: corewindow.h:68
int content_width
content width
Definition: corewindow.h:48
nserror(* toolbar_update)(struct ro_corewindow *ro_cw)
callback for updating state of buttons in ro core window toolbar.
Definition: corewindow.h:107
int content_height
content height
Definition: corewindow.h:51
struct toolbar * toolbar
toolbar
Definition: corewindow.h:42
core_window_drag_status drag_status
drag status set by core
Definition: corewindow.h:54
void(* theme_update)(void *, bool)
Call on theme update.
Definition: toolbar.h:63
NetSurf types.
Union to hold the different widget action data that can be passed from widget via toolbar to client.
Definition: toolbar.h:54
button_bar_action button
Definition: toolbar.h:55
bool ro_gui_wimp_event_register_keypress(wimp_w w, bool(*callback)(wimp_key *key))
Register a function to be called for all keypresses within a particular window.
Definition: wimp_event.c:1461
bool ro_gui_wimp_event_register_redraw_window(wimp_w w, void(*callback)(wimp_draw *redraw))
Register a function to be called for all window redraw operations.
Definition: wimp_event.c:1507
void ro_gui_wimp_event_finalise(wimp_w w)
Free any resources associated with a window.
Definition: wimp_event.c:296
void * ro_gui_wimp_event_get_user_data(wimp_w w)
Gets the user data associated with a window.
Definition: wimp_event.c:486
bool ro_gui_wimp_event_register_mouse_click(wimp_w w, bool(*callback)(wimp_pointer *pointer))
Register a function to be called for all mouse-clicks to icons in a window that don't have registered...
Definition: wimp_event.c:1439
bool ro_gui_wimp_event_set_user_data(wimp_w w, void *user)
Sets the user data associated with a window.
Definition: wimp_event.c:467
bool ro_gui_wimp_event_register_pointer_entering_window(wimp_w w, void(*callback)(wimp_entering *entering))
Register a function to be called for all pointer entering window requests.
Definition: wimp_event.c:1539
bool ro_gui_wimp_event_register_scroll_window(wimp_w w, void(*callback)(wimp_scroll *scroll))
Register a function to be called for all window scroll requests.
Definition: wimp_event.c:1523
bool ro_gui_wimp_event_register_open_window(wimp_w w, void(*callback)(wimp_open *open))
Register a function to be called for all window opening requests.
Definition: wimp_event.c:1477
bool ro_gui_wimp_event_process_window_menu_click(wimp_pointer *pointer)
Process a Menu click in a window, by checking for a registered window menu and opening it if one is f...
Definition: wimp_event.c:1186
Automated RISC OS WIMP event handling (interface).
#define IS_WIMP_KEY
Definition: wimp_event.h:37
A collection of grubby utilities for working with OSLib's wimp API.
#define PTR_WIMP_OPEN(pstate)
Definition: wimputils.h:39