From 1a6ac30b077e52ba1da9ac22a8d38356ece00cec Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 6 Jan 2010 14:58:29 +0000 Subject: [Bug 2926819]: Factor out the pointer warping code a bit better and extend it to work on OSX too. --- ChangeLog | 8 ++++++++ carbon/tkMacOSXMouseEvent.c | 36 +++++++++++++++++++++++++++++++++++- generic/tkBind.c | 22 ++++++++++++---------- generic/tkInt.h | 7 +++++-- generic/tkWindow.c | 4 ++-- macosx/tkMacOSXMouseEvent.c | 36 +++++++++++++++++++++++++++++++++++- unix/tkUnixEvent.c | 18 +++++++++++++++++- win/tkWinPointer.c | 16 +++++++++++++++- 8 files changed, 129 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7824f1..2ec6e79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2010-01-06 Donal K. Fellows + * generic/tkBind.c (HandleEventGenerate, DoWarp): [Bug 2926819]: + * generic/tkInt.h (TkDisplay): Factor out the pointer + * generic/tkWindow.c (GetScreen): warping code a bit + * carbon/tkMacOSXMouseEvent.c (TkpWarpPointer): better and extend it + * macosx/tkMacOSXMouseEvent.c (TkpWarpPointer): to work on OSX too. + * unix/tkUnixEvent.c (TkpWarpPointer): + * win/tkWinPointer.c (TkpWarpPointer): + * unix/tkUnixWm.c (TkWmMapWindow): [Bug 1163496]: Allow windows to be * tests/wm.test (wm-transient-8.1): set to be transients for withdrawn masters correctly. diff --git a/carbon/tkMacOSXMouseEvent.c b/carbon/tkMacOSXMouseEvent.c index b9e54f5..a653073 100644 --- a/carbon/tkMacOSXMouseEvent.c +++ b/carbon/tkMacOSXMouseEvent.c @@ -48,7 +48,7 @@ * permission to use and distribute the software in accordance with the * terms specified in this license. * - * RCS: @(#) $Id: tkMacOSXMouseEvent.c,v 1.2 2009/06/29 14:35:01 das Exp $ + * RCS: @(#) $Id: tkMacOSXMouseEvent.c,v 1.3 2010/01/06 14:58:30 dkf Exp $ */ #include "tkMacOSXPrivate.h" @@ -1148,6 +1148,40 @@ GenerateToolbarButtonEvent( return true; } +void +TkpWarpPointer( + TkDisplay *dispPtr) +{ + CGPoint pt; + UInt32 buttonState; + + if (dispPtr->warpWindow) { + int x, y; + + Tk_GetRootCoords(dispPtr->warpWindow, &x, &y); + pt.x = x + dispPtr->warpX; + pt.y = y + dispPtr->warpY; + } else { + pt.x = dispPtr->warpX; + pt.y = dispPtr->warpY; + } + + /* + * Tell the OSX core to generate the events to make it happen. This is + * fairly ugly, but means that under most circumstances we'll register all + * the events that would normally be generated correctly. If we use + * CGWarpMouseCursorPosition instead, strange things happen. + */ + + buttonState = (GetCurrentEvent() && Tk_MacOSXIsAppInFront()) + ? GetCurrentEventButtonState() : GetCurrentButtonState(); + + CGPostMouseEvent(pt, 1 /* generate motion events */, 5, + buttonState&1 ? 1 : 0, buttonState&2 ? 1 : 0, + buttonState&4 ? 1 : 0, buttonState&8 ? 1 : 0, + buttonState&16 ? 1 : 0); +} + /* * Local Variables: * mode: c diff --git a/generic/tkBind.c b/generic/tkBind.c index 1dafaa2..4821513 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkBind.c,v 1.59 2010/01/02 22:52:38 dkf Exp $ + * RCS: @(#) $Id: tkBind.c,v 1.60 2010/01/06 14:58:30 dkf Exp $ */ #include "tkInt.h" @@ -3360,7 +3360,8 @@ HandleEventGenerate( event.general.xkey.y_root = -1; } - if (event.general.xany.type == FocusIn || event.general.xany.type == FocusOut) { + if (event.general.xany.type == FocusIn + || event.general.xany.type == FocusOut) { event.general.xany.send_event = GENERATED_FOCUS_EVENT_MAGIC; } @@ -3544,7 +3545,8 @@ HandleEventGenerate( "\"", NULL); return TCL_ERROR; } - if (!(flags & KEY) || (event.general.xkey.type == MouseWheelEvent)) { + if (!(flags & KEY) + || (event.general.xkey.type == MouseWheelEvent)) { goto badopt; } break; @@ -3817,12 +3819,14 @@ HandleEventGenerate( Tcl_DoWhenIdle(DoWarp, dispPtr); dispPtr->flags |= TK_DISPLAY_IN_WARP; } - dispPtr->warpWindow = event.general.xany.window; - dispPtr->warpX = event.general.xkey.x; - dispPtr->warpY = event.general.xkey.y; + dispPtr->warpWindow = Tk_IdToWindow(Tk_Display(mainWin), + event.general.xmotion.window); + dispPtr->warpMainwin = mainWin; + dispPtr->warpX = event.general.xmotion.x; + dispPtr->warpY = event.general.xmotion.y; } -done: + done: Tcl_ResetResult(interp); return TCL_OK; } @@ -3888,9 +3892,7 @@ DoWarp( { TkDisplay *dispPtr = clientData; - XWarpPointer(dispPtr->display, (Window) None, - (Window) dispPtr->warpWindow, 0, 0, 0, 0, - (int) dispPtr->warpX, (int) dispPtr->warpY); + TkpWarpPointer(dispPtr); XForceScreenSaver(dispPtr->display, ScreenSaverReset); dispPtr->flags &= ~TK_DISPLAY_IN_WARP; } diff --git a/generic/tkInt.h b/generic/tkInt.h index 73297d8..83ccbae 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: $Id: tkInt.h,v 1.117 2010/01/02 11:07:56 dkf Exp $ + * RCS: $Id: tkInt.h,v 1.118 2010/01/06 14:58:30 dkf Exp $ */ #ifndef _TKINT @@ -506,7 +506,9 @@ typedef struct TkDisplay { * display. */ Window mouseButtonWindow; /* Window the button state was set in, added * in Tk 8.4. */ - Window warpWindow; + Tk_Window warpWindow; + Tk_Window warpMainwin; /* For finding the root window for warping + * purposes. */ int warpX; int warpY; @@ -1242,6 +1244,7 @@ MODULE_SCOPE int TkInitTkCmd(Tcl_Interp *interp, ClientData clientData); MODULE_SCOPE int TkInitFontchooser(Tcl_Interp *interp, ClientData clientData); +MODULE_SCOPE void TkpWarpPointer(TkDisplay *dispPtr); /* * Unsupported commands. diff --git a/generic/tkWindow.c b/generic/tkWindow.c index c023507..5080cc0 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWindow.c,v 1.106 2009/12/12 00:10:45 nijtmans Exp $ + * RCS: @(#) $Id: tkWindow.c,v 1.107 2010/01/06 14:58:30 dkf Exp $ */ #include "tkInt.h" @@ -508,7 +508,7 @@ GetScreen( dispPtr->lastEventTime = CurrentTime; dispPtr->bindInfoStale = 1; dispPtr->cursorFont = None; - dispPtr->warpWindow = None; + dispPtr->warpWindow = NULL; dispPtr->multipleAtom = None; /* diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 06b35b2..b5caf5a 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXMouseEvent.c,v 1.37 2009/07/06 20:29:21 dkf Exp $ + * RCS: @(#) $Id: tkMacOSXMouseEvent.c,v 1.38 2010/01/06 14:58:30 dkf Exp $ */ #include "tkMacOSXPrivate.h" @@ -537,6 +537,40 @@ GenerateButtonEvent( return true; } +void +TkpWarpPointer( + TkDisplay *dispPtr) +{ + CGPoint pt; + UInt32 buttonState; + + if (dispPtr->warpWindow) { + int x, y; + + Tk_GetRootCoords(dispPtr->warpWindow, &x, &y); + pt.x = x + dispPtr->warpX; + pt.y = y + dispPtr->warpY; + } else { + pt.x = dispPtr->warpX; + pt.y = dispPtr->warpY; + } + + /* + * Tell the OSX core to generate the events to make it happen. This is + * fairly ugly, but means that under most circumstances we'll register all + * the events that would normally be generated correctly. If we use + * CGWarpMouseCursorPosition instead, strange things happen. + */ + + buttonState = (GetCurrentEvent() && Tk_MacOSXIsAppInFront()) + ? GetCurrentEventButtonState() : GetCurrentButtonState(); + + CGPostMouseEvent(pt, 1 /* generate motion events */, 5, + buttonState&1 ? 1 : 0, buttonState&2 ? 1 : 0, + buttonState&4 ? 1 : 0, buttonState&8 ? 1 : 0, + buttonState&16 ? 1 : 0); +} + /* * Local Variables: * mode: objc diff --git a/unix/tkUnixEvent.c b/unix/tkUnixEvent.c index 4542876..a4bdb23 100644 --- a/unix/tkUnixEvent.c +++ b/unix/tkUnixEvent.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkUnixEvent.c,v 1.34 2010/01/02 11:07:56 dkf Exp $ + * RCS: @(#) $Id: tkUnixEvent.c,v 1.35 2010/01/06 14:58:30 dkf Exp $ */ #include "tkUnixInt.h" @@ -696,6 +696,22 @@ error: } #endif /* TK_USE_INPUT_METHODS */ +void +TkpWarpPointer( + TkDisplay *dispPtr) +{ + Window w; /* Which window to warp relative to. */ + + if (dispPtr->warpWindow != NULL) { + w = Tk_WindowId(dispPtr->warpWindow); + } else { + w = RootWindow(dispPtr->display, + Tk_ScreenNumber(dispPtr->warpMainwin)); + } + XWarpPointer(dispPtr->display, None, w, 0, 0, 0, 0, + (int) dispPtr->warpX, (int) dispPtr->warpY); +} + /* * Local Variables: * mode: c diff --git a/win/tkWinPointer.c b/win/tkWinPointer.c index 6788c71..86c0f53 100644 --- a/win/tkWinPointer.c +++ b/win/tkWinPointer.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinPointer.c,v 1.10 2005/12/02 00:19:04 dkf Exp $ + * RCS: @(#) $Id: tkWinPointer.c,v 1.11 2010/01/06 14:58:30 dkf Exp $ */ #include "tkWinInt.h" @@ -362,6 +362,20 @@ XWarpPointer( GetWindowRect(Tk_GetHWND(dest_w), &r); SetCursorPos(r.left+dest_x, r.top+dest_y); } + +void +TkpWarpPointer( + TkDisplay *dispPtr) +{ + if (dispPtr->warpWindow) { + RECT r; + + GetWindowRect(Tk_GetHWND(Tk_WindowId(dispPtr->warpWindow)), &r); + SetCursorPos(r.left + dispPtr->warpX, r.top + dispPtr->warpY); + } else { + SetCursorPos(dispPtr->warpX, dispPtr->warpY); + } +} /* *---------------------------------------------------------------------- -- cgit v0.12