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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkPointer.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkPointer.c --
3
 *
4
 *      This file contains functions for emulating the X server
5
 *      pointer and grab state machine.  This file is used by the
6
 *      Mac and Windows platforms to generate appropriate enter/leave
7
 *      events, and to update the global grab window information.
8
 *
9
 * Copyright (c) 1996 by Sun Microsystems, Inc.
10
 *
11
 * See the file "license.terms" for information on usage and redistribution
12
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
 *
14
 * RCS: @(#) $Id: tkPointer.c,v 1.1.1.1 2002-01-16 10:25:52 markom Exp $
15
 */
16
 
17
#include "tkInt.h"
18
 
19
#ifdef MAC_TCL
20
#define Cursor XCursor
21
#endif
22
 
23
/*
24
 * Mask that selects any of the state bits corresponding to buttons,
25
 * plus masks that select individual buttons' bits:
26
 */
27
 
28
#define ALL_BUTTONS \
29
        (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
30
static unsigned int buttonMasks[] = {
31
    Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
32
};
33
#define ButtonMask(b) (buttonMasks[(b)-Button1])
34
 
35
/*
36
 * Declarations of static variables used in the pointer module.
37
 */
38
 
39
static TkWindow *cursorWinPtr = NULL;   /* Window that is currently
40
                                         * controlling the global cursor. */
41
static TkWindow *grabWinPtr = NULL;     /* Window that defines the top of the
42
                                         * grab tree in a global grab. */
43
static XPoint lastPos = { 0, 0};  /* Last reported mouse position. */
44
static int lastState = 0;                /* Last known state flags. */
45
static TkWindow *lastWinPtr = NULL;     /* Last reported mouse window. */
46
static TkWindow *restrictWinPtr = NULL; /* Window to which all mouse events
47
                                         * will be reported. */
48
 
49
/*
50
 * Forward declarations of procedures used in this file.
51
 */
52
 
53
static int              GenerateEnterLeave _ANSI_ARGS_((TkWindow *winPtr,
54
                            int x, int y, int state));
55
static void             InitializeEvent _ANSI_ARGS_((XEvent* eventPtr,
56
                            TkWindow *winPtr, int type, int x, int y,
57
                            int state, int detail));
58
static void             UpdateCursor _ANSI_ARGS_((TkWindow *winPtr));
59
 
60
/*
61
 *----------------------------------------------------------------------
62
 *
63
 * InitializeEvent --
64
 *
65
 *      Initializes the common fields for several X events.
66
 *
67
 * Results:
68
 *      None.
69
 *
70
 * Side effects:
71
 *      Fills in the specified event structure.
72
 *
73
 *----------------------------------------------------------------------
74
 */
75
 
76
static void
77
InitializeEvent(eventPtr, winPtr, type, x, y, state, detail)
78
    XEvent* eventPtr;           /* Event structure to initialize. */
79
    TkWindow *winPtr;           /* Window to make event relative to. */
80
    int type;                   /* Message type. */
81
    int x, y;                   /* Root coords of event. */
82
    int state;                  /* State flags. */
83
    int detail;                 /* Detail value. */
84
{
85
    eventPtr->type = type;
86
    eventPtr->xany.serial = LastKnownRequestProcessed(winPtr->display);
87
    eventPtr->xany.send_event = False;
88
    eventPtr->xany.display = winPtr->display;
89
 
90
    eventPtr->xcrossing.root = RootWindow(winPtr->display, winPtr->screenNum);
91
    eventPtr->xcrossing.time = TkpGetMS();
92
    eventPtr->xcrossing.x_root = x;
93
    eventPtr->xcrossing.y_root = y;
94
 
95
    switch (type) {
96
        case EnterNotify:
97
        case LeaveNotify:
98
            eventPtr->xcrossing.mode = NotifyNormal;
99
            eventPtr->xcrossing.state = state;
100
            eventPtr->xcrossing.detail = detail;
101
            eventPtr->xcrossing.focus = False;
102
            break;
103
        case MotionNotify:
104
            eventPtr->xmotion.state = state;
105
            eventPtr->xmotion.is_hint = detail;
106
            break;
107
        case ButtonPress:
108
        case ButtonRelease:
109
            eventPtr->xbutton.state = state;
110
            eventPtr->xbutton.button = detail;
111
            break;
112
    }
113
    TkChangeEventWindow(eventPtr, winPtr);
114
}
115
 
116
/*
117
 *----------------------------------------------------------------------
118
 *
119
 * GenerateEnterLeave --
120
 *
121
 *      Update the current mouse window and position, and generate
122
 *      any enter/leave events that are needed.
123
 *
124
 * Results:
125
 *      Returns 1 if enter/leave events were generated.
126
 *
127
 * Side effects:
128
 *      May insert events into the Tk event queue.
129
 *
130
 *----------------------------------------------------------------------
131
 */
132
 
133
static int
134
GenerateEnterLeave(winPtr, x, y, state)
135
    TkWindow *winPtr;           /* Current Tk window (or NULL). */
136
    int x,y;                    /* Current mouse position in root coords. */
137
    int state;                  /* State flags. */
138
{
139
    int crossed = 0;             /* 1 if mouse crossed a window boundary */
140
 
141
    if (winPtr != lastWinPtr) {
142
        if (restrictWinPtr) {
143
            int newPos, oldPos;
144
 
145
            newPos = TkPositionInTree(winPtr, restrictWinPtr);
146
            oldPos = TkPositionInTree(lastWinPtr, restrictWinPtr);
147
 
148
            /*
149
             * Check if the mouse crossed into or out of the restrict
150
             * window.  If so, we need to generate an Enter or Leave event.
151
             */
152
 
153
            if ((newPos != oldPos) && ((newPos == TK_GRAB_IN_TREE)
154
                    || (oldPos == TK_GRAB_IN_TREE))) {
155
                XEvent event;
156
                int type, detail;
157
 
158
                if (newPos == TK_GRAB_IN_TREE) {
159
                    type = EnterNotify;
160
                } else {
161
                    type = LeaveNotify;
162
                }
163
                if ((oldPos == TK_GRAB_ANCESTOR)
164
                        || (newPos == TK_GRAB_ANCESTOR)) {
165
                    detail = NotifyAncestor;
166
                } else {
167
                    detail = NotifyVirtual;
168
                }
169
                InitializeEvent(&event, restrictWinPtr, type, x, y,
170
                        state, detail);
171
                Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
172
            }
173
 
174
        } else {
175
            TkWindow *targetPtr;
176
 
177
            if ((lastWinPtr == NULL)
178
                || (lastWinPtr->window == None)) {
179
                targetPtr = winPtr;
180
            } else {
181
                targetPtr = lastWinPtr;
182
            }
183
 
184
            if (targetPtr && (targetPtr->window != None)) {
185
                XEvent event;
186
 
187
                /*
188
                 * Generate appropriate Enter/Leave events.
189
                 */
190
 
191
                InitializeEvent(&event, targetPtr, LeaveNotify, x, y, state,
192
                        NotifyNormal);
193
 
194
                TkInOutEvents(&event, lastWinPtr, winPtr, LeaveNotify,
195
                        EnterNotify, TCL_QUEUE_TAIL);
196
                crossed = 1;
197
            }
198
        }
199
        lastWinPtr = winPtr;
200
    }
201
 
202
    return crossed;
203
}
204
 
205
/*
206
 *----------------------------------------------------------------------
207
 *
208
 * Tk_UpdatePointer --
209
 *
210
 *      This function updates the pointer state machine given an
211
 *      the current window, position and modifier state.
212
 *
213
 * Results:
214
 *      None.
215
 *
216
 * Side effects:
217
 *      May queue new events and update the grab state.
218
 *
219
 *----------------------------------------------------------------------
220
 */
221
 
222
void
223
Tk_UpdatePointer(tkwin, x, y, state)
224
    Tk_Window tkwin;            /* Window to which pointer event
225
                                 * is reported. May be NULL. */
226
    int x, y;                   /* Pointer location in root coords. */
227
    int state;                  /* Modifier state mask. */
228
{
229
    TkWindow *winPtr = (TkWindow *)tkwin;
230
    TkWindow *targetWinPtr;
231
    XPoint pos;
232
    XEvent event;
233
    int changes = (state ^ lastState) & ALL_BUTTONS;
234
    int type, b, mask;
235
 
236
    pos.x = x;
237
    pos.y = y;
238
 
239
    /*
240
     * Use the current keyboard state, but the old mouse button
241
     * state since we haven't generated the button events yet.
242
     */
243
 
244
    lastState = (state & ~ALL_BUTTONS) | (lastState & ALL_BUTTONS);
245
 
246
    /*
247
     * Generate Enter/Leave events.  If the pointer has crossed window
248
     * boundaries, update the current mouse position so we don't generate
249
     * redundant motion events.
250
     */
251
 
252
    if (GenerateEnterLeave(winPtr, x, y, lastState)) {
253
        lastPos = pos;
254
    }
255
 
256
    /*
257
     * Generate ButtonPress/ButtonRelease events based on the differences
258
     * between the current button state and the last known button state.
259
     */
260
 
261
    for (b = Button1; b <= Button3; b++) {
262
        mask = ButtonMask(b);
263
        if (changes & mask) {
264
            if (state & mask) {
265
                type = ButtonPress;
266
 
267
                /*
268
                 * ButtonPress - Set restrict window if we aren't grabbed, or
269
                 * if this is the first button down.
270
                 */
271
 
272
                if (!restrictWinPtr) {
273
                    if (!grabWinPtr) {
274
 
275
                        /*
276
                         * Mouse is not grabbed, so set a button grab.
277
                         */
278
 
279
                        restrictWinPtr = winPtr;
280
                        TkpSetCapture(restrictWinPtr);
281
 
282
                    } else if ((lastState & ALL_BUTTONS) == 0) {
283
 
284
                        /*
285
                         * Mouse is in a non-button grab, so ensure
286
                         * the button grab is inside the grab tree.
287
                         */
288
 
289
                        if (TkPositionInTree(winPtr, grabWinPtr)
290
                                == TK_GRAB_IN_TREE) {
291
                            restrictWinPtr = winPtr;
292
                        } else {
293
                            restrictWinPtr = grabWinPtr;
294
                        }
295
                        TkpSetCapture(restrictWinPtr);
296
                    }
297
                }
298
 
299
            } else {
300
                type = ButtonRelease;
301
 
302
                /*
303
                 * ButtonRelease - Release the mouse capture and clear the
304
                 * restrict window when the last button is released and we
305
                 * aren't in a global grab.
306
                 */
307
 
308
                if ((lastState & ALL_BUTTONS) == mask) {
309
                    if (!grabWinPtr) {
310
                        TkpSetCapture(NULL);
311
                    }
312
                }
313
 
314
                /*
315
                 * If we are releasing a restrict window, then we need
316
                 * to send the button event followed by mouse motion from
317
                 * the restrict window to the current mouse position.
318
                 */
319
 
320
                if (restrictWinPtr) {
321
                    InitializeEvent(&event, restrictWinPtr, type, x, y,
322
                            lastState, b);
323
                    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
324
                    lastState &= ~mask;
325
                    lastWinPtr = restrictWinPtr;
326
                    restrictWinPtr = NULL;
327
 
328
                    GenerateEnterLeave(winPtr, x, y, lastState);
329
                    lastPos = pos;
330
                    continue;
331
                }
332
            }
333
 
334
            /*
335
             * If a restrict window is set, make sure the pointer event
336
             * is reported relative to that window.  Otherwise, if a
337
             * global grab is in effect then events outside of windows
338
             * managed by Tk should be reported to the grab window.
339
             */
340
 
341
            if (restrictWinPtr) {
342
                targetWinPtr = restrictWinPtr;
343
            } else if (grabWinPtr && !winPtr) {
344
                targetWinPtr = grabWinPtr;
345
            } else {
346
                targetWinPtr = winPtr;
347
            }
348
 
349
            /*
350
             * If we still have a target window, send the event.
351
             */
352
 
353
            if (winPtr != NULL) {
354
                InitializeEvent(&event, targetWinPtr, type, x, y,
355
                        lastState, b);
356
                Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
357
            }
358
 
359
            /*
360
             * Update the state for the next iteration.
361
             */
362
 
363
            lastState = (type == ButtonPress)
364
                ? (lastState | mask) : (lastState & ~mask);
365
            lastPos = pos;
366
        }
367
    }
368
 
369
    /*
370
     * Make sure the cursor window is up to date.
371
     */
372
 
373
    if (restrictWinPtr) {
374
        targetWinPtr = restrictWinPtr;
375
    } else if (grabWinPtr) {
376
        targetWinPtr = (TkPositionInTree(winPtr, grabWinPtr)
377
                == TK_GRAB_IN_TREE) ? winPtr : grabWinPtr;
378
    } else {
379
        targetWinPtr = winPtr;
380
    }
381
    UpdateCursor(targetWinPtr);
382
 
383
    /*
384
     * If no other events caused the position to be updated,
385
     * generate a motion event.
386
     */
387
 
388
    if (lastPos.x != pos.x || lastPos.y != pos.y) {
389
        if (restrictWinPtr) {
390
            targetWinPtr = restrictWinPtr;
391
        } else if (grabWinPtr && !winPtr) {
392
            targetWinPtr = grabWinPtr;
393
        }
394
 
395
        if (targetWinPtr != NULL) {
396
            InitializeEvent(&event, targetWinPtr, MotionNotify, x, y,
397
                    lastState, NotifyNormal);
398
            Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
399
        }
400
        lastPos = pos;
401
    }
402
}
403
 
404
/*
405
 *----------------------------------------------------------------------
406
 *
407
 * XGrabPointer --
408
 *
409
 *      Capture the mouse so event are reported outside of toplevels.
410
 *      Note that this is a very limited implementation that only
411
 *      supports GrabModeAsync and owner_events True.
412
 *
413
 * Results:
414
 *      Always returns GrabSuccess.
415
 *
416
 * Side effects:
417
 *      Turns on mouse capture, sets the global grab pointer, and
418
 *      clears any window restrictions.
419
 *
420
 *----------------------------------------------------------------------
421
 */
422
 
423
int
424
XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode,
425
        keyboard_mode, confine_to, cursor, time)
426
    Display* display;
427
    Window grab_window;
428
    Bool owner_events;
429
    unsigned int event_mask;
430
    int pointer_mode;
431
    int keyboard_mode;
432
    Window confine_to;
433
    Cursor cursor;
434
    Time time;
435
{
436
    display->request++;
437
    grabWinPtr = (TkWindow *) Tk_IdToWindow(display, grab_window);
438
    restrictWinPtr = NULL;
439
    TkpSetCapture(grabWinPtr);
440
    if (TkPositionInTree(lastWinPtr, grabWinPtr) != TK_GRAB_IN_TREE) {
441
        UpdateCursor(grabWinPtr);
442
    }
443
    return GrabSuccess;
444
}
445
 
446
/*
447
 *----------------------------------------------------------------------
448
 *
449
 * XUngrabPointer --
450
 *
451
 *      Release the current grab.
452
 *
453
 * Results:
454
 *      None.
455
 *
456
 * Side effects:
457
 *      Releases the mouse capture.
458
 *
459
 *----------------------------------------------------------------------
460
 */
461
 
462
void
463
XUngrabPointer(display, time)
464
    Display* display;
465
    Time time;
466
{
467
    display->request++;
468
    grabWinPtr = NULL;
469
    restrictWinPtr = NULL;
470
    TkpSetCapture(NULL);
471
    UpdateCursor(lastWinPtr);
472
}
473
 
474
/*
475
 *----------------------------------------------------------------------
476
 *
477
 * TkPointerDeadWindow --
478
 *
479
 *      Clean up pointer module state when a window is destroyed.
480
 *
481
 * Results:
482
 *      None.
483
 *
484
 * Side effects:
485
 *      May release the current capture window.
486
 *
487
 *----------------------------------------------------------------------
488
 */
489
 
490
void
491
TkPointerDeadWindow(winPtr)
492
    TkWindow *winPtr;
493
{
494
    if (winPtr == lastWinPtr) {
495
        lastWinPtr = NULL;
496
    }
497
    if (winPtr == grabWinPtr) {
498
        grabWinPtr = NULL;
499
    }
500
    if (winPtr == restrictWinPtr) {
501
        restrictWinPtr = NULL;
502
    }
503
    if (!(restrictWinPtr || grabWinPtr)) {
504
        TkpSetCapture(NULL);
505
    }
506
}
507
 
508
/*
509
 *----------------------------------------------------------------------
510
 *
511
 * UpdateCursor --
512
 *
513
 *      Set the windows global cursor to the cursor associated with
514
 *      the given Tk window.
515
 *
516
 * Results:
517
 *      None.
518
 *
519
 * Side effects:
520
 *      Changes the mouse cursor.
521
 *
522
 *----------------------------------------------------------------------
523
 */
524
 
525
static void
526
UpdateCursor(winPtr)
527
    TkWindow *winPtr;
528
{
529
    Cursor cursor = None;
530
 
531
    /*
532
     * A window inherits its cursor from its parent if it doesn't
533
     * have one of its own.  Top level windows inherit the default
534
     * cursor.
535
     */
536
 
537
    cursorWinPtr = winPtr;
538
    while (winPtr != NULL) {
539
        if (winPtr->atts.cursor != None) {
540
            cursor = winPtr->atts.cursor;
541
            break;
542
        } else if (winPtr->flags & TK_TOP_LEVEL) {
543
            break;
544
        }
545
        winPtr = winPtr->parentPtr;
546
    }
547
    TkpSetCursor((TkpCursor) cursor);
548
}
549
 
550
/*
551
 *----------------------------------------------------------------------
552
 *
553
 * XDefineCursor --
554
 *
555
 *      This function is called to update the cursor on a window.
556
 *      Since the mouse might be in the specified window, we need to
557
 *      check the specified window against the current mouse position
558
 *      and grab state.
559
 *
560
 * Results:
561
 *      None.
562
 *
563
 * Side effects:
564
 *      May update the cursor.
565
 *
566
 *----------------------------------------------------------------------
567
 */
568
 
569
void
570
XDefineCursor(display, w, cursor)
571
    Display* display;
572
    Window w;
573
    Cursor cursor;
574
{
575
    TkWindow *winPtr = (TkWindow *)Tk_IdToWindow(display, w);
576
 
577
    if (cursorWinPtr == winPtr) {
578
        UpdateCursor(winPtr);
579
    }
580
    display->request++;
581
}
582
 
583
/*
584
 *----------------------------------------------------------------------
585
 *
586
 * TkGenerateActivateEvents --
587
 *
588
 *      This function is called by the Mac and Windows window manager
589
 *      routines when a toplevel window is activated or deactivated.
590
 *      Activate/Deactivate events will be sent to every subwindow of
591
 *      the toplevel followed by a FocusIn/FocusOut message.
592
 *
593
 * Results:
594
 *      None.
595
 *
596
 * Side effects:
597
 *      Generates X events.
598
 *
599
 *----------------------------------------------------------------------
600
 */
601
 
602
void
603
TkGenerateActivateEvents(winPtr, active)
604
    TkWindow *winPtr;           /* Toplevel to activate. */
605
    int active;                 /* Non-zero if the window is being
606
                                 * activated, else 0.*/
607
{
608
    XEvent event;
609
 
610
    /*
611
     * Generate Activate and Deactivate events.  This event
612
     * is sent to every subwindow in a toplevel window.
613
     */
614
 
615
    event.xany.serial = winPtr->display->request++;
616
    event.xany.send_event = False;
617
    event.xany.display = winPtr->display;
618
    event.xany.window = winPtr->window;
619
 
620
    event.xany.type = active ? ActivateNotify : DeactivateNotify;
621
    TkQueueEventForAllChildren(winPtr, &event);
622
 
623
}

powered by: WebSVN 2.1.0

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