From 3936fed2e4bd2538177704d1624300aa7d8e52ef Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 14 May 2020 14:35:30 +0000 Subject: First concept cleanup for [d2a10a14a8] (already merged to core-8-6-branch but with a quickfix). This makes TkKeyEvent usable for all platforms, and adds a generic TkWheelEvent. So far, only adapted for X11 and Windows, still has to be modified for MacOS. --- generic/tkEvent.c | 4 +- generic/tkInt.h | 24 ++++++++++ win/tkWinKey.c | 5 +- win/tkWinMenu.c | 9 ++-- win/tkWinX.c | 140 +++++++++++++++++++++++++++--------------------------- 5 files changed, 105 insertions(+), 77 deletions(-) diff --git a/generic/tkEvent.c b/generic/tkEvent.c index 0beb8b6..a2fa293 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -1751,13 +1751,15 @@ CleanUpTkEvent( switch (eventPtr->type) { case KeyPress: case KeyRelease: { - TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr; +#if !defined(_WIN32) && !defined(MAC_OSX_TK) + TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr; if (kePtr->charValuePtr != NULL) { ckfree(kePtr->charValuePtr); kePtr->charValuePtr = NULL; kePtr->charValueLen = 0; } +#endif break; } diff --git a/generic/tkInt.h b/generic/tkInt.h index 8f958ab..fd124d5 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -850,8 +850,15 @@ typedef struct TkWindow { * but have internally generated pieces added to them. */ +#define XMaxTransChars 7 + typedef struct { XKeyEvent keyEvent; /* The real event from X11. */ +#if defined(_WIN32) || defined(MAC_OSX_TK) + char trans_chars[XMaxTransChars]; + /* translated characters */ + unsigned char nbytes; /* Length of trans_chars. */ +#else char *charValuePtr; /* A pointer to a string that holds the key's * %A substitution text (before backslash * adding), or NULL if that has not been @@ -861,8 +868,25 @@ typedef struct { * is non-NULL. */ KeySym keysym; /* Key symbol computed after input methods * have been invoked */ +#endif } TkKeyEvent; +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window it is reported relative to */ + Window root; /* root window that the event occured on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + int delta; /* delta */ + unsigned int button; /* detail */ + Bool same_screen; /* same screen flag */ +} TkWheelEvent; + /* * Flags passed to TkpMakeMenuWindow's 'transient' argument. */ diff --git a/win/tkWinKey.c b/win/tkWinKey.c index c7fa20c..4451296 100644 --- a/win/tkWinKey.c +++ b/win/tkWinKey.c @@ -102,9 +102,10 @@ TkpGetString( Tcl_DStringInit(dsPtr); if (keyEv->send_event == -1) { - if (keyEv->nbytes > 0) { + TkKeyEvent *ev = (TkKeyEvent *)keyEv; + if (ev->nbytes > 0) { Tcl_ExternalToUtfDString(TkWinGetKeyInputEncoding(), - keyEv->trans_chars, keyEv->nbytes, dsPtr); + ev->trans_chars, ev->nbytes, dsPtr); } } else if (keyEv->send_event == -3) { diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index daf32ec..c81551d 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -2229,15 +2229,16 @@ TkWinMenuKeyObjCmd( virtualKey = XKeysymToKeycode(winPtr->display, keySym); scanCode = MapVirtualKeyW(virtualKey, 0); if (0 != scanCode) { - XKeyEvent xkey = eventPtr->xkey; + union {XEvent x; TkKeyEvent tk;} xkey; + memcpy(&xkey, &eventPtr->xkey, sizeof(XEvent)); CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSKEYDOWN, virtualKey, (int) ((scanCode << 16) | (1 << 29))); - if (xkey.nbytes > 0) { - for (i = 0; i < xkey.nbytes; i++) { + if (xkey.tk.nbytes > 0) { + for (i = 0; i < xkey.tk.nbytes; i++) { CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSCHAR, - xkey.trans_chars[i], + xkey.tk.trans_chars[i], (int) ((scanCode << 16) | (1 << 29))); } } diff --git a/win/tkWinX.c b/win/tkWinX.c index 689268d..5d0f639 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -104,7 +104,7 @@ static Tcl_ThreadDataKey dataKey; static void GenerateXEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static unsigned int GetState(UINT message, WPARAM wParam, LPARAM lParam); -static void GetTranslatedKey(XKeyEvent *xkey, UINT type); +static void GetTranslatedKey(TkKeyEvent *xkey, UINT type); static void UpdateInputLanguage(int charset); static int HandleIMEComposition(HWND hwnd, LPARAM lParam); @@ -994,7 +994,7 @@ GenerateXEvent( WPARAM wParam, LPARAM lParam) { - XEvent event; + union {XEvent x; TkKeyEvent key;; TkWheelEvent wheel;} event; TkWindow *winPtr; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); @@ -1020,33 +1020,33 @@ GenerateXEvent( return; } - memset(&event, 0, sizeof(XEvent)); - event.xany.serial = winPtr->display->request++; - event.xany.send_event = False; - event.xany.display = winPtr->display; - event.xany.window = winPtr->window; + memset(&event.x, 0, sizeof(XEvent)); + event.x.xany.serial = winPtr->display->request++; + event.x.xany.send_event = False; + event.x.xany.display = winPtr->display; + event.x.xany.window = winPtr->window; switch (message) { case WM_PAINT: { PAINTSTRUCT ps; - event.type = Expose; + event.x.type = Expose; BeginPaint(hwnd, &ps); - event.xexpose.x = ps.rcPaint.left; - event.xexpose.y = ps.rcPaint.top; - event.xexpose.width = ps.rcPaint.right - ps.rcPaint.left; - event.xexpose.height = ps.rcPaint.bottom - ps.rcPaint.top; + event.x.xexpose.x = ps.rcPaint.left; + event.x.xexpose.y = ps.rcPaint.top; + event.x.xexpose.width = ps.rcPaint.right - ps.rcPaint.left; + event.x.xexpose.height = ps.rcPaint.bottom - ps.rcPaint.top; EndPaint(hwnd, &ps); - event.xexpose.count = 0; + event.x.xexpose.count = 0; break; } case WM_CLOSE: - event.type = ClientMessage; - event.xclient.message_type = + event.x.type = ClientMessage; + event.x.xclient.message_type = Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS"); - event.xclient.format = 32; - event.xclient.data.l[0] = + event.x.xclient.format = 32; + event.x.xclient.data.l[0] = Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW"); break; @@ -1082,10 +1082,10 @@ GenerateXEvent( return; } - event.xany.window = winPtr->window; - event.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut; - event.xfocus.mode = NotifyNormal; - event.xfocus.detail = NotifyNonlinear; + event.x.xany.window = winPtr->window; + event.x.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut; + event.x.xfocus.mode = NotifyNormal; + event.x.xfocus.detail = NotifyNonlinear; /* * Destroy the caret if we own it. If we are moving to another Tk @@ -1107,10 +1107,10 @@ GenerateXEvent( return; } - event.type = SelectionClear; - event.xselectionclear.selection = + event.x.type = SelectionClear; + event.x.xselectionclear.selection = Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD"); - event.xselectionclear.time = TkpGetMS(); + event.x.xselectionclear.time = TkpGetMS(); break; case WM_MOUSEWHEEL: @@ -1139,15 +1139,15 @@ GenerateXEvent( * Set up the common event fields. */ - event.xbutton.root = RootWindow(winPtr->display, winPtr->screenNum); - event.xbutton.subwindow = None; - event.xbutton.x = clientPoint.x; - event.xbutton.y = clientPoint.y; - event.xbutton.x_root = root.point.x; - event.xbutton.y_root = root.point.y; - event.xbutton.state = state; - event.xbutton.time = time; - event.xbutton.same_screen = True; + event.x.xbutton.root = RootWindow(winPtr->display, winPtr->screenNum); + event.x.xbutton.subwindow = None; + event.x.xbutton.x = clientPoint.x; + event.x.xbutton.y = clientPoint.y; + event.x.xbutton.x_root = root.point.x; + event.x.xbutton.y_root = root.point.y; + event.x.xbutton.state = state; + event.x.xbutton.time = time; + event.x.xbutton.same_screen = True; /* * Now set up event specific fields. @@ -1179,10 +1179,10 @@ GenerateXEvent( * TkpGetString. [Bug 1118340]. */ - event.type = MouseWheelEvent; - event.xany.send_event = -1; - event.xkey.nbytes = 0; - event.xkey.keycode = tsdPtr->vWheelAcc / WHEEL_DELTA * WHEEL_DELTA; + event.x.type = MouseWheelEvent; + event.x.xany.send_event = -1; + event.key.nbytes = 0; + event.wheel.delta = tsdPtr->vWheelAcc / WHEEL_DELTA * WHEEL_DELTA; tsdPtr->vWheelAcc = tsdPtr->vWheelAcc % WHEEL_DELTA; break; } @@ -1211,11 +1211,11 @@ GenerateXEvent( * TkpGetString. [Bug 1118340]. */ - event.type = MouseWheelEvent; - event.xany.send_event = -1; - event.xkey.nbytes = 0; - event.xkey.state |= ShiftMask; - event.xkey.keycode = tsdPtr->hWheelAcc / WHEEL_DELTA * WHEEL_DELTA; + event.x.type = MouseWheelEvent; + event.x.xany.send_event = -1; + event.key.nbytes = 0; + event.x.xkey.state |= ShiftMask; + event.wheel.delta = tsdPtr->hWheelAcc / WHEEL_DELTA * WHEEL_DELTA; tsdPtr->hWheelAcc = tsdPtr->hWheelAcc % WHEEL_DELTA; break; } @@ -1229,10 +1229,10 @@ GenerateXEvent( * MBCS characters that came from the TranslateMessage call. */ - event.type = KeyPress; - event.xany.send_event = -1; - event.xkey.keycode = wParam; - GetTranslatedKey(&event.xkey, (message == WM_KEYDOWN) ? WM_CHAR : + event.x.type = KeyPress; + event.x.xany.send_event = -1; + event.x.xkey.keycode = wParam; + GetTranslatedKey(&event.key, (message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR); break; @@ -1244,9 +1244,9 @@ GenerateXEvent( * WM_CHAR messages which will follow. */ - event.type = KeyRelease; - event.xkey.keycode = wParam; - event.xkey.nbytes = 0; + event.x.type = KeyRelease; + event.x.xkey.keycode = wParam; + event.key.nbytes = 0; break; case WM_CHAR: @@ -1280,9 +1280,9 @@ GenerateXEvent( * character. */ - event.type = KeyPress; - event.xany.send_event = -1; - event.xkey.keycode = 0; + event.x.type = KeyPress; + event.x.xany.send_event = -1; + event.x.xkey.keycode = 0; if ((int)wParam & 0xff00) { int ch1 = wParam & 0xffff; @@ -1295,12 +1295,12 @@ GenerateXEvent( (ch1 & 0x3ff) | 0x10000; tsdPtr->surrogateBuffer = 0; } - event.xany.send_event = -3; - event.xkey.nbytes = 0; - event.xkey.keycode = ch1; + event.x.xany.send_event = -3; + event.key.nbytes = 0; + event.x.xkey.keycode = ch1; } else { - event.xkey.nbytes = 1; - event.xkey.trans_chars[0] = (char) wParam; + event.key.nbytes = 1; + event.key.trans_chars[0] = (char) wParam; if (IsDBCSLeadByte((BYTE) wParam)) { MSG msg; @@ -1309,22 +1309,22 @@ GenerateXEvent( PM_NOREMOVE) != 0) && (msg.message == WM_CHAR)) { GetMessageW(&msg, NULL, WM_CHAR, WM_CHAR); - event.xkey.nbytes = 2; - event.xkey.trans_chars[1] = (char) msg.wParam; + event.key.nbytes = 2; + event.key.trans_chars[1] = (char) msg.wParam; } } } - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - event.type = KeyRelease; + Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL); + event.x.type = KeyRelease; break; case WM_UNICHAR: { - event.type = KeyPress; - event.xany.send_event = -3; - event.xkey.keycode = wParam; - event.xkey.nbytes = 0; - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - event.type = KeyRelease; + event.x.type = KeyPress; + event.x.xany.send_event = -3; + event.x.xkey.keycode = wParam; + event.key.nbytes = 0; + Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL); + event.x.type = KeyRelease; break; } @@ -1345,7 +1345,7 @@ GenerateXEvent( * Post the translated event to the main Tk event queue. */ - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL); } /* @@ -1447,7 +1447,7 @@ GetState( static void GetTranslatedKey( - XKeyEvent *xkey, + TkKeyEvent *xkey, UINT type) { MSG msg; @@ -1470,7 +1470,7 @@ GetTranslatedKey( */ if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) { - xkey->state = 0; + xkey->keyEvent.state = 0; } xkey->trans_chars[xkey->nbytes++] = (char) msg.wParam; -- cgit v0.12 From 41617cb3f6dc92eeb21c55eb776e0135bfa6e935 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 14 May 2020 21:46:39 +0000 Subject: Add the macOS support, using the TkWheelEvent but not the TkKeyEvent since macOS no longer needs trans_chars. --- generic/tkBind.c | 6 +++--- generic/tkInt.h | 28 ++++++++++++++-------------- macosx/tkMacOSXKeyEvent.c | 25 ++----------------------- macosx/tkMacOSXKeyboard.c | 36 ++++++++++++++++++------------------ macosx/tkMacOSXMouseEvent.c | 34 +++++++++++++++++----------------- 5 files changed, 54 insertions(+), 75 deletions(-) diff --git a/generic/tkBind.c b/generic/tkBind.c index 48f51e3..79f6cb1 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -3139,7 +3139,7 @@ ExpandPercents( break; case 'D': if (flags & WHEEL) { - SET_NUMBER((int)evPtr->xbutton.button); /* mis-use button field for this */ + SET_NUMBER(((TkWheelEvent *)evPtr)->delta); } break; case 'E': @@ -3796,7 +3796,7 @@ HandleEventGenerate( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - union { XEvent general; XVirtualEvent virtual; } event; + union { XEvent general; XVirtualEvent virtual; TkWheelEvent wheel;} event; const char *p; const char *name; @@ -4022,7 +4022,7 @@ HandleEventGenerate( return TCL_ERROR; } if (flags & WHEEL) { - event.general.xbutton.button = (unsigned)number; /* mis-use button field for this */ + event.wheel.delta = number; } else { badOpt = 1; } diff --git a/generic/tkInt.h b/generic/tkInt.h index fd124d5..64e7947 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -854,7 +854,7 @@ typedef struct TkWindow { typedef struct { XKeyEvent keyEvent; /* The real event from X11. */ -#if defined(_WIN32) || defined(MAC_OSX_TK) +#if defined(_WIN32) char trans_chars[XMaxTransChars]; /* translated characters */ unsigned char nbytes; /* Length of trans_chars. */ @@ -872,19 +872,19 @@ typedef struct { } TkKeyEvent; typedef struct { - int type; /* of event */ - unsigned long serial; /* # of last request processed by server */ - Bool send_event; /* true if this came from a SendEvent request */ - Display *display; /* Display the event was read from */ - Window window; /* "event" window it is reported relative to */ - Window root; /* root window that the event occured on */ - Window subwindow; /* child window */ - Time time; /* milliseconds */ - int x, y; /* pointer x, y coordinates in event window */ - int x_root, y_root; /* coordinates relative to root */ - int delta; /* delta */ - unsigned int button; /* detail */ - Bool same_screen; /* same screen flag */ + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window it is reported relative to */ + Window root; /* root window that the event occured on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + int delta; /* delta */ + unsigned int state; /* detail */ + Bool same_screen; /* same screen flag */ } TkWheelEvent; /* diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index ee69c35..e0b0094 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -247,16 +247,7 @@ static NSUInteger textInputModifiers; } macKC.v.keychar = keychar; xEvent.xkey.keycode = macKC.uint; - - /* - * Set the trans_chars for keychars outside of the private-use range. - */ - setXEventPoint(&xEvent, tkwin, w); - if (IS_PRINTABLE(keychar)) { - int length = TkUniCharToUtf(keychar, xEvent.xkey.trans_chars); - xEvent.xkey.trans_chars[length] = 0; - } /* * Finally we can queue the XEvent, inserting a KeyRelease before a @@ -351,26 +342,18 @@ static NSUInteger textInputModifiers; * represented by a sequence of two 16-bit "surrogates". We record this in * the XEvent by setting the low order 21-bits of the keycode to the UCS-32 * value value of the character and the virtual keycode in the high order - * byte to the special value NON_BMP. In principle we could set the - * trans_chars string to the UTF-8 string for the non-BMP character. - * However, that will not work when TCL_UTF_MAX is set to 3, as is the case - * for Tcl 8.6. A workaround used internally by Tcl 8.6 is to encode each - * surrogate as a 3-byte sequence using the UTF-8 algorithm (ignoring the - * fact that the UTF-8 encoding specification does not allow encoding - * UTF-16 surrogates). This gives a 6-byte encoding of the non-BMP - * character which we write into the trans_chars field of the XEvent. + * byte to the special value NON_BMP. */ state = xEvent.xkey.state; for (i = 0; i < len; i++) { - unsigned int code; UniChar keychar; MacKeycode macKC = {0}; keychar = [str characterAtIndex:i]; macKC.v.keychar = keychar; if (CFStringIsSurrogateHighCharacter(keychar)) { - UniChar lowChar = [str characterAtIndex:i+1]; + UniChar lowChar = [str characterAtIndex:++i]; macKC.v.keychar = CFStringGetLongCharacterForSurrogatePair( (UniChar)keychar, lowChar); macKC.v.virtual = NON_BMP_VIRTUAL; @@ -389,10 +372,6 @@ static NSUInteger textInputModifiers; if (xEvent.xkey.state & Mod2Mask) { macKC.v.o_s |= INDEX_OPTION; } - TkUtfAtIndex(str, i, xEvent.xkey.trans_chars, &code); - if (code > 0xFFFF){ - i++; - } xEvent.xkey.keycode = macKC.uint; xEvent.xany.type = KeyPress; Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c index db693ea..5952fa3 100644 --- a/macosx/tkMacOSXKeyboard.c +++ b/macosx/tkMacOSXKeyboard.c @@ -62,15 +62,13 @@ * * When the keyboard focus is on a Tk widget which provides text input, there * are some X11 KeyPress events which cause text to be inserted. We will call - * these "printable" events. On macOS the text which should be inserted is - * contained in the xkeys.trans_chars field of a key XEvent as a - * null-terminated unicode string encoded with a special Tcl encoding. The - * value of the trans_chars string in an Xevent depends on more than the three - * items above. It may also depend on the sequence of keypresses that preceded - * the one being reported by the XEvent. For example, on macOS an - * event does not cause text to be inserted but a following event causes an - * accented 'a' to be inserted. The events in such a composition sequence, - * other than the final one, are known as "dead-key" events. + * these "printable" events. The UCS-32 character stored in the keycode field + * of an XKeyEvent depends on more than the three items above. It may also + * depend on the sequence of keypresses that preceded the one being reported by + * the XKeyEvent. For example, on macOS an event does not cause text + * to be inserted but a following event causes an accented 'a' to be + * inserted. The events in such a composition sequence, other than the final + * one, are known as "dead-key" events. * * MacOS packages the information described above in a different way. Every * meaningful effect from a key action *other than changing the state of @@ -488,11 +486,18 @@ TkpGetString( * result. */ { (void) winPtr; /*unused*/ - int ch; + MacKeycode macKC; + char utfChars[8]; + int length = 0; + + macKC.uint = eventPtr->xkey.keycode; + if (IS_PRINTABLE(macKC.v.keychar)) { + length = TkUniCharToUtf(macKC.v.keychar, utfChars); + } + utfChars[length] = 0; Tcl_DStringInit(dsPtr); - return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, - TkUtfToUniChar(eventPtr->xkey.trans_chars, &ch)); + return Tcl_DStringAppend(dsPtr, utfChars, length); } /* @@ -667,7 +672,7 @@ XKeysymToKeycode( * Modifies the XEvent. Sets the xkey.keycode to a keycode value formatted * by XKeysymToKeycode and updates the shift and option flags in * xkey.state if either of those modifiers is required to generate the - * keysym. Also fills in xkey.trans_chars for printable events. + * keysym. * *---------------------------------------------------------------------- */ @@ -718,11 +723,6 @@ TkpSetKeycodeAndState( } eventPtr->xkey.keycode = macKC.uint; eventPtr->xkey.state |= INDEX2STATE(macKC.v.o_s); - if (IS_PRINTABLE(macKC.v.keychar)) { - int length = TkUniCharToUtf(macKC.v.keychar, - eventPtr->xkey.trans_chars); - eventPtr->xkey.trans_chars[length] = 0; - } } } diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index dd50d0a..36544ec 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -275,34 +275,34 @@ enum { CGFloat delta; int coarseDelta; - XEvent xEvent; + TkWheelEvent wheelEvent; - xEvent.type = MouseWheelEvent; - xEvent.xbutton.x = local.x; - xEvent.xbutton.y = local.y; - xEvent.xbutton.x_root = global.x; - xEvent.xbutton.y_root = global.y; - xEvent.xany.send_event = false; - xEvent.xany.display = Tk_Display(tkwin); - xEvent.xany.window = Tk_WindowId(tkwin); + wheelEvent.type = MouseWheelEvent; + wheelEvent.x = local.x; + wheelEvent.y = local.y; + wheelEvent.x_root = global.x; + wheelEvent.y_root = global.y; + wheelEvent.send_event = false; + wheelEvent.display = Tk_Display(tkwin); + wheelEvent.window = Tk_WindowId(tkwin); delta = [theEvent deltaY]; if (delta != 0.0) { coarseDelta = (delta > -1.0 && delta < 1.0) ? (signbit(delta) ? -1 : 1) : lround(delta); - xEvent.xbutton.state = state; - xEvent.xkey.keycode = coarseDelta; - xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + wheelEvent.state = state; + wheelEvent.delta = coarseDelta; + wheelEvent.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); + Tk_QueueWindowEvent((XEvent *) &wheelEvent, TCL_QUEUE_TAIL); } delta = [theEvent deltaX]; if (delta != 0.0) { coarseDelta = (delta > -1.0 && delta < 1.0) ? (signbit(delta) ? -1 : 1) : lround(delta); - xEvent.xbutton.state = state | ShiftMask; - xEvent.xkey.keycode = coarseDelta; - xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + wheelEvent.state = state | ShiftMask; + wheelEvent.delta = coarseDelta; + wheelEvent.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); + Tk_QueueWindowEvent((XEvent *) &wheelEvent, TCL_QUEUE_TAIL); } } return theEvent; -- cgit v0.12 From 628f50c27564e967f89b3d16524ed5ad4a8bc140 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 14 May 2020 22:50:34 +0000 Subject: Fix the build for MSVC --- win/tkWinX.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/tkWinX.c b/win/tkWinX.c index 5d0f639..e2ad472 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -994,7 +994,7 @@ GenerateXEvent( WPARAM wParam, LPARAM lParam) { - union {XEvent x; TkKeyEvent key;; TkWheelEvent wheel;} event; + union {XEvent x; TkKeyEvent key; TkWheelEvent wheel;} event; TkWindow *winPtr; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); -- cgit v0.12 From 65a92e1ff12c799847d876490cb3a7501ce65ba6 Mon Sep 17 00:00:00 2001 From: marc_culler Date: Thu, 14 May 2020 23:07:49 +0000 Subject: Switch state and delta in TkWheelEvent so they match the layout in XKeyEvent. --- generic/tkInt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tkInt.h b/generic/tkInt.h index 64e7947..023cac4 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -882,8 +882,8 @@ typedef struct { Time time; /* milliseconds */ int x, y; /* pointer x, y coordinates in event window */ int x_root, y_root; /* coordinates relative to root */ + unsigned int state; /* key or button mask */ int delta; /* delta */ - unsigned int state; /* detail */ Bool same_screen; /* same screen flag */ } TkWheelEvent; -- cgit v0.12 From ab74779f73176b4eacf5486eb39d73e16e93771c Mon Sep 17 00:00:00 2001 From: marc_culler Date: Fri, 15 May 2020 14:19:32 +0000 Subject: Move platform-specific declarations into platform-specific header files. --- generic/tkInt.h | 30 +++++------------------------- macosx/tkMacOSXClipboard.c | 2 +- macosx/tkMacOSXFont.c | 6 +++--- macosx/tkMacOSXInt.h | 8 ++++++++ macosx/tkMacOSXPrivate.h | 2 +- unix/tkUnixInt.h | 20 ++++++++++++++++++++ win/tkWinInt.h | 13 +++++++++++++ 7 files changed, 51 insertions(+), 30 deletions(-) diff --git a/generic/tkInt.h b/generic/tkInt.h index 744844f..5cdcbef 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -846,31 +846,11 @@ typedef struct TkWindow { } TkWindow; /* - * Real definition of some events. Note that these events come from outside - * but have internally generated pieces added to them. + * Modified version of XButtonEvent which replaces the unsigned button field + * with a signed delta field to correctly reflect how MouseWheelEvents report + * the delta. */ -#define XMaxTransChars 7 - -typedef struct { - XKeyEvent keyEvent; /* The real event from X11. */ -#ifdef _WIN32 - char trans_chars[XMaxTransChars]; - /* translated characters */ - unsigned char nbytes; -#else - char *charValuePtr; /* A pointer to a string that holds the key's - * %A substitution text (before backslash - * adding), or NULL if that has not been - * computed yet. If non-NULL, this string was - * allocated with ckalloc(). */ - int charValueLen; /* Length of string in charValuePtr when that - * is non-NULL. */ - KeySym keysym; /* Key symbol computed after input methods - * have been invoked */ -#endif -} TkKeyEvent; - typedef struct { int type; /* of event */ unsigned long serial; /* # of last request processed by server */ @@ -882,8 +862,8 @@ typedef struct { Time time; /* milliseconds */ int x, y; /* pointer x, y coordinates in event window */ int x_root, y_root; /* coordinates relative to root */ - unsigned int state; /* key or button mask */ - int delta; /* delta */ + unsigned int state; /* modifier key mask */ + int delta; /* delta detail */ Bool same_screen; /* same screen flag */ } TkWheelEvent; diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c index 529b5fa..8000c4d 100644 --- a/macosx/tkMacOSXClipboard.c +++ b/macosx/tkMacOSXClipboard.c @@ -36,7 +36,7 @@ static Tk_Window clipboardOwner = NULL; for (TkClipboardBuffer *cbPtr = targetPtr->firstBufferPtr; cbPtr; cbPtr = cbPtr->nextPtr) { NSString *s = [[TKNSString alloc] - initWithTclUtfBytes:cbPtr->buffer + initWithCESU8Bytes:cbPtr->buffer length:cbPtr->length]; [string appendString:s]; [s release]; diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index 89df102..7ea3d37 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -108,7 +108,7 @@ static void DrawCharsInContext(Display *display, Drawable drawable, @implementation TKNSString -- (instancetype)initWithTclUtfBytes:(const void *)bytes +- (instancetype)initWithCESU8Bytes:(const void *)bytes length:(NSUInteger)len { if (self = [self init]) { @@ -979,7 +979,7 @@ TkpMeasureCharsInContext( if (maxLength > 32767) { maxLength = 32767; } - string = [[TKNSString alloc] initWithTclUtfBytes:source length:numBytes]; + string = [[TKNSString alloc] initWithCESU8Bytes:source length:numBytes]; if (!string) { length = 0; fit = rangeLength; @@ -1258,7 +1258,7 @@ DrawCharsInContext( !TkMacOSXSetupDrawingContext(drawable, gc, 1, &drawingContext)) { return; } - string = [[TKNSString alloc] initWithTclUtfBytes:source length:numBytes]; + string = [[TKNSString alloc] initWithCESU8Bytes:source length:numBytes]; if (!string) { return; } diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index 9cb75d2..95e7ade 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -211,6 +211,14 @@ MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin); #include "tkIntPlatDecls.h" +/* + * The size of a buffer needed to hold a single UCS-32 character + * when encoded using Tcl's internal CESU-8 encoding. + */ + +#define XMaxTransChars 7 + + #endif /* _TKMACINT */ /* diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index b5b93d5..9c726d4 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -540,7 +540,7 @@ VISIBILITY_HIDDEN NSString *_string; } @property const char *UTF8String; -- (instancetype)initWithTclUtfBytes:(const void *)bytes +- (instancetype)initWithCESU8Bytes:(const void *)bytes length:(NSUInteger)len; @end diff --git a/unix/tkUnixInt.h b/unix/tkUnixInt.h index 805f314..4ab89b4 100644 --- a/unix/tkUnixInt.h +++ b/unix/tkUnixInt.h @@ -24,6 +24,26 @@ #include "tkIntPlatDecls.h" +/* + * Platform specific extension of the XKeyEvent struct which appends a + * character string to be used for the %A percent replacement. + */ + +#define XMaxTransChars 7 + +typedef struct { + XKeyEvent keyEvent; /* The real event from X11. */ + char *charValuePtr; /* A pointer to a string that holds the key's + * %A substitution text (before backslash + * adding), or NULL if that has not been + * computed yet. If non-NULL, this string was + * allocated with ckalloc(). */ + int charValueLen; /* Length of string in charValuePtr when that + * is non-NULL. */ + KeySym keysym; /* Key symbol computed after input methods + * have been invoked */ +} TkKeyEvent; + #endif /* _TKUNIXINT */ /* diff --git a/win/tkWinInt.h b/win/tkWinInt.h index ccc57db..ed3ff12 100644 --- a/win/tkWinInt.h +++ b/win/tkWinInt.h @@ -27,6 +27,19 @@ #endif /* + * Platform specific extension of the XKeyEvent struct which appends a + * character string to be used for the %A percent replacement. + */ + +#define XMaxTransChars 7 + +typedef struct { + XKeyEvent keyEvent; /* The real event from X11. */ + char trans_chars[XMaxTransChars]; /* translated characters */ + unsigned char nbytes; /* size of trans_chars string */ +} TkKeyEvent; + +/* * Define constants missing from older Win32 SDK header files. */ -- cgit v0.12 From 623aceed37d5ea18f8f176002f5b3f9fa6968025 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 15 May 2020 15:04:42 +0000 Subject: Make sure unix includes its platform-specific header in files that use TkKeyEvent. --- generic/tkEvent.c | 10 ++++++++++ unix/tkUnixKey.c | 1 + 2 files changed, 11 insertions(+) diff --git a/generic/tkEvent.c b/generic/tkEvent.c index a2fa293..783f25b 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -15,6 +15,16 @@ #include "tkInt.h" +/* + * Include platform-specific TkKeyEvent + */ + +#if defined(_WIN32) +#include "tkWinInt.h" +#elif !defined(MAC_OSX_TK) +#include "tkUnixInt.h" +#endif + /* * There's a potential problem if a handler is deleted while it's current * (i.e. its function is executing), since Tk_HandleEvent will need to read diff --git a/unix/tkUnixKey.c b/unix/tkUnixKey.c index 3e41626..973da22 100644 --- a/unix/tkUnixKey.c +++ b/unix/tkUnixKey.c @@ -11,6 +11,7 @@ */ #include "tkInt.h" +#include "tkUnixInt.h" /* ** Bug [3607830]: Before using Xkb, it must be initialized. TkpOpenDisplay -- cgit v0.12 From 5a4f76d01da9cb86af3866cd7e387699baeaf6b0 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 15 May 2020 15:33:26 +0000 Subject: Experiment: What if we would use the trans_chars array on all platforms, X11 too? --- generic/tkEvent.c | 14 -------------- generic/tkInt.h | 18 +++++++++--------- unix/tkUnixEvent.c | 3 +-- unix/tkUnixKey.c | 17 ++++++++--------- xlib/X11/Xlib.h | 4 +++- 5 files changed, 21 insertions(+), 35 deletions(-) diff --git a/generic/tkEvent.c b/generic/tkEvent.c index a2fa293..6c2ba94 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -1749,20 +1749,6 @@ CleanUpTkEvent( XEvent *eventPtr) { switch (eventPtr->type) { - case KeyPress: - case KeyRelease: { - -#if !defined(_WIN32) && !defined(MAC_OSX_TK) - TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr; - if (kePtr->charValuePtr != NULL) { - ckfree(kePtr->charValuePtr); - kePtr->charValuePtr = NULL; - kePtr->charValueLen = 0; - } -#endif - break; - } - case VirtualEvent: { XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr; diff --git a/generic/tkInt.h b/generic/tkInt.h index d90cb0e..008b8c4 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -850,20 +850,20 @@ typedef struct TkWindow { * but have internally generated pieces added to them. */ +#ifndef XMaxTransChars +# if defined(_WIN32) +# define XMaxTransChars 15 +# else +# define XMaxTransChars 27 +# endif +#endif + typedef struct { XKeyEvent keyEvent; /* The real event from X11. */ -#ifdef _WIN32 char trans_chars[XMaxTransChars]; /* translated characters */ unsigned char nbytes; -#else - char *charValuePtr; /* A pointer to a string that holds the key's - * %A substitution text (before backslash - * adding), or NULL if that has not been - * computed yet. If non-NULL, this string was - * allocated with ckalloc(). */ - int charValueLen; /* Length of string in charValuePtr when that - * is non-NULL. */ +#if !defined(_WIN32) KeySym keysym; /* Key symbol computed after input methods * have been invoked */ #endif diff --git a/unix/tkUnixEvent.c b/unix/tkUnixEvent.c index 4d0b9be..dacc1f3 100644 --- a/unix/tkUnixEvent.c +++ b/unix/tkUnixEvent.c @@ -397,8 +397,7 @@ TransferXEventsToTcl( continue; } if (event.type == KeyPress || event.type == KeyRelease) { - event.k.charValuePtr = NULL; - event.k.charValueLen = 0; + event.k.nbytes = 0; event.k.keysym = NoSymbol; /* diff --git a/unix/tkUnixKey.c b/unix/tkUnixKey.c index 3e41626..7f8d8b7 100644 --- a/unix/tkUnixKey.c +++ b/unix/tkUnixKey.c @@ -119,10 +119,10 @@ TkpGetString( * If we have the value cached already, use it now. [Bug 1373712] */ - if (kePtr->charValuePtr != NULL) { - Tcl_DStringSetLength(dsPtr, kePtr->charValueLen); - memcpy(Tcl_DStringValue(dsPtr), kePtr->charValuePtr, - (unsigned) kePtr->charValueLen+1); + if (kePtr->nbytes > 0) { + Tcl_DStringSetLength(dsPtr, kePtr->nbytes); + memcpy(Tcl_DStringValue(dsPtr), kePtr->trans_chars, + (unsigned) kePtr->nbytes+1); return Tcl_DStringValue(dsPtr); } @@ -228,9 +228,8 @@ TkpGetString( */ done: - kePtr->charValuePtr = ckalloc(len + 1); - kePtr->charValueLen = len; - memcpy(kePtr->charValuePtr, Tcl_DStringValue(dsPtr), (unsigned) len + 1); + kePtr->nbytes = len; + memcpy(kePtr->trans_chars, Tcl_DStringValue(dsPtr), (unsigned) len + 1); return Tcl_DStringValue(dsPtr); } @@ -336,7 +335,7 @@ TkpGetKeySym( if (eventPtr->type == KeyPress && dispPtr && (dispPtr->flags & TK_DISPLAY_USE_IM)) { - if (kePtr->charValuePtr == NULL) { + if (kePtr->nbytes == 0) { Tcl_DString ds; TkWindow *winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, eventPtr->xany.window); @@ -345,7 +344,7 @@ TkpGetKeySym( (void) TkpGetString(winPtr, eventPtr, &ds); Tcl_DStringFree(&ds); } - if (kePtr->charValuePtr != NULL) { + if (kePtr->nbytes > 0) { return kePtr->keysym; } } diff --git a/xlib/X11/Xlib.h b/xlib/X11/Xlib.h index f3ee13d..08adfa3 100644 --- a/xlib/X11/Xlib.h +++ b/xlib/X11/Xlib.h @@ -530,7 +530,9 @@ typedef struct _XDisplay { #endif #ifndef _XEVENT_ -#define XMaxTransChars 7 +#ifdef MAC_OSX_TK +# define XMaxTransChars 27 +#endif /* * Definitions of specific events. -- cgit v0.12