]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/services/gfx/mw/v2_0/src/mwin/winexpos.c
Initial revision
[karo-tx-redboot.git] / packages / services / gfx / mw / v2_0 / src / mwin / winexpos.c
1 /*
2  * Copyright (c) 1999 Greg Haerr <greg@censoft.com>
3  * Portions Copyright (c) 1991 David I. Bell
4  *
5  * Non-Win32 API helper routines for window showing/hiding/exposing
6  */
7 #include "windows.h"
8 #include "wintern.h"
9 #include <stdlib.h>
10
11 /* Redraw all windows*/
12 void
13 MwRedrawScreen(void)
14 {
15         /* redraw all windows except desktop window*/
16         MwExposeArea(rootwp, 0, 0, rootwp->winrect.right,
17                 rootwp->winrect.bottom);
18
19         /* redraw desktop window*/
20         PostMessage(rootwp, WM_PAINT, 0, 0L);
21 }
22
23 /*
24  * Hide the window to make it and its children invisible on the screen.
25  * This is a recursive routine which increments the unmapcount values for
26  * this window and all of its children, and causes exposure events for
27  * windows which are newly uncovered.
28  */
29 void
30 MwHideWindow(HWND hwnd,BOOL bChangeFocus, BOOL bSendMsg)
31 {
32         HWND    wp = hwnd;
33         HWND    pwp;            /* parent window */
34         HWND    sibwp;          /* sibling window */
35         HWND    childwp;        /* child window */
36
37         if (wp == rootwp)
38                 return;
39
40         ++mwpaintNC;            /* experimental NC paint handling*/
41
42         /* send hide message if currently visible*/
43         if(bSendMsg && wp->unmapcount == 0)
44                 SendMessage(wp, WM_SHOWWINDOW, FALSE, 0L);
45
46         wp->unmapcount++;
47
48         for (childwp = wp->children; childwp; childwp = childwp->siblings)
49                 MwHideWindow(childwp, bChangeFocus, bSendMsg);
50
51         if (wp == mousewp) {
52                 MwCheckMouseWindow();
53                 MwCheckCursor();
54         }
55
56         if (bChangeFocus && wp == focuswp)
57                 SetFocus(rootwp->children? rootwp->children: rootwp);
58
59         /*
60          * If the parent window is still unmapped, then we are all done.
61          */
62         if (wp->parent->unmapcount)
63                 return;
64
65         /*
66          * Clear the area in the parent for this window, causing an
67          * exposure event for it.
68          */
69         pwp = wp->parent;
70         MwClearWindow(pwp, wp->winrect.left - pwp->winrect.left,
71                 wp->winrect.top - pwp->winrect.top,
72                 wp->winrect.right - wp->winrect.left,
73                 wp->winrect.bottom - wp->winrect.top, TRUE);
74
75         /*
76          * Finally clear and redraw all parts of our lower sibling
77          * windows that were covered by this window.
78          */
79         sibwp = wp;
80         while (sibwp->siblings) {
81                 sibwp = sibwp->siblings;
82                 MwExposeArea(sibwp, wp->winrect.left, wp->winrect.top,
83                         wp->winrect.right - wp->winrect.left,
84                         wp->winrect.bottom - wp->winrect.top);
85         }
86 }
87
88 /*
89  * Map the window to possibly make it and its children visible on the screen.
90  * This is a recursive routine which decrements the unmapcount values for
91  * this window and all of its children, and causes exposure events for
92  * those windows which become visible.
93  */
94 void
95 MwShowWindow(HWND hwnd, BOOL bSendMsg)
96 {
97         HWND    wp = hwnd;
98
99         if (wp == rootwp)
100                 return;
101
102         ++mwpaintNC;            /* experimental NC paint handling*/
103
104         if (wp->unmapcount)
105                 wp->unmapcount--;
106
107         if (wp->unmapcount == 0) {
108                 SendMessage(wp, WM_SHOWWINDOW, TRUE, 0L);
109                 MwCheckMouseWindow();
110                 MwCheckCursor();
111         }
112
113         /*
114          * If the window just became visible,
115          * then draw its border, clear it to the background color, and
116          * generate an exposure event.
117          */
118         if (wp->unmapcount == 0) {
119                 /*MwDrawBorder(wp);*/
120                 MwClearWindow(wp, 0, 0, wp->winrect.right - wp->winrect.left,
121                         wp->winrect.bottom - wp->winrect.top, TRUE);
122         }
123
124         /*
125          * Do the same thing for the children.
126          */
127         for (wp = wp->children; wp; wp = wp->siblings)
128                 MwShowWindow(wp, bSendMsg);
129 }
130
131 /*
132  * Raise a window to the highest level among its siblings.
133  */
134 void
135 MwRaiseWindow(HWND hwnd)
136 {
137         HWND    wp = hwnd;
138         HWND    prevwp;
139         BOOL    overlap;
140
141         if (!wp || wp == rootwp)
142                 return;
143
144         ++mwpaintNC;            /* experimental NC paint handling*/
145
146         /*
147          * If this is already the highest window then we are done.
148          */
149         prevwp = wp->parent->children;
150         if (prevwp == wp)
151                 return;
152
153         /*
154          * Find the sibling just before this window so we can unlink it.
155          * Also, determine if any sibling ahead of us overlaps the window.
156          * Remember that for exposure events.
157          */
158         overlap = FALSE;
159         while (prevwp->siblings != wp) {
160                 overlap |= MwCheckOverlap(prevwp, wp);
161                 prevwp = prevwp->siblings;
162         }
163         overlap |= MwCheckOverlap(prevwp, wp);
164
165         /*
166          * Now unlink the window and relink it in at the front of the
167          * sibling chain.
168          */
169         prevwp->siblings = wp->siblings;
170         wp->siblings = wp->parent->children;
171         wp->parent->children = wp;
172
173         /*
174          * Finally redraw the window if necessary.
175          */
176         if (overlap) {
177                 /*MwDrawBorder(wp);*/
178                 MwExposeArea(wp, wp->winrect.left, wp->winrect.top,
179                         wp->winrect.right - wp->winrect.left,
180                         wp->winrect.bottom - wp->winrect.top);
181         }
182 }
183
184 /*
185  * Lower a window to the lowest level among its siblings.
186  */
187 void
188 MwLowerWindow(HWND hwnd)
189 {
190         HWND    wp = hwnd;
191         HWND    prevwp;
192         HWND    sibwp;          /* sibling window */
193         HWND    expwp;          /* siblings being exposed */
194
195         if (!wp || wp == rootwp || !wp->siblings)
196                 return;
197
198         ++mwpaintNC;            /* experimental NC paint handling*/
199
200         /*
201          * Find the sibling just before this window so we can unlink us.
202          */
203         prevwp = wp->parent->children;
204         if (prevwp != wp) {
205                 while (prevwp->siblings != wp)
206                         prevwp = prevwp->siblings;
207         }
208
209         /*
210          * Remember the first sibling that is after us, so we can
211          * generate exposure events for the remaining siblings.  Then
212          * walk down the sibling chain looking for the last sibling.
213          */
214         expwp = wp->siblings;
215         sibwp = wp;
216         while (sibwp->siblings)
217                 sibwp = sibwp->siblings;
218
219         /*
220          * Now unlink the window and relink it in at the end of the
221          * sibling chain.
222          */
223         if (prevwp == wp)
224                 wp->parent->children = wp->siblings;
225         else
226                 prevwp->siblings = wp->siblings;
227         sibwp->siblings = wp;
228
229         wp->siblings = NULL;
230
231         /*
232          * Finally redraw the sibling windows which this window covered
233          * if they overlapped our window.
234          */
235         while (expwp && (expwp != wp)) {
236                 if (MwCheckOverlap(wp, expwp))
237                         MwExposeArea(expwp, wp->winrect.left, wp->winrect.top,
238                                 wp->winrect.right - wp->winrect.left,
239                                 wp->winrect.bottom - wp->winrect.top);
240                 expwp = expwp->siblings;
241         }
242 }
243
244 /*
245  * Check to see if the first window overlaps the second window.
246  */
247 BOOL
248 MwCheckOverlap(HWND topwp, HWND botwp)
249 {
250         MWCOORD minx1;
251         MWCOORD miny1;
252         MWCOORD maxx1;
253         MWCOORD maxy1;
254         MWCOORD minx2;
255         MWCOORD miny2;
256         MWCOORD maxx2;
257         MWCOORD maxy2;
258
259         if (topwp->unmapcount || botwp->unmapcount)
260                 return FALSE;
261
262         minx1 = topwp->winrect.left;
263         miny1 = topwp->winrect.top;
264         maxx1 = topwp->winrect.right - 1;
265         maxy1 = topwp->winrect.bottom - 1;
266
267         minx2 = botwp->winrect.left;
268         miny2 = botwp->winrect.top;
269         maxx2 = botwp->winrect.right - 1;
270         maxy2 = botwp->winrect.bottom - 1;
271
272         if (minx1 > maxx2 || minx2 > maxx1 || miny1 > maxy2 || miny2 > maxy1)
273                 return FALSE;
274
275         return TRUE;
276 }
277
278 /*
279  * Clear the specified area of a window and possibly make an exposure event.
280  * This sets the area window to its background color.  If the exposeflag is
281  * nonzero, then this also creates an exposure event for the window.
282  */
283 void
284 MwClearWindow(HWND wp, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
285         BOOL exposeflag)
286 {
287         if (wp->unmapcount)
288                 return;
289
290         /*
291          * Reduce the arguments so that they actually lie within the window.
292          */
293         if (x < 0) {
294                 width += x;
295                 x = 0;
296         }
297         if (y < 0) {
298                 height += y;
299                 y = 0;
300         }
301         if (x + width > wp->winrect.right - wp->winrect.left)
302                 width = (wp->winrect.right - wp->winrect.left) - x;
303         if (y + height > wp->winrect.bottom - wp->winrect.top)
304                 height = (wp->winrect.bottom - wp->winrect.top) - y;
305
306         /*
307          * Now see if the region is really in the window.  If not, then
308          * do nothing.
309          */
310         if (x >= (wp->winrect.right - wp->winrect.left) ||
311             y >= (wp->winrect.bottom - wp->winrect.top) ||
312             width <= 0 || height <= 0)
313                 return;
314
315         /*
316          * Now do the exposure if required.
317          */
318         if (exposeflag)
319                 MwDeliverExposureEvent(wp, x, y, width, height);
320 }
321
322 /*
323  * Handle the exposing of the specified absolute region of the screen,
324  * starting with the specified window.  That window and all of its
325  * children will be redrawn and/or exposure events generated if they
326  * overlap the specified area.  This is a recursive routine.
327  */
328 void
329 MwExposeArea(HWND wp, MWCOORD rootx, MWCOORD rooty, MWCOORD width,
330         MWCOORD height)
331 {
332         if (wp->unmapcount)
333                 return;
334
335         ++mwpaintNC;            /* experimental NC paint handling*/
336
337         /*
338          * First see if the area overlaps the window including the border.
339          * If not, then there is nothing more to do.
340          */
341         if (rootx >= wp->winrect.right || rooty >= wp->winrect.bottom ||
342             (rootx + width) <= wp->winrect.left ||
343             (rooty + height) <= wp->winrect.top)
344                 return;
345
346 #if 0
347         /*
348          * The area does overlap the window.  See if the area overlaps
349          * the border, and if so, then redraw it.
350          */
351         if (rootx < wp->winrect.left || rooty < wp->winrect.top ||
352                 (rootx + width) > wp->winrect.right ||
353                 (rooty + height) > wp->winrect.bottom)
354                         MwDrawBorder(wp);
355 #endif
356
357         /*
358          * Now clear the window itself in the specified area,
359          * which might cause an exposure event.
360          */
361         MwClearWindow(wp, rootx - wp->winrect.left, rooty - wp->winrect.top,
362                 width, height, TRUE);
363
364         /*
365          * Now do the same for all the children.
366          */
367         for (wp = wp->children; wp; wp = wp->siblings)
368                 MwExposeArea(wp, rootx, rooty, width, height);
369 }