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

Subversion Repositories or1k

[/] [or1k/] [tags/] [MW_0_8_9PRE7/] [mw/] [src/] [nanox/] [srvevent.c] - Blame information for rev 1765

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

powered by: WebSVN 2.1.0

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