stk/Tk/win/tkWinPointer.c

467 lines
11 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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");
}
/*
* 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) {
SetForegroundWindow(Tk_GetHWND(winPtr->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();
}
}