diff options
Diffstat (limited to 'tk8.6/win/tkWinX.c')
-rw-r--r-- | tk8.6/win/tkWinX.c | 1955 |
1 files changed, 0 insertions, 1955 deletions
diff --git a/tk8.6/win/tkWinX.c b/tk8.6/win/tkWinX.c deleted file mode 100644 index fca72c3..0000000 --- a/tk8.6/win/tkWinX.c +++ /dev/null @@ -1,1955 +0,0 @@ -/* - * tkWinX.c -- - * - * 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. - */ - -#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. - */ - -#ifndef _WIN32_IE -#define _WIN32_IE 0x0550 /* IE 5.5 */ -#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. - */ - -#include <zmouse.h> - -/* - * imm.h is needed by HandleIMEComposition - */ - -#include <imm.h> -#ifdef _MSC_VER -# pragma comment (lib, "imm32.lib") -#endif - -/* - * WM_UNICHAR is a message for Unicode input on all windows systems. - * Perhaps this definition should be moved in another file. - */ -#ifndef WM_UNICHAR -#define WM_UNICHAR 0x0109 -#define UNICODE_NOCHAR 0xFFFF -#endif - -/* - * Declarations of static variables used in this file. - */ - -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. */ -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. - */ - -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; - -/* - * Forward declarations of functions used in this file. - */ - -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 UpdateInputLanguage(int charset); -static int HandleIMEComposition(HWND hwnd, LPARAM lParam); - -/* - *---------------------------------------------------------------------- - * - * TkGetServerInfo -- - * - * 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. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -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. */ -{ - static char buffer[32]; /* Empty string means not initialized yet. */ - OSVERSIONINFOW os; - - if (!buffer[0]) { - 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); - } - /* 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, -#ifdef _WIN64 - "Win64" -#else - "Win32" -#endif - ); - buffer[0] = 'W'; - } - Tcl_AppendResult(interp, buffer, NULL); -} - -/* - *---------------------------------------------------------------------- - * - * Tk_GetHINSTANCE -- - * - * Retrieves the global instance handle used by the Tk library. - * - * Results: - * Returns the global instance handle. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -HINSTANCE -Tk_GetHINSTANCE(void) -{ - if (tkInstance == NULL) { - tkInstance = GetModuleHandle(NULL); - } - return tkInstance; -} - -/* - *---------------------------------------------------------------------- - * - * TkWinSetHINSTANCE -- - * - * Sets the global instance handle used by the Tk library. This should be - * called by DllMain. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TkWinSetHINSTANCE( - HINSTANCE hInstance) -{ - tkInstance = hInstance; -} - -/* - *---------------------------------------------------------------------- - * - * TkWinXInit -- - * - * Initialize Xlib emulation layer. - * - * Results: - * None. - * - * Side effects: - * Sets up various data structures. - * - *---------------------------------------------------------------------- - */ - -void -TkWinXInit( - HINSTANCE hInstance) -{ - INITCOMMONCONTROLSEX comctl; - CHARSETINFO lpCs; - DWORD lpCP; - - if (childClassInitialized != 0) { - return; - } - childClassInitialized = 1; - - comctl.dwSize = sizeof(INITCOMMONCONTROLSEX); - comctl.dwICC = ICC_WIN95_CLASSES; - if (!InitCommonControlsEx(&comctl)) { - Tcl_Panic("Unable to load common controls?!"); - } - - childClass.style = CS_HREDRAW | CS_VREDRAW; - childClass.cbClsExtra = 0; - childClass.cbWndExtra = 0; - childClass.hInstance = hInstance; - childClass.hbrBackground = NULL; - childClass.lpszMenuName = NULL; - - /* - * Register the Child window class. - */ - - childClass.lpszClassName = TK_WIN_CHILD_CLASS_NAME; - childClass.lpfnWndProc = TkWinChildProc; - childClass.hIcon = NULL; - childClass.hCursor = NULL; - - if (!RegisterClass(&childClass)) { - Tcl_Panic("Unable to register TkChild class"); - } - - /* - * Initialize input language info - */ - - if (GetLocaleInfo(LANGIDFROMLCID(PTR2INT(GetKeyboardLayout(0))), - LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, - (LPTSTR) &lpCP, sizeof(lpCP)/sizeof(TCHAR)) - && TranslateCharsetInfo(INT2PTR(lpCP), &lpCs, TCI_SRCCODEPAGE)) { - UpdateInputLanguage((int) lpCs.ciCharset); - } - - /* - * Make sure we cleanup on finalize. - */ - - TkCreateExitHandler(TkWinXCleanup, (ClientData) hInstance); -} - -/* - *---------------------------------------------------------------------- - * - * TkWinXCleanup -- - * - * Removes the registered classes for Tk. - * - * Results: - * None. - * - * Side effects: - * Removes window classes from the system. - * - *---------------------------------------------------------------------- - */ - -void -TkWinXCleanup( - ClientData clientData) -{ - HINSTANCE hInstance = (HINSTANCE) clientData; - - /* - * Clean up our own class. - */ - - if (childClassInitialized) { - childClassInitialized = 0; - UnregisterClass(TK_WIN_CHILD_CLASS_NAME, hInstance); - } - - if (unicodeEncoding != NULL) { - Tcl_FreeEncoding(unicodeEncoding); - unicodeEncoding = NULL; - } - - /* - * And let the window manager clean up its own class(es). - */ - - TkWinWmCleanup(hInstance); - TkWinCleanupContainerList(); -} - -/* - *---------------------------------------------------------------------- - * - * TkWinGetPlatformId -- - * - * 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 (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. - * - *---------------------------------------------------------------------- - */ - -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; - LPCTSTR szSubKey = TEXT("Control Panel\\Appearance"); - LPCTSTR szCurrent = TEXT("Current"); - 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; - } else { - 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; - } - } - return tkPlatformId; -} - -/* - *---------------------------------------------------------------------- - * - * 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; -} - -/* - *---------------------------------------------------------------------- - * - * TkGetDefaultScreenName -- - * - * Returns the name of the screen that Tk should use during - * initialization. - * - * Results: - * Returns a statically allocated string. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -const char * -TkGetDefaultScreenName( - Tcl_Interp *interp, /* Not used. */ - const char *screenName) /* If NULL, use default string. */ -{ - if ((screenName == NULL) || (screenName[0] == '\0')) { - screenName = winScreenName; - } - return screenName; -} - -/* - *---------------------------------------------------------------------- - * - * TkWinDisplayChanged -- - * - * Called to set up initial screen info or when an event indicated - * display (screen) change. - * - * Results: - * None. - * - * Side effects: - * May change info regarding the screen. - * - *---------------------------------------------------------------------- - */ - -void -TkWinDisplayChanged( - Display *display) -{ - HDC dc; - Screen *screen; - - if (display == NULL || display->screens == NULL) { - return; - } - screen = display->screens; - - dc = GetDC(NULL); - screen->width = GetDeviceCaps(dc, HORZRES); - screen->height = GetDeviceCaps(dc, VERTRES); - screen->mwidth = MulDiv(screen->width, 254, - GetDeviceCaps(dc, LOGPIXELSX) * 10); - screen->mheight = MulDiv(screen->height, 254, - GetDeviceCaps(dc, LOGPIXELSY) * 10); - - /* - * 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 - * HBITMAP for offscreen rendering, we can specify the correct value for - * 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. - */ - - screen->ext_data = INT2PTR(GetDeviceCaps(dc, PLANES)); - screen->root_depth = GetDeviceCaps(dc, BITSPIXEL) * PTR2INT(screen->ext_data); - - if (screen->root_visual != NULL) { - ckfree(screen->root_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); - screen->root_visual->class = PseudoColor; - screen->root_visual->red_mask = 0x0; - screen->root_visual->green_mask = 0x0; - screen->root_visual->blue_mask = 0x0; - } else if (screen->root_depth == 4) { - screen->root_visual->class = StaticColor; - screen->root_visual->map_entries = 16; - } else if (screen->root_depth == 8) { - screen->root_visual->class = StaticColor; - screen->root_visual->map_entries = 256; - } else if (screen->root_depth == 12) { - screen->root_visual->class = TrueColor; - screen->root_visual->map_entries = 32; - screen->root_visual->red_mask = 0xf0; - screen->root_visual->green_mask = 0xf000; - screen->root_visual->blue_mask = 0xf00000; - } else if (screen->root_depth == 16) { - screen->root_visual->class = TrueColor; - screen->root_visual->map_entries = 64; - screen->root_visual->red_mask = 0xf8; - screen->root_visual->green_mask = 0xfc00; - screen->root_visual->blue_mask = 0xf80000; - } else if (screen->root_depth >= 24) { - screen->root_visual->class = TrueColor; - screen->root_visual->map_entries = 256; - screen->root_visual->red_mask = 0xff; - screen->root_visual->green_mask = 0xff00; - screen->root_visual->blue_mask = 0xff0000; - } - screen->root_visual->bits_per_rgb = screen->root_depth; - ReleaseDC(NULL, dc); - - if (screen->cmap != None) { - XFreeColormap(display, screen->cmap); - } - screen->cmap = XCreateColormap(display, None, screen->root_visual, - AllocNone); -} - -/* - *---------------------------------------------------------------------- - * - * TkpOpenDisplay -- - * - * Create the Display structure and fill it with device specific - * information. - * - * Results: - * Returns a TkDisplay structure on success or NULL on failure. - * - * Side effects: - * Allocates a new TkDisplay structure. - * - *---------------------------------------------------------------------- - */ - -TkDisplay * -TkpOpenDisplay( - const char *display_name) -{ - Screen *screen; - TkWinDrawable *twdPtr; - Display *display; - ThreadSpecificData *tsdPtr = - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - if (tsdPtr->winDisplay != NULL) { - if (!strcmp(tsdPtr->winDisplay->display->display_name, display_name)) { - return tsdPtr->winDisplay; - } else { - return NULL; - } - } - - display = ckalloc(sizeof(Display)); - ZeroMemory(display, sizeof(Display)); - - display->display_name = ckalloc(strlen(display_name) + 1); - strcpy(display->display_name, display_name); - - display->cursor_font = 1; - display->nscreens = 1; - display->request = 1; - display->qlen = 0; - - screen = ckalloc(sizeof(Screen)); - ZeroMemory(screen, sizeof(Screen)); - screen->display = display; - - /* - * Set up the root window. - */ - - twdPtr = ckalloc(sizeof(TkWinDrawable)); - if (twdPtr == NULL) { - return None; - } - twdPtr->type = TWD_WINDOW; - twdPtr->window.winPtr = NULL; - twdPtr->window.handle = NULL; - screen->root = (Window)twdPtr; - - /* - * Note that these pixel values are not palette relative. - */ - - screen->white_pixel = RGB(255, 255, 255); - screen->black_pixel = RGB(0, 0, 0); - screen->cmap = None; - - display->screens = screen; - display->nscreens = 1; - display->default_screen = 0; - - TkWinDisplayChanged(display); - - tsdPtr->winDisplay = ckalloc(sizeof(TkDisplay)); - ZeroMemory(tsdPtr->winDisplay, sizeof(TkDisplay)); - tsdPtr->winDisplay->display = display; - tsdPtr->updatingClipboard = FALSE; - - return tsdPtr->winDisplay; -} - -/* - *---------------------------------------------------------------------- - * - * TkpCloseDisplay -- - * - * Closes and deallocates a Display structure created with the - * TkpOpenDisplay function. - * - * Results: - * None. - * - * Side effects: - * Frees up memory. - * - *---------------------------------------------------------------------- - */ - -void -TkpCloseDisplay( - TkDisplay *dispPtr) -{ - Display *display = dispPtr->display; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - if (dispPtr != tsdPtr->winDisplay) { - Tcl_Panic("TkpCloseDisplay: tried to call TkpCloseDisplay on another display"); - return; /* not reached */ - } - - tsdPtr->winDisplay = NULL; - - if (display->display_name != NULL) { - ckfree(display->display_name); - } - if (display->screens != NULL) { - if (display->screens->root_visual != NULL) { - ckfree(display->screens->root_visual); - } - if (display->screens->root != None) { - ckfree(display->screens->root); - } - if (display->screens->cmap != None) { - XFreeColormap(display, display->screens->cmap); - } - ckfree(display->screens); - } - ckfree(display); -} - -/* - *---------------------------------------------------------------------- - * - * TkClipCleanup -- - * - * 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. - * - * Side effects: - * Resources are freed - the clipboard may no longer be used. - * - *---------------------------------------------------------------------- - */ - -void -TkClipCleanup( - TkDisplay *dispPtr) /* Display associated with clipboard. */ -{ - if (dispPtr->clipWindow != NULL) { - Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom, - dispPtr->applicationAtom); - Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom, - dispPtr->windowAtom); - - Tk_DestroyWindow(dispPtr->clipWindow); - Tcl_Release((ClientData) dispPtr->clipWindow); - dispPtr->clipWindow = NULL; - } -} - -/* - *---------------------------------------------------------------------- - * - * XBell -- - * - * Generate a beep. - * - * Results: - * None. - * - * Side effects: - * Plays a sounds out the system speakers. - * - *---------------------------------------------------------------------- - */ - -int -XBell( - Display *display, - int percent) -{ - MessageBeep(MB_OK); - return Success; -} - -/* - *---------------------------------------------------------------------- - * - * TkWinChildProc -- - * - * Callback from Windows whenever an event occurs on a child window. - * - * Results: - * Standard Windows return value. - * - * Side effects: - * May process events off the Tk event queue. - * - *---------------------------------------------------------------------- - */ - -LRESULT CALLBACK -TkWinChildProc( - HWND hwnd, - UINT message, - WPARAM wParam, - LPARAM lParam) -{ - LRESULT result; - - switch (message) { - 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; - - 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); - 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 { - result = 1; - } - } - break; - - default: - if (!Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) { - result = DefWindowProc(hwnd, message, wParam, lParam); - } - break; - } - - /* - * Handle any newly queued events before returning control to Windows. - */ - - Tcl_ServiceAll(); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * Tk_TranslateWinEvent -- - * - * 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. - * - * Side effects: - * Depends on the event. - * - *---------------------------------------------------------------------- - */ - -int -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_RENDERALLFORMATS: { - TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd); - - if (winPtr && OpenClipboard(hwnd)) { - /* - * Make sure that nobody had taken ownership of the clipboard - * before we opened it. - */ - - if (GetClipboardOwner() == hwnd) { - TkWinClipboardRender(winPtr->dispPtr, CF_TEXT); - } - CloseClipboard(); - } - 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. - */ - - 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)); - 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_SYSKEYUP: - 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; -} - -/* - *---------------------------------------------------------------------- - * - * GenerateXEvent -- - * - * This routine generates an X event from the corresponding Windows - * event. - * - * Results: - * None. - * - * Side effects: - * Queues one or more X events. - * - *---------------------------------------------------------------------- - */ - -static void -GenerateXEvent( - HWND hwnd, - UINT message, - WPARAM wParam, - LPARAM lParam) -{ - XEvent event; - TkWindow *winPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - 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; - } - - 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_CLOSE: - event.type = ClientMessage; - event.xclient.message_type = - Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS"); - event.xclient.format = 32; - event.xclient.data.l[0] = - Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW"); - break; - - 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. - */ - - 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); - } - - 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) { - /* - * We want to avoid this event if we are the ones that caused this - * event. - */ - - return; - } - event.type = SelectionClear; - event.xselectionclear.selection = - Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD"); - event.xselectionclear.time = TkpGetMS(); - break; - - case WM_MOUSEWHEEL: - 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: - /* - * 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, (message == WM_KEYDOWN) ? WM_CHAR : - WM_SYSCHAR); - 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; - 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); - event.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; - break; - } - - } - 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); -} - -/* - *---------------------------------------------------------------------- - * - * GetState -- - * - * 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. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static unsigned int -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 (message == WM_SYSKEYDOWN || message == WM_KEYDOWN - || message == WM_SYSKEYUP || message == WM_KEYUP) { - 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; - } - if (prevState) { - state |= mask; - } else { - state &= ~mask; - } - if (HIWORD(lParam) & KF_EXTENDED) { - state |= EXTENDED_MASK; - } - } - return state; -} - -/* - *---------------------------------------------------------------------- - * - * 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. - * - * 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. - * - *---------------------------------------------------------------------- - */ - -static void -GetTranslatedKey( - XKeyEvent *xkey, - UINT type) -{ - MSG msg; - - xkey->nbytes = 0; - - while ((xkey->nbytes < XMaxTransChars) - && (PeekMessageA(&msg, NULL, type, type, PM_NOREMOVE) != 0)) { - if (msg.message != type) { - break; - } - - GetMessageA(&msg, NULL, type, type); - - /* - * 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)) { - /* - * 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 ++; - } - } -} - -/* - *---------------------------------------------------------------------- - * - * UpdateInputLanguage -- - * - * Gets called when a WM_INPUTLANGCHANGE message is received by the Tk - * 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. - * - * Side effects: - * Old value of keyInputEncoding is freed. - * - *---------------------------------------------------------------------- - */ - -static void -UpdateInputLanguage( - int charset) -{ - CHARSETINFO charsetInfo; - Tcl_Encoding encoding; - char codepage[4 + TCL_INTEGER_SPACE]; - - if (keyInputCharset == charset) { - return; - } - if (TranslateCharsetInfo(INT2PTR(charset), &charsetInfo, - TCI_SRCCHARSET) == 0) { - /* - * Some mysterious failure. - */ - - return; - } - - wsprintfA(codepage, "cp%d", charsetInfo.ciACP); - - if ((encoding = Tcl_GetEncoding(NULL, codepage)) == NULL) { - /* - * The encoding is not supported by Tcl. - */ - - return; - } - - if (keyInputEncoding != NULL) { - Tcl_FreeEncoding(keyInputEncoding); - } - - keyInputEncoding = encoding; - keyInputCharset = charset; -} - -/* - *---------------------------------------------------------------------- - * - * TkWinGetKeyInputEncoding -- - * - * Returns the current keyboard input encoding selected by the user (with - * WM_INPUTLANGCHANGE events). - * - * Results: - * The current keyboard input encoding. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tcl_Encoding -TkWinGetKeyInputEncoding(void) -{ - return keyInputEncoding; -} - -/* - *---------------------------------------------------------------------- - * - * TkWinGetUnicodeEncoding -- - * - * Returns the cached unicode encoding. - * - * Results: - * The unicode encoding. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tcl_Encoding -TkWinGetUnicodeEncoding(void) -{ - if (unicodeEncoding == NULL) { - unicodeEncoding = Tcl_GetEncoding(NULL, "unicode"); - } - return unicodeEncoding; -} - -/* - *---------------------------------------------------------------------- - * - * HandleIMEComposition -- - * - * 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. - * - * 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. - * - * Results: - * If this function has processed the composition data, returns 1. - * Otherwise returns 0. - * - * Side effects: - * Key events are put into the TK event queue. - * - *---------------------------------------------------------------------- - */ - -static int -HandleIMEComposition( - HWND hwnd, /* Window receiving the message. */ - LPARAM lParam) /* Flags for the WM_IME_COMPOSITION message */ -{ - HIMC hIMC; - int n; - int high = 0; - - if ((lParam & GCS_RESULTSTR) == 0) { - /* - * Composition is not finished yet. - */ - - return 0; - } - - hIMC = ImmGetContext(hwnd); - if (!hIMC) { - return 0; - } - - n = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0); - - if (n > 0) { - WCHAR *buff = (WCHAR *) ckalloc(n); - TkWindow *winPtr; - XEvent event; - int i; - - 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 -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 - * 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 = -3; - 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; - - for (i=0; i<n; ) { - /* - * Simulate a pair of KeyPress and KeyRelease events for each - * UNICODE character in the composition. - */ - - 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); - - event.type = KeyRelease; - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - } - - ckfree(buff); - } - ImmReleaseContext(hwnd, hIMC); - return 1; -} - -/* - *---------------------------------------------------------------------- - * - * Tk_FreeXId -- - * - * This interface is not needed under Windows. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -Tk_FreeXId( - Display *display, - XID xid) -{ - /* Do nothing */ -} - -/* - *---------------------------------------------------------------------- - * - * TkWinResendEvent -- - * - * 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 function - * - *---------------------------------------------------------------------- - */ - -LRESULT -TkWinResendEvent( - WNDPROC wndproc, - HWND hwnd, - XEvent *eventPtr) -{ - UINT msg; - WPARAM wparam; - LPARAM lparam; - - 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); -} - -/* - *---------------------------------------------------------------------- - * - * TkpGetMS -- - * - * Return a relative time in milliseconds. It doesn't matter when the - * epoch was. - * - * Results: - * Number of milliseconds. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -unsigned long -TkpGetMS(void) -{ - return GetTickCount(); -} - -/* - *---------------------------------------------------------------------- - * - * TkWinUpdatingClipboard -- - * - * - * Results: - * Number of milliseconds. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TkWinUpdatingClipboard( - int mode) -{ - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - tsdPtr->updatingClipboard = 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: - * - * 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. - * - * Results: - * None - * - * Side effects: - * Sets the global Windows caret position. - * - *---------------------------------------------------------------------- - */ - -void -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. - */ - - if ((caretPtr->winPtr == ((TkWindow *) tkwin)) - && (caretPtr->x == x) && (caretPtr->y == y)) { - return; - } - - caretPtr->winPtr = ((TkWindow *) tkwin); - caretPtr->x = x; - caretPtr->y = y; - 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. - */ - - while (!Tk_IsTopLevel(tkwin)) { - x += Tk_X(tkwin); - y += Tk_Y(tkwin); - tkwin = Tk_Parent(tkwin); - if (tkwin == NULL) { - return; - } - } - - win = Tk_WindowId(tkwin); - if (win) { - HIMC hIMC; - HWND hwnd = Tk_GetHWND(win); - - if (hwnd != caretHWND) { - DestroyCaret(); - if (CreateCaret(hwnd, NULL, 0, 0)) { - caretHWND = hwnd; - } - } - - if (!SetCaretPos(x, y) && CreateCaret(hwnd, NULL, 0, 0)) { - caretHWND = hwnd; - SetCaretPos(x, y); - } - - /* - * 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 - */ - - hIMC = ImmGetContext(hwnd); - if (hIMC) { - COMPOSITIONFORM cform; - - cform.dwStyle = CFS_POINT; - cform.ptCurrentPos.x = x; - cform.ptCurrentPos.y = y; - ImmSetCompositionWindow(hIMC, &cform); - ImmReleaseContext(hwnd, hIMC); - } - } -} - -/* - *---------------------------------------------------------------------- - * - * 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 */ -{ - LASTINPUTINFO li; - - li.cbSize = sizeof(li); - if (!(BOOL)GetLastInputInfo(&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) 0; - - SendInput(1, &inp, sizeof(inp)); -} - -/* - * Local Variables: - * mode: c - * c-basic-offset: 4 - * fill-column: 78 - * End: - */ |