Import Tk 8.6.11
This commit is contained in:
291
win/tkWinX.c
291
win/tkWinX.c
@@ -70,7 +70,6 @@ static const char winScreenName[] = ":0"; /* Default name of windows display. */
|
||||
static HINSTANCE tkInstance = NULL; /* Application instance handle. */
|
||||
static int childClassInitialized; /* Registered child class? */
|
||||
static WNDCLASSW childClass; /* Window class for child windows. */
|
||||
static int tkPlatformId = 0; /* version of Windows platform */
|
||||
static int tkWinTheme = 0; /* See TkWinGetPlatformTheme */
|
||||
static Tcl_Encoding keyInputEncoding = NULL;
|
||||
/* The current character encoding for
|
||||
@@ -105,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);
|
||||
|
||||
@@ -139,8 +138,8 @@ TkGetServerInfo(
|
||||
|
||||
if (!buffer[0]) {
|
||||
HANDLE handle = GetModuleHandleW(L"NTDLL");
|
||||
int(__stdcall *getversion)(void *) =
|
||||
(int(__stdcall *)(void *))GetProcAddress(handle, "RtlGetVersion");
|
||||
int(__stdcall *getversion)(void *) = (int(__stdcall *)(void *))
|
||||
(void *)GetProcAddress(handle, "RtlGetVersion");
|
||||
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
|
||||
if (!getversion || getversion(&os)) {
|
||||
GetVersionExW(&os);
|
||||
@@ -325,6 +324,69 @@ TkWinXCleanup(
|
||||
TkWinCleanupContainerList();
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkWinGetPlatformTheme --
|
||||
*
|
||||
* Return the Windows drawing style we should be using.
|
||||
*
|
||||
* Results:
|
||||
* The return value is one of:
|
||||
* TK_THEME_WIN_CLASSIC 95/98/NT or XP in classic mode
|
||||
* TK_THEME_WIN_XP XP not in classic mode
|
||||
* TK_THEME_WIN_VISTA Vista or higher
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TkWinGetPlatformTheme(void)
|
||||
{
|
||||
if (tkWinTheme == 0) {
|
||||
OSVERSIONINFOW os;
|
||||
|
||||
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
|
||||
GetVersionExW(&os);
|
||||
|
||||
if (os.dwPlatformId != VER_PLATFORM_WIN32_NT) {
|
||||
Tcl_Panic("Windows NT is the only supported platform");
|
||||
}
|
||||
|
||||
/*
|
||||
* Set tkWinTheme to be TK_THEME_WIN_(CLASSIC|XP|VISTA). The
|
||||
* TK_THEME_WIN_CLASSIC could be set even when running under XP if the
|
||||
* windows classic theme was selected.
|
||||
*/
|
||||
if (os.dwMajorVersion == 5 && os.dwMinorVersion >= 1) {
|
||||
HKEY hKey;
|
||||
LPCWSTR szSubKey = L"Control Panel\\Appearance";
|
||||
LPCWSTR szCurrent = L"Current";
|
||||
DWORD dwSize = 200;
|
||||
WCHAR pBuffer[200];
|
||||
|
||||
memset(pBuffer, 0, dwSize);
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, szSubKey, 0L,
|
||||
KEY_READ, &hKey) != ERROR_SUCCESS) {
|
||||
tkWinTheme = TK_THEME_WIN_XP;
|
||||
} else {
|
||||
RegQueryValueExW(hKey, szCurrent, NULL, NULL, (LPBYTE) pBuffer, &dwSize);
|
||||
RegCloseKey(hKey);
|
||||
if (wcscmp(pBuffer, L"Windows Standard") == 0) {
|
||||
tkWinTheme = TK_THEME_WIN_CLASSIC;
|
||||
} else {
|
||||
tkWinTheme = TK_THEME_WIN_XP;
|
||||
}
|
||||
}
|
||||
} else if (os.dwMajorVersion > 5) {
|
||||
tkWinTheme = TK_THEME_WIN_VISTA;
|
||||
} else {
|
||||
tkWinTheme = TK_THEME_WIN_CLASSIC;
|
||||
}
|
||||
}
|
||||
return tkWinTheme;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -334,11 +396,8 @@ TkWinXCleanup(
|
||||
* conditional code. Win32s is no longer supported.
|
||||
*
|
||||
* Results:
|
||||
* The return value is one of:
|
||||
* VER_PLATFORM_WIN32s Win32s on Windows 3.1 (not supported)
|
||||
* VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95, 98, ME (not supported)
|
||||
* The return value is always:
|
||||
* VER_PLATFORM_WIN32_NT Win32 on Windows XP, Vista, Windows 7, Windows 8
|
||||
* VER_PLATFORM_WIN32_CE Win32 on Windows CE
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
@@ -349,74 +408,9 @@ TkWinXCleanup(
|
||||
int
|
||||
TkWinGetPlatformId(void)
|
||||
{
|
||||
if (tkPlatformId == 0) {
|
||||
OSVERSIONINFOW os;
|
||||
|
||||
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
|
||||
GetVersionExW(&os);
|
||||
tkPlatformId = os.dwPlatformId;
|
||||
|
||||
/*
|
||||
* Set tkWinTheme to be TK_THEME_WIN_XP or TK_THEME_WIN_CLASSIC. The
|
||||
* TK_THEME_WIN_CLASSIC could be set even when running under XP if the
|
||||
* windows classic theme was selected.
|
||||
*/
|
||||
|
||||
if ((os.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
|
||||
(os.dwMajorVersion == 5 && os.dwMinorVersion == 1)) {
|
||||
HKEY hKey;
|
||||
LPCWSTR szSubKey = L"Control Panel\\Appearance";
|
||||
LPCWSTR szCurrent = L"Current";
|
||||
DWORD dwSize = 200;
|
||||
char pBuffer[200];
|
||||
|
||||
memset(pBuffer, 0, dwSize);
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, szSubKey, 0L,
|
||||
KEY_READ, &hKey) != ERROR_SUCCESS) {
|
||||
tkWinTheme = TK_THEME_WIN_XP;
|
||||
} else {
|
||||
RegQueryValueExW(hKey, szCurrent, NULL, NULL, (LPBYTE) pBuffer, &dwSize);
|
||||
RegCloseKey(hKey);
|
||||
if (strcmp(pBuffer, "Windows Standard") == 0) {
|
||||
tkWinTheme = TK_THEME_WIN_CLASSIC;
|
||||
} else {
|
||||
tkWinTheme = TK_THEME_WIN_XP;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tkWinTheme = TK_THEME_WIN_CLASSIC;
|
||||
}
|
||||
}
|
||||
return tkPlatformId;
|
||||
return VER_PLATFORM_WIN32_NT;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkWinGetPlatformTheme --
|
||||
*
|
||||
* Return the Windows drawing style we should be using.
|
||||
*
|
||||
* Results:
|
||||
* The return value is one of:
|
||||
* TK_THEME_WIN_CLASSIC 95/98/NT or XP in classic mode
|
||||
* TK_THEME_WIN_XP XP not in classic mode
|
||||
*
|
||||
* Side effects:
|
||||
* Could invoke TkWinGetPlatformId.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TkWinGetPlatformTheme(void)
|
||||
{
|
||||
if (tkPlatformId == 0) {
|
||||
TkWinGetPlatformId();
|
||||
}
|
||||
return tkWinTheme;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1000,7 +994,7 @@ GenerateXEvent(
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
XEvent event;
|
||||
union {XEvent x; TkKeyEvent key;} event;
|
||||
TkWindow *winPtr;
|
||||
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
|
||||
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
|
||||
@@ -1026,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;
|
||||
|
||||
@@ -1088,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
|
||||
@@ -1113,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:
|
||||
@@ -1145,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.
|
||||
@@ -1185,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.x.xkey.keycode = tsdPtr->vWheelAcc / WHEEL_DELTA * WHEEL_DELTA;
|
||||
tsdPtr->vWheelAcc = tsdPtr->vWheelAcc % WHEEL_DELTA;
|
||||
break;
|
||||
}
|
||||
@@ -1217,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.x.xkey.keycode = tsdPtr->hWheelAcc / WHEEL_DELTA * WHEEL_DELTA;
|
||||
tsdPtr->hWheelAcc = tsdPtr->hWheelAcc % WHEEL_DELTA;
|
||||
break;
|
||||
}
|
||||
@@ -1235,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;
|
||||
|
||||
@@ -1250,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:
|
||||
@@ -1286,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;
|
||||
|
||||
@@ -1301,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;
|
||||
@@ -1315,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;
|
||||
}
|
||||
|
||||
@@ -1351,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1360,7 +1354,7 @@ GenerateXEvent(
|
||||
* GetState --
|
||||
*
|
||||
* This function constructs a state mask for the mouse buttons and
|
||||
* modifier keys as they were before the event occured.
|
||||
* modifier keys as they were before the event occurred.
|
||||
*
|
||||
* Results:
|
||||
* Returns a composite value of all the modifier and button state flags
|
||||
@@ -1453,7 +1447,7 @@ GetState(
|
||||
|
||||
static void
|
||||
GetTranslatedKey(
|
||||
XKeyEvent *xkey,
|
||||
TkKeyEvent *xkey,
|
||||
UINT type)
|
||||
{
|
||||
MSG msg;
|
||||
@@ -1476,10 +1470,9 @@ GetTranslatedKey(
|
||||
*/
|
||||
|
||||
if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
|
||||
xkey->state = 0;
|
||||
xkey->keyEvent.state = 0;
|
||||
}
|
||||
xkey->trans_chars[xkey->nbytes] = (char) msg.wParam;
|
||||
xkey->nbytes++;
|
||||
xkey->trans_chars[xkey->nbytes++] = (char) msg.wParam;
|
||||
|
||||
if (((unsigned short) msg.wParam) > ((unsigned short) 0xff)) {
|
||||
/*
|
||||
@@ -1536,7 +1529,11 @@ UpdateInputLanguage(
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(codepage, "cp%d", charsetInfo.ciACP);
|
||||
if (charsetInfo.ciACP == CP_UTF8) {
|
||||
strcpy(codepage, "utf-8");
|
||||
} else {
|
||||
sprintf(codepage, "cp%d", charsetInfo.ciACP);
|
||||
}
|
||||
|
||||
if ((encoding = Tcl_GetEncoding(NULL, codepage)) == NULL) {
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user