467 lines
11 KiB
C
467 lines
11 KiB
C
/*
|
||
* 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();
|
||
}
|
||
}
|