1619 lines
40 KiB
C
1619 lines
40 KiB
C
/*
|
||
* tkMacWindowMgr.c --
|
||
*
|
||
* Implements common window manager functions for the Macintosh.
|
||
*
|
||
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
|
||
*
|
||
* See the file "license.terms" for information on usage and redistribution
|
||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||
*
|
||
* SCCS: @(#) tkMacWindowMgr.c 1.35 96/09/20 14:29:27
|
||
*/
|
||
|
||
#include <Events.h>
|
||
#include <Dialogs.h>
|
||
#include <EPPC.h>
|
||
#include <Windows.h>
|
||
#include <ToolUtils.h>
|
||
#include <DiskInit.h>
|
||
#include <LowMem.h>
|
||
|
||
#include "tkInt.h"
|
||
#include "tkPort.h"
|
||
#include "tkMacInt.h"
|
||
|
||
#define TK_DEFAULT_ABOUT 128
|
||
|
||
/*
|
||
* Declarations of global variables defined in this file.
|
||
*/
|
||
|
||
int tkMacAppInFront = true; /* Boolean variable for determining
|
||
* if we are the frontmost app. */
|
||
|
||
/*
|
||
* Declarations of static variables used in this file.
|
||
*/
|
||
|
||
static int gEatButtonUp = 0; /* 1 if we need to eat the next up event */
|
||
static int gCaptured = 0; /* 1 if mouse events outside of Tk
|
||
* windows will be reported, else 0 */
|
||
static Tk_Window gGrabWinPtr = NULL; /* Window that defines the top of the
|
||
* grab tree in a global grab. */
|
||
static Tk_Window gKeyboardWinPtr = NULL; /* Current keyboard grab window. */
|
||
static Point gLastPointerPos; /* Last known position of mouse. */
|
||
static Tk_Window gLastWinPtr = NULL; /* The last window the mouse was in */
|
||
static Tk_Window gRestrictWinPtr = NULL; /* Window to which all mouse
|
||
* events will be reported. */
|
||
static RgnHandle gDamageRgn = NULL; /* Damage region used for handling
|
||
* screen updates. */
|
||
/*
|
||
* Forward declarations of procedures used in this file.
|
||
*/
|
||
|
||
static void BringWindowForward _ANSI_ARGS_((WindowRef wRef));
|
||
static int CheckEventsAvail _ANSI_ARGS_((void));
|
||
static int GenerateActivateEvents _ANSI_ARGS_((EventRecord *macEvent));
|
||
static int GenerateKeyEvent _ANSI_ARGS_((EventRecord *macEvent));
|
||
static int GenerateUpdateEvent _ANSI_ARGS_((EventRecord *macEvent));
|
||
static int GenerateEnterLeave _ANSI_ARGS_((Tk_Window tkwin,
|
||
long x, int y));
|
||
static int GenerateMotion _ANSI_ARGS_((Tk_Window tkwin,
|
||
Point whereLocal, Point whereGlobal));
|
||
static void GenerateUpdates _ANSI_ARGS_((RgnHandle updateRgn,
|
||
TkWindow *winPtr));
|
||
static int GeneratePollingEvents _ANSI_ARGS_((void));
|
||
static void InitializeCrossingEvent _ANSI_ARGS_((XEvent *eventPtr,
|
||
TkWindow *winPtr, long x, long y));
|
||
static OSErr TellWindowDefProcToCalcRegions _ANSI_ARGS_((WindowRef wRef));
|
||
static void UpdateCursor _ANSI_ARGS_((TkWindow *winPtr,
|
||
WindowRef whichwindow, Point whereLocal));
|
||
static int WindowManagerMouse _ANSI_ARGS_((EventRecord *theEvent));
|
||
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* WindowManagerMouse --
|
||
*
|
||
* This function determines if a button event is a "Window Manager"
|
||
* function or an event that should be passed to Tk's event
|
||
* queue.
|
||
*
|
||
* Results:
|
||
* Return true if event was placed on Tk's event queue.
|
||
*
|
||
* Side effects:
|
||
* Depends on where the button event occurs.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static int
|
||
WindowManagerMouse(eventPtr)
|
||
EventRecord *eventPtr;
|
||
{
|
||
WindowRef whichWindow, frontWindow;
|
||
Window window;
|
||
Tk_Window tkwin;
|
||
Point where, where2;
|
||
int xOffset, yOffset;
|
||
short windowPart;
|
||
|
||
|
||
frontWindow = FrontWindow();
|
||
|
||
/*
|
||
* The window manager only needs to know about mouse down events.
|
||
*/
|
||
if (eventPtr->what == mouseUp) {
|
||
if (gEatButtonUp) {
|
||
gEatButtonUp = false;
|
||
return false;
|
||
}
|
||
return TkGenerateButtonEvent(eventPtr->where.h, eventPtr->where.v,
|
||
TkMacButtonKeyState());
|
||
}
|
||
|
||
windowPart = FindWindow(eventPtr->where, &whichWindow);
|
||
switch (windowPart) {
|
||
case inSysWindow:
|
||
SystemClick(eventPtr, (GrafPort *) whichWindow);
|
||
return false;
|
||
case inDrag:
|
||
if (whichWindow != frontWindow) {
|
||
if (!(eventPtr->modifiers & cmdKey)) {
|
||
BringWindowForward(whichWindow);
|
||
}
|
||
}
|
||
|
||
SetPort((GrafPort *) whichWindow);
|
||
where.h = where.v = 0;
|
||
LocalToGlobal(&where);
|
||
DragWindow(whichWindow, eventPtr->where,
|
||
&qd.screenBits.bounds);
|
||
|
||
where2.h = where2.v = 0;
|
||
LocalToGlobal(&where2);
|
||
if (EqualPt(where, where2)) {
|
||
return false;
|
||
}
|
||
|
||
window = TkMacGetXWindow(whichWindow);
|
||
tkwin = Tk_IdToWindow(tkDisplayList->display, window);
|
||
TkMacWindowOffset(whichWindow, &xOffset, &yOffset);
|
||
where2.h -= xOffset;
|
||
where2.v -= yOffset;
|
||
TkGenWMConfigureEvent(tkwin, where2.h, where2.v, -1, -1, TK_LOCATION_CHANGED);
|
||
return true;
|
||
case inGrow:
|
||
case inContent:
|
||
if (whichWindow != frontWindow ) {
|
||
BringWindowForward(whichWindow);
|
||
SetPort((GrafPort *) whichWindow);
|
||
return false;
|
||
} else {
|
||
/*
|
||
* Generally the content region is the domain of Tk
|
||
* sub-windows. However, one exception is the grow
|
||
* region. A button down in this area will be handled
|
||
* by the window manager. Note: this means that Tk
|
||
* may not get button down events in this area!
|
||
*/
|
||
|
||
if (TkMacGrowToplevel(whichWindow, eventPtr->where) == true) {
|
||
return true;
|
||
} else {
|
||
return TkGenerateButtonEvent(eventPtr->where.h,
|
||
eventPtr->where.v, TkMacButtonKeyState());
|
||
}
|
||
}
|
||
case inGoAway:
|
||
if (TrackGoAway( whichWindow, eventPtr->where)) {
|
||
Window window;
|
||
Tk_Window tkwin;
|
||
|
||
window = TkMacGetXWindow(whichWindow);
|
||
tkwin = Tk_IdToWindow(tkDisplayList->display, window);
|
||
if (tkwin == NULL) {
|
||
return false;
|
||
}
|
||
TkGenWMDestroyEvent(tkwin);
|
||
return true;
|
||
}
|
||
return false;
|
||
case inMenuBar:
|
||
{
|
||
KeyMap theKeys;
|
||
|
||
GetKeys(theKeys);
|
||
TkMacHandleMenuSelect(MenuSelect(eventPtr->where),
|
||
theKeys[1] & 4);
|
||
return true; /* TODO: may not be on event on queue. */
|
||
}
|
||
case inZoomIn:
|
||
case inZoomOut:
|
||
if (TkMacZoomToplevel(whichWindow, eventPtr->where, windowPart)
|
||
== true) {
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkAboutDlg --
|
||
*
|
||
* Displays the default Tk About box. This code uses Macintosh
|
||
* resources to define the content of the About Box.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkAboutDlg()
|
||
{
|
||
DialogPtr aboutDlog;
|
||
short itemHit = -9;
|
||
|
||
aboutDlog = GetNewDialog(128, NULL, (void*)(-1));
|
||
|
||
if (!aboutDlog) {
|
||
return;
|
||
}
|
||
|
||
SelectWindow((WindowRef) aboutDlog);
|
||
|
||
while (itemHit != 1) {
|
||
ModalDialog( NULL, &itemHit);
|
||
}
|
||
DisposDialog(aboutDlog);
|
||
aboutDlog = NULL;
|
||
|
||
SelectWindow(FrontWindow());
|
||
|
||
return;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* GenerateUpdateEvent --
|
||
*
|
||
* Given a Macintosh update event this function generates all the
|
||
* X update events needed by Tk.
|
||
*
|
||
* Results:
|
||
* True if event(s) are generated - false otherwise.
|
||
*
|
||
* Side effects:
|
||
* Additional events may be place on the Tk event queue.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static int
|
||
GenerateUpdateEvent(macEvent)
|
||
EventRecord *macEvent; /* Incoming Mac event */
|
||
{
|
||
WindowRef macWindow = (WindowRef)macEvent->message;
|
||
Window window;
|
||
register TkWindow *winPtr;
|
||
|
||
window = TkMacGetXWindow(macWindow);
|
||
winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window);
|
||
|
||
if (gDamageRgn == NULL) {
|
||
gDamageRgn = NewRgn();
|
||
}
|
||
|
||
/*
|
||
* After the call to BeginUpdate the visable region (visRgn) of the
|
||
* window is equal to the intersection of the real visable region and
|
||
* the update region for this event. We use this region in all of our
|
||
* calculations.
|
||
*/
|
||
|
||
if (winPtr != NULL) {
|
||
BeginUpdate(macWindow);
|
||
GenerateUpdates(macWindow->visRgn, winPtr);
|
||
EndUpdate(macWindow);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* GenerateUpdates --
|
||
*
|
||
* Given a Macintosh update region and a Tk window this function
|
||
* geneates a X damage event for the window if it is within the
|
||
* update region. The function will then recursivly have each
|
||
* damaged window generate damage events for its child windows.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Additional events may be place on the Tk event queue.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static void
|
||
GenerateUpdates(updateRgn, winPtr)
|
||
RgnHandle updateRgn;
|
||
TkWindow *winPtr;
|
||
{
|
||
TkWindow *childPtr;
|
||
XEvent event;
|
||
Rect bounds;
|
||
|
||
TkMacWinBounds(winPtr, &bounds);
|
||
|
||
if (bounds.top > (*updateRgn)->rgnBBox.bottom ||
|
||
(*updateRgn)->rgnBBox.top > bounds.bottom ||
|
||
bounds.left > (*updateRgn)->rgnBBox.right ||
|
||
(*updateRgn)->rgnBBox.left > bounds.right ||
|
||
!RectInRgn(&bounds, updateRgn)) {
|
||
return;
|
||
}
|
||
|
||
event.xany.serial = Tk_Display(winPtr)->request;
|
||
event.xany.send_event = false;
|
||
event.xany.window = Tk_WindowId(winPtr);
|
||
event.xany.display = Tk_Display(winPtr);
|
||
|
||
event.type = Expose;
|
||
|
||
/*
|
||
* Compute the bounding box of the area that the damage occured in.
|
||
*/
|
||
|
||
/*
|
||
* CopyRgn(TkMacVisableClipRgn(winPtr), rgn);
|
||
* TODO: this call doesn't work doing resizes!!!
|
||
*/
|
||
RectRgn(gDamageRgn, &bounds);
|
||
SectRgn(gDamageRgn, updateRgn, gDamageRgn);
|
||
OffsetRgn(gDamageRgn, -bounds.left, -bounds.top);
|
||
event.xexpose.x = (**gDamageRgn).rgnBBox.left;
|
||
event.xexpose.y = (**gDamageRgn).rgnBBox.top;
|
||
event.xexpose.width = (**gDamageRgn).rgnBBox.right -
|
||
(**gDamageRgn).rgnBBox.left;
|
||
event.xexpose.height = (**gDamageRgn).rgnBBox.bottom -
|
||
(**gDamageRgn).rgnBBox.top;
|
||
event.xexpose.count = 0;
|
||
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
|
||
for (childPtr = winPtr->childList; childPtr != NULL;
|
||
childPtr = childPtr->nextPtr) {
|
||
if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
|
||
continue;
|
||
}
|
||
|
||
GenerateUpdates(updateRgn, childPtr);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkGenerateButtonEvent --
|
||
*
|
||
* Given a global x & y position and the button key status this
|
||
* procedure generates the appropiate X button event. It also
|
||
* handles the state changes needed to implement implicit grabs.
|
||
*
|
||
* Results:
|
||
* True if event(s) are generated - false otherwise.
|
||
*
|
||
* Side effects:
|
||
* Additional events may be place on the Tk event queue.
|
||
* Grab state may also change.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
TkGenerateButtonEvent(x, y, state)
|
||
int x; /* X location of mouse */
|
||
int y; /* Y location of mouse */
|
||
unsigned int state; /* Button Key state suitable for X event */
|
||
{
|
||
WindowRef whichWin, frontWin;
|
||
Point where;
|
||
Tk_Window tkwin;
|
||
Window window;
|
||
XEvent event;
|
||
Rect bounds;
|
||
|
||
/*
|
||
* ButtonDown events will always occur in the front
|
||
* window. ButtonUp events, however, may occur anywhere
|
||
* on the screen. ButtonUp events should only be sent
|
||
* to Tk if in the front window or during an implicit grab.
|
||
*/
|
||
where.h = x;
|
||
where.v = y;
|
||
FindWindow(where, &whichWin);
|
||
frontWin = FrontWindow();
|
||
|
||
if ((frontWin == NULL) ||
|
||
(frontWin != whichWin && gRestrictWinPtr == NULL)) {
|
||
return false;
|
||
}
|
||
|
||
event.xany.send_event = False;
|
||
event.xbutton.x_root = where.h;
|
||
event.xbutton.y_root = where.v;
|
||
event.xbutton.subwindow = None;
|
||
event.xbutton.same_screen = true;
|
||
|
||
GlobalToLocal(&where);
|
||
window = TkMacGetXWindow(whichWin);
|
||
tkwin = Tk_IdToWindow(tkDisplayList->display, window);
|
||
|
||
if (tkwin == NULL) {
|
||
tkwin = gRestrictWinPtr;
|
||
} else {
|
||
tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v,
|
||
&event.xbutton.x, &event.xbutton.y);
|
||
}
|
||
|
||
if (TkPositionInTree((TkWindow *) tkwin, (TkWindow *) gGrabWinPtr) !=
|
||
TK_GRAB_IN_TREE) {
|
||
tkwin = gGrabWinPtr;
|
||
}
|
||
|
||
TkMacWinBounds((TkWindow *) tkwin, &bounds);
|
||
event.xbutton.x = where.h - bounds.left;
|
||
event.xbutton.y = where.v - bounds.top;
|
||
|
||
event.xany.serial = Tk_Display(tkwin)->request;
|
||
event.xany.display = Tk_Display(tkwin);
|
||
event.xbutton.root = XRootWindow(Tk_Display(tkwin), 0);
|
||
event.xbutton.window = Tk_WindowId(tkwin);
|
||
event.xbutton.state = state;
|
||
event.xbutton.button = Button1;
|
||
|
||
/*
|
||
* Button events will also start or end an implicit grab. Do
|
||
* different things wether we generate up or down mouse events.
|
||
*/
|
||
if (state & Button1Mask) {
|
||
event.xany.type = ButtonPress;
|
||
/*
|
||
* Set mouse capture and the restrict window if we are
|
||
* currently unrestricted.
|
||
*/
|
||
|
||
if (!gRestrictWinPtr) {
|
||
if (!gGrabWinPtr) {
|
||
gRestrictWinPtr = tkwin;
|
||
gCaptured = 1;
|
||
} else {
|
||
|
||
/*
|
||
* Make sure the new restrict window is inside the
|
||
* current grab tree.
|
||
*/
|
||
|
||
if (TkPositionInTree((TkWindow *) tkwin, (TkWindow *)
|
||
gGrabWinPtr) > 0) {
|
||
gRestrictWinPtr = tkwin;
|
||
} else {
|
||
gRestrictWinPtr = gGrabWinPtr;
|
||
}
|
||
gCaptured = 1;
|
||
}
|
||
}
|
||
} else {
|
||
event.xany.type = ButtonRelease;
|
||
|
||
/*
|
||
* The function TkMacButtonKeyState which is used to passed the
|
||
* state into this function will have incorrect information
|
||
* during a ButtonRelease event. It will report that no
|
||
* button is depressed - which is true. However, during a
|
||
* ButtonRelease event the state needs to include the button
|
||
* that *was* depressed. There for we need to set the
|
||
* Button1Mask here.
|
||
*/
|
||
event.xbutton.state |= Button1Mask;
|
||
|
||
/*
|
||
* Release the mouse capture when the last button is
|
||
* released and we aren't in a global grab.
|
||
*/
|
||
|
||
if (gGrabWinPtr == NULL) {
|
||
gCaptured = 0;
|
||
}
|
||
|
||
/*
|
||
* If we are releasing a restrict window, then we need
|
||
* to send the button event followed by mouse motion from
|
||
* the restrict window the the current mouse position.
|
||
*/
|
||
|
||
if (gRestrictWinPtr) {
|
||
if (Tk_WindowId(gRestrictWinPtr) != event.xbutton.window) {
|
||
TkChangeEventWindow(&event, (TkWindow *) gRestrictWinPtr);
|
||
}
|
||
gLastWinPtr = gRestrictWinPtr;
|
||
gRestrictWinPtr = NULL;
|
||
}
|
||
|
||
}
|
||
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* GenerateActivateEvents --
|
||
*
|
||
* Generate Activate/Deactivate and FocusIn/FocusOut events from
|
||
* a Macintosh Activate event. Note, the activate-on-foreground
|
||
* bit must be set in the SIZE flags to ensure we get
|
||
* Activate/Deactivate in addition to Susspend/Resume events.
|
||
*
|
||
* Results:
|
||
* Returns true if events were generate.
|
||
*
|
||
* Side effects:
|
||
* Queue events on Tk's event queue.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static int
|
||
GenerateActivateEvents(macEvent)
|
||
EventRecord *macEvent; /* Incoming Mac event */
|
||
{
|
||
XEvent event;
|
||
Tk_Window tkwin;
|
||
Window window;
|
||
|
||
window = TkMacGetXWindow((WindowRef) macEvent->message);
|
||
tkwin = Tk_IdToWindow(tkDisplayList->display, window);
|
||
if (tkwin == NULL) {
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
* Generate Activate and Deactivate events. This event
|
||
* is sent to every subwindow in a toplevel window.
|
||
*/
|
||
if (macEvent->modifiers & activeFlag) {
|
||
event.xany.type = ActivateNotify;
|
||
} else {
|
||
event.xany.type = DeactivateNotify;
|
||
}
|
||
|
||
event.xany.serial = tkDisplayList->display->request;
|
||
event.xany.send_event = False;
|
||
event.xany.display = tkDisplayList->display;
|
||
event.xany.window = window;
|
||
|
||
TkQueueEventForAllChildren(tkwin, &event);
|
||
|
||
/*
|
||
* Generate FocusIn and FocusOut events. This event
|
||
* is only sent to the toplevel window.
|
||
*/
|
||
if (macEvent->modifiers & activeFlag) {
|
||
event.xany.type = FocusIn;
|
||
} else {
|
||
event.xany.type = FocusOut;
|
||
}
|
||
|
||
event.xany.serial = tkDisplayList->display->request;
|
||
event.xany.send_event = False;
|
||
event.xfocus.display = tkDisplayList->display;
|
||
event.xfocus.window = window;
|
||
event.xfocus.mode = NotifyNormal;
|
||
event.xfocus.detail = NotifyDetailNone;
|
||
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* GenerateKeyEvent --
|
||
*
|
||
* Given Macintosh keyUp, keyDown & autoKey events this function
|
||
* generates the appropiate X key events.
|
||
*
|
||
* Results:
|
||
* True if event(s) are generated - false otherwise.
|
||
*
|
||
* Side effects:
|
||
* Additional events may be place on the Tk event queue.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static int
|
||
GenerateKeyEvent(macEvent)
|
||
EventRecord *macEvent; /* Incoming Mac event */
|
||
{
|
||
Point where;
|
||
Tk_Window tkwin;
|
||
XEvent event;
|
||
|
||
/*
|
||
* Tk keeps track of the current focus window. If Tk doesn't
|
||
* claim to have any focus - then we ignore the event.
|
||
*/
|
||
tkwin = (Tk_Window) tkDisplayList->focusWinPtr;
|
||
if (tkwin == NULL) {
|
||
return false;
|
||
}
|
||
|
||
event.xany.send_event = False;
|
||
event.xkey.same_screen = true;
|
||
event.xkey.subwindow = None;
|
||
event.xkey.time = TkMacGenerateTime();
|
||
event.xkey.keycode = macEvent->message;
|
||
|
||
where.v = macEvent->where.v;
|
||
where.h = macEvent->where.h;
|
||
event.xkey.x_root = where.h;
|
||
event.xkey.y_root = where.v;
|
||
GlobalToLocal(&where);
|
||
Tk_TopCoordsToWindow(tkwin, where.h, where.v,
|
||
&event.xkey.x, &event.xkey.y);
|
||
|
||
event.xany.serial = Tk_Display(tkwin)->request;
|
||
event.xkey.window = Tk_WindowId(tkwin);
|
||
event.xkey.display = Tk_Display(tkwin);
|
||
event.xkey.root = XRootWindow(Tk_Display(tkwin), 0);
|
||
event.xkey.state = TkMacButtonKeyState();
|
||
|
||
if (macEvent->what == keyDown) {
|
||
event.xany.type = KeyPress;
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
} else if (macEvent->what == keyUp) {
|
||
event.xany.type = KeyRelease;
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
} else {
|
||
/*
|
||
* Autokey events send multiple XKey events.
|
||
*
|
||
* Note: the last KeyRelease will always be missed with
|
||
* this scheme. However, most Tk scripts don't look for
|
||
* KeyUp events so we should be OK.
|
||
*/
|
||
event.xany.type = KeyRelease;
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
event.xany.type = KeyPress;
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* GeneratePollingEvents --
|
||
*
|
||
* This function polls the mouse position and generates X Motion,
|
||
* Enter & Leave events. The cursor is also updated at this
|
||
* time.
|
||
*
|
||
* Results:
|
||
* True if event(s) are generated - false otherwise.
|
||
*
|
||
* Side effects:
|
||
* Additional events may be place on the Tk event queue.
|
||
* The cursor may be changed.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static int
|
||
GeneratePollingEvents()
|
||
{
|
||
Tk_Window tkwin, rootwin;
|
||
Window window;
|
||
WindowRef whichwindow, frontWin;
|
||
Point whereLocal, whereGlobal;
|
||
Boolean inContentRgn;
|
||
short part;
|
||
int local_x, local_y;
|
||
int generatedEvents = false;
|
||
|
||
/*
|
||
* First we get the current mouse position and determine
|
||
* what Tk window the mouse is over (if any).
|
||
*/
|
||
frontWin = FrontWindow();
|
||
if (frontWin == NULL) {
|
||
return false;
|
||
}
|
||
SetPort((GrafPort *) frontWin);
|
||
|
||
GetMouse(&whereLocal);
|
||
whereGlobal = whereLocal;
|
||
LocalToGlobal(&whereGlobal);
|
||
|
||
part = FindWindow(whereGlobal, &whichwindow);
|
||
inContentRgn = (part == inContent || part == inGrow);
|
||
|
||
if ((frontWin != whichwindow) || !inContentRgn) {
|
||
tkwin = NULL;
|
||
} else {
|
||
window = TkMacGetXWindow(whichwindow);
|
||
rootwin = Tk_IdToWindow(tkDisplayList->display, window);
|
||
if (rootwin == NULL) {
|
||
tkwin = NULL;
|
||
} else {
|
||
tkwin = Tk_TopCoordsToWindow(rootwin, whereLocal.h, whereLocal.v,
|
||
&local_x, &local_y);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Then check to see if the window the mouse is positioned
|
||
* over has changed. Generate enter and leave events if it
|
||
* has. We can also generate the cursor at this time.
|
||
*/
|
||
|
||
generatedEvents = GenerateEnterLeave(tkwin, whereGlobal.h, whereGlobal.v);
|
||
UpdateCursor((TkWindow *) gLastWinPtr, whichwindow, whereLocal);
|
||
|
||
/*
|
||
* Now we generate motion events - assuming the mouse moved.
|
||
*/
|
||
|
||
if (EqualPt(gLastPointerPos, whereGlobal)) {
|
||
return generatedEvents;
|
||
} else {
|
||
generatedEvents |= GenerateMotion(tkwin, whereLocal, whereGlobal);
|
||
gLastPointerPos = whereGlobal;
|
||
}
|
||
|
||
return generatedEvents;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkMacButtonKeyState --
|
||
*
|
||
* Returns the current state of the button & modifier keys. This
|
||
* value is usually used in the XEvent structure.
|
||
*
|
||
* Results:
|
||
* A bitwise inclusive OR of a subset of the following:
|
||
* Button1Mask, ShiftMask, LockMask, ControlMask, Mod?Mask,
|
||
* Mod?Mask.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
unsigned int
|
||
TkMacButtonKeyState()
|
||
{
|
||
unsigned int state = 0;
|
||
KeyMap theKeys;
|
||
|
||
if (Button() & !gEatButtonUp) {
|
||
state |= Button1Mask;
|
||
}
|
||
|
||
GetKeys(theKeys);
|
||
|
||
if (theKeys[1] & 2) {
|
||
state |= LockMask;
|
||
}
|
||
|
||
if (theKeys[1] & 1) {
|
||
state |= ShiftMask;
|
||
}
|
||
|
||
if (theKeys[1] & 8) {
|
||
state |= ControlMask;
|
||
}
|
||
|
||
if (theKeys[1] & 32768) {
|
||
state |= Mod1Mask; /* command key */
|
||
}
|
||
|
||
if (theKeys[1] & 4) {
|
||
state |= Mod2Mask; /* option key */
|
||
}
|
||
|
||
return state;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* UpdateCursor --
|
||
*
|
||
* This function updates the cursor based on the current window the
|
||
* the cursor is over. It also generates the resize cursor for the
|
||
* resize region in the lower right hand corner of the window.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* The cursor may change shape.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static void
|
||
UpdateCursor(winPtr, whichwindow, whereLocal)
|
||
TkWindow *winPtr;
|
||
WindowRef whichwindow;
|
||
Point whereLocal;
|
||
{
|
||
WindowRef frontWin;
|
||
CursHandle cursor;
|
||
|
||
if (tkMacAppInFront == false) {
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* The cursor will change during an implicit grab only under
|
||
* a few special cases - such as bindings.
|
||
*/
|
||
if (gRestrictWinPtr != NULL) {
|
||
if (TkPositionInTree(winPtr, (TkWindow *) gRestrictWinPtr) ==
|
||
TK_GRAB_IN_TREE) {
|
||
TkUpdateCursor(winPtr);
|
||
} else {
|
||
TkUpdateCursor((TkWindow *) gRestrictWinPtr);
|
||
}
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* The cursor should be the arrow if outside the active window.
|
||
*/
|
||
frontWin = FrontWindow();
|
||
if (frontWin != whichwindow) {
|
||
TkUpdateCursor(NULL);
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* One special case is the grow region. Because a Tk window may
|
||
* not have allocated space for the grow region the grow region
|
||
* floats above the rest of the Tk window. This is shown by
|
||
* changing the cursor over the grow region. This is not needed
|
||
* if the window is not resizable or a scrollbar is growing the
|
||
* drag region for the window.
|
||
*/
|
||
if ((gGrabWinPtr == NULL) && TkMacResizable(winPtr) &&
|
||
(TkMacGetScrollbarGrowWindow(winPtr) == NULL)) {
|
||
if (whereLocal.h > (whichwindow->portRect.right - 16) &&
|
||
whereLocal.v > (whichwindow->portRect.bottom - 16)) {
|
||
cursor = (CursHandle) GetNamedResource('CURS', "\presize");
|
||
SetCursor(*cursor);
|
||
return;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Set the cursor to the value set for the given window. If
|
||
* the value is None - set to the arrow cursor
|
||
*/
|
||
TkUpdateCursor(winPtr);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* GenerateMotion --
|
||
*
|
||
* Given a Tk window and the current mouse position this
|
||
* function will generate the appropiate X Motion events.
|
||
*
|
||
* Results:
|
||
* True if event(s) are generated - false otherwise.
|
||
*
|
||
* Side effects:
|
||
* Additional events may be place on the Tk event queue.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static int
|
||
GenerateMotion(tkwin, whereLocal, whereGlobal)
|
||
Tk_Window tkwin; /* current Tk window (or NULL) */
|
||
Point whereLocal; /* current mouse position local coords */
|
||
Point whereGlobal; /* current mouse position global coords */
|
||
{
|
||
XEvent event;
|
||
int local_x, local_y;
|
||
Rect bounds;
|
||
|
||
/*
|
||
* Mouse moved events generated only when mouse is in the
|
||
* content of the front window. We also need to take into
|
||
* account any grabs that may be in effect.
|
||
*/
|
||
|
||
if (gRestrictWinPtr) {
|
||
tkwin = gRestrictWinPtr;
|
||
} else if (gGrabWinPtr && !tkwin) {
|
||
tkwin = gGrabWinPtr;
|
||
}
|
||
|
||
if (tkwin == NULL) {
|
||
return false;
|
||
}
|
||
|
||
TkMacWinBounds((TkWindow *) tkwin, &bounds);
|
||
local_x = whereLocal.h - bounds.left;
|
||
local_y = whereLocal.v - bounds.top;
|
||
|
||
event.xany.type = MotionNotify;
|
||
event.xany.serial = Tk_Display(tkwin)->request;
|
||
event.xany.send_event = False;
|
||
event.xany.display = Tk_Display(tkwin);
|
||
event.xmotion.window = Tk_WindowId(tkwin);
|
||
event.xmotion.root = XRootWindow(Tk_Display(tkwin), 0);
|
||
event.xmotion.state = TkMacButtonKeyState();
|
||
event.xmotion.subwindow = None;
|
||
event.xmotion.time = TkMacGenerateTime();
|
||
event.xmotion.x_root = whereGlobal.h;
|
||
event.xmotion.y_root = whereGlobal.v;
|
||
event.xmotion.x = local_x;
|
||
event.xmotion.y = local_y;
|
||
event.xmotion.same_screen = true;
|
||
event.xmotion.is_hint = NotifyNormal;
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* InitializeCrossingEvent --
|
||
*
|
||
* Initializes the common fields for enter/leave events.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Fills in the specified event structure.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static void
|
||
InitializeCrossingEvent(eventPtr, winPtr, x, y)
|
||
XEvent* eventPtr; /* Event structure to initialize. */
|
||
TkWindow *winPtr; /* Window to make event relative to. */
|
||
long x, y; /* Root coords of event. */
|
||
{
|
||
eventPtr->xcrossing.serial = Tk_Display(winPtr)->request;
|
||
eventPtr->xcrossing.send_event = 0;
|
||
eventPtr->xcrossing.display = winPtr->display;
|
||
eventPtr->xcrossing.root = RootWindow(winPtr->display,
|
||
winPtr->screenNum);
|
||
eventPtr->xcrossing.time = TkMacGenerateTime();
|
||
eventPtr->xcrossing.x_root = x;
|
||
eventPtr->xcrossing.y_root = y;
|
||
eventPtr->xcrossing.state = TkMacButtonKeyState();
|
||
eventPtr->xcrossing.mode = NotifyNormal;
|
||
eventPtr->xcrossing.focus = False;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* GenerateEnterLeave --
|
||
*
|
||
* Given a Tk window and the current mouse position this
|
||
* function will generate the appropiate X Enter and Leave
|
||
* events.
|
||
*
|
||
* Results:
|
||
* True if event(s) are generated - false otherwise.
|
||
*
|
||
* Side effects:
|
||
* Additional events may be place on the Tk event queue.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static int
|
||
GenerateEnterLeave(tkwin, x, y)
|
||
Tk_Window tkwin; /* current Tk window (or NULL) */
|
||
long x; /* current mouse position in */
|
||
long y; /* root coordinates */
|
||
{
|
||
int crossed = 0; /* 1 if mouse crossed a window boundary */
|
||
|
||
if (tkwin != gLastWinPtr) {
|
||
if (gRestrictWinPtr) {
|
||
int newPos, oldPos;
|
||
|
||
newPos = TkPositionInTree((TkWindow *) tkwin,
|
||
(TkWindow *) gRestrictWinPtr);
|
||
oldPos = TkPositionInTree((TkWindow *) gLastWinPtr,
|
||
(TkWindow *) gRestrictWinPtr);
|
||
|
||
/*
|
||
* Check if the mouse crossed into or out of the restrict
|
||
* window. If so, we need to generate an Enter or Leave event.
|
||
*/
|
||
|
||
if ((newPos != oldPos) && ((newPos == TK_GRAB_IN_TREE)
|
||
|| (oldPos == TK_GRAB_IN_TREE))) {
|
||
XEvent event;
|
||
|
||
InitializeCrossingEvent(&event, gRestrictWinPtr, x, y);
|
||
if (newPos == TK_GRAB_IN_TREE) {
|
||
event.type = EnterNotify;
|
||
} else {
|
||
event.type = LeaveNotify;
|
||
}
|
||
if ((oldPos == TK_GRAB_ANCESTOR)
|
||
|| (newPos == TK_GRAB_ANCESTOR)) {
|
||
event.xcrossing.detail = NotifyAncestor;
|
||
} else {
|
||
event.xcrossing.detail = NotifyVirtual;
|
||
}
|
||
TkChangeEventWindow(&event, (TkWindow *) gRestrictWinPtr);
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
}
|
||
|
||
} else {
|
||
Tk_Window targetPtr;
|
||
|
||
if ((gLastWinPtr == NULL)
|
||
|| (Tk_WindowId(gLastWinPtr) == None)) {
|
||
targetPtr = tkwin;
|
||
} else {
|
||
targetPtr = gLastWinPtr;
|
||
}
|
||
|
||
if (targetPtr && (Tk_WindowId(targetPtr) != None)) {
|
||
XEvent event;
|
||
|
||
/*
|
||
* Generate appropriate Enter/Leave events.
|
||
*/
|
||
|
||
InitializeCrossingEvent(&event, targetPtr, x, y);
|
||
|
||
TkInOutEvents(&event, (TkWindow *) gLastWinPtr,
|
||
(TkWindow *) tkwin, LeaveNotify,
|
||
EnterNotify, TCL_QUEUE_TAIL);
|
||
|
||
crossed = 1;
|
||
}
|
||
}
|
||
gLastWinPtr = tkwin;
|
||
}
|
||
|
||
return crossed;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XGrabPointer --
|
||
*
|
||
* Capture the mouse so event are reported outside of toplevels.
|
||
* Note that this is a very limited implementation that only
|
||
* supports GrabModeAsync and owner_events True.
|
||
*
|
||
* Results:
|
||
* Always returns GrabSuccess.
|
||
*
|
||
* Side effects:
|
||
* Turns on mouse capture, sets the global grab pointer, and
|
||
* clears any window restrictions.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode,
|
||
keyboard_mode, confine_to, cursor, time)
|
||
Display* display;
|
||
Window grab_window;
|
||
Bool owner_events;
|
||
unsigned int event_mask;
|
||
int pointer_mode;
|
||
int keyboard_mode;
|
||
Window confine_to;
|
||
Cursor cursor;
|
||
Time time;
|
||
{
|
||
gCaptured = 1;
|
||
gGrabWinPtr = Tk_IdToWindow(display, grab_window);
|
||
gRestrictWinPtr = NULL;
|
||
if (TkPositionInTree((TkWindow *) gLastWinPtr, (TkWindow *) gGrabWinPtr)
|
||
!= TK_GRAB_IN_TREE) {
|
||
TkUpdateCursor((TkWindow *) gGrabWinPtr);
|
||
}
|
||
return GrabSuccess;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XUngrabPointer --
|
||
*
|
||
* Release the current grab.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Releases the mouse capture.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XUngrabPointer(display, time)
|
||
Display* display;
|
||
Time time;
|
||
{
|
||
gCaptured = 0;
|
||
gGrabWinPtr = NULL;
|
||
gRestrictWinPtr = NULL;
|
||
TkUpdateCursor((TkWindow *) gLastWinPtr);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XGrabKeyboard --
|
||
*
|
||
* Simulates a keyboard grab by setting the focus.
|
||
*
|
||
* Results:
|
||
* Always returns GrabSuccess.
|
||
*
|
||
* Side effects:
|
||
* Sets the keyboard focus to the specified window.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
XGrabKeyboard(display, grab_window, owner_events, pointer_mode,
|
||
keyboard_mode, time)
|
||
Display* display;
|
||
Window grab_window;
|
||
Bool owner_events;
|
||
int pointer_mode;
|
||
int keyboard_mode;
|
||
Time time;
|
||
{
|
||
gKeyboardWinPtr = Tk_IdToWindow(display, grab_window);
|
||
return GrabSuccess;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XUngrabKeyboard --
|
||
*
|
||
* Releases the simulated keyboard grab.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Sets the keyboard focus back to the value before the grab.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XUngrabKeyboard(display, time)
|
||
Display* display;
|
||
Time time;
|
||
{
|
||
gKeyboardWinPtr = NULL;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XQueryPointer --
|
||
*
|
||
* Check the current state of the mouse. This is not a complete
|
||
* implementation of this function. It only computes the root
|
||
* coordinates and the current mask.
|
||
*
|
||
* Results:
|
||
* Sets root_x_return, root_y_return, and mask_return. Returns
|
||
* true on success.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
Bool
|
||
XQueryPointer(display, w, root_return, child_return, root_x_return,
|
||
root_y_return, win_x_return, win_y_return, mask_return)
|
||
Display* display;
|
||
Window w;
|
||
Window* root_return;
|
||
Window* child_return;
|
||
int* root_x_return;
|
||
int* root_y_return;
|
||
int* win_x_return;
|
||
int* win_y_return;
|
||
unsigned int* mask_return;
|
||
{
|
||
Point where;
|
||
|
||
GetMouse(&where);
|
||
LocalToGlobal(&where);
|
||
*root_x_return = where.h;
|
||
*root_y_return = where.v;
|
||
*mask_return = TkMacButtonKeyState();
|
||
return True;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkMacGenerateTime --
|
||
*
|
||
* Returns the total number of ticks from startup This function
|
||
* is used to generate the time of generated X events.
|
||
*
|
||
* Results:
|
||
* Returns the current time (ticks from startup).
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
Time
|
||
TkMacGenerateTime()
|
||
{
|
||
return (Time) LMGetTicks();
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkMacPointerDeadWindow --
|
||
*
|
||
* Clean up pointer module state when a window is destroyed.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* May change the grab module settings.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkMacPointerDeadWindow(winPtr)
|
||
TkWindow *winPtr;
|
||
{
|
||
if ((Tk_Window) winPtr == gLastWinPtr) {
|
||
gLastWinPtr = NULL;
|
||
}
|
||
if ((Tk_Window) winPtr == gGrabWinPtr) {
|
||
gGrabWinPtr = NULL;
|
||
}
|
||
if ((Tk_Window) winPtr == gRestrictWinPtr) {
|
||
gRestrictWinPtr = NULL;
|
||
}
|
||
if (!(gRestrictWinPtr || gGrabWinPtr)) {
|
||
gCaptured = 0;
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkMacConvertEvent --
|
||
*
|
||
* This function converts a Macintosh event into zero or more
|
||
* Tcl events.
|
||
*
|
||
* Results:
|
||
* Returns 1 if event added to Tcl queue, 0 otherwse.
|
||
*
|
||
* Side effects:
|
||
* May add events to Tcl's event queue.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
TkMacConvertEvent(eventPtr)
|
||
EventRecord *eventPtr;
|
||
{
|
||
int eventFound = false;
|
||
|
||
switch (eventPtr->what) {
|
||
case nullEvent:
|
||
if (GeneratePollingEvents()) {
|
||
eventFound = true;
|
||
}
|
||
break;
|
||
case updateEvt:
|
||
if (GenerateUpdateEvent(eventPtr)) {
|
||
eventFound = true;
|
||
}
|
||
break;
|
||
case mouseDown:
|
||
case mouseUp:
|
||
if (WindowManagerMouse(eventPtr)) {
|
||
eventFound = true;
|
||
}
|
||
break;
|
||
case autoKey:
|
||
case keyDown:
|
||
/*
|
||
* Handle menu-key events here. If it is *not*
|
||
* a menu key - just fall through to handle as a
|
||
* normal key event.
|
||
*/
|
||
if ((eventPtr->modifiers & cmdKey) == cmdKey) {
|
||
long menuResult = MenuKey(eventPtr->message & charCodeMask);
|
||
|
||
if (HiWord(menuResult) != 0) {
|
||
TkMacHandleMenuSelect(menuResult, false);
|
||
break;
|
||
}
|
||
}
|
||
case keyUp:
|
||
eventFound |= GenerateKeyEvent(eventPtr);
|
||
break;
|
||
case activateEvt:
|
||
eventFound |= GenerateActivateEvents(eventPtr);
|
||
break;
|
||
case kHighLevelEvent:
|
||
TkMacDoHLEvent(eventPtr);
|
||
/* TODO: should return true if events were placed on event queue. */
|
||
break;
|
||
case osEvt:
|
||
/*
|
||
* Do clipboard conversion.
|
||
*/
|
||
switch ((eventPtr->message & osEvtMessageMask) >> 24) {
|
||
case mouseMovedMessage:
|
||
if (GeneratePollingEvents()) {
|
||
eventFound = true;
|
||
}
|
||
break;
|
||
case suspendResumeMessage:
|
||
if (eventPtr->message & resumeFlag) {
|
||
if (eventPtr->message & convertClipboardFlag) {
|
||
TkResumeClipboard();
|
||
}
|
||
} else {
|
||
TkSuspendClipboard();
|
||
}
|
||
tkMacAppInFront = (eventPtr->message & resumeFlag);
|
||
break;
|
||
}
|
||
break;
|
||
case diskEvt:
|
||
/*
|
||
* Disk insertion.
|
||
*/
|
||
if (HiWord(eventPtr->message) != noErr) {
|
||
Point pt;
|
||
|
||
DILoad();
|
||
pt.v = pt.h = 120; /* parameter ignored in sys 7 */
|
||
DIBadMount(pt, eventPtr->message);
|
||
DIUnload();
|
||
}
|
||
break;
|
||
}
|
||
|
||
return eventFound;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* CheckEventsAvail --
|
||
*
|
||
* Checks to see if events are available on the Macintosh queue.
|
||
* This function looks for both queued events (eg. key & button)
|
||
* and generated events (update).
|
||
*
|
||
* Results:
|
||
* True is events exist, false otherwise.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static int
|
||
CheckEventsAvail()
|
||
{
|
||
QHdrPtr evPtr;
|
||
WindowPeek macWinPtr;
|
||
|
||
evPtr = GetEvQHdr();
|
||
if (evPtr->qHead != NULL) {
|
||
return true;
|
||
}
|
||
|
||
macWinPtr = (WindowPeek) FrontWindow();
|
||
while (macWinPtr != NULL) {
|
||
if (!EmptyRgn(macWinPtr->updateRgn)) {
|
||
return true;
|
||
}
|
||
macWinPtr = macWinPtr->nextWindow;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkMacWindowOffset --
|
||
*
|
||
* Determines the x and y offset from the orgin of the toplevel
|
||
* window dressing (the structure region, ie. title bar) and the
|
||
* orgin of the content area.
|
||
*
|
||
* Results:
|
||
* The x & y offset in pixels.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkMacWindowOffset(wRef, xOffset, yOffset)
|
||
WindowRef wRef;
|
||
int *xOffset;
|
||
int *yOffset;
|
||
{
|
||
OSErr err = noErr;
|
||
WindowPeek wPeek = (WindowPeek) wRef;
|
||
RgnHandle strucRgn = wPeek->strucRgn;
|
||
RgnHandle contRgn = wPeek->contRgn;
|
||
Rect strucRect, contRect;
|
||
|
||
if (!EmptyRgn(strucRgn) && !EmptyRgn(contRgn)) {
|
||
strucRect = (**strucRgn).rgnBBox;
|
||
contRect = (**contRgn).rgnBBox;
|
||
} else {
|
||
/*
|
||
* The current window's regions are not up to date.
|
||
* Probably because the window isn't visable. What we
|
||
* will do is save the old regions, have the window calculate
|
||
* what the regions should be, and then restore it self.
|
||
*/
|
||
strucRgn = NewRgn( );
|
||
contRgn = NewRgn( );
|
||
|
||
if (!strucRgn || !contRgn) {
|
||
err = MemError( );
|
||
} else {
|
||
CopyRgn(wPeek->strucRgn, strucRgn);
|
||
CopyRgn(wPeek->contRgn, contRgn);
|
||
|
||
if (!(err = TellWindowDefProcToCalcRegions(wRef))) {
|
||
strucRect = (**(wPeek->strucRgn)).rgnBBox;
|
||
contRect = (**(wPeek->contRgn)).rgnBBox;
|
||
}
|
||
|
||
CopyRgn(strucRgn, wPeek->strucRgn);
|
||
CopyRgn(contRgn, wPeek->contRgn);
|
||
}
|
||
|
||
if (contRgn) {
|
||
DisposeRgn(contRgn);
|
||
}
|
||
|
||
if (strucRgn) {
|
||
DisposeRgn(strucRgn);
|
||
}
|
||
}
|
||
|
||
if (!err) {
|
||
*xOffset = contRect.left - strucRect.left;
|
||
*yOffset = contRect.top - strucRect.top;
|
||
} else {
|
||
*xOffset = 0;
|
||
*yOffset = 0;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TellWindowDefProcToCalcRegions --
|
||
*
|
||
* Force a Macintosh window to recalculate it's content and
|
||
* structure regions.
|
||
*
|
||
* Results:
|
||
* An OS error.
|
||
*
|
||
* Side effects:
|
||
* The windows content and structure regions may be updated.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static OSErr
|
||
TellWindowDefProcToCalcRegions(wRef)
|
||
WindowRef wRef;
|
||
{
|
||
OSErr err = noErr;
|
||
SInt8 hState;
|
||
Handle wdef = ((WindowPeek) wRef)->windowDefProc;
|
||
|
||
/*
|
||
* Load and lock the window definition procedure for
|
||
* the window.
|
||
*/
|
||
hState = HGetState(wdef);
|
||
if (!(err = MemError())) {
|
||
LoadResource(wdef);
|
||
if (!(err = ResError())) {
|
||
MoveHHi(wdef);
|
||
err = MemError();
|
||
if (err == memLockedErr) {
|
||
err = noErr;
|
||
} else if (!err) {
|
||
HLock(wdef);
|
||
err = MemError();
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Assuming there are no errors we now call the window definition
|
||
* procedure to tell it to calculate the regions for the window.
|
||
*/
|
||
if (err == noErr) {
|
||
(void) CallWindowDefProc((WindowDefProcPtr) *wdef,
|
||
GetWVariant(wRef), wRef, wCalcRgns, 0);
|
||
|
||
HSetState(wdef, hState);
|
||
if (!err) {
|
||
err = MemError();
|
||
}
|
||
}
|
||
|
||
return err;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* BringWindowForward --
|
||
*
|
||
* Bring this background window to the front. We also set state
|
||
* so Tk thinks the button is currently up.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* The window is brought forward.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static void
|
||
BringWindowForward(wRef)
|
||
WindowRef wRef;
|
||
{
|
||
SelectWindow(wRef);
|
||
gEatButtonUp = true;
|
||
}
|