NetSurf
frames.c
Go to the documentation of this file.
1/*
2 * Copyright 2006 Richard Wilson <info@tinct.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/** \file
20 * Frame and frameset creation and manipulation (implementation).
21 */
22
23#include <assert.h>
24#include <limits.h>
25#include <stdbool.h>
26#include <stdint.h>
27#include <stdlib.h>
28#include <string.h>
29#include <time.h>
30#include <math.h>
31
32#include "utils/log.h"
33#include "utils/utils.h"
34#include "netsurf/content.h"
35#include "content/hlcache.h"
36#include "html/html.h"
37#include "html/box.h"
38#include "html/box_inspect.h"
39
41#include "desktop/frames.h"
42#include "desktop/scrollbar.h"
43
44/** maximum frame resize margin */
45#define FRAME_RESIZE 6
46
48 struct browser_window *sibling, int x, int y, bool width,
49 bool height);
50
51
52/**
53 * Callback for (i)frame scrollbars.
54 */
55void browser_window_scroll_callback(void *client_data,
56 struct scrollbar_msg_data *scrollbar_data)
57{
58 struct browser_window *bw = client_data;
59
60 switch(scrollbar_data->msg) {
64 } else {
65 struct rect rect;
66
69 rect.x1 = rect.x0 + bw->width;
70 rect.y1 = rect.y0 + bw->height;
71
73 }
74 break;
76 {
77 struct rect rect = {
78 .x0 = scrollbar_data->x0,
79 .y0 = scrollbar_data->y0,
80 .x1 = scrollbar_data->x1,
81 .y1 = scrollbar_data->y1
82 };
83
84 if (scrollbar_is_horizontal(scrollbar_data->scrollbar))
86 else
88 }
89 break;
92
94 break;
95 }
96}
97
98/* exported interface, documented in browser.h */
100{
101 struct hlcache_handle *h = bw->current_content;
102 bool scroll_x;
103 bool scroll_y;
104 int c_width = 0;
105 int c_height = 0;
106
107 assert(!bw->window); /* Core-handled windows only */
108
109 if (h != NULL) {
110 c_width = content_get_width(h);
111 c_height = content_get_height(h);
112 }
113
114 if (bw->scrolling == BW_SCROLLING_YES) {
115 scroll_x = true;
116 scroll_y = true;
117 } else if (bw->scrolling == BW_SCROLLING_AUTO &&
118 bw->current_content) {
119 int bw_width = bw->width;
120 int bw_height = bw->height;
121
122 /* subtract existing scrollbar width */
123 bw_width -= bw->scroll_y ? SCROLLBAR_WIDTH : 0;
124 bw_height -= bw->scroll_x ? SCROLLBAR_WIDTH : 0;
125
126 scroll_y = (c_height > bw_height) ? true : false;
127 scroll_x = (c_width > bw_width) ? true : false;
128 } else {
129 /* No scrollbars */
130 scroll_x = false;
131 scroll_y = false;
132 }
133
134 if (!scroll_x && bw->scroll_x != NULL) {
136 bw->scroll_x = NULL;
137 }
138
139 if (!scroll_y && bw->scroll_y != NULL) {
141 bw->scroll_y = NULL;
142 }
143
144 if (scroll_y) {
145 int length = bw->height;
146 int visible = bw->height - (scroll_x ? SCROLLBAR_WIDTH : 0);
147
148 if (bw->scroll_y == NULL) {
149 /* create vertical scrollbar */
150 if (scrollbar_create(false, length, c_height, visible,
152 &(bw->scroll_y)) != NSERROR_OK) {
153 return;
154 }
155 } else {
156 /* update vertical scrollbar */
158 visible, c_height);
159 }
160 }
161
162 if (scroll_x) {
163 int length = bw->width - (scroll_y ? SCROLLBAR_WIDTH : 0);
164 int visible = length;
165
166 if (bw->scroll_x == NULL) {
167 /* create horizontal scrollbar */
168 if (scrollbar_create(true, length, c_width, visible,
170 &(bw->scroll_x)) != NSERROR_OK) {
171 return;
172 }
173 } else {
174 /* update horizontal scrollbar */
176 visible, c_width);
177 }
178 }
179
180 if (scroll_x && scroll_y)
182}
183
184/* exported function documented in desktop/frames.h */
186{
188 return NSERROR_OK;
189}
190
191/* exported function documented in desktop/frames.h */
193{
194 nserror ret = NSERROR_OK;
195 struct browser_window *window;
196 struct content_html_iframe *cur;
197 struct rect rect;
198 int iframes = 0;
199 int index;
200 struct content_html_iframe *iframe;
201
202 bw->iframe_count = 0;
203
204 /* only html contents can have iframes */
206 return NSERROR_OK;
207 }
208
209 /* obtain the iframes for this content */
210 iframe = html_get_iframe(bw->current_content);
211 if (iframe == NULL) {
212 return NSERROR_OK;
213 }
214
215 /* Count iframe list and allocate enough space within the
216 * browser window.
217 */
218 for (cur = iframe; cur; cur = cur->next) {
219 iframes++;
220 }
221 bw->iframes = calloc(iframes, sizeof(*bw));
222 if (!bw->iframes) {
223 return NSERROR_NOMEM;
224 }
225 bw->iframe_count = iframes;
226
227 index = 0;
228 for (cur = iframe; cur; cur = cur->next) {
229 window = &(bw->iframes[index++]);
230
231 /* Initialise common parts */
233 window, NULL);
234
235 /* window characteristics */
236 window->browser_window_type = BROWSER_WINDOW_IFRAME;
237 window->scrolling = cur->scrolling;
238 window->border = cur->border;
239 window->border_colour = cur->border_colour;
240 window->no_resize = true;
241 window->margin_width = cur->margin_width;
242 window->margin_height = cur->margin_height;
243 window->scale = bw->scale;
244 if (cur->name != NULL) {
245 window->name = strdup(cur->name);
246 if (window->name == NULL) {
247 free(bw->iframes) ;
248 bw->iframes = 0;
249 bw->iframe_count = 0;
250 return NSERROR_NOMEM;
251 }
252 }
253
254 /* linking */
255 window->box = cur->box;
256 window->parent = bw;
257 window->box->iframe = window;
258
259 /* iframe dimensions */
260 box_bounds(window->box, &rect);
261
264 rect.y1 - rect.y0);
265 }
266
267 /* calculate dimensions */
270
271 index = 0;
272 for (cur = iframe; cur; cur = cur->next) {
273 window = &(bw->iframes[index++]);
274 if (cur->url) {
275 /* fetch iframe's content */
276 ret = browser_window_navigate(window,
277 cur->url,
280 NULL,
281 NULL,
282 bw->current_content);
283 }
284 }
285
286 return ret;
287}
288
289
290/* exported function documented in desktop/frames.h */
292{
293 struct browser_window *window;
294 int index;
295
296 for (index = 0; index < bw->iframe_count; index++) {
297 window = &(bw->iframes[index]);
298
299 if (window != NULL) {
301 }
302 }
303}
304
305
306/* exported function documented in desktop/frames.h */
308{
309 int i;
310
311 if (bw->iframes != NULL) {
312 for (i = 0; i < bw->iframe_count; i++) {
313 if (bw->iframes[i].box != NULL) {
314 bw->iframes[i].box->iframe = NULL;
315 bw->iframes[i].box = NULL;
316 }
318 }
319 free(bw->iframes);
320 bw->iframes = NULL;
321 bw->iframe_count = 0;
322 }
323 return NSERROR_OK;
324}
325
326
327/**
328 * Recalculate frameset positions following a resize.
329 *
330 * \param bw The browser window to reposition framesets for
331 */
333{
334 int widths[bw->cols][bw->rows];
335 int heights[bw->cols][bw->rows];
336 int bw_width, bw_height;
337 int avail_width, avail_height;
338 int row, row2, col, index;
339 struct browser_window *window;
340 float relative;
341 int size, extent, applied;
342 int x, y;
343 int new_width, new_height;
344
345 assert(bw);
346
347 /* window dimensions */
348 if (!bw->parent) {
349 browser_window_get_dimensions(bw, &bw_width, &bw_height);
350 bw_width /= bw->scale;
351 bw_height /= bw->scale;
352 bw->x = 0;
353 bw->y = 0;
354 bw->width = bw_width;
355 bw->height = bw_height;
356 } else {
357 bw_width = bw->width;
358 bw_height = bw->height;
359 }
360 bw_width++;
361 bw_height++;
362
363 /* widths */
364 for (row = 0; row < bw->rows; row++) {
365 avail_width = bw_width;
366 relative = 0;
367 for (col = 0; col < bw->cols; col++) {
368 index = (row * bw->cols) + col;
369 window = &bw->children[index];
370
371 switch (window->frame_width.unit) {
372 case FRAME_DIMENSION_PIXELS:
373 widths[col][row] = window->frame_width.value *
374 window->scale;
375 if (window->border) {
376 if (col != 0)
377 widths[col][row] += 1;
378 if (col != bw->cols - 1)
379 widths[col][row] += 1;
380 }
381 break;
382 case FRAME_DIMENSION_PERCENT:
383 widths[col][row] = bw_width *
384 window->frame_width.value / 100;
385 break;
386 case FRAME_DIMENSION_RELATIVE:
387 widths[col][row] = 0;
388 relative += window->frame_width.value;
389 break;
390 default:
391 /* unknown frame dimension unit */
392 assert(window->frame_width.unit ==
393 FRAME_DIMENSION_PIXELS ||
394 window->frame_width.unit ==
395 FRAME_DIMENSION_PERCENT ||
396 window->frame_width.unit ==
397 FRAME_DIMENSION_RELATIVE);
398 break;
399 }
400 avail_width -= widths[col][row];
401 }
402
403 /* Redistribute to fit window */
404 if ((relative > 0) && (avail_width > 0)) {
405 /* Expand the relative sections to fill remainder */
406 for (col = 0; col < bw->cols; col++) {
407 index = (row * bw->cols) + col;
408 window = &bw->children[index];
409
410 if (window->frame_width.unit ==
411 FRAME_DIMENSION_RELATIVE) {
412 size = avail_width * window->
414 relative;
415 avail_width -= size;
416 relative -= window->frame_width.value;
417 widths[col][row] += size;
418 }
419 }
420 } else if (bw_width != avail_width) {
421 /* proportionally distribute error */
422 extent = avail_width;
423 applied = 0;
424 for (col = 0; col < bw->cols; col++) {
425 if (col == bw->cols - 1) {
426 /* Last cell, use up remainder */
427 widths[col][row] += extent - applied;
428 widths[col][row] =
429 widths[col][row] < 0 ?
430 0 : widths[col][row];
431 } else {
432 /* Find size of cell adjustment */
433 size = (widths[col][row] * extent) /
434 (bw_width - extent);
435 /* Modify cell */
436 widths[col][row] += size;
437 applied += size;
438 }
439 }
440 }
441 }
442
443 /* heights */
444 for (col = 0; col < bw->cols; col++) {
445 avail_height = bw_height;
446 relative = 0;
447 for (row = 0; row < bw->rows; row++) {
448 index = (row * bw->cols) + col;
449 window = &bw->children[index];
450
451 switch (window->frame_height.unit) {
452 case FRAME_DIMENSION_PIXELS:
453 heights[col][row] = window->frame_height.value *
454 window->scale;
455 if (window->border) {
456 if (row != 0)
457 heights[col][row] += 1;
458 if (row != bw->rows - 1)
459 heights[col][row] += 1;
460 }
461 break;
462 case FRAME_DIMENSION_PERCENT:
463 heights[col][row] = bw_height *
464 window->frame_height.value / 100;
465 break;
466 case FRAME_DIMENSION_RELATIVE:
467 heights[col][row] = 0;
468 relative += window->frame_height.value;
469 break;
470 default:
471 /* unknown frame dimension unit */
472 assert(window->frame_height.unit ==
473 FRAME_DIMENSION_PIXELS ||
474 window->frame_height.unit ==
475 FRAME_DIMENSION_PERCENT ||
476 window->frame_height.unit ==
477 FRAME_DIMENSION_RELATIVE);
478 break;
479 }
480 avail_height -= heights[col][row];
481 }
482
483 if (avail_height == 0)
484 continue;
485
486 /* Redistribute to fit window */
487 if ((relative > 0) && (avail_height > 0)) {
488 /* Expand the relative sections to fill remainder */
489 for (row = 0; row < bw->rows; row++) {
490 index = (row * bw->cols) + col;
491 window = &bw->children[index];
492
493 if (window->frame_height.unit ==
494 FRAME_DIMENSION_RELATIVE) {
495 size = avail_height * window->
497 relative;
498 avail_height -= size;
499 relative -= window->frame_height.value;
500 heights[col][row] += size;
501 }
502 }
503 } else if (bw_height != avail_height) {
504 /* proportionally distribute error */
505 extent = avail_height;
506 applied = 0;
507 for (row = 0; row < bw->rows; row++) {
508 if (row == bw->rows - 1) {
509 /* Last cell, use up remainder */
510 heights[col][row] += extent - applied;
511 heights[col][row] =
512 heights[col][row] < 0 ?
513 0 : heights[col][row];
514 } else {
515 /* Find size of cell adjustment */
516 size = (heights[col][row] * extent) /
517 (bw_height - extent);
518 /* Modify cell */
519 heights[col][row] += size;
520 applied += size;
521 }
522 }
523 }
524 }
525
526 /* position frames and calculate children */
527 for (row = 0; row < bw->rows; row++) {
528 x = 0;
529 for (col = 0; col < bw->cols; col++) {
530 index = (row * bw->cols) + col;
531 window = &bw->children[index];
532
533 y = 0;
534 for (row2 = 0; row2 < row; row2++)
535 y+= heights[col][row2];
536
537 window->x = x;
538 window->y = y;
539
540 new_width = widths[col][row] - 1;
541 new_height = heights[col][row] - 1;
542
543 if (window->width != new_width ||
544 window->height != new_height) {
545 /* Change in frame size */
547 new_width * bw->scale,
548 new_height * bw->scale);
549 window->width = new_width;
550 window->height = new_height;
551
553 }
554
555 x += widths[col][row];
556
557 if (window->children)
559 }
560 }
561}
562
563
564/**
565 * Create and open a frameset for a browser window.
566 *
567 * \param[in,out] bw The browser window to create the frameset for
568 * \param[in] frameset The frameset to create
569 * \return NSERROR_OK or error code on faliure
570 */
571static nserror
573 struct content_html_frames *frameset)
574{
575 int row, col, index;
576 struct content_html_frames *frame;
577 struct browser_window *window;
579
580 assert(bw && frameset);
581
582 /* 1. Create children */
583 assert(bw->children == NULL);
584 assert(frameset->cols + frameset->rows != 0);
585
586 bw->children = calloc((frameset->cols * frameset->rows), sizeof(*bw));
587 if (!bw->children) {
588 return NSERROR_NOMEM;
589 }
590
591 bw->cols = frameset->cols;
592 bw->rows = frameset->rows;
593 for (row = 0; row < bw->rows; row++) {
594 for (col = 0; col < bw->cols; col++) {
595 index = (row * bw->cols) + col;
596 frame = &frameset->children[index];
597 window = &bw->children[index];
598
599 /* Initialise common parts */
601 window, NULL);
602
603 /* window characteristics */
604 if (frame->children)
605 window->browser_window_type =
607 else
608 window->browser_window_type =
610 window->scrolling = frame->scrolling;
611 window->border = frame->border;
612 window->border_colour = frame->border_colour;
613 window->no_resize = frame->no_resize;
614 window->frame_width = frame->width;
615 window->frame_height = frame->height;
616 window->margin_width = frame->margin_width;
617 window->margin_height = frame->margin_height;
618 if (frame->name) {
619 window->name = strdup(frame->name);
620 if (!window->name) {
621 free(bw->children);
622 bw->children = NULL;
623 return NSERROR_NOMEM;
624 }
625 }
626
627 window->scale = bw->scale;
628
629 /* linking */
630 window->parent = bw;
631
632 if (window->name)
633 NSLOG(netsurf, INFO, "Created frame '%s'",
634 window->name);
635 else
636 NSLOG(netsurf, INFO,
637 "Created frame (unnamed)");
638 }
639 }
640
641 /* 2. Calculate dimensions */
644
645 /* 3. Recurse for grandchildren */
646 for (row = 0; row < bw->rows; row++) {
647 for (col = 0; col < bw->cols; col++) {
648 index = (row * bw->cols) + col;
649 frame = &frameset->children[index];
650 window = &bw->children[index];
651
652 if (frame->children)
654 }
655 }
656
657 /* Use the URL of the first ancestor window containing html content
658 * as the referer */
659 for (window = bw; window->parent; window = window->parent) {
660 if (window->current_content &&
661 content_get_type(window->current_content) ==
663 break;
664 }
665
666 parent = window->current_content;
667
668 /* 4. Launch content */
669 for (row = 0; row < bw->rows; row++) {
670 for (col = 0; col < bw->cols; col++) {
671 index = (row * bw->cols) + col;
672 frame = &frameset->children[index];
673 window = &bw->children[index];
674
675 if (frame->url) {
677 frame->url,
681 NULL,
682 NULL,
683 parent);
684 }
685 }
686 }
687
688 return NSERROR_OK;
689}
690
691
692/* exported interface documented in desktop/frames.h */
694{
695 struct content_html_frames *frameset;
696
698 return NSERROR_OK;
699 }
700
701 frameset = html_get_frameset(bw->current_content);
702 if (frameset == NULL) {
703 return NSERROR_OK;
704 }
705
706 return browser_window_create_frameset_internal(bw, frameset);
707}
708
709
710
711
712/**
713 * Recalculate frameset positions following a resize.
714 *
715 * \param bw The browser window to reposition framesets for
716 */
717
719{
721 return;
722 }
723
724 if (html_get_frameset(bw->current_content) == NULL) {
725 return;
726 }
727
729}
730
731
732/**
733 * Resize a browser window that is a frame.
734 *
735 * \param bw The browser window to resize
736 * \param x The new width to set.
737 * \param y The new height to set.
738 */
739
740void browser_window_resize_frame(struct browser_window *bw, int x, int y)
741{
742 struct browser_window *parent;
743 struct browser_window *sibling;
744 int col = -1, row = -1, i;
745 bool change = false;
746
747 parent = bw->parent;
748 assert(parent);
749
750 /* get frame location */
751 for (i = 0; i < (parent->cols * parent->rows); i++) {
752 if (&parent->children[i] == bw) {
753 col = i % parent->cols;
754 row = i / parent->cols;
755 }
756 }
757 assert((col >= 0) && (row >= 0));
758
759 sibling = NULL;
760 if (bw->drag.resize_left) {
761 sibling = &parent->children[row * parent->cols + (col - 1)];
762 } else if (bw->drag.resize_right) {
763 sibling = &parent->children[row * parent->cols + (col + 1)];
764 }
765 if (sibling) {
767 x, y, true, false);
768 }
769
770 sibling = NULL;
771 if (bw->drag.resize_up) {
772 sibling = &parent->children[(row - 1) * parent->cols + col];
773 } else if (bw->drag.resize_down) {
774 sibling = &parent->children[(row + 1) * parent->cols + col];
775 }
776
777 if (sibling) {
779 x, y, false, true);
780 }
781
782 if (change) {
784 }
785}
786
787
789 struct browser_window *sibling,
790 int x, int y, bool width, bool height)
791{
792 int bw_dimension, sibling_dimension;
793 int bw_pixels, sibling_pixels;
794 struct frame_dimension *bw_d, *sibling_d;
795 float total_new;
796 int frame_size;
797
798 assert(!(width && height));
799
800 /* extend/shrink the box to the pointer */
801 if (width) {
802 if (bw->drag.resize_left) {
803 bw_dimension = bw->x + bw->width - x;
804 } else {
805 bw_dimension = x - bw->x;
806 }
807 bw_pixels = bw->width;
808 sibling_pixels = sibling->width;
809 bw_d = &bw->frame_width;
810 sibling_d = &sibling->frame_width;
811 frame_size = bw->parent->width;
812 } else {
813 if (bw->drag.resize_up) {
814 bw_dimension = bw->y + bw->height - y;
815 } else {
816 bw_dimension = y - bw->y;
817 }
818 bw_pixels = bw->height;
819 sibling_pixels = sibling->height;
820 bw_d = &bw->frame_height;
821 sibling_d = &sibling->frame_height;
822 frame_size = bw->parent->height;
823 }
824 sibling_dimension = bw_pixels + sibling_pixels - bw_dimension;
825
826 /* check for no change or no frame size*/
827 if ((bw_dimension == bw_pixels) || (frame_size == 0))
828 return false;
829 /* check for both being 0 */
830 total_new = bw_dimension + sibling_dimension;
831 if ((bw_dimension + sibling_dimension) == 0)
832 return false;
833
834 /* our frame dimensions are now known to be:
835 *
836 * <-- frame_size --> [VISIBLE PIXELS]
837 * |<-- bw_pixels -->|<-- sibling_pixels -->| [VISIBLE PIXELS, BEFORE RESIZE]
838 * |<-- bw_d->value-->|<-- sibling_d->value-->| [SPECIFIED UNITS, BEFORE RESIZE]
839 * |<--bw_dimension-->|<--sibling_dimension-->| [VISIBLE PIXELS, AFTER RESIZE]
840 * |<-- total_new -->| [VISIBLE PIXELS, AFTER RESIZE]
841 *
842 * when we resize, we must retain the original unit specification such that any
843 * subsequent resizing of the parent window will recalculate the page as the
844 * author specified.
845 *
846 * if the units of both frames are the same then we can resize the values simply
847 * by updating the values to be a percentage of the original widths.
848 */
849 if (bw_d->unit == sibling_d->unit) {
850 float total_specified = bw_d->value + sibling_d->value;
851 bw_d->value = (total_specified * bw_dimension) / total_new;
852 sibling_d->value = total_specified - bw_d->value;
853 return true;
854 }
855
856 /* if one of the sizes is relative then we don't alter the relative width and
857 * just let it reflow across. the non-relative (pixel/percentage) value can
858 * simply be resolved to the specified width that will result in the required
859 * dimension.
860 */
861 if (bw_d->unit == FRAME_DIMENSION_RELATIVE) {
862 if ((sibling_pixels == 0) && (bw_dimension == 0))
863 return false;
864 if (fabs(sibling_d->value) < 0.0001)
865 bw_d->value = 1;
866 if (sibling_pixels == 0)
867 sibling_d->value = (sibling_d->value * bw_pixels) / bw_dimension;
868 else
869 sibling_d->value =
870 (sibling_d->value * sibling_dimension) / sibling_pixels;
871
872 /* todo: the availble resize may have changed, update the drag box */
873 return true;
874 } else if (sibling_d->unit == FRAME_DIMENSION_RELATIVE) {
875 if ((bw_pixels == 0) && (sibling_dimension == 0))
876 return false;
877 if (fabs(bw_d->value) < 0.0001)
878 bw_d->value = 1;
879 if (bw_pixels == 0)
880 bw_d->value = (bw_d->value * sibling_pixels) / sibling_dimension;
881 else
882 bw_d->value = (bw_d->value * bw_dimension) / bw_pixels;
883
884 /* todo: the availble resize may have changed, update the drag box */
885 return true;
886 }
887
888 /* finally we have a pixel/percentage mix. unlike relative values, percentages
889 * can easily be backwards-calculated as they can simply be scaled like pixel
890 * values
891 */
892 if (bw_d->unit == FRAME_DIMENSION_PIXELS) {
893 float total_specified = bw_d->value + frame_size * sibling_d->value / 100;
894 bw_d->value = (total_specified * bw_dimension) / total_new;
895 sibling_d->value = (total_specified - bw_d->value) * 100 / frame_size;
896 return true;
897 } else if (sibling_d->unit == FRAME_DIMENSION_PIXELS) {
898 float total_specified = bw_d->value * frame_size / 100 + sibling_d->value;
899 sibling_d->value = (total_specified * sibling_dimension) / total_new;
900 bw_d->value = (total_specified - sibling_d->value) * 100 / frame_size;
901 return true;
902 }
903 assert(!"Invalid frame dimension unit");
904 return false;
905}
906
907
909 browser_mouse_state mouse, int x, int y,
910 browser_pointer_shape *pointer)
911{
912 struct browser_window *parent;
913 bool left, right, up, down;
914 int i, resize_margin;
915
916 if ((x < bw->x) || (x > bw->x + bw->width) ||
917 (y < bw->y) || (y > bw->y + bw->height))
918 return false;
919
920 parent = bw->parent;
921 if ((!bw->no_resize) && parent) {
922 resize_margin = FRAME_RESIZE;
923 if (resize_margin * 2 > bw->width)
924 resize_margin = bw->width / 2;
925 left = (x < bw->x + resize_margin);
926 right = (x > bw->x + bw->width - resize_margin);
927 resize_margin = FRAME_RESIZE;
928 if (resize_margin * 2 > bw->height)
929 resize_margin = bw->height / 2;
930 up = (y < bw->y + resize_margin);
931 down = (y > bw->y + bw-> height - resize_margin);
932
933 /* check if the edges can actually be moved */
934 if (left || right || up || down) {
935 int row = -1, col = -1;
936 switch (bw->browser_window_type) {
939 assert(0);
940 break;
943 break;
944 }
945 for (i = 0; i < (parent->cols * parent->rows); i++) {
946 if (&parent->children[i] == bw) {
947 col = i % parent->cols;
948 row = i / parent->cols;
949 break;
950 }
951 }
952 assert((row >= 0) && (col >= 0));
953
954 /* check the sibling frame is within bounds */
955 left &= (col > 0);
956 right &= (col < parent->cols - 1);
957 up &= (row > 0);
958 down &= (row < parent->rows - 1);
959
960 /* check the sibling frames can be resized */
961 if (left)
962 left &= !parent->children[row *
963 parent->cols + (col - 1)].
964 no_resize;
965 if (right)
966 right &= !parent->children[row *
967 parent->cols + (col + 1)].
968 no_resize;
969 if (up)
970 up &= !parent->children[(row - 1) *
971 parent->cols + col].
972 no_resize;
973 if (down)
974 down &= !parent->children[(row + 1) *
975 parent->cols + col].
976 no_resize;
977
978 /* can't have opposite directions simultaneously */
979 if (up)
980 down = false;
981 if (left)
982 right = false;
983 }
984
985 if (left || right || up || down) {
986 if (left) {
987 if (down)
988 *pointer = BROWSER_POINTER_LD;
989 else if (up)
990 *pointer = BROWSER_POINTER_LU;
991 else
992 *pointer = BROWSER_POINTER_LEFT;
993 } else if (right) {
994 if (down)
995 *pointer = BROWSER_POINTER_RD;
996 else if (up)
997 *pointer = BROWSER_POINTER_RU;
998 else
999 *pointer = BROWSER_POINTER_RIGHT;
1000 } else if (up) {
1001 *pointer = BROWSER_POINTER_UP;
1002 } else {
1003 *pointer = BROWSER_POINTER_DOWN;
1004 }
1005 if (mouse & (BROWSER_MOUSE_DRAG_1 |
1007
1008 /* TODO: Pass appropriate rectangle to allow
1009 * front end to clamp pointer range */
1011 DRAGGING_FRAME, NULL);
1012 bw->drag.start_x = x;
1013 bw->drag.start_y = y;
1014 bw->drag.resize_left = left;
1015 bw->drag.resize_right = right;
1016 bw->drag.resize_up = up;
1017 bw->drag.resize_down = down;
1018 }
1019 return true;
1020 }
1021 }
1022
1023 if (bw->children) {
1024 for (i = 0; i < (bw->cols * bw->rows); i++)
1026 mouse, x, y, pointer))
1027 return true;
1028 }
1029 if (bw->iframes) {
1030 for (i = 0; i < bw->iframe_count; i++)
1032 mouse, x, y, pointer))
1033 return true;
1034 }
1035 return false;
1036}
1037
1038
1040 browser_mouse_state mouse, int x, int y,
1041 browser_pointer_shape *pointer)
1042{
1044 int offx, offy;
1045
1046 browser_window_get_position(bw, true, &offx, &offy);
1047
1048 return browser_window_resize_frames(root, mouse,
1049 x + offx, y + offy, pointer);
1050}
Box interface.
void box_bounds(struct box *box, struct rect *r)
Find the bounds of a box.
Definition: box_inspect.c:567
HTML Box tree inspection interface.
Browser window private structure.
nserror browser_window_initialise_common(enum browser_window_create_flags flags, struct browser_window *bw, const struct browser_window *existing)
Initialise common parts of a browser window.
void browser_window_update_extent(struct browser_window *bw)
Update the extent of the inside of a browser window to that of the current content.
nserror browser_window_get_dimensions(struct browser_window *bw, int *width, int *height)
Get the dimensions of the area a browser window occupies.
nserror browser_window_destroy_internal(struct browser_window *bw)
Release all memory associated with a browser window.
nserror browser_window_invalidate_rect(struct browser_window *bw, struct rect *rect)
Cause an area of a browser window to be marked invalid and hence redrawn.
struct browser_window * browser_window_get_root(struct browser_window *bw)
Get the root level browser window.
@ DRAGGING_SCR_Y
@ DRAGGING_SCR_X
@ DRAGGING_NONE
@ DRAGGING_FRAME
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.
void browser_window_set_drag_type(struct browser_window *bw, browser_drag_type type, const struct rect *rect)
Set drag type for a browser window, and inform front end.
void browser_window_set_position(struct browser_window *bw, int x, int y)
Set the position of the current browser window with respect to the parent browser window.
@ BW_SCROLLING_AUTO
@ BW_SCROLLING_YES
void browser_window_set_dimensions(struct browser_window *bw, int width, int height)
Set the dimensions of the area a browser window occupies.
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.
void browser_window_get_position(struct browser_window *bw, bool root, int *pos_x, int *pos_y)
Get the position of the current browser window with respect to the root or parent browser window.
@ BW_CREATE_NONE
No flags set.
@ BW_NAVIGATE_HISTORY
this will form a new history node (don't set for back/reload/etc)
@ BW_NAVIGATE_UNVERIFIABLE
Transation not caused by user interaction (e.g.
void browser_window_set_pointer(struct browser_window *bw, browser_pointer_shape shape)
Change the shape of the mouse pointer.
@ CONTENT_HTML
content is HTML
Definition: content_type.h:58
wimp_w parent
Definition: dialog.c:88
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
static struct directory * root
Definition: filename.c:55
#define FRAME_RESIZE
maximum frame resize margin
Definition: frames.c:45
nserror browser_window_destroy_iframes(struct browser_window *bw)
Destroy iframes opened in browser_window_create_iframes()
Definition: frames.c:307
void browser_window_recalculate_frameset(struct browser_window *bw)
Recalculate frameset positions following a resize.
Definition: frames.c:718
void browser_window_scroll_callback(void *client_data, struct scrollbar_msg_data *scrollbar_data)
Callback for (i)frame scrollbars.
Definition: frames.c:55
static void browser_window_recalculate_frameset_internal(struct browser_window *bw)
Recalculate frameset positions following a resize.
Definition: frames.c:332
void browser_window_recalculate_iframes(struct browser_window *bw)
Recalculate iframe positions following a resize.
Definition: frames.c:291
bool browser_window_frame_resize_start(struct browser_window *bw, browser_mouse_state mouse, int x, int y, browser_pointer_shape *pointer)
Definition: frames.c:1039
void browser_window_handle_scrollbars(struct browser_window *bw)
Create, remove, and update browser window scrollbars.
Definition: frames.c:99
nserror browser_window_create_iframes(struct browser_window *bw)
Create and open iframes for a browser window.
Definition: frames.c:192
static bool browser_window_resolve_frame_dimension(struct browser_window *bw, struct browser_window *sibling, int x, int y, bool width, bool height)
Definition: frames.c:788
nserror browser_window_invalidate_iframe(struct browser_window *bw)
Invalidate an iframe causing a redraw.
Definition: frames.c:185
static bool browser_window_resize_frames(struct browser_window *bw, browser_mouse_state mouse, int x, int y, browser_pointer_shape *pointer)
Definition: frames.c:908
static nserror browser_window_create_frameset_internal(struct browser_window *bw, struct content_html_frames *frameset)
Create and open a frameset for a browser window.
Definition: frames.c:572
void browser_window_resize_frame(struct browser_window *bw, int x, int y)
Resize a browser window that is a frame.
Definition: frames.c:740
nserror browser_window_create_frameset(struct browser_window *bw)
Create and open a frameset for a browser window.
Definition: frames.c:693
Frame and frameset creation and manipulation (interface).
High-level resource cache interface.
void html_redraw_a_box(hlcache_handle *h, struct box *box)
Redraw a box.
Definition: html.c:1111
struct content_html_iframe * html_get_iframe(hlcache_handle *h)
Retrieve iframes used in an HTML document.
Definition: html.c:2024
struct content_html_frames * html_get_frameset(hlcache_handle *h)
Retrieve framesets used in an HTML document.
Definition: html.c:2009
Interface to text/html content handler.
Public content interface.
struct nsurl * hlcache_handle_get_url(const struct hlcache_handle *handle)
Retrieve the URL associated with a high level cache handle.
int content_get_height(struct hlcache_handle *h)
Retrieve height of content.
Definition: content.c:1175
int content_get_width(struct hlcache_handle *h)
Retrieve width of content.
Definition: content.c:1158
content_type content_get_type(struct hlcache_handle *h)
Retrieve computed type of content.
Definition: content.c:1061
browser_pointer_shape
Mouse pointer type.
Definition: mouse.h:135
@ BROWSER_POINTER_RD
Definition: mouse.h:147
@ BROWSER_POINTER_UP
Definition: mouse.h:140
@ BROWSER_POINTER_LEFT
Definition: mouse.h:142
@ BROWSER_POINTER_LD
Definition: mouse.h:145
@ BROWSER_POINTER_DOWN
Definition: mouse.h:141
@ BROWSER_POINTER_RIGHT
Definition: mouse.h:143
@ BROWSER_POINTER_LU
Definition: mouse.h:146
@ BROWSER_POINTER_DEFAULT
Definition: mouse.h:136
@ BROWSER_POINTER_RU
Definition: mouse.h:144
browser_mouse_state
Mouse state: 1 is primary mouse button.
Definition: mouse.h:52
@ BROWSER_MOUSE_DRAG_1
start of button 1 drag
Definition: mouse.h:86
@ BROWSER_MOUSE_DRAG_2
start of button 2 drag
Definition: mouse.h:88
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
int width
Definition: gui.c:160
int height
Definition: gui.c:161
bool scrollbar_is_horizontal(struct scrollbar *s)
Check orientation of the scrollbar.
Definition: scrollbar.c:695
void scrollbar_make_pair(struct scrollbar *horizontal, struct scrollbar *vertical)
Connect a horizontal and a vertical scrollbar into a pair so that they co-operate during 2D drags.
Definition: scrollbar.c:990
int scrollbar_get_offset(struct scrollbar *s)
Get the current scroll offset to the visible part of the full area.
Definition: scrollbar.c:628
nserror scrollbar_create(bool horizontal, int length, int full_size, int visible_size, void *client_data, scrollbar_client_callback client_callback, struct scrollbar **s)
Create a scrollbar.
Definition: scrollbar.c:93
void scrollbar_destroy(struct scrollbar *s)
Destroy a scrollbar.
Definition: scrollbar.c:138
void scrollbar_set_extents(struct scrollbar *s, int length, int visible_size, int full_size)
Set the length of the scrollbar widget, the size of the visible area, and the size of the full area.
Definition: scrollbar.c:640
Scrollbar widget interface.
@ SCROLLBAR_MSG_MOVED
the scroll value has changed
Definition: scrollbar.h:47
@ SCROLLBAR_MSG_SCROLL_START
a scrollbar drag has started, all mouse events should be passed to the scrollbar regardless of the co...
Definition: scrollbar.h:48
@ SCROLLBAR_MSG_SCROLL_FINISHED
cancel a scrollbar drag
Definition: scrollbar.h:53
#define SCROLLBAR_WIDTH
Definition: scrollbar.h:32
Interface to utility string handling.
struct browser_window * iframe
Iframe's browser_window, or NULL if none.
Definition: box.h:452
Browser window data.
browser_scrolling scrolling
struct browser_window * iframes
struct scrollbar * scroll_x
Horizontal scroll.
unsigned int resize_up
struct browser_window::@59 drag
Current drag status.
int x
Window dimensions.
struct browser_window * bw
float scale
scale of window contents
struct frame_dimension frame_height
int rows
frameset characteristics
struct scrollbar * scroll_y
Vertical scroll.
int iframe_count
[iframe_count] iframes
unsigned int resize_left
Frame resize directions for current frame resize drag.
struct browser_window * parent
unsigned int resize_right
struct gui_window * window
Platform specific window data only valid at top level.
int start_x
Mouse position at start of current scroll drag.
bool no_resize
frame characteristics
struct box * box
iframe parent box
struct browser_window * children
[cols * rows] children
struct hlcache_handle * current_content
Content handle of page currently displayed which must have READY or DONE status or NULL for no conten...
unsigned int resize_down
char * name
frame name for targetting
enum browser_window::@60 browser_window_type
Window characteristics.
struct frame_dimension frame_width
frame dimensions
Frame tree (frameset or frame tag)
Definition: html.h:108
char * name
frame margin height
Definition: html.h:117
int rows
number of columns in frameset
Definition: html.h:110
struct content_html_frames * children
frame border colour
Definition: html.h:125
bool no_resize
frame url
Definition: html.h:120
int margin_width
frame width
Definition: html.h:114
struct nsurl * url
frame name (for targetting)
Definition: html.h:118
browser_scrolling scrolling
frame is not resizable
Definition: html.h:121
bool border
scrolling characteristics
Definition: html.h:122
colour border_colour
frame has a border
Definition: html.h:123
int margin_height
frame margin width
Definition: html.h:115
struct frame_dimension width
number of rows in frameset
Definition: html.h:112
struct frame_dimension height
frame width
Definition: html.h:113
Inline frame list (iframe tag)
Definition: html.h:131
struct content_html_iframe * next
frame border colour
Definition: html.h:144
struct box * box
Definition: html.h:132
int margin_height
frame margin width
Definition: html.h:135
browser_scrolling scrolling
frame url
Definition: html.h:140
struct nsurl * url
frame name (for targetting)
Definition: html.h:138
colour border_colour
frame has a border
Definition: html.h:142
bool border
scrolling characteristics
Definition: html.h:141
char * name
frame margin height
Definition: html.h:137
enum frame_dimension::@63 unit
@ FRAME_DIMENSION_RELATIVE
Definition: frame_types.h:32
int height
height of drawing area
Definition: browser.h:34
int width
width of window
Definition: browser.h:34
float scale
Definition: gui.h:155
High-level cache handle.
Definition: hlcache.c:66
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
scrollbar message context data
Definition: scrollbar.h:59
struct scrollbar * scrollbar
Definition: scrollbar.h:60
scrollbar_msg msg
Definition: scrollbar.h:61
Interface to time operations.
Interface to a number of general purpose functionality.