summaryrefslogtreecommitdiffstats
path: root/win/tkWinX.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tkWinX.c')
-rw-r--r--win/tkWinX.c286
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;
}