diff options
Diffstat (limited to 'tk8.6/win/tkWinPointer.c')
-rw-r--r-- | tk8.6/win/tkWinPointer.c | 546 |
1 files changed, 546 insertions, 0 deletions
diff --git a/tk8.6/win/tkWinPointer.c b/tk8.6/win/tkWinPointer.c new file mode 100644 index 0000000..6f1f840 --- /dev/null +++ b/tk8.6/win/tkWinPointer.c @@ -0,0 +1,546 @@ +/* + * tkWinPointer.c -- + * + * Windows specific mouse tracking code. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright (c) 1998-1999 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" + +/* + * Check for enter/leave events every MOUSE_TIMER_INTERVAL milliseconds. + */ + +#define MOUSE_TIMER_INTERVAL 250 + +/* + * Declarations of static variables used in this file. + */ + +static int captured = 0; /* 1 if mouse is currently captured. */ +static TkWindow *keyboardWinPtr = NULL; /* Current keyboard grab window. */ +static Tcl_TimerToken mouseTimer; /* Handle to the latest mouse timer. */ +static int mouseTimerSet = 0; /* 1 if the mouse timer is active. */ + +/* + * Forward declarations of procedures used in this file. + */ + +static void MouseTimerProc(ClientData clientData); + +/* + *---------------------------------------------------------------------- + * + * TkWinGetModifierState -- + * + * Return the modifier state as of the last message. + * + * Results: + * Returns the X modifier mask. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkWinGetModifierState(void) +{ + int state = 0; + + if (GetKeyState(VK_SHIFT) & 0x8000) { + state |= ShiftMask; + } + if (GetKeyState(VK_CONTROL) & 0x8000) { + state |= ControlMask; + } + if (GetKeyState(VK_MENU) & 0x8000) { + state |= ALT_MASK; + } + if (GetKeyState(VK_CAPITAL) & 0x0001) { + state |= LockMask; + } + if (GetKeyState(VK_NUMLOCK) & 0x0001) { + state |= Mod1Mask; + } + if (GetKeyState(VK_SCROLL) & 0x0001) { + state |= Mod3Mask; + } + if (GetKeyState(VK_LBUTTON) & 0x8000) { + state |= Button1Mask; + } + if (GetKeyState(VK_MBUTTON) & 0x8000) { + state |= Button2Mask; + } + if (GetKeyState(VK_RBUTTON) & 0x8000) { + state |= Button3Mask; + } + return state; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_PointerEvent -- + * + * This procedure is called for each pointer-related event. It converts + * the position to root coords and updates the global pointer state + * machine. It also ensures that the mouse timer is scheduled. + * + * Results: + * None. + * + * Side effects: + * May queue events and change the grab state. + * + *---------------------------------------------------------------------- + */ + +void +Tk_PointerEvent( + HWND hwnd, /* Window for coords, or NULL for the root + * window. */ + int x, int y) /* Coords relative to hwnd, or screen if hwnd + * is NULL. */ +{ + POINT pos; + int state; + Tk_Window tkwin; + + pos.x = x; + pos.y = y; + + /* + * Convert client coords to root coords if we were given a window. + */ + + if (hwnd) { + ClientToScreen(hwnd, &pos); + } + + /* + * If the mouse is captured, Windows will report all pointer events to the + * capture window. So, we need to determine which window the mouse is + * really over and change the event. Note that the computed hwnd may point + * to a window not owned by Tk, or a toplevel decorative frame, so tkwin + * can be NULL. + */ + + if (captured || hwnd == NULL) { + hwnd = WindowFromPoint(pos); + } + tkwin = Tk_HWNDToWindow(hwnd); + + state = TkWinGetModifierState(); + + Tk_UpdatePointer(tkwin, pos.x, pos.y, state); + + if ((captured || tkwin) && !mouseTimerSet) { + mouseTimerSet = 1; + mouseTimer = Tcl_CreateTimerHandler(MOUSE_TIMER_INTERVAL, + MouseTimerProc, NULL); + } +} + +/* + *---------------------------------------------------------------------- + * + * XGrabKeyboard -- + * + * Simulates a keyboard grab by setting the focus. + * + * Results: + * Always returns GrabSuccess. + * + * Side effects: + * Sets the keyboard focus to the specified window. + * + *---------------------------------------------------------------------- + */ + +int +XGrabKeyboard( + Display *display, + Window grab_window, + Bool owner_events, + int pointer_mode, + int keyboard_mode, + Time time) +{ + keyboardWinPtr = TkWinGetWinPtr(grab_window); + return GrabSuccess; +} + +/* + *---------------------------------------------------------------------- + * + * XUngrabKeyboard -- + * + * Releases the simulated keyboard grab. + * + * Results: + * None. + * + * Side effects: + * Sets the keyboard focus back to the value before the grab. + * + *---------------------------------------------------------------------- + */ + +int +XUngrabKeyboard( + Display *display, + Time time) +{ + keyboardWinPtr = NULL; + return Success; +} + +/* + *---------------------------------------------------------------------- + * + * MouseTimerProc -- + * + * Check the current mouse position and look for enter/leave events. + * + * Results: + * None. + * + * Side effects: + * May schedule a new timer and/or generate enter/leave events. + * + *---------------------------------------------------------------------- + */ + +void +MouseTimerProc( + ClientData clientData) +{ + POINT pos; + + mouseTimerSet = 0; + + /* + * Get the current mouse position and window. Don't do anything if the + * mouse hasn't moved since the last time we looked. + */ + + GetCursorPos(&pos); + Tk_PointerEvent(NULL, pos.x, pos.y); +} + +/* + *---------------------------------------------------------------------- + * + * TkWinCancelMouseTimer -- + * + * If the mouse timer is set, cancel it. + * + * Results: + * None. + * + * Side effects: + * May cancel the mouse timer. + * + *---------------------------------------------------------------------- + */ + +void +TkWinCancelMouseTimer(void) +{ + if (mouseTimerSet) { + Tcl_DeleteTimerHandler(mouseTimer); + mouseTimerSet = 0; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkGetPointerCoords -- + * + * Fetch the position of the mouse pointer. + * + * Results: + * *xPtr and *yPtr are filled in with the root coordinates of the mouse + * pointer for the display. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkGetPointerCoords( + Tk_Window tkwin, /* Window that identifies screen on which + * lookup is to be done. */ + int *xPtr, int *yPtr) /* Store pointer coordinates here. */ +{ + POINT point; + + GetCursorPos(&point); + *xPtr = point.x; + *yPtr = point.y; +} + +/* + *---------------------------------------------------------------------- + * + * XQueryPointer -- + * + * Check the current state of the mouse. This is not a complete + * implementation of this function. It only computes the root coordinates + * and the current mask. + * + * Results: + * Sets root_x_return, root_y_return, and mask_return. Returns true on + * success. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Bool +XQueryPointer( + Display *display, + Window w, + Window *root_return, + Window *child_return, + int *root_x_return, + int *root_y_return, + int *win_x_return, + int *win_y_return, + unsigned int *mask_return) +{ + display->request++; + TkGetPointerCoords(NULL, root_x_return, root_y_return); + *mask_return = TkWinGetModifierState(); + return True; +} + +/* + *---------------------------------------------------------------------- + * + * XWarpPointer -- + * + * Move pointer to new location. This is not a complete implementation of + * this function. + * + * Results: + * None. + * + * Side effects: + * Mouse pointer changes position on screen. + * + *---------------------------------------------------------------------- + */ + +int +XWarpPointer( + Display *display, + Window src_w, + Window dest_w, + int src_x, + int src_y, + unsigned int src_width, + unsigned int src_height, + int dest_x, + int dest_y) +{ + RECT r; + + GetWindowRect(Tk_GetHWND(dest_w), &r); + SetCursorPos(r.left+dest_x, r.top+dest_y); + return Success; +} + +void +TkpWarpPointer( + TkDisplay *dispPtr) +{ + if (dispPtr->warpWindow) { + RECT r; + + GetWindowRect(Tk_GetHWND(Tk_WindowId(dispPtr->warpWindow)), &r); + SetCursorPos(r.left + dispPtr->warpX, r.top + dispPtr->warpY); + } else { + SetCursorPos(dispPtr->warpX, dispPtr->warpY); + } +} + +/* + *---------------------------------------------------------------------- + * + * XGetInputFocus -- + * + * Retrieves the current keyboard focus window. + * + * Results: + * Returns the current focus window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +XGetInputFocus( + Display *display, + Window *focus_return, + int *revert_to_return) +{ + Tk_Window tkwin = Tk_HWNDToWindow(GetFocus()); + + *focus_return = tkwin ? Tk_WindowId(tkwin) : None; + *revert_to_return = RevertToParent; + display->request++; + return Success; +} + +/* + *---------------------------------------------------------------------- + * + * XSetInputFocus -- + * + * Set the current focus window. + * + * Results: + * None. + * + * Side effects: + * Changes the keyboard focus and causes the selected window to + * be activated. + * + *---------------------------------------------------------------------- + */ + +int +XSetInputFocus( + Display *display, + Window focus, + int revert_to, + Time time) +{ + display->request++; + if (focus != None) { + SetFocus(Tk_GetHWND(focus)); + } + return Success; +} + +/* + *---------------------------------------------------------------------- + * + * TkpChangeFocus -- + * + * This procedure is invoked to move the system focus from one window to + * another. + * + * Results: + * The return value is the serial number of the command that changed the + * focus. It may be needed by the caller to filter out focus change + * events that were queued before the command. If the procedure doesn't + * actually change the focus then it returns 0. + * + * Side effects: + * The official Windows focus window changes; the application's focus + * window isn't changed by this procedure. + * + *---------------------------------------------------------------------- + */ + +int +TkpChangeFocus( + TkWindow *winPtr, /* Window that is to receive the X focus. */ + int force) /* Non-zero means claim the focus even if it + * didn't originally belong to topLevelPtr's + * application. */ +{ + TkDisplay *dispPtr = winPtr->dispPtr; + Window focusWindow; + int dummy, serial; + TkWindow *winPtr2; + + if (!force) { + XGetInputFocus(dispPtr->display, &focusWindow, &dummy); + winPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, focusWindow); + if ((winPtr2 == NULL) || (winPtr2->mainPtr != winPtr->mainPtr)) { + return 0; + } + } + + if (winPtr->window == None) { + Tcl_Panic("ChangeXFocus got null X window"); + } + + /* + * Change the foreground window so the focus window is raised to the top + * of the system stacking order and gets the keyboard focus. + */ + + if (force) { + TkWinSetForegroundWindow(winPtr); + } + XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent, + CurrentTime); + + /* + * Remember the current serial number for the X server and issue a dummy + * server request. This marks the position at which we changed the focus, + * so we can distinguish FocusIn and FocusOut events on either side of the + * mark. + */ + + serial = NextRequest(winPtr->display); + XNoOp(winPtr->display); + return serial; +} + +/* + *---------------------------------------------------------------------- + * + * TkpSetCapture -- + * + * This function captures the mouse so that all future events will be + * reported to this window, even if the mouse is outside the window. If + * the specified window is NULL, then the mouse is released. + * + * Results: + * None. + * + * Side effects: + * Sets the capture flag and captures the mouse. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetCapture( + TkWindow *winPtr) /* Capture window, or NULL. */ +{ + if (winPtr) { + SetCapture(Tk_GetHWND(Tk_WindowId(winPtr))); + captured = 1; + } else { + captured = 0; + ReleaseCapture(); + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |