📄 tkmacwindowmgr.c
字号:
/* * tkMacWindowMgr.c -- * * Implements common window manager functions for the Macintosh. * * Copyright (c) 1995-1997 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.59 97/11/20 18:56:39 */#include <Events.h>#include <Dialogs.h>#include <EPPC.h>#include <Windows.h>#include <ToolUtils.h>#include <DiskInit.h>#include <LowMem.h>#include <Timer.h>#include <Sound.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. *//* * Non-standard event types that can be passed to HandleEvent. * These are defined and used by Netscape's plugin architecture. */#define getFocusEvent (osEvt + 16)#define loseFocusEvent (osEvt + 17)#define adjustCursorEvent (osEvt + 18)/* * Declarations of static variables used in this file. */static int gEatButtonUp = 0; /* 1 if we need to eat the next * up event */static Tk_Window gGrabWinPtr = NULL; /* Current grab window, NULL if no grab. */static Tk_Window gKeyboardWinPtr = NULL; /* Current keyboard grab window. */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 *eventPtr, Window window));static int GenerateFocusEvent _ANSI_ARGS_((EventRecord *eventPtr, Window window));static int GenerateKeyEvent _ANSI_ARGS_((EventRecord *eventPtr, Window window));static int GenerateUpdateEvent _ANSI_ARGS_((EventRecord *eventPtr, Window window));static void GenerateUpdates _ANSI_ARGS_((RgnHandle updateRgn, TkWindow *winPtr));static int GeneratePollingEvents _ANSI_ARGS_((void)); static int GeneratePollingEvents2 _ANSI_ARGS_((Window window, int adjustCursor)); static OSErr TellWindowDefProcToCalcRegions _ANSI_ARGS_((WindowRef wRef));static int WindowManagerMouse _ANSI_ARGS_((EventRecord *theEvent, Window window));/* *---------------------------------------------------------------------- * * 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 intWindowManagerMouse( EventRecord *eventPtr, /* Macintosh event record. */ Window window) /* Window pointer. */{ WindowRef whichWindow, frontWindow; Tk_Window tkwin; Point where, where2; int xOffset, yOffset; short windowPart; frontWindow = FrontWindow(); /* * The window manager only needs to know about mouse down events * and sometimes we need to "eat" the mouse up. Otherwise, we * just pass the event to Tk. */ if (eventPtr->what == mouseUp) { if (gEatButtonUp) { gEatButtonUp = false; return false; } return TkGenerateButtonEvent(eventPtr->where.h, eventPtr->where.v, window, TkMacButtonKeyState()); } windowPart = FindWindow(eventPtr->where, &whichWindow); tkwin = Tk_IdToWindow(tkDisplayList->display, window); switch (windowPart) { case inSysWindow: SystemClick(eventPtr, (GrafPort *) whichWindow); return false; case inDrag: if (whichWindow != frontWindow) { if (!(eventPtr->modifiers & cmdKey)) { if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) { SysBeep(1); return false; } } } /* * Call DragWindow to move the window around. It will * also eat the mouse up event. */ SetPort((GrafPort *) whichWindow); where.h = where.v = 0; LocalToGlobal(&where); DragWindow(whichWindow, eventPtr->where, &tcl_macQdPtr->screenBits.bounds); gEatButtonUp = false; where2.h = where2.v = 0; LocalToGlobal(&where2); if (EqualPt(where, where2)) { return false; } 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 ) { /* * This click moves the window forward. We don't want * the corasponding mouse-up to be reported to the application * or else it will mess up some Tk scripts. */ if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) { SysBeep(1); return false; } BringWindowForward(whichWindow); gEatButtonUp = true; 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, window, TkMacButtonKeyState()); } } case inGoAway: if (TrackGoAway( whichWindow, eventPtr->where)) { if (tkwin == NULL) { return false; } TkGenWMDestroyEvent(tkwin); return true; } return false; case inMenuBar: { int oldMode; KeyMap theKeys; GetKeys(theKeys); oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); TkMacClearMenubarActive(); TkMacHandleMenuSelect(MenuSelect(eventPtr->where), theKeys[1] & 4); Tcl_SetServiceMode(oldMode); 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 intGenerateUpdateEvent( EventRecord *eventPtr, /* Incoming Mac event */ Window window) /* Root X window for event. */{ WindowRef macWindow; register TkWindow *winPtr; winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window); if (winPtr == NULL) { return false; } 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 (eventPtr->message != NULL) { macWindow = (WindowRef) TkMacGetDrawablePort(window); BeginUpdate(macWindow); GenerateUpdates(macWindow->visRgn, winPtr); EndUpdate(macWindow); return true; } else { /* * This event didn't come from the system. This might * occur if we are running from inside of Netscape. * In this we shouldn't call BeginUpdate as the vis region * may be NULL. */ RgnHandle rgn; Rect bounds; rgn = NewRgn(); TkMacWinBounds(winPtr, &bounds); RectRgn(rgn, &bounds); GenerateUpdates(rgn, winPtr); DisposeRgn(rgn); return true; }}/* *---------------------------------------------------------------------- * * 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 voidGenerateUpdates( 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); /* * Generate updates for the children of this window */ for (childPtr = winPtr->childList; childPtr != NULL; childPtr = childPtr->nextPtr) { if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) { continue; } GenerateUpdates(updateRgn, childPtr); } /* * Generate updates for any contained windows */ if (Tk_IsContainer(winPtr)) { childPtr = TkpGetOtherWindow(winPtr); if (childPtr != NULL && Tk_IsMapped(childPtr)) { GenerateUpdates(updateRgn, childPtr); } /* * NOTE: Here we should handle out of process embedding. */ } 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. * *---------------------------------------------------------------------- */intTkGenerateButtonEvent( int x, /* X location of mouse */ int y, /* Y location of mouse */ Window window, /* X Window containing button event. */ unsigned int state) /* Button Key state suitable for X event */{ WindowRef whichWin, frontWin; Point where; Tk_Window tkwin; int dummy; /* * 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 && gGrabWinPtr == NULL)) { return false; } tkwin = Tk_IdToWindow(tkDisplayList->display, window); GlobalToLocal(&where); if (tkwin != NULL) { tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v, &dummy, &dummy); } Tk_UpdatePointer(tkwin, x, y, state); return true;}/* *---------------------------------------------------------------------- * * GenerateActivateEvents -- * * Generate Activate/Deactivate 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 intGenerateActivateEvents( EventRecord *eventPtr, /* Incoming Mac event */ Window window) /* Root X window for event. */{ TkWindow *winPtr; winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window); if (winPtr == NULL || winPtr->window == None) { return false; } TkGenerateActivateEvents(winPtr, (eventPtr->modifiers & activeFlag) ? 1 : 0); return true;}/* *---------------------------------------------------------------------- * * XSetInputFocus -- * * Change the focus window for the application. * * Results: * None. * * Side effects: * None. * *----------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -