849 lines
20 KiB
C
849 lines
20 KiB
C
/*
|
||
* tkWinPointer.c --
|
||
*
|
||
* Windows specific mouse tracking code.
|
||
*
|
||
* Copyright (c) 1995 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.14 96/02/15 18:56:05
|
||
*/
|
||
|
||
#include "tkWinInt.h"
|
||
|
||
/*
|
||
* Check for enter/leave events every MOUSE_TIMER_INTERVAL milliseconds.
|
||
*/
|
||
|
||
#define MOUSE_TIMER_INTERVAL 250
|
||
|
||
/*
|
||
* Mask that selects any of the state bits corresponding to buttons,
|
||
* plus masks that select individual buttons' bits:
|
||
*/
|
||
|
||
#define ALL_BUTTONS \
|
||
(Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
|
||
static unsigned int buttonStates[] = {
|
||
Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
|
||
};
|
||
|
||
/*
|
||
* Declarations of static variables used in the grab module.
|
||
*/
|
||
|
||
static int captured; /* 1 if mouse events outside of Tk windows
|
||
* will be reported, else 0. */
|
||
static TkWindow *grabWinPtr; /* Window that defines the top of the grab
|
||
* tree in a global grab. */
|
||
static TkWindow *keyboardWinPtr;/* Current keyboard grab window. */
|
||
static TkWindow *restrictWinPtr;
|
||
/* Window to which all mouse
|
||
events will be reported. */
|
||
|
||
/*
|
||
* Declarations of static variables used in mouse position tracking.
|
||
*/
|
||
|
||
static POINT lastMousePos; /* Last known mouse position. */
|
||
static HWND lastMouseWindow; /* Last known mouse window. */
|
||
static TkWindow *lastMouseWinPtr;
|
||
/* Last window mouse was seen in. Used to
|
||
* detect Enter/Leave events. */
|
||
static Tcl_TimerToken mouseTimer;
|
||
/* Handle to the latest mouse timer. */
|
||
static int mouseTimerSet; /* Non-zero if the mouse timer is active. */
|
||
|
||
/*
|
||
* Forward declarations of procedures used in this file.
|
||
*/
|
||
|
||
static void InitializeCrossingEvent _ANSI_ARGS_((
|
||
XEvent* eventPtr, TkWindow *winPtr,
|
||
long x, long y));
|
||
static void MouseTimerProc _ANSI_ARGS_((ClientData clientData));
|
||
static int UpdateMousePosition _ANSI_ARGS_((HWND hwnd,
|
||
TkWindow *winPtr, long x, long y));
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkWinPointerInit --
|
||
*
|
||
* Initialize the mouse pointer module.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Initializes various static variables.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkWinPointerInit()
|
||
{
|
||
captured = 0;
|
||
grabWinPtr = NULL;
|
||
keyboardWinPtr = NULL;
|
||
restrictWinPtr = NULL;
|
||
|
||
mouseTimerSet = 0;
|
||
GetCursorPos(&lastMousePos);
|
||
lastMouseWindow = WindowFromPoint(lastMousePos);
|
||
lastMouseWinPtr = NULL;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkWinPointerDeadWindow --
|
||
*
|
||
* Clean up pointer module state when a window is destroyed.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* May change the grab module settings.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkWinPointerDeadWindow(winPtr)
|
||
TkWindow *winPtr;
|
||
{
|
||
if (winPtr == lastMouseWinPtr) {
|
||
lastMouseWinPtr = NULL;
|
||
}
|
||
if (winPtr == grabWinPtr) {
|
||
grabWinPtr = NULL;
|
||
}
|
||
if (winPtr == restrictWinPtr) {
|
||
restrictWinPtr = NULL;
|
||
}
|
||
if (!(restrictWinPtr || grabWinPtr)) {
|
||
captured = 0;
|
||
ReleaseCapture();
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkWinPointerEvent --
|
||
*
|
||
* This procedure is called for each pointer-related event,
|
||
* before the event is queued. It simulates X style automatic
|
||
* grabs so that button release events are not lost. It also
|
||
* updates the pointer position so enter/leave events will be
|
||
* correctly generated.
|
||
*
|
||
* Results:
|
||
* Returns 0 if the event should be discarded.
|
||
*
|
||
* Side effects:
|
||
* Changes the current mouse capture window.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkWinPointerEvent(eventPtr, winPtr)
|
||
XEvent *eventPtr; /* Event to process */
|
||
TkWindow *winPtr; /* Window to which event was reported. */
|
||
{
|
||
POINT pos;
|
||
HWND hwnd;
|
||
TkWinDrawable *twdPtr;
|
||
|
||
/*
|
||
* 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 winPtr can be NULL.
|
||
*/
|
||
|
||
if (captured) {
|
||
pos.x = eventPtr->xmotion.x_root;
|
||
pos.y = eventPtr->xmotion.y_root;
|
||
hwnd = WindowFromPoint(pos);
|
||
twdPtr = TkWinGetDrawableFromHandle(hwnd);
|
||
if (twdPtr && (twdPtr->type == TWD_WINDOW)) {
|
||
winPtr = TkWinGetWinPtr(twdPtr);
|
||
} else {
|
||
winPtr = NULL;
|
||
}
|
||
} else {
|
||
hwnd = TkWinGetHWND(Tk_WindowId(winPtr));
|
||
}
|
||
|
||
switch (eventPtr->type) {
|
||
case MotionNotify:
|
||
|
||
/*
|
||
* If updating the mouse position caused an enter or leave
|
||
* event to be generated, we discard the motion event.
|
||
*/
|
||
|
||
if (UpdateMousePosition(hwnd, winPtr, eventPtr->xmotion.x_root,
|
||
eventPtr->xmotion.y_root)) {
|
||
return;
|
||
}
|
||
break;
|
||
|
||
case ButtonPress:
|
||
|
||
/*
|
||
* Set mouse capture and the restrict window if we are
|
||
* currently unrestricted. However, If this is not the
|
||
* first button pressed and we are already grabbed, do not
|
||
* change anything.
|
||
*/
|
||
|
||
if (!restrictWinPtr) {
|
||
if (!grabWinPtr) {
|
||
/*
|
||
* Mouse was ungrabbed, so set a button grab.
|
||
*/
|
||
|
||
restrictWinPtr = winPtr;
|
||
captured = 1;
|
||
SetCapture(hwnd);
|
||
} else if ((eventPtr->xmotion.state & ALL_BUTTONS) == 0) {
|
||
|
||
/*
|
||
* Mouse was grabbed, but not in a button grab.
|
||
* Make sure the new restrict window is inside the
|
||
* current grab tree.
|
||
*/
|
||
|
||
if (TkPositionInTree(winPtr, grabWinPtr)
|
||
== TK_GRAB_IN_TREE) {
|
||
restrictWinPtr = winPtr;
|
||
} else {
|
||
restrictWinPtr = grabWinPtr;
|
||
}
|
||
captured = 1;
|
||
SetCapture(TkWinGetHWND(Tk_WindowId(restrictWinPtr)));
|
||
}
|
||
}
|
||
break;
|
||
|
||
case ButtonRelease:
|
||
|
||
/*
|
||
* Release the mouse capture when the last button is
|
||
* released and we aren't in a global grab.
|
||
*/
|
||
|
||
if ((eventPtr->xbutton.state & ALL_BUTTONS)
|
||
== buttonStates[eventPtr->xbutton.button - Button1]) {
|
||
if (!grabWinPtr) {
|
||
captured = 0;
|
||
ReleaseCapture();
|
||
}
|
||
|
||
/*
|
||
* If we are releasing a restrict window, then we need
|
||
* to send the button event followed by mouse motion from
|
||
* the restrict window the the current mouse position.
|
||
*/
|
||
|
||
if (restrictWinPtr) {
|
||
if (Tk_WindowId(restrictWinPtr) != eventPtr->xany.window) {
|
||
TkChangeEventWindow(eventPtr, restrictWinPtr);
|
||
}
|
||
Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
|
||
lastMouseWinPtr = restrictWinPtr;
|
||
restrictWinPtr = NULL;
|
||
UpdateMousePosition(hwnd, winPtr, eventPtr->xmotion.x_root,
|
||
eventPtr->xmotion.y_root);
|
||
return;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
/*
|
||
* If a restrict window is set, make sure the pointer event is reported
|
||
* relative to that window. Otherwise, if a global grab is in effect
|
||
* then events outside of window managed by Tk should be reported to the
|
||
* grab window.
|
||
*/
|
||
|
||
if (restrictWinPtr) {
|
||
winPtr = restrictWinPtr;
|
||
} else if (grabWinPtr && !winPtr) {
|
||
winPtr = grabWinPtr;
|
||
}
|
||
|
||
/*
|
||
* If the target window has changed, update the coordinates in the event.
|
||
*/
|
||
|
||
if (winPtr && Tk_WindowId(winPtr) != eventPtr->xany.window) {
|
||
TkChangeEventWindow(eventPtr, winPtr);
|
||
}
|
||
Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XGrabPointer --
|
||
*
|
||
* Capture the mouse so event are reported outside of toplevels.
|
||
* Note that this is a very limited implementation that only
|
||
* supports GrabModeAsync and owner_events True.
|
||
*
|
||
* Results:
|
||
* Always returns GrabSuccess.
|
||
*
|
||
* Side effects:
|
||
* Turns on mouse capture, sets the global grab pointer, and
|
||
* clears any window restrictions.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode,
|
||
keyboard_mode, confine_to, cursor, time)
|
||
Display* display;
|
||
Window grab_window;
|
||
Bool owner_events;
|
||
unsigned int event_mask;
|
||
int pointer_mode;
|
||
int keyboard_mode;
|
||
Window confine_to;
|
||
Cursor cursor;
|
||
Time time;
|
||
{
|
||
HWND hwnd = TkWinGetHWND(grab_window);
|
||
grabWinPtr = TkWinGetWinPtr(grab_window);
|
||
captured = 1;
|
||
restrictWinPtr = NULL;
|
||
SetCapture(hwnd);
|
||
if (TkPositionInTree(lastMouseWinPtr, grabWinPtr) == TK_GRAB_IN_TREE) {
|
||
TkWinUpdateCursor(lastMouseWinPtr);
|
||
} else {
|
||
TkWinUpdateCursor(grabWinPtr);
|
||
}
|
||
return GrabSuccess;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XUngrabPointer --
|
||
*
|
||
* Release the current grab.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Releases the mouse capture.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XUngrabPointer(display, time)
|
||
Display* display;
|
||
Time time;
|
||
{
|
||
captured = 0;
|
||
grabWinPtr = NULL;
|
||
restrictWinPtr = NULL;
|
||
ReleaseCapture();
|
||
TkWinUpdateCursor(lastMouseWinPtr);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* 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;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* InitializeCrossingEvent --
|
||
*
|
||
* Initializes the common fields for enter/leave events.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Fills in the specified event structure.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static void
|
||
InitializeCrossingEvent(eventPtr, winPtr, x, y)
|
||
XEvent* eventPtr; /* Event structure to initialize. */
|
||
TkWindow *winPtr; /* Window to make event relative to. */
|
||
long x, y; /* Root coords of event. */
|
||
{
|
||
eventPtr->xcrossing.serial = LastKnownRequestProcessed(winPtr->display);
|
||
eventPtr->xcrossing.send_event = 0;
|
||
eventPtr->xcrossing.display = winPtr->display;
|
||
eventPtr->xcrossing.root = RootWindow(winPtr->display, winPtr->screenNum);
|
||
eventPtr->xcrossing.time = TkCurrentTime(winPtr->dispPtr);
|
||
eventPtr->xcrossing.x_root = x;
|
||
eventPtr->xcrossing.y_root = y;
|
||
eventPtr->xcrossing.state = TkWinGetModifierState(WM_MOUSEMOVE, 0, 0);
|
||
eventPtr->xcrossing.mode = NotifyNormal;
|
||
eventPtr->xcrossing.focus = False;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* UpdateMousePosition --
|
||
*
|
||
* Update the current mouse window and position, and generate
|
||
* any enter/leave events that are needed. Will schedule a
|
||
* timer to check the mouse position if the pointer is still
|
||
* inside a Tk window.
|
||
*
|
||
* Results:
|
||
* Returns 1 if enter/leave events were generated.
|
||
*
|
||
* Side effects:
|
||
* May generate enter/leave events and schedule a timer.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
UpdateMousePosition(hwnd, winPtr, x, y)
|
||
HWND hwnd; /* current mouse window */
|
||
TkWindow *winPtr; /* current Tk window (or NULL) */
|
||
long x; /* current mouse position in */
|
||
long y; /* root coordinates */
|
||
{
|
||
int crossed = 0; /* 1 if mouse crossed a window boundary */
|
||
TkWindow *cursorWinPtr;
|
||
|
||
if (winPtr != lastMouseWinPtr) {
|
||
if (restrictWinPtr) {
|
||
int newPos, oldPos;
|
||
|
||
newPos = TkPositionInTree(winPtr, restrictWinPtr);
|
||
oldPos = TkPositionInTree(lastMouseWinPtr, restrictWinPtr);
|
||
|
||
/*
|
||
* Check if the mouse crossed into or out of the restrict
|
||
* window. If so, we need to generate an Enter or Leave event.
|
||
*/
|
||
|
||
if ((newPos != oldPos) && ((newPos == TK_GRAB_IN_TREE)
|
||
|| (oldPos == TK_GRAB_IN_TREE))) {
|
||
XEvent event;
|
||
|
||
InitializeCrossingEvent(&event, restrictWinPtr, x, y);
|
||
if (newPos == TK_GRAB_IN_TREE) {
|
||
event.type = EnterNotify;
|
||
} else {
|
||
event.type = LeaveNotify;
|
||
}
|
||
if ((oldPos == TK_GRAB_ANCESTOR)
|
||
|| (newPos == TK_GRAB_ANCESTOR)) {
|
||
event.xcrossing.detail = NotifyAncestor;
|
||
} else {
|
||
event.xcrossing.detail = NotifyVirtual;
|
||
}
|
||
TkChangeEventWindow(&event, restrictWinPtr);
|
||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||
}
|
||
|
||
} else {
|
||
TkWindow *targetPtr;
|
||
|
||
if ((lastMouseWinPtr == NULL)
|
||
|| (lastMouseWinPtr->window == None)) {
|
||
targetPtr = winPtr;
|
||
} else {
|
||
targetPtr = lastMouseWinPtr;
|
||
}
|
||
|
||
if (targetPtr && (targetPtr->window != None)) {
|
||
XEvent event;
|
||
|
||
/*
|
||
* Generate appropriate Enter/Leave events.
|
||
*/
|
||
|
||
InitializeCrossingEvent(&event, targetPtr, x, y);
|
||
|
||
TkInOutEvents(&event, lastMouseWinPtr, winPtr, LeaveNotify,
|
||
EnterNotify, TCL_QUEUE_TAIL);
|
||
|
||
if (TkPositionInTree(winPtr, grabWinPtr) == TK_GRAB_IN_TREE) {
|
||
cursorWinPtr = winPtr;
|
||
} else {
|
||
cursorWinPtr = grabWinPtr;
|
||
}
|
||
crossed = 1;
|
||
}
|
||
}
|
||
lastMouseWinPtr = winPtr;
|
||
}
|
||
|
||
/*
|
||
* Make sure the cursor reflects the current mouse position.
|
||
*/
|
||
|
||
if (restrictWinPtr) {
|
||
cursorWinPtr = restrictWinPtr;
|
||
} else if (grabWinPtr) {
|
||
cursorWinPtr = (TkPositionInTree(winPtr, grabWinPtr)
|
||
== TK_GRAB_IN_TREE) ? winPtr : grabWinPtr;
|
||
} else {
|
||
cursorWinPtr = winPtr;
|
||
}
|
||
TkWinUpdateCursor(cursorWinPtr);
|
||
|
||
lastMouseWindow = hwnd;
|
||
lastMousePos.x = x;
|
||
lastMousePos.y = y;
|
||
|
||
/*
|
||
* Ensure the mouse timer is set if we are still inside a Tk window.
|
||
*/
|
||
|
||
if (winPtr != NULL && !mouseTimerSet) {
|
||
mouseTimerSet = 1;
|
||
mouseTimer = Tcl_CreateTimerHandler(MOUSE_TIMER_INTERVAL,
|
||
MouseTimerProc, NULL);
|
||
}
|
||
|
||
return crossed;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* 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;
|
||
HWND hwnd;
|
||
TkWinDrawable *twdPtr;
|
||
TkWindow *winPtr;
|
||
|
||
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);
|
||
if (pos.x == lastMousePos.y && pos.y == lastMousePos.y) {
|
||
hwnd = lastMouseWindow;
|
||
} else {
|
||
hwnd = WindowFromPoint(pos);
|
||
}
|
||
|
||
/*
|
||
* Check to see if the current window is managed by Tk.
|
||
*/
|
||
|
||
if (hwnd == lastMouseWindow) {
|
||
winPtr = lastMouseWinPtr;
|
||
} else {
|
||
twdPtr = TkWinGetDrawableFromHandle(hwnd);
|
||
if (twdPtr && (twdPtr->type == TWD_WINDOW)) {
|
||
winPtr = TkWinGetWinPtr(twdPtr);
|
||
} else {
|
||
winPtr = NULL;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Generate enter/leave events.
|
||
*/
|
||
|
||
UpdateMousePosition(hwnd, winPtr, 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. */
|
||
{
|
||
DWORD msgPos;
|
||
POINTS rootPoint;
|
||
|
||
msgPos = GetMessagePos();
|
||
rootPoint = MAKEPOINTS(msgPos);
|
||
*xPtr = rootPoint.x;
|
||
*yPtr = rootPoint.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;
|
||
{
|
||
TkGetPointerCoords(NULL, root_x_return, root_y_return);
|
||
*mask_return = TkWinGetModifierState(WM_MOUSEMOVE, 0, 0);
|
||
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;
|
||
{
|
||
HWND hwnd = GetFocus();
|
||
TkWinDrawable *twdPtr = TkWinGetDrawableFromHandle(hwnd);
|
||
|
||
/*
|
||
* The focus window may be a Tk window or a window manager decorative
|
||
* frame.
|
||
*/
|
||
|
||
if (twdPtr) {
|
||
*focus_return = Tk_WindowId(TkWinGetWinPtr(twdPtr));
|
||
} else {
|
||
*focus_return = NULL;
|
||
}
|
||
*revert_to_return = RevertToParent;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* 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;
|
||
{
|
||
HWND hwnd = TkWinGetHWND(focus);
|
||
SetFocus(hwnd);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XDefineCursor --
|
||
*
|
||
* This function is called to update the cursor on a window.
|
||
* Since the mouse might be in the specified window, we need to
|
||
* check the specified window against the current mouse position
|
||
* and grab state.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* May update the cursor.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XDefineCursor(display, w, cursor)
|
||
Display* display;
|
||
Window w;
|
||
Cursor cursor;
|
||
{
|
||
TkWindow *winPtr = TkWinGetWinPtr(w);
|
||
|
||
if (restrictWinPtr) {
|
||
|
||
/*
|
||
* If there is a restrict window, then we only update the cursor
|
||
* if the restrict window is the window being modified.
|
||
*/
|
||
|
||
if (winPtr == restrictWinPtr) {
|
||
goto update;
|
||
}
|
||
} else if (grabWinPtr) {
|
||
|
||
/*
|
||
* If a grab is in effect, then we only update the cursor if the mouse
|
||
* pointer is outside the grab tree and the specified window is the
|
||
* grab window, or the pointer is inside the grab tree and the
|
||
* specified window is also the pointer window.
|
||
*/
|
||
|
||
if (TkPositionInTree(lastMouseWinPtr, grabWinPtr) == TK_GRAB_IN_TREE) {
|
||
if (winPtr == lastMouseWinPtr) {
|
||
goto update;
|
||
}
|
||
} else if (winPtr == grabWinPtr) {
|
||
goto update;
|
||
}
|
||
} else {
|
||
|
||
/*
|
||
* Otherwise, we only update the cursor if the specified window
|
||
* contains the mouse pointer.
|
||
*/
|
||
|
||
if (winPtr == lastMouseWinPtr) {
|
||
goto update;
|
||
}
|
||
}
|
||
return;
|
||
|
||
update:
|
||
TkWinUpdateCursor(winPtr);
|
||
}
|
||
|