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/] [srvevent.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 event routines for windows.
8
 */
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <string.h>
12
#include "serv.h"
13
 
14
#ifndef __ECOS
15
/* readable error strings*/
16
char *nxErrorStrings[] = {
17
        GR_ERROR_STRINGS
18
};
19
#endif
20
 
21
#if NONETWORK
22
/* [copied from client.c]
23
 * The following is the user defined function for handling errors.
24
 * If this is not set, then the default action is to close the connection
25
 * to the server, describe the error, and then exit.  This error function
26
 * will only be called when the client asks for events.
27
 */
28
static GR_FNCALLBACKEVENT ErrorFunc = GrDefaultErrorHandler;
29
 
30
/*
31
 * The default error handler which is called when the server
32
 * reports an error event and the client hasn't set a handler for error events.
33
 */
34
void
35
GrDefaultErrorHandler(GR_EVENT *ep)
36
{
37
        if (ep->type == GR_EVENT_TYPE_ERROR) {
38
                EPRINTF("nxclient: Error (%s) ", ep->error.name);
39
                EPRINTF(nxErrorStrings[ep->error.code], ep->error.id);
40
                GrClose();
41
                exit(1);
42
        }
43
}
44
 
45
/*
46
 * Set an error handling routine, which will be called on any errors from
47
 * the server (when events are asked for by the client).  If zero is given,
48
 * then errors will be returned as regular events.
49
 * Returns the previous error handler.
50
 */
51
GR_FNCALLBACKEVENT
52
GrSetErrorHandler(GR_FNCALLBACKEVENT fncb)
53
{
54
        GR_FNCALLBACKEVENT orig = ErrorFunc;
55
 
56
        ErrorFunc = fncb;
57
        return orig;
58
}
59
#endif /* NONETWORK*/
60
 
61
/*
62
 * Generate an error from a graphics function.
63
 * This creates a special event which describes the error.
64
 * Only one error event at a time can be saved for delivery to a client.
65
 * This is ok since there are usually lots of redundant errors generated
66
 * before the client can notice, errors occurs after the fact, and clients
67
 * can't do much about them except complain and die.  The error is saved
68
 * specially so that memory problems cannot occur.
69
 */
70
void GsError(GR_ERROR code, GR_ID id)
71
{
72
        GR_EVENT_ERROR  *ep;            /* event to describe error */
73
 
74
        EPRINTF("nano-X: GsError ");
75
        if(curfunc)
76
                EPRINTF("(%s) ", curfunc);
77
        EPRINTF(nxErrorStrings[code], id);
78
 
79
        /* if no clients, nothing to report*/
80
        if (!curclient)
81
                return;
82
 
83
        /* queue the error event regardless of GrSelectEvents*/
84
        ep = (GR_EVENT_ERROR *)GsAllocEvent(curclient);
85
        ep->type = GR_EVENT_TYPE_ERROR;
86
        ep->name[0] = 0;
87
        if(curfunc) {
88
                strncpy(ep->name, curfunc, sizeof(GR_FUNC_NAME));
89
                ep->name[sizeof(GR_FUNC_NAME)-1] = '\0';
90
        }
91
        ep->code = code;
92
        ep->id = id;
93
}
94
 
95
/*
96
 * Allocate an event to be passed back to the specified client.
97
 * The event is already chained onto the event queue, and only
98
 * needs filling out.  Returns NULL with an error generated if
99
 * the event cannot be allocated.
100
 */
101
GR_EVENT *GsAllocEvent(GR_CLIENT *client)
102
{
103
        GR_EVENT_LIST   *elp;           /* current element list */
104
        GR_CLIENT       *oldcurclient;  /* old current client */
105
 
106
        /*
107
         * Get a new event structure from the free list, or else
108
         * allocate it using malloc.
109
         */
110
        elp = eventfree;
111
        if (elp)
112
                eventfree = elp->next;
113
        else {
114
                elp = (GR_EVENT_LIST *) malloc(sizeof(GR_EVENT_LIST));
115
                if (elp == NULL) {
116
                        oldcurclient = curclient;
117
                        curclient = client;
118
                        GsError(GR_ERROR_MALLOC_FAILED, 0);
119
                        curclient = oldcurclient;
120
                        return NULL;
121
                }
122
        }
123
 
124
        /*
125
         * Add the event to the end of the event list.
126
         */
127
        if (client->eventhead)
128
                client->eventtail->next = elp;
129
        else
130
                client->eventhead = elp;
131
        client->eventtail = elp;
132
        elp->next = NULL;
133
        elp->event.type = GR_EVENT_TYPE_NONE;
134
 
135
        return &elp->event;
136
}
137
 
138
/*
139
 * Update mouse status and issue events on it if necessary.
140
 * This function doesn't block, but is normally only called when
141
 * there is known to be some data waiting to be read from the mouse.
142
 */
143
GR_BOOL GsCheckMouseEvent(void)
144
{
145
        GR_COORD        rootx;          /* latest mouse x position */
146
        GR_COORD        rooty;          /* latest mouse y position */
147
        int             newbuttons;     /* latest buttons */
148
        int             mousestatus;    /* latest mouse status */
149
 
150
        /* Read the latest mouse status: */
151
        mousestatus = GdReadMouse(&rootx, &rooty, &newbuttons);
152
        if(mousestatus < 0) {
153
                GsError(GR_ERROR_MOUSE_ERROR, 0);
154
                return FALSE;
155
        } else if(mousestatus) {        /* Deliver events as appropriate: */
156
                GsHandleMouseStatus(rootx, rooty, newbuttons);
157
 
158
                /* possibly reset portrait mode based on mouse position*/
159
                if (autoportrait)
160
                        GsSetPortraitModeFromXY(rootx, rooty);
161
                return TRUE;
162
        }
163
        return FALSE;
164
}
165
 
166
/*
167
 * Update keyboard status and issue events on it if necessary.
168
 * This function doesn't block, but is normally only called when
169
 * there is known to be some data waiting to be read from the keyboard.
170
 */
171
GR_BOOL GsCheckKeyboardEvent(void)
172
{
173
        MWKEY           mwkey;          /* latest character */
174
        MWKEYMOD        modifiers;      /* latest modifiers */
175
        MWSCANCODE      scancode;
176
        int             keystatus;      /* latest keyboard status */
177
 
178
        /* Read the latest keyboard status: */
179
        keystatus = GdReadKeyboard(&mwkey, &modifiers, &scancode);
180
 
181
        if(keystatus < 0) {
182
                if(keystatus == -2)     /* special case return code*/
183
                        GsTerminate();
184
                GsError(GR_ERROR_KEYBOARD_ERROR, 0);
185
                return FALSE;
186
        } else if(keystatus) {          /* Deliver events as appropriate: */
187
                switch (mwkey) {
188
                case MWKEY_QUIT:
189
                        GsTerminate();
190
                        /* no return*/
191
                case MWKEY_REDRAW:
192
                        GsRedrawScreen();
193
                        break;
194
                case MWKEY_PRINT:
195
                        if (keystatus == 1)
196
                                GdCaptureScreen("screen.bmp");
197
                        break;
198
                }
199
                GsDeliverKeyboardEvent(0,
200
                        (keystatus==1?
201
                        GR_EVENT_TYPE_KEY_DOWN: GR_EVENT_TYPE_KEY_UP),
202
                        mwkey, modifiers, scancode);
203
                return TRUE;
204
        }
205
        return FALSE;
206
}
207
 
208
/*
209
 * Handle all mouse events.  These are mouse enter, mouse exit, mouse
210
 * motion, mouse position, button down, and button up.  This also moves
211
 * the cursor to the new mouse position and changes it shape if needed.
212
 */
213
void GsHandleMouseStatus(GR_COORD newx, GR_COORD newy, int newbuttons)
214
{
215
        int      changebuttons; /* buttons that have changed */
216
        MWKEYMOD modifiers;     /* latest modifiers */
217
 
218
        GdGetModifierInfo(NULL, &modifiers); /* Read kbd modifiers */
219
 
220
        /*
221
         * First, if the mouse has moved, then position the cursor to the
222
         * new location, which will send mouse enter, mouse exit, focus in,
223
         * and focus out events if needed.  Check here for mouse motion and
224
         * mouse position events.  Flush the device queue to make sure the
225
         * new cursor location is quickly seen by the user.
226
         */
227
        if ((newx != cursorx) || (newy != cursory)) {
228
                GsResetScreenSaver();
229
                GrMoveCursor(newx, newy);
230
                GsDeliverMotionEvent(GR_EVENT_TYPE_MOUSE_MOTION,
231
                        newbuttons, modifiers);
232
                GsDeliverMotionEvent(GR_EVENT_TYPE_MOUSE_POSITION,
233
                        newbuttons, modifiers);
234
        }
235
 
236
        /*
237
         * Next, generate a button up event if any buttons have been released.
238
         */
239
        changebuttons = (curbuttons & ~newbuttons);
240
        if (changebuttons) {
241
                GsResetScreenSaver();
242
                GsDeliverButtonEvent(GR_EVENT_TYPE_BUTTON_UP,
243
                        newbuttons, changebuttons, modifiers);
244
        }
245
 
246
        /*
247
         * Finally, generate a button down event if any buttons have been
248
         * pressed.
249
         */
250
        changebuttons = (~curbuttons & newbuttons);
251
        if (changebuttons) {
252
                GsResetScreenSaver();
253
                GsDeliverButtonEvent(GR_EVENT_TYPE_BUTTON_DOWN,
254
                        newbuttons, changebuttons, modifiers);
255
        }
256
 
257
        curbuttons = newbuttons;
258
}
259
 
260
/*
261
 * Deliver a mouse button event to the clients which have selected for it.
262
 * Each client can only be delivered one instance of the event.  The window
263
 * the event is delivered for is either the smallest one containing the
264
 * mouse coordinates, or else one of its direct ancestors.  The lowest
265
 * window in that tree which has enabled for the event gets it.  This scan
266
 * is done independently for each client.  If a window with the correct
267
 * noprop mask is reached, or if no window selects for the event, then the
268
 * event is discarded for that client.  Special case: for the first client
269
 * that is enabled for both button down and button up events in a window,
270
 * then the pointer is implicitly grabbed by that window when a button is
271
 * pressed down in that window.  The grabbing remains until all buttons are
272
 * released.  While the pointer is grabbed, no other clients or windows can
273
 * receive button down or up events.
274
 */
275
void GsDeliverButtonEvent(GR_EVENT_TYPE type, int buttons, int changebuttons,
276
                        int modifiers)
277
{
278
        GR_EVENT_BUTTON *ep;            /* mouse button event */
279
        GR_WINDOW       *wp;            /* current window */
280
        GR_EVENT_CLIENT *ecp;           /* current event client */
281
        GR_CLIENT       *client;        /* current client */
282
        GR_WINDOW_ID    subwid;         /* subwindow id event is for */
283
        GR_EVENT_MASK   eventmask;      /* event mask */
284
        GR_EVENT_MASK   tempmask;       /* to get around compiler bug */
285
 
286
        eventmask = GR_EVENTMASK(type);
287
        if (eventmask == 0)
288
                return;
289
 
290
        /*
291
         * If the pointer is implicitly grabbed, then the only window
292
         * which can receive button events is that window.  Otherwise
293
         * the window the pointer is in gets the events.  Determine the
294
         * subwindow by seeing if it is a child of the grabbed button.
295
         */
296
        wp = mousewp;
297
        subwid = wp->id;
298
 
299
        if (grabbuttonwp) {
300
                while ((wp != rootwp) && (wp != grabbuttonwp))
301
                        wp = wp->parent;
302
#if 0
303
                if (wp != grabbuttonwp)
304
                        subwid = grabbuttonwp->id;
305
#endif
306
                wp = grabbuttonwp;
307
        }
308
 
309
        for (;;) {
310
                for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
311
                        if ((ecp->eventmask & eventmask) == 0)
312
                                continue;
313
 
314
                        client = ecp->client;
315
 
316
                        /*
317
                         * If this is a button down, the buttons are not
318
                         * yet grabbed, and this client is enabled for both
319
                         * button down and button up events, then implicitly
320
                         * grab the window for him.
321
                         */
322
                        if ((type == GR_EVENT_TYPE_BUTTON_DOWN)
323
                                && (grabbuttonwp == NULL))
324
                        {
325
                                tempmask = GR_EVENT_MASK_BUTTON_UP;
326
                                if (ecp->eventmask & tempmask) {
327
/*DPRINTF("nano-X: implicit grab on window %d\n", wp->id);*/
328
                                        grabbuttonwp = wp;
329
                                }
330
                        }
331
 
332
                        ep = (GR_EVENT_BUTTON *) GsAllocEvent(client);
333
                        if (ep == NULL)
334
                                continue;
335
 
336
                        ep->type = type;
337
                        ep->wid = wp->id;
338
                        ep->subwid = subwid;
339
                        ep->rootx = cursorx;
340
                        ep->rooty = cursory;
341
                        ep->x = cursorx - wp->x;
342
                        ep->y = cursory - wp->y;
343
                        ep->buttons = buttons;
344
                        ep->changebuttons = changebuttons;
345
                        ep->modifiers = modifiers;
346
                        ep->time = GsGetTickCount();
347
                }
348
 
349
                /*
350
                 * Events do not propagate if the window was grabbed.
351
                 * Also release the grab if the buttons are now all released,
352
                 * which can cause various events.
353
                 */
354
                if (grabbuttonwp) {
355
                        if (buttons == 0) {
356
                                grabbuttonwp = NULL;
357
                                GrMoveCursor(cursorx, cursory);
358
                        }
359
                        return;
360
                }
361
 
362
                if ((wp == rootwp) || (wp->nopropmask & eventmask))
363
                        return;
364
 
365
                wp = wp->parent;
366
        }
367
}
368
 
369
/*
370
 * Deliver a mouse motion event to the clients which have selected for it.
371
 * Each client can only be delivered one instance of the event.  The window
372
 * the event is delivered for is either the smallest one containing the
373
 * mouse coordinates, or else one of its direct ancestors.  The lowest
374
 * window in that tree which has enabled for the event gets it.  This scan
375
 * is done independently for each client.  If a window with the correct
376
 * noprop mask is reached, or if no window selects for the event, then the
377
 * event is discarded for that client.  Special case: If the event type is
378
 * GR_EVENT_TYPE_MOUSE_POSITION, then only the last such event is queued for
379
 * any single client to reduce events.  If the mouse is implicitly grabbed,
380
 * then only the grabbing window receives the events, and continues to do
381
 * so even if the mouse is currently outside of the grabbing window.
382
 */
383
void GsDeliverMotionEvent(GR_EVENT_TYPE type, int buttons, MWKEYMOD modifiers)
384
{
385
        GR_EVENT_MOUSE  *ep;            /* mouse motion event */
386
        GR_WINDOW       *wp;            /* current window */
387
        GR_EVENT_CLIENT *ecp;           /* current event client */
388
        GR_CLIENT       *client;        /* current client */
389
        GR_WINDOW_ID    subwid;         /* subwindow id event is for */
390
        GR_EVENT_MASK   eventmask;      /* event mask */
391
 
392
        eventmask = GR_EVENTMASK(type);
393
        if (eventmask == 0)
394
                return;
395
 
396
        wp = mousewp;
397
        subwid = wp->id;
398
 
399
        if (grabbuttonwp) {
400
                while ((wp != rootwp) && (wp != grabbuttonwp))
401
                        wp = wp->parent;
402
#if 0
403
                if (wp != grabbuttonwp)
404
                        subwid = grabbuttonwp->id;
405
#endif
406
                wp = grabbuttonwp;
407
        }
408
 
409
        for (;;) {
410
                for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
411
                        if ((ecp->eventmask & eventmask) == 0)
412
                                continue;
413
 
414
                        client = ecp->client;
415
 
416
                        /*
417
                         * If the event is for just the latest position,
418
                         * then search the event queue for an existing
419
                         * event of this type (if any), and free it.
420
                         */
421
                        if (type == GR_EVENT_TYPE_MOUSE_POSITION)
422
                                GsFreePositionEvent(client, wp->id, subwid);
423
 
424
                        ep = (GR_EVENT_MOUSE *) GsAllocEvent(client);
425
                        if (ep == NULL)
426
                                continue;
427
 
428
                        ep->type = type;
429
                        ep->wid = wp->id;
430
                        ep->subwid = subwid;
431
                        ep->rootx = cursorx;
432
                        ep->rooty = cursory;
433
                        ep->x = cursorx - wp->x;
434
                        ep->y = cursory - wp->y;
435
                        ep->buttons = buttons;
436
                        ep->modifiers = modifiers;
437
                }
438
 
439
                if ((wp == rootwp) || grabbuttonwp ||
440
                        (wp->nopropmask & eventmask))
441
                                return;
442
 
443
                wp = wp->parent;
444
        }
445
}
446
 
447
/*
448
 * Deliver a keyboard event to one of the clients which have selected for it.
449
 * Only the first client found gets the event (no duplicates are sent).  The
450
 * window the event is delivered to is either the smallest one containing
451
 * the mouse coordinates, or else one of its direct ancestors (if such a
452
 * window is a descendant of the focus window), or else just the focus window.
453
 * The lowest window in that tree which has enabled for the event gets it.
454
 * If a window with the correct noprop mask is reached, or if no window selects
455
 * for the event, then the event is discarded.
456
 */
457
void GsDeliverKeyboardEvent(GR_WINDOW_ID wid, GR_EVENT_TYPE type,
458
        GR_KEY keyvalue, GR_KEYMOD modifiers, GR_SCANCODE scancode)
459
{
460
        GR_EVENT_KEYSTROKE      *ep;            /* keystroke event */
461
        GR_WINDOW               *wp;            /* current window */
462
        GR_WINDOW               *tempwp;        /* temporary window pointer */
463
        GR_EVENT_CLIENT         *ecp;           /* current event client */
464
        GR_WINDOW_ID            subwid;         /* subwindow id event is for */
465
        GR_EVENT_MASK           eventmask;      /* event mask */
466
        GR_WINDOW               *kwp;
467
 
468
        eventmask = GR_EVENTMASK(type);
469
        if (eventmask == 0)
470
                return;
471
 
472
        GsResetScreenSaver();
473
 
474
        /* if window id passed, use it, otherwise focus window*/
475
        if (wid) {
476
                kwp = GsFindWindow(wid);
477
                if (!kwp)
478
                        return;
479
        } else
480
                kwp = focuswp;
481
        wp = mousewp;
482
        subwid = wp->id;
483
 
484
        /*
485
         * See if the actual window the pointer is in is a descendant of
486
         * the focus window.  If not, then ignore it, and force the input
487
         * into the focus window itself.
488
         */
489
        tempwp = wp;
490
        while ((tempwp != kwp) && (tempwp != rootwp))
491
                tempwp = tempwp->parent;
492
 
493
        if (tempwp != kwp) {
494
                wp = kwp;
495
                subwid = wp->id;
496
        }
497
 
498
        /*
499
         * Now walk upwards looking for the first window which will accept
500
         * the keyboard event.  However, do not go beyond the focus window,
501
         * and only give the event to one client.
502
         */
503
        for (;;) {
504
                for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
505
                        if ((ecp->eventmask & eventmask) == 0)
506
                                continue;
507
 
508
                        ep = (GR_EVENT_KEYSTROKE *) GsAllocEvent(ecp->client);
509
                        if (ep == NULL)
510
                                return;
511
 
512
                        ep->type = type;
513
                        ep->wid = wp->id;
514
                        ep->subwid = subwid;
515
                        ep->rootx = cursorx;
516
                        ep->rooty = cursory;
517
                        ep->x = cursorx - wp->x;
518
                        ep->y = cursory - wp->y;
519
                        ep->buttons = curbuttons;
520
                        ep->modifiers = modifiers;
521
                        ep->ch = keyvalue;
522
                        ep->scancode = scancode;
523
                        return;                 /* only one client gets it */
524
                }
525
 
526
                if ((wp == rootwp) || (wp == kwp) ||
527
                        (wp->nopropmask & eventmask))
528
                                return;
529
 
530
                wp = wp->parent;
531
        }
532
}
533
 
534
/*
535
 * Try to deliver a exposure event to the clients which have selected for it.
536
 * This does not send exposure events for unmapped or input-only windows.
537
 * Exposure events do not propagate upwards.
538
 */
539
void
540
GsDeliverExposureEvent(GR_WINDOW *wp, GR_COORD x, GR_COORD y,
541
        GR_SIZE width, GR_SIZE height)
542
{
543
        GR_EVENT_EXPOSURE       *ep;            /* exposure event */
544
        GR_EVENT_CLIENT         *ecp;           /* current event client */
545
 
546
        if (wp->unmapcount || !wp->output)
547
                return;
548
 
549
        for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
550
                if ((ecp->eventmask & GR_EVENT_MASK_EXPOSURE) == 0)
551
                        continue;
552
 
553
                GsFreeExposureEvent(ecp->client, wp->id, x, y, width, height);
554
 
555
                ep = (GR_EVENT_EXPOSURE *) GsAllocEvent(ecp->client);
556
                if (ep == NULL)
557
                        continue;
558
 
559
                ep->type = GR_EVENT_TYPE_EXPOSURE;
560
                ep->wid = wp->id;
561
                ep->x = x;
562
                ep->y = y;
563
                ep->width = width;
564
                ep->height = height;
565
        }
566
}
567
 
568
/*
569
 * Search for an enclosed expose event in the specified client's
570
 * event queue, and remove it.  This is used to prevent multiple expose
571
 * events from being delivered, thus providing a more pleasing visual
572
 * redraw effect than if the events were all sent.
573
 */
574
void
575
GsFreeExposureEvent(GR_CLIENT *client, GR_WINDOW_ID wid, GR_COORD x,
576
        GR_COORD y, GR_SIZE width, GR_SIZE height)
577
{
578
        GR_EVENT_LIST   *elp;           /* current element list */
579
        GR_EVENT_LIST   *prevelp;       /* previous element list */
580
 
581
        prevelp = NULL;
582
        for (elp = client->eventhead; elp; prevelp = elp, elp = elp->next) {
583
                if (elp->event.type != GR_EVENT_TYPE_EXPOSURE ||
584
                    elp->event.exposure.wid != wid)
585
                        continue;
586
                if (elp->event.exposure.x < x || elp->event.exposure.y < y ||
587
                    elp->event.exposure.x+elp->event.exposure.width > x+width ||
588
                    elp->event.exposure.y+elp->event.exposure.height > y+height)
589
                        continue;
590
 
591
                /*
592
                 * Found one, remove it and put it back on the free list.
593
                 */
594
                if (prevelp)
595
                        prevelp->next = elp->next;
596
                else
597
                        client->eventhead = elp->next;
598
                if (client->eventtail == elp)
599
                        client->eventtail = prevelp;
600
 
601
                elp->next = eventfree;
602
                eventfree = elp;
603
                return;
604
        }
605
}
606
 
607
/*
608
 * Try to deliver an update event to the clients which have selected for it.
609
 */
610
void GsDeliverUpdateEvent(GR_WINDOW *wp, GR_UPDATE_TYPE utype, GR_COORD x,
611
                        GR_COORD y, GR_SIZE width, GR_SIZE height)
612
{
613
        GR_EVENT_MASK           cmask = GR_EVENT_MASK_UPDATE;
614
        GR_EVENT_UPDATE         *ep;            /* update event */
615
        GR_EVENT_CLIENT         *ecp;           /* current event client */
616
        GR_WINDOW_ID            id = wp->id;
617
        int                     lcount = 0;
618
 
619
        /* adjust reported x,y to be parent-relative*/
620
        if (wp->parent) {
621
                x -= wp->parent->x;
622
                y -= wp->parent->y;
623
        }
624
 
625
update_again:
626
        for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
627
                if ((ecp->eventmask & cmask) == 0)
628
                        continue;
629
 
630
                ep = (GR_EVENT_UPDATE *) GsAllocEvent(ecp->client);
631
                if (ep == NULL)
632
                        continue;
633
 
634
                ep->type = lcount?
635
                        GR_EVENT_TYPE_CHLD_UPDATE: GR_EVENT_TYPE_UPDATE;
636
                ep->utype = utype;
637
                ep->wid = wp->id;       /* GrSelectEvents window id*/
638
                ep->subwid = id;        /* update window id*/
639
                ep->x = x;
640
                ep->y = y;
641
                ep->width = width;
642
                ep->height = height;
643
        }
644
 
645
        /* If we are currently checking the window updated, go back and
646
         * check its parent too */
647
        if (!lcount++) {
648
                wp = wp->parent;
649
                /* check for NULL on root window id*/
650
                if (wp == NULL)
651
                        return;
652
                cmask = GR_EVENT_MASK_CHLD_UPDATE;
653
                goto update_again;
654
        }
655
}
656
 
657
/*
658
 * Try to deliver a general event such as focus in, focus out, mouse enter,
659
 * or mouse exit to the clients which have selected for it.  These events
660
 * only have the window id as data, and do not propagate upwards.
661
 */
662
void GsDeliverGeneralEvent(GR_WINDOW *wp, GR_EVENT_TYPE type, GR_WINDOW *other)
663
{
664
        GR_EVENT_GENERAL        *gp;            /* general event */
665
        GR_EVENT_CLIENT         *ecp;           /* current event client */
666
        GR_EVENT_MASK           eventmask;      /* event mask */
667
 
668
        eventmask = GR_EVENTMASK(type);
669
        if (eventmask == 0)
670
                return;
671
 
672
        for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
673
                if ((ecp->eventmask & eventmask) == 0)
674
                        continue;
675
 
676
                gp = (GR_EVENT_GENERAL *) GsAllocEvent(ecp->client);
677
                if (gp == NULL)
678
                        continue;
679
 
680
                gp->type = type;
681
                gp->wid = wp->id;
682
                if (other)
683
                        gp->otherid = other->id;
684
                else gp->otherid = 0;
685
        }
686
}
687
 
688
/*
689
 * Deliver a portrait mode changed event to all windows which
690
 * have selected for it.
691
 */
692
void GsDeliverPortraitChangedEvent(void)
693
{
694
        GR_WINDOW               *wp;
695
        GR_EVENT_GENERAL        *gp;
696
        GR_EVENT_CLIENT         *ecp;
697
 
698
        for (wp=listwp; wp; wp=wp->next) {
699
                for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
700
                        if ((ecp->eventmask & GR_EVENT_MASK_PORTRAIT_CHANGED) == 0)
701
                                continue;
702
 
703
                        gp = (GR_EVENT_GENERAL *) GsAllocEvent(ecp->client);
704
                        if (gp == NULL)
705
                                continue;
706
 
707
                        gp->type = GR_EVENT_TYPE_PORTRAIT_CHANGED;
708
                        gp->wid = wp->id;
709
                        gp->otherid = 0;
710
                }
711
        }
712
}
713
 
714
/*
715
 * Deliver a Screen Saver event. There is only one parameter- activate the
716
 * screen saver or deactivate it. We only deliver it to the root window,
717
 * but we do send it to every client which has selected for it (because the
718
 * program which starts the screen saver on an activate event might not also
719
 * be the screen saver program which wants to catch the deactivate event).
720
 */
721
void GsDeliverScreenSaverEvent(GR_BOOL activate)
722
{
723
        GR_EVENT_SCREENSAVER    *gp;            /* screensaver event */
724
        GR_EVENT_CLIENT         *ecp;           /* current event client */
725
 
726
        for (ecp = rootwp->eventclients; ecp; ecp = ecp->next) {
727
                if ((ecp->eventmask & GR_EVENT_MASK_SCREENSAVER) == 0)
728
                        continue;
729
 
730
                gp = (GR_EVENT_SCREENSAVER *) GsAllocEvent(ecp->client);
731
                if (gp == NULL)
732
                        continue;
733
 
734
                gp->type = GR_EVENT_TYPE_SCREENSAVER;
735
                gp->activate = activate;
736
        }
737
}
738
 
739
/*
740
 * Deliver a client data request event. Delivered to the clients who have
741
 * selected for this event on the specified window only.
742
 */
743
void
744
GsDeliverClientDataReqEvent(GR_WINDOW_ID wid, GR_WINDOW_ID rid,
745
                        GR_SERIALNO serial, GR_MIMETYPE mimetype)
746
{
747
        GR_EVENT_CLIENT_DATA_REQ *gp;           /* client data request event */
748
        GR_EVENT_CLIENT         *ecp;           /* current event client */
749
        GR_WINDOW *wp;
750
 
751
        if(!(wp = GsFindWindow(wid))) return;
752
 
753
        for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
754
                if ((ecp->eventmask & GR_EVENT_MASK_CLIENT_DATA_REQ) == 0)
755
                        continue;
756
 
757
                gp = (GR_EVENT_CLIENT_DATA_REQ *) GsAllocEvent(ecp->client);
758
                if (gp == NULL)
759
                        continue;
760
 
761
                gp->type = GR_EVENT_TYPE_CLIENT_DATA_REQ;
762
                gp->wid = wid;
763
                gp->rid = rid;
764
                gp->serial = serial;
765
                gp->mimetype = mimetype;
766
                continue;
767
        }
768
}
769
 
770
/*
771
 * Deliver a client data event. Delivered to the clients who have selected for
772
 * this event on the specified window only.
773
 */
774
void
775
GsDeliverClientDataEvent(GR_WINDOW_ID wid, GR_WINDOW_ID rid,
776
        GR_SERIALNO serial, GR_LENGTH len, GR_LENGTH thislen, void *data)
777
{
778
        GR_EVENT_CLIENT_DATA *gp;               /* client data request event */
779
        GR_EVENT_CLIENT         *ecp;           /* current event client */
780
        GR_WINDOW *wp;
781
 
782
        if(!(wp = GsFindWindow(wid))) return;
783
 
784
        for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
785
                if ((ecp->eventmask & GR_EVENT_MASK_CLIENT_DATA) == 0)
786
                        continue;
787
 
788
                gp = (GR_EVENT_CLIENT_DATA *) GsAllocEvent(ecp->client);
789
                if (gp == NULL)
790
                        continue;
791
 
792
                gp->type = GR_EVENT_TYPE_CLIENT_DATA;
793
                gp->wid = wid;
794
                gp->rid = rid;
795
                gp->serial = serial;
796
                gp->len = len;
797
                gp->datalen = thislen;
798
                if(!(gp->data = malloc(thislen))) {
799
                        GsError(GR_ERROR_MALLOC_FAILED, wid);
800
                        return;
801
                }
802
                memcpy(gp->data, data, thislen);
803
                continue;
804
        }
805
}
806
 
807
/*
808
 * Search for a matching mouse position event in the specified client's
809
 * event queue, and remove it.  This is used to prevent multiple position
810
 * events from being delivered, thus providing a more efficient rubber-
811
 * banding effect than if the mouse motion events were all sent.
812
 */
813
void
814
GsFreePositionEvent(GR_CLIENT *client, GR_WINDOW_ID wid, GR_WINDOW_ID subwid)
815
{
816
        GR_EVENT_LIST   *elp;           /* current element list */
817
        GR_EVENT_LIST   *prevelp;       /* previous element list */
818
 
819
        prevelp = NULL;
820
        for (elp = client->eventhead; elp; prevelp = elp, elp = elp->next) {
821
                if (elp->event.type != GR_EVENT_TYPE_MOUSE_POSITION)
822
                        continue;
823
                if (elp->event.mouse.wid != wid)
824
                        continue;
825
                if (elp->event.mouse.subwid != subwid)
826
                        continue;
827
 
828
                /*
829
                 * Found one, remove it and put it back on the free list.
830
                 */
831
                if (prevelp)
832
                        prevelp->next = elp->next;
833
                else
834
                        client->eventhead = elp->next;
835
                if (client->eventtail == elp)
836
                        client->eventtail = prevelp;
837
 
838
                elp->next = eventfree;
839
                eventfree = elp;
840
                return;
841
        }
842
}
843
 
844
/*
845
 * Deliver a "selection owner changed" event to all windows which have
846
 * selected for it. We deliver this event to all clients which have selected
847
 * to receive GR_EVENT_TYPE_SELECTION_CHANGED events for the window of the
848
 * _previous_ selection owner.
849
 */
850
void GsDeliverSelectionChangedEvent(GR_WINDOW_ID old_owner,
851
                                        GR_WINDOW_ID new_owner)
852
{
853
        GR_EVENT_SELECTION_CHANGED *gp;         /* selection changed event */
854
        GR_EVENT_CLIENT         *ecp;           /* current event client */
855
        GR_WINDOW *wp;
856
 
857
        if(!(wp = GsFindWindow(old_owner))) return;
858
 
859
        for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
860
                if ((ecp->eventmask & GR_EVENT_MASK_SELECTION_CHANGED) == 0)
861
                        continue;
862
 
863
                fprintf(stderr, "Delivering a selection changed event\n");
864
                gp = (GR_EVENT_SELECTION_CHANGED *) GsAllocEvent(ecp->client);
865
                if (gp == NULL)
866
                        continue;
867
 
868
                gp->type = GR_EVENT_TYPE_SELECTION_CHANGED;
869
                gp->new_owner = new_owner;
870
        }
871
}
872
 
873
void GsDeliverTimerEvent (GR_CLIENT *client, GR_WINDOW_ID wid, GR_TIMER_ID tid)
874
{
875
    GR_EVENT_TIMER    *event;           /* general event */
876
    GR_EVENT_CLIENT   *ecp;             /* current event client */
877
    GR_WINDOW         *wp;              /* current window */
878
 
879
    if ((wp = GsFindWindow (wid)) == NULL)
880
    {
881
        return;
882
    }
883
 
884
    for (ecp = wp->eventclients; ecp != NULL; ecp = ecp->next)
885
    {
886
        if ((ecp->client == client) && ((ecp->eventmask & GR_EVENT_MASK_TIMER) != 0))
887
        {
888
            event = (GR_EVENT_TIMER*) GsAllocEvent (client);
889
            if (event == NULL)
890
            {
891
                break;
892
            }
893
 
894
            event->type = GR_EVENT_TYPE_TIMER;
895
            event->wid  = wid;
896
            event->tid  = tid;
897
        }
898
    }
899
}
900
 

powered by: WebSVN 2.1.0

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