Tk Source Code

Check-in [45d655d3]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to tclconference@googlegroups.com
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix [609e0045f5]: MouseWheel binding for canvas on MacOS provides wrong values for %x %y
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:45d655d3a5253f3a5a16ad41fcda67a61e8290e1de4cca28a4204031a4ef943e
User & Date: fvogel 2019-03-14 21:01:23
Context
2019-03-15
20:28
Merge 8.6 check-in: 8d31bf8b user: jan.nijtmans tags: trunk
2019-03-14
21:05
merge trunk check-in: 76d45a3e user: fvogel tags: revised_text, tip-466
21:01
Fix [609e0045f5]: MouseWheel binding for canvas on MacOS provides wrong values for %x %y check-in: 45d655d3 user: fvogel tags: trunk
21:01
Fix [609e0045f5]: MouseWheel binding for canvas on MacOS provides wrong values for %x %y check-in: d0405802 user: fvogel tags: core-8-6-branch
2019-03-07
17:16
Fixed one more None -> NULL compiler warning. check-in: 6eaf88ea user: culler tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to macosx/tkMacOSXMouseEvent.c.

    44     44    * window that it received in a mouse event. If it receives an NSEvent with a
    45     45    * Nil window attribute then the saved window is used.
    46     46    */
    47     47   
    48     48   @implementation TKApplication(TKMouseEvent)
    49     49   - (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent
    50     50   {
    51         -#ifdef TK_MAC_DEBUG_EVENTS
    52         -    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
    53         -#endif
    54     51       NSWindow*    eventWindow = [theEvent window];
    55     52       NSEventType	 eventType = [theEvent type];
           53  +    TkWindow *winPtr, *grabWinPtr;
           54  +    Tk_Window tkwin;
    56     55   #if 0
    57     56       NSTrackingArea  *trackingArea = nil;
    58     57       NSInteger eventNumber, clickCount, buttonNumber;
    59     58   #endif
           59  +#ifdef TK_MAC_DEBUG_EVENTS
           60  +    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
           61  +#endif
    60     62       switch (eventType) {
    61     63       case NSMouseEntered:
    62     64       case NSMouseExited:
    63     65       case NSCursorUpdate:
    64     66       case NSLeftMouseDown:
    65     67       case NSLeftMouseUp:
    66     68       case NSRightMouseDown:
................................................................................
    84     86   	if (_windowWithMouse) {
    85     87   	    [_windowWithMouse release];
    86     88   	}
    87     89   	_windowWithMouse = eventWindow;
    88     90   	[_windowWithMouse retain];
    89     91       }
    90     92   
    91         -    /* Create an Xevent to add to the Tk queue. */
           93  +    /*
           94  +     * Compute the mouse position in Tk screen coordinates (global) and in
           95  +     * the Tk coordinates of its containing Tk Window.
           96  +     */
           97  +
    92     98       NSPoint global, local = [theEvent locationInWindow];
    93         -    if (eventWindow) { /* local will be in window coordinates. */
           99  +
          100  +    /*
          101  +     * If the event has no NSWindow, try using the cached NSWindow from the
          102  +     * last mouse event.
          103  +     */
          104  +
          105  +    if (eventWindow == NULL) {
          106  +	eventWindow == _windowWithMouse;
          107  +    }
          108  +    if (eventWindow) {
          109  +
          110  +	/*
          111  +	 * Set the local mouse position to its NSWindow flipped coordinates,
          112  +	 * with the origin at top left, and the global mouse position to the
          113  +	 * flipped screen coordinates.
          114  +	 */
          115  +
    94    116   	global = [eventWindow tkConvertPointToScreen: local];
    95    117   	local.y = [eventWindow frame].size.height - local.y;
    96    118   	global.y = tkMacOSXZeroScreenHeight - global.y;
    97         -    } else { /* local will be in screen coordinates. */
    98         -	if (_windowWithMouse ) {
    99         -	    eventWindow = _windowWithMouse;
   100         -	    global = local;
   101         -	    local = [eventWindow tkConvertPointFromScreen: local];
   102         -	    local.y = [eventWindow frame].size.height - local.y;
   103         -	    global.y = tkMacOSXZeroScreenHeight - global.y;
   104         -	} else { /* We have no window. Use the screen???*/
   105         -	    local.y = tkMacOSXZeroScreenHeight - local.y;
   106         -	    global = local;
   107         -	}
   108         -    }
   109         -
   110         -    TkWindow *winPtr = TkMacOSXGetTkWindow(eventWindow);
   111         -    Tk_Window tkwin = (Tk_Window) winPtr;
   112         -
   113         -    if (tkwin) {
   114         -	TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;
   115         -	if (grabWinPtr &&
   116         -	    grabWinPtr != winPtr &&
   117         -	    !winPtr->dispPtr->grabFlags && /* this means the grab is local. */
   118         -	    grabWinPtr->mainPtr == winPtr->mainPtr) {
   119         -	    return theEvent;
   120         -	}
          119  +
          120  +    } else {
          121  +
          122  +	/*
          123  +	 * As a last resort, with no NSWindow to work with, set both local and
          124  +	 * global to the screen coordinates.
          125  +	 */
          126  +
          127  +	local.y = tkMacOSXZeroScreenHeight - local.y;
          128  +	global = local;
          129  +    }
          130  +
          131  +    /*
          132  +     * Find the toplevel which corresponds to the event NSWindow.
          133  +     */
          134  +
          135  +    winPtr = TkMacOSXGetTkWindow(eventWindow);
          136  +    if (winPtr == NULL) {
          137  +	tkwin = TkMacOSXGetCapture();
          138  +	winPtr = (TkWindow *)tkwin;
   121    139       } else {
   122         -	tkwin = TkMacOSXGetCapture();
          140  +	tkwin = (Tk_Window) winPtr;
   123    141       }
   124    142       if (!tkwin) {
   125    143   	TkMacOSXDbgMsg("tkwin == NULL");
   126    144   	return theEvent; /* Give up.  No window for this event. */
   127         -    } else {
   128         -	winPtr = (TkWindow *)tkwin;
   129    145       }
   130    146   
          147  +    /*
          148  +     * If another toplevel has a grab, we ignore the event.
          149  +     */
          150  +
          151  +    grabWinPtr = winPtr->dispPtr->grabWinPtr;
          152  +    if (grabWinPtr &&
          153  +	grabWinPtr != winPtr &&
          154  +	!winPtr->dispPtr->grabFlags && /* this means the grab is local. */
          155  +	grabWinPtr->mainPtr == winPtr->mainPtr) {
          156  +	return theEvent;
          157  +    }
          158  +
          159  +    /*
          160  +     * Convert local from NSWindow flipped coordinates to the toplevel's
          161  +     * coordinates.
          162  +     */
          163  +
   131    164       local.x -= winPtr->wmInfoPtr->xInParent;
   132    165       local.y -= winPtr->wmInfoPtr->yInParent;
   133    166   
          167  +    /*
          168  +     * Find the containing Tk window, and convert local into the coordinates
          169  +     * of the Tk window.  (The converted local coordinates are only needed
          170  +     * for scrollwheel events.)
          171  +     */
          172  +
   134    173       int win_x, win_y;
   135    174       tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
          175  +    local.x = win_x;
          176  +    local.y = win_y;
          177  +
          178  +    /*
          179  +     *  Generate an XEvent for this mouse event.
          180  +     */
   136    181   
   137    182       unsigned int state = 0;
   138    183       NSInteger button = [theEvent buttonNumber];
   139    184       EventRef eventRef = (EventRef)[theEvent eventRef];
   140    185       UInt32 buttons;
   141    186       OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord,
   142    187   				     typeUInt32, NULL, sizeof(UInt32), NULL, &buttons);
................................................................................
   178    223   	state |= Mod3Mask;
   179    224       }
   180    225       if (modifiers & NSFunctionKeyMask) {
   181    226   	state |= Mod4Mask;
   182    227       }
   183    228   
   184    229       if (eventType != NSScrollWheel) {
          230  +
          231  +	/*
          232  +	 * For normal mouse events, Tk_UpdatePointer will send the XEvent.
          233  +	 */
          234  +
   185    235   #ifdef TK_MAC_DEBUG_EVENTS
   186    236   	TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state);
   187    237   #endif
   188    238   	Tk_UpdatePointer(tkwin, global.x, global.y, state);
   189         -    } else { /* handle scroll wheel event */
          239  +    } else {
          240  +
          241  +	/*
          242  +	 * For scroll wheel events we need to send the XEvent here.
          243  +	 */
          244  +	
   190    245   	CGFloat delta;
   191    246   	int coarseDelta;
   192    247   	XEvent xEvent;
   193    248   
   194    249   	xEvent.type = MouseWheelEvent;
   195    250   	xEvent.xbutton.x = local.x;
   196    251   	xEvent.xbutton.y = local.y;