OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [nanox/] [srvutil.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
/*
2
 * Copyright (c) 2000 Greg Haerr <greg@censoft.com>
3
 * Copyright (c) 1991 David I. Bell
4
 * Permission is granted to use, distribute, or modify this source,
5
 * provided that this copyright notice remains intact.
6
 *
7
 * Graphics server utility routines for windows.
8
 */
9
#include <stdio.h>
10
#include <stdlib.h>
11
 
12
#ifndef __PACIFIC__
13
#include <fcntl.h>
14
#endif
15
 
16
#include "serv.h"
17
 
18
/*
19
 * Help prevent future bugs by defining this variable to an illegal value.
20
 * These routines should not be referencing this, but should be using
21
 * unmapcount instead.
22
 */
23
#define mapped  cannotusemapped
24
 
25
/*
26
 * Redraw the screen completely.
27
 */
28
void
29
GsRedrawScreen(void)
30
{
31
        /* Redraw all windows*/
32
        GsExposeArea(rootwp, 0, 0, rootwp->width, rootwp->height, NULL);
33
}
34
 
35
/*
36
 * Activate Screen Saver.
37
 */
38
void
39
GsActivateScreenSaver(void *arg)
40
{
41
        screensaver_active = GR_TRUE;
42
        GsDeliverScreenSaverEvent(GR_TRUE);
43
}
44
 
45
/*
46
 * Deactivate screen saver and reset timer if active.
47
 */
48
void
49
GsResetScreenSaver(void)
50
{
51
        MWTIMER *timer;
52
 
53
        if(screensaver_active == GR_TRUE) {
54
                screensaver_active = GR_FALSE;
55
                GsDeliverScreenSaverEvent(GR_FALSE);
56
        }
57
        if(screensaver_delay) {
58
                if((timer = GdFindTimer(GsActivateScreenSaver)))
59
                        GdDestroyTimer(timer);
60
                GdAddTimer(screensaver_delay, GsActivateScreenSaver,
61
                        GsActivateScreenSaver);
62
        }
63
}
64
 
65
void
66
GsTimerCB (void *arg)
67
{
68
    GR_TIMER *timer = (GR_TIMER*) arg;
69
 
70
    GsDeliverTimerEvent (timer->owner, timer->wid, timer->id);
71
}
72
 
73
 
74
/*
75
 * Unmap the window to make it and its children invisible on the screen.
76
 * This is a recursive routine which increments the unmapcount values for
77
 * this window and all of its children, and causes exposure events for
78
 * windows which are newly uncovered.
79
 * If temp_unmap set, don't reset focus or generate mouse/focus events,
80
 * as window will be mapped again momentarily (window move, resize, etc)
81
 */
82
void GsWpUnmapWindow(GR_WINDOW *wp, GR_BOOL temp_unmap)
83
{
84
        GR_WINDOW       *pwp;           /* parent window */
85
        GR_WINDOW       *sibwp;         /* sibling window */
86
        GR_WINDOW       *childwp;       /* child window */
87
        GR_SIZE         bs;             /* border size of this window */
88
 
89
        if (wp == rootwp) {
90
                GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
91
                return;
92
        }
93
 
94
        if (wp == clipwp)
95
                clipwp = NULL;
96
 
97
        ++wp->unmapcount;
98
 
99
        for (childwp = wp->children; childwp; childwp = childwp->siblings)
100
                GsWpUnmapWindow(childwp, temp_unmap);
101
 
102
        if (!temp_unmap && wp == mousewp) {
103
                GsCheckMouseWindow();
104
                GsCheckCursor();
105
        }
106
 
107
        if (!temp_unmap && wp == focuswp) {
108
                if (focusfixed)
109
                        /* don't revert to mouse enter/leave focus if fixed*/
110
                        focuswp = rootwp;
111
                else {
112
                        focusfixed = GR_FALSE;
113
                        GsCheckFocusWindow();
114
                }
115
        }
116
 
117
        /* Send update event if just unmapped*/
118
        if (wp->unmapcount == 1) {
119
                GsDeliverUpdateEvent(wp,
120
                        (temp_unmap? GR_UPDATE_UNMAPTEMP: GR_UPDATE_UNMAP),
121
                        0, 0, 0, 0);
122
        }
123
 
124
        /*
125
         * If this is an input-only window or the parent window is
126
         * still unmapped, then we are all done.
127
         */
128
        if (!wp->output || wp->parent->unmapcount)
129
                return;
130
 
131
        /*
132
         * Clear the area in the parent for this window, causing an
133
         * exposure event for it.  Take into account the border size.
134
         */
135
        bs = wp->bordersize;
136
        pwp = wp->parent;
137
        GsWpClearWindow(pwp, wp->x - pwp->x - bs, wp->y - pwp->y - bs,
138
                wp->width + bs * 2, wp->height + bs * 2, GR_TRUE);
139
 
140
        /*
141
         * Finally clear and redraw all parts of our lower sibling
142
         * windows that were covered by this window.
143
         */
144
        sibwp = wp;
145
        while (sibwp->siblings) {
146
                sibwp = sibwp->siblings;
147
                GsExposeArea(sibwp, wp->x - bs, wp->y - bs,
148
                        wp->width + bs * 2, wp->height + bs * 2, NULL);
149
        }
150
}
151
 
152
/*
153
 * Map the window to possibly make it and its children visible on the screen.
154
 * This is a recursive routine which decrements the unmapcount values for
155
 * this window and all of its children, and causes exposure events for
156
 * those windows which become visible.
157
 * If temp is set, then window is being mapped again after a temporary
158
 * unmap, so don't reset focus or generate mouse/focus events.
159
 */
160
void GsWpMapWindow(GR_WINDOW *wp, GR_BOOL temp)
161
{
162
        if (wp == rootwp) {
163
                GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
164
                return;
165
        }
166
 
167
        if (wp->unmapcount)
168
                --wp->unmapcount;
169
 
170
        if (!temp && wp->unmapcount == 0) {
171
                GsCheckMouseWindow();
172
                GsCheckFocusWindow();
173
                GsCheckCursor();
174
        }
175
 
176
        /* send update event if just mapped*/
177
        if (wp->unmapcount == 0) {
178
                GsDeliverUpdateEvent(wp, GR_UPDATE_MAP, wp->x, wp->y,
179
                        wp->width, wp->height);
180
        }
181
 
182
        /*
183
         * If the window is an output window and just became visible,
184
         * then draw its border, clear it to the background color, and
185
         * generate an exposure event.
186
         */
187
        if (wp->output && (wp->unmapcount == 0)) {
188
                GsDrawBorder(wp);
189
                GsWpClearWindow(wp, 0, 0, wp->width, wp->height, GR_TRUE);
190
        }
191
 
192
        /*
193
         * Do the same thing for the children.
194
         */
195
        for (wp = wp->children; wp; wp = wp->siblings)
196
                GsWpMapWindow(wp, temp);
197
}
198
 
199
/*
200
 * Destroy the specified window, and all of its children.
201
 * This is a recursive routine.
202
 */
203
void GsWpDestroyWindow(GR_WINDOW *wp)
204
{
205
        GR_WINDOW       *prevwp;        /* previous window pointer */
206
        GR_EVENT_CLIENT *ecp;           /* selections for window */
207
        GR_WINDOW_ID    oldwid;         /* old selection owner */
208
 
209
        if (wp == rootwp) {
210
                GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
211
                return;
212
        }
213
 
214
        /* Disable selection if this window is the owner */
215
        if(selection_owner.wid == wp->id) {
216
                oldwid = selection_owner.wid;
217
                selection_owner.wid = 0;
218
                if(selection_owner.typelist) free(selection_owner.typelist);
219
                GsDeliverSelectionChangedEvent(oldwid, 0);
220
        }
221
 
222
        /*
223
         * Unmap the window first.
224
         */
225
        if (wp->unmapcount == 0)
226
                GsWpUnmapWindow(wp, GR_FALSE);
227
 
228
        /* send update event*/
229
        GsDeliverUpdateEvent(wp, GR_UPDATE_DESTROY, wp->x, wp->y,
230
                wp->width, wp->height);
231
 
232
        /*
233
         * Destroy all children.
234
         */
235
        while (wp->children)
236
                GsWpDestroyWindow(wp->children);
237
 
238
        /*
239
         * Free all client selection structures.
240
         */
241
        while (wp->eventclients) {
242
                ecp = wp->eventclients;
243
                wp->eventclients = ecp->next;
244
                free(ecp);
245
        }
246
 
247
        /*
248
         * Remove this window from the child list of its parent.
249
         */
250
        prevwp = wp->parent->children;
251
        if (prevwp == wp)
252
                wp->parent->children = wp->siblings;
253
        else {
254
                while (prevwp->siblings != wp)
255
                        prevwp = prevwp->siblings;
256
                prevwp->siblings = wp->siblings;
257
        }
258
        wp->siblings = NULL;
259
 
260
        /*
261
         * Remove this window from the complete list of windows.
262
         */
263
        prevwp = listwp;
264
        if (prevwp == wp)
265
                listwp = wp->next;
266
        else {
267
                while (prevwp->next != wp)
268
                        prevwp = prevwp->next;
269
                prevwp->next = wp->next;
270
        }
271
        wp->next = NULL;
272
 
273
        /*
274
         * Forget various information if they related to this window.
275
         * Then finally free the structure.
276
         */
277
        if (wp == clipwp)
278
                clipwp = NULL;
279
        if (wp == grabbuttonwp)
280
                grabbuttonwp = NULL;
281
        if (wp == cachewp) {
282
                cachewindowid = 0;
283
                cachewp = NULL;
284
        }
285
        if (wp == focuswp) {
286
                /* don't revert to mouse enter/leave focus if fixed*/
287
                /*focusfixed = GR_FALSE;*/
288
                focuswp = rootwp;
289
        }
290
 
291
        GsCheckMouseWindow();
292
 
293
        if(wp->title)
294
                free(wp->title);
295
 
296
        free(wp);
297
}
298
 
299
/*
300
 * Draw a window's background pixmap.
301
 *
302
 * The flags mean:
303
 *   GR_BACKGROUND_TILE- tile the pixmap across the window (default).
304
 *   GR_BACKGROUND_TOPLEFT- draw the pixmap at (0,0) relative to the window.
305
 *   GR_BACKGROUND_CENTER- draw the pixmap in the middle of the window.
306
 *   GR_BACKGROUND_STRETCH- stretch the pixmap within the window.
307
 *   GR_BACKGROUND_TRANS- if the pixmap is smaller than the window and not
308
 *     using tile mode, there will be gaps around the pixmap. This flag causes
309
 *     to not fill in the spaces with the background colour.
310
 */
311
void GsWpDrawBackgroundPixmap(GR_WINDOW *wp, GR_PIXMAP *pm, GR_COORD x,
312
        GR_COORD y, GR_SIZE width, GR_SIZE height)
313
{
314
        GR_SIZE destwidth, destheight, fillwidth, fillheight, pmwidth, pmheight;
315
        GR_COORD fromx, fromy, destx, desty, pixmapx = 0, pixmapy = 0;
316
 
317
        if(wp->bgpixmapflags & (GR_BACKGROUND_TOPLEFT|GR_BACKGROUND_STRETCH)) {
318
                pixmapx = 0;
319
                pixmapy = 0;
320
        } else if(wp->bgpixmapflags & GR_BACKGROUND_CENTER) {
321
                if(pm->width >= wp->width) pixmapx = 0;
322
                else pixmapx = (wp->width - pm->width) / 2;
323
                if(pm->height >= wp->height) pixmapy = 0;
324
                else pixmapy = (wp->height - pm->height) / 2;
325
        } else {
326
                /* GR_BACKGROUND_TILE (default)*/
327
                GsWpTileBackgroundPixmap(wp, pm, x, y, width, height);
328
                return;
329
        }
330
 
331
        if(pm->width > wp->width) pmwidth = wp->width;
332
        else pmwidth = pm->width;
333
        if(pm->height > wp->height) pmheight = wp->height;
334
        else pmheight = pm->height;
335
 
336
        if(x > pixmapx) {
337
                destx = x;
338
                fromx = x - pixmapx;
339
                destwidth = pixmapx + pmwidth - x;
340
        } else {
341
                destx = pixmapx;
342
                fromx = 0;
343
                destwidth = x + width - pixmapx;
344
        }
345
 
346
        if(y > pixmapy) {
347
                desty = y;
348
                fromy = y - pixmapy;
349
                destheight = pixmapy + pmheight - desty;
350
        } else {
351
                desty = pixmapy;
352
                fromy = 0;
353
                destheight = y + height - pixmapy;
354
        }
355
 
356
        if(destwidth > 0 && destheight > 0) {
357
                if (wp->bgpixmapflags & GR_BACKGROUND_STRETCH) {
358
                        GdStretchBlit(wp->psd, destx + wp->x, desty + wp->y,
359
                                destwidth, destheight, pm->psd, fromx, fromy,
360
                                pm->width, pm->height, MWROP_COPY);
361
                } else GdBlit(wp->psd, destx + wp->x, desty + wp->y, destwidth,
362
                        destheight, pm->psd, fromx, fromy, MWROP_COPY);
363
        }
364
 
365
        if(wp->bgpixmapflags & (GR_BACKGROUND_TRANS|GR_BACKGROUND_STRETCH))
366
                return;
367
 
368
        /* Fill in the gaps around the pixmap */
369
        if(x < pixmapx) {
370
                fillwidth = pixmapx - x;
371
                if(fillwidth > width) fillwidth = width;
372
                fillheight = height;
373
                GdFillRect(wp->psd, wp->x + x, wp->y + y, fillwidth,fillheight);
374
        }
375
        if((x + width) > (pixmapx + pmwidth)) {
376
                fillwidth = (x + width) - (pixmapx + pmwidth);
377
                if(fillwidth > width) fillwidth = width;
378
                fillheight = height;
379
                if(x < (pixmapx + pmwidth)) destx = pixmapx + pmwidth + wp->x;
380
                else destx = x + wp->x;
381
                GdFillRect(wp->psd, destx, wp->y + y, fillwidth, fillheight);
382
        }
383
        if(y < pixmapy) {
384
                fillheight = pixmapy - y;
385
                if(fillheight > height) fillheight = height;
386
                if(x < pixmapx) destx = pixmapx + wp->x;
387
                else destx = x + wp->x;
388
                if((x + width) > (pixmapx + pmwidth))
389
                        fillwidth = pixmapx + pmwidth - destx;
390
                else fillwidth = x + width - destx;
391
                if((fillwidth > 0) && (fillheight > 0)) {
392
                        GdFillRect(wp->psd, destx, wp->y + y, fillwidth,
393
                                                        fillheight);
394
                }
395
        }
396
        if((y + height) > (pixmapy + pmheight)) {
397
                fillheight = (y + height) - (pixmapy + pmheight);
398
                if(fillheight > height) fillheight = height;
399
                if(x < pixmapx) destx = pixmapx + wp->x;
400
                else destx = x + wp->x;
401
                if(y < (pixmapy + pmheight)) desty = pixmapy + pmheight + wp->y;
402
                else desty = y + wp->y;
403
 
404
                if((x + width) > (pixmapx + pmwidth))
405
                        fillwidth = pixmapx + pmwidth - destx;
406
                else fillwidth = x + width - destx;
407
                if((fillwidth > 0) && (fillheight > 0)) {
408
                        GdFillRect(wp->psd, destx, desty, fillwidth,fillheight);
409
                }
410
        }
411
}
412
 
413
/*
414
 * Draw a tiled pixmap window background.
415
 */
416
void
417
GsWpTileBackgroundPixmap(GR_WINDOW *wp, GR_PIXMAP *pm, GR_COORD x, GR_COORD y,
418
        GR_SIZE width, GR_SIZE height)
419
{
420
        GR_COORD tilex = 0, tiley = 0, fromx, fromy, cx, cy;
421
        GR_SIZE destwidth, destheight, pmwidth, pmheight, cwidth, cheight;
422
 
423
        if(pm->width > wp->width) pmwidth = wp->width;
424
        else pmwidth = pm->width;
425
        if(pm->height > wp->height) pmheight = wp->height;
426
        else pmheight = pm->height;
427
 
428
        for(;tiley < wp->height; tiley += pmheight, tilex = 0) {
429
                if(tiley > (y + height)) continue;
430
                if(y > (tiley + pmheight)) continue;
431
                if((tiley + pmheight) > wp->height)
432
                        destheight = wp->height - tiley;
433
                else destheight = pmheight;
434
                for(;tilex < wp->width; tilex += pmwidth) {
435
                        if(tilex > (x + width)) continue;
436
                        if(x > (tilex + pmwidth)) continue;
437
                        if((tilex + pmwidth) > wp->width)
438
                                destwidth = wp->width - tilex;
439
                        else destwidth = pmwidth;
440
 
441
                        if((tilex >= x) && ((tilex + destwidth)<=(x + width))) {
442
                                fromx = 0;
443
                                cx = tilex + wp->x;
444
                                cwidth = destwidth;
445
                        } else {
446
                                if(x > tilex) {
447
                                        fromx = x - tilex;
448
                                        cwidth = destwidth - fromx;
449
                                } else {
450
                                        fromx = 0;
451
                                        cwidth = x + width - tilex;
452
                                }
453
                                if(cwidth > width) cwidth = width;
454
                                if(cwidth > destwidth) cwidth = destwidth;
455
                                cx = wp->x + tilex + fromx;
456
                        }
457
 
458
                        if((tiley >= y)&&((tiley + destheight)<=(y + height))) {
459
                                fromy = 0;
460
                                cy = tiley + wp->y;
461
                                cheight = destheight;
462
                        } else {
463
                                if(y > tiley) {
464
                                        fromy = y - tiley;
465
                                        cheight = destheight - fromy;
466
                                } else {
467
                                        fromy = 0;
468
                                        cheight = y + height - tiley;
469
                                }
470
                                if(cwidth > width) cwidth = width;
471
                                if(cheight > destheight) cheight = destheight;
472
                                cy = wp->y + tiley + fromy;
473
                        }
474
 
475
                        if((cwidth > 0) && (cheight > 0)) {
476
                                GdBlit(wp->psd, cx, cy, cwidth, cheight,
477
                                        pm->psd, fromx, fromy, MWROP_COPY);
478
                        }
479
                }
480
        }
481
}
482
 
483
/*
484
 * Clear the specified area of a window and possibly make an exposure event.
485
 * This sets the area window to its background color or pixmap.  If the
486
 * exposeflag is nonzero, then this also creates an exposure event for the
487
 * window.
488
 */
489
void
490
GsWpClearWindow(GR_WINDOW *wp, GR_COORD x, GR_COORD y, GR_SIZE width,
491
        GR_SIZE  height, GR_BOOL exposeflag)
492
{
493
        if (wp->unmapcount || !wp->output)
494
                return;
495
        /*
496
         * Reduce the arguments so that they actually lie within the window.
497
         */
498
        if (x < 0) {
499
                width += x;
500
                x = 0;
501
        }
502
        if (y < 0) {
503
                height += y;
504
                y = 0;
505
        }
506
        if (x + width > wp->width)
507
                width = wp->width - x;
508
        if (y + height > wp->height)
509
                height = wp->height - y;
510
 
511
        /*
512
         * Now see if the region is really in the window.  If not, then
513
         * do nothing.
514
         */
515
        if ((x >= wp->width) || (y >= wp->height) || (width <= 0) ||
516
                (height <= 0))
517
                        return;
518
 
519
        /*
520
         * Draw the background of the window.
521
         * Invalidate the current graphics context since
522
         * we are changing the foreground color and mode.
523
         */
524
        GsSetClipWindow(wp, NULL, 0);
525
        curgcp = NULL;
526
        if (!(wp->props & GR_WM_PROPS_NOBACKGROUND)) {
527
                GdSetMode(GR_MODE_COPY);
528
                GdSetForeground(GdFindColor(wp->background));
529
                if (wp->bgpixmap) {
530
                        GsWpDrawBackgroundPixmap(wp, wp->bgpixmap, x, y,
531
                                width, height);
532
                } else {
533
                        GdFillRect(wp->psd, wp->x + x, wp->y + y, width,height);
534
                }
535
        }
536
 
537
        /*
538
         * Now do the exposure if required.
539
         */
540
        if (exposeflag)
541
                GsDeliverExposureEvent(wp, x, y, width, height);
542
}
543
 
544
/*
545
 * Handle the exposing of the specified absolute region of the screen,
546
 * starting with the specified window.  That window and all of its
547
 * children will be redrawn and/or exposure events generated if they
548
 * overlap the specified area.  This is a recursive routine.
549
 */
550
void
551
GsExposeArea(GR_WINDOW *wp, GR_COORD rootx, GR_COORD rooty, GR_SIZE width,
552
        GR_SIZE height, GR_WINDOW *stopwp)
553
{
554
        if (!wp->output || wp->unmapcount || wp == stopwp)
555
                return;
556
 
557
        /*
558
         * First see if the area overlaps the window including the border.
559
         * If not, then there is nothing more to do.
560
         */
561
        if ((rootx >= wp->x + wp->width + wp->bordersize) ||
562
                (rooty >= wp->y + wp->height + wp->bordersize) ||
563
                (rootx + width <= wp->x - wp->bordersize) ||
564
                (rooty + height <= wp->y - wp->bordersize))
565
                        return;
566
 
567
        /*
568
         * The area does overlap the window.  See if the area overlaps
569
         * the border, and if so, then redraw it.
570
         */
571
        if ((rootx < wp->x) || (rooty < wp->y) ||
572
                (rootx + width > wp->x + wp->width) ||
573
                (rooty + height > wp->y + wp->height))
574
                        GsDrawBorder(wp);
575
 
576
        /*
577
         * Now clear the window itself in the specified area,
578
         * which might cause an exposure event.
579
         */
580
        GsWpClearWindow(wp, rootx - wp->x, rooty - wp->y,
581
                width, height, GR_TRUE);
582
 
583
        /*
584
         * Now do the same for all the children.
585
         */
586
        for (wp = wp->children; wp; wp = wp->siblings)
587
                GsExposeArea(wp, rootx, rooty, width, height, stopwp);
588
}
589
 
590
/*
591
 * Draw the border of a window if there is one.
592
 * Note: To allow the border to be drawn with the correct clipping,
593
 * we temporarily grow the size of the window to include the border.
594
 */
595
void GsDrawBorder(GR_WINDOW *wp)
596
{
597
        GR_COORD        lminx;          /* left edge minimum x */
598
        GR_COORD        rminx;          /* right edge minimum x */
599
        GR_COORD        tminy;          /* top edge minimum y */
600
        GR_COORD        bminy;          /* bottom edge minimum y */
601
        GR_COORD        topy;           /* top y value of window */
602
        GR_COORD        boty;           /* bottom y value of window */
603
        GR_SIZE         width;          /* original width of window */
604
        GR_SIZE         height;         /* original height of window */
605
        GR_SIZE         bs;             /* border size */
606
 
607
        bs = wp->bordersize;
608
        if (bs <= 0)
609
                return;
610
 
611
        width = wp->width;
612
        height = wp->height;
613
        lminx = wp->x - bs;
614
        rminx = wp->x + width;
615
        tminy = wp->y - bs;
616
        bminy = wp->y + height;
617
        topy = wp->y;
618
        boty = bminy - 1;
619
 
620
        wp->x -= bs;
621
        wp->y -= bs;
622
        wp->width += (bs * 2);
623
        wp->height += (bs * 2);
624
        wp->bordersize = 0;
625
 
626
        clipwp = NULL;
627
        GsSetClipWindow(wp, NULL, 0);
628
        curgcp = NULL;
629
        GdSetMode(GR_MODE_COPY);
630
        GdSetForeground(GdFindColor(wp->bordercolor));
631
 
632
        if (bs == 1) {
633
                GdLine(wp->psd, lminx, tminy, rminx, tminy, TRUE);
634
                GdLine(wp->psd, lminx, bminy, rminx, bminy, TRUE);
635
                GdLine(wp->psd, lminx, topy, lminx, boty, TRUE);
636
                GdLine(wp->psd, rminx, topy, rminx, boty, TRUE);
637
        } else {
638
                GdFillRect(wp->psd, lminx, tminy, width + bs * 2, bs);
639
                GdFillRect(wp->psd, lminx, bminy, width + bs * 2, bs);
640
                GdFillRect(wp->psd, lminx, topy, bs, height);
641
                GdFillRect(wp->psd, rminx, topy, bs, height);
642
        }
643
 
644
        /*
645
         * Restore the true window size.
646
         * Forget the currently clipped window since we messed it up.
647
         */
648
        wp->x += bs;
649
        wp->y += bs;
650
        wp->width -= (bs * 2);
651
        wp->height -= (bs * 2);
652
        wp->bordersize = bs;
653
        clipwp = NULL;
654
}
655
 
656
/*
657
 * Check to see if the first window overlaps the second window.
658
 */
659
GR_BOOL GsCheckOverlap(GR_WINDOW *topwp, GR_WINDOW *botwp)
660
{
661
        GR_COORD        minx1;
662
        GR_COORD        miny1;
663
        GR_COORD        maxx1;
664
        GR_COORD        maxy1;
665
        GR_COORD        minx2;
666
        GR_COORD        miny2;
667
        GR_COORD        maxx2;
668
        GR_COORD        maxy2;
669
        GR_SIZE         bs;
670
 
671
        if (!topwp->output || topwp->unmapcount || botwp->unmapcount)
672
                return GR_FALSE;
673
 
674
        bs = topwp->bordersize;
675
        minx1 = topwp->x - bs;
676
        miny1 = topwp->y - bs;
677
        maxx1 = topwp->x + topwp->width + bs - 1;
678
        maxy1 = topwp->y + topwp->height + bs - 1;
679
 
680
        bs = botwp->bordersize;
681
        minx2 = botwp->x - bs;
682
        miny2 = botwp->y - bs;
683
        maxx2 = botwp->x + botwp->width + bs - 1;
684
        maxy2 = botwp->y + botwp->height + bs - 1;
685
 
686
        if ((minx1 > maxx2) || (minx2 > maxx1) || (miny1 > maxy2)
687
                || (miny2 > maxy1))
688
                        return GR_FALSE;
689
 
690
        return GR_TRUE;
691
}
692
 
693
/*
694
 * Return a pointer to the window structure with the specified window id.
695
 * Returns NULL if the window does not exist.
696
 */
697
GR_WINDOW *
698
GsFindWindow(GR_WINDOW_ID id)
699
{
700
        GR_WINDOW       *wp;            /* current window pointer */
701
 
702
        /*
703
         * See if this is the root window or the same window as last time.
704
         */
705
        if (id == GR_ROOT_WINDOW_ID)
706
                return rootwp;
707
 
708
        if ((id == cachewindowid) && id)
709
                return cachewp;
710
 
711
        /*
712
         * No, search for it and cache it for future calls.
713
         */
714
        for (wp = listwp; wp; wp = wp->next) {
715
                if (wp->id == id) {
716
                        cachewindowid = id;
717
                        cachewp = wp;
718
                        return wp;
719
                }
720
        }
721
 
722
        return NULL;
723
}
724
 
725
 
726
 
727
/*
728
 * Return a pointer to the pixmap structure with the specified window id.
729
 * Returns NULL if the pixmap does not exist.
730
 */
731
GR_PIXMAP *
732
GsFindPixmap(GR_WINDOW_ID id)
733
{
734
        GR_PIXMAP       *pp;            /* current pixmap pointer */
735
 
736
        if ((id == cachepixmapid) && id)
737
                return cachepp;
738
 
739
        /*
740
         * No, search for it and cache it for future calls.
741
         */
742
        for (pp = listpp; pp; pp = pp->next) {
743
                if (pp->id == id) {
744
                        cachepixmapid = id;
745
                        cachepp = pp;
746
                        return pp;
747
                }
748
        }
749
 
750
        return NULL;
751
}
752
 
753
 
754
/*
755
 * Return a pointer to the graphics context with the specified id.
756
 * Returns NULL if the graphics context does not exist, with an
757
 * error saved.
758
 */
759
GR_GC *
760
GsFindGC(GR_GC_ID gcid)
761
{
762
        GR_GC           *gcp;           /* current graphics context pointer */
763
 
764
        /*
765
         * See if this is the same graphics context as last time.
766
         */
767
        if ((gcid == cachegcid) && gcid)
768
                return cachegcp;
769
 
770
        /*
771
         * No, search for it and cache it for future calls.
772
         */
773
        for (gcp = listgcp; gcp; gcp = gcp->next) {
774
                if (gcp->id == gcid) {
775
                        cachegcid = gcid;
776
                        cachegcp = gcp;
777
                        return gcp;
778
                }
779
        }
780
 
781
        GsError(GR_ERROR_BAD_GC_ID, gcid);
782
 
783
        return NULL;
784
}
785
 
786
/* Return a pointer to the region with the specified id.*/
787
GR_REGION *
788
GsFindRegion(GR_REGION_ID regionid)
789
{
790
        GR_REGION       *regionp;       /* current region pointer */
791
 
792
        for (regionp = listregionp; regionp; regionp = regionp->next) {
793
                if (regionp->id == regionid) {
794
                        return regionp;
795
                }
796
        }
797
 
798
        return NULL;
799
}
800
 
801
/* find a font with specified id*/
802
GR_FONT *
803
GsFindFont(GR_FONT_ID fontid)
804
{
805
        GR_FONT         *fontp;
806
 
807
        for (fontp = listfontp; fontp; fontp = fontp->next) {
808
                if (fontp->id == fontid)
809
                        return fontp;
810
        }
811
        return NULL;
812
}
813
 
814
/* find a cursor with specified id*/
815
GR_CURSOR *
816
GsFindCursor(GR_CURSOR_ID cursorid)
817
{
818
        GR_CURSOR       *cursorp;
819
 
820
        for (cursorp = listcursorp; cursorp; cursorp = cursorp->next) {
821
                if (cursorp->id == cursorid)
822
                        return cursorp;
823
        }
824
        return NULL;
825
}
826
 
827
GR_TIMER *
828
GsFindTimer (GR_TIMER_ID timer_id)
829
{
830
    GR_TIMER   *timer;
831
 
832
    /*
833
     * See if this is the same graphics context as last time.
834
     */
835
    if ((timer_id == cache_timer_id) && timer_id)
836
        return cache_timer;
837
 
838
    /*
839
     * No, search for it and cache it for future calls.
840
     */
841
    for (timer = list_timer; timer != NULL; timer = timer->next)
842
    {
843
        if (timer->id == timer_id)
844
        {
845
            cache_timer_id = timer_id;
846
            cache_timer = timer;
847
            return timer;
848
        }
849
    }
850
    return NULL;
851
}
852
 
853
 
854
/*
855
 * Prepare to do drawing in a window or pixmap using the specified
856
 * graphics context.  Returns the drawable pointer if successful,
857
 * and the type of drawing id that was supplied.  Returns the special value
858
 * GR_DRAW_TYPE_NONE if an error is generated, or if drawing is useless.
859
 */
860
GR_DRAW_TYPE GsPrepareDrawing(GR_DRAW_ID id, GR_GC_ID gcid, GR_DRAWABLE **retdp)
861
{
862
        GR_WINDOW       *wp;            /* found window */
863
        GR_PIXMAP       *pp;            /* found pixmap */
864
        GR_GC           *gcp;           /* found graphics context */
865
        GR_FONT         *fontp;
866
        GR_REGION       *regionp;       /* user clipping region */
867
        MWCLIPREGION    *reg;
868
        PMWFONT         pf;
869
 
870
        *retdp = NULL;
871
 
872
        gcp = GsFindGC(gcid);
873
        if (gcp == NULL)
874
                return GR_DRAW_TYPE_NONE;
875
 
876
        /*
877
         * If the graphics context is not the current one, then
878
         * make it the current one and remember to update it.
879
         */
880
        if (gcp != curgcp) {
881
                curgcp = gcp;
882
                gcp->changed = GR_TRUE;
883
        }
884
 
885
        /*
886
         * Look for window or pixmap id
887
         */
888
        pp = NULL;
889
        wp = GsFindWindow(id);
890
        if (wp == NULL) {
891
                pp = GsFindPixmap(id);
892
                if (pp == NULL)
893
                          return GR_DRAW_TYPE_NONE;
894
 
895
#if DYNAMICREGIONS
896
                reg = GdAllocRectRegion(0, 0, pp->psd->xvirtres,
897
                        pp->psd->yvirtres);
898
                /* intersect with user region if any*/
899
                if (gcp->regionid) {
900
                        regionp = GsFindRegion(gcp->regionid);
901
                        if (regionp)
902
                                GdIntersectRegion(reg, reg, regionp->rgn);
903
                }
904
                GdSetClipRegion(pp->psd, reg);
905
#else
906
                {
907
                MWCLIPRECT      cliprect;
908
                /* FIXME: setup pixmap clipping, different from windows*/
909
                cliprect.x = 0;
910
                cliprect.y = 0;
911
                cliprect.width = pp->psd->xvirtres;
912
                cliprect.height = pp->psd->yvirtres;
913
                GdSetClipRects(pp->psd, 1, &cliprect);
914
                }
915
#endif
916
                /* reset clip cache for next window draw*/
917
                clipwp = NULL;
918
        } else {
919
 
920
                if (!wp->output) {
921
                          GsError(GR_ERROR_INPUT_ONLY_WINDOW, id);
922
                          return GR_DRAW_TYPE_NONE;
923
                }
924
 
925
                if (wp->unmapcount)
926
                          return GR_DRAW_TYPE_NONE;
927
 
928
                /*
929
                 * If the window is not the currently clipped one,
930
                 * then make it the current one and define its clip rectangles.
931
                 */
932
                if (wp != clipwp || gcp->changed) {
933
                        /* find user region for intersect*/
934
                        if (gcp->regionid)
935
                                regionp = GsFindRegion(gcp->regionid);
936
                        else regionp = NULL;
937
 
938
                        /*
939
                         * Special handling if user region is not at offset 0,0
940
                         */
941
                        if (regionp && (gcp->xoff || gcp->yoff)) {
942
                                MWCLIPREGION *local = GdAllocRegion();
943
 
944
                                GdCopyRegion(local, regionp->rgn);
945
                                GdOffsetRegion(local, gcp->xoff, gcp->yoff);
946
 
947
                                GsSetClipWindow(wp, local,
948
                                        gcp->mode & ~GR_MODE_DRAWMASK);
949
 
950
                                GdDestroyRegion(local);
951
                          } else {
952
                                GsSetClipWindow(wp, regionp? regionp->rgn: NULL,
953
                                        gcp->mode & ~GR_MODE_DRAWMASK);
954
                          }
955
                }
956
        }
957
 
958
        /*
959
         * If the graphics context has been changed, then tell the
960
         * device driver about it.
961
         */
962
        if (gcp->changed) {
963
                GdSetForeground(GdFindColor(gcp->foreground));
964
                GdSetBackground(GdFindColor(gcp->background));
965
                GdSetMode(gcp->mode & GR_MODE_DRAWMASK);
966
                GdSetUseBackground(gcp->usebackground);
967
                fontp = GsFindFont(gcp->fontid);
968
                pf = fontp? fontp->pfont: stdfont;
969
                GdSetFont(pf);
970
                gcp->changed = GR_FALSE;
971
        }
972
 
973
        *retdp = wp? (GR_DRAWABLE *)wp: (GR_DRAWABLE *)pp;
974
        return wp? GR_DRAW_TYPE_WINDOW: GR_DRAW_TYPE_PIXMAP;
975
}
976
 
977
/*
978
 * Prepare the specified window for drawing into it.
979
 * This sets up the clipping regions to just allow drawing into it.
980
 * Returns NULL if the drawing is illegal (with an error generated),
981
 * or if the window is not mapped.
982
 */
983
GR_WINDOW *GsPrepareWindow(GR_WINDOW_ID wid)
984
{
985
        GR_WINDOW       *wp;            /* found window */
986
 
987
        wp = GsFindWindow(wid);
988
        if (wp == NULL)
989
                return NULL;
990
 
991
        if (!wp->output) {
992
                GsError(GR_ERROR_INPUT_ONLY_WINDOW, wid);
993
                return NULL;
994
        }
995
 
996
        if (wp->unmapcount)
997
                return NULL;
998
 
999
        if (wp != clipwp) {
1000
                /* FIXME: no user region clipping here*/
1001
                GsSetClipWindow(wp, NULL, 0);
1002
        }
1003
 
1004
        return wp;
1005
}
1006
 
1007
/*
1008
 * Find the window which is currently visible for the specified coordinates.
1009
 * This just walks down the window tree looking for the deepest mapped
1010
 * window which contains the specified point.  If the coordinates are
1011
 * off the screen, the root window is returned.
1012
 */
1013
GR_WINDOW *GsFindVisibleWindow(GR_COORD x, GR_COORD y)
1014
{
1015
        GR_WINDOW       *wp;            /* current window */
1016
        GR_WINDOW       *retwp;         /* returned window */
1017
 
1018
        wp = rootwp;
1019
        retwp = wp;
1020
        while (wp) {
1021
                if ((wp->unmapcount == 0) && (wp->x <= x) && (wp->y <= y) &&
1022
                        (wp->x + wp->width > x) && (wp->y + wp->height > y))
1023
                {
1024
                        retwp = wp;
1025
                        wp = wp->children;
1026
                        continue;
1027
                }
1028
                wp = wp->siblings;
1029
        }
1030
        return retwp;
1031
}
1032
 
1033
/*
1034
 * Check to see if the cursor shape is the correct shape for its current
1035
 * location.  If not, its shape is changed.
1036
 */
1037
void GsCheckCursor(void)
1038
{
1039
        GR_WINDOW       *wp;            /* window cursor is in */
1040
        GR_CURSOR       *cp;            /* cursor definition */
1041
 
1042
        /*
1043
         * Get the cursor at its current position, and if it is not the
1044
         * currently defined one, then set the new cursor.  However,
1045
         * if the pointer is currently grabbed, then leave it alone.
1046
         */
1047
        wp = grabbuttonwp;
1048
        if (wp == NULL)
1049
                wp = mousewp;
1050
 
1051
        cp = GsFindCursor(wp->cursorid);
1052
        if (!cp)
1053
                cp = stdcursor;
1054
        if (cp == curcursor)
1055
                return;
1056
 
1057
        /*
1058
         * It needs redefining, so do it.
1059
         */
1060
        curcursor = cp;
1061
        GdMoveCursor(cursorx - cp->cursor.hotx, cursory - cp->cursor.hoty);
1062
        GdSetCursor(&cp->cursor);
1063
}
1064
 
1065
/*
1066
 * Check to see if the window the mouse is currently in has changed.
1067
 * If so, generate enter and leave events as required.  The newest
1068
 * mouse window is remembered in mousewp.  However, do not change the
1069
 * window while it is grabbed.
1070
 */
1071
void GsCheckMouseWindow(void)
1072
{
1073
        GR_WINDOW       *wp;            /* newest window for mouse */
1074
 
1075
        wp = grabbuttonwp;
1076
        if (wp == NULL)
1077
                wp = GsFindVisibleWindow(cursorx, cursory);
1078
        if (wp == mousewp)
1079
                return;
1080
 
1081
        GsDeliverGeneralEvent(mousewp, GR_EVENT_TYPE_MOUSE_EXIT, NULL);
1082
 
1083
        mousewp = wp;
1084
 
1085
        GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_MOUSE_ENTER, NULL);
1086
}
1087
 
1088
/*
1089
 * Determine the current focus window for the current mouse coordinates.
1090
 * The mouse coordinates only matter if the focus is not fixed.  Otherwise,
1091
 * the selected window is dependant on the window which wants keyboard
1092
 * events.  This also sets the current focus for that found window.
1093
 * The window with focus is remembered in focuswp.
1094
 */
1095
void GsCheckFocusWindow(void)
1096
{
1097
        GR_WINDOW               *wp;            /* current window */
1098
        GR_EVENT_CLIENT         *ecp;           /* current event client */
1099
        GR_EVENT_MASK           eventmask;      /* event mask */
1100
 
1101
        if (focusfixed)
1102
                return;
1103
 
1104
        eventmask = GR_EVENT_MASK_KEY_DOWN;
1105
 
1106
        /*
1107
         * Walk upwards from the current window containing the mouse
1108
         * looking for the first window which would accept a keyboard event.
1109
         */
1110
        for (wp = mousewp; ;wp = wp->parent) {
1111
                if (wp->props & GR_WM_PROPS_NOFOCUS)
1112
                        continue;
1113
                for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
1114
                        if (ecp->eventmask & eventmask) {
1115
                                GsWpSetFocus(wp);
1116
                                return;
1117
                        }
1118
                }
1119
                if ((wp == rootwp) || (wp->nopropmask & eventmask)) {
1120
                        GsWpSetFocus(rootwp);
1121
                        return;
1122
                }
1123
        }
1124
}
1125
 
1126
/* Send an update activate event to top level window of passed window*/
1127
static void
1128
GsWpNotifyActivate(GR_WINDOW *wp)
1129
{
1130
        GR_WINDOW       *pwp;
1131
 
1132
        for (pwp=wp; pwp->parent; pwp=pwp->parent)
1133
                if (pwp->parent->id == GR_ROOT_WINDOW_ID)
1134
                        break;
1135
        if (pwp->id != GR_ROOT_WINDOW_ID)
1136
                GsDeliverUpdateEvent(pwp, GR_UPDATE_ACTIVATE, 0, 0, 0, 0);
1137
}
1138
 
1139
/*
1140
 * Set the input focus to the specified window.
1141
 * This generates focus out and focus in events as necessary.
1142
 */
1143
void GsWpSetFocus(GR_WINDOW *wp)
1144
{
1145
        GR_WINDOW       *oldfocus;
1146
 
1147
        if (wp == focuswp)
1148
                return;
1149
 
1150
        GsDeliverGeneralEvent(focuswp, GR_EVENT_TYPE_FOCUS_OUT, wp);
1151
        GsWpNotifyActivate(focuswp);
1152
 
1153
        oldfocus = focuswp;
1154
        focuswp = wp;
1155
 
1156
        GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_FOCUS_IN, oldfocus);
1157
        GsWpNotifyActivate(focuswp);
1158
}
1159
 
1160
/*
1161
 * Set dynamic portrait mode and redraw screen.
1162
 */
1163
void
1164
GsSetPortraitMode(int mode)
1165
{
1166
        GdSetPortraitMode(&scrdev, mode);
1167
        GdRestrictMouse(0, 0, scrdev.xvirtres - 1, scrdev.yvirtres - 1);
1168
 
1169
        /* reset clip and root window size*/
1170
        clipwp = NULL;
1171
        rootwp->width = scrdev.xvirtres;
1172
        rootwp->height = scrdev.yvirtres;
1173
 
1174
        /* deliver portrait changed event to all windows selecting it*/
1175
        GsDeliverPortraitChangedEvent();
1176
 
1177
        /* redraw screen - apps may redraw/resize again causing flicker*/
1178
        GsRedrawScreen();
1179
}
1180
 
1181
/*
1182
 * Check mouse coordinates and possibly set indicated portrait
1183
 * mode from mouse position.
1184
 */
1185
void
1186
GsSetPortraitModeFromXY(GR_COORD rootx, GR_COORD rooty)
1187
{
1188
        int newmode;
1189
 
1190
        if (rootx == 0) {
1191
                /* rotate left*/
1192
                switch (scrdev.portrait) {
1193
                case MWPORTRAIT_NONE:
1194
                default:
1195
                        newmode = MWPORTRAIT_LEFT;
1196
                        break;
1197
                case MWPORTRAIT_LEFT:
1198
                        newmode = MWPORTRAIT_DOWN;
1199
                        break;
1200
                case MWPORTRAIT_DOWN:
1201
                        newmode = MWPORTRAIT_RIGHT;
1202
                        break;
1203
                case MWPORTRAIT_RIGHT:
1204
                        newmode = MWPORTRAIT_NONE;
1205
                        break;
1206
                }
1207
                GsSetPortraitMode(newmode);
1208
                GrMoveCursor(5, rooty);
1209
                GdMoveMouse(5, rooty);
1210
        } else if (rootx == scrdev.xvirtres-1) {
1211
                /* rotate right*/
1212
                switch (scrdev.portrait) {
1213
                case MWPORTRAIT_NONE:
1214
                default:
1215
                        newmode = MWPORTRAIT_RIGHT;
1216
                        break;
1217
                case MWPORTRAIT_LEFT:
1218
                        newmode = MWPORTRAIT_NONE;
1219
                        break;
1220
                case MWPORTRAIT_DOWN:
1221
                        newmode = MWPORTRAIT_LEFT;
1222
                        break;
1223
                case MWPORTRAIT_RIGHT:
1224
                        newmode = MWPORTRAIT_DOWN;
1225
                        break;
1226
                }
1227
                GsSetPortraitMode(newmode);
1228
                GrMoveCursor(scrdev.xvirtres-5, rooty);
1229
                GdMoveMouse(scrdev.xvirtres-5, rooty);
1230
        }
1231
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.