summaryrefslogtreecommitdiffstats
path: root/win/tkWinPointer.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tkWinPointer.c')
-rw-r--r--win/tkWinPointer.c457
1 files changed, 457 insertions, 0 deletions
diff --git a/win/tkWinPointer.c b/win/tkWinPointer.c
new file mode 100644
index 0000000..96661ae
--- /dev/null
+++ b/win/tkWinPointer.c
@@ -0,0 +1,457 @@
+/*
+ * tkWinPointer.c --
+ *
+ * Windows specific mouse tracking code.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkWinPointer.c 1.28 97/10/31 08:40:07
+ */
+
+#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 _ANSI_ARGS_((ClientData clientData));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWinGetModifierState --
+ *
+ * Return the modifier state as of the last message.
+ *
+ * Results:
+ * Returns the X modifier mask.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkWinGetModifierState()
+{
+ int state = 0;
+
+ if (GetKeyState(VK_SHIFT) & 0x8000) {
+ state |= ShiftMask;
+ }
+ if (GetKeyState(VK_CONTROL) & 0x8000) {
+ state |= ControlMask;
+ }
+ if (GetKeyState(VK_MENU) & 0x8000) {
+ state |= Mod2Mask;
+ }
+ 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, x, y)
+ HWND hwnd; /* Window for coords, or NULL for
+ * the root window. */
+ int x, 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, grab_window, owner_events, pointer_mode,
+ keyboard_mode, time)
+ 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XUngrabKeyboard(display, time)
+ Display* display;
+ Time time;
+{
+ keyboardWinPtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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 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);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(tkwin, xPtr, yPtr)
+ Tk_Window tkwin; /* Window that identifies screen on which
+ * lookup is to be done. */
+ int *xPtr, *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, w, root_return, child_return, root_x_return,
+ root_y_return, win_x_return, win_y_return, mask_return)
+ 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;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XGetInputFocus --
+ *
+ * Retrieves the current keyboard focus window.
+ *
+ * Results:
+ * Returns the current focus window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XGetInputFocus(display, focus_return, revert_to_return)
+ 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++;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XSetInputFocus --
+ *
+ * Set the current focus window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the keyboard focus and causes the selected window to
+ * be activated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XSetInputFocus(display, focus, revert_to, time)
+ Display* display;
+ Window focus;
+ int revert_to;
+ Time time;
+{
+ display->request++;
+ if (focus != None) {
+ SetFocus(Tk_GetHWND(focus));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(winPtr, force)
+ 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) {
+ panic("ChangeXFocus got null X window");
+ }
+ 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(winPtr)
+ TkWindow *winPtr; /* Capture window, or NULL. */
+{
+ if (winPtr) {
+ SetCapture(Tk_GetHWND(Tk_WindowId(winPtr)));
+ captured = 1;
+ } else {
+ captured = 0;
+ ReleaseCapture();
+ }
+}