Index: win/tkWinX.c ================================================================== --- win/tkWinX.c +++ win/tkWinX.c @@ -33,10 +33,19 @@ * The zmouse.h file includes the definition for WM_MOUSEWHEEL. */ #include +/* + * WM_MOUSEHWHEEL is normally defined by Winuser.h for Vista/2008 or later, + * but is also usable on 2000/XP if IntelliPoint drivers are installed. + */ + +#ifndef WM_MOUSEHWHEEL +#define WM_MOUSEHWHEEL 0x020E +#endif + /* * imm.h is needed by HandleIMEComposition */ #include @@ -80,12 +89,14 @@ typedef struct ThreadSpecificData { TkDisplay *winDisplay; /* TkDisplay structure that represents Windows * screen. */ int updatingClipboard; /* If 1, we are updating the clipboard. */ int surrogateBuffer; /* Buffer for first of surrogate pair. */ - DWORD wheelTickPrev; /* For high resolution wheels. */ - short wheelAcc; /* For high resolution wheels. */ + DWORD vWheelTickPrev; /* For high resolution wheels (vertical). */ + DWORD hWheelTickPrev; /* For high resolution wheels (horizontal). */ + short vWheelAcc; /* For high resolution wheels (vertical). */ + short hWheelAcc; /* For high resolution wheels (horizontal). */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * Forward declarations of functions used in this file. @@ -553,10 +564,11 @@ Screen *screen; TkWinDrawable *twdPtr; Display *display; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + DWORD initialWheelTick; if (tsdPtr->winDisplay != NULL) { if (!strcmp(tsdPtr->winDisplay->display->display_name, display_name)) { return tsdPtr->winDisplay; } else { @@ -608,12 +620,15 @@ tsdPtr->winDisplay = ckalloc(sizeof(TkDisplay)); ZeroMemory(tsdPtr->winDisplay, sizeof(TkDisplay)); tsdPtr->winDisplay->display = display; tsdPtr->updatingClipboard = FALSE; - tsdPtr->wheelTickPrev = GetTickCount(); - tsdPtr->wheelAcc = 0; + initialWheelTick = GetTickCount(); + tsdPtr->vWheelTickPrev = initialWheelTick; + tsdPtr->hWheelTickPrev = initialWheelTick; + tsdPtr->vWheelAcc = 0; + tsdPtr->hWheelAcc = 0; /* * Key map info must be available immediately, because of "send event". */ TkpInitKeymapInfo(tsdPtr->winDisplay); @@ -940,10 +955,11 @@ case WM_UNICHAR: case WM_CHAR: case WM_SYSKEYUP: case WM_KEYUP: case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: GenerateXEvent(hwnd, message, wParam, lParam); return 1; case WM_MENUCHAR: GenerateXEvent(hwnd, message, wParam, lParam); @@ -984,11 +1000,11 @@ XEvent event; TkWindow *winPtr; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (message == WM_MOUSEWHEEL) { + if ((message == WM_MOUSEWHEEL) || (message == WM_MOUSEHWHEEL)) { union {LPARAM lParam; POINTS point;} root; POINT pos; root.lParam = lParam; /* @@ -1099,10 +1115,11 @@ Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD"); event.xselectionclear.time = TkpGetMS(); break; case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: case WM_CHAR: case WM_UNICHAR: case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_KEYDOWN: @@ -1140,22 +1157,54 @@ */ switch (message) { case WM_MOUSEWHEEL: { /* - * Support for high resolution wheels. + * Support for high resolution wheels (vertical). + */ + + DWORD wheelTick = GetTickCount(); + + if (wheelTick - tsdPtr->vWheelTickPrev < 1500) { + tsdPtr->vWheelAcc += (short) HIWORD(wParam); + } else { + tsdPtr->vWheelAcc = (short) HIWORD(wParam); + } + tsdPtr->vWheelTickPrev = wheelTick; + if (abs(tsdPtr->vWheelAcc) < WHEEL_DELTA) { + return; + } + + /* + * We have invented a new X event type to handle this event. It + * still uses the KeyPress struct. However, the keycode field has + * been overloaded to hold the zDelta of the wheel. Set nbytes to + * 0 to prevent conversion of the keycode to a keysym in + * TkpGetString. [Bug 1118340]. + */ + + event.type = MouseWheelEvent; + event.xany.send_event = -1; + event.xkey.nbytes = 0; + event.xkey.keycode = tsdPtr->vWheelAcc / WHEEL_DELTA * WHEEL_DELTA; + tsdPtr->vWheelAcc = tsdPtr->vWheelAcc % WHEEL_DELTA; + break; + } + case WM_MOUSEHWHEEL: { + /* + * Support for high resolution wheels (horizontal). */ DWORD wheelTick = GetTickCount(); - if (wheelTick - tsdPtr->wheelTickPrev < 1500) { - tsdPtr->wheelAcc += (short) HIWORD(wParam); + if (wheelTick - tsdPtr->hWheelTickPrev < 1500) { + tsdPtr->hWheelAcc -= (short) HIWORD(wParam); } else { - tsdPtr->wheelAcc = (short) HIWORD(wParam); + tsdPtr->hWheelAcc = -((short) HIWORD(wParam)); } - tsdPtr->wheelTickPrev = wheelTick; - if (abs(tsdPtr->wheelAcc) < WHEEL_DELTA) { + tsdPtr->hWheelTickPrev = wheelTick; + if (abs(tsdPtr->hWheelAcc) < WHEEL_DELTA) { return; } /* * We have invented a new X event type to handle this event. It @@ -1166,12 +1215,13 @@ */ event.type = MouseWheelEvent; event.xany.send_event = -1; event.xkey.nbytes = 0; - event.xkey.keycode = tsdPtr->wheelAcc / WHEEL_DELTA * WHEEL_DELTA; - tsdPtr->wheelAcc = tsdPtr->wheelAcc % WHEEL_DELTA; + event.xkey.state |= ShiftMask; + event.xkey.keycode = tsdPtr->hWheelAcc / WHEEL_DELTA * WHEEL_DELTA; + tsdPtr->hWheelAcc = tsdPtr->hWheelAcc % WHEEL_DELTA; break; } case WM_SYSKEYDOWN: case WM_KEYDOWN: /*