1 |
/* $Header$ */ |
2 |
|
3 |
/* |
4 |
* tkWinPointer.c -- |
5 |
* |
6 |
* Windows specific mouse tracking code. |
7 |
* |
8 |
* Copyright (c) 1995-1997 Sun Microsystems, Inc. |
9 |
* Copyright (c) 1998-1999 by Scriptics Corporation. |
10 |
* |
11 |
* See the file "license.terms" for information on usage and redistribution |
12 |
* of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
13 |
* |
14 |
* RCS: @(#) $Id: tkwinpointer.c,v 1.1.1.1 2001/06/13 05:14:12 dtashley Exp $ |
15 |
*/ |
16 |
|
17 |
#include "tkWinInt.h" |
18 |
|
19 |
/* |
20 |
* Check for enter/leave events every MOUSE_TIMER_INTERVAL milliseconds. |
21 |
*/ |
22 |
|
23 |
#define MOUSE_TIMER_INTERVAL 250 |
24 |
|
25 |
/* |
26 |
* Declarations of static variables used in this file. |
27 |
*/ |
28 |
|
29 |
static int captured = 0; /* 1 if mouse is currently captured. */ |
30 |
static TkWindow *keyboardWinPtr = NULL; /* Current keyboard grab window. */ |
31 |
static Tcl_TimerToken mouseTimer; /* Handle to the latest mouse timer. */ |
32 |
static int mouseTimerSet = 0; /* 1 if the mouse timer is active. */ |
33 |
|
34 |
/* |
35 |
* Forward declarations of procedures used in this file. |
36 |
*/ |
37 |
|
38 |
static void MouseTimerProc _ANSI_ARGS_((ClientData clientData)); |
39 |
|
40 |
/* |
41 |
*---------------------------------------------------------------------- |
42 |
* |
43 |
* TkWinGetModifierState -- |
44 |
* |
45 |
* Return the modifier state as of the last message. |
46 |
* |
47 |
* Results: |
48 |
* Returns the X modifier mask. |
49 |
* |
50 |
* Side effects: |
51 |
* None. |
52 |
* |
53 |
*---------------------------------------------------------------------- |
54 |
*/ |
55 |
|
56 |
int |
57 |
TkWinGetModifierState() |
58 |
{ |
59 |
int state = 0; |
60 |
|
61 |
if (GetKeyState(VK_SHIFT) & 0x8000) { |
62 |
state |= ShiftMask; |
63 |
} |
64 |
if (GetKeyState(VK_CONTROL) & 0x8000) { |
65 |
state |= ControlMask; |
66 |
} |
67 |
if (GetKeyState(VK_MENU) & 0x8000) { |
68 |
state |= ALT_MASK; |
69 |
} |
70 |
if (GetKeyState(VK_CAPITAL) & 0x0001) { |
71 |
state |= LockMask; |
72 |
} |
73 |
if (GetKeyState(VK_NUMLOCK) & 0x0001) { |
74 |
state |= Mod1Mask; |
75 |
} |
76 |
if (GetKeyState(VK_SCROLL) & 0x0001) { |
77 |
state |= Mod3Mask; |
78 |
} |
79 |
if (GetKeyState(VK_LBUTTON) & 0x8000) { |
80 |
state |= Button1Mask; |
81 |
} |
82 |
if (GetKeyState(VK_MBUTTON) & 0x8000) { |
83 |
state |= Button2Mask; |
84 |
} |
85 |
if (GetKeyState(VK_RBUTTON) & 0x8000) { |
86 |
state |= Button3Mask; |
87 |
} |
88 |
return state; |
89 |
} |
90 |
|
91 |
/* |
92 |
*---------------------------------------------------------------------- |
93 |
* |
94 |
* Tk_PointerEvent -- |
95 |
* |
96 |
* This procedure is called for each pointer-related event. |
97 |
* It converts the position to root coords and updates the |
98 |
* global pointer state machine. It also ensures that the |
99 |
* mouse timer is scheduled. |
100 |
* |
101 |
* Results: |
102 |
* None. |
103 |
* |
104 |
* Side effects: |
105 |
* May queue events and change the grab state. |
106 |
* |
107 |
*---------------------------------------------------------------------- |
108 |
*/ |
109 |
|
110 |
void |
111 |
Tk_PointerEvent(hwnd, x, y) |
112 |
HWND hwnd; /* Window for coords, or NULL for |
113 |
* the root window. */ |
114 |
int x, y; /* Coords relative to hwnd, or screen |
115 |
* if hwnd is NULL. */ |
116 |
{ |
117 |
POINT pos; |
118 |
int state; |
119 |
Tk_Window tkwin; |
120 |
|
121 |
pos.x = x; |
122 |
pos.y = y; |
123 |
|
124 |
/* |
125 |
* Convert client coords to root coords if we were given a window. |
126 |
*/ |
127 |
|
128 |
if (hwnd) { |
129 |
ClientToScreen(hwnd, &pos); |
130 |
} |
131 |
|
132 |
/* |
133 |
* If the mouse is captured, Windows will report all pointer |
134 |
* events to the capture window. So, we need to determine which |
135 |
* window the mouse is really over and change the event. Note |
136 |
* that the computed hwnd may point to a window not owned by Tk, |
137 |
* or a toplevel decorative frame, so tkwin can be NULL. |
138 |
*/ |
139 |
|
140 |
if (captured || hwnd == NULL) { |
141 |
hwnd = WindowFromPoint(pos); |
142 |
} |
143 |
tkwin = Tk_HWNDToWindow(hwnd); |
144 |
|
145 |
state = TkWinGetModifierState(); |
146 |
|
147 |
Tk_UpdatePointer(tkwin, pos.x, pos.y, state); |
148 |
|
149 |
if ((captured || tkwin) && !mouseTimerSet) { |
150 |
mouseTimerSet = 1; |
151 |
mouseTimer = Tcl_CreateTimerHandler(MOUSE_TIMER_INTERVAL, |
152 |
MouseTimerProc, NULL); |
153 |
} |
154 |
} |
155 |
|
156 |
/* |
157 |
*---------------------------------------------------------------------- |
158 |
* |
159 |
* XGrabKeyboard -- |
160 |
* |
161 |
* Simulates a keyboard grab by setting the focus. |
162 |
* |
163 |
* Results: |
164 |
* Always returns GrabSuccess. |
165 |
* |
166 |
* Side effects: |
167 |
* Sets the keyboard focus to the specified window. |
168 |
* |
169 |
*---------------------------------------------------------------------- |
170 |
*/ |
171 |
|
172 |
int |
173 |
XGrabKeyboard(display, grab_window, owner_events, pointer_mode, |
174 |
keyboard_mode, time) |
175 |
Display* display; |
176 |
Window grab_window; |
177 |
Bool owner_events; |
178 |
int pointer_mode; |
179 |
int keyboard_mode; |
180 |
Time time; |
181 |
{ |
182 |
keyboardWinPtr = TkWinGetWinPtr(grab_window); |
183 |
return GrabSuccess; |
184 |
} |
185 |
|
186 |
/* |
187 |
*---------------------------------------------------------------------- |
188 |
* |
189 |
* XUngrabKeyboard -- |
190 |
* |
191 |
* Releases the simulated keyboard grab. |
192 |
* |
193 |
* Results: |
194 |
* None. |
195 |
* |
196 |
* Side effects: |
197 |
* Sets the keyboard focus back to the value before the grab. |
198 |
* |
199 |
*---------------------------------------------------------------------- |
200 |
*/ |
201 |
|
202 |
void |
203 |
XUngrabKeyboard(display, time) |
204 |
Display* display; |
205 |
Time time; |
206 |
{ |
207 |
keyboardWinPtr = NULL; |
208 |
} |
209 |
|
210 |
/* |
211 |
*---------------------------------------------------------------------- |
212 |
* |
213 |
* MouseTimerProc -- |
214 |
* |
215 |
* Check the current mouse position and look for enter/leave |
216 |
* events. |
217 |
* |
218 |
* Results: |
219 |
* None. |
220 |
* |
221 |
* Side effects: |
222 |
* May schedule a new timer and/or generate enter/leave events. |
223 |
* |
224 |
*---------------------------------------------------------------------- |
225 |
*/ |
226 |
|
227 |
void |
228 |
MouseTimerProc(clientData) |
229 |
ClientData clientData; |
230 |
{ |
231 |
POINT pos; |
232 |
|
233 |
mouseTimerSet = 0; |
234 |
|
235 |
/* |
236 |
* Get the current mouse position and window. Don't do anything |
237 |
* if the mouse hasn't moved since the last time we looked. |
238 |
*/ |
239 |
|
240 |
GetCursorPos(&pos); |
241 |
Tk_PointerEvent(NULL, pos.x, pos.y); |
242 |
} |
243 |
|
244 |
/* |
245 |
*---------------------------------------------------------------------- |
246 |
* |
247 |
* TkWinCancelMouseTimer -- |
248 |
* |
249 |
* If the mouse timer is set, cancel it. |
250 |
* |
251 |
* Results: |
252 |
* None. |
253 |
* |
254 |
* Side effects: |
255 |
* May cancel the mouse timer. |
256 |
* |
257 |
*---------------------------------------------------------------------- |
258 |
*/ |
259 |
|
260 |
void |
261 |
TkWinCancelMouseTimer() |
262 |
{ |
263 |
if (mouseTimerSet) { |
264 |
Tcl_DeleteTimerHandler(mouseTimer); |
265 |
mouseTimerSet = 0; |
266 |
} |
267 |
} |
268 |
|
269 |
/* |
270 |
*---------------------------------------------------------------------- |
271 |
* |
272 |
* TkGetPointerCoords -- |
273 |
* |
274 |
* Fetch the position of the mouse pointer. |
275 |
* |
276 |
* Results: |
277 |
* *xPtr and *yPtr are filled in with the root coordinates |
278 |
* of the mouse pointer for the display. |
279 |
* |
280 |
* Side effects: |
281 |
* None. |
282 |
* |
283 |
*---------------------------------------------------------------------- |
284 |
*/ |
285 |
|
286 |
void |
287 |
TkGetPointerCoords(tkwin, xPtr, yPtr) |
288 |
Tk_Window tkwin; /* Window that identifies screen on which |
289 |
* lookup is to be done. */ |
290 |
int *xPtr, *yPtr; /* Store pointer coordinates here. */ |
291 |
{ |
292 |
POINT point; |
293 |
|
294 |
GetCursorPos(&point); |
295 |
*xPtr = point.x; |
296 |
*yPtr = point.y; |
297 |
} |
298 |
|
299 |
/* |
300 |
*---------------------------------------------------------------------- |
301 |
* |
302 |
* XQueryPointer -- |
303 |
* |
304 |
* Check the current state of the mouse. This is not a complete |
305 |
* implementation of this function. It only computes the root |
306 |
* coordinates and the current mask. |
307 |
* |
308 |
* Results: |
309 |
* Sets root_x_return, root_y_return, and mask_return. Returns |
310 |
* true on success. |
311 |
* |
312 |
* Side effects: |
313 |
* None. |
314 |
* |
315 |
*---------------------------------------------------------------------- |
316 |
*/ |
317 |
|
318 |
Bool |
319 |
XQueryPointer(display, w, root_return, child_return, root_x_return, |
320 |
root_y_return, win_x_return, win_y_return, mask_return) |
321 |
Display* display; |
322 |
Window w; |
323 |
Window* root_return; |
324 |
Window* child_return; |
325 |
int* root_x_return; |
326 |
int* root_y_return; |
327 |
int* win_x_return; |
328 |
int* win_y_return; |
329 |
unsigned int* mask_return; |
330 |
{ |
331 |
display->request++; |
332 |
TkGetPointerCoords(NULL, root_x_return, root_y_return); |
333 |
*mask_return = TkWinGetModifierState(); |
334 |
return True; |
335 |
} |
336 |
|
337 |
/* |
338 |
*---------------------------------------------------------------------- |
339 |
* |
340 |
* XWarpPointer -- |
341 |
* |
342 |
* Move pointer to new location. This is not a complete |
343 |
* implementation of this function. |
344 |
* |
345 |
* Results: |
346 |
* None. |
347 |
* |
348 |
* Side effects: |
349 |
* Mouse pointer changes position on screen. |
350 |
* |
351 |
*---------------------------------------------------------------------- |
352 |
*/ |
353 |
|
354 |
void |
355 |
XWarpPointer(display, src_w, dest_w, src_x, src_y, src_width, |
356 |
src_height, dest_x, dest_y) |
357 |
Display* display; |
358 |
Window src_w; |
359 |
Window dest_w; |
360 |
int src_x; |
361 |
int src_y; |
362 |
unsigned int src_width; |
363 |
unsigned int src_height; |
364 |
int dest_x; |
365 |
int dest_y; |
366 |
{ |
367 |
RECT r; |
368 |
|
369 |
GetWindowRect(Tk_GetHWND(dest_w), &r); |
370 |
SetCursorPos(r.left+dest_x, r.top+dest_y); |
371 |
} |
372 |
|
373 |
/* |
374 |
*---------------------------------------------------------------------- |
375 |
* |
376 |
* XGetInputFocus -- |
377 |
* |
378 |
* Retrieves the current keyboard focus window. |
379 |
* |
380 |
* Results: |
381 |
* Returns the current focus window. |
382 |
* |
383 |
* Side effects: |
384 |
* None. |
385 |
* |
386 |
*---------------------------------------------------------------------- |
387 |
*/ |
388 |
|
389 |
void |
390 |
XGetInputFocus(display, focus_return, revert_to_return) |
391 |
Display *display; |
392 |
Window *focus_return; |
393 |
int *revert_to_return; |
394 |
{ |
395 |
Tk_Window tkwin = Tk_HWNDToWindow(GetFocus()); |
396 |
*focus_return = tkwin ? Tk_WindowId(tkwin) : None; |
397 |
*revert_to_return = RevertToParent; |
398 |
display->request++; |
399 |
} |
400 |
|
401 |
/* |
402 |
*---------------------------------------------------------------------- |
403 |
* |
404 |
* XSetInputFocus -- |
405 |
* |
406 |
* Set the current focus window. |
407 |
* |
408 |
* Results: |
409 |
* None. |
410 |
* |
411 |
* Side effects: |
412 |
* Changes the keyboard focus and causes the selected window to |
413 |
* be activated. |
414 |
* |
415 |
*---------------------------------------------------------------------- |
416 |
*/ |
417 |
|
418 |
void |
419 |
XSetInputFocus(display, focus, revert_to, time) |
420 |
Display* display; |
421 |
Window focus; |
422 |
int revert_to; |
423 |
Time time; |
424 |
{ |
425 |
display->request++; |
426 |
if (focus != None) { |
427 |
SetFocus(Tk_GetHWND(focus)); |
428 |
} |
429 |
} |
430 |
|
431 |
/* |
432 |
*---------------------------------------------------------------------- |
433 |
* |
434 |
* TkpChangeFocus -- |
435 |
* |
436 |
* This procedure is invoked to move the system focus from |
437 |
* one window to another. |
438 |
* |
439 |
* Results: |
440 |
* The return value is the serial number of the command that |
441 |
* changed the focus. It may be needed by the caller to filter |
442 |
* out focus change events that were queued before the command. |
443 |
* If the procedure doesn't actually change the focus then |
444 |
* it returns 0. |
445 |
* |
446 |
* Side effects: |
447 |
* The official Windows focus window changes; the application's focus |
448 |
* window isn't changed by this procedure. |
449 |
* |
450 |
*---------------------------------------------------------------------- |
451 |
*/ |
452 |
|
453 |
int |
454 |
TkpChangeFocus(winPtr, force) |
455 |
TkWindow *winPtr; /* Window that is to receive the X focus. */ |
456 |
int force; /* Non-zero means claim the focus even |
457 |
* if it didn't originally belong to |
458 |
* topLevelPtr's application. */ |
459 |
{ |
460 |
TkDisplay *dispPtr = winPtr->dispPtr; |
461 |
Window focusWindow; |
462 |
int dummy, serial; |
463 |
TkWindow *winPtr2; |
464 |
|
465 |
if (!force) { |
466 |
XGetInputFocus(dispPtr->display, &focusWindow, &dummy); |
467 |
winPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, focusWindow); |
468 |
if ((winPtr2 == NULL) || (winPtr2->mainPtr != winPtr->mainPtr)) { |
469 |
return 0; |
470 |
} |
471 |
} |
472 |
|
473 |
if (winPtr->window == None) { |
474 |
panic("ChangeXFocus got null X window"); |
475 |
} |
476 |
|
477 |
/* |
478 |
* Change the foreground window so the focus window is raised to the top of |
479 |
* the system stacking order and gets the keyboard focus. |
480 |
*/ |
481 |
|
482 |
if (force) { |
483 |
TkWinSetForegroundWindow(winPtr); |
484 |
} |
485 |
XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent, |
486 |
CurrentTime); |
487 |
|
488 |
/* |
489 |
* Remember the current serial number for the X server and issue |
490 |
* a dummy server request. This marks the position at which we |
491 |
* changed the focus, so we can distinguish FocusIn and FocusOut |
492 |
* events on either side of the mark. |
493 |
*/ |
494 |
|
495 |
serial = NextRequest(winPtr->display); |
496 |
XNoOp(winPtr->display); |
497 |
return serial; |
498 |
} |
499 |
|
500 |
/* |
501 |
*---------------------------------------------------------------------- |
502 |
* |
503 |
* TkpSetCapture -- |
504 |
* |
505 |
* This function captures the mouse so that all future events |
506 |
* will be reported to this window, even if the mouse is outside |
507 |
* the window. If the specified window is NULL, then the mouse |
508 |
* is released. |
509 |
* |
510 |
* Results: |
511 |
* None. |
512 |
* |
513 |
* Side effects: |
514 |
* Sets the capture flag and captures the mouse. |
515 |
* |
516 |
*---------------------------------------------------------------------- |
517 |
*/ |
518 |
|
519 |
void |
520 |
TkpSetCapture(winPtr) |
521 |
TkWindow *winPtr; /* Capture window, or NULL. */ |
522 |
{ |
523 |
if (winPtr) { |
524 |
SetCapture(Tk_GetHWND(Tk_WindowId(winPtr))); |
525 |
captured = 1; |
526 |
} else { |
527 |
captured = 0; |
528 |
ReleaseCapture(); |
529 |
} |
530 |
} |
531 |
|
532 |
/* End of tkwinpointer.c */ |