Commit 0fc8c475a840527ec9a4bb030939f7c7e0dc0bde
- Diff rendering mode:
- inline
- side by side
gdk/x11/gdkgeometry-x11.c
(0 / 112)
|   | |||
| 17 | 17 | * Boston, MA 02111-1307, USA. | |
| 18 | 18 | */ | |
| 19 | 19 | ||
| 20 | /* gdkgeometry-x11.c: emulation of 32 bit coordinates within the | ||
| 21 | * limits of X. | ||
| 22 | * | ||
| 23 | * By Owen Taylor <otaylor@redhat.com> | ||
| 24 | * Copyright Red Hat, Inc. 2000 | ||
| 25 | * | ||
| 26 | * The algorithms implemented in this file are an extension of the | ||
| 27 | * idea of guffaw scrolling, a technique (and name) taken from the classic | ||
| 28 | * Netscape source code. The basic idea of guffaw scrolling is a trick | ||
| 29 | * to get around a limitation of X: there is no way of scrolling the | ||
| 30 | * contents of a window. Guffaw scrolling exploits the X concepts of | ||
| 31 | * window gravity and bit gravity: | ||
| 32 | * | ||
| 33 | * window gravity: the window gravity of a window affects what happens | ||
| 34 | * to a windows position when _its parent_ is resized, or | ||
| 35 | * moved and resized simultaneously. | ||
| 36 | * | ||
| 37 | * bit gravity: the bit gravity of a window affects what happens to | ||
| 38 | * the pixels of a window when _it_ is is resized, or moved and | ||
| 39 | * resized simultaneously. | ||
| 40 | * | ||
| 41 | * These were basically intended to do things like have right | ||
| 42 | * justified widgets in a window automatically stay right justified | ||
| 43 | * when the window was resized, but there is also the special | ||
| 44 | * "StaticGravity" which means "do nothing." We can exploit | ||
| 45 | * StaticGravity to scroll a window: | ||
| 46 | * | ||
| 47 | * | VISIBLE | | ||
| 48 | * | ||
| 49 | * |abcdefghijk| | ||
| 50 | * |abcdefghijk | (1) Resize bigger | ||
| 51 | * | efghijk | (2) Move | ||
| 52 | * |efghijk | (3) Move-resize back to the original size | ||
| 53 | * | ||
| 54 | * Or, going the other way: | ||
| 55 | |||
| 56 | * |abcdefghijk| | ||
| 57 | * | abcdefghijk| (1) Move-resize bigger | ||
| 58 | * | abcdefghijk| (2) Move | ||
| 59 | * | abcdefg| (4) Resize back to the original size | ||
| 60 | * | ||
| 61 | * By using this technique, we can simulate scrolling around in a | ||
| 62 | * large virtual space without having to actually have windows that | ||
| 63 | * big; for the pixels of the window, this is all we have to do. For | ||
| 64 | * subwindows, we have to take care of one other detail - since | ||
| 65 | * coordinates in X are limited to 16 bits, subwindows scrolled off | ||
| 66 | * will wrap around and come back eventually. So, we have to take care | ||
| 67 | * to unmap windows that go outside the 16-bit range and remap them as | ||
| 68 | * they come back in. | ||
| 69 | * | ||
| 70 | * Since we are temporarily making the window bigger, this only looks | ||
| 71 | * good if the edges of the window are obscured. Typically, we do | ||
| 72 | * this by making the window we are scrolling the immediate child | ||
| 73 | * of a "clip window". | ||
| 74 | * | ||
| 75 | * But, this isn't a perfect API for applications for several reasons: | ||
| 76 | * | ||
| 77 | * - We have to use this inefficient technique even for small windows | ||
| 78 | * if the window _could_ be big. | ||
| 79 | * - Applications have to use a special scrolling API. | ||
| 80 | * | ||
| 81 | * What we'd like is to simply have windows with 32 bit coordinates | ||
| 82 | * so applications could scroll in the classic way - just move a big | ||
| 83 | * window around. | ||
| 84 | * | ||
| 85 | * It turns out that StaticGravity can also be used to achieve emulation | ||
| 86 | * of 32 bit coordinates with only 16 bit coordinates if we expand | ||
| 87 | * our horizons just a bit; what guffaw scrolling really is is a way | ||
| 88 | * to move the contents of a window a different amount than we move | ||
| 89 | * the borders of of the window. In the above example pictures we | ||
| 90 | * ended up with the borders of the window not moving at all, but | ||
| 91 | * that isn't necessary. | ||
| 92 | * | ||
| 93 | * So, what we do is set up a mapping from virtual 32 bit window position/size | ||
| 94 | * to: | ||
| 95 | * | ||
| 96 | * - Real window position/size | ||
| 97 | * - Offset between virtual coordinates and real coordinates for the window | ||
| 98 | * - Map state (mapped or unmapped) | ||
| 99 | * | ||
| 100 | * By the following rules: | ||
| 101 | * | ||
| 102 | * - If the window is less than 32767 pixels in width (resp. height), we use it's | ||
| 103 | * virtual width and position. | ||
| 104 | * - Otherwise, we use a width of 32767 and determine the position of the window | ||
| 105 | * so that the portion of the real window [16384, 16383] in _toplevel window | ||
| 106 | * coordinates_ is the same as the portion of the real window | ||
| 107 | * | ||
| 108 | * This is implemented in gdk_window_compute_position(). Then the algorithm | ||
| 109 | * for a moving a window (_window_move_resize_child ()) is: | ||
| 110 | * | ||
| 111 | * - Compute the new window mappings for the window and all subwindows | ||
| 112 | * - Expand out the boundary of the window and all subwindows by the amount | ||
| 113 | * that the real/virtual offset changes for each window. | ||
| 114 | * (compute_intermediate_position() computes expanded boundary) | ||
| 115 | * - Move the toplevel by the amount that it's contents need to translate. | ||
| 116 | * - Move/resize the window and all subwindows to the newly computed | ||
| 117 | * positions. | ||
| 118 | * | ||
| 119 | * If we just are scrolling (gdk_window_guffaw_scroll()), then things | ||
| 120 | * are similar, except that the final mappings for the toplevel are | ||
| 121 | * the same as the initial mappings, but we act as if it moved by the | ||
| 122 | * amount we are scrolling by. | ||
| 123 | * | ||
| 124 | * Note that we don't have to worry about a clip window in | ||
| 125 | * _gdk_window_move_resize() since we have set up our translation so | ||
| 126 | * that things in the range [16384,16383] in toplevel window | ||
| 127 | * coordinates look exactly as they would if we were simply moving the | ||
| 128 | * windows, and nothing outside this range is going to be visible | ||
| 129 | * unless the user has a _really_ huge screen. | ||
| 130 | */ | ||
| 131 | |||
| 132 | 20 | #include "config.h" | |
| 133 | 21 | #include "gdk.h" /* For gdk_rectangle_intersect */ | |
| 134 | 22 | #include "gdkprivate-x11.h" |

