diff options
Diffstat (limited to 'win/tkWinX.c')
-rw-r--r-- | win/tkWinX.c | 286 |
1 files changed, 106 insertions, 180 deletions
diff --git a/win/tkWinX.c b/win/tkWinX.c index af28e41..098fc6d 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -11,14 +11,6 @@ * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -/* - * Make sure the SendInput API is available (NT SP 3): - */ -#if (_WIN32_WINNT <= 0x0400) -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0403 -#endif - #include "tkWinInt.h" /* @@ -28,7 +20,7 @@ */ #ifndef _WIN32_IE -#define _WIN32_IE 0x0501 /* IE 5 */ +#define _WIN32_IE 0x0550 /* IE 5.5 */ #endif #include <commctrl.h> @@ -61,49 +53,11 @@ #define UNICODE_NOCHAR 0xFFFF #endif -static TkWinProcs asciiProcs = { - 0, - - (LRESULT (WINAPI *)(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, - WPARAM wParam, LPARAM lParam)) CallWindowProcA, - (LRESULT (WINAPI *)(HWND hWnd, UINT Msg, WPARAM wParam, - LPARAM lParam)) DefWindowProcA, - (ATOM (WINAPI *)(CONST WNDCLASS *lpWndClass)) RegisterClassA, - (BOOL (WINAPI *)(HWND hWnd, LPCTSTR lpString)) SetWindowTextA, - (HWND (WINAPI *)(DWORD dwExStyle, LPCTSTR lpClassName, - LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, - int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, - HINSTANCE hInstance, LPVOID lpParam)) CreateWindowExA, - (BOOL (WINAPI *)(HMENU hMenu, UINT uPosition, UINT uFlags, - UINT uIDNewItem, LPCTSTR lpNewItem)) InsertMenuA, - (int (WINAPI *)(HWND hWnd, LPCTSTR lpString, int nMaxCount)) GetWindowTextA, -}; - -static TkWinProcs unicodeProcs = { - 1, - - (LRESULT (WINAPI *)(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, - WPARAM wParam, LPARAM lParam)) CallWindowProcW, - (LRESULT (WINAPI *)(HWND hWnd, UINT Msg, WPARAM wParam, - LPARAM lParam)) DefWindowProcW, - (ATOM (WINAPI *)(CONST WNDCLASS *lpWndClass)) RegisterClassW, - (BOOL (WINAPI *)(HWND hWnd, LPCTSTR lpString)) SetWindowTextW, - (HWND (WINAPI *)(DWORD dwExStyle, LPCTSTR lpClassName, - LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, - int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, - HINSTANCE hInstance, LPVOID lpParam)) CreateWindowExW, - (BOOL (WINAPI *)(HMENU hMenu, UINT uPosition, UINT uFlags, - UINT uIDNewItem, LPCTSTR lpNewItem)) InsertMenuW, - (int (WINAPI *)(HWND hWnd, LPCTSTR lpString, int nMaxCount)) GetWindowTextW, -}; - -TkWinProcs *tkWinProcs; - /* * Declarations of static variables used in this file. */ -static char winScreenName[] = ":0"; /* Default name of windows display. */ +static const char winScreenName[] = ":0"; /* Default name of windows display. */ static HINSTANCE tkInstance = NULL; /* Application instance handle. */ static int childClassInitialized; /* Registered child class? */ static WNDCLASS childClass; /* Window class for child windows. */ @@ -127,6 +81,7 @@ 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. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -170,16 +125,13 @@ TkGetServerInfo( OSVERSIONINFOW os; if (!buffer[0]) { - HANDLE handle = LoadLibraryW(L"NTDLL"); + HANDLE handle = GetModuleHandle(TEXT("NTDLL")); int(__stdcall *getversion)(void *) = (int(__stdcall *)(void *))GetProcAddress(handle, "RtlGetVersion"); os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); if (!getversion || getversion(&os)) { GetVersionExW(&os); } - if (handle) { - FreeLibrary(handle); - } /* Write the first character last, preventing multi-thread issues. */ sprintf(buffer+1, "indows %d.%d %d %s", (int)os.dwMajorVersion, (int)os.dwMinorVersion, (int)os.dwBuildNumber, @@ -191,7 +143,7 @@ TkGetServerInfo( ); buffer[0] = 'W'; } - Tcl_SetResult(interp, buffer, TCL_STATIC); + Tcl_AppendResult(interp, buffer, NULL); } /* @@ -278,12 +230,6 @@ TkWinXInit( Tcl_Panic("Unable to load common controls?!"); } - if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { - tkWinProcs = &unicodeProcs; - } else { - tkWinProcs = &asciiProcs; - } - childClass.style = CS_HREDRAW | CS_VREDRAW; childClass.cbClsExtra = 0; childClass.cbWndExtra = 0; @@ -376,9 +322,10 @@ TkWinXCleanup( * * Results: * The return value is one of: - * VER_PLATFORM_WIN32s Win32s on Windows 3.1. - * VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95. - * VER_PLATFORM_WIN32_NT Win32 on Windows NT + * VER_PLATFORM_WIN32s Win32s on Windows 3.1 (not supported) + * VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95, 98, ME (not supported) + * VER_PLATFORM_WIN32_NT Win32 on Windows XP, Vista, Windows 7, Windows 8 + * VER_PLATFORM_WIN32_CE Win32 on Windows CE * * Side effects: * None. @@ -405,8 +352,8 @@ TkWinGetPlatformId(void) if ((os.dwPlatformId == VER_PLATFORM_WIN32_NT) && (os.dwMajorVersion == 5 && os.dwMinorVersion == 1)) { HKEY hKey; - LPCSTR szSubKey = TEXT("Control Panel\\Appearance"); - LPCSTR szCurrent = TEXT("Current"); + LPCTSTR szSubKey = TEXT("Control Panel\\Appearance"); + LPCTSTR szCurrent = TEXT("Current"); DWORD dwSize = 200; char pBuffer[200]; @@ -474,10 +421,10 @@ TkWinGetPlatformTheme(void) *---------------------------------------------------------------------- */ -CONST char * +const char * TkGetDefaultScreenName( Tcl_Interp *interp, /* Not used. */ - CONST char *screenName) /* If NULL, use default string. */ + const char *screenName) /* If NULL, use default string. */ { if ((screenName == NULL) || (screenName[0] == '\0')) { screenName = winScreenName; @@ -535,9 +482,9 @@ TkWinDisplayChanged( screen->root_depth = GetDeviceCaps(dc, BITSPIXEL) * PTR2INT(screen->ext_data); if (screen->root_visual != NULL) { - ckfree((char *) screen->root_visual); + ckfree(screen->root_visual); } - screen->root_visual = (Visual *) ckalloc(sizeof(Visual)); + screen->root_visual = ckalloc(sizeof(Visual)); screen->root_visual->visualid = 0; if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) { screen->root_visual->map_entries = GetDeviceCaps(dc, SIZEPALETTE); @@ -599,12 +546,12 @@ TkWinDisplayChanged( TkDisplay * TkpOpenDisplay( - CONST char *display_name) + const char *display_name) { Screen *screen; TkWinDrawable *twdPtr; Display *display; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (tsdPtr->winDisplay != NULL) { @@ -615,10 +562,10 @@ TkpOpenDisplay( } } - display = (Display *) ckalloc(sizeof(Display)); + display = ckalloc(sizeof(Display)); ZeroMemory(display, sizeof(Display)); - display->display_name = (char *) ckalloc(strlen(display_name)+1); + display->display_name = ckalloc(strlen(display_name) + 1); strcpy(display->display_name, display_name); display->cursor_font = 1; @@ -626,7 +573,7 @@ TkpOpenDisplay( display->request = 1; display->qlen = 0; - screen = (Screen *) ckalloc(sizeof(Screen)); + screen = ckalloc(sizeof(Screen)); ZeroMemory(screen, sizeof(Screen)); screen->display = display; @@ -634,7 +581,7 @@ TkpOpenDisplay( * Set up the root window. */ - twdPtr = (TkWinDrawable*) ckalloc(sizeof(TkWinDrawable)); + twdPtr = ckalloc(sizeof(TkWinDrawable)); if (twdPtr == NULL) { return None; } @@ -657,7 +604,7 @@ TkpOpenDisplay( TkWinDisplayChanged(display); - tsdPtr->winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay)); + tsdPtr->winDisplay = ckalloc(sizeof(TkDisplay)); ZeroMemory(tsdPtr->winDisplay, sizeof(TkDisplay)); tsdPtr->winDisplay->display = display; tsdPtr->updatingClipboard = FALSE; @@ -702,17 +649,17 @@ TkpCloseDisplay( } if (display->screens != NULL) { if (display->screens->root_visual != NULL) { - ckfree((char *) display->screens->root_visual); + ckfree(display->screens->root_visual); } if (display->screens->root != None) { - ckfree((char *) display->screens->root); + ckfree(display->screens->root); } if (display->screens->cmap != None) { XFreeColormap(display, display->screens->cmap); } - ckfree((char *) display->screens); + ckfree(display->screens); } - ckfree((char *) display); + ckfree(display); } /* @@ -962,15 +909,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); @@ -1017,7 +973,23 @@ GenerateXEvent( ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd); + if (message == WM_MOUSEWHEEL) { + union {LPARAM lParam; POINTS point;} root; + POINT pos; + root.lParam = lParam; + + /* + * Redirect mousewheel events to the window containing the cursor. + * That feels much less strange to users, and is how all the other + * platforms work. + */ + + pos.x = root.point.x; + pos.y = root.point.y; + hwnd = WindowFromPoint(pos); + } + + winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd); if (!winPtr || winPtr->window == None) { return; } @@ -1116,11 +1088,6 @@ GenerateXEvent( break; case WM_MOUSEWHEEL: - /* - * The mouse wheel event is closer to a key event than a mouse event - * in that the message is sent to the window that has focus. - */ - case WM_CHAR: case WM_UNICHAR: case WM_SYSKEYDOWN: @@ -1238,18 +1205,35 @@ 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)) { - MSG msg; - - if ((PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, - PM_NOREMOVE) != 0) - && (msg.message == WM_CHAR)) { - GetMessage(&msg, NULL, WM_CHAR, WM_CHAR); - event.xkey.nbytes = 2; - event.xkey.trans_chars[1] = (char) msg.wParam; + if ((int)wParam & 0xff00) { + int ch1 = wParam & 0xffff; + + if ((ch1 & 0xfc00) == 0xd800) { + tsdPtr->surrogateBuffer = ch1; + return; + } + if ((ch1 & 0xfc00) == 0xdc00) { + ch1 = ((tsdPtr->surrogateBuffer & 0x3ff) << 10) | + (ch1 & 0x3ff) | 0x10000; + tsdPtr->surrogateBuffer = 0; + } + event.xany.send_event = -3; + event.xkey.nbytes = 0; + event.xkey.keycode = ch1; + } else { + event.xkey.nbytes = 1; + event.xkey.trans_chars[0] = (char) wParam; + + if (IsDBCSLeadByte((BYTE) wParam)) { + MSG msg; + + if ((PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, + PM_NOREMOVE) != 0) + && (msg.message == WM_CHAR)) { + GetMessage(&msg, NULL, WM_CHAR, WM_CHAR); + event.xkey.nbytes = 2; + event.xkey.trans_chars[1] = (char) msg.wParam; + } } } Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); @@ -1257,15 +1241,10 @@ GenerateXEvent( break; case WM_UNICHAR: { - char buffer[TCL_UTF_MAX+1]; - int i; event.type = KeyPress; event.xany.send_event = -3; event.xkey.keycode = wParam; - event.xkey.nbytes = Tcl_UniCharToUtf((int)wParam, buffer); - for (i=0; i<event.xkey.nbytes && i<TCL_UTF_MAX; ++i) { - event.xkey.trans_chars[i] = buffer[i]; - } + event.xkey.nbytes = 0; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); event.type = KeyRelease; break; @@ -1363,11 +1342,7 @@ GetState( state &= ~mask; } if (HIWORD(lParam) & KF_EXTENDED) { - if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) { - state |= EXTENDED_MASK; - } else { - state &= ~EXTENDED_MASK; - } + state |= EXTENDED_MASK; } } return state; @@ -1402,12 +1377,12 @@ GetTranslatedKey( xkey->nbytes = 0; while ((xkey->nbytes < XMaxTransChars) - && PeekMessage(&msg, NULL, type, type, PM_NOREMOVE)) { + && (PeekMessageA(&msg, NULL, type, type, PM_NOREMOVE) != 0)) { if (msg.message != type) { break; } - GetMessage(&msg, NULL, type, type); + GetMessageA(&msg, NULL, type, type); /* * If this is a normal character message, we may need to strip off the @@ -1548,7 +1523,7 @@ TkWinGetUnicodeEncoding(void) * * HandleIMEComposition -- * - * This function works around a definciency in some versions of Windows + * This function works around a deficiency in some versions of Windows * 2000 to make it possible to entry multi-lingual characters under all * versions of Windows 2000. * @@ -1578,7 +1553,7 @@ HandleIMEComposition( { HIMC hIMC; int n; - BOOL isWinNT = (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT); + int high = 0; if ((lParam & GCS_RESULTSTR) == 0) { /* @@ -1593,53 +1568,21 @@ HandleIMEComposition( return 0; } - if (isWinNT) { - n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0); - } else { - n = ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, NULL, 0); - } + n = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0); if (n > 0) { - char *buff = ckalloc((unsigned) n); + WCHAR *buff = (WCHAR *) ckalloc(n); TkWindow *winPtr; XEvent event; int i; - if (isWinNT) { - n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, - (unsigned) n); - } else { - Tcl_DString utfString, unicodeString; - Tcl_Encoding unicodeEncoding = TkWinGetUnicodeEncoding(); - - n = ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, buff, - (unsigned) n); - Tcl_DStringInit(&utfString); - Tcl_ExternalToUtfDString(keyInputEncoding, buff, n, &utfString); - Tcl_UtfToExternalDString(unicodeEncoding, - Tcl_DStringValue(&utfString), -1, &unicodeString); - i = Tcl_DStringLength(&unicodeString); - if (n < i) { - /* - * Only alloc more space if we need, otherwise just use what - * we've created. Don't realloc as that may copy data we no - * longer need. - */ - - ckfree((char *) buff); - buff = (char *) ckalloc((unsigned) i); - } - n = i; - memcpy(buff, Tcl_DStringValue(&unicodeString), (unsigned) n); - Tcl_DStringFree(&utfString); - Tcl_DStringFree(&unicodeString); - } + n = ImmGetCompositionString(hIMC, GCS_RESULTSTR, buff, (unsigned) n) / 2; /* * Set up the fields pertinent to key event. * - * We set send_event to the special value of -2, so that TkpGetString - * in tkWinKey.c knows that trans_chars[] already contains a UNICODE + * We set send_event to the special value of -3, so that TkpGetString + * in tkWinKey.c knows that keycode already contains a UNICODE * char and there's no need to do encoding conversion. * * Note that the event *must* be zeroed out first; Tk plays cunning @@ -1650,7 +1593,7 @@ HandleIMEComposition( memset(&event, 0, sizeof(XEvent)); event.xkey.serial = winPtr->display->request++; - event.xkey.send_event = -2; + event.xkey.send_event = -3; event.xkey.display = winPtr->display; event.xkey.window = winPtr->window; event.xkey.root = RootWindow(winPtr->display, winPtr->screenNum); @@ -1658,8 +1601,6 @@ HandleIMEComposition( event.xkey.state = TkWinGetModifierState(); event.xkey.time = TkpGetMS(); event.xkey.same_screen = True; - event.xkey.keycode = 0; - event.xkey.nbytes = 2; for (i=0; i<n; ) { /* @@ -1667,9 +1608,16 @@ HandleIMEComposition( * UNICODE character in the composition. */ - event.xkey.trans_chars[0] = (char) buff[i++]; - event.xkey.trans_chars[1] = (char) buff[i++]; + event.xkey.keycode = buff[i++]; + if ((event.xkey.keycode & 0xfc00) == 0xd800) { + high = ((event.xkey.keycode & 0x3ff) << 10) + 0x10000; + break; + } else if (high && (event.xkey.keycode & 0xfc00) == 0xdc00) { + event.xkey.keycode &= 0x3ff; + event.xkey.keycode += high; + high = 0; + } event.type = KeyPress; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); @@ -1946,32 +1894,10 @@ long Tk_GetUserInactiveTime( Display *dpy) /* Ignored on Windows */ { - struct tagLASTINPUTINFO { - UINT cbSize; - DWORD dwTime; - } li; - - /* - * Multiple settings of either of these variables should be OK; any thread - * hazards should just cause inefficiency... - */ + LASTINPUTINFO li; - static FARPROC pfnGetLastInputInfo = NULL; - static int initinfo = 0; - - if (!initinfo) { - HMODULE hMod = GetModuleHandleA("USER32.DLL"); - - initinfo = 1; - if (hMod){ - pfnGetLastInputInfo = GetProcAddress(hMod, "GetLastInputInfo"); - } - } - if (pfnGetLastInputInfo == NULL) { - return -1; - } li.cbSize = sizeof(li); - if (!(BOOL)(pfnGetLastInputInfo)(&li)) { + if (!(BOOL)GetLastInputInfo(&li)) { return -1; } |