/[dtapublic]/projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkpointer.c
ViewVC logotype

Diff of /projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkpointer.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.69  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25