summaryrefslogtreecommitdiffstats
path: root/win/tkWinX.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tkWinX.c')
-rw-r--r--win/tkWinX.c1636
1 files changed, 889 insertions, 747 deletions
diff --git a/win/tkWinX.c b/win/tkWinX.c
index cafacb9..288da26 100644
--- a/win/tkWinX.c
+++ b/win/tkWinX.c
@@ -1,22 +1,30 @@
-/*
+/*
* tkWinX.c --
*
- * This file contains Windows emulation procedures for X routines.
+ * This file contains Windows emulation procedures for X routines.
*
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
* Copyright (c) 1994 Software Research Associates, Inc.
* Copyright (c) 1998-2000 by Scriptics Corporation.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * 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"
/*
- * The w32api 1.1 package (included in Mingw 1.1) does not define _WIN32_IE
- * by default. Define it here to gain access to the InitCommonControlsEx API
- * in commctrl.h.
+ * The w32api 1.1 package (included in Mingw 1.1) does not define _WIN32_IE by
+ * default. Define it here to gain access to the InitCommonControlsEx API in
+ * commctrl.h.
*/
#ifndef _WIN32_IE
@@ -24,6 +32,10 @@
#endif
#include <commctrl.h>
+#ifdef _MSC_VER
+# pragma comment (lib, "comctl32.lib")
+# pragma comment (lib, "advapi32.lib")
+#endif
/*
* The zmouse.h file includes the definition for WM_MOUSEWHEEL.
@@ -36,6 +48,9 @@
*/
#include <imm.h>
+#ifdef _MSC_VER
+# pragma comment (lib, "imm32.lib")
+#endif
/*
* WM_UNICHAR is a message for Unicode input on all windows systems.
@@ -61,6 +76,7 @@ static TkWinProcs asciiProcs = {
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 = {
@@ -78,6 +94,7 @@ static TkWinProcs unicodeProcs = {
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;
@@ -86,51 +103,52 @@ TkWinProcs *tkWinProcs;
* Declarations of static variables used in this file.
*/
-static 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. */
-static int tkPlatformId = 0; /* version of Windows platform */
-static int tkWinTheme = 0; /* See TkWinGetPlatformTheme */
-static Tcl_Encoding keyInputEncoding = NULL;/* The current character
- * encoding for keyboard input */
-static int keyInputCharset = -1; /* The Win32 CHARSET for the keyboard
- * encoding */
-static Tcl_Encoding unicodeEncoding = NULL; /* unicode encoding */
+static 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. */
+static int tkPlatformId = 0; /* version of Windows platform */
+static int tkWinTheme = 0; /* See TkWinGetPlatformTheme */
+static Tcl_Encoding keyInputEncoding = NULL;
+ /* The current character encoding for
+ * keyboard input */
+static int keyInputCharset = -1; /* The Win32 CHARSET for the keyboard
+ * encoding */
+static Tcl_Encoding unicodeEncoding = NULL;
+ /* The UNICODE encoding */
/*
- * Thread local storage. Notice that now each thread must have its
- * own TkDisplay structure, since this structure contains most of
- * the thread-specific date for threads.
+ * Thread local storage. Notice that now each thread must have its own
+ * TkDisplay structure, since this structure contains most of the thread-
+ * specific date for threads.
*/
+
typedef struct ThreadSpecificData {
- TkDisplay *winDisplay; /* TkDisplay structure that *
- * represents Windows screen. */
- int updatingClipboard; /* If 1, we are updating the clipboard */
+ TkDisplay *winDisplay; /* TkDisplay structure that represents Windows
+ * screen. */
+ int updatingClipboard; /* If 1, we are updating the clipboard. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
/*
- * Forward declarations of procedures used in this file.
+ * Forward declarations of functions used in this file.
*/
-static void GenerateXEvent _ANSI_ARGS_((HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam));
-static unsigned int GetState _ANSI_ARGS_((UINT message, WPARAM wParam,
- LPARAM lParam));
-static void GetTranslatedKey _ANSI_ARGS_((XKeyEvent *xkey));
-static void UpdateInputLanguage _ANSI_ARGS_((int charset));
-static int HandleIMEComposition _ANSI_ARGS_((HWND hwnd,
- LPARAM lParam));
+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);
+static void UpdateInputLanguage(int charset);
+static int HandleIMEComposition(HWND hwnd, LPARAM lParam);
/*
*----------------------------------------------------------------------
*
* TkGetServerInfo --
*
- * Given a window, this procedure returns information about
- * the window server for that window. This procedure provides
- * the guts of the "winfo server" command.
+ * Given a window, this function returns information about the window
+ * server for that window. This function provides the guts of the "winfo
+ * server" command.
*
* Results:
* None.
@@ -142,25 +160,25 @@ static int HandleIMEComposition _ANSI_ARGS_((HWND hwnd,
*/
void
-TkGetServerInfo(interp, tkwin)
- Tcl_Interp *interp; /* The server information is returned in
- * this interpreter's result. */
- Tk_Window tkwin; /* Token for window; this selects a
- * particular display and server. */
+TkGetServerInfo(
+ Tcl_Interp *interp, /* The server information is returned in this
+ * interpreter's result. */
+ Tk_Window tkwin) /* Token for window; this selects a particular
+ * display and server. */
{
char buffer[60];
OSVERSIONINFO os;
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&os);
- sprintf(buffer, "Windows %d.%d %d %s", os.dwMajorVersion,
- os.dwMinorVersion, os.dwBuildNumber,
+ sprintf(buffer, "Windows %d.%d %d %s", (int)os.dwMajorVersion,
+ (int)os.dwMinorVersion, (int)os.dwBuildNumber,
#ifdef _WIN64
"Win64"
#else
"Win32"
#endif
- );
+ );
Tcl_SetResult(interp, buffer, TCL_VOLATILE);
}
@@ -181,7 +199,7 @@ TkGetServerInfo(interp, tkwin)
*/
HINSTANCE
-Tk_GetHINSTANCE()
+Tk_GetHINSTANCE(void)
{
if (tkInstance == NULL) {
tkInstance = GetModuleHandle(NULL);
@@ -194,8 +212,8 @@ Tk_GetHINSTANCE()
*
* TkWinSetHINSTANCE --
*
- * Sets the global instance handle used by the Tk library.
- * This should be called by DllMain.
+ * Sets the global instance handle used by the Tk library. This should be
+ * called by DllMain.
*
* Results:
* None.
@@ -207,8 +225,8 @@ Tk_GetHINSTANCE()
*/
void
-TkWinSetHINSTANCE(hInstance)
- HINSTANCE hInstance;
+TkWinSetHINSTANCE(
+ HINSTANCE hInstance)
{
tkInstance = hInstance;
}
@@ -230,9 +248,10 @@ TkWinSetHINSTANCE(hInstance)
*/
void
-TkWinXInit(hInstance)
- HINSTANCE hInstance;
+TkWinXInit(
+ HINSTANCE hInstance)
{
+ INITCOMMONCONTROLSEX comctl;
CHARSETINFO lpCs;
DWORD lpCP;
@@ -241,16 +260,13 @@ TkWinXInit(hInstance)
}
childClassInitialized = 1;
- if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
- /*
- * This is necessary to enable the use of themeable elements on XP,
- * so we don't even try and call it for Win9*.
- */
-
- INITCOMMONCONTROLSEX comctl;
- ZeroMemory(&comctl, sizeof(comctl));
- (void) InitCommonControlsEx(&comctl);
+ comctl.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ comctl.dwICC = ICC_WIN95_CLASSES;
+ if (!InitCommonControlsEx(&comctl)) {
+ Tcl_Panic("Unable to load common controls?!");
+ }
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
tkWinProcs = &unicodeProcs;
} else {
tkWinProcs = &asciiProcs;
@@ -273,23 +289,24 @@ TkWinXInit(hInstance)
childClass.hCursor = NULL;
if (!RegisterClass(&childClass)) {
- panic("Unable to register TkChild class");
+ Tcl_Panic("Unable to register TkChild class");
}
/*
* Initialize input language info
*/
- if (GetLocaleInfo(LANGIDFROMLCID(GetKeyboardLayout(0)),
+ if (GetLocaleInfo(LANGIDFROMLCID((DWORD)GetKeyboardLayout(0)),
LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
(LPTSTR) &lpCP, sizeof(lpCP)/sizeof(TCHAR))
&& TranslateCharsetInfo((DWORD *)lpCP, &lpCs, TCI_SRCCODEPAGE)) {
- UpdateInputLanguage(lpCs.ciCharset);
+ UpdateInputLanguage((int) lpCs.ciCharset);
}
/*
* Make sure we cleanup on finalize.
*/
+
TkCreateExitHandler(TkWinXCleanup, (ClientData) hInstance);
}
@@ -310,17 +327,18 @@ TkWinXInit(hInstance)
*/
void
-TkWinXCleanup(clientData)
- ClientData clientData;
+TkWinXCleanup(
+ ClientData clientData)
{
HINSTANCE hInstance = (HINSTANCE) clientData;
+
/*
* Clean up our own class.
*/
-
+
if (childClassInitialized) {
- childClassInitialized = 0;
- UnregisterClass(TK_WIN_CHILD_CLASS_NAME, hInstance);
+ childClassInitialized = 0;
+ UnregisterClass(TK_WIN_CHILD_CLASS_NAME, hInstance);
}
if (unicodeEncoding != NULL) {
@@ -331,8 +349,9 @@ TkWinXCleanup(clientData)
/*
* And let the window manager clean up its own class(es).
*/
-
+
TkWinWmCleanup(hInstance);
+ TkWinCleanupContainerList();
}
/*
@@ -340,12 +359,12 @@ TkWinXCleanup(clientData)
*
* TkWinGetPlatformId --
*
- * Determines whether running under NT, 95, or Win32s, to allow
- * runtime conditional code. Win32s is no longer supported.
+ * Determines whether running under NT, 95, or Win32s, to allow runtime
+ * conditional code. Win32s is no longer supported.
*
* Results:
* The return value is one of:
- * VER_PLATFORM_WIN32s Win32s on Windows 3.1.
+ * VER_PLATFORM_WIN32s Win32s on Windows 3.1.
* VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95.
* VER_PLATFORM_WIN32_NT Win32 on Windows NT
*
@@ -356,7 +375,7 @@ TkWinXCleanup(clientData)
*/
int
-TkWinGetPlatformId()
+TkWinGetPlatformId(void)
{
if (tkPlatformId == 0) {
OSVERSIONINFO os;
@@ -364,29 +383,33 @@ TkWinGetPlatformId()
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&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. */
+
+ /*
+ * 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;
- LPCSTR szSubKey = TEXT("Control Panel\\Appearance");
+ (os.dwMajorVersion == 5 && os.dwMinorVersion == 1)) {
+ HKEY hKey;
+ LPCSTR szSubKey = TEXT("Control Panel\\Appearance");
LPCSTR szCurrent = TEXT("Current");
- DWORD dwSize = 200;
+ DWORD dwSize = 200;
char pBuffer[200];
+
memset(pBuffer, 0, dwSize);
if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0L,
- KEY_READ, &hKey) != ERROR_SUCCESS) {
- tkWinTheme = TK_THEME_WIN_XP;
+ KEY_READ, &hKey) != ERROR_SUCCESS) {
+ tkWinTheme = TK_THEME_WIN_XP;
} else {
- RegQueryValueEx(hKey, szCurrent, NULL, NULL, pBuffer, &dwSize);
- RegCloseKey(hKey);
- if (strcmp(pBuffer, "Windows Standard") == 0) {
- tkWinTheme = TK_THEME_WIN_CLASSIC;
- } else {
- tkWinTheme = TK_THEME_WIN_XP;
- }
+ RegQueryValueEx(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;
@@ -404,8 +427,8 @@ TkWinGetPlatformId()
*
* 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_CLASSIC 95/98/NT or XP in classic mode
+ * TK_THEME_WIN_XP XP not in classic mode
*
* Side effects:
* Could invoke TkWinGetPlatformId.
@@ -414,10 +437,10 @@ TkWinGetPlatformId()
*/
int
-TkWinGetPlatformTheme()
+TkWinGetPlatformTheme(void)
{
if (tkPlatformId == 0) {
- TkWinGetPlatformId();
+ TkWinGetPlatformId();
}
return tkWinTheme;
}
@@ -440,9 +463,9 @@ TkWinGetPlatformTheme()
*/
CONST char *
-TkGetDefaultScreenName(interp, screenName)
- Tcl_Interp *interp; /* Not used. */
- CONST char *screenName; /* If NULL, use default string. */
+TkGetDefaultScreenName(
+ Tcl_Interp *interp, /* Not used. */
+ CONST char *screenName) /* If NULL, use default string. */
{
if ((screenName == NULL) || (screenName[0] == '\0')) {
screenName = winScreenName;
@@ -468,7 +491,8 @@ TkGetDefaultScreenName(interp, screenName)
*/
void
-TkWinDisplayChanged(Display *display)
+TkWinDisplayChanged(
+ Display *display)
{
HDC dc;
Screen *screen;
@@ -489,9 +513,9 @@ TkWinDisplayChanged(Display *display)
/*
* On windows, when creating a color bitmap, need two pieces of
* information: the number of color planes and the number of pixels per
- * plane. Need to remember both quantities so that when constructing an
+ * plane. Need to remember both quantities so that when constructing an
* HBITMAP for offscreen rendering, we can specify the correct value for
- * the number of planes. Otherwise the HBITMAP won't be compatible with
+ * the number of planes. Otherwise the HBITMAP won't be compatible with
* the HWND and we'll just get blank spots copied onto the screen.
*/
@@ -549,8 +573,8 @@ TkWinDisplayChanged(Display *display)
*
* TkpOpenDisplay --
*
- * Create the Display structure and fill it with device
- * specific information.
+ * Create the Display structure and fill it with device specific
+ * information.
*
* Results:
* Returns a TkDisplay structure on success or NULL on failure.
@@ -562,18 +586,17 @@ TkWinDisplayChanged(Display *display)
*/
TkDisplay *
-TkpOpenDisplay(display_name)
- CONST char *display_name;
+TkpOpenDisplay(
+ CONST char *display_name)
{
Screen *screen;
TkWinDrawable *twdPtr;
Display *display;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (tsdPtr->winDisplay != NULL) {
- if (strcmp(tsdPtr->winDisplay->display->display_name, display_name)
- == 0) {
+ if (!strcmp(tsdPtr->winDisplay->display->display_name, display_name)) {
return tsdPtr->winDisplay;
} else {
return NULL;
@@ -587,9 +610,9 @@ TkpOpenDisplay(display_name)
strcpy(display->display_name, display_name);
display->cursor_font = 1;
- display->nscreens = 1;
- display->request = 1;
- display->qlen = 0;
+ display->nscreens = 1;
+ display->request = 1;
+ display->qlen = 0;
screen = (Screen *) ckalloc(sizeof(Screen));
ZeroMemory(screen, sizeof(Screen));
@@ -614,7 +637,7 @@ TkpOpenDisplay(display_name)
screen->white_pixel = RGB(255, 255, 255);
screen->black_pixel = RGB(0, 0, 0);
- screen->cmap = None;
+ screen->cmap = None;
display->screens = screen;
display->nscreens = 1;
@@ -648,49 +671,34 @@ TkpOpenDisplay(display_name)
*/
void
-TkpCloseDisplay(dispPtr)
- TkDisplay *dispPtr;
+TkpCloseDisplay(
+ TkDisplay *dispPtr)
{
Display *display = dispPtr->display;
- HWND hwnd;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (dispPtr != tsdPtr->winDisplay) {
- panic("TkpCloseDisplay: tried to call TkpCloseDisplay on another display");
- return;
- }
-
- /*
- * Force the clipboard to be rendered if we are the clipboard owner.
- */
-
- if (dispPtr->clipWindow) {
- hwnd = Tk_GetHWND(Tk_WindowId(dispPtr->clipWindow));
- if (GetClipboardOwner() == hwnd) {
- OpenClipboard(hwnd);
- EmptyClipboard();
- TkWinClipboardRender(dispPtr, CF_TEXT);
- CloseClipboard();
- }
+ Tcl_Panic("TkpCloseDisplay: tried to call TkpCloseDisplay on another display");
+ return; /* not reached */
}
tsdPtr->winDisplay = NULL;
- if (display->display_name != (char *) NULL) {
- ckfree(display->display_name);
+ if (display->display_name != NULL) {
+ ckfree(display->display_name);
}
- if (display->screens != (Screen *) NULL) {
- if (display->screens->root_visual != NULL) {
- ckfree((char *) display->screens->root_visual);
- }
- if (display->screens->root != None) {
- ckfree((char *) display->screens->root);
- }
- if (display->screens->cmap != None) {
- XFreeColormap(display, display->screens->cmap);
- }
- ckfree((char *) display->screens);
+ if (display->screens != NULL) {
+ if (display->screens->root_visual != NULL) {
+ ckfree((char *) display->screens->root_visual);
+ }
+ if (display->screens->root != None) {
+ ckfree((char *) display->screens->root);
+ }
+ if (display->screens->cmap != None) {
+ XFreeColormap(display, display->screens->cmap);
+ }
+ ckfree((char *) display->screens);
}
ckfree((char *) display);
}
@@ -700,11 +708,10 @@ TkpCloseDisplay(dispPtr)
*
* TkClipCleanup --
*
- * This procedure is called to cleanup resources associated with
- * claiming clipboard ownership and for receiving selection get
- * results. This function is called in tkWindow.c. This has to be
- * called by the display cleanup function because we still need the
- * access display elements.
+ * This function is called to cleanup resources associated with claiming
+ * clipboard ownership and for receiving selection get results. This
+ * function is called in tkWindow.c. This has to be called by the display
+ * cleanup function because we still need the access display elements.
*
* Results:
* None.
@@ -716,8 +723,8 @@ TkpCloseDisplay(dispPtr)
*/
void
-TkClipCleanup(dispPtr)
- TkDisplay *dispPtr; /* display associated with clipboard */
+TkClipCleanup(
+ TkDisplay *dispPtr) /* Display associated with clipboard. */
{
if (dispPtr->clipWindow != NULL) {
/*
@@ -725,6 +732,7 @@ TkClipCleanup(dispPtr)
*/
HWND hwnd = Tk_GetHWND(Tk_WindowId(dispPtr->clipWindow));
+
if (GetClipboardOwner() == hwnd) {
OpenClipboard(hwnd);
EmptyClipboard();
@@ -760,9 +768,9 @@ TkClipCleanup(dispPtr)
*/
void
-XBell(display, percent)
- Display* display;
- int percent;
+XBell(
+ Display *display,
+ int percent)
{
MessageBeep(MB_OK);
}
@@ -772,8 +780,7 @@ XBell(display, percent)
*
* TkWinChildProc --
*
- * Callback from Windows whenever an event occurs on a child
- * window.
+ * Callback from Windows whenever an event occurs on a child window.
*
* Results:
* Standard Windows return value.
@@ -785,75 +792,83 @@ XBell(display, percent)
*/
LRESULT CALLBACK
-TkWinChildProc(hwnd, message, wParam, lParam)
- HWND hwnd;
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
+TkWinChildProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
{
LRESULT result;
switch (message) {
- case WM_INPUTLANGCHANGE:
- UpdateInputLanguage(wParam);
- result = 1;
- break;
-
- case WM_IME_COMPOSITION:
- result = 0;
- if (HandleIMEComposition(hwnd, lParam) == 0) {
- result = DefWindowProc(hwnd, message, wParam, lParam);
- }
- break;
-
- case WM_SETCURSOR:
- /*
- * Short circuit the WM_SETCURSOR message since we set
- * the cursor elsewhere.
- */
-
- result = TRUE;
- break;
-
- case WM_CREATE:
- case WM_ERASEBKGND:
- result = 0;
- break;
-
- case WM_PAINT:
- GenerateXEvent(hwnd, message, wParam, lParam);
+ case WM_INPUTLANGCHANGE:
+ UpdateInputLanguage((int) wParam);
+ result = 1;
+ break;
+
+ case WM_IME_COMPOSITION:
+ result = 0;
+ if (HandleIMEComposition(hwnd, lParam) == 0) {
result = DefWindowProc(hwnd, message, wParam, lParam);
- break;
+ }
+ break;
- case TK_CLAIMFOCUS:
- case TK_GEOMETRYREQ:
- case TK_ATTACHWINDOW:
- case TK_DETACHWINDOW:
- result = TkWinEmbeddedEventProc(hwnd, message, wParam, lParam);
- break;
+ case WM_SETCURSOR:
+ /*
+ * Short circuit the WM_SETCURSOR message since we set the cursor
+ * elsewhere.
+ */
- case WM_UNICHAR:
- if (wParam == UNICODE_NOCHAR) {
- /* If wParam is UNICODE_NOCHAR and the application processes
- * this message, then return TRUE. */
- result = 1;
+ result = TRUE;
+ break;
+
+ case WM_CREATE:
+ case WM_ERASEBKGND:
+ result = 0;
+ break;
+
+ case WM_PAINT:
+ GenerateXEvent(hwnd, message, wParam, lParam);
+ result = DefWindowProc(hwnd, message, wParam, lParam);
+ break;
+
+ case TK_CLAIMFOCUS:
+ case TK_GEOMETRYREQ:
+ case TK_ATTACHWINDOW:
+ case TK_DETACHWINDOW:
+ case TK_ICONIFY:
+ case TK_DEICONIFY:
+ case TK_MOVEWINDOW:
+ case TK_WITHDRAW:
+ case TK_RAISEWINDOW:
+ case TK_GETFRAMEWID:
+ case TK_OVERRIDEREDIRECT:
+ case TK_SETMENU:
+ case TK_STATE:
+ case TK_INFO:
+ result = TkWinEmbeddedEventProc(hwnd, message, wParam, lParam);
+ break;
+
+ case WM_UNICHAR:
+ if (wParam == UNICODE_NOCHAR) {
+ /* If wParam is UNICODE_NOCHAR and the application processes
+ * this message, then return TRUE. */
+ result = 1;
+ } else {
+ /* If the event was translated, we must return 0 */
+ if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
+ result = 0;
} else {
- /* If the event was translated, we must return 0 */
- if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam,
- &result)) {
- result = 0;
- } else {
- result = 1;
- }
+ result = 1;
}
- break;
+ }
+ break;
- default:
- if (!Tk_TranslateWinEvent(hwnd, message, wParam, lParam,
- &result)) {
- result = DefWindowProc(hwnd, message, wParam, lParam);
- }
- break;
+ default:
+ if (!Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
+ result = DefWindowProc(hwnd, message, wParam, lParam);
+ }
+ break;
}
/*
@@ -869,8 +884,8 @@ TkWinChildProc(hwnd, message, wParam, lParam)
*
* Tk_TranslateWinEvent --
*
- * This function is called by widget window procedures to handle
- * the translation from Win32 events to Tk events.
+ * This function is called by widget window functions to handle the
+ * translation from Win32 events to Tk events.
*
* Results:
* Returns 1 if the event was handled, else 0.
@@ -882,75 +897,80 @@ TkWinChildProc(hwnd, message, wParam, lParam)
*/
int
-Tk_TranslateWinEvent(hwnd, message, wParam, lParam, resultPtr)
- HWND hwnd;
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
- LRESULT *resultPtr;
+Tk_TranslateWinEvent(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam,
+ LRESULT *resultPtr)
{
*resultPtr = 0;
switch (message) {
- case WM_RENDERFORMAT: {
- TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);
- if (winPtr) {
- TkWinClipboardRender(winPtr->dispPtr, wParam);
- }
- return 1;
+ case WM_RENDERFORMAT: {
+ TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);
+
+ if (winPtr) {
+ TkWinClipboardRender(winPtr->dispPtr, wParam);
}
+ return 1;
+ }
- case WM_COMMAND:
- case WM_NOTIFY:
- case WM_VSCROLL:
- case WM_HSCROLL: {
- /*
- * Reflect these messages back to the sender so that they
- * can be handled by the window proc for the control. Note
- * that we need to be careful not to reflect a message that
- * is targeted to this window, or we will loop.
- */
+ case WM_COMMAND:
+ case WM_NOTIFY:
+ case WM_VSCROLL:
+ case WM_HSCROLL: {
+ /*
+ * Reflect these messages back to the sender so that they can be
+ * handled by the window proc for the control. Note that we need to be
+ * careful not to reflect a message that is targeted to this window,
+ * or we will loop.
+ */
- HWND target = (message == WM_NOTIFY)
+ HWND target = (message == WM_NOTIFY)
? ((NMHDR*)lParam)->hwndFrom : (HWND) lParam;
- if (target && target != hwnd) {
- *resultPtr = SendMessage(target, message, wParam, lParam);
- return 1;
- }
- break;
- }
- case WM_LBUTTONDOWN:
- case WM_LBUTTONDBLCLK:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONDBLCLK:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONDBLCLK:
- case WM_LBUTTONUP:
- case WM_MBUTTONUP:
- case WM_RBUTTONUP:
- case WM_MOUSEMOVE:
- Tk_PointerEvent(hwnd, (short) LOWORD(lParam),
- (short) HIWORD(lParam));
+ if (target && target != hwnd) {
+ *resultPtr = SendMessage(target, message, wParam, lParam);
return 1;
+ }
+ break;
+ }
- 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);
- return 1;
- case WM_MENUCHAR:
- GenerateXEvent(hwnd, message, wParam, lParam);
- /* MNC_CLOSE is the only one that looks right. This is a hack. */
- *resultPtr = MAKELONG (0, MNC_CLOSE);
- return 1;
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_MBUTTONDOWN:
+ case WM_MBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONDBLCLK:
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MOUSEMOVE:
+ Tk_PointerEvent(hwnd, (short) LOWORD(lParam), (short) HIWORD(lParam));
+ return 1;
+
+ 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);
+ return 1;
+ case WM_MENUCHAR:
+ GenerateXEvent(hwnd, message, wParam, lParam);
+
+ /*
+ * MNC_CLOSE is the only one that looks right. This is a hack.
+ */
+
+ *resultPtr = MAKELONG (0, MNC_CLOSE);
+ return 1;
}
return 0;
}
@@ -960,8 +980,8 @@ Tk_TranslateWinEvent(hwnd, message, wParam, lParam, resultPtr)
*
* GenerateXEvent --
*
- * This routine generates an X event from the corresponding
- * Windows event.
+ * This routine generates an X event from the corresponding Windows
+ * event.
*
* Results:
* None.
@@ -973,281 +993,286 @@ Tk_TranslateWinEvent(hwnd, message, wParam, lParam, resultPtr)
*/
static void
-GenerateXEvent(hwnd, message, wParam, lParam)
- HWND hwnd;
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
+GenerateXEvent(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
{
XEvent event;
- TkWindow *winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd);
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ TkWindow *winPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd);
if (!winPtr || winPtr->window == None) {
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;
switch (message) {
- case WM_PAINT: {
- PAINTSTRUCT ps;
-
- event.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;
- EndPaint(hwnd, &ps);
- event.xexpose.count = 0;
- break;
- }
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+
+ event.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;
+ EndPaint(hwnd, &ps);
+ event.xexpose.count = 0;
+ break;
+ }
- case WM_CLOSE:
- event.type = ClientMessage;
- event.xclient.message_type =
+ case WM_CLOSE:
+ event.type = ClientMessage;
+ event.xclient.message_type =
Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS");
- event.xclient.format = 32;
- event.xclient.data.l[0] =
+ event.xclient.format = 32;
+ event.xclient.data.l[0] =
Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW");
- break;
+ break;
- case WM_SETFOCUS:
- case WM_KILLFOCUS: {
- TkWindow *otherWinPtr = (TkWindow *)Tk_HWNDToWindow((HWND) wParam);
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS: {
+ TkWindow *otherWinPtr = (TkWindow *) Tk_HWNDToWindow((HWND) wParam);
- /*
- * Compare toplevel windows to avoid reporting focus
- * changes within the same toplevel.
- */
+ /*
+ * Compare toplevel windows to avoid reporting focus changes within
+ * the same toplevel.
+ */
- while (!(winPtr->flags & TK_TOP_LEVEL)) {
- winPtr = winPtr->parentPtr;
- if (winPtr == NULL) {
- return;
- }
- }
- while (otherWinPtr && !(otherWinPtr->flags & TK_TOP_LEVEL)) {
- otherWinPtr = otherWinPtr->parentPtr;
+ while (!(winPtr->flags & TK_TOP_LEVEL)) {
+ winPtr = winPtr->parentPtr;
+ if (winPtr == NULL) {
+ return;
}
+ }
+ while (otherWinPtr && !(otherWinPtr->flags & TK_TOP_LEVEL)) {
+ otherWinPtr = otherWinPtr->parentPtr;
+ }
- /*
- * Do a catch-all Tk_SetCaretPos here to make sure that the
- * window receiving focus sets the caret at least once.
- */
- if (message == WM_SETFOCUS) {
- Tk_SetCaretPos((Tk_Window) winPtr, 0, 0, 0);
- }
+ /*
+ * Do a catch-all Tk_SetCaretPos here to make sure that the window
+ * receiving focus sets the caret at least once.
+ */
- if (otherWinPtr == winPtr) {
- return;
- }
+ if (message == WM_SETFOCUS) {
+ Tk_SetCaretPos((Tk_Window) winPtr, 0, 0, 0);
+ }
- event.xany.window = winPtr->window;
- event.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut;
- event.xfocus.mode = NotifyNormal;
- event.xfocus.detail = NotifyNonlinear;
+ if (otherWinPtr == winPtr) {
+ return;
+ }
+
+ event.xany.window = winPtr->window;
+ event.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut;
+ event.xfocus.mode = NotifyNormal;
+ event.xfocus.detail = NotifyNonlinear;
+
+ /*
+ * Destroy the caret if we own it. If we are moving to another Tk
+ * window, it will reclaim and reposition it with Tk_SetCaretPos.
+ */
+ if (message == WM_KILLFOCUS) {
+ DestroyCaret();
+ }
+ break;
+ }
+
+ case WM_DESTROYCLIPBOARD:
+ if (tsdPtr->updatingClipboard == TRUE) {
/*
- * Destroy the caret if we own it. If we are moving to another Tk
- * window, it will reclaim and reposition it with Tk_SetCaretPos.
+ * We want to avoid this event if we are the ones that caused this
+ * event.
*/
- if (message == WM_KILLFOCUS) {
- DestroyCaret();
- }
- break;
- }
- case WM_DESTROYCLIPBOARD:
- if (tsdPtr->updatingClipboard == TRUE) {
- /*
- * We want to avoid this event if we are the ones that caused
- * this event.
- */
- return;
- }
- event.type = SelectionClear;
- event.xselectionclear.selection =
+ return;
+ }
+ event.type = SelectionClear;
+ event.xselectionclear.selection =
Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD");
- event.xselectionclear.time = TkpGetMS();
- break;
+ event.xselectionclear.time = TkpGetMS();
+ 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:
+ case WM_SYSKEYUP:
+ case WM_KEYDOWN:
+ case WM_KEYUP: {
+ unsigned int state = GetState(message, wParam, lParam);
+ Time time = TkpGetMS();
+ POINT clientPoint;
+ union {DWORD msgpos; POINTS point;} root; /* Note: POINT and POINTS are different */
+
+ /*
+ * Compute the screen and window coordinates of the event.
+ */
+
+ root.msgpos = GetMessagePos();
+ clientPoint.x = root.point.x;
+ clientPoint.y = root.point.y;
+ ScreenToClient(hwnd, &clientPoint);
+
+ /*
+ * 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;
+
+ /*
+ * Now set up event specific fields.
+ */
+
+ switch (message) {
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.
+ * We have invented a new X event type to handle this event. It
+ * still uses the KeyPress struct. However, the keycode field has
+ * been overloaded to hold the zDelta of the wheel. Set nbytes to
+ * 0 to prevent conversion of the keycode to a keysym in
+ * TkpGetString. [Bug 1118340].
*/
- case WM_CHAR:
- case WM_UNICHAR:
+ event.type = MouseWheelEvent;
+ event.xany.send_event = -1;
+ event.xkey.nbytes = 0;
+ event.xkey.keycode = (short) HIWORD(wParam);
+ break;
case WM_SYSKEYDOWN:
- case WM_SYSKEYUP:
case WM_KEYDOWN:
- case WM_KEYUP: {
- unsigned int state = GetState(message, wParam, lParam);
- Time time = TkpGetMS();
- POINT clientPoint;
- POINTS rootPoint; /* Note: POINT and POINTS are different */
- DWORD msgPos;
-
/*
- * Compute the screen and window coordinates of the event.
+ * Check for translated characters in the event queue. Setting
+ * xany.send_event to -1 indicates to the Windows implementation
+ * of TkpGetString() that this event was generated by windows and
+ * that the Windows extension xkey.trans_chars is filled with the
+ * MBCS characters that came from the TranslateMessage call.
*/
- msgPos = GetMessagePos();
- rootPoint = MAKEPOINTS(msgPos);
- clientPoint.x = rootPoint.x;
- clientPoint.y = rootPoint.y;
- ScreenToClient(hwnd, &clientPoint);
+ event.type = KeyPress;
+ event.xany.send_event = -1;
+ event.xkey.keycode = wParam;
+ GetTranslatedKey(&event.xkey);
+ break;
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
/*
- * Set up the common event fields.
+ * We don't check for translated characters on keyup because Tk
+ * won't know what to do with them. Instead, we wait for the
+ * WM_CHAR messages which will follow.
*/
- 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 = rootPoint.x;
- event.xbutton.y_root = rootPoint.y;
- event.xbutton.state = state;
- event.xbutton.time = time;
- event.xbutton.same_screen = True;
+ event.type = KeyRelease;
+ event.xkey.keycode = wParam;
+ event.xkey.nbytes = 0;
+ break;
+ case WM_CHAR:
/*
- * Now set up event specific fields.
+ * Synthesize both a KeyPress and a KeyRelease. Strings generated
+ * by Input Method Editor are handled in the following manner:
+ * 1. A series of WM_KEYDOWN & WM_KEYUP messages that cause
+ * GetTranslatedKey() to be called and return immediately
+ * because the WM_KEYDOWNs have no associated WM_CHAR messages
+ * -- the IME window is accumulating the characters and
+ * translating them itself. In the "bind" command, you get an
+ * event with a mystery keysym and %A == "" for each WM_KEYDOWN
+ * that actually was meant for the IME.
+ * 2. A WM_KEYDOWN corresponding to the "confirm typing"
+ * character. This causes GetTranslatedKey() to be called.
+ * 3. A WM_IME_NOTIFY message saying that the IME is done. A side
+ * effect of this message is that GetTranslatedKey() thinks
+ * this means that there are no WM_CHAR messages and returns
+ * immediately. In the "bind" command, you get an another event
+ * with a mystery keysym and %A == "".
+ * 4. A sequence of WM_CHAR messages that correspond to the
+ * characters in the IME window. A bunch of simulated
+ * KeyPress/KeyRelease events will be generated, one for each
+ * character. Adjacent WM_CHAR messages may actually specify
+ * the high and low bytes of a multi-byte character -- in that
+ * case the two WM_CHAR messages will be combined into one
+ * event. It is the event-consumer's responsibility to convert
+ * the string returned from XLookupString from system encoding
+ * to UTF-8.
+ * 5. And finally we get the WM_KEYUP for the "confirm typing"
+ * character.
*/
- switch (message) {
- case WM_MOUSEWHEEL:
- /*
- * We have invented a new X event type to handle
- * this event. It still uses the KeyPress struct.
- * However, the keycode field has been overloaded
- * to hold the zDelta of the wheel. Set nbytes to 0
- * to prevent conversion of the keycode to a keysym
- * in TkpGetString. [Bug 1118340].
- */
-
- event.type = MouseWheelEvent;
- event.xany.send_event = -1;
- event.xkey.nbytes = 0;
- event.xkey.keycode = (short) HIWORD(wParam);
- break;
- case WM_SYSKEYDOWN:
- case WM_KEYDOWN:
- /*
- * Check for translated characters in the event queue.
- * Setting xany.send_event to -1 indicates to the
- * Windows implementation of TkpGetString() that this
- * event was generated by windows and that the Windows
- * extension xkey.trans_chars is filled with the
- * MBCS characters that came from the TranslateMessage
- * call.
- */
-
- event.type = KeyPress;
- event.xany.send_event = -1;
- event.xkey.keycode = wParam;
- GetTranslatedKey(&event.xkey);
- break;
-
- case WM_SYSKEYUP:
- case WM_KEYUP:
- /*
- * We don't check for translated characters on keyup
- * because Tk won't know what to do with them. Instead, we
- * wait for the WM_CHAR messages which will follow.
- */
- event.type = KeyRelease;
- event.xkey.keycode = wParam;
- event.xkey.nbytes = 0;
- break;
-
- case WM_CHAR:
- /*
- * Synthesize both a KeyPress and a KeyRelease.
- * Strings generated by Input Method Editor are handled
- * in the following manner:
- * 1. A series of WM_KEYDOWN & WM_KEYUP messages that
- * cause GetTranslatedKey() to be called and return
- * immediately because the WM_KEYDOWNs have no
- * associated WM_CHAR messages -- the IME window is
- * accumulating the characters and translating them
- * itself. In the "bind" command, you get an event
- * with a mystery keysym and %A == "" for each
- * WM_KEYDOWN that actually was meant for the IME.
- * 2. A WM_KEYDOWN corresponding to the "confirm typing"
- * character. This causes GetTranslatedKey() to be
- * called.
- * 3. A WM_IME_NOTIFY message saying that the IME is
- * done. A side effect of this message is that
- * GetTranslatedKey() thinks this means that there
- * are no WM_CHAR messages and returns immediately.
- * In the "bind" command, you get an another event
- * with a mystery keysym and %A == "".
- * 4. A sequence of WM_CHAR messages that correspond to
- * the characters in the IME window. A bunch of
- * simulated KeyPress/KeyRelease events will be
- * generated, one for each character. Adjacent
- * WM_CHAR messages may actually specify the high
- * and low bytes of a multi-byte character -- in that
- * case the two WM_CHAR messages will be combined into
- * one event. It is the event-consumer's
- * responsibility to convert the string returned from
- * XLookupString from system encoding to UTF-8.
- * 5. And finally we get the WM_KEYUP for the "confirm
- * typing" character.
- */
-
- 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, 0, 0, PM_NOREMOVE) != 0)
- && (msg.message == WM_CHAR)) {
- GetMessage(&msg, NULL, 0, 0);
- event.xkey.nbytes = 2;
- event.xkey.trans_chars[1] = (char) msg.wParam;
- }
- }
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
- event.type = KeyRelease;
- 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(wParam, buffer);
- for (i=0; i<event.xkey.nbytes && i<TCL_UTF_MAX; ++i) {
- event.xkey.trans_chars[i] = buffer[i];
- }
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
- event.type = KeyRelease;
- break;
+ 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, 0, 0, PM_NOREMOVE) != 0)
+ && (msg.message == WM_CHAR)) {
+ GetMessage(&msg, NULL, 0, 0);
+ event.xkey.nbytes = 2;
+ event.xkey.trans_chars[1] = (char) msg.wParam;
}
}
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ event.type = KeyRelease;
+ 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];
+ }
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ event.type = KeyRelease;
break;
}
- default:
- return;
+ }
+ break;
+ }
+
+ default:
+ /*
+ * Don't know how to translate this event, so ignore it. (It probably
+ * should not have got here, but ignoring it should be harmless.)
+ */
+
+ return;
}
+
+ /*
+ * Post the translated event to the main Tk event queue.
+ */
+
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
}
@@ -1256,12 +1281,12 @@ GenerateXEvent(hwnd, message, wParam, lParam)
*
* GetState --
*
- * This function constructs a state mask for the mouse buttons
- * and modifier keys as they were before the event occured.
+ * This function constructs a state mask for the mouse buttons and
+ * modifier keys as they were before the event occured.
*
* Results:
- * Returns a composite value of all the modifier and button state
- * flags that were set at the time the event occurred.
+ * Returns a composite value of all the modifier and button state flags
+ * that were set at the time the event occurred.
*
* Side effects:
* None.
@@ -1270,18 +1295,18 @@ GenerateXEvent(hwnd, message, wParam, lParam)
*/
static unsigned int
-GetState(message, wParam, lParam)
- UINT message; /* Win32 message type */
- WPARAM wParam; /* wParam of message, used if key message */
- LPARAM lParam; /* lParam of message, used if key message */
+GetState(
+ UINT message, /* Win32 message type */
+ WPARAM wParam, /* wParam of message, used if key message */
+ LPARAM lParam) /* lParam of message, used if key message */
{
int mask;
int prevState; /* 1 if key was previously down */
unsigned int state = TkWinGetModifierState();
/*
- * If the event is a key press or release, we check for modifier
- * keys so we can report the state of the world before the event.
+ * If the event is a key press or release, we check for modifier keys so
+ * we can report the state of the world before the event.
*/
if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN
@@ -1289,39 +1314,46 @@ GetState(message, wParam, lParam)
mask = 0;
prevState = HIWORD(lParam) & KF_REPEAT;
switch(wParam) {
- case VK_SHIFT:
- mask = ShiftMask;
- break;
- case VK_CONTROL:
- mask = ControlMask;
- break;
- case VK_MENU:
- mask = ALT_MASK;
- break;
- case VK_CAPITAL:
- if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
- mask = LockMask;
- prevState = ((state & mask) ^ prevState) ? 0 : 1;
- }
- break;
- case VK_NUMLOCK:
- if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
- mask = Mod1Mask;
- prevState = ((state & mask) ^ prevState) ? 0 : 1;
- }
- break;
- case VK_SCROLL:
- if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
- mask = Mod3Mask;
- prevState = ((state & mask) ^ prevState) ? 0 : 1;
- }
- break;
+ case VK_SHIFT:
+ mask = ShiftMask;
+ break;
+ case VK_CONTROL:
+ mask = ControlMask;
+ break;
+ case VK_MENU:
+ mask = ALT_MASK;
+ break;
+ case VK_CAPITAL:
+ if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
+ mask = LockMask;
+ prevState = ((state & mask) ^ prevState) ? 0 : 1;
+ }
+ break;
+ case VK_NUMLOCK:
+ if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
+ mask = Mod1Mask;
+ prevState = ((state & mask) ^ prevState) ? 0 : 1;
+ }
+ break;
+ case VK_SCROLL:
+ if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
+ mask = Mod3Mask;
+ prevState = ((state & mask) ^ prevState) ? 0 : 1;
+ }
+ break;
}
if (prevState) {
state |= mask;
} else {
state &= ~mask;
}
+ if (HIWORD(lParam) & KF_EXTENDED) {
+ if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
+ state |= EXTENDED_MASK;
+ } else {
+ state &= ~EXTENDED_MASK;
+ }
+ }
}
return state;
}
@@ -1331,61 +1363,59 @@ GetState(message, wParam, lParam)
*
* GetTranslatedKey --
*
- * Retrieves WM_CHAR messages that are placed on the system queue
- * by the TranslateMessage system call and places them in the
- * given KeyPress event.
+ * Retrieves WM_CHAR messages that are placed on the system queue by the
+ * TranslateMessage system call and places them in the given KeyPress
+ * event.
*
* Results:
* Sets the trans_chars and nbytes member of the key event.
*
* Side effects:
- * Removes any WM_CHAR messages waiting on the top of the system
- * event queue.
+ * Removes any WM_CHAR messages waiting on the top of the system event
+ * queue.
*
*----------------------------------------------------------------------
*/
static void
-GetTranslatedKey(xkey)
- XKeyEvent *xkey;
+GetTranslatedKey(
+ XKeyEvent *xkey)
{
MSG msg;
-
+
xkey->nbytes = 0;
while ((xkey->nbytes < XMaxTransChars)
&& PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
- if ((msg.message == WM_CHAR) || (msg.message == WM_SYSCHAR)) {
- GetMessage(&msg, NULL, 0, 0);
+ if ((msg.message != WM_CHAR) && (msg.message != WM_SYSCHAR)) {
+ break;
+ }
+
+ GetMessage(&msg, NULL, 0, 0);
+
+ /*
+ * If this is a normal character message, we may need to strip off the
+ * Alt modifier (e.g. Alt-digits). Note that we don't want to do this
+ * for system messages, because those were presumably generated as an
+ * Alt-char sequence (e.g. accelerator keys).
+ */
+ if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
+ xkey->state = 0;
+ }
+ xkey->trans_chars[xkey->nbytes] = (char) msg.wParam;
+ xkey->nbytes++;
+
+ if (((unsigned short) msg.wParam) > ((unsigned short) 0xff)) {
/*
- * If this is a normal character message, we may need to strip
- * off the Alt modifier (e.g. Alt-digits). Note that we don't
- * want to do this for system messages, because those were
- * presumably generated as an Alt-char sequence (e.g. accelerator
- * keys).
+ * Some "addon" input devices, such as the popular PenPower
+ * Chinese writing pad, generate 16 bit values in WM_CHAR messages
+ * (instead of passing them in two separate WM_CHAR messages
+ * containing two 8-bit values.
*/
- if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
- xkey->state = 0;
- }
- xkey->trans_chars[xkey->nbytes] = (char) msg.wParam;
- xkey->nbytes++;
-
- if (((unsigned short) msg.wParam) > ((unsigned short) 0xff)) {
- /*
- * Some "addon" input devices, such as the popular
- * PenPower Chinese writing pad, generate 16 bit
- * values in WM_CHAR messages (instead of passing them
- * in two separate WM_CHAR messages containing two
- * 8-bit values.
- */
-
- xkey->trans_chars[xkey->nbytes] = (char) (msg.wParam >> 8);
- xkey->nbytes ++;
- }
- } else {
- break;
+ xkey->trans_chars[xkey->nbytes] = (char) (msg.wParam >> 8);
+ xkey->nbytes ++;
}
}
}
@@ -1396,11 +1426,11 @@ GetTranslatedKey(xkey)
* UpdateInputLanguage --
*
* Gets called when a WM_INPUTLANGCHANGE message is received by the Tk
- * child window procedure. This message is sent by the Input Method
- * Editor system when the user chooses a different input method. All
- * subsequent WM_CHAR messages will contain characters in the new
- * encoding. We record the new encoding so that TkpGetString() knows how
- * to correctly translate the WM_CHAR into unicode.
+ * child window function. This message is sent by the Input Method Editor
+ * system when the user chooses a different input method. All subsequent
+ * WM_CHAR messages will contain characters in the new encoding. We
+ * record the new encoding so that TkpGetString() knows how to correctly
+ * translate the WM_CHAR into unicode.
*
* Results:
* Records the new encoding in keyInputEncoding.
@@ -1412,8 +1442,8 @@ GetTranslatedKey(xkey)
*/
static void
-UpdateInputLanguage(charset)
- int charset;
+UpdateInputLanguage(
+ int charset)
{
CHARSETINFO charsetInfo;
Tcl_Encoding encoding;
@@ -1422,8 +1452,8 @@ UpdateInputLanguage(charset)
if (keyInputCharset == charset) {
return;
}
- if (TranslateCharsetInfo((DWORD*)charset, &charsetInfo, TCI_SRCCHARSET)
- == 0) {
+ if (TranslateCharsetInfo((DWORD*)charset, &charsetInfo,
+ TCI_SRCCHARSET) == 0) {
/*
* Some mysterious failure.
*/
@@ -1454,8 +1484,8 @@ UpdateInputLanguage(charset)
*
* TkWinGetKeyInputEncoding --
*
- * Returns the current keyboard input encoding selected by the
- * user (with WM_INPUTLANGCHANGE events).
+ * Returns the current keyboard input encoding selected by the user (with
+ * WM_INPUTLANGCHANGE events).
*
* Results:
* The current keyboard input encoding.
@@ -1467,7 +1497,7 @@ UpdateInputLanguage(charset)
*/
Tcl_Encoding
-TkWinGetKeyInputEncoding()
+TkWinGetKeyInputEncoding(void)
{
return keyInputEncoding;
}
@@ -1489,7 +1519,7 @@ TkWinGetKeyInputEncoding()
*/
Tcl_Encoding
-TkWinGetUnicodeEncoding()
+TkWinGetUnicodeEncoding(void)
{
if (unicodeEncoding == NULL) {
unicodeEncoding = Tcl_GetEncoding(NULL, "unicode");
@@ -1502,23 +1532,22 @@ TkWinGetUnicodeEncoding()
*
* HandleIMEComposition --
*
- * This function works around a definciency in some versions
- * of Windows 2000 to make it possible to entry multi-lingual
- * characters under all versions of Windows 2000.
+ * This function works around a definciency in some versions of Windows
+ * 2000 to make it possible to entry multi-lingual characters under all
+ * versions of Windows 2000.
*
- * When an Input Method Editor (IME) is ready to send input
- * characters to an application, it sends a WM_IME_COMPOSITION
- * message with the GCS_RESULTSTR. However, The DefWindowProc()
- * on English Windows 2000 arbitrarily converts all non-Latin-1
- * characters in the composition to "?".
+ * When an Input Method Editor (IME) is ready to send input characters to
+ * an application, it sends a WM_IME_COMPOSITION message with the
+ * GCS_RESULTSTR. However, The DefWindowProc() on English Windows 2000
+ * arbitrarily converts all non-Latin-1 characters in the composition to
+ * "?".
*
- * This function correctly processes the composition data and
- * sends the UNICODE values of the composed characters to
- * TK's event queue.
+ * This function correctly processes the composition data and sends the
+ * UNICODE values of the composed characters to TK's event queue.
*
* Results:
* If this function has processed the composition data, returns 1.
- * Otherwise returns 0.
+ * Otherwise returns 0.
*
* Side effects:
* Key events are put into the TK event queue.
@@ -1527,109 +1556,115 @@ TkWinGetUnicodeEncoding()
*/
static int
-HandleIMEComposition(hwnd, lParam)
- HWND hwnd; /* Window receiving the message. */
- LPARAM lParam; /* Flags for the WM_IME_COMPOSITION
- * message */
+HandleIMEComposition(
+ HWND hwnd, /* Window receiving the message. */
+ LPARAM lParam) /* Flags for the WM_IME_COMPOSITION message */
{
HIMC hIMC;
- int i, n;
- XEvent event;
- char * buff;
- TkWindow *winPtr;
- Tcl_Encoding unicodeEncoding = TkWinGetUnicodeEncoding();
+ int n;
BOOL isWinNT = (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT);
if ((lParam & GCS_RESULTSTR) == 0) {
- /*
- * Composition is not finished yet.
- */
+ /*
+ * Composition is not finished yet.
+ */
- return 0;
+ return 0;
}
hIMC = ImmGetContext(hwnd);
- if (hIMC) {
+ if (!hIMC) {
+ return 0;
+ }
+
+ if (isWinNT) {
+ n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
+ } else {
+ n = ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, NULL, 0);
+ }
+
+ if (n > 0) {
+ char *buff = ckalloc((unsigned) n);
+ TkWindow *winPtr;
+ XEvent event;
+ int i;
+
if (isWinNT) {
- n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
+ n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff,
+ (unsigned) n);
} else {
- n = ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, NULL, 0);
- }
+ 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.
+ */
- if ((n > 0) && ((buff = (char *) ckalloc(n)) != NULL)) {
- if (isWinNT) {
- n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, n);
- } else {
- Tcl_DString utfString, unicodeString;
-
- n = ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, buff, 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(i);
- }
- n = i;
- memcpy(buff, Tcl_DStringValue(&unicodeString), n);
- Tcl_DStringFree(&utfString);
- Tcl_DStringFree(&unicodeString);
+ ckfree((char *) buff);
+ buff = (char *) ckalloc((unsigned) i);
}
+ n = i;
+ memcpy(buff, Tcl_DStringValue(&unicodeString), (unsigned) n);
+ Tcl_DStringFree(&utfString);
+ Tcl_DStringFree(&unicodeString);
+ }
+ /*
+ * 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
+ * char and there's no need to do encoding conversion.
+ *
+ * Note that the event *must* be zeroed out first; Tk plays cunning
+ * games with the overalls structure. [Bug 2992129]
+ */
+
+ winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);
+
+ memset(&event, 0, sizeof(XEvent));
+ event.xkey.serial = winPtr->display->request++;
+ event.xkey.send_event = -2;
+ event.xkey.display = winPtr->display;
+ event.xkey.window = winPtr->window;
+ event.xkey.root = RootWindow(winPtr->display, winPtr->screenNum);
+ event.xkey.subwindow = None;
+ 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; ) {
/*
- * 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 char and there's no need to
- * do encoding conversion.
+ * Simulate a pair of KeyPress and KeyRelease events for each
+ * UNICODE character in the composition.
*/
- winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd);
-
- event.xkey.serial = winPtr->display->request++;
- event.xkey.send_event = -2;
- event.xkey.display = winPtr->display;
- event.xkey.window = winPtr->window;
- event.xkey.root = RootWindow(winPtr->display, winPtr->screenNum);
- event.xkey.subwindow = None;
- 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;) {
- /*
- * Simulate a pair of KeyPress and KeyRelease events
- * for each UNICODE character in the composition.
- */
-
- event.xkey.trans_chars[0] = (char) buff[i++];
- event.xkey.trans_chars[1] = (char) buff[i++];
-
- event.type = KeyPress;
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
-
- event.type = KeyRelease;
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
- }
-
- ckfree(buff);
- }
- ImmReleaseContext(hwnd, hIMC);
- return 1;
- }
+ event.xkey.trans_chars[0] = (char) buff[i++];
+ event.xkey.trans_chars[1] = (char) buff[i++];
- return 0;
+ event.type = KeyPress;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+
+ event.type = KeyRelease;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ }
+
+ ckfree(buff);
+ }
+ ImmReleaseContext(hwnd, hIMC);
+ return 1;
}
/*
@@ -1649,10 +1684,11 @@ HandleIMEComposition(hwnd, lParam)
*/
void
-Tk_FreeXId(display, xid)
- Display *display;
- XID xid;
+Tk_FreeXId(
+ Display *display,
+ XID xid)
{
+ /* Do nothing */
}
/*
@@ -1660,65 +1696,66 @@ Tk_FreeXId(display, xid)
*
* TkWinResendEvent --
*
- * This function converts an X event into a Windows event and
- * invokes the specified windo procedure.
+ * This function converts an X event into a Windows event and invokes the
+ * specified windo function.
*
* Results:
* A standard Windows result.
*
* Side effects:
- * Invokes the window procedure
+ * Invokes the window function
*
*----------------------------------------------------------------------
*/
LRESULT
-TkWinResendEvent(wndproc, hwnd, eventPtr)
- WNDPROC wndproc;
- HWND hwnd;
- XEvent *eventPtr;
+TkWinResendEvent(
+ WNDPROC wndproc,
+ HWND hwnd,
+ XEvent *eventPtr)
{
UINT msg;
WPARAM wparam;
LPARAM lparam;
- if (eventPtr->type == ButtonPress) {
- switch (eventPtr->xbutton.button) {
- case Button1:
- msg = WM_LBUTTONDOWN;
- wparam = MK_LBUTTON;
- break;
- case Button2:
- msg = WM_MBUTTONDOWN;
- wparam = MK_MBUTTON;
- break;
- case Button3:
- msg = WM_RBUTTONDOWN;
- wparam = MK_RBUTTON;
- break;
- default:
- return 0;
- }
- if (eventPtr->xbutton.state & Button1Mask) {
- wparam |= MK_LBUTTON;
- }
- if (eventPtr->xbutton.state & Button2Mask) {
- wparam |= MK_MBUTTON;
- }
- if (eventPtr->xbutton.state & Button3Mask) {
- wparam |= MK_RBUTTON;
- }
- if (eventPtr->xbutton.state & ShiftMask) {
- wparam |= MK_SHIFT;
- }
- if (eventPtr->xbutton.state & ControlMask) {
- wparam |= MK_CONTROL;
- }
- lparam = MAKELPARAM((short) eventPtr->xbutton.x,
- (short) eventPtr->xbutton.y);
- } else {
+ if (eventPtr->type != ButtonPress) {
return 0;
}
+
+ switch (eventPtr->xbutton.button) {
+ case Button1:
+ msg = WM_LBUTTONDOWN;
+ wparam = MK_LBUTTON;
+ break;
+ case Button2:
+ msg = WM_MBUTTONDOWN;
+ wparam = MK_MBUTTON;
+ break;
+ case Button3:
+ msg = WM_RBUTTONDOWN;
+ wparam = MK_RBUTTON;
+ break;
+ default:
+ return 0;
+ }
+
+ if (eventPtr->xbutton.state & Button1Mask) {
+ wparam |= MK_LBUTTON;
+ }
+ if (eventPtr->xbutton.state & Button2Mask) {
+ wparam |= MK_MBUTTON;
+ }
+ if (eventPtr->xbutton.state & Button3Mask) {
+ wparam |= MK_RBUTTON;
+ }
+ if (eventPtr->xbutton.state & ShiftMask) {
+ wparam |= MK_SHIFT;
+ }
+ if (eventPtr->xbutton.state & ControlMask) {
+ wparam |= MK_CONTROL;
+ }
+ lparam = MAKELPARAM((short) eventPtr->xbutton.x,
+ (short) eventPtr->xbutton.y);
return CallWindowProc(wndproc, hwnd, msg, wparam, lparam);
}
@@ -1727,8 +1764,8 @@ TkWinResendEvent(wndproc, hwnd, eventPtr)
*
* TkpGetMS --
*
- * Return a relative time in milliseconds. It doesn't matter
- * when the epoch was.
+ * Return a relative time in milliseconds. It doesn't matter when the
+ * epoch was.
*
* Results:
* Number of milliseconds.
@@ -1740,7 +1777,7 @@ TkWinResendEvent(wndproc, hwnd, eventPtr)
*/
unsigned long
-TkpGetMS()
+TkpGetMS(void)
{
return GetTickCount();
}
@@ -1761,9 +1798,10 @@ TkpGetMS()
*/
void
-TkWinUpdatingClipboard(int mode)
+TkWinUpdatingClipboard(
+ int mode)
{
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
tsdPtr->updatingClipboard = mode;
@@ -1774,17 +1812,17 @@ TkWinUpdatingClipboard(int mode)
*
* Tk_SetCaretPos --
*
- * This enables correct movement of focus in the MS Magnifier, as well
- * as allowing us to correctly position the IME Window. The following
- * Win32 APIs are used to work with MS caret:
+ * This enables correct movement of focus in the MS Magnifier, as well as
+ * allowing us to correctly position the IME Window. The following Win32
+ * APIs are used to work with MS caret:
*
* CreateCaret DestroyCaret SetCaretPos GetCaretPos
*
- * Only one instance of caret can be active at any time
- * (e.g. DestroyCaret API does not take any argument such as handle).
- * Since do-it-right approach requires to track the create/destroy
- * caret status all the time in a global scope among windows (or
- * widgets), we just implement this minimal setup to get the job done.
+ * Only one instance of caret can be active at any time (e.g.
+ * DestroyCaret API does not take any argument such as handle). Since
+ * do-it-right approach requires to track the create/destroy caret status
+ * all the time in a global scope among windows (or widgets), we just
+ * implement this minimal setup to get the job done.
*
* Results:
* None
@@ -1796,16 +1834,20 @@ TkWinUpdatingClipboard(int mode)
*/
void
-Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
+Tk_SetCaretPos(
+ Tk_Window tkwin,
+ int x, int y,
+ int height)
{
static HWND caretHWND = NULL;
TkCaret *caretPtr = &(((TkWindow *) tkwin)->dispPtr->caret);
Window win;
/*
- * Prevent processing anything if the values haven't changed.
- * Windows only has one display, so we can do this with statics.
+ * Prevent processing anything if the values haven't changed. Windows only
+ * has one display, so we can do this with statics.
*/
+
if ((caretPtr->winPtr == ((TkWindow *) tkwin))
&& (caretPtr->x == x) && (caretPtr->y == y)) {
return;
@@ -1817,9 +1859,8 @@ Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
caretPtr->height = height;
/*
- * We adjust to the toplevel to get the coords right, as setting
- * the IME composition window is based on the toplevel hwnd, so
- * ignore height.
+ * We adjust to the toplevel to get the coords right, as setting the IME
+ * composition window is based on the toplevel hwnd, so ignore height.
*/
while (!Tk_IsTopLevel(tkwin)) {
@@ -1852,11 +1893,13 @@ Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
* The IME composition window should be updated whenever the caret
* position is changed because a clause of the composition string may
* be converted to the final characters and the other clauses still
- * stay on the composition window. -- yamamoto
+ * stay on the composition window. -- yamamoto
*/
+
hIMC = ImmGetContext(hwnd);
if (hIMC) {
COMPOSITIONFORM cform;
+
cform.dwStyle = CFS_POINT;
cform.ptCurrentPos.x = x;
cform.ptCurrentPos.y = y;
@@ -1865,3 +1908,102 @@ Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height)
}
}
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetUserInactiveTime --
+ *
+ * Return the number of milliseconds the user was inactive.
+ *
+ * Results:
+ * Milliseconds of user inactive time or -1 if the user32.dll doesn't
+ * have the symbol GetLastInputInfo or GetLastInputInfo returns an error.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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...
+ */
+
+ 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)) {
+ return -1;
+ }
+
+ /*
+ * Last input info is in milliseconds, since restart time.
+ */
+
+ return (GetTickCount()-li.dwTime);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ResetUserInactiveTime --
+ *
+ * Reset the user inactivity timer
+ *
+ * Results:
+ * none
+ *
+ * Side effects:
+ * The user inactivity timer of the underlaying windowing system is reset
+ * to zero.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_ResetUserInactiveTime(
+ Display *dpy)
+{
+ INPUT inp;
+
+ inp.type = INPUT_MOUSE;
+ inp.mi.dx = 0;
+ inp.mi.dy = 0;
+ inp.mi.mouseData = 0;
+ inp.mi.dwFlags = MOUSEEVENTF_MOVE;
+ inp.mi.time = 0;
+ inp.mi.dwExtraInfo = (DWORD) NULL;
+
+ SendInput(1, &inp, sizeof(inp));
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */