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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [mac/] [tkMacWindowMgr.c] - Blame information for rev 578

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

Line No. Rev Author Line
1 578 markom
/*
2
 * tkMacWindowMgr.c --
3
 *
4
 *      Implements common window manager functions for the Macintosh.
5
 *
6
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
7
 *
8
 * See the file "license.terms" for information on usage and redistribution
9
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10
 *
11
 * RCS: @(#) $Id: tkMacWindowMgr.c,v 1.1.1.1 2002-01-16 10:25:57 markom Exp $
12
 */
13
 
14
#include <Events.h>
15
#include <Dialogs.h>
16
#include <EPPC.h>
17
#include <Windows.h>
18
#include <ToolUtils.h>
19
#include <DiskInit.h>
20
#include <LowMem.h>
21
#include <Timer.h>
22
#include <Sound.h>
23
 
24
#include "tkInt.h"
25
#include "tkPort.h"
26
#include "tkMacInt.h"
27
 
28
#define TK_DEFAULT_ABOUT 128
29
 
30
/*
31
 * Declarations of global variables defined in this file.
32
 */
33
 
34
int tkMacAppInFront = true;              /* Boolean variable for determining
35
                                          * if we are the frontmost app. */
36
 
37
/*
38
 *  Non-standard event types that can be passed to HandleEvent.
39
 * These are defined and used by Netscape's plugin architecture.
40
 */
41
#define getFocusEvent       (osEvt + 16)
42
#define loseFocusEvent      (osEvt + 17)
43
#define adjustCursorEvent   (osEvt + 18)
44
 
45
/*
46
 * Declarations of static variables used in this file.
47
 */
48
 
49
static int       gEatButtonUp = 0;        /* 1 if we need to eat the next
50
                                          * up event */
51
static Tk_Window gGrabWinPtr = NULL;     /* Current grab window, NULL if no grab. */
52
static Tk_Window gKeyboardWinPtr = NULL; /* Current keyboard grab window. */
53
static RgnHandle gDamageRgn = NULL;      /* Damage region used for handling
54
                                          * screen updates. */
55
/*
56
 * Forward declarations of procedures used in this file.
57
 */
58
 
59
static void     BringWindowForward _ANSI_ARGS_((WindowRef wRef));
60
static int      CheckEventsAvail _ANSI_ARGS_((void));
61
static int      GenerateActivateEvents _ANSI_ARGS_((EventRecord *eventPtr,
62
                        Window window));
63
static int      GenerateFocusEvent _ANSI_ARGS_((EventRecord *eventPtr,
64
                        Window window));
65
static int      GenerateKeyEvent _ANSI_ARGS_((EventRecord *eventPtr,
66
                        Window window));
67
static int      GenerateUpdateEvent _ANSI_ARGS_((EventRecord *eventPtr,
68
                        Window window));
69
static void     GenerateUpdates _ANSI_ARGS_((RgnHandle updateRgn,
70
                        TkWindow *winPtr));
71
static int      GeneratePollingEvents _ANSI_ARGS_((void));
72
static int      GeneratePollingEvents2 _ANSI_ARGS_((Window window,
73
                        int adjustCursor));
74
static OSErr    TellWindowDefProcToCalcRegions _ANSI_ARGS_((WindowRef wRef));
75
static int      WindowManagerMouse _ANSI_ARGS_((EventRecord *theEvent,
76
                    Window window));
77
 
78
 
79
/*
80
 *----------------------------------------------------------------------
81
 *
82
 * WindowManagerMouse --
83
 *
84
 *      This function determines if a button event is a "Window Manager"
85
 *      function or an event that should be passed to Tk's event
86
 *      queue.
87
 *
88
 * Results:
89
 *      Return true if event was placed on Tk's event queue.
90
 *
91
 * Side effects:
92
 *      Depends on where the button event occurs.
93
 *
94
 *----------------------------------------------------------------------
95
 */
96
 
97
static int
98
WindowManagerMouse(
99
    EventRecord *eventPtr,      /* Macintosh event record. */
100
    Window window)              /* Window pointer. */
101
{
102
    WindowRef whichWindow, frontWindow;
103
    Tk_Window tkwin;
104
    Point where, where2;
105
    int xOffset, yOffset;
106
    short windowPart;
107
 
108
    frontWindow = FrontWindow();
109
 
110
    /*
111
     * The window manager only needs to know about mouse down events
112
     * and sometimes we need to "eat" the mouse up.  Otherwise, we
113
     * just pass the event to Tk.
114
     */
115
    if (eventPtr->what == mouseUp) {
116
        if (gEatButtonUp) {
117
            gEatButtonUp = false;
118
            return false;
119
        }
120
        return TkGenerateButtonEvent(eventPtr->where.h, eventPtr->where.v,
121
                window, TkMacButtonKeyState());
122
    }
123
 
124
    windowPart = FindWindow(eventPtr->where, &whichWindow);
125
    tkwin = Tk_IdToWindow(tkDisplayList->display, window);
126
    switch (windowPart) {
127
        case inSysWindow:
128
            SystemClick(eventPtr, (GrafPort *) whichWindow);
129
            return false;
130
        case inDrag:
131
            if (whichWindow != frontWindow) {
132
                if (!(eventPtr->modifiers & cmdKey)) {
133
                    if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) {
134
                        SysBeep(1);
135
                        return false;
136
                    }
137
                }
138
            }
139
 
140
            /*
141
             * Call DragWindow to move the window around.  It will
142
             * also eat the mouse up event.
143
             */
144
            SetPort((GrafPort *) whichWindow);
145
            where.h = where.v = 0;
146
            LocalToGlobal(&where);
147
            DragWindow(whichWindow, eventPtr->where,
148
                    &tcl_macQdPtr->screenBits.bounds);
149
            gEatButtonUp = false;
150
 
151
            where2.h = where2.v = 0;
152
            LocalToGlobal(&where2);
153
            if (EqualPt(where, where2)) {
154
                return false;
155
            }
156
 
157
            TkMacWindowOffset(whichWindow, &xOffset, &yOffset);
158
            where2.h -= xOffset;
159
            where2.v -= yOffset;
160
            TkGenWMConfigureEvent(tkwin, where2.h, where2.v,
161
                    -1, -1, TK_LOCATION_CHANGED);
162
            return true;
163
        case inGrow:
164
        case inContent:
165
            if (whichWindow != frontWindow ) {
166
                /*
167
                 * This click moves the window forward.  We don't want
168
                 * the corasponding mouse-up to be reported to the application
169
                 * or else it will mess up some Tk scripts.
170
                 */
171
                if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) {
172
                    SysBeep(1);
173
                    return false;
174
                }
175
                BringWindowForward(whichWindow);
176
                gEatButtonUp = true;
177
                SetPort((GrafPort *) whichWindow);
178
                return false;
179
            } else {
180
                /*
181
                 * Generally the content region is the domain of Tk
182
                 * sub-windows.  However, one exception is the grow
183
                 * region.  A button down in this area will be handled
184
                 * by the window manager.  Note: this means that Tk
185
                 * may not get button down events in this area!
186
                 */
187
 
188
                if (TkMacGrowToplevel(whichWindow, eventPtr->where) == true) {
189
                    return true;
190
                } else {
191
                    return TkGenerateButtonEvent(eventPtr->where.h,
192
                            eventPtr->where.v, window, TkMacButtonKeyState());
193
                }
194
            }
195
        case inGoAway:
196
            if (TrackGoAway( whichWindow, eventPtr->where)) {
197
                if (tkwin == NULL) {
198
                    return false;
199
                }
200
                TkGenWMDestroyEvent(tkwin);
201
                return true;
202
            }
203
            return false;
204
        case inMenuBar:
205
            {
206
                int oldMode;
207
                KeyMap theKeys;
208
 
209
                GetKeys(theKeys);
210
                oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
211
                TkMacClearMenubarActive();
212
                TkMacHandleMenuSelect(MenuSelect(eventPtr->where),
213
                        theKeys[1] & 4);
214
                Tcl_SetServiceMode(oldMode);
215
                return true; /* TODO: may not be on event on queue. */
216
            }
217
        case inZoomIn:
218
        case inZoomOut:
219
            if (TkMacZoomToplevel(whichWindow, eventPtr->where, windowPart)
220
                    == true) {
221
                return true;
222
            } else {
223
                return false;
224
            }
225
        default:
226
            return false;
227
    }
228
}
229
 
230
/*
231
 *----------------------------------------------------------------------
232
 *
233
 * TkAboutDlg --
234
 *
235
 *      Displays the default Tk About box.  This code uses Macintosh
236
 *      resources to define the content of the About Box.
237
 *
238
 * Results:
239
 *      None.
240
 *
241
 * Side effects:
242
 *      None.
243
 *
244
 *----------------------------------------------------------------------
245
 */
246
 
247
void
248
TkAboutDlg()
249
{
250
    DialogPtr aboutDlog;
251
    short itemHit = -9;
252
 
253
    aboutDlog = GetNewDialog(128, NULL, (void*)(-1));
254
 
255
    if (!aboutDlog) {
256
        return;
257
    }
258
 
259
    SelectWindow((WindowRef) aboutDlog);
260
 
261
    while (itemHit != 1) {
262
        ModalDialog( NULL, &itemHit);
263
    }
264
    DisposDialog(aboutDlog);
265
    aboutDlog = NULL;
266
 
267
    SelectWindow(FrontWindow());
268
 
269
    return;
270
}
271
 
272
/*
273
 *----------------------------------------------------------------------
274
 *
275
 * GenerateUpdateEvent --
276
 *
277
 *      Given a Macintosh update event this function generates all the
278
 *      X update events needed by Tk.
279
 *
280
 * Results:
281
 *      True if event(s) are generated - false otherwise.
282
 *
283
 * Side effects:
284
 *      Additional events may be place on the Tk event queue.
285
 *
286
 *----------------------------------------------------------------------
287
 */
288
 
289
static int
290
GenerateUpdateEvent(
291
    EventRecord *eventPtr,      /* Incoming Mac event */
292
    Window window)              /* Root X window for event. */
293
{
294
    WindowRef macWindow;
295
    register TkWindow *winPtr;
296
 
297
    winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window);
298
 
299
    if (winPtr == NULL) {
300
         return false;
301
    }
302
 
303
    if (gDamageRgn == NULL) {
304
        gDamageRgn = NewRgn();
305
    }
306
 
307
    /*
308
     * After the call to BeginUpdate the visable region (visRgn) of the
309
     * window is equal to the intersection of the real visable region and
310
     * the update region for this event.  We use this region in all of our
311
     * calculations.
312
     */
313
 
314
    if (eventPtr->message != NULL) {
315
        macWindow = (WindowRef) TkMacGetDrawablePort(window);
316
        BeginUpdate(macWindow);
317
        GenerateUpdates(macWindow->visRgn, winPtr);
318
        EndUpdate(macWindow);
319
        return true;
320
    } else {
321
        /*
322
         * This event didn't come from the system.  This might
323
         * occur if we are running from inside of Netscape.
324
         * In this we shouldn't call BeginUpdate as the vis region
325
         * may be NULL.
326
         */
327
        RgnHandle rgn;
328
        Rect bounds;
329
 
330
        rgn = NewRgn();
331
        TkMacWinBounds(winPtr, &bounds);
332
        RectRgn(rgn, &bounds);
333
        GenerateUpdates(rgn, winPtr);
334
        DisposeRgn(rgn);
335
        return true;
336
    }
337
}
338
 
339
/*
340
 *----------------------------------------------------------------------
341
 *
342
 * GenerateUpdates --
343
 *
344
 *      Given a Macintosh update region and a Tk window this function
345
 *      geneates a X damage event for the window if it is within the
346
 *      update region.  The function will then recursivly have each
347
 *      damaged window generate damage events for its child windows.
348
 *
349
 * Results:
350
 *      None.
351
 *
352
 * Side effects:
353
 *      Additional events may be place on the Tk event queue.
354
 *
355
 *----------------------------------------------------------------------
356
 */
357
 
358
static void
359
GenerateUpdates(
360
    RgnHandle updateRgn,
361
    TkWindow *winPtr)
362
{
363
    TkWindow *childPtr;
364
    XEvent event;
365
    Rect bounds;
366
 
367
    TkMacWinBounds(winPtr, &bounds);
368
 
369
    if (bounds.top > (*updateRgn)->rgnBBox.bottom ||
370
            (*updateRgn)->rgnBBox.top > bounds.bottom ||
371
            bounds.left > (*updateRgn)->rgnBBox.right ||
372
            (*updateRgn)->rgnBBox.left > bounds.right ||
373
            !RectInRgn(&bounds, updateRgn)) {
374
        return;
375
    }
376
 
377
    event.xany.serial = Tk_Display(winPtr)->request;
378
    event.xany.send_event = false;
379
    event.xany.window = Tk_WindowId(winPtr);
380
    event.xany.display = Tk_Display(winPtr);
381
 
382
    event.type = Expose;
383
 
384
    /*
385
     * Compute the bounding box of the area that the damage occured in.
386
     */
387
 
388
    /*
389
     * CopyRgn(TkMacVisableClipRgn(winPtr), rgn);
390
     * TODO: this call doesn't work doing resizes!!!
391
     */
392
    RectRgn(gDamageRgn, &bounds);
393
    SectRgn(gDamageRgn, updateRgn, gDamageRgn);
394
    OffsetRgn(gDamageRgn, -bounds.left, -bounds.top);
395
    event.xexpose.x = (**gDamageRgn).rgnBBox.left;
396
    event.xexpose.y = (**gDamageRgn).rgnBBox.top;
397
    event.xexpose.width = (**gDamageRgn).rgnBBox.right -
398
        (**gDamageRgn).rgnBBox.left;
399
    event.xexpose.height = (**gDamageRgn).rgnBBox.bottom -
400
        (**gDamageRgn).rgnBBox.top;
401
    event.xexpose.count = 0;
402
 
403
    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
404
 
405
    /*
406
     * Generate updates for the children of this window
407
     */
408
 
409
    for (childPtr = winPtr->childList; childPtr != NULL;
410
                                       childPtr = childPtr->nextPtr) {
411
        if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
412
            continue;
413
        }
414
 
415
        GenerateUpdates(updateRgn, childPtr);
416
    }
417
 
418
    /*
419
     * Generate updates for any contained windows
420
     */
421
 
422
    if (Tk_IsContainer(winPtr)) {
423
        childPtr = TkpGetOtherWindow(winPtr);
424
        if (childPtr != NULL && Tk_IsMapped(childPtr)) {
425
            GenerateUpdates(updateRgn, childPtr);
426
        }
427
 
428
        /*
429
         * NOTE: Here we should handle out of process embedding.
430
         */
431
 
432
    }
433
 
434
    return;
435
}
436
 
437
/*
438
 *----------------------------------------------------------------------
439
 *
440
 * TkGenerateButtonEvent --
441
 *
442
 *      Given a global x & y position and the button key status this
443
 *      procedure generates the appropiate X button event.  It also
444
 *      handles the state changes needed to implement implicit grabs.
445
 *
446
 * Results:
447
 *      True if event(s) are generated - false otherwise.
448
 *
449
 * Side effects:
450
 *      Additional events may be place on the Tk event queue.
451
 *      Grab state may also change.
452
 *
453
 *----------------------------------------------------------------------
454
 */
455
 
456
int
457
TkGenerateButtonEvent(
458
    int x,              /* X location of mouse */
459
    int y,              /* Y location of mouse */
460
    Window window,      /* X Window containing button event. */
461
    unsigned int state) /* Button Key state suitable for X event */
462
{
463
    WindowRef whichWin, frontWin;
464
    Point where;
465
    Tk_Window tkwin;
466
    int dummy;
467
 
468
    /*
469
     * ButtonDown events will always occur in the front
470
     * window.  ButtonUp events, however, may occur anywhere
471
     * on the screen.  ButtonUp events should only be sent
472
     * to Tk if in the front window or during an implicit grab.
473
     */
474
    where.h = x;
475
    where.v = y;
476
    FindWindow(where, &whichWin);
477
    frontWin = FrontWindow();
478
 
479
    if ((frontWin == NULL) || (frontWin != whichWin && gGrabWinPtr == NULL)) {
480
        return false;
481
    }
482
 
483
    tkwin = Tk_IdToWindow(tkDisplayList->display, window);
484
 
485
    GlobalToLocal(&where);
486
    if (tkwin != NULL) {
487
        tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v, &dummy, &dummy);
488
    }
489
 
490
    Tk_UpdatePointer(tkwin, x,  y, state);
491
 
492
    return true;
493
}
494
 
495
/*
496
 *----------------------------------------------------------------------
497
 *
498
 * GenerateActivateEvents --
499
 *
500
 *      Generate Activate/Deactivate events from a Macintosh Activate
501
 *      event.  Note, the activate-on-foreground bit must be set in the
502
 *      SIZE flags to ensure we get Activate/Deactivate in addition to
503
 *      Susspend/Resume events.
504
 *
505
 * Results:
506
 *      Returns true if events were generate.
507
 *
508
 * Side effects:
509
 *      Queue events on Tk's event queue.
510
 *
511
 *----------------------------------------------------------------------
512
 */
513
 
514
static int
515
GenerateActivateEvents(
516
    EventRecord *eventPtr,      /* Incoming Mac event */
517
    Window window)              /* Root X window for event. */
518
{
519
    TkWindow *winPtr;
520
 
521
    winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window);
522
    if (winPtr == NULL || winPtr->window == None) {
523
        return false;
524
    }
525
 
526
    TkGenerateActivateEvents(winPtr,
527
            (eventPtr->modifiers & activeFlag) ? 1 : 0);
528
    return true;
529
}
530
 
531
/*
532
 *----------------------------------------------------------------------
533
 *
534
 * XSetInputFocus --
535
 *
536
 *      Change the focus window for the application.
537
 *
538
 * Results:
539
 *      None.
540
 *
541
 * Side effects:
542
 *      None.
543
 *
544
 *----------------------------------------------------------------------
545
 */
546
 
547
void
548
XSetInputFocus(
549
    Display* display,
550
    Window focus,
551
    int revert_to,
552
    Time time)
553
{
554
    /*
555
     * Don't need to do a thing.  Tk manages the focus for us.
556
     */
557
}
558
 
559
/*
560
 *----------------------------------------------------------------------
561
 *
562
 * TkpChangeFocus --
563
 *
564
 *      This procedure is a stub on the Mac because we always own the
565
 *      focus if we are a front most application.
566
 *
567
 * Results:
568
 *      The return value is the serial number of the command that
569
 *      changed the focus.  It may be needed by the caller to filter
570
 *      out focus change events that were queued before the command.
571
 *      If the procedure doesn't actually change the focus then
572
 *      it returns 0.
573
 *
574
 * Side effects:
575
 *      None.
576
 *
577
 *----------------------------------------------------------------------
578
 */
579
 
580
int
581
TkpChangeFocus(winPtr, force)
582
    TkWindow *winPtr;           /* Window that is to receive the X focus. */
583
    int force;                  /* Non-zero means claim the focus even
584
                                 * if it didn't originally belong to
585
                                 * topLevelPtr's application. */
586
{
587
    /*
588
     * We don't really need to do anything on the Mac.  Tk will
589
     * keep all this state for us.
590
     */
591
 
592
    if (winPtr->atts.override_redirect) {
593
        return 0;
594
    }
595
 
596
    /*
597
     * Remember the current serial number for the X server and issue
598
     * a dummy server request.  This marks the position at which we
599
     * changed the focus, so we can distinguish FocusIn and FocusOut
600
     * events on either side of the mark.
601
     */
602
 
603
    return NextRequest(winPtr->display);
604
}
605
 
606
/*
607
 *----------------------------------------------------------------------
608
 *
609
 * GenerateFocusEvent --
610
 *
611
 *      Generate FocusIn/FocusOut events from a Macintosh Activate
612
 *      event.  Note, the activate-on-foreground bit must be set in
613
 *      the SIZE flags to ensure we get Activate/Deactivate in addition
614
 *      to Susspend/Resume events.
615
 *
616
 * Results:
617
 *      Returns true if events were generate.
618
 *
619
 * Side effects:
620
 *      Queue events on Tk's event queue.
621
 *
622
 *----------------------------------------------------------------------
623
 */
624
 
625
static int
626
GenerateFocusEvent(
627
    EventRecord *eventPtr,      /* Incoming Mac event */
628
    Window window)              /* Root X window for event. */
629
{
630
    XEvent event;
631
    Tk_Window tkwin;
632
 
633
    tkwin = Tk_IdToWindow(tkDisplayList->display, window);
634
    if (tkwin == NULL) {
635
        return false;
636
    }
637
 
638
    /*
639
     * Generate FocusIn and FocusOut events.  This event
640
     * is only sent to the toplevel window.
641
     */
642
 
643
    if (eventPtr->modifiers & activeFlag) {
644
        event.xany.type = FocusIn;
645
    } else {
646
        event.xany.type = FocusOut;
647
    }
648
 
649
    event.xany.serial = tkDisplayList->display->request;
650
    event.xany.send_event = False;
651
    event.xfocus.display = tkDisplayList->display;
652
    event.xfocus.window = window;
653
    event.xfocus.mode = NotifyNormal;
654
    event.xfocus.detail = NotifyDetailNone;
655
 
656
    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
657
    return true;
658
}
659
 
660
/*
661
 *----------------------------------------------------------------------
662
 *
663
 * GenerateKeyEvent --
664
 *
665
 *      Given Macintosh keyUp, keyDown & autoKey events this function
666
 *      generates the appropiate X key events.  The window that is passed
667
 *      should represent the frontmost window - which will recieve the
668
 *      event.
669
 *
670
 * Results:
671
 *      True if event(s) are generated - false otherwise.
672
 *
673
 * Side effects:
674
 *      Additional events may be place on the Tk event queue.
675
 *
676
 *----------------------------------------------------------------------
677
 */
678
 
679
static int
680
GenerateKeyEvent(
681
    EventRecord *eventPtr,      /* Incoming Mac event */
682
    Window window)              /* Root X window for event. */
683
{
684
    Point where;
685
    Tk_Window tkwin;
686
    XEvent event;
687
 
688
    /*
689
     * The focus must be in the FrontWindow on the Macintosh.
690
     * We then query Tk to determine the exact Tk window
691
     * that owns the focus.
692
     */
693
 
694
    tkwin = Tk_IdToWindow(tkDisplayList->display, window);
695
    tkwin = (Tk_Window) ((TkWindow *) tkwin)->dispPtr->focusPtr;
696
    if (tkwin == NULL) {
697
        return false;
698
    }
699
 
700
    where.v = eventPtr->where.v;
701
    where.h = eventPtr->where.h;
702
 
703
    event.xany.send_event = False;
704
    event.xkey.same_screen = true;
705
    event.xkey.subwindow = None;
706
    event.xkey.time = TkpGetMS();
707
 
708
    event.xkey.x_root = where.h;
709
    event.xkey.y_root = where.v;
710
    GlobalToLocal(&where);
711
    Tk_TopCoordsToWindow(tkwin, where.h, where.v,
712
            &event.xkey.x, &event.xkey.y);
713
    event.xkey.keycode = eventPtr->message;
714
 
715
    event.xany.serial = Tk_Display(tkwin)->request;
716
    event.xkey.window = Tk_WindowId(tkwin);
717
    event.xkey.display = Tk_Display(tkwin);
718
    event.xkey.root = XRootWindow(Tk_Display(tkwin), 0);
719
    event.xkey.state = TkMacButtonKeyState();
720
 
721
    if (eventPtr->what == keyDown) {
722
        event.xany.type = KeyPress;
723
        Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
724
    } else if (eventPtr->what == keyUp) {
725
        event.xany.type = KeyRelease;
726
        Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
727
    } else {
728
        /*
729
         * Autokey events send multiple XKey events.
730
         *
731
         * Note: the last KeyRelease will always be missed with
732
         * this scheme.  However, most Tk scripts don't look for
733
         * KeyUp events so we should be OK.
734
         */
735
        event.xany.type = KeyRelease;
736
        Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
737
        event.xany.type = KeyPress;
738
        Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
739
    }
740
    return true;
741
}
742
 
743
/*
744
 *----------------------------------------------------------------------
745
 *
746
 * GeneratePollingEvents --
747
 *
748
 *      This function polls the mouse position and generates X Motion,
749
 *      Enter & Leave events.  The cursor is also updated at this
750
 *      time.
751
 *
752
 * Results:
753
 *      True if event(s) are generated - false otherwise.
754
 *
755
 * Side effects:
756
 *      Additional events may be place on the Tk event queue.
757
 *      The cursor may be changed.
758
 *
759
 *----------------------------------------------------------------------
760
 */
761
 
762
static int
763
GeneratePollingEvents()
764
{
765
    Tk_Window tkwin, rootwin;
766
    Window window;
767
    WindowRef whichwindow, frontWin;
768
    Point whereLocal, whereGlobal;
769
    Boolean inContentRgn;
770
    short part;
771
    int local_x, local_y;
772
    int generatedEvents = false;
773
 
774
    /*
775
     * First we get the current mouse position and determine
776
     * what Tk window the mouse is over (if any).
777
     */
778
    frontWin = FrontWindow();
779
    if (frontWin == NULL) {
780
        return false;
781
    }
782
    SetPort((GrafPort *) frontWin);
783
 
784
    GetMouse(&whereLocal);
785
    whereGlobal = whereLocal;
786
    LocalToGlobal(&whereGlobal);
787
 
788
    part = FindWindow(whereGlobal, &whichwindow);
789
    inContentRgn = (part == inContent || part == inGrow);
790
 
791
    if ((frontWin != whichwindow) || !inContentRgn) {
792
        tkwin = NULL;
793
    } else {
794
        window = TkMacGetXWindow(whichwindow);
795
        rootwin = Tk_IdToWindow(tkDisplayList->display, window);
796
        if (rootwin == NULL) {
797
            tkwin = NULL;
798
        } else {
799
            tkwin = Tk_TopCoordsToWindow(rootwin, whereLocal.h, whereLocal.v,
800
                    &local_x, &local_y);
801
        }
802
    }
803
 
804
    /*
805
     * The following call will generate the appropiate X events and
806
     * adjust any state that Tk must remember.
807
     */
808
 
809
    if ((tkwin == NULL) && (gGrabWinPtr != NULL)) {
810
        tkwin = gGrabWinPtr;
811
    }
812
    Tk_UpdatePointer(tkwin, whereGlobal.h,  whereGlobal.v,
813
            TkMacButtonKeyState());
814
 
815
    /*
816
     * Finally, we make sure the proper cursor is installed.  The installation
817
     * is polled to 1) make our resize hack work, and 2) make sure we have the
818
     * proper cursor even if someone else changed the cursor out from under
819
     * us.
820
     */
821
    if ((gGrabWinPtr == NULL) && (part == inGrow) &&
822
            TkMacResizable((TkWindow *) tkwin) &&
823
            (TkMacGetScrollbarGrowWindow((TkWindow *) tkwin) == NULL)) {
824
        TkMacInstallCursor(1);
825
    } else {
826
        TkMacInstallCursor(0);
827
    }
828
 
829
    return true;
830
}
831
 
832
/*
833
 *----------------------------------------------------------------------
834
 *
835
 * GeneratePollingEvents2 --
836
 *
837
 *      This function polls the mouse position and generates X Motion,
838
 *      Enter & Leave events.  The cursor is also updated at this
839
 *      time.  NOTE: this version is for Netscape!!!
840
 *
841
 * Results:
842
 *      True if event(s) are generated - false otherwise.
843
 *
844
 * Side effects:
845
 *      Additional events may be place on the Tk event queue.
846
 *      The cursor may be changed.
847
 *
848
 *----------------------------------------------------------------------
849
 */
850
 
851
static int
852
GeneratePollingEvents2(
853
    Window window,
854
    int adjustCursor)
855
{
856
    Tk_Window tkwin, rootwin;
857
    WindowRef whichwindow, frontWin;
858
    Point whereLocal, whereGlobal;
859
    int local_x, local_y;
860
    int generatedEvents = false;
861
    Rect bounds;
862
 
863
    /*
864
     * First we get the current mouse position and determine
865
     * what Tk window the mouse is over (if any).
866
     */
867
    frontWin = FrontWindow();
868
    if (frontWin == NULL) {
869
        return false;
870
    }
871
    SetPort((GrafPort *) frontWin);
872
 
873
    GetMouse(&whereLocal);
874
    whereGlobal = whereLocal;
875
    LocalToGlobal(&whereGlobal);
876
 
877
    /*
878
     * Determine if we are in a Tk window or not.
879
     */
880
    whichwindow = (WindowRef) TkMacGetDrawablePort(window);
881
    if (whichwindow != frontWin) {
882
        tkwin = NULL;
883
    } else {
884
        rootwin = Tk_IdToWindow(tkDisplayList->display, window);
885
        TkMacWinBounds((TkWindow *) rootwin, &bounds);
886
        if (!PtInRect(whereLocal, &bounds)) {
887
            tkwin = NULL;
888
        } else {
889
            tkwin = Tk_TopCoordsToWindow(rootwin, whereLocal.h, whereLocal.v,
890
                    &local_x, &local_y);
891
        }
892
    }
893
 
894
 
895
    /*
896
     * The following call will generate the appropiate X events and
897
     * adjust any state that Tk must remember.
898
     */
899
 
900
    if ((tkwin == NULL) && (gGrabWinPtr != NULL)) {
901
        tkwin = gGrabWinPtr;
902
    }
903
    Tk_UpdatePointer(tkwin, whereGlobal.h,  whereGlobal.v,
904
            TkMacButtonKeyState());
905
 
906
    /*
907
     * Finally, we make sure the proper cursor is installed.  The installation
908
     * is polled to 1) make our resize hack work, and 2) make sure we have the
909
     * proper cursor even if someone else changed the cursor out from under
910
     * us.
911
     */
912
 
913
    if (adjustCursor) {
914
        TkMacInstallCursor(0);
915
    }
916
    return true;
917
}
918
 
919
/*
920
 *----------------------------------------------------------------------
921
 *
922
 * TkMacButtonKeyState --
923
 *
924
 *      Returns the current state of the button & modifier keys.
925
 *
926
 * Results:
927
 *      A bitwise inclusive OR of a subset of the following:
928
 *      Button1Mask, ShiftMask, LockMask, ControlMask, Mod?Mask,
929
 *      Mod?Mask.
930
 *
931
 * Side effects:
932
 *      None.
933
 *
934
 *----------------------------------------------------------------------
935
 */
936
 
937
unsigned int
938
TkMacButtonKeyState()
939
{
940
    unsigned int state = 0;
941
    KeyMap theKeys;
942
 
943
    if (Button() & !gEatButtonUp) {
944
        state |= Button1Mask;
945
    }
946
 
947
    GetKeys(theKeys);
948
 
949
    if (theKeys[1] & 2) {
950
        state |= LockMask;
951
    }
952
 
953
    if (theKeys[1] & 1) {
954
        state |= ShiftMask;
955
    }
956
 
957
    if (theKeys[1] & 8) {
958
        state |= ControlMask;
959
    }
960
 
961
    if (theKeys[1] & 32768) {
962
        state |= Mod1Mask;              /* command key */
963
    }
964
 
965
    if (theKeys[1] & 4) {
966
        state |= Mod2Mask;              /* option key */
967
    }
968
 
969
    return state;
970
}
971
 
972
/*
973
 *----------------------------------------------------------------------
974
 *
975
 * XGrabKeyboard --
976
 *
977
 *      Simulates a keyboard grab by setting the focus.
978
 *
979
 * Results:
980
 *      Always returns GrabSuccess.
981
 *
982
 * Side effects:
983
 *      Sets the keyboard focus to the specified window.
984
 *
985
 *----------------------------------------------------------------------
986
 */
987
 
988
int
989
XGrabKeyboard(
990
    Display* display,
991
    Window grab_window,
992
    Bool owner_events,
993
    int pointer_mode,
994
    int keyboard_mode,
995
    Time time)
996
{
997
    gKeyboardWinPtr = Tk_IdToWindow(display, grab_window);
998
    return GrabSuccess;
999
}
1000
 
1001
/*
1002
 *----------------------------------------------------------------------
1003
 *
1004
 * XUngrabKeyboard --
1005
 *
1006
 *      Releases the simulated keyboard grab.
1007
 *
1008
 * Results:
1009
 *      None.
1010
 *
1011
 * Side effects:
1012
 *      Sets the keyboard focus back to the value before the grab.
1013
 *
1014
 *----------------------------------------------------------------------
1015
 */
1016
 
1017
void
1018
XUngrabKeyboard(
1019
    Display* display,
1020
    Time time)
1021
{
1022
    gKeyboardWinPtr = NULL;
1023
}
1024
 
1025
/*
1026
 *----------------------------------------------------------------------
1027
 *
1028
 * XQueryPointer --
1029
 *
1030
 *      Check the current state of the mouse.  This is not a complete
1031
 *      implementation of this function.  It only computes the root
1032
 *      coordinates and the current mask.
1033
 *
1034
 * Results:
1035
 *      Sets root_x_return, root_y_return, and mask_return.  Returns
1036
 *      true on success.
1037
 *
1038
 * Side effects:
1039
 *      None.
1040
 *
1041
 *----------------------------------------------------------------------
1042
 */
1043
 
1044
Bool
1045
XQueryPointer(
1046
    Display* display,
1047
    Window w,
1048
    Window* root_return,
1049
    Window* child_return,
1050
    int* root_x_return,
1051
    int* root_y_return,
1052
    int* win_x_return,
1053
    int* win_y_return,
1054
    unsigned int* mask_return)
1055
{
1056
    Point where;
1057
 
1058
    GetMouse(&where);
1059
    LocalToGlobal(&where);
1060
    *root_x_return = where.h;
1061
    *root_y_return = where.v;
1062
    *mask_return = TkMacButtonKeyState();
1063
    return True;
1064
}
1065
 
1066
/*
1067
 *----------------------------------------------------------------------
1068
 *
1069
 * TkMacGenerateTime --
1070
 *
1071
 *      Returns the total number of ticks from startup  This function
1072
 *      is used to generate the time of generated X events.
1073
 *
1074
 * Results:
1075
 *      Returns the current time (ticks from startup).
1076
 *
1077
 * Side effects:
1078
 *      None.
1079
 *
1080
 *----------------------------------------------------------------------
1081
 */
1082
 
1083
Time
1084
TkMacGenerateTime()
1085
{
1086
    return (Time) LMGetTicks();
1087
}
1088
 
1089
/*
1090
 *----------------------------------------------------------------------
1091
 *
1092
 * TkMacConvertEvent --
1093
 *
1094
 *      This function converts a Macintosh event into zero or more
1095
 *      Tcl events.
1096
 *
1097
 * Results:
1098
 *      Returns 1 if event added to Tcl queue, 0 otherwse.
1099
 *
1100
 * Side effects:
1101
 *      May add events to Tcl's event queue.
1102
 *
1103
 *----------------------------------------------------------------------
1104
 */
1105
 
1106
int
1107
TkMacConvertEvent(
1108
    EventRecord *eventPtr)
1109
{
1110
    WindowRef whichWindow;
1111
    Window window;
1112
    int eventFound = false;
1113
 
1114
    switch (eventPtr->what) {
1115
        case nullEvent:
1116
        case adjustCursorEvent:
1117
            if (GeneratePollingEvents()) {
1118
                eventFound = true;
1119
            }
1120
            break;
1121
        case updateEvt:
1122
            whichWindow = (WindowRef)eventPtr->message;
1123
            window = TkMacGetXWindow(whichWindow);
1124
            if (GenerateUpdateEvent(eventPtr, window)) {
1125
                eventFound = true;
1126
            }
1127
            break;
1128
        case mouseDown:
1129
        case mouseUp:
1130
            FindWindow(eventPtr->where, &whichWindow);
1131
            window = TkMacGetXWindow(whichWindow);
1132
            if (WindowManagerMouse(eventPtr, window)) {
1133
                eventFound = true;
1134
            }
1135
            break;
1136
        case autoKey:
1137
        case keyDown:
1138
            /*
1139
             * Handle menu-key events here.  If it is *not*
1140
             * a menu key - just fall through to handle as a
1141
             * normal key event.
1142
             */
1143
            if ((eventPtr->modifiers & cmdKey) == cmdKey) {
1144
                long menuResult;
1145
                int oldMode;
1146
 
1147
                oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
1148
                menuResult = MenuKey(eventPtr->message & charCodeMask);
1149
                Tcl_SetServiceMode(oldMode);
1150
 
1151
                if (HiWord(menuResult) != 0) {
1152
                    TkMacHandleMenuSelect(menuResult, false);
1153
                    break;
1154
                }
1155
            }
1156
        case keyUp:
1157
            whichWindow = FrontWindow();
1158
            window = TkMacGetXWindow(whichWindow);
1159
            eventFound |= GenerateKeyEvent(eventPtr, window);
1160
            break;
1161
        case activateEvt:
1162
            window = TkMacGetXWindow((WindowRef) eventPtr->message);
1163
            eventFound |= GenerateActivateEvents(eventPtr, window);
1164
            eventFound |= GenerateFocusEvent(eventPtr, window);
1165
            break;
1166
        case getFocusEvent:
1167
            eventPtr->modifiers |= activeFlag;
1168
            window = TkMacGetXWindow((WindowRef) eventPtr->message);
1169
            eventFound |= GenerateFocusEvent(eventPtr, window);
1170
            break;
1171
        case loseFocusEvent:
1172
            eventPtr->modifiers &= ~activeFlag;
1173
            window = TkMacGetXWindow((WindowRef) eventPtr->message);
1174
            eventFound |= GenerateFocusEvent(eventPtr, window);
1175
            break;
1176
        case kHighLevelEvent:
1177
            TkMacDoHLEvent(eventPtr);
1178
            /* TODO: should return true if events were placed on event queue. */
1179
            break;
1180
        case osEvt:
1181
            /*
1182
             * Do clipboard conversion.
1183
             */
1184
            switch ((eventPtr->message & osEvtMessageMask) >> 24) {
1185
                case mouseMovedMessage:
1186
                    if (GeneratePollingEvents()) {
1187
                        eventFound = true;
1188
                    }
1189
                    break;
1190
                case suspendResumeMessage:
1191
                    if (!(eventPtr->message & resumeFlag)) {
1192
                        TkSuspendClipboard();
1193
                    }
1194
                    tkMacAppInFront = (eventPtr->message & resumeFlag);
1195
                    break;
1196
            }
1197
            break;
1198
        case diskEvt:
1199
            /*
1200
             * Disk insertion.
1201
             */
1202
            if (HiWord(eventPtr->message) != noErr) {
1203
                Point pt;
1204
 
1205
                DILoad();
1206
                pt.v = pt.h = 120;        /* parameter ignored in sys 7 */
1207
                DIBadMount(pt, eventPtr->message);
1208
                DIUnload();
1209
            }
1210
            break;
1211
    }
1212
 
1213
    return eventFound;
1214
}
1215
 
1216
/*
1217
 *----------------------------------------------------------------------
1218
 *
1219
 * TkMacConvertTkEvent --
1220
 *
1221
 *      This function converts a Macintosh event into zero or more
1222
 *      Tcl events.  It is intended for use in Netscape-style embedding.
1223
 *
1224
 * Results:
1225
 *      Returns 1 if event added to Tcl queue, 0 otherwse.
1226
 *
1227
 * Side effects:
1228
 *      May add events to Tcl's event queue.
1229
 *
1230
 *----------------------------------------------------------------------
1231
 */
1232
 
1233
int
1234
TkMacConvertTkEvent(
1235
    EventRecord *eventPtr,
1236
    Window window)
1237
{
1238
    int eventFound = false;
1239
    Point where;
1240
 
1241
    /*
1242
     * By default, assume it is legal for us to set the cursor
1243
     */
1244
 
1245
    Tk_MacTkOwnsCursor(1);
1246
 
1247
    switch (eventPtr->what) {
1248
        case nullEvent:
1249
        /*
1250
         * We get NULL events only when the cursor is NOT over
1251
         * the plugin.  Otherwise we get updateCursor events.
1252
         * We will not generate polling events or move the cursor
1253
         * in this case.
1254
         */
1255
 
1256
            eventFound = false;
1257
            break;
1258
        case adjustCursorEvent:
1259
            if (GeneratePollingEvents2(window, 1)) {
1260
                eventFound = true;
1261
            }
1262
            break;
1263
        case updateEvt:
1264
        /*
1265
         * It is possibly not legal for us to set the cursor
1266
         */
1267
 
1268
            Tk_MacTkOwnsCursor(0);
1269
            if (GenerateUpdateEvent(eventPtr, window)) {
1270
                eventFound = true;
1271
            }
1272
            break;
1273
        case mouseDown:
1274
        case mouseUp:
1275
            GetMouse(&where);
1276
            LocalToGlobal(&where);
1277
            eventFound |= TkGenerateButtonEvent(where.h, where.v,
1278
                window, TkMacButtonKeyState());
1279
            break;
1280
        case autoKey:
1281
        case keyDown:
1282
            /*
1283
             * Handle menu-key events here.  If it is *not*
1284
             * a menu key - just fall through to handle as a
1285
             * normal key event.
1286
             */
1287
            if ((eventPtr->modifiers & cmdKey) == cmdKey) {
1288
                long menuResult = MenuKey(eventPtr->message & charCodeMask);
1289
 
1290
                if (HiWord(menuResult) != 0) {
1291
                    TkMacHandleMenuSelect(menuResult, false);
1292
                    break;
1293
                }
1294
            }
1295
        case keyUp:
1296
            eventFound |= GenerateKeyEvent(eventPtr, window);
1297
            break;
1298
        case activateEvt:
1299
        /*
1300
         * It is probably not legal for us to set the cursor
1301
         * here, since we don't know where the mouse is in the
1302
         * window that is being activated.
1303
         */
1304
 
1305
            Tk_MacTkOwnsCursor(0);
1306
            eventFound |= GenerateActivateEvents(eventPtr, window);
1307
            eventFound |= GenerateFocusEvent(eventPtr, window);
1308
            break;
1309
        case getFocusEvent:
1310
            eventPtr->modifiers |= activeFlag;
1311
            eventFound |= GenerateFocusEvent(eventPtr, window);
1312
            break;
1313
        case loseFocusEvent:
1314
            eventPtr->modifiers &= ~activeFlag;
1315
            eventFound |= GenerateFocusEvent(eventPtr, window);
1316
            break;
1317
        case kHighLevelEvent:
1318
            TkMacDoHLEvent(eventPtr);
1319
            /* TODO: should return true if events were placed on event queue. */
1320
            break;
1321
        case osEvt:
1322
            /*
1323
             * Do clipboard conversion.
1324
             */
1325
            switch ((eventPtr->message & osEvtMessageMask) >> 24) {
1326
        /*
1327
         * It is possibly not legal for us to set the cursor.
1328
         * Netscape sends us these events all the time...
1329
         */
1330
 
1331
                Tk_MacTkOwnsCursor(0);
1332
 
1333
                case mouseMovedMessage:
1334
                    /* if (GeneratePollingEvents2(window, 0)) {
1335
                        eventFound = true;
1336
                    }  NEXT LINE IS TEMPORARY */
1337
                    eventFound = false;
1338
                    break;
1339
                case suspendResumeMessage:
1340
                    if (!(eventPtr->message & resumeFlag)) {
1341
                        TkSuspendClipboard();
1342
                    }
1343
                    tkMacAppInFront = (eventPtr->message & resumeFlag);
1344
                    break;
1345
            }
1346
            break;
1347
        case diskEvt:
1348
            /*
1349
             * Disk insertion.
1350
             */
1351
            if (HiWord(eventPtr->message) != noErr) {
1352
                Point pt;
1353
 
1354
                DILoad();
1355
                pt.v = pt.h = 120;        /* parameter ignored in sys 7 */
1356
                DIBadMount(pt, eventPtr->message);
1357
                DIUnload();
1358
            }
1359
            break;
1360
    }
1361
 
1362
    return eventFound;
1363
}
1364
 
1365
/*
1366
 *----------------------------------------------------------------------
1367
 *
1368
 * CheckEventsAvail --
1369
 *
1370
 *      Checks to see if events are available on the Macintosh queue.
1371
 *      This function looks for both queued events (eg. key & button)
1372
 *      and generated events (update).
1373
 *
1374
 * Results:
1375
 *      True is events exist, false otherwise.
1376
 *
1377
 * Side effects:
1378
 *      None.
1379
 *
1380
 *----------------------------------------------------------------------
1381
 */
1382
 
1383
static int
1384
CheckEventsAvail()
1385
{
1386
    QHdrPtr evPtr;
1387
    WindowPeek macWinPtr;
1388
 
1389
    evPtr = GetEvQHdr();
1390
    if (evPtr->qHead != NULL) {
1391
        return true;
1392
    }
1393
 
1394
    macWinPtr = (WindowPeek) FrontWindow();
1395
    while (macWinPtr != NULL) {
1396
        if (!EmptyRgn(macWinPtr->updateRgn)) {
1397
            return true;
1398
        }
1399
        macWinPtr = macWinPtr->nextWindow;
1400
    }
1401
    return false;
1402
}
1403
 
1404
/*
1405
 *----------------------------------------------------------------------
1406
 *
1407
 * TkpSetCapture --
1408
 *
1409
 *      This function captures the mouse so that all future events
1410
 *      will be reported to this window, even if the mouse is outside
1411
 *      the window.  If the specified window is NULL, then the mouse
1412
 *      is released.
1413
 *
1414
 * Results:
1415
 *      None.
1416
 *
1417
 * Side effects:
1418
 *      Sets the capture flag and captures the mouse.
1419
 *
1420
 *----------------------------------------------------------------------
1421
 */
1422
 
1423
void
1424
TkpSetCapture(
1425
    TkWindow *winPtr)                   /* Capture window, or NULL. */
1426
{
1427
    while ((winPtr != NULL) && !Tk_IsTopLevel(winPtr)) {
1428
        winPtr = winPtr->parentPtr;
1429
    }
1430
    gGrabWinPtr = (Tk_Window) winPtr;
1431
}
1432
 
1433
/*
1434
 *----------------------------------------------------------------------
1435
 *
1436
 * TkMacWindowOffset --
1437
 *
1438
 *      Determines the x and y offset from the orgin of the toplevel
1439
 *      window dressing (the structure region, ie. title bar) and the
1440
 *      orgin of the content area.
1441
 *
1442
 * Results:
1443
 *      The x & y offset in pixels.
1444
 *
1445
 * Side effects:
1446
 *      None.
1447
 *
1448
 *----------------------------------------------------------------------
1449
 */
1450
 
1451
void
1452
TkMacWindowOffset(
1453
    WindowRef wRef,
1454
    int *xOffset,
1455
    int *yOffset)
1456
{
1457
    OSErr err = noErr;
1458
    WindowPeek wPeek = (WindowPeek) wRef;
1459
    RgnHandle strucRgn = wPeek->strucRgn;
1460
    RgnHandle contRgn = wPeek->contRgn;
1461
    Rect strucRect, contRect;
1462
 
1463
    if (!EmptyRgn(strucRgn) && !EmptyRgn(contRgn)) {
1464
        strucRect = (**strucRgn).rgnBBox;
1465
        contRect = (**contRgn).rgnBBox;
1466
    } else {
1467
        /*
1468
         * The current window's regions are not up to date.
1469
         * Probably because the window isn't visable.  What we
1470
         * will do is save the old regions, have the window calculate
1471
         * what the regions should be, and then restore it self.
1472
         */
1473
        strucRgn = NewRgn( );
1474
        contRgn = NewRgn( );
1475
 
1476
        if (!strucRgn || !contRgn) {
1477
            err = MemError( );
1478
        } else {
1479
            CopyRgn(wPeek->strucRgn, strucRgn);
1480
            CopyRgn(wPeek->contRgn, contRgn);
1481
 
1482
            if (!(err = TellWindowDefProcToCalcRegions(wRef))) {
1483
                strucRect = (**(wPeek->strucRgn)).rgnBBox;
1484
                contRect = (**(wPeek->contRgn)).rgnBBox;
1485
            }
1486
 
1487
            CopyRgn(strucRgn, wPeek->strucRgn);
1488
            CopyRgn(contRgn, wPeek->contRgn);
1489
        }
1490
 
1491
        if (contRgn) {
1492
            DisposeRgn(contRgn);
1493
        }
1494
 
1495
        if (strucRgn) {
1496
            DisposeRgn(strucRgn);
1497
        }
1498
    }
1499
 
1500
    if (!err) {
1501
        *xOffset = contRect.left - strucRect.left;
1502
        *yOffset = contRect.top - strucRect.top;
1503
    } else {
1504
        *xOffset = 0;
1505
        *yOffset = 0;
1506
    }
1507
 
1508
    return;
1509
}
1510
 
1511
/*
1512
 *----------------------------------------------------------------------
1513
 *
1514
 * TellWindowDefProcToCalcRegions --
1515
 *
1516
 *      Force a Macintosh window to recalculate it's content and
1517
 *      structure regions.
1518
 *
1519
 * Results:
1520
 *      An OS error.
1521
 *
1522
 * Side effects:
1523
 *      The windows content and structure regions may be updated.
1524
 *
1525
 *----------------------------------------------------------------------
1526
 */
1527
 
1528
static OSErr
1529
TellWindowDefProcToCalcRegions(
1530
    WindowRef wRef)
1531
{
1532
    OSErr err = noErr;
1533
    SInt8 hState;
1534
    Handle wdef = ((WindowPeek) wRef)->windowDefProc;
1535
 
1536
    /*
1537
     * Load and lock the window definition procedure for
1538
     * the window.
1539
     */
1540
    hState = HGetState(wdef);
1541
    if (!(err = MemError())) {
1542
        LoadResource(wdef);
1543
        if (!(err = ResError())) {
1544
            MoveHHi(wdef);
1545
            err = MemError();
1546
            if (err == memLockedErr) {
1547
                err = noErr;
1548
            } else if (!err) {
1549
                HLock(wdef);
1550
                err = MemError();
1551
            }
1552
        }
1553
    }
1554
 
1555
    /*
1556
     * Assuming there are no errors we now call the window definition
1557
     * procedure to tell it to calculate the regions for the window.
1558
     */
1559
    if (err == noErr) {
1560
        (void) CallWindowDefProc((UniversalProcPtr) *wdef,
1561
                GetWVariant(wRef), wRef, wCalcRgns, 0);
1562
 
1563
        HSetState(wdef, hState);
1564
        if (!err) {
1565
             err = MemError();
1566
        }
1567
    }
1568
 
1569
    return err;
1570
}
1571
 
1572
/*
1573
 *----------------------------------------------------------------------
1574
 *
1575
 * BringWindowForward --
1576
 *
1577
 *      Bring this background window to the front.  We also set state
1578
 *      so Tk thinks the button is currently up.
1579
 *
1580
 * Results:
1581
 *      None.
1582
 *
1583
 * Side effects:
1584
 *      The window is brought forward.
1585
 *
1586
 *----------------------------------------------------------------------
1587
 */
1588
 
1589
static void
1590
BringWindowForward(
1591
    WindowRef wRef)
1592
{
1593
    SelectWindow(wRef);
1594
}
1595
 
1596
/*
1597
 *----------------------------------------------------------------------
1598
 *
1599
 * TkpGetMS --
1600
 *
1601
 *      Return a relative time in milliseconds.  It doesn't matter
1602
 *      when the epoch was.
1603
 *
1604
 * Results:
1605
 *      Number of milliseconds.
1606
 *
1607
 * Side effects:
1608
 *      None.
1609
 *
1610
 *----------------------------------------------------------------------
1611
 */
1612
 
1613
unsigned long
1614
TkpGetMS()
1615
{
1616
    long long * int64Ptr;
1617
    UnsignedWide micros;
1618
 
1619
    Microseconds(&micros);
1620
    int64Ptr = (long long *) &micros;
1621
 
1622
    /*
1623
     * We need 64 bit math to do this.  This is available in CW 11
1624
     * and on.  Other's will need to use a different scheme.
1625
     */
1626
 
1627
    *int64Ptr /= 1000;
1628
 
1629
    return (long) *int64Ptr;
1630
}

powered by: WebSVN 2.1.0

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