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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [mw/] [src/] [nanox/] [srvutil.c] - Blame information for rev 1775

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
/*
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 716 simons
        if (wp == grabbuttonwp) {
280 673 markom
                grabbuttonwp = NULL;
281 716 simons
        }
282 673 markom
        if (wp == cachewp) {
283
                cachewindowid = 0;
284
                cachewp = NULL;
285
        }
286
        if (wp == focuswp) {
287
                /* don't revert to mouse enter/leave focus if fixed*/
288
                /*focusfixed = GR_FALSE;*/
289
                focuswp = rootwp;
290
        }
291
 
292
        GsCheckMouseWindow();
293
 
294
        if(wp->title)
295
                free(wp->title);
296
 
297
        free(wp);
298
}
299
 
300
/*
301
 * Draw a window's background pixmap.
302
 *
303
 * The flags mean:
304
 *   GR_BACKGROUND_TILE- tile the pixmap across the window (default).
305
 *   GR_BACKGROUND_TOPLEFT- draw the pixmap at (0,0) relative to the window.
306
 *   GR_BACKGROUND_CENTER- draw the pixmap in the middle of the window.
307
 *   GR_BACKGROUND_STRETCH- stretch the pixmap within the window.
308
 *   GR_BACKGROUND_TRANS- if the pixmap is smaller than the window and not
309
 *     using tile mode, there will be gaps around the pixmap. This flag causes
310
 *     to not fill in the spaces with the background colour.
311
 */
312
void GsWpDrawBackgroundPixmap(GR_WINDOW *wp, GR_PIXMAP *pm, GR_COORD x,
313
        GR_COORD y, GR_SIZE width, GR_SIZE height)
314
{
315
        GR_SIZE destwidth, destheight, fillwidth, fillheight, pmwidth, pmheight;
316
        GR_COORD fromx, fromy, destx, desty, pixmapx = 0, pixmapy = 0;
317
 
318
        if(wp->bgpixmapflags & (GR_BACKGROUND_TOPLEFT|GR_BACKGROUND_STRETCH)) {
319
                pixmapx = 0;
320
                pixmapy = 0;
321
        } else if(wp->bgpixmapflags & GR_BACKGROUND_CENTER) {
322
                if(pm->width >= wp->width) pixmapx = 0;
323
                else pixmapx = (wp->width - pm->width) / 2;
324
                if(pm->height >= wp->height) pixmapy = 0;
325
                else pixmapy = (wp->height - pm->height) / 2;
326
        } else {
327
                /* GR_BACKGROUND_TILE (default)*/
328
                GsWpTileBackgroundPixmap(wp, pm, x, y, width, height);
329
                return;
330
        }
331
 
332
        if(pm->width > wp->width) pmwidth = wp->width;
333
        else pmwidth = pm->width;
334
        if(pm->height > wp->height) pmheight = wp->height;
335
        else pmheight = pm->height;
336
 
337
        if(x > pixmapx) {
338
                destx = x;
339
                fromx = x - pixmapx;
340
                destwidth = pixmapx + pmwidth - x;
341
        } else {
342
                destx = pixmapx;
343
                fromx = 0;
344
                destwidth = x + width - pixmapx;
345
        }
346
 
347
        if(y > pixmapy) {
348
                desty = y;
349
                fromy = y - pixmapy;
350
                destheight = pixmapy + pmheight - desty;
351
        } else {
352
                desty = pixmapy;
353
                fromy = 0;
354
                destheight = y + height - pixmapy;
355
        }
356
 
357
        if(destwidth > 0 && destheight > 0) {
358
                if (wp->bgpixmapflags & GR_BACKGROUND_STRETCH) {
359
                        GdStretchBlit(wp->psd, destx + wp->x, desty + wp->y,
360
                                destwidth, destheight, pm->psd, fromx, fromy,
361
                                pm->width, pm->height, MWROP_COPY);
362
                } else GdBlit(wp->psd, destx + wp->x, desty + wp->y, destwidth,
363
                        destheight, pm->psd, fromx, fromy, MWROP_COPY);
364
        }
365
 
366
        if(wp->bgpixmapflags & (GR_BACKGROUND_TRANS|GR_BACKGROUND_STRETCH))
367
                return;
368
 
369
        /* Fill in the gaps around the pixmap */
370
        if(x < pixmapx) {
371
                fillwidth = pixmapx - x;
372
                if(fillwidth > width) fillwidth = width;
373
                fillheight = height;
374
                GdFillRect(wp->psd, wp->x + x, wp->y + y, fillwidth,fillheight);
375
        }
376
        if((x + width) > (pixmapx + pmwidth)) {
377
                fillwidth = (x + width) - (pixmapx + pmwidth);
378
                if(fillwidth > width) fillwidth = width;
379
                fillheight = height;
380
                if(x < (pixmapx + pmwidth)) destx = pixmapx + pmwidth + wp->x;
381
                else destx = x + wp->x;
382
                GdFillRect(wp->psd, destx, wp->y + y, fillwidth, fillheight);
383
        }
384
        if(y < pixmapy) {
385
                fillheight = pixmapy - y;
386
                if(fillheight > height) fillheight = height;
387
                if(x < pixmapx) destx = pixmapx + wp->x;
388
                else destx = x + wp->x;
389
                if((x + width) > (pixmapx + pmwidth))
390
                        fillwidth = pixmapx + pmwidth - destx;
391
                else fillwidth = x + width - destx;
392
                if((fillwidth > 0) && (fillheight > 0)) {
393
                        GdFillRect(wp->psd, destx, wp->y + y, fillwidth,
394
                                                        fillheight);
395
                }
396
        }
397
        if((y + height) > (pixmapy + pmheight)) {
398
                fillheight = (y + height) - (pixmapy + pmheight);
399
                if(fillheight > height) fillheight = height;
400
                if(x < pixmapx) destx = pixmapx + wp->x;
401
                else destx = x + wp->x;
402
                if(y < (pixmapy + pmheight)) desty = pixmapy + pmheight + wp->y;
403
                else desty = y + wp->y;
404
 
405
                if((x + width) > (pixmapx + pmwidth))
406
                        fillwidth = pixmapx + pmwidth - destx;
407
                else fillwidth = x + width - destx;
408
                if((fillwidth > 0) && (fillheight > 0)) {
409
                        GdFillRect(wp->psd, destx, desty, fillwidth,fillheight);
410
                }
411
        }
412
}
413
 
414
/*
415
 * Draw a tiled pixmap window background.
416
 */
417
void
418
GsWpTileBackgroundPixmap(GR_WINDOW *wp, GR_PIXMAP *pm, GR_COORD x, GR_COORD y,
419
        GR_SIZE width, GR_SIZE height)
420
{
421
        GR_COORD tilex = 0, tiley = 0, fromx, fromy, cx, cy;
422
        GR_SIZE destwidth, destheight, pmwidth, pmheight, cwidth, cheight;
423
 
424
        if(pm->width > wp->width) pmwidth = wp->width;
425
        else pmwidth = pm->width;
426
        if(pm->height > wp->height) pmheight = wp->height;
427
        else pmheight = pm->height;
428
 
429
        for(;tiley < wp->height; tiley += pmheight, tilex = 0) {
430
                if(tiley > (y + height)) continue;
431
                if(y > (tiley + pmheight)) continue;
432
                if((tiley + pmheight) > wp->height)
433
                        destheight = wp->height - tiley;
434
                else destheight = pmheight;
435
                for(;tilex < wp->width; tilex += pmwidth) {
436
                        if(tilex > (x + width)) continue;
437
                        if(x > (tilex + pmwidth)) continue;
438
                        if((tilex + pmwidth) > wp->width)
439
                                destwidth = wp->width - tilex;
440
                        else destwidth = pmwidth;
441
 
442
                        if((tilex >= x) && ((tilex + destwidth)<=(x + width))) {
443
                                fromx = 0;
444
                                cx = tilex + wp->x;
445
                                cwidth = destwidth;
446
                        } else {
447
                                if(x > tilex) {
448
                                        fromx = x - tilex;
449
                                        cwidth = destwidth - fromx;
450
                                } else {
451
                                        fromx = 0;
452
                                        cwidth = x + width - tilex;
453
                                }
454
                                if(cwidth > width) cwidth = width;
455
                                if(cwidth > destwidth) cwidth = destwidth;
456
                                cx = wp->x + tilex + fromx;
457
                        }
458
 
459
                        if((tiley >= y)&&((tiley + destheight)<=(y + height))) {
460
                                fromy = 0;
461
                                cy = tiley + wp->y;
462
                                cheight = destheight;
463
                        } else {
464
                                if(y > tiley) {
465
                                        fromy = y - tiley;
466
                                        cheight = destheight - fromy;
467
                                } else {
468
                                        fromy = 0;
469
                                        cheight = y + height - tiley;
470
                                }
471
                                if(cwidth > width) cwidth = width;
472
                                if(cheight > destheight) cheight = destheight;
473
                                cy = wp->y + tiley + fromy;
474
                        }
475
 
476
                        if((cwidth > 0) && (cheight > 0)) {
477
                                GdBlit(wp->psd, cx, cy, cwidth, cheight,
478
                                        pm->psd, fromx, fromy, MWROP_COPY);
479
                        }
480
                }
481
        }
482
}
483
 
484
/*
485
 * Clear the specified area of a window and possibly make an exposure event.
486
 * This sets the area window to its background color or pixmap.  If the
487
 * exposeflag is nonzero, then this also creates an exposure event for the
488
 * window.
489
 */
490
void
491
GsWpClearWindow(GR_WINDOW *wp, GR_COORD x, GR_COORD y, GR_SIZE width,
492
        GR_SIZE  height, GR_BOOL exposeflag)
493
{
494
        if (wp->unmapcount || !wp->output)
495
                return;
496
        /*
497
         * Reduce the arguments so that they actually lie within the window.
498
         */
499
        if (x < 0) {
500
                width += x;
501
                x = 0;
502
        }
503
        if (y < 0) {
504
                height += y;
505
                y = 0;
506
        }
507
        if (x + width > wp->width)
508
                width = wp->width - x;
509
        if (y + height > wp->height)
510
                height = wp->height - y;
511
 
512
        /*
513
         * Now see if the region is really in the window.  If not, then
514
         * do nothing.
515
         */
516
        if ((x >= wp->width) || (y >= wp->height) || (width <= 0) ||
517
                (height <= 0))
518
                        return;
519
 
520
        /*
521
         * Draw the background of the window.
522
         * Invalidate the current graphics context since
523
         * we are changing the foreground color and mode.
524
         */
525
        GsSetClipWindow(wp, NULL, 0);
526
        curgcp = NULL;
527
        if (!(wp->props & GR_WM_PROPS_NOBACKGROUND)) {
528
                GdSetMode(GR_MODE_COPY);
529
                GdSetForeground(GdFindColor(wp->background));
530
                if (wp->bgpixmap) {
531
                        GsWpDrawBackgroundPixmap(wp, wp->bgpixmap, x, y,
532
                                width, height);
533
                } else {
534
                        GdFillRect(wp->psd, wp->x + x, wp->y + y, width,height);
535
                }
536
        }
537
 
538
        /*
539
         * Now do the exposure if required.
540
         */
541
        if (exposeflag)
542
                GsDeliverExposureEvent(wp, x, y, width, height);
543
}
544
 
545
/*
546
 * Handle the exposing of the specified absolute region of the screen,
547
 * starting with the specified window.  That window and all of its
548
 * children will be redrawn and/or exposure events generated if they
549
 * overlap the specified area.  This is a recursive routine.
550
 */
551
void
552
GsExposeArea(GR_WINDOW *wp, GR_COORD rootx, GR_COORD rooty, GR_SIZE width,
553
        GR_SIZE height, GR_WINDOW *stopwp)
554
{
555
        if (!wp->output || wp->unmapcount || wp == stopwp)
556
                return;
557
 
558
        /*
559
         * First see if the area overlaps the window including the border.
560
         * If not, then there is nothing more to do.
561
         */
562
        if ((rootx >= wp->x + wp->width + wp->bordersize) ||
563
                (rooty >= wp->y + wp->height + wp->bordersize) ||
564
                (rootx + width <= wp->x - wp->bordersize) ||
565
                (rooty + height <= wp->y - wp->bordersize))
566
                        return;
567
 
568
        /*
569
         * The area does overlap the window.  See if the area overlaps
570
         * the border, and if so, then redraw it.
571
         */
572
        if ((rootx < wp->x) || (rooty < wp->y) ||
573
                (rootx + width > wp->x + wp->width) ||
574
                (rooty + height > wp->y + wp->height))
575
                        GsDrawBorder(wp);
576
 
577
        /*
578
         * Now clear the window itself in the specified area,
579
         * which might cause an exposure event.
580
         */
581
        GsWpClearWindow(wp, rootx - wp->x, rooty - wp->y,
582
                width, height, GR_TRUE);
583
 
584
        /*
585
         * Now do the same for all the children.
586
         */
587
        for (wp = wp->children; wp; wp = wp->siblings)
588
                GsExposeArea(wp, rootx, rooty, width, height, stopwp);
589
}
590
 
591
/*
592
 * Draw the border of a window if there is one.
593
 * Note: To allow the border to be drawn with the correct clipping,
594
 * we temporarily grow the size of the window to include the border.
595
 */
596
void GsDrawBorder(GR_WINDOW *wp)
597
{
598
        GR_COORD        lminx;          /* left edge minimum x */
599
        GR_COORD        rminx;          /* right edge minimum x */
600
        GR_COORD        tminy;          /* top edge minimum y */
601
        GR_COORD        bminy;          /* bottom edge minimum y */
602
        GR_COORD        topy;           /* top y value of window */
603
        GR_COORD        boty;           /* bottom y value of window */
604
        GR_SIZE         width;          /* original width of window */
605
        GR_SIZE         height;         /* original height of window */
606
        GR_SIZE         bs;             /* border size */
607
 
608
        bs = wp->bordersize;
609
        if (bs <= 0)
610
                return;
611
 
612
        width = wp->width;
613
        height = wp->height;
614
        lminx = wp->x - bs;
615
        rminx = wp->x + width;
616
        tminy = wp->y - bs;
617
        bminy = wp->y + height;
618
        topy = wp->y;
619
        boty = bminy - 1;
620
 
621
        wp->x -= bs;
622
        wp->y -= bs;
623
        wp->width += (bs * 2);
624
        wp->height += (bs * 2);
625
        wp->bordersize = 0;
626
 
627
        clipwp = NULL;
628
        GsSetClipWindow(wp, NULL, 0);
629
        curgcp = NULL;
630
        GdSetMode(GR_MODE_COPY);
631
        GdSetForeground(GdFindColor(wp->bordercolor));
632
 
633
        if (bs == 1) {
634
                GdLine(wp->psd, lminx, tminy, rminx, tminy, TRUE);
635
                GdLine(wp->psd, lminx, bminy, rminx, bminy, TRUE);
636
                GdLine(wp->psd, lminx, topy, lminx, boty, TRUE);
637
                GdLine(wp->psd, rminx, topy, rminx, boty, TRUE);
638
        } else {
639
                GdFillRect(wp->psd, lminx, tminy, width + bs * 2, bs);
640
                GdFillRect(wp->psd, lminx, bminy, width + bs * 2, bs);
641
                GdFillRect(wp->psd, lminx, topy, bs, height);
642
                GdFillRect(wp->psd, rminx, topy, bs, height);
643
        }
644
 
645
        /*
646
         * Restore the true window size.
647
         * Forget the currently clipped window since we messed it up.
648
         */
649
        wp->x += bs;
650
        wp->y += bs;
651
        wp->width -= (bs * 2);
652
        wp->height -= (bs * 2);
653
        wp->bordersize = bs;
654
        clipwp = NULL;
655
}
656
 
657
/*
658
 * Check to see if the first window overlaps the second window.
659
 */
660
GR_BOOL GsCheckOverlap(GR_WINDOW *topwp, GR_WINDOW *botwp)
661
{
662
        GR_COORD        minx1;
663
        GR_COORD        miny1;
664
        GR_COORD        maxx1;
665
        GR_COORD        maxy1;
666
        GR_COORD        minx2;
667
        GR_COORD        miny2;
668
        GR_COORD        maxx2;
669
        GR_COORD        maxy2;
670
        GR_SIZE         bs;
671
 
672
        if (!topwp->output || topwp->unmapcount || botwp->unmapcount)
673
                return GR_FALSE;
674
 
675
        bs = topwp->bordersize;
676
        minx1 = topwp->x - bs;
677
        miny1 = topwp->y - bs;
678
        maxx1 = topwp->x + topwp->width + bs - 1;
679
        maxy1 = topwp->y + topwp->height + bs - 1;
680
 
681
        bs = botwp->bordersize;
682
        minx2 = botwp->x - bs;
683
        miny2 = botwp->y - bs;
684
        maxx2 = botwp->x + botwp->width + bs - 1;
685
        maxy2 = botwp->y + botwp->height + bs - 1;
686
 
687
        if ((minx1 > maxx2) || (minx2 > maxx1) || (miny1 > maxy2)
688
                || (miny2 > maxy1))
689
                        return GR_FALSE;
690
 
691
        return GR_TRUE;
692
}
693
 
694
/*
695
 * Return a pointer to the window structure with the specified window id.
696
 * Returns NULL if the window does not exist.
697
 */
698
GR_WINDOW *
699
GsFindWindow(GR_WINDOW_ID id)
700
{
701
        GR_WINDOW       *wp;            /* current window pointer */
702
 
703
        /*
704
         * See if this is the root window or the same window as last time.
705
         */
706
        if (id == GR_ROOT_WINDOW_ID)
707
                return rootwp;
708
 
709
        if ((id == cachewindowid) && id)
710
                return cachewp;
711
 
712
        /*
713
         * No, search for it and cache it for future calls.
714
         */
715
        for (wp = listwp; wp; wp = wp->next) {
716
                if (wp->id == id) {
717
                        cachewindowid = id;
718
                        cachewp = wp;
719
                        return wp;
720
                }
721
        }
722
 
723
        return NULL;
724
}
725
 
726
 
727
 
728
/*
729
 * Return a pointer to the pixmap structure with the specified window id.
730
 * Returns NULL if the pixmap does not exist.
731
 */
732
GR_PIXMAP *
733
GsFindPixmap(GR_WINDOW_ID id)
734
{
735
        GR_PIXMAP       *pp;            /* current pixmap pointer */
736
 
737
        if ((id == cachepixmapid) && id)
738
                return cachepp;
739
 
740
        /*
741
         * No, search for it and cache it for future calls.
742
         */
743
        for (pp = listpp; pp; pp = pp->next) {
744
                if (pp->id == id) {
745
                        cachepixmapid = id;
746
                        cachepp = pp;
747
                        return pp;
748
                }
749
        }
750
 
751
        return NULL;
752
}
753
 
754
 
755
/*
756
 * Return a pointer to the graphics context with the specified id.
757
 * Returns NULL if the graphics context does not exist, with an
758
 * error saved.
759
 */
760
GR_GC *
761
GsFindGC(GR_GC_ID gcid)
762
{
763
        GR_GC           *gcp;           /* current graphics context pointer */
764
 
765
        /*
766
         * See if this is the same graphics context as last time.
767
         */
768
        if ((gcid == cachegcid) && gcid)
769
                return cachegcp;
770
 
771
        /*
772
         * No, search for it and cache it for future calls.
773
         */
774
        for (gcp = listgcp; gcp; gcp = gcp->next) {
775
                if (gcp->id == gcid) {
776
                        cachegcid = gcid;
777
                        cachegcp = gcp;
778
                        return gcp;
779
                }
780
        }
781
 
782
        GsError(GR_ERROR_BAD_GC_ID, gcid);
783
 
784
        return NULL;
785
}
786
 
787
/* Return a pointer to the region with the specified id.*/
788
GR_REGION *
789
GsFindRegion(GR_REGION_ID regionid)
790
{
791
        GR_REGION       *regionp;       /* current region pointer */
792
 
793
        for (regionp = listregionp; regionp; regionp = regionp->next) {
794
                if (regionp->id == regionid) {
795
                        return regionp;
796
                }
797
        }
798
 
799
        return NULL;
800
}
801
 
802
/* find a font with specified id*/
803
GR_FONT *
804
GsFindFont(GR_FONT_ID fontid)
805
{
806
        GR_FONT         *fontp;
807
 
808
        for (fontp = listfontp; fontp; fontp = fontp->next) {
809
                if (fontp->id == fontid)
810
                        return fontp;
811
        }
812
        return NULL;
813
}
814
 
815
/* find a cursor with specified id*/
816
GR_CURSOR *
817
GsFindCursor(GR_CURSOR_ID cursorid)
818
{
819
        GR_CURSOR       *cursorp;
820
 
821
        for (cursorp = listcursorp; cursorp; cursorp = cursorp->next) {
822
                if (cursorp->id == cursorid)
823
                        return cursorp;
824
        }
825
        return NULL;
826
}
827
 
828
GR_TIMER *
829
GsFindTimer (GR_TIMER_ID timer_id)
830
{
831
    GR_TIMER   *timer;
832
 
833
    /*
834
     * See if this is the same graphics context as last time.
835
     */
836
    if ((timer_id == cache_timer_id) && timer_id)
837
        return cache_timer;
838
 
839
    /*
840
     * No, search for it and cache it for future calls.
841
     */
842
    for (timer = list_timer; timer != NULL; timer = timer->next)
843
    {
844
        if (timer->id == timer_id)
845
        {
846
            cache_timer_id = timer_id;
847
            cache_timer = timer;
848
            return timer;
849
        }
850
    }
851
    return NULL;
852
}
853
 
854
 
855
/*
856
 * Prepare to do drawing in a window or pixmap using the specified
857
 * graphics context.  Returns the drawable pointer if successful,
858
 * and the type of drawing id that was supplied.  Returns the special value
859
 * GR_DRAW_TYPE_NONE if an error is generated, or if drawing is useless.
860
 */
861
GR_DRAW_TYPE GsPrepareDrawing(GR_DRAW_ID id, GR_GC_ID gcid, GR_DRAWABLE **retdp)
862
{
863
        GR_WINDOW       *wp;            /* found window */
864
        GR_PIXMAP       *pp;            /* found pixmap */
865
        GR_GC           *gcp;           /* found graphics context */
866
        GR_FONT         *fontp;
867
        GR_REGION       *regionp;       /* user clipping region */
868
        MWCLIPREGION    *reg;
869
        PMWFONT         pf;
870
 
871
        *retdp = NULL;
872
 
873
        gcp = GsFindGC(gcid);
874
        if (gcp == NULL)
875
                return GR_DRAW_TYPE_NONE;
876
 
877
        /*
878
         * If the graphics context is not the current one, then
879
         * make it the current one and remember to update it.
880
         */
881
        if (gcp != curgcp) {
882
                curgcp = gcp;
883
                gcp->changed = GR_TRUE;
884
        }
885
 
886
        /*
887
         * Look for window or pixmap id
888
         */
889
        pp = NULL;
890
        wp = GsFindWindow(id);
891
        if (wp == NULL) {
892
                pp = GsFindPixmap(id);
893
                if (pp == NULL)
894
                          return GR_DRAW_TYPE_NONE;
895
 
896
#if DYNAMICREGIONS
897
                reg = GdAllocRectRegion(0, 0, pp->psd->xvirtres,
898
                        pp->psd->yvirtres);
899
                /* intersect with user region if any*/
900
                if (gcp->regionid) {
901
                        regionp = GsFindRegion(gcp->regionid);
902
                        if (regionp)
903
                                GdIntersectRegion(reg, reg, regionp->rgn);
904
                }
905
                GdSetClipRegion(pp->psd, reg);
906
#else
907
                {
908
                MWCLIPRECT      cliprect;
909
                /* FIXME: setup pixmap clipping, different from windows*/
910
                cliprect.x = 0;
911
                cliprect.y = 0;
912
                cliprect.width = pp->psd->xvirtres;
913
                cliprect.height = pp->psd->yvirtres;
914
                GdSetClipRects(pp->psd, 1, &cliprect);
915
                }
916
#endif
917
                /* reset clip cache for next window draw*/
918
                clipwp = NULL;
919
        } else {
920
 
921
                if (!wp->output) {
922
                          GsError(GR_ERROR_INPUT_ONLY_WINDOW, id);
923
                          return GR_DRAW_TYPE_NONE;
924
                }
925
 
926
                if (wp->unmapcount)
927
                          return GR_DRAW_TYPE_NONE;
928
 
929
                /*
930
                 * If the window is not the currently clipped one,
931
                 * then make it the current one and define its clip rectangles.
932
                 */
933
                if (wp != clipwp || gcp->changed) {
934
                        /* find user region for intersect*/
935
                        if (gcp->regionid)
936
                                regionp = GsFindRegion(gcp->regionid);
937
                        else regionp = NULL;
938
 
939
                        /*
940
                         * Special handling if user region is not at offset 0,0
941
                         */
942
                        if (regionp && (gcp->xoff || gcp->yoff)) {
943
                                MWCLIPREGION *local = GdAllocRegion();
944
 
945
                                GdCopyRegion(local, regionp->rgn);
946
                                GdOffsetRegion(local, gcp->xoff, gcp->yoff);
947
 
948
                                GsSetClipWindow(wp, local,
949
                                        gcp->mode & ~GR_MODE_DRAWMASK);
950
 
951
                                GdDestroyRegion(local);
952
                          } else {
953
                                GsSetClipWindow(wp, regionp? regionp->rgn: NULL,
954
                                        gcp->mode & ~GR_MODE_DRAWMASK);
955
                          }
956
                }
957
        }
958
 
959
        /*
960
         * If the graphics context has been changed, then tell the
961
         * device driver about it.
962
         */
963
        if (gcp->changed) {
964
                GdSetForeground(GdFindColor(gcp->foreground));
965
                GdSetBackground(GdFindColor(gcp->background));
966
                GdSetMode(gcp->mode & GR_MODE_DRAWMASK);
967
                GdSetUseBackground(gcp->usebackground);
968
                fontp = GsFindFont(gcp->fontid);
969
                pf = fontp? fontp->pfont: stdfont;
970
                GdSetFont(pf);
971
                gcp->changed = GR_FALSE;
972
        }
973
 
974
        *retdp = wp? (GR_DRAWABLE *)wp: (GR_DRAWABLE *)pp;
975
        return wp? GR_DRAW_TYPE_WINDOW: GR_DRAW_TYPE_PIXMAP;
976
}
977
 
978
/*
979
 * Prepare the specified window for drawing into it.
980
 * This sets up the clipping regions to just allow drawing into it.
981
 * Returns NULL if the drawing is illegal (with an error generated),
982
 * or if the window is not mapped.
983
 */
984
GR_WINDOW *GsPrepareWindow(GR_WINDOW_ID wid)
985
{
986
        GR_WINDOW       *wp;            /* found window */
987
 
988
        wp = GsFindWindow(wid);
989
        if (wp == NULL)
990
                return NULL;
991
 
992
        if (!wp->output) {
993
                GsError(GR_ERROR_INPUT_ONLY_WINDOW, wid);
994
                return NULL;
995
        }
996
 
997
        if (wp->unmapcount)
998
                return NULL;
999
 
1000
        if (wp != clipwp) {
1001
                /* FIXME: no user region clipping here*/
1002
                GsSetClipWindow(wp, NULL, 0);
1003
        }
1004
 
1005
        return wp;
1006
}
1007
 
1008
/*
1009
 * Find the window which is currently visible for the specified coordinates.
1010
 * This just walks down the window tree looking for the deepest mapped
1011
 * window which contains the specified point.  If the coordinates are
1012
 * off the screen, the root window is returned.
1013
 */
1014
GR_WINDOW *GsFindVisibleWindow(GR_COORD x, GR_COORD y)
1015
{
1016
        GR_WINDOW       *wp;            /* current window */
1017
        GR_WINDOW       *retwp;         /* returned window */
1018
 
1019
        wp = rootwp;
1020
        retwp = wp;
1021
        while (wp) {
1022
                if ((wp->unmapcount == 0) && (wp->x <= x) && (wp->y <= y) &&
1023
                        (wp->x + wp->width > x) && (wp->y + wp->height > y))
1024
                {
1025
                        retwp = wp;
1026
                        wp = wp->children;
1027
                        continue;
1028
                }
1029
                wp = wp->siblings;
1030
        }
1031
        return retwp;
1032
}
1033
 
1034
/*
1035
 * Check to see if the cursor shape is the correct shape for its current
1036
 * location.  If not, its shape is changed.
1037
 */
1038
void GsCheckCursor(void)
1039
{
1040
        GR_WINDOW       *wp;            /* window cursor is in */
1041
        GR_CURSOR       *cp;            /* cursor definition */
1042
 
1043
        /*
1044
         * Get the cursor at its current position, and if it is not the
1045
         * currently defined one, then set the new cursor.  However,
1046
         * if the pointer is currently grabbed, then leave it alone.
1047
         */
1048
        wp = grabbuttonwp;
1049
        if (wp == NULL)
1050
                wp = mousewp;
1051
 
1052
        cp = GsFindCursor(wp->cursorid);
1053
        if (!cp)
1054
                cp = stdcursor;
1055
        if (cp == curcursor)
1056
                return;
1057
 
1058
        /*
1059
         * It needs redefining, so do it.
1060
         */
1061
        curcursor = cp;
1062
        GdMoveCursor(cursorx - cp->cursor.hotx, cursory - cp->cursor.hoty);
1063
        GdSetCursor(&cp->cursor);
1064
}
1065
 
1066
/*
1067
 * Check to see if the window the mouse is currently in has changed.
1068
 * If so, generate enter and leave events as required.  The newest
1069
 * mouse window is remembered in mousewp.  However, do not change the
1070
 * window while it is grabbed.
1071
 */
1072
void GsCheckMouseWindow(void)
1073
{
1074
        GR_WINDOW       *wp;            /* newest window for mouse */
1075
 
1076
        wp = grabbuttonwp;
1077
        if (wp == NULL)
1078
                wp = GsFindVisibleWindow(cursorx, cursory);
1079
        if (wp == mousewp)
1080
                return;
1081
 
1082
        GsDeliverGeneralEvent(mousewp, GR_EVENT_TYPE_MOUSE_EXIT, NULL);
1083
 
1084
        mousewp = wp;
1085
 
1086
        GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_MOUSE_ENTER, NULL);
1087
}
1088
 
1089
/*
1090
 * Determine the current focus window for the current mouse coordinates.
1091
 * The mouse coordinates only matter if the focus is not fixed.  Otherwise,
1092
 * the selected window is dependant on the window which wants keyboard
1093
 * events.  This also sets the current focus for that found window.
1094
 * The window with focus is remembered in focuswp.
1095
 */
1096
void GsCheckFocusWindow(void)
1097
{
1098
        GR_WINDOW               *wp;            /* current window */
1099
        GR_EVENT_CLIENT         *ecp;           /* current event client */
1100
        GR_EVENT_MASK           eventmask;      /* event mask */
1101
 
1102
        if (focusfixed)
1103
                return;
1104
 
1105
        eventmask = GR_EVENT_MASK_KEY_DOWN;
1106
 
1107
        /*
1108
         * Walk upwards from the current window containing the mouse
1109
         * looking for the first window which would accept a keyboard event.
1110
         */
1111
        for (wp = mousewp; ;wp = wp->parent) {
1112
                if (wp->props & GR_WM_PROPS_NOFOCUS)
1113
                        continue;
1114
                for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
1115
                        if (ecp->eventmask & eventmask) {
1116
                                GsWpSetFocus(wp);
1117
                                return;
1118
                        }
1119
                }
1120
                if ((wp == rootwp) || (wp->nopropmask & eventmask)) {
1121
                        GsWpSetFocus(rootwp);
1122
                        return;
1123
                }
1124
        }
1125
}
1126
 
1127
/* Send an update activate event to top level window of passed window*/
1128
static void
1129
GsWpNotifyActivate(GR_WINDOW *wp)
1130
{
1131
        GR_WINDOW       *pwp;
1132
 
1133
        for (pwp=wp; pwp->parent; pwp=pwp->parent)
1134
                if (pwp->parent->id == GR_ROOT_WINDOW_ID)
1135
                        break;
1136
        if (pwp->id != GR_ROOT_WINDOW_ID)
1137
                GsDeliverUpdateEvent(pwp, GR_UPDATE_ACTIVATE, 0, 0, 0, 0);
1138
}
1139
 
1140
/*
1141
 * Set the input focus to the specified window.
1142
 * This generates focus out and focus in events as necessary.
1143
 */
1144
void GsWpSetFocus(GR_WINDOW *wp)
1145
{
1146
        GR_WINDOW       *oldfocus;
1147
 
1148
        if (wp == focuswp)
1149
                return;
1150
 
1151
        GsDeliverGeneralEvent(focuswp, GR_EVENT_TYPE_FOCUS_OUT, wp);
1152
        GsWpNotifyActivate(focuswp);
1153
 
1154
        oldfocus = focuswp;
1155
        focuswp = wp;
1156
 
1157
        GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_FOCUS_IN, oldfocus);
1158
        GsWpNotifyActivate(focuswp);
1159
}
1160
 
1161
/*
1162
 * Set dynamic portrait mode and redraw screen.
1163
 */
1164
void
1165
GsSetPortraitMode(int mode)
1166
{
1167
        GdSetPortraitMode(&scrdev, mode);
1168
        GdRestrictMouse(0, 0, scrdev.xvirtres - 1, scrdev.yvirtres - 1);
1169
 
1170
        /* reset clip and root window size*/
1171
        clipwp = NULL;
1172
        rootwp->width = scrdev.xvirtres;
1173
        rootwp->height = scrdev.yvirtres;
1174
 
1175
        /* deliver portrait changed event to all windows selecting it*/
1176
        GsDeliverPortraitChangedEvent();
1177
 
1178
        /* redraw screen - apps may redraw/resize again causing flicker*/
1179
        GsRedrawScreen();
1180
}
1181
 
1182
/*
1183
 * Check mouse coordinates and possibly set indicated portrait
1184
 * mode from mouse position.
1185
 */
1186
void
1187
GsSetPortraitModeFromXY(GR_COORD rootx, GR_COORD rooty)
1188
{
1189
        int newmode;
1190
 
1191
        if (rootx == 0) {
1192
                /* rotate left*/
1193
                switch (scrdev.portrait) {
1194
                case MWPORTRAIT_NONE:
1195
                default:
1196
                        newmode = MWPORTRAIT_LEFT;
1197
                        break;
1198
                case MWPORTRAIT_LEFT:
1199
                        newmode = MWPORTRAIT_DOWN;
1200
                        break;
1201
                case MWPORTRAIT_DOWN:
1202
                        newmode = MWPORTRAIT_RIGHT;
1203
                        break;
1204
                case MWPORTRAIT_RIGHT:
1205
                        newmode = MWPORTRAIT_NONE;
1206
                        break;
1207
                }
1208
                GsSetPortraitMode(newmode);
1209
                GrMoveCursor(5, rooty);
1210
                GdMoveMouse(5, rooty);
1211
        } else if (rootx == scrdev.xvirtres-1) {
1212
                /* rotate right*/
1213
                switch (scrdev.portrait) {
1214
                case MWPORTRAIT_NONE:
1215
                default:
1216
                        newmode = MWPORTRAIT_RIGHT;
1217
                        break;
1218
                case MWPORTRAIT_LEFT:
1219
                        newmode = MWPORTRAIT_NONE;
1220
                        break;
1221
                case MWPORTRAIT_DOWN:
1222
                        newmode = MWPORTRAIT_LEFT;
1223
                        break;
1224
                case MWPORTRAIT_RIGHT:
1225
                        newmode = MWPORTRAIT_DOWN;
1226
                        break;
1227
                }
1228
                GsSetPortraitMode(newmode);
1229
                GrMoveCursor(scrdev.xvirtres-5, rooty);
1230
                GdMoveMouse(scrdev.xvirtres-5, rooty);
1231
        }
1232
}

powered by: WebSVN 2.1.0

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