From 9900ef4bf9c3880f8d01968600aa70ab2897b8a6 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 23 Aug 2016 20:16:55 +0000 Subject: Patch [6c0d7aec67] from Christian Werner on upstream Androwish to better handle unicode text input for Windows 8 by dealing with wParam VK_PACKET in WM_KEYDOWN and WM_SYSKEYDOWN events. This was observed on a Windows 8.1 tablet when the on-screen virtual keyboard is used to enter Emojis for example. The changes allow to enter Emojis when Tcl/Tk is built with TCL_UTF_MAX>3. --- win/tkWinX.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 9 deletions(-) diff --git a/win/tkWinX.c b/win/tkWinX.c index 7e25826..96a8720 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -911,15 +911,24 @@ Tk_TranslateWinEvent( Tk_PointerEvent(hwnd, (short) LOWORD(lParam), (short) HIWORD(lParam)); return 1; + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + if (wParam == VK_PACKET) { + /* + * This will trigger WM_CHAR event(s) with unicode data. + */ + *resultPtr = + PostMessageW(hwnd, message, HIWORD(lParam), LOWORD(lParam)); + return 1; + } + /* else fall through */ case WM_CLOSE: case WM_SETFOCUS: case WM_KILLFOCUS: case WM_DESTROYCLIPBOARD: case WM_UNICHAR: case WM_CHAR: - case WM_SYSKEYDOWN: case WM_SYSKEYUP: - case WM_KEYDOWN: case WM_KEYUP: case WM_MOUSEWHEEL: GenerateXEvent(hwnd, message, wParam, lParam); @@ -1197,17 +1206,50 @@ GenerateXEvent( event.type = KeyPress; event.xany.send_event = -1; event.xkey.keycode = 0; - event.xkey.nbytes = 1; - event.xkey.trans_chars[0] = (char) wParam; - - if (IsDBCSLeadByte((BYTE) wParam)) { + if ((int)wParam & 0xff00) { + int i, ch1 = wParam & 0xffff; + char buffer[TCL_UTF_MAX+1]; +#if TCL_UTF_MAX >= 4 MSG msg; - if ((PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) != 0) + if ((((int)wParam & 0xfc00) == 0xd800) + && (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) != 0) && (msg.message == WM_CHAR)) { + MSG msg; + int ch2; + GetMessage(&msg, NULL, 0, 0); - event.xkey.nbytes = 2; - event.xkey.trans_chars[1] = (char) msg.wParam; + ch2 = wParam & 0xffff; +#if TCL_UTF_MAX == 4 + event.xkey.nbytes = Tcl_UniCharToUtf(ch1, buffer); + event.xkey.nbytes += Tcl_UniCharToUtf(ch2, buffer); +#else + ch1 = ((ch1 & 0x3ff) << 10) | (ch2 & 0x3ff); + ch1 += 0x10000; + event.xkey.nbytes = Tcl_UniCharToUtf(ch1, buffer); +#endif + } else +#endif + { + event.xkey.nbytes = Tcl_UniCharToUtf(ch1, buffer); + } + for (i=0; i 0xffff) ? + 0xfffd : (int)wParam, buffer); +#else +#if TCL_UTF_MAX == 4 + if ((int)wParam > 0xffff) { + Tcl_UniChar uch; + + uch = (((int)wParam - 0x10000) >> 10) & 0x3ff; + event.xkey.nbytes = Tcl_UniCharToUtf(uch | 0xd800, buffer); + uch = ((int)wParam - 0x10000) & 0x3ff; + event.xkey.nbytes += Tcl_UniCharToUtf(uch | 0xdc00, + buffer + event.xkey.nbytes); + } else +#endif event.xkey.nbytes = Tcl_UniCharToUtf((int)wParam, buffer); +#endif for (i=0; i Date: Tue, 30 Aug 2016 10:24:09 +0000 Subject: Enhance TkpGetString() to handle Unicode characters, even when TCL_UTF_MAX==3. --- win/tkWinFont.c | 2 +- win/tkWinKey.c | 16 ++++++++++++---- win/tkWinX.c | 10 ++++++++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/win/tkWinFont.c b/win/tkWinFont.c index 9172b00..940bc10 100644 --- a/win/tkWinFont.c +++ b/win/tkWinFont.c @@ -2188,7 +2188,7 @@ FontMapLoadPage( { FontFamily *familyPtr; Tcl_Encoding encoding; - char src[TCL_UTF_MAX], buf[16]; + char src[XMaxTransChars], buf[16]; USHORT *startCount, *endCount; int i, j, bitOffset, end, segCount; diff --git a/win/tkWinKey.c b/win/tkWinKey.c index ed546f7..a49898f 100644 --- a/win/tkWinKey.c +++ b/win/tkWinKey.c @@ -102,7 +102,7 @@ TkpGetString( */ int unichar; - char buf[TCL_UTF_MAX]; + char buf[XMaxTransChars]; int len; unichar = keyEv->trans_chars[1] & 0xff; @@ -115,10 +115,18 @@ TkpGetString( } else if (keyEv->send_event == -3) { /* * Special case for WM_UNICHAR. xkey.trans_chars[] already contains a - * UTF-8 char. + * UTF-8 char, except when nbytes == 0 (then it didn't fit there). */ - Tcl_DStringAppend(dsPtr, keyEv->trans_chars, keyEv->nbytes); + if (keyEv->nbytes) { + Tcl_DStringAppend(dsPtr, keyEv->trans_chars, keyEv->nbytes); + } else if (keyEv->keycode > 0xffff) { + char buf[XMaxTransChars]; + Tcl_UniCharToUtf(((keyEv->keycode - 0x10000) >> 10) | 0xd800, buf); + Tcl_DStringAppend(dsPtr, buf, 3); + Tcl_UniCharToUtf(((keyEv->keycode - 0x10000) & 0x3ff) | 0xdc00, buf); + Tcl_DStringAppend(dsPtr, buf, 3); + } } else { /* * This is an event generated from generic code. It has no nchars or @@ -129,7 +137,7 @@ TkpGetString( if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256)) || (keysym == XK_Return) || (keysym == XK_Tab)) { - char buf[TCL_UTF_MAX]; + char buf[XMaxTransChars]; int len; len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf); diff --git a/win/tkWinX.c b/win/tkWinX.c index 2180f52..6b8bdff 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -1252,8 +1252,14 @@ GenerateXEvent( event.xany.send_event = -3; event.xkey.keycode = wParam; event.xkey.nbytes = Tcl_UniCharToUtf((int)wParam, buffer); - for (i=0; i 0xffff) && (event.xkey.nbytes < 4)) { + /* trans_chars buffer is not big enough to hold 2 surrogate + characters, so don't store anything */ + event.xkey.nbytes = 0; + } else { + for (i=0; i Date: Thu, 1 Sep 2016 12:56:25 +0000 Subject: don't forget to set the keycode ;-) --- win/tkWinX.c | 1 + 1 file changed, 1 insertion(+) diff --git a/win/tkWinX.c b/win/tkWinX.c index f4908e0..e8715b3 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -1225,6 +1225,7 @@ GenerateXEvent( event.xany.send_event = -3; event.xkey.nbytes = Tcl_UniCharToUtf(ch1, buffer); if ((ch1 <= 0xffff) || (event.xkey.nbytes == XMaxTransChars)) { + event.xkey.keycode = ch1; for (i=0; i Date: Thu, 1 Sep 2016 13:21:49 +0000 Subject: (experiment) don't fill trans_chars any more when send_event == -3. Results in many simplifications while it still should work the same --- win/tkWinKey.c | 15 ++++++++------ win/tkWinX.c | 64 ++++------------------------------------------------------ 2 files changed, 13 insertions(+), 66 deletions(-) diff --git a/win/tkWinKey.c b/win/tkWinKey.c index a49898f..64f8cd4 100644 --- a/win/tkWinKey.c +++ b/win/tkWinKey.c @@ -113,15 +113,18 @@ TkpGetString( Tcl_DStringAppend(dsPtr, buf, len); } else if (keyEv->send_event == -3) { + + char buf[XMaxTransChars]; + int len; + /* - * Special case for WM_UNICHAR. xkey.trans_chars[] already contains a - * UTF-8 char, except when nbytes == 0 (then it didn't fit there). + * Special case for WM_UNICHAR. */ - if (keyEv->nbytes) { - Tcl_DStringAppend(dsPtr, keyEv->trans_chars, keyEv->nbytes); - } else if (keyEv->keycode > 0xffff) { - char buf[XMaxTransChars]; + len = Tcl_UniCharToUtf(keyEv->keycode, buf); + if ((keyEv->keycode <= 0xffff) || (len == XMaxTransChars)) { + Tcl_DStringAppend(dsPtr, buf, len); + } else { Tcl_UniCharToUtf(((keyEv->keycode - 0x10000) >> 10) | 0xd800, buf); Tcl_DStringAppend(dsPtr, buf, 3); Tcl_UniCharToUtf(((keyEv->keycode - 0x10000) & 0x3ff) | 0xdc00, buf); diff --git a/win/tkWinX.c b/win/tkWinX.c index e8715b3..ccccf56 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -1210,8 +1210,7 @@ GenerateXEvent( event.xany.send_event = -1; event.xkey.keycode = 0; if ((int)wParam & 0xff00) { - int i, ch1 = wParam & 0xffff; - char buffer[XMaxTransChars]; + int ch1 = wParam & 0xffff; if ((ch1 & 0xfc00) == 0xd800) { tsdPtr->surrogateBuffer = ch1; @@ -1223,32 +1222,8 @@ GenerateXEvent( tsdPtr->surrogateBuffer = 0; } event.xany.send_event = -3; - event.xkey.nbytes = Tcl_UniCharToUtf(ch1, buffer); - if ((ch1 <= 0xffff) || (event.xkey.nbytes == XMaxTransChars)) { - event.xkey.keycode = ch1; - for (i=0; i>10) | 0xd800; - event.xkey.nbytes = Tcl_UniCharToUtf(event.xkey.keycode, buffer); - for (i=0; i 0xffff) && (event.xkey.nbytes < XMaxTransChars)) { -#if USE_EXTRA_EVENTS - /* trans_chars buffer is not big enough to hold 2 surrogate - characters, so split it in two separate events */ - - event.xkey.keycode = ((int)(wParam - 0x10000)>>10) | 0xd800; - event.xkey.nbytes = Tcl_UniCharToUtf(event.xkey.keycode, buffer); - for (i=0; i Date: Thu, 1 Sep 2016 13:43:28 +0000 Subject: unnecessary macro --- win/tkWinX.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/win/tkWinX.c b/win/tkWinX.c index ccccf56..1e66620 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -29,8 +29,6 @@ # pragma comment (lib, "advapi32.lib") #endif -#define USE_EXTRA_EVENTS 0 /* Set this to 1 if you want to generate - additional events for surrogates */ /* * The zmouse.h file includes the definition for WM_MOUSEWHEEL. */ -- cgit v0.12