tkMacOSXMouseEvent.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:30k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * tkMacOSXMouseEvent.c --
  3.  *
  4.  * This file implements functions that decode & handle mouse events
  5.  * on MacOS X.
  6.  *
  7.  * Copyright 2001, Apple Computer, Inc.
  8.  * Copyright (c) 2005-2007 Daniel A. Steffen <das@users.sourceforge.net>
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution of
  11.  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * The following terms apply to all files originating from Apple
  14.  * Computer, Inc. ("Apple") and associated with the software
  15.  * unless explicitly disclaimed in individual files.
  16.  *
  17.  *
  18.  * Apple hereby grants permission to use, copy, modify,
  19.  * distribute, and license this software and its documentation
  20.  * for any purpose, provided that existing copyright notices are
  21.  * retained in all copies and that this notice is included
  22.  * verbatim in any distributions. No written agreement, license,
  23.  * or royalty fee is required for any of the authorized
  24.  * uses. Modifications to this software may be copyrighted by
  25.  * their authors and need not follow the licensing terms
  26.  * described here, provided that the new terms are clearly
  27.  * indicated on the first page of each file where they apply.
  28.  *
  29.  *
  30.  * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE
  31.  * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
  32.  * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
  33.  * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
  34.  * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE
  35.  * POSSIBILITY OF SUCH DAMAGE.  APPLE, THE AUTHORS AND
  36.  * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
  37.  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  38.  * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS
  39.  * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE
  40.  * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
  41.  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  42.  *
  43.  * GOVERNMENT USE: If you are acquiring this software on behalf
  44.  * of the U.S. government, the Government shall have only
  45.  * "Restricted Rights" in the software and related documentation
  46.  * as defined in the Federal Acquisition Regulations (FARs) in
  47.  * Clause 52.227.19 (c) (2).  If you are acquiring the software
  48.  * on behalf of the Department of Defense, the software shall be
  49.  * classified as "Commercial Computer Software" and the
  50.  * Government shall have only "Restricted Rights" as defined in
  51.  * Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
  52.  * foregoing, the authors grant the U.S. Government and others
  53.  * acting in its behalf permission to use and distribute the
  54.  * software in accordance with the terms specified in this
  55.  * license.
  56.  *
  57.  * RCS: @(#) $Id: tkMacOSXMouseEvent.c,v 1.6.2.23 2007/12/18 18:21:30 das Exp $
  58.  */
  59. #include "tkMacOSXPrivate.h"
  60. #include "tkMacOSXWm.h"
  61. #include "tkMacOSXEvent.h"
  62. #include "tkMacOSXDebug.h"
  63. typedef struct {
  64.     WindowRef    whichWin;
  65.     WindowRef    activeNonFloating;
  66.     WindowPartCode windowPart;
  67.     unsigned int   state;
  68.     long    delta;
  69.     Window    window;
  70.     Point    global;
  71.     Point    local;
  72. } MouseEventData;
  73. /*
  74.  * Declarations of static variables used in this file.
  75.  */
  76. static int gEatButtonUp = 0;    /* 1 if we need to eat the next up event */
  77. /*
  78.  * Declarations of functions used only in this file.
  79.  */
  80. static void BringWindowForward(WindowRef wRef, int isFrontProcess,
  81. int frontWindowOnly);
  82. static int GeneratePollingEvents(MouseEventData * medPtr);
  83. static int GenerateMouseWheelEvent(MouseEventData * medPtr);
  84. static int GenerateButtonEvent(MouseEventData * medPtr);
  85. static int GenerateToolbarButtonEvent(MouseEventData * medPtr);
  86. static int HandleWindowTitlebarMouseDown(MouseEventData * medPtr, Tk_Window tkwin);
  87. static unsigned int ButtonModifiers2State(UInt32 buttonState, UInt32 keyModifiers);
  88. static Tk_Window GetGrabWindowForWindow(Tk_Window tkwin);
  89. static int TkMacOSXGetEatButtonUp(void);
  90. static void TkMacOSXSetEatButtonUp(int f);
  91. /*
  92.  *----------------------------------------------------------------------
  93.  *
  94.  * TkMacOSXProcessMouseEvent --
  95.  *
  96.  * This routine processes the event in eventPtr, and
  97.  * generates the appropriate Tk events from it.
  98.  *
  99.  * Results:
  100.  * True if event(s) are generated - false otherwise.
  101.  *
  102.  * Side effects:
  103.  * Additional events may be place on the Tk event queue.
  104.  *
  105.  *----------------------------------------------------------------------
  106.  */
  107. MODULE_SCOPE int
  108. TkMacOSXProcessMouseEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr)
  109. {
  110.     Tk_Window tkwin;
  111.     Point where, where2;
  112.     int result;
  113.     TkDisplay * dispPtr;
  114.     OSStatus err;
  115.     MouseEventData mouseEventData, * medPtr = &mouseEventData;
  116.     int isFrontProcess;
  117.     switch (eventPtr->eKind) {
  118. case kEventMouseDown:
  119. case kEventMouseUp:
  120. case kEventMouseMoved:
  121. case kEventMouseDragged:
  122. case kEventMouseWheelMoved:
  123.     break;
  124. default:
  125.     return false;
  126.     break;
  127.     }
  128.     err = ChkErr(GetEventParameter, eventPtr->eventRef,
  129.     kEventParamMouseLocation,
  130.     typeQDPoint, NULL,
  131.     sizeof(where), NULL,
  132.     &where);
  133.     if (err != noErr) {
  134. GetGlobalMouse(&where);
  135.     }
  136.     err = ChkErr(GetEventParameter, eventPtr->eventRef,
  137.     kEventParamWindowRef,
  138.     typeWindowRef, NULL,
  139.     sizeof(WindowRef), NULL,
  140.     &medPtr->whichWin);
  141.     if (err == noErr) {
  142. err = ChkErr(GetEventParameter, eventPtr->eventRef,
  143. kEventParamWindowPartCode,
  144. typeWindowPartCode, NULL,
  145. sizeof(WindowPartCode), NULL,
  146. &medPtr->windowPart);
  147.     }
  148.     if (err != noErr) {
  149. medPtr->windowPart = FindWindow(where, &medPtr->whichWin);
  150.     }
  151.     medPtr->window = TkMacOSXGetXWindow(medPtr->whichWin);
  152.     if (medPtr->whichWin != NULL && medPtr->window == None) {
  153. return false;
  154.     }
  155.     if (eventPtr->eKind == kEventMouseDown) {
  156. if (IsWindowActive(medPtr->whichWin) && IsWindowPathSelectEvent(
  157. medPtr->whichWin, eventPtr->eventRef)) {
  158.     ChkErr(WindowPathSelect, medPtr->whichWin, NULL, NULL);
  159.     return false;
  160. }
  161. if (medPtr->windowPart == inProxyIcon) {
  162.     TkMacOSXTrackingLoop(1);
  163.     err = ChkErr(TrackWindowProxyDrag, medPtr->whichWin, where);
  164.     TkMacOSXTrackingLoop(0);
  165.     if (err == errUserWantsToDragWindow) {
  166. medPtr->windowPart = inDrag;
  167.     } else {
  168. return false;
  169.     }
  170. }
  171.     }
  172.     isFrontProcess = Tk_MacOSXIsAppInFront();
  173.     if (isFrontProcess) {
  174. medPtr->state = ButtonModifiers2State(GetCurrentEventButtonState(),
  175. GetCurrentEventKeyModifiers());
  176.     } else {
  177. medPtr->state = ButtonModifiers2State(GetCurrentButtonState(),
  178. GetCurrentKeyModifiers());
  179.     }
  180.     medPtr->global = where;
  181.     err = ChkErr(GetEventParameter, eventPtr->eventRef,
  182.     kEventParamWindowMouseLocation,
  183.     typeQDPoint, NULL,
  184.     sizeof(Point), NULL,
  185.     &medPtr->local);
  186.     if (err == noErr) {
  187. if (medPtr->whichWin) {
  188.     Rect widths;
  189.     GetWindowStructureWidths(medPtr->whichWin, &widths);
  190.     medPtr->local.h -= widths.left;
  191.     medPtr->local.v -= widths.top;
  192. }
  193.     } else {
  194. medPtr->local = where;
  195. if (medPtr->whichWin) {
  196.     QDGlobalToLocalPoint(GetWindowPort(medPtr->whichWin),
  197.     &medPtr->local);
  198. }
  199.     }
  200.     medPtr->activeNonFloating = ActiveNonFloatingWindow();
  201.     dispPtr = TkGetDisplayList();
  202.     tkwin = Tk_IdToWindow(dispPtr->display, medPtr->window);
  203.     if (eventPtr->eKind != kEventMouseDown) {
  204. int res = false;
  205. switch (eventPtr->eKind) {
  206.     case kEventMouseUp:
  207. /*
  208.  * The window manager only needs to know about mouse down
  209.  * events and sometimes we need to "eat" the mouse up.
  210.  * Otherwise, we just pass the event to Tk.
  211.  */
  212. if (TkMacOSXGetEatButtonUp()) {
  213.     TkMacOSXSetEatButtonUp(false);
  214. } else {
  215.     res = GenerateButtonEvent(medPtr);
  216. }
  217. break;
  218.     case kEventMouseWheelMoved:
  219. err = ChkErr(GetEventParameter, eventPtr->eventRef,
  220. kEventParamMouseWheelDelta, typeLongInteger, NULL,
  221. sizeof(long), NULL, &medPtr->delta);
  222. if (err != noErr ) {
  223.     statusPtr->err = 1;
  224. } else {
  225.     EventMouseWheelAxis axis;
  226.     err = ChkErr(GetEventParameter, eventPtr->eventRef,
  227.     kEventParamMouseWheelAxis, typeMouseWheelAxis,
  228.     NULL, sizeof(EventMouseWheelAxis), NULL, &axis);
  229.     if (err == noErr && axis == kEventMouseWheelAxisX) {
  230.  medPtr->state |= ShiftMask;
  231.     }
  232.     res = GenerateMouseWheelEvent(medPtr);
  233. }
  234. break;
  235.     case kEventMouseMoved:
  236.     case kEventMouseDragged:
  237. res = GeneratePollingEvents(medPtr);
  238. break;
  239.     default:
  240. Tcl_Panic("Unknown mouse event !");
  241. }
  242. if (res) {
  243. statusPtr->stopProcessing = 1;
  244. }
  245. return res;
  246.     }
  247.     TkMacOSXSetEatButtonUp(false);
  248.     if (medPtr->whichWin) {
  249. /*
  250.  * We got a mouse down in a window
  251.  * See if this is the activate click
  252.  * This click moves the window forward. We don't want
  253.  * the corresponding mouse-up to be reported to the application
  254.  * or else it will mess up some Tk scripts.
  255.  */
  256. if (!(TkpIsWindowFloating(medPtr->whichWin))
  257. && (medPtr->whichWin != medPtr->activeNonFloating
  258. || !isFrontProcess)) {
  259.     int frontWindowOnly = 1;
  260.     int cmdDragGrow = ((medPtr->windowPart == inDrag ||
  261.     medPtr->windowPart == inGrow) && medPtr->state & Mod1Mask);
  262.     if (!cmdDragGrow) {
  263. Tk_Window grabWin = GetGrabWindowForWindow(tkwin);
  264. frontWindowOnly = !grabWin;
  265. if (grabWin && grabWin != tkwin) {
  266.     TkMacOSXSetEatButtonUp(true);
  267.     BringWindowForward(TkMacOSXDrawableWindow(
  268.     ((TkWindow*)grabWin)->window), isFrontProcess,
  269.     frontWindowOnly);
  270.     return false;
  271. }
  272.     }
  273.     /*
  274.      * Clicks in the titlebar widgets are handled without bringing the
  275.      * window forward.
  276.      */
  277.     if ((result = HandleWindowTitlebarMouseDown(medPtr, tkwin)) != -1) {
  278. statusPtr->stopProcessing = 1;
  279. return result;
  280.     } else {
  281. /*
  282.  * Only windows with the kWindowNoActivatesAttribute can
  283.  * receive mouse events in the background.
  284.  */
  285. if (!(((TkWindow *)tkwin)->wmInfoPtr->attributes &
  286. kWindowNoActivatesAttribute)) {
  287.     /*
  288.      * Allow background window dragging & growing with Command
  289.      * down.
  290.      */
  291.     if (!cmdDragGrow) {
  292. TkMacOSXSetEatButtonUp(true);
  293. BringWindowForward(medPtr->whichWin, isFrontProcess,
  294. frontWindowOnly);
  295.     }
  296.     /*
  297.      * Allow dragging & growing of windows that were/are in the
  298.      * background.
  299.      */
  300.     if (!(medPtr->windowPart == inDrag ||
  301.     medPtr->windowPart == inGrow)) {
  302. return false;
  303.     }
  304. }
  305.     }
  306. } else {
  307.     if ((result = HandleWindowTitlebarMouseDown(medPtr, tkwin)) != -1) {
  308. statusPtr->stopProcessing = 1;
  309. return result;
  310.     }
  311. }
  312. switch (medPtr->windowPart) {
  313.     case inDrag: {
  314. WindowAttributes attributes;
  315. GetWindowAttributes(medPtr->whichWin, &attributes);
  316. if (!(attributes & kWindowAsyncDragAttribute)) {
  317.     TkMacOSXTrackingLoop(1);
  318.     DragWindow(medPtr->whichWin, where, NULL);
  319.     TkMacOSXTrackingLoop(0);
  320.     where2.h = where2.v = 0;
  321.     QDLocalToGlobalPoint(GetWindowPort(medPtr->whichWin),
  322.     &where2);
  323.     if (EqualPt(where, where2)) {
  324. return false;
  325.     }
  326.     return true;
  327. }
  328. break;
  329.     }
  330.     case inGrow:
  331. /*
  332.  * Generally the content region is the domain of Tk
  333.  * sub-windows. However, one exception is the grow
  334.  * region. A button down in this area will be handled
  335.  * by the window manager. Note: this means that Tk
  336.  * may not get button down events in this area!
  337.  */
  338. if (TkMacOSXGrowToplevel(medPtr->whichWin, where) == true) {
  339.     statusPtr->stopProcessing = 1;
  340.     return true;
  341. } else {
  342.     return GenerateButtonEvent(medPtr);
  343. }
  344. break;
  345.     case inContent:
  346. return GenerateButtonEvent(medPtr);
  347. break;
  348.     default:
  349. return false;
  350. break;
  351. }
  352.     }
  353.     return false;
  354. }
  355. /*
  356.  *----------------------------------------------------------------------
  357.  *
  358.  * HandleWindowTitlebarMouseDown --
  359.  *
  360.  * Handle clicks in window titlebar.
  361.  *
  362.  * Results:
  363.  * 1 if event was handled, 0 if event was not handled,
  364.  * -1 if MouseDown was not in window titlebar.
  365.  *
  366.  * Side effects:
  367.  * Additional events may be place on the Tk event queue.
  368.  *
  369.  *----------------------------------------------------------------------
  370.  */
  371. int
  372. HandleWindowTitlebarMouseDown(MouseEventData * medPtr, Tk_Window tkwin)
  373. {
  374.     int result = INT_MAX;
  375.     switch (medPtr->windowPart) {
  376. case inGoAway:
  377. case inCollapseBox:
  378. case inZoomIn:
  379. case inZoomOut:
  380. case inToolbarButton:
  381.     if (!IsWindowActive(medPtr->whichWin)) {
  382. WindowRef frontWindow = FrontNonFloatingWindow();
  383. WindowModality frontWindowModality = kWindowModalityNone;
  384. if (frontWindow && frontWindow != medPtr->whichWin) {
  385.     ChkErr(GetWindowModality, frontWindow,
  386.     &frontWindowModality, NULL);
  387. }
  388. if (frontWindowModality == kWindowModalityAppModal) {
  389.     result  = 0;
  390. }
  391.     }
  392.     break;
  393. default:
  394.     result = -1;
  395.     break;
  396.     }
  397.     
  398.     if (result == INT_MAX) {
  399. result = 0;
  400. TkMacOSXTrackingLoop(1);
  401. switch (medPtr->windowPart) {
  402.     case inGoAway:
  403. if (TrackGoAway(medPtr->whichWin, medPtr->global) && tkwin) {
  404.     TkGenWMDestroyEvent(tkwin);
  405.     result = 1;
  406. }
  407. break;
  408.     case inCollapseBox:
  409. if (TrackBox(medPtr->whichWin, medPtr->global,
  410. medPtr->windowPart) && tkwin) {
  411.     TkpWmSetState((TkWindow *)tkwin, IconicState);
  412.     result = 1;
  413. }
  414. break;
  415.     case inZoomIn:
  416.     case inZoomOut:
  417. if (TrackBox(medPtr->whichWin, medPtr->global,
  418. medPtr->windowPart)) {
  419.     result = TkMacOSXZoomToplevel(medPtr->whichWin,
  420.     medPtr->windowPart);
  421. }
  422. break;
  423.     case inToolbarButton:
  424. if (TrackBox(medPtr->whichWin, medPtr->global,
  425. medPtr->windowPart)) {
  426.     result = GenerateToolbarButtonEvent(medPtr);
  427. }
  428. break;
  429. }
  430. TkMacOSXTrackingLoop(0);
  431.     }
  432.     return result;
  433. }
  434. /*
  435.  *----------------------------------------------------------------------
  436.  *
  437.  * GeneratePollingEvents --
  438.  *
  439.  * This function polls the mouse position and generates X Motion,
  440.  * Enter & Leave events. The cursor is also updated at this
  441.  * time.
  442.  *
  443.  * Results:
  444.  * True if event(s) are generated - false otherwise.
  445.  *
  446.  * Side effects:
  447.  * Additional events may be place on the Tk event queue.
  448.  * The cursor may be changed.
  449.  *
  450.  *----------------------------------------------------------------------
  451.  */
  452. static int
  453. GeneratePollingEvents(MouseEventData * medPtr)
  454. {
  455.     Tk_Window tkwin, rootwin, grabWin;
  456.     int local_x, local_y;
  457.     TkDisplay *dispPtr;
  458.     grabWin = TkMacOSXGetCapture();
  459.     if ((!TkpIsWindowFloating(medPtr->whichWin)
  460.     && (medPtr->activeNonFloating != medPtr->whichWin))) {
  461. /*
  462.  * If the window for this event is not floating, and is not the
  463.  * active non-floating window, don't generate polling events.
  464.  * We don't send events to backgrounded windows. So either send
  465.  * it to the grabWin, or NULL if there is no grabWin.
  466.  */
  467. tkwin = grabWin;
  468.     } else {
  469. /*
  470.  * First check whether the toplevel containing this mouse
  471.  * event is the grab window. If not, then send the event
  472.  * to the grab window. Otherwise, set tkWin to the subwindow
  473.  * which most closely contains the mouse event.
  474.  */
  475. dispPtr = TkGetDisplayList();
  476. rootwin = Tk_IdToWindow(dispPtr->display, medPtr->window);
  477. if ((rootwin == NULL)
  478. || ((grabWin != NULL) && (rootwin != grabWin))) {
  479.     tkwin = grabWin;
  480. } else {
  481.     tkwin = Tk_TopCoordsToWindow(rootwin,
  482.     medPtr->local.h, medPtr->local.v,
  483.     &local_x, &local_y);
  484. }
  485.     }
  486.     /*
  487.      * The following call will generate the appropiate X events and
  488.      * adjust any state that Tk must remember.
  489.      */
  490.     Tk_UpdatePointer(tkwin, medPtr->global.h, medPtr->global.v,
  491.     medPtr->state);
  492.     return true;
  493. }
  494. /*
  495.  *----------------------------------------------------------------------
  496.  *
  497.  * BringWindowForward --
  498.  *
  499.  * Bring this background window to the front.
  500.  *
  501.  * Results:
  502.  * None.
  503.  *
  504.  * Side effects:
  505.  * The window is brought forward.
  506.  *
  507.  *----------------------------------------------------------------------
  508.  */
  509. static void
  510. BringWindowForward(
  511.     WindowRef wRef,
  512.     int isFrontProcess,
  513.     int frontWindowOnly)
  514. {
  515.     if (wRef && !TkpIsWindowFloating(wRef) && IsValidWindowPtr(wRef)) {
  516. WindowRef frontWindow = FrontNonFloatingWindow();
  517. WindowModality frontWindowModality = kWindowModalityNone;
  518. if (frontWindow && frontWindow != wRef) {
  519.     ChkErr(GetWindowModality, frontWindow, &frontWindowModality, NULL);
  520. }
  521. if (frontWindowModality != kWindowModalityAppModal) {
  522.     Window window = TkMacOSXGetXWindow(wRef);
  523.     if (window != None) {
  524. TkDisplay *dispPtr = TkGetDisplayList();
  525. TkWindow * winPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display,
  526. window);
  527. if (winPtr && winPtr->wmInfoPtr &&
  528. winPtr->wmInfoPtr->master != None) {
  529.     TkWindow *masterWinPtr = (TkWindow *)Tk_IdToWindow(
  530.     dispPtr->display, winPtr->wmInfoPtr->master);
  531.     if (masterWinPtr && masterWinPtr->window != None &&
  532.     TkMacOSXHostToplevelExists(masterWinPtr)) {
  533. WindowRef masterMacWin =
  534. TkMacOSXDrawableWindow(masterWinPtr->window);
  535. if (masterMacWin) {
  536.     BringToFront(masterMacWin);
  537. }
  538.     }
  539. }
  540.     }
  541.     SelectWindow(wRef);
  542. } else {
  543.     frontWindowOnly = 0;
  544. }
  545.     }
  546.     if (!isFrontProcess) {
  547. ProcessSerialNumber ourPsn = {0, kCurrentProcess};
  548. ChkErr(SetFrontProcessWithOptions, &ourPsn, frontWindowOnly ?
  549.     kSetFrontProcessFrontWindowOnly : 0);
  550.     }
  551. }
  552. /*
  553.  *----------------------------------------------------------------------
  554.  *
  555.  * TkMacOSXBringWindowForward --
  556.  *
  557.  * Bring this window to the front in response to a mouse click. If
  558.  * a grab is in effect, bring the grab window to the front instead.
  559.  *
  560.  * Results:
  561.  * None.
  562.  *
  563.  * Side effects:
  564.  * The window is brought forward.
  565.  *
  566.  *----------------------------------------------------------------------
  567.  */
  568. void
  569. TkMacOSXBringWindowForward(
  570.     WindowRef wRef)
  571. {
  572.     TkDisplay *dispPtr = TkGetDisplayList();
  573.     Tk_Window tkwin = Tk_IdToWindow(dispPtr->display,TkMacOSXGetXWindow(wRef));
  574.     Tk_Window grabWin = GetGrabWindowForWindow(tkwin);
  575.     if (grabWin && grabWin != tkwin) {
  576. wRef = TkMacOSXDrawableWindow(((TkWindow*)grabWin)->window);
  577.     }
  578.     TkMacOSXSetEatButtonUp(true);
  579.     BringWindowForward(wRef, Tk_MacOSXIsAppInFront(), !grabWin);
  580. }
  581. /*
  582.  *----------------------------------------------------------------------
  583.  *
  584.  * GetGrabWindowForWindow --
  585.  *
  586.  * Get the grab window for the given window, if any.
  587.  *
  588.  * Results:
  589.  * Grab Tk_Window or None.
  590.  *
  591.  * Side effects:
  592.  * None.
  593.  *
  594.  *----------------------------------------------------------------------
  595.  */
  596. Tk_Window
  597. GetGrabWindowForWindow(
  598.     Tk_Window tkwin) 
  599. {
  600.     Tk_Window grabWin = TkMacOSXGetCapture();
  601.     if (!grabWin) {
  602. int grabState = TkGrabState((TkWindow*)tkwin);
  603. if (grabState != TK_GRAB_NONE && grabState != TK_GRAB_IN_TREE) {
  604.     grabWin = (Tk_Window) (((TkWindow*)tkwin)->dispPtr->grabWinPtr);
  605. }
  606.     }
  607.     
  608.     return grabWin;
  609. }
  610. /*
  611.  *----------------------------------------------------------------------
  612.  *
  613.  * GenerateMouseWheelEvent --
  614.  *
  615.  * Generates a "MouseWheel" Tk event.
  616.  *
  617.  * Results:
  618.  * None.
  619.  *
  620.  * Side effects:
  621.  * Places a mousewheel event on the event queue.
  622.  *
  623.  *----------------------------------------------------------------------
  624.  */
  625. static int
  626. GenerateMouseWheelEvent(MouseEventData * medPtr)
  627. {
  628.     Tk_Window tkwin, rootwin;
  629.     TkDisplay *dispPtr;
  630.     TkWindow  *winPtr;
  631.     XEvent xEvent;
  632.     dispPtr = TkGetDisplayList();
  633.     rootwin = Tk_IdToWindow(dispPtr->display, medPtr->window);
  634.     if (rootwin == NULL) {
  635. tkwin = NULL;
  636.     } else {
  637. tkwin = Tk_TopCoordsToWindow(rootwin,
  638. medPtr->local.h, medPtr->local.v,
  639. &xEvent.xbutton.x, &xEvent.xbutton.y);
  640.     }
  641.     /*
  642.      * The following call will generate the appropiate X events and
  643.      * adjust any state that Tk must remember.
  644.      */
  645.     if (!tkwin) {
  646. tkwin = TkMacOSXGetCapture();
  647.     }
  648.     if (!tkwin) {
  649. return false;
  650.     }
  651.     winPtr = (TkWindow *) tkwin;
  652.     xEvent.type = MouseWheelEvent;
  653.     xEvent.xkey.keycode = medPtr->delta;
  654.     xEvent.xbutton.x_root = medPtr->global.h;
  655.     xEvent.xbutton.y_root = medPtr->global.v;
  656.     xEvent.xbutton.state = medPtr->state;
  657.     xEvent.xany.serial = LastKnownRequestProcessed(winPtr->display);
  658.     xEvent.xany.send_event = false;
  659.     xEvent.xany.display = winPtr->display;
  660.     xEvent.xany.window = Tk_WindowId(winPtr);
  661.     Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
  662.     return true;
  663. }
  664. /*
  665.  *----------------------------------------------------------------------
  666.  *
  667.  * TkMacOSXGetEatButtonUp --
  668.  *
  669.  * Results:
  670.  * Returns the flag indicating if we need to eat the
  671.  * next mouse up event
  672.  *
  673.  * Side effects:
  674.  * None.
  675.  *
  676.  *----------------------------------------------------------------------
  677.  */
  678. int
  679. TkMacOSXGetEatButtonUp(void)
  680. {
  681.     return gEatButtonUp;
  682. }
  683. /*
  684.  *----------------------------------------------------------------------
  685.  *
  686.  * TkMacOSXSetEatButtonUp --
  687.  *
  688.  * Results:
  689.  * None.
  690.  *
  691.  * Side effects:
  692.  * Sets the flag indicating if we need to eat the
  693.  * next mouse up event
  694.  *
  695.  *----------------------------------------------------------------------
  696.  */
  697. void
  698. TkMacOSXSetEatButtonUp(int f)
  699. {
  700.     gEatButtonUp = f;
  701. }
  702. /*
  703.  *----------------------------------------------------------------------
  704.  *
  705.  * TkMacOSXKeyModifiers --
  706.  *
  707.  * Returns the current state of the modifier keys.
  708.  *
  709.  * Results:
  710.  * An OS Modifier state.
  711.  *
  712.  * Side effects:
  713.  * None.
  714.  *
  715.  *----------------------------------------------------------------------
  716.  */
  717. EventModifiers
  718. TkMacOSXModifierState(void)
  719. {
  720.     UInt32 keyModifiers;
  721.     int isFrontProcess = (GetCurrentEvent() && Tk_MacOSXIsAppInFront());
  722.     keyModifiers = isFrontProcess ? GetCurrentEventKeyModifiers() :
  723.     GetCurrentKeyModifiers();
  724.     return (EventModifiers)(keyModifiers & USHRT_MAX);
  725. }
  726. /*
  727.  *----------------------------------------------------------------------
  728.  *
  729.  * TkMacOSXButtonKeyState --
  730.  *
  731.  * Returns the current state of the button & modifier keys.
  732.  *
  733.  * Results:
  734.  * A bitwise inclusive OR of a subset of the following:
  735.  * Button1Mask, ShiftMask, LockMask, ControlMask, Mod*Mask.
  736.  *
  737.  * Side effects:
  738.  * None.
  739.  *
  740.  *----------------------------------------------------------------------
  741.  */
  742. unsigned int
  743. TkMacOSXButtonKeyState(void)
  744. {
  745.     UInt32 buttonState = 0, keyModifiers;
  746.     int isFrontProcess = (GetCurrentEvent() && Tk_MacOSXIsAppInFront());
  747.     if (!TkMacOSXGetEatButtonUp()) {
  748. buttonState = isFrontProcess ? GetCurrentEventButtonState() :
  749. GetCurrentButtonState();
  750.     }
  751.     keyModifiers = isFrontProcess ? GetCurrentEventKeyModifiers() :
  752.     GetCurrentKeyModifiers();
  753.     return ButtonModifiers2State(buttonState, keyModifiers);
  754. }
  755. /*
  756.  *----------------------------------------------------------------------
  757.  *
  758.  * ButtonModifiers2State --
  759.  *
  760.  * Converts Carbon mouse button state and modifier values into a Tk
  761.  * button/modifier state.
  762.  *
  763.  * Results:
  764.  * None.
  765.  *
  766.  * Side effects:
  767.  * None.
  768.  *
  769.  *----------------------------------------------------------------------
  770.  */
  771. static unsigned int
  772. ButtonModifiers2State(UInt32 buttonState, UInt32 keyModifiers)
  773. {
  774.     unsigned int state;
  775.     /* Tk supports at most 5 buttons */
  776.     state = (buttonState & ((1<<5) - 1)) << 8;
  777.     if (keyModifiers & alphaLock) {
  778. state |= LockMask;
  779.     }
  780.     if (keyModifiers & shiftKey) {
  781. state |= ShiftMask;
  782.     }
  783.     if (keyModifiers & controlKey) {
  784. state |= ControlMask;
  785.     }
  786.     if (keyModifiers & cmdKey) {
  787. state |= Mod1Mask; /* command key */
  788.     }
  789.     if (keyModifiers & optionKey) {
  790. state |= Mod2Mask; /* option key */
  791.     }
  792.     if (keyModifiers & kEventKeyModifierNumLockMask) {
  793. state |= Mod3Mask;
  794.     }
  795.     if (keyModifiers & kEventKeyModifierFnMask) {
  796. state |= Mod4Mask;
  797.     }
  798.     return state;
  799. }
  800. /*
  801.  *----------------------------------------------------------------------
  802.  *
  803.  * XQueryPointer --
  804.  *
  805.  * Check the current state of the mouse. This is not a complete
  806.  * implementation of this function. It only computes the root
  807.  * coordinates and the current mask.
  808.  *
  809.  * Results:
  810.  * Sets root_x_return, root_y_return, and mask_return. Returns
  811.  * true on success.
  812.  *
  813.  * Side effects:
  814.  * None.
  815.  *
  816.  *----------------------------------------------------------------------
  817.  */
  818. Bool
  819. XQueryPointer(
  820.     Display* display,
  821.     Window w,
  822.     Window* root_return,
  823.     Window* child_return,
  824.     int* root_x_return,
  825.     int* root_y_return,
  826.     int* win_x_return,
  827.     int* win_y_return,
  828.     unsigned int* mask_return)
  829. {
  830.     int getGlobal = (root_x_return && root_y_return);
  831.     int getLocal = (win_x_return && win_y_return);
  832.     if (getGlobal || getLocal) {
  833. Point where, local;
  834. OSStatus err = noErr;
  835. int gotMouseLoc = 0;
  836. EventRef ev = GetCurrentEvent();
  837. if (ev && getLocal) {
  838.     err = ChkErr(GetEventParameter, ev, kEventParamWindowMouseLocation,
  839.     typeQDPoint, NULL, sizeof(Point), NULL, &local);
  840.     gotMouseLoc = (err == noErr);
  841. }
  842. if (getGlobal || !gotMouseLoc) {
  843.     if (ev) {
  844. err = ChkErr(GetEventParameter, ev, kEventParamMouseLocation,
  845. typeQDPoint, NULL, sizeof(Point), NULL, &where);
  846.     }
  847.     if (!ev || err != noErr) {
  848. GetGlobalMouse(&where);
  849.     }
  850. }
  851. if (getLocal) {
  852.     WindowRef whichWin;
  853.     if (ev) {
  854. err = ChkErr(GetEventParameter, ev, kEventParamWindowRef,
  855. typeWindowRef, NULL, sizeof(WindowRef), NULL,
  856. &whichWin);
  857.     }
  858.     if (!ev || err != noErr) {
  859. FindWindow(where, &whichWin);
  860.     }
  861.     if (gotMouseLoc) {
  862. if (whichWin) {
  863.     Rect widths;
  864.     ChkErr(GetWindowStructureWidths, whichWin, &widths);
  865.     local.h -= widths.left;
  866.     local.v -= widths.top;
  867. }
  868.     } else {
  869. local = where;
  870. if (whichWin) {
  871.     QDGlobalToLocalPoint(GetWindowPort(whichWin), &local);
  872. }
  873.     }
  874. }
  875. if (getGlobal) {
  876.     *root_x_return = where.h;
  877.     *root_y_return = where.v;
  878. }
  879. if (getLocal) {
  880.     *win_x_return = local.h;
  881.     *win_y_return = local.v;
  882. }
  883.     }
  884.     if (mask_return) {
  885. *mask_return = TkMacOSXButtonKeyState();
  886.     }
  887.     return True;
  888. }
  889. /*
  890.  *----------------------------------------------------------------------
  891.  *
  892.  * TkGenerateButtonEventForXPointer --
  893.  *
  894.  * This procedure generates an X button event for the current
  895.  * pointer state as reported by XQueryPointer().
  896.  *
  897.  * Results:
  898.  * True if event(s) are generated - false otherwise.
  899.  *
  900.  * Side effects:
  901.  * Additional events may be place on the Tk event queue.
  902.  * Grab state may also change.
  903.  *
  904.  *----------------------------------------------------------------------
  905.  */
  906. MODULE_SCOPE int
  907. TkGenerateButtonEventForXPointer(
  908.     Window window)   /* X Window containing button event. */
  909. {
  910.     MouseEventData med;
  911.     int global_x, global_y, local_x, local_y;
  912.     bzero(&med, sizeof(MouseEventData));
  913.     XQueryPointer(NULL, None, NULL, NULL, &global_x, &global_y,
  914.     &local_x, &local_y, &med.state);
  915.     med.global.h = global_x;
  916.     med.global.v = global_y;
  917.     med.local.h = local_x;
  918.     med.local.v = local_y;
  919.     med.window = window;
  920.     med.activeNonFloating = ActiveNonFloatingWindow();
  921.     return GenerateButtonEvent(&med);
  922. }
  923. /*
  924.  *----------------------------------------------------------------------
  925.  *
  926.  * TkGenerateButtonEvent --
  927.  *
  928.  * Given a global x & y position and the button key status this
  929.  * procedure generates the appropiate X button event. It also
  930.  * handles the state changes needed to implement implicit grabs.
  931.  *
  932.  * Results:
  933.  * True if event(s) are generated - false otherwise.
  934.  *
  935.  * Side effects:
  936.  * Additional events may be place on the Tk event queue.
  937.  * Grab state may also change.
  938.  *
  939.  *----------------------------------------------------------------------
  940.  */
  941. int
  942. TkGenerateButtonEvent(
  943.     int x,   /* X location of mouse */
  944.     int y,   /* Y location of mouse */
  945.     Window window,   /* X Window containing button event. */
  946.     unsigned int state)   /* Button Key state suitable for X event */
  947. {
  948.     MouseEventData med;
  949.     bzero(&med, sizeof(MouseEventData));
  950.     med.state = state;
  951.     med.window = window;
  952.     med.global.h = x;
  953.     med.global.v = y;
  954.     FindWindow(med.global, &med.whichWin);
  955.     med.activeNonFloating = ActiveNonFloatingWindow();
  956.     med.local = med.global;
  957.     QDGlobalToLocalPoint(GetWindowPort(med.whichWin), &med.local);
  958.     return GenerateButtonEvent(&med);
  959. }
  960. /*
  961.  *----------------------------------------------------------------------
  962.  *
  963.  * GenerateButtonEvent --
  964.  *
  965.  * Generate an X button event from a MouseEventData structure.
  966.  * Handles the state changes needed to implement implicit grabs.
  967.  *
  968.  * Results:
  969.  * True if event(s) are generated - false otherwise.
  970.  *
  971.  * Side effects:
  972.  * Additional events may be place on the Tk event queue.
  973.  * Grab state may also change.
  974.  *
  975.  *----------------------------------------------------------------------
  976.  */
  977. static int
  978. GenerateButtonEvent(MouseEventData * medPtr)
  979. {
  980.     Tk_Window tkwin;
  981.     int dummy;
  982.     TkDisplay *dispPtr;
  983. #if UNUSED
  984.     /*
  985.      * ButtonDown events will always occur in the front
  986.      * window. ButtonUp events, however, may occur anywhere
  987.      * on the screen. ButtonUp events should only be sent
  988.      * to Tk if in the front window or during an implicit grab.
  989.      */
  990.     if ((medPtr->activeNonFloating == NULL)
  991.     || ((!(TkpIsWindowFloating(medPtr->whichWin))
  992.     && (medPtr->activeNonFloating != medPtr->whichWin))
  993.     && TkMacOSXGetCapture() == NULL)) {
  994. return false;
  995.     }
  996. #endif
  997.     dispPtr = TkGetDisplayList();
  998.     tkwin = Tk_IdToWindow(dispPtr->display, medPtr->window);
  999.     if (tkwin != NULL) {
  1000. tkwin = Tk_TopCoordsToWindow(tkwin, medPtr->local.h, medPtr->local.v,
  1001. &dummy, &dummy);
  1002.     }
  1003.     Tk_UpdatePointer(tkwin, medPtr->global.h, medPtr->global.v, medPtr->state);
  1004.     return true;
  1005. }
  1006. /*
  1007.  *----------------------------------------------------------------------
  1008.  *
  1009.  * GenerateToolbarButtonEvent --
  1010.  *
  1011.  * Generates a "ToolbarButton" virtual event.
  1012.  * This can be used to manage disappearing toolbars.
  1013.  *
  1014.  * Results:
  1015.  * None.
  1016.  *
  1017.  * Side effects:
  1018.  * Places a virtual event on the event queue.
  1019.  *
  1020.  *----------------------------------------------------------------------
  1021.  */
  1022. static int
  1023. GenerateToolbarButtonEvent(MouseEventData * medPtr)
  1024. {
  1025.     Tk_Window rootwin, tkwin = NULL;
  1026.     TkDisplay *dispPtr;
  1027.     TkWindow  *winPtr;
  1028.     XVirtualEvent event;
  1029.     dispPtr = TkGetDisplayList();
  1030.     rootwin = Tk_IdToWindow(dispPtr->display, medPtr->window);
  1031.     if (rootwin) {
  1032. tkwin = Tk_TopCoordsToWindow(rootwin,
  1033. medPtr->local.h, medPtr->local.v, &event.x, &event.y);
  1034.     }
  1035.     if (!tkwin) {
  1036. return true;
  1037.     }
  1038.     winPtr = (TkWindow *)tkwin;
  1039.     bzero(&event, sizeof(XVirtualEvent));
  1040.     event.type = VirtualEvent;
  1041.     event.serial = LastKnownRequestProcessed(winPtr->display);
  1042.     event.send_event = false;
  1043.     event.display = winPtr->display;
  1044.     event.event = winPtr->window;
  1045.     event.root = XRootWindow(winPtr->display, 0);
  1046.     event.subwindow = None;
  1047.     event.time = TkpGetMS();
  1048.     event.x_root = medPtr->global.h;
  1049.     event.y_root = medPtr->global.v;
  1050.     event.state = medPtr->state;
  1051.     event.same_screen = true;
  1052.     event.name = Tk_GetUid("ToolbarButton");
  1053.     Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
  1054.     return true;
  1055. }