1 | /* |
---|
2 | * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC. |
---|
3 | * ALL RIGHTS RESERVED |
---|
4 | */ |
---|
5 | /* |
---|
6 | * Motif Release 1.2.3 |
---|
7 | */ |
---|
8 | #ifdef REV_INFO |
---|
9 | #ifndef lint |
---|
10 | static char rcsid[] = "$RCSfile: WmEvent.c,v $ $Revision: 1.1.1.1 $ $Date: 1997-03-25 09:12:17 $" |
---|
11 | #endif |
---|
12 | #endif |
---|
13 | /* |
---|
14 | * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */ |
---|
15 | |
---|
16 | /* |
---|
17 | * Included Files: |
---|
18 | */ |
---|
19 | |
---|
20 | #include "WmGlobal.h" |
---|
21 | /* |
---|
22 | * include extern functions |
---|
23 | */ |
---|
24 | #include "WmEvent.h" |
---|
25 | #include "WmCDInfo.h" |
---|
26 | #include "WmCDecor.h" |
---|
27 | #include "WmCEvent.h" |
---|
28 | #include "WmColormap.h" |
---|
29 | #include "WmFunction.h" |
---|
30 | #include "WmKeyFocus.h" |
---|
31 | #include "WmManage.h" |
---|
32 | #include "WmMenu.h" |
---|
33 | #include "WmWinInfo.h" |
---|
34 | #include "WmWinState.h" |
---|
35 | |
---|
36 | |
---|
37 | |
---|
38 | /* |
---|
39 | * Global Variables: |
---|
40 | */ |
---|
41 | |
---|
42 | extern unsigned int buttonModifierMasks[]; |
---|
43 | |
---|
44 | #ifndef MOTIF_ONE_DOT_ONE |
---|
45 | #include <Xm/MenuShellP.h> |
---|
46 | #endif |
---|
47 | |
---|
48 | |
---|
49 | |
---|
50 | /*************************************<->************************************* |
---|
51 | * |
---|
52 | * InitEventHandling () |
---|
53 | * |
---|
54 | * |
---|
55 | * Description: |
---|
56 | * ----------- |
---|
57 | * This function initializes window manager event handling in preparation |
---|
58 | * for managing client windows. |
---|
59 | * |
---|
60 | * |
---|
61 | * Inputs: |
---|
62 | * ------ |
---|
63 | * wmGD = (keySpecs) |
---|
64 | * |
---|
65 | *************************************<->***********************************/ |
---|
66 | |
---|
67 | #ifdef _NO_PROTO |
---|
68 | void InitEventHandling () |
---|
69 | |
---|
70 | #else /* _NO_PROTO */ |
---|
71 | void InitEventHandling (void) |
---|
72 | #endif /* _NO_PROTO */ |
---|
73 | { |
---|
74 | WmScreenData *pSD; |
---|
75 | XSetWindowAttributes setAttributes; |
---|
76 | unsigned long base_mask; |
---|
77 | unsigned int n, scr; |
---|
78 | |
---|
79 | |
---|
80 | /* |
---|
81 | * Prepare to get root (workspace) window events that are used to |
---|
82 | * manage client windows. Setup accelerator event processing. |
---|
83 | */ |
---|
84 | |
---|
85 | base_mask = SubstructureRedirectMask | FocusChangeMask; |
---|
86 | |
---|
87 | /* handle entry of root window */ |
---|
88 | base_mask |= EnterWindowMask | LeaveWindowMask; |
---|
89 | |
---|
90 | for (scr=0; scr<wmGD.numScreens; scr++) |
---|
91 | { |
---|
92 | pSD = &(wmGD.Screens[scr]); |
---|
93 | |
---|
94 | if (pSD->managed) |
---|
95 | { |
---|
96 | setAttributes.event_mask = base_mask; |
---|
97 | |
---|
98 | if (pSD->buttonBindings) |
---|
99 | { |
---|
100 | /* |
---|
101 | * The desktop menu and button bindings for window |
---|
102 | * manager functions use button press and button |
---|
103 | * release events. |
---|
104 | */ |
---|
105 | setAttributes.event_mask |= |
---|
106 | (ButtonPressMask | ButtonReleaseMask); |
---|
107 | } |
---|
108 | |
---|
109 | XChangeWindowAttributes (DISPLAY, pSD->rootWindow, |
---|
110 | CWEventMask, &setAttributes); |
---|
111 | |
---|
112 | |
---|
113 | /* |
---|
114 | * Setup event handling for "accelerated" window management |
---|
115 | * functions done with key bindings. |
---|
116 | */ |
---|
117 | |
---|
118 | if (pSD->keySpecs) |
---|
119 | { |
---|
120 | SetupKeyBindings (pSD->keySpecs, pSD->rootWindow, |
---|
121 | GrabModeSync, F_CONTEXT_ALL); |
---|
122 | } |
---|
123 | |
---|
124 | if (pSD->acceleratorMenuCount) |
---|
125 | { |
---|
126 | for (n = 0; n < pSD->acceleratorMenuCount; n++) |
---|
127 | { |
---|
128 | SetupKeyBindings ( |
---|
129 | pSD->acceleratorMenuSpecs[n]->accelKeySpecs, |
---|
130 | pSD->rootWindow, GrabModeSync, F_CONTEXT_ALL); |
---|
131 | } |
---|
132 | } |
---|
133 | } /* end if (managed) */ |
---|
134 | } /* end for (all screens) */ |
---|
135 | } /* END OF FUNCTION InitEventHandling */ |
---|
136 | |
---|
137 | |
---|
138 | |
---|
139 | /*************************************<->************************************* |
---|
140 | * |
---|
141 | * SetupKeyBindings (keySpecs, grabWindow, keyboardMode, context) |
---|
142 | * |
---|
143 | * |
---|
144 | * Description: |
---|
145 | * ----------- |
---|
146 | * This function sets up the event handling necessary to support user |
---|
147 | * specified key bindings for window manager functions. |
---|
148 | * |
---|
149 | * |
---|
150 | * Inputs: |
---|
151 | * ------ |
---|
152 | * keySpecs = list of key bindings for window manager functions. |
---|
153 | * |
---|
154 | * grabWindow = window that is to be associated with the passive key grab. |
---|
155 | * |
---|
156 | * keyboardMode = indicates keyboard mode for grab. |
---|
157 | * |
---|
158 | * context = context of key binding to set |
---|
159 | * |
---|
160 | * |
---|
161 | * Outputs: |
---|
162 | * ------- |
---|
163 | * RETURN = number of key bindings set |
---|
164 | * |
---|
165 | *************************************<->***********************************/ |
---|
166 | |
---|
167 | #ifdef _NO_PROTO |
---|
168 | int SetupKeyBindings (keySpecs, grabWindow, keyboardMode, context) |
---|
169 | KeySpec *keySpecs; |
---|
170 | Window grabWindow; |
---|
171 | int keyboardMode; |
---|
172 | long context; |
---|
173 | |
---|
174 | #else /* _NO_PROTO */ |
---|
175 | int SetupKeyBindings (KeySpec *keySpecs, Window grabWindow, int keyboardMode, long context) |
---|
176 | #endif /* _NO_PROTO */ |
---|
177 | { |
---|
178 | KeySpec *keySpec; |
---|
179 | int setCount = 0; |
---|
180 | Boolean iconContext; |
---|
181 | |
---|
182 | |
---|
183 | /* |
---|
184 | * Use key grabs to get the keys that invoke window manger functions. |
---|
185 | */ |
---|
186 | |
---|
187 | iconContext = (context == F_CONTEXT_ICON); |
---|
188 | keySpec = keySpecs; |
---|
189 | while (keySpec) |
---|
190 | { |
---|
191 | if (((F_CONTEXT_ICON == (keySpec->context ^ |
---|
192 | (F_CONTEXT_ICONBOX | |
---|
193 | F_SUBCONTEXT_IB_IICON | |
---|
194 | F_SUBCONTEXT_IB_WICON))) && |
---|
195 | iconContext) || |
---|
196 | ((F_CONTEXT_ICON != (keySpec->context ^ |
---|
197 | (F_CONTEXT_ICONBOX | |
---|
198 | F_SUBCONTEXT_IB_IICON | |
---|
199 | F_SUBCONTEXT_IB_WICON))) && |
---|
200 | !iconContext)) |
---|
201 | { |
---|
202 | |
---|
203 | XGrabKey (DISPLAY, keySpec->keycode, keySpec->state, grabWindow, |
---|
204 | False, GrabModeAsync, keyboardMode); |
---|
205 | |
---|
206 | XGrabKey (DISPLAY, keySpec->keycode, (keySpec->state | LockMask), |
---|
207 | grabWindow, False, GrabModeAsync, keyboardMode); |
---|
208 | |
---|
209 | setCount++; |
---|
210 | } |
---|
211 | |
---|
212 | keySpec = keySpec->nextKeySpec; |
---|
213 | } |
---|
214 | |
---|
215 | return (setCount); |
---|
216 | |
---|
217 | } /* END OF FUNCTION SetupKeyBindings */ |
---|
218 | |
---|
219 | |
---|
220 | |
---|
221 | /*************************************<->************************************* |
---|
222 | * |
---|
223 | * WmDispatchMenuEvent (event) |
---|
224 | * |
---|
225 | * |
---|
226 | * Description: |
---|
227 | * ----------- |
---|
228 | * This function detects and processes events that affect menu behavior that |
---|
229 | * are NOT dispatched (processed) by the toolkit. The events may cause the |
---|
230 | * menu to be unposted, may trigger hotspot processing, or may represent |
---|
231 | * menu accelerators. This processing is generally done when the system |
---|
232 | * menu is posted in "sticky" mode. |
---|
233 | * |
---|
234 | * |
---|
235 | * Inputs: |
---|
236 | * ------ |
---|
237 | * event = This is an X event that has been retrieved by XtNextEvent. |
---|
238 | * wmGD.menuActive == nonNULL |
---|
239 | * |
---|
240 | * |
---|
241 | * Outputs: |
---|
242 | * ------- |
---|
243 | * RETURN = If True the event should be dispatched by the toolkit, |
---|
244 | * otherwise the event should not be dispatched. |
---|
245 | * |
---|
246 | *************************************<->***********************************/ |
---|
247 | |
---|
248 | #ifdef _NO_PROTO |
---|
249 | Boolean WmDispatchMenuEvent (event) |
---|
250 | XButtonEvent *event; |
---|
251 | |
---|
252 | #else /* _NO_PROTO */ |
---|
253 | Boolean WmDispatchMenuEvent (XButtonEvent *event) |
---|
254 | #endif /* _NO_PROTO */ |
---|
255 | { |
---|
256 | ClientData *pCD = wmGD.menuClient; |
---|
257 | Boolean doXtDispatchEvent = True; |
---|
258 | Boolean checkContext; |
---|
259 | Context context = 0; |
---|
260 | /* For fixing the bug CR 5227 */ |
---|
261 | XKeyEvent *keyEvent; |
---|
262 | KeySpec *keySpecs; |
---|
263 | MenuButton *menuBtnPtr; |
---|
264 | |
---|
265 | |
---|
266 | if (event->type == KeyPress) |
---|
267 | { |
---|
268 | if (wmGD.menuActive->accelKeySpecs) |
---|
269 | { |
---|
270 | /* |
---|
271 | * Check to see if the KeyPress is a menu accelerator |
---|
272 | * (don't require context match for system menu accelerators). |
---|
273 | * If so, the active menu will be unposted and the KeyPress event |
---|
274 | * will not be sent on to the toolkit. |
---|
275 | */ |
---|
276 | |
---|
277 | checkContext = (!pCD || (pCD->systemMenuSpec != wmGD.menuActive)); |
---|
278 | if (checkContext) |
---|
279 | { |
---|
280 | if (pCD) |
---|
281 | { |
---|
282 | if (pCD->clientState == MINIMIZED_STATE) |
---|
283 | { |
---|
284 | context = F_CONTEXT_ICON; |
---|
285 | } |
---|
286 | else if (pCD->clientState == NORMAL_STATE) |
---|
287 | { |
---|
288 | context = F_CONTEXT_NORMAL; |
---|
289 | } |
---|
290 | else |
---|
291 | { |
---|
292 | context = F_CONTEXT_MAXIMIZE; |
---|
293 | } |
---|
294 | } |
---|
295 | else |
---|
296 | { |
---|
297 | context = F_CONTEXT_ROOT; |
---|
298 | } |
---|
299 | } |
---|
300 | /* Begin fixing CR 5227 */ |
---|
301 | keySpecs = wmGD.menuActive->accelKeySpecs; |
---|
302 | keyEvent = (XKeyEvent *)event; |
---|
303 | menuBtnPtr = wmGD.menuActive->menuButtons + |
---|
304 | (wmGD.menuActive->menuButtonSize - 1); |
---|
305 | |
---|
306 | while (keySpecs) |
---|
307 | { |
---|
308 | if ((keyEvent->state == keySpecs->state) && |
---|
309 | (keyEvent->keycode == keySpecs->keycode) |
---|
310 | && ((!checkContext) || (context & keySpecs->context))) |
---|
311 | { |
---|
312 | doXtDispatchEvent = |
---|
313 | XtIsSensitive(menuBtnPtr->buttonWidget); |
---|
314 | break; |
---|
315 | } |
---|
316 | keySpecs = keySpecs->nextKeySpec; |
---|
317 | menuBtnPtr--; |
---|
318 | } |
---|
319 | |
---|
320 | doXtDispatchEvent = |
---|
321 | HandleKeyPress ((XKeyEvent *)event, |
---|
322 | wmGD.menuActive->accelKeySpecs, |
---|
323 | checkContext, context, |
---|
324 | TRUE, (ClientData *)NULL); |
---|
325 | } |
---|
326 | |
---|
327 | if (wmGD.menuActive && wmGD.menuUnpostKeySpec) |
---|
328 | { |
---|
329 | if ((wmGD.menuUnpostKeySpec->state == event->state) && |
---|
330 | (wmGD.menuUnpostKeySpec->keycode == event->button)) |
---|
331 | { |
---|
332 | /* |
---|
333 | * This is an alternate key for unposting a menu from the |
---|
334 | * keyboard (in addition to [ESC]). |
---|
335 | */ |
---|
336 | |
---|
337 | UnpostMenu (wmGD.menuActive); |
---|
338 | doXtDispatchEvent = False; |
---|
339 | } |
---|
340 | } |
---|
341 | } |
---|
342 | |
---|
343 | else if (wmGD.checkHotspot && |
---|
344 | ((event->type == ButtonPress) || |
---|
345 | (event->type == ButtonRelease)) && |
---|
346 | (event->x_root >= wmGD.hotspotRectangle.x) && |
---|
347 | (event->y_root >= wmGD.hotspotRectangle.y) && |
---|
348 | (event->x_root < |
---|
349 | (wmGD.hotspotRectangle.x + wmGD.hotspotRectangle.width)) && |
---|
350 | (event->y_root < |
---|
351 | (wmGD.hotspotRectangle.y + wmGD.hotspotRectangle.height))&& |
---|
352 | pCD) |
---|
353 | { |
---|
354 | /* ^^^ |
---|
355 | * Added check for NULL pCD in the above condition. |
---|
356 | * We should never get here with a NULL pCD, but, |
---|
357 | * sometimes our UnmapCallback for a menu does not |
---|
358 | * get called, so..., we get to this point because |
---|
359 | * wmGD.menuActive is not cleared, but, wmGD.menuClient |
---|
360 | * is set to NULL when we unmanage the client window. |
---|
361 | */ |
---|
362 | |
---|
363 | /* |
---|
364 | * The event triggers hotspot processing for the system menu button |
---|
365 | * or an icon. |
---|
366 | */ |
---|
367 | |
---|
368 | if (event->type == ButtonRelease) |
---|
369 | { |
---|
370 | /* |
---|
371 | * The system menu is posted from a system menu button or an |
---|
372 | * icon. By doing a button release over the system menu button |
---|
373 | * or icon the system menu that is posted is put into keyboard |
---|
374 | * traversal mode. |
---|
375 | */ |
---|
376 | |
---|
377 | ProcessClickBRelease (event, pCD, wmGD.clickData.context, |
---|
378 | wmGD.clickData.subContext); |
---|
379 | |
---|
380 | if (wmGD.clickData.context == F_SUBCONTEXT_W_SYSTEM) |
---|
381 | { |
---|
382 | PopGadgetOut (pCD, FRAME_SYSTEM); |
---|
383 | } |
---|
384 | #ifdef MOTIF_ONE_DOT_ONE |
---|
385 | TraversalOn (pCD->systemMenuSpec); |
---|
386 | doXtDispatchEvent = False; |
---|
387 | #else |
---|
388 | _XmSetLastManagedMenuTime ((Widget)XtParent(pCD->systemMenuSpec->menuWidget), |
---|
389 | ((XButtonEvent *)event)->time); |
---|
390 | doXtDispatchEvent = True; |
---|
391 | #endif |
---|
392 | } |
---|
393 | else |
---|
394 | { |
---|
395 | /* |
---|
396 | * A button press over a system menu button or an icon when the |
---|
397 | * system menu is posted indicates that a double-click action is |
---|
398 | * to be done if appropriate and the menu is to be taken |
---|
399 | * out of traversal mode (done by the menu widget). |
---|
400 | */ |
---|
401 | |
---|
402 | ProcessClickBPress (event, pCD, wmGD.clickData.context, |
---|
403 | wmGD.clickData.subContext); |
---|
404 | |
---|
405 | if (wmGD.clickData.subContext == F_SUBCONTEXT_W_SYSTEM) |
---|
406 | { |
---|
407 | PushGadgetIn (pCD, FRAME_SYSTEM); |
---|
408 | } |
---|
409 | |
---|
410 | if (wmGD.clickData.doubleClickContext == F_SUBCONTEXT_W_SYSTEM) |
---|
411 | { |
---|
412 | if (wmGD.systemButtonClick2 && |
---|
413 | (pCD->clientFunctions & MWM_FUNC_CLOSE)) |
---|
414 | { |
---|
415 | /* |
---|
416 | * Close the client window. Cancel other system menu |
---|
417 | * button actions. |
---|
418 | */ |
---|
419 | |
---|
420 | UnpostMenu (pCD->systemMenuSpec); |
---|
421 | F_Kill (NULL, pCD, (XEvent *) event); |
---|
422 | doXtDispatchEvent = False; |
---|
423 | } |
---|
424 | } |
---|
425 | else |
---|
426 | if (wmGD.clickData.doubleClickContext == F_SUBCONTEXT_I_ALL) |
---|
427 | { |
---|
428 | /* |
---|
429 | * Normalize the icon. |
---|
430 | */ |
---|
431 | int newState; |
---|
432 | |
---|
433 | UnpostMenu (pCD->systemMenuSpec); |
---|
434 | if (pCD->maxConfig) |
---|
435 | { |
---|
436 | newState = MAXIMIZED_STATE; |
---|
437 | } |
---|
438 | else |
---|
439 | { |
---|
440 | newState = NORMAL_STATE; |
---|
441 | } |
---|
442 | |
---|
443 | SetClientState (pCD, newState, event->time); |
---|
444 | wmGD.clickData.clickPending = False; |
---|
445 | wmGD.clickData.doubleClickPending = False; |
---|
446 | doXtDispatchEvent = False; |
---|
447 | } |
---|
448 | else |
---|
449 | if ((wmGD.clickData.doubleClickContext == F_SUBCONTEXT_IB_IICON)|| |
---|
450 | (wmGD.clickData.doubleClickContext == F_SUBCONTEXT_IB_WICON)) |
---|
451 | { |
---|
452 | /* |
---|
453 | * Raise the Window and Normalize |
---|
454 | */ |
---|
455 | |
---|
456 | UnpostMenu (pCD->systemMenuSpec); |
---|
457 | F_Restore_And_Raise ((String)NULL, pCD, (XEvent *)NULL); |
---|
458 | /* F_Normalize_And_Raise ((String)NULL, pCD, (XEvent *)NULL); |
---|
459 | */ doXtDispatchEvent = False; |
---|
460 | } |
---|
461 | |
---|
462 | /* |
---|
463 | * Else no special button press processing; have the toolkit |
---|
464 | * dispatch the event to the menu widgets. |
---|
465 | */ |
---|
466 | } |
---|
467 | } |
---|
468 | |
---|
469 | return (doXtDispatchEvent); |
---|
470 | |
---|
471 | |
---|
472 | } /* END OF FUNCTION WmDispatchMenuEvent */ |
---|
473 | |
---|
474 | |
---|
475 | |
---|
476 | /*************************************<->************************************* |
---|
477 | * |
---|
478 | * WmDispatchWsEvent (event) |
---|
479 | * |
---|
480 | * |
---|
481 | * Description: |
---|
482 | * ----------- |
---|
483 | * This function detects and dispatches events that are reported to the root |
---|
484 | * (workspace) window and that are not widget-related (i.e. they would not be |
---|
485 | * dispatched by the Xtk intrinsics). |
---|
486 | * |
---|
487 | * |
---|
488 | * Inputs: |
---|
489 | * ------ |
---|
490 | * event = This is an X event that has been retrieved by XtNextEvent. |
---|
491 | * |
---|
492 | * |
---|
493 | * Outputs: |
---|
494 | * ------- |
---|
495 | * RETURN = If True the event should be dispatched by the toolkit, |
---|
496 | * otherwise the event should not be dispatched. |
---|
497 | * |
---|
498 | *************************************<->***********************************/ |
---|
499 | |
---|
500 | #ifdef _NO_PROTO |
---|
501 | Boolean WmDispatchWsEvent (event) |
---|
502 | XEvent *event; |
---|
503 | |
---|
504 | #else /* _NO_PROTO */ |
---|
505 | Boolean WmDispatchWsEvent (XEvent *event) |
---|
506 | #endif /* _NO_PROTO */ |
---|
507 | { |
---|
508 | ClientData *pCD; |
---|
509 | Boolean dispatchEvent = False; |
---|
510 | WmScreenData *pSD; |
---|
511 | |
---|
512 | |
---|
513 | /* |
---|
514 | * Detect and dispatch non-widget events that have been reported to |
---|
515 | * the root window. |
---|
516 | */ |
---|
517 | |
---|
518 | switch (event->type) |
---|
519 | { |
---|
520 | case KeyPress: |
---|
521 | { |
---|
522 | /* |
---|
523 | * The key press is to initiate some window management |
---|
524 | * function (e.g., shuffle the client windows). |
---|
525 | */ |
---|
526 | |
---|
527 | dispatchEvent = HandleWsKeyPress ((XKeyEvent *)event); |
---|
528 | break; |
---|
529 | } |
---|
530 | |
---|
531 | case ButtonPress: |
---|
532 | { |
---|
533 | /* |
---|
534 | * The button press is to initiate some window management |
---|
535 | * function (e.g., pop up the desktop menu). |
---|
536 | */ |
---|
537 | |
---|
538 | if (wmGD.menuActive) |
---|
539 | { |
---|
540 | dispatchEvent = True; /* have the toolkit dispatch the event */ |
---|
541 | } |
---|
542 | else |
---|
543 | { |
---|
544 | HandleWsButtonPress ((XButtonEvent *)event); |
---|
545 | } |
---|
546 | break; |
---|
547 | } |
---|
548 | |
---|
549 | case ButtonRelease: |
---|
550 | { |
---|
551 | /* |
---|
552 | * The button release may do some window management |
---|
553 | * function. |
---|
554 | */ |
---|
555 | |
---|
556 | if (wmGD.menuActive) |
---|
557 | { |
---|
558 | dispatchEvent = True; /* have the toolkit dispatch the event */ |
---|
559 | } |
---|
560 | else |
---|
561 | { |
---|
562 | HandleWsButtonRelease ((XButtonEvent *)event); |
---|
563 | } |
---|
564 | break; |
---|
565 | } |
---|
566 | |
---|
567 | case UnmapNotify: |
---|
568 | { |
---|
569 | /* BEGIN CR 5183 */ |
---|
570 | if ( (!XFindContext (DISPLAY, event->xunmap.window, |
---|
571 | wmGD.windowContextType, |
---|
572 | (XPointer *)&pCD) |
---|
573 | ) |
---|
574 | && (((XUnmapEvent *)event)->window == pCD->client) |
---|
575 | ) |
---|
576 | /* END CR 5183 */ |
---|
577 | { |
---|
578 | /* |
---|
579 | * This is a synthetic UnmapNotity used to withdraw a client |
---|
580 | * window form window manager control. |
---|
581 | */ |
---|
582 | |
---|
583 | UnManageWindow (pCD); |
---|
584 | } |
---|
585 | break; |
---|
586 | } |
---|
587 | |
---|
588 | case EnterNotify: |
---|
589 | { |
---|
590 | HandleWsEnterNotify ((XEnterWindowEvent *)event); |
---|
591 | break; |
---|
592 | } |
---|
593 | |
---|
594 | case LeaveNotify: |
---|
595 | { |
---|
596 | HandleWsLeaveNotify ((XLeaveWindowEvent *)event); |
---|
597 | break; |
---|
598 | } |
---|
599 | |
---|
600 | case ConfigureRequest: |
---|
601 | { |
---|
602 | HandleWsConfigureRequest ((XConfigureRequestEvent *)event); |
---|
603 | break; |
---|
604 | } |
---|
605 | |
---|
606 | case MapRequest: |
---|
607 | { |
---|
608 | /* |
---|
609 | * Determine if the window is already being managed: |
---|
610 | */ |
---|
611 | |
---|
612 | if ((XFindContext (DISPLAY, event->xmaprequest.window, |
---|
613 | wmGD.windowContextType, (XPointer *)&pCD)) && |
---|
614 | (pSD = GetScreenForWindow (event->xmaprequest.window))) |
---|
615 | { |
---|
616 | /* |
---|
617 | * The window is not yet managed and it's parented to a |
---|
618 | * screen/root window that we manage. Start to manage the |
---|
619 | * new window. Management details are dependent on the |
---|
620 | * type of the window. For a typical top-level application |
---|
621 | * window reparent the window to a window frame, add it to |
---|
622 | * the wm saveset, ... |
---|
623 | */ |
---|
624 | |
---|
625 | ManageWindow (pSD, event->xmaprequest.window, MANAGEW_NORMAL); |
---|
626 | } |
---|
627 | /* else ... |
---|
628 | * The context information on the window WAS found. |
---|
629 | * The window is already managed by the window manager |
---|
630 | * so this is redundant request to have the client |
---|
631 | * window managed. |
---|
632 | */ |
---|
633 | |
---|
634 | break; |
---|
635 | } |
---|
636 | |
---|
637 | case FocusIn: |
---|
638 | { |
---|
639 | HandleWsFocusIn ((XFocusInEvent *)event); |
---|
640 | break; |
---|
641 | } |
---|
642 | |
---|
643 | case FocusOut: |
---|
644 | { |
---|
645 | break; |
---|
646 | } |
---|
647 | |
---|
648 | } /* end of event.type switch */ |
---|
649 | |
---|
650 | |
---|
651 | return (dispatchEvent); |
---|
652 | |
---|
653 | } /* END OF FUNCTION WmDispatchWsEvent */ |
---|
654 | |
---|
655 | |
---|
656 | |
---|
657 | /*************************************<->************************************* |
---|
658 | * |
---|
659 | * HandleWsKeyPress (keyEvent) |
---|
660 | * |
---|
661 | * |
---|
662 | * Description: |
---|
663 | * ----------- |
---|
664 | * This function processes KeyPress events that are reported to the root |
---|
665 | * window. These events are generally associated with accelerators. |
---|
666 | * |
---|
667 | * |
---|
668 | * Inputs: |
---|
669 | * ------ |
---|
670 | * keyEvent = pointer to a key press event on the root window. |
---|
671 | * |
---|
672 | * Output: |
---|
673 | * ------ |
---|
674 | * RETURN = True is the event is to be dispatched by XtDispatch. |
---|
675 | * |
---|
676 | *************************************<->***********************************/ |
---|
677 | |
---|
678 | #ifdef _NO_PROTO |
---|
679 | Boolean HandleWsKeyPress (keyEvent) |
---|
680 | XKeyEvent *keyEvent; |
---|
681 | |
---|
682 | #else /* _NO_PROTO */ |
---|
683 | Boolean HandleWsKeyPress (XKeyEvent *keyEvent) |
---|
684 | #endif /* _NO_PROTO */ |
---|
685 | { |
---|
686 | Boolean dispatchEvent = False; |
---|
687 | Boolean checkKeyEvent = True; |
---|
688 | unsigned int n; |
---|
689 | Context context; |
---|
690 | |
---|
691 | if (wmGD.menuActive) |
---|
692 | { |
---|
693 | /* |
---|
694 | * The active menu accelerators have been checked and keyEvent was |
---|
695 | * not one of them. We will check for pass keys mode and then |
---|
696 | * have the toolkit dispatch the event, without searching any other |
---|
697 | * key or accelerator specification list. |
---|
698 | */ |
---|
699 | |
---|
700 | dispatchEvent = True; |
---|
701 | checkKeyEvent = False; |
---|
702 | } |
---|
703 | |
---|
704 | /* |
---|
705 | * If pass keys is active then only check for getting out of the |
---|
706 | * pass keys mode. Unfreeze the keyboard and replay the key if |
---|
707 | * pass keys is active. |
---|
708 | */ |
---|
709 | |
---|
710 | if (wmGD.passKeysActive) |
---|
711 | { |
---|
712 | if (wmGD.passKeysKeySpec && |
---|
713 | (wmGD.passKeysKeySpec->state == keyEvent->state) && |
---|
714 | (wmGD.passKeysKeySpec->keycode == keyEvent->keycode)) |
---|
715 | { |
---|
716 | /* |
---|
717 | * Get out of the pass keys mode. |
---|
718 | */ |
---|
719 | |
---|
720 | F_Pass_Key (NULL, (ClientData *) NULL, (XEvent *) NULL); |
---|
721 | XAllowEvents (DISPLAY, AsyncKeyboard, CurrentTime); |
---|
722 | } |
---|
723 | else |
---|
724 | { |
---|
725 | XAllowEvents (DISPLAY, ReplayKeyboard, CurrentTime); |
---|
726 | } |
---|
727 | checkKeyEvent = False; |
---|
728 | } |
---|
729 | else |
---|
730 | { |
---|
731 | XAllowEvents (DISPLAY, AsyncKeyboard, CurrentTime); |
---|
732 | } |
---|
733 | |
---|
734 | |
---|
735 | /* |
---|
736 | * Search through the key specification list and the menu |
---|
737 | * accelerator lists until these lists are exhausted or |
---|
738 | * the event is handled. |
---|
739 | */ |
---|
740 | |
---|
741 | if (checkKeyEvent) |
---|
742 | { |
---|
743 | if (wmGD.keyboardFocus) |
---|
744 | { |
---|
745 | if (wmGD.keyboardFocus->clientState == MINIMIZED_STATE) |
---|
746 | { |
---|
747 | context = F_CONTEXT_ICON; |
---|
748 | } |
---|
749 | else if (wmGD.keyboardFocus->clientState == NORMAL_STATE) |
---|
750 | { |
---|
751 | context = F_CONTEXT_NORMAL; |
---|
752 | } |
---|
753 | else |
---|
754 | { |
---|
755 | context = F_CONTEXT_MAXIMIZE; |
---|
756 | } |
---|
757 | } |
---|
758 | else |
---|
759 | { |
---|
760 | context = F_CONTEXT_ROOT; |
---|
761 | } |
---|
762 | |
---|
763 | if (HandleKeyPress (keyEvent, ACTIVE_PSD->keySpecs, |
---|
764 | TRUE, context, FALSE, (ClientData *)NULL) && |
---|
765 | ACTIVE_PSD->acceleratorMenuCount) |
---|
766 | { |
---|
767 | for (n = 0; ((keyEvent->keycode != 0) && |
---|
768 | (n < ACTIVE_PSD->acceleratorMenuCount)); n++) |
---|
769 | { |
---|
770 | if (!HandleKeyPress (keyEvent, |
---|
771 | ACTIVE_PSD->acceleratorMenuSpecs[n]->accelKeySpecs, |
---|
772 | TRUE, context, TRUE,(ClientData *)NULL)) |
---|
773 | { |
---|
774 | break; |
---|
775 | } |
---|
776 | } |
---|
777 | } |
---|
778 | } |
---|
779 | |
---|
780 | return (dispatchEvent); |
---|
781 | |
---|
782 | } /* END OF FUNCTION HandleWsKeyPress */ |
---|
783 | |
---|
784 | |
---|
785 | |
---|
786 | /*************************************<->************************************* |
---|
787 | * |
---|
788 | * HandleKeyPress (keyEvent, keySpecs, checkContext, context, onlyFirst, pCD) |
---|
789 | * |
---|
790 | * |
---|
791 | * Description: |
---|
792 | * ----------- |
---|
793 | * This function identifies window manager functions that are triggered by |
---|
794 | * a KeyPress event. The window manager functions are done if appropriate. |
---|
795 | * |
---|
796 | * |
---|
797 | * Inputs: |
---|
798 | * ------ |
---|
799 | * keyEvent = pointer to a key press event on the root window |
---|
800 | * keySpecs = pointer to a key specification list to search |
---|
801 | * checkContext = TRUE iff the context must match the keySpec context. |
---|
802 | * context = context to match keySpec context. |
---|
803 | * onlyFirst = TRUE iff key processing should stop with the first match. |
---|
804 | * |
---|
805 | * Output: |
---|
806 | * ------ |
---|
807 | * RETURN = False if key binding processing should be terminated; True if |
---|
808 | * key binding processing can continue |
---|
809 | * |
---|
810 | *************************************<->***********************************/ |
---|
811 | |
---|
812 | #ifdef _NO_PROTO |
---|
813 | Boolean HandleKeyPress (keyEvent, keySpecs, checkContext, context, onlyFirst, pCD) |
---|
814 | |
---|
815 | XKeyEvent *keyEvent; |
---|
816 | KeySpec *keySpecs; |
---|
817 | Boolean checkContext; |
---|
818 | Context context; |
---|
819 | Boolean onlyFirst; |
---|
820 | ClientData *pCD; |
---|
821 | |
---|
822 | |
---|
823 | #else /* _NO_PROTO */ |
---|
824 | Boolean HandleKeyPress (XKeyEvent *keyEvent, |
---|
825 | KeySpec *keySpecs, |
---|
826 | Boolean checkContext, |
---|
827 | Context context, |
---|
828 | Boolean onlyFirst, |
---|
829 | ClientData *pCD) |
---|
830 | #endif /* _NO_PROTO */ |
---|
831 | { |
---|
832 | Boolean processKey = True; |
---|
833 | ClientData *functionClient; |
---|
834 | |
---|
835 | /* |
---|
836 | * Search for matching key specification. |
---|
837 | */ |
---|
838 | |
---|
839 | while (processKey && keySpecs) |
---|
840 | { |
---|
841 | if ((keyEvent->state == keySpecs->state) && |
---|
842 | (keyEvent->keycode == keySpecs->keycode) && |
---|
843 | ((!checkContext) || (context & keySpecs->context))) |
---|
844 | { |
---|
845 | /* |
---|
846 | * A matching key binding has been found. |
---|
847 | * Determine the client to which the key binding function is to |
---|
848 | * apply. |
---|
849 | * Unpost any active menu and specify that no futher key binding |
---|
850 | * processing should be done. |
---|
851 | * Do the function associated with the matching key binding. |
---|
852 | * Stop if onlyFirst == TRUE |
---|
853 | */ |
---|
854 | |
---|
855 | if (pCD) |
---|
856 | { |
---|
857 | functionClient = pCD; |
---|
858 | } |
---|
859 | else |
---|
860 | { |
---|
861 | functionClient = wmGD.keyboardFocus; |
---|
862 | } |
---|
863 | |
---|
864 | if (wmGD.menuActive) |
---|
865 | { |
---|
866 | functionClient = wmGD.menuClient; /* might not have focus! */ |
---|
867 | UnpostMenu (wmGD.menuActive); |
---|
868 | processKey = False; |
---|
869 | } |
---|
870 | else if (onlyFirst) |
---|
871 | { |
---|
872 | processKey = False; |
---|
873 | } |
---|
874 | |
---|
875 | if ((keySpecs->wmFunction == F_Menu) || |
---|
876 | (keySpecs->wmFunction == F_Post_SMenu)) |
---|
877 | { |
---|
878 | wmGD.menuUnpostKeySpec = keySpecs; /* menu unpost key spec */ |
---|
879 | } |
---|
880 | else if (keySpecs->wmFunction == F_Pass_Key) |
---|
881 | { |
---|
882 | wmGD.passKeysKeySpec = keySpecs; |
---|
883 | } |
---|
884 | if (!(keySpecs->wmFunction (keySpecs->wmFuncArgs, |
---|
885 | functionClient, keyEvent))) |
---|
886 | { |
---|
887 | /* |
---|
888 | * The window manager function return indicates that further |
---|
889 | * key binding processing should not be done. |
---|
890 | */ |
---|
891 | |
---|
892 | processKey = False; |
---|
893 | } |
---|
894 | } |
---|
895 | keySpecs = keySpecs->nextKeySpec; |
---|
896 | } |
---|
897 | |
---|
898 | return (processKey); |
---|
899 | |
---|
900 | |
---|
901 | } /* END OF FUNCTION HandleKeyPress */ |
---|
902 | |
---|
903 | |
---|
904 | |
---|
905 | /*************************************<->************************************* |
---|
906 | * |
---|
907 | * HandleWsButtonPress (buttonEvent) |
---|
908 | * |
---|
909 | * |
---|
910 | * Description: |
---|
911 | * ----------- |
---|
912 | * This function identifies button events that are associated with window |
---|
913 | * manager functions. Window manager functions are done if appropriate. |
---|
914 | * |
---|
915 | * |
---|
916 | * Inputs: |
---|
917 | * ------ |
---|
918 | * buttonEvent = pointer to a button press event on the root window |
---|
919 | * |
---|
920 | *************************************<->***********************************/ |
---|
921 | |
---|
922 | #ifdef _NO_PROTO |
---|
923 | void HandleWsButtonPress (buttonEvent) |
---|
924 | XButtonEvent *buttonEvent; |
---|
925 | |
---|
926 | #else /* _NO_PROTO */ |
---|
927 | void HandleWsButtonPress (XButtonEvent *buttonEvent) |
---|
928 | #endif /* _NO_PROTO */ |
---|
929 | { |
---|
930 | ClientData *pCD; |
---|
931 | Context context; |
---|
932 | int partContext; |
---|
933 | Context subContext; |
---|
934 | |
---|
935 | |
---|
936 | /* |
---|
937 | * Determine if the top-level window that contains the pointer is a |
---|
938 | * client managed by the window manager (there may be no window under |
---|
939 | * the pointer or it may be an "override-redirect" window). |
---|
940 | */ |
---|
941 | |
---|
942 | if ((buttonEvent->subwindow == None) || |
---|
943 | (XFindContext (DISPLAY, buttonEvent->subwindow, wmGD.windowContextType, |
---|
944 | (XPointer *)&pCD))) |
---|
945 | { |
---|
946 | /* no managed window under the pointer */ |
---|
947 | pCD = NULL; |
---|
948 | } |
---|
949 | |
---|
950 | |
---|
951 | /* |
---|
952 | * Look through the window manager function button binding list for |
---|
953 | * matches with the event: |
---|
954 | */ |
---|
955 | |
---|
956 | IdentifyEventContext (buttonEvent, pCD, &context, &partContext); |
---|
957 | subContext = (1L << partContext); |
---|
958 | |
---|
959 | ProcessClickBPress (buttonEvent, pCD, context, subContext); |
---|
960 | |
---|
961 | if (CheckForButtonAction (buttonEvent, context, subContext, pCD) && pCD) |
---|
962 | { |
---|
963 | /* |
---|
964 | * Button bindings have been processed, now check for bindings that |
---|
965 | * are associated with the built-in semantics of the window frame |
---|
966 | * decorations. |
---|
967 | */ |
---|
968 | |
---|
969 | CheckButtonPressBuiltin (buttonEvent, context, subContext, partContext, |
---|
970 | pCD); |
---|
971 | } |
---|
972 | /* |
---|
973 | * Else skip built-in processing due to execution of a function that |
---|
974 | * does on-going event processing or that has changed the client state |
---|
975 | * (e.g., f.move or f.minimize). |
---|
976 | */ |
---|
977 | |
---|
978 | |
---|
979 | } /* END OF FUNCTION HandleWsButtonPress */ |
---|
980 | |
---|
981 | |
---|
982 | |
---|
983 | /*************************************<->************************************* |
---|
984 | * |
---|
985 | * HandleWsButtonRelease (buttonEvent) |
---|
986 | * |
---|
987 | * |
---|
988 | * Description: |
---|
989 | * ----------- |
---|
990 | * This function identifies button release events that are associated with |
---|
991 | * window manager functions. Window manager functions are done if |
---|
992 | * appropriate. |
---|
993 | * |
---|
994 | * |
---|
995 | * Inputs: |
---|
996 | * ------ |
---|
997 | * buttonEvent = pointer to a button release event |
---|
998 | * |
---|
999 | *************************************<->***********************************/ |
---|
1000 | |
---|
1001 | #ifdef _NO_PROTO |
---|
1002 | void HandleWsButtonRelease (buttonEvent) |
---|
1003 | XButtonEvent *buttonEvent; |
---|
1004 | |
---|
1005 | #else /* _NO_PROTO */ |
---|
1006 | void HandleWsButtonRelease (XButtonEvent *buttonEvent) |
---|
1007 | #endif /* _NO_PROTO */ |
---|
1008 | { |
---|
1009 | ClientData *pCD; |
---|
1010 | Context context; |
---|
1011 | int partContext; |
---|
1012 | Context subContext; |
---|
1013 | |
---|
1014 | |
---|
1015 | /* |
---|
1016 | * Determine if the top-level window that contains the pointer is a |
---|
1017 | * client managed by the window manager (there may be no window under |
---|
1018 | * the pointer or it may be an "override-redirect" window). |
---|
1019 | */ |
---|
1020 | |
---|
1021 | if ((buttonEvent->subwindow == None) || |
---|
1022 | (XFindContext (DISPLAY, buttonEvent->subwindow, wmGD.windowContextType, |
---|
1023 | (XPointer *)&pCD))) |
---|
1024 | { |
---|
1025 | /* no managed window under the pointer */ |
---|
1026 | pCD = NULL; |
---|
1027 | } |
---|
1028 | |
---|
1029 | |
---|
1030 | /* |
---|
1031 | * Look for a builtin function that may be done by this event. |
---|
1032 | */ |
---|
1033 | |
---|
1034 | IdentifyEventContext (buttonEvent, pCD, &context, &partContext); |
---|
1035 | subContext = (1L << partContext); |
---|
1036 | |
---|
1037 | ProcessClickBRelease (buttonEvent, pCD, context, subContext); |
---|
1038 | |
---|
1039 | if (CheckForButtonAction (buttonEvent, context, subContext, pCD) && pCD) |
---|
1040 | { |
---|
1041 | /* |
---|
1042 | * Button bindings have been processed, now check for bindings that |
---|
1043 | * are associated with the built-in semantics of the window frame |
---|
1044 | * decorations. |
---|
1045 | */ |
---|
1046 | |
---|
1047 | CheckButtonReleaseBuiltin (buttonEvent, context, subContext, pCD); |
---|
1048 | } |
---|
1049 | /* |
---|
1050 | * Else skip built-in processing due to execution of a function that |
---|
1051 | * does on-going event processing or that has changed the client state |
---|
1052 | * (e.g., f.move or f.minimize). |
---|
1053 | */ |
---|
1054 | |
---|
1055 | |
---|
1056 | } /* END OF FUNCTION HandleWsButtonRelease */ |
---|
1057 | |
---|
1058 | |
---|
1059 | |
---|
1060 | /*************************************<->************************************* |
---|
1061 | * |
---|
1062 | * CheckForButtonAction (buttonEvent, context, subContext, pCD) |
---|
1063 | * |
---|
1064 | * |
---|
1065 | * Description: |
---|
1066 | * ----------- |
---|
1067 | * This function checks to see if a button event is to do a button binding |
---|
1068 | * action. The action is done if specified. |
---|
1069 | * |
---|
1070 | * |
---|
1071 | * Inputs: |
---|
1072 | * ------ |
---|
1073 | * buttonEvent = a button event handled by the window manager |
---|
1074 | * |
---|
1075 | * context = button event context (root, icon, window) |
---|
1076 | * |
---|
1077 | * subContext = button event subContext (title, system button, etc.) |
---|
1078 | * |
---|
1079 | * pCD = a pointer to client data that is associated with the button event |
---|
1080 | * |
---|
1081 | * |
---|
1082 | * Outputs: |
---|
1083 | * ------- |
---|
1084 | * RETURN = If True then further button binding processing can be done; |
---|
1085 | * if false then a state change function, menu function, or |
---|
1086 | * configuration function is ongoing and further button binding |
---|
1087 | * processing should not be done. |
---|
1088 | * |
---|
1089 | * |
---|
1090 | *************************************<->***********************************/ |
---|
1091 | |
---|
1092 | #ifdef _NO_PROTO |
---|
1093 | Boolean CheckForButtonAction (buttonEvent, context, subContext, pCD) |
---|
1094 | XButtonEvent *buttonEvent; |
---|
1095 | Context context; |
---|
1096 | Context subContext; |
---|
1097 | ClientData *pCD; |
---|
1098 | |
---|
1099 | #else /* _NO_PROTO */ |
---|
1100 | Boolean CheckForButtonAction (XButtonEvent *buttonEvent, Context context, Context subContext, ClientData *pCD) |
---|
1101 | #endif /* _NO_PROTO */ |
---|
1102 | { |
---|
1103 | ButtonSpec *buttonSpec; |
---|
1104 | |
---|
1105 | /* |
---|
1106 | * Look through the window manager function button binding list for |
---|
1107 | * matches with the event: |
---|
1108 | */ |
---|
1109 | |
---|
1110 | buttonSpec = ACTIVE_PSD->buttonSpecs; |
---|
1111 | while (buttonSpec) |
---|
1112 | { |
---|
1113 | if ((buttonEvent->button == buttonSpec->button) && |
---|
1114 | ((buttonEvent->state == buttonSpec->state) || |
---|
1115 | (wmGD.currentEventState == buttonSpec->state))) |
---|
1116 | { |
---|
1117 | /* |
---|
1118 | * See if the event context matches the binding context. |
---|
1119 | */ |
---|
1120 | |
---|
1121 | if ((buttonEvent->type == buttonSpec->eventType) && |
---|
1122 | (context & buttonSpec->context) && |
---|
1123 | (subContext & buttonSpec->subContext)) |
---|
1124 | { |
---|
1125 | |
---|
1126 | /* |
---|
1127 | * For click type bindings check for a match between the |
---|
1128 | * event context and the click / double-click context. |
---|
1129 | */ |
---|
1130 | |
---|
1131 | if (buttonEvent->type == ButtonRelease) |
---|
1132 | { |
---|
1133 | /* |
---|
1134 | * Clicks occur on button releases. A button release |
---|
1135 | * binding is always treated as a click binding. |
---|
1136 | */ |
---|
1137 | |
---|
1138 | if ((buttonSpec->subContext | wmGD.clickData.clickContext) |
---|
1139 | != buttonSpec->subContext) |
---|
1140 | { |
---|
1141 | /* click binding and event contexts do not match */ |
---|
1142 | buttonSpec = buttonSpec->nextButtonSpec; |
---|
1143 | continue; |
---|
1144 | } |
---|
1145 | /* else there is a click match */ |
---|
1146 | } |
---|
1147 | else if (buttonSpec->click && (buttonEvent->type==ButtonPress)) |
---|
1148 | { |
---|
1149 | /* |
---|
1150 | * Double-clicks occur on button presses. |
---|
1151 | */ |
---|
1152 | |
---|
1153 | if ((buttonSpec->subContext | |
---|
1154 | wmGD.clickData.doubleClickContext) |
---|
1155 | != buttonSpec->subContext) |
---|
1156 | { |
---|
1157 | /* click binding and event contexts do not match */ |
---|
1158 | buttonSpec = buttonSpec->nextButtonSpec; |
---|
1159 | continue; |
---|
1160 | } |
---|
1161 | else |
---|
1162 | { |
---|
1163 | /* |
---|
1164 | * The is a double-click match. Don't do any click |
---|
1165 | * or double-click matches for the following button |
---|
1166 | * press and release. |
---|
1167 | */ |
---|
1168 | |
---|
1169 | wmGD.clickData.clickPending = False; |
---|
1170 | wmGD.clickData.doubleClickPending = False; |
---|
1171 | } |
---|
1172 | } |
---|
1173 | |
---|
1174 | if (!(buttonSpec->wmFunction (buttonSpec->wmFuncArgs, pCD, |
---|
1175 | buttonEvent))) |
---|
1176 | { |
---|
1177 | /* |
---|
1178 | * The window manager function return indicates that |
---|
1179 | * further button binding processing should not be done. |
---|
1180 | */ |
---|
1181 | |
---|
1182 | return (False); |
---|
1183 | } |
---|
1184 | } |
---|
1185 | } |
---|
1186 | buttonSpec = buttonSpec->nextButtonSpec; |
---|
1187 | } |
---|
1188 | |
---|
1189 | return (True); |
---|
1190 | |
---|
1191 | |
---|
1192 | } /* END OF FUNCTION CheckForButtonAction */ |
---|
1193 | |
---|
1194 | |
---|
1195 | |
---|
1196 | /*************************************<->************************************* |
---|
1197 | * |
---|
1198 | * IdentifyEventContext (event, pCD, pContext, pPartContext) |
---|
1199 | * |
---|
1200 | * |
---|
1201 | * Description: |
---|
1202 | * ----------- |
---|
1203 | * This function identifies the context in which an event occured. The |
---|
1204 | * pointer position is used to identify the context if the event is a |
---|
1205 | * button event. If the context and the window state are incompatible |
---|
1206 | * (e.g., the context is window and the window is minimized) then the |
---|
1207 | * context is reset to 0 (none). |
---|
1208 | * |
---|
1209 | * |
---|
1210 | * Inputs: |
---|
1211 | * ------ |
---|
1212 | * event = find the context of this X event |
---|
1213 | * |
---|
1214 | * pCD = client data (maybe NULL) that the event is associated with |
---|
1215 | * |
---|
1216 | * |
---|
1217 | * Outputs: |
---|
1218 | * ------- |
---|
1219 | * pContext = event context |
---|
1220 | * |
---|
1221 | * pPartContext = part (e.g, frame) context associated with the event |
---|
1222 | * |
---|
1223 | *************************************<->***********************************/ |
---|
1224 | |
---|
1225 | #ifdef _NO_PROTO |
---|
1226 | void IdentifyEventContext (event, pCD, pContext, pPartContext) |
---|
1227 | XButtonEvent *event; |
---|
1228 | ClientData *pCD; |
---|
1229 | Context *pContext; |
---|
1230 | int *pPartContext; |
---|
1231 | |
---|
1232 | #else /* _NO_PROTO */ |
---|
1233 | void IdentifyEventContext (XButtonEvent *event, ClientData *pCD, Context *pContext, int *pPartContext) |
---|
1234 | #endif /* _NO_PROTO */ |
---|
1235 | { |
---|
1236 | Boolean eventOnRoot; |
---|
1237 | Window actionWindow; |
---|
1238 | int clientX; |
---|
1239 | int clientY; |
---|
1240 | int framePart; |
---|
1241 | |
---|
1242 | |
---|
1243 | eventOnRoot = (event->window == ACTIVE_ROOT) ? |
---|
1244 | True : False; |
---|
1245 | |
---|
1246 | if (pCD) |
---|
1247 | { |
---|
1248 | actionWindow = (eventOnRoot) ? event->subwindow : event->window; |
---|
1249 | if (actionWindow == pCD->clientFrameWin) |
---|
1250 | { |
---|
1251 | *pContext = F_CONTEXT_WINDOW; |
---|
1252 | |
---|
1253 | if (eventOnRoot) |
---|
1254 | { |
---|
1255 | clientX = event->x - |
---|
1256 | (pCD->maxConfig ? pCD->maxX : pCD->clientX) + |
---|
1257 | pCD->clientOffset.x; |
---|
1258 | clientY = event->y - |
---|
1259 | (pCD->maxConfig ? pCD->maxY : pCD->clientY) + |
---|
1260 | pCD->clientOffset.y; |
---|
1261 | } |
---|
1262 | else |
---|
1263 | { |
---|
1264 | clientX = event->x; |
---|
1265 | clientY = event->y; |
---|
1266 | } |
---|
1267 | framePart = IdentifyFramePart (pCD, clientX, clientY); |
---|
1268 | *pPartContext = framePart; |
---|
1269 | } |
---|
1270 | else if (actionWindow == pCD->clientBaseWin) |
---|
1271 | { |
---|
1272 | *pContext = F_CONTEXT_WINDOW; |
---|
1273 | *pPartContext = FRAME_CLIENT; |
---|
1274 | } |
---|
1275 | else if ((actionWindow == ICON_FRAME_WIN(pCD)) || |
---|
1276 | (actionWindow == ACTIVE_PSD->activeIconTextWin)) |
---|
1277 | { |
---|
1278 | if (P_ICON_BOX(pCD)) |
---|
1279 | { |
---|
1280 | *pContext = F_CONTEXT_ICONBOX; |
---|
1281 | if (pCD->clientState == MINIMIZED_STATE) |
---|
1282 | { |
---|
1283 | *pPartContext = ICONBOX_PART_IICON; |
---|
1284 | } |
---|
1285 | else |
---|
1286 | { |
---|
1287 | *pPartContext = ICONBOX_PART_WICON; |
---|
1288 | } |
---|
1289 | } |
---|
1290 | else |
---|
1291 | { |
---|
1292 | *pContext = F_CONTEXT_ICON; |
---|
1293 | *pPartContext = ICON_PART_ALL; |
---|
1294 | } |
---|
1295 | } |
---|
1296 | else |
---|
1297 | { |
---|
1298 | *pContext = F_CONTEXT_ROOT; |
---|
1299 | *pPartContext = ROOT_PART_ALL; |
---|
1300 | } |
---|
1301 | |
---|
1302 | /* |
---|
1303 | * Check for an incompatible context and window state. |
---|
1304 | */ |
---|
1305 | |
---|
1306 | if (((*pContext & F_CONTEXT_WINDOW) && |
---|
1307 | (pCD->clientState != NORMAL_STATE) && |
---|
1308 | (pCD->clientState != MAXIMIZED_STATE)) || |
---|
1309 | ((*pContext & F_CONTEXT_ICON) && |
---|
1310 | (pCD->clientState != MINIMIZED_STATE))) |
---|
1311 | { |
---|
1312 | *pContext = F_CONTEXT_NONE; |
---|
1313 | } |
---|
1314 | } |
---|
1315 | else |
---|
1316 | { |
---|
1317 | *pContext = F_CONTEXT_ROOT; |
---|
1318 | *pPartContext = ROOT_PART_ALL; |
---|
1319 | } |
---|
1320 | |
---|
1321 | |
---|
1322 | } /* END OF FUNCTION IdentifyEventContext */ |
---|
1323 | |
---|
1324 | |
---|
1325 | |
---|
1326 | /*************************************<->************************************* |
---|
1327 | * |
---|
1328 | * ProcessClickBPress (buttonEvent, pCD, context, subContext) |
---|
1329 | * |
---|
1330 | * |
---|
1331 | * Description: |
---|
1332 | * ----------- |
---|
1333 | * This function checks for a double-click match and saves state information |
---|
1334 | * to do click and double-click processing. |
---|
1335 | * |
---|
1336 | * |
---|
1337 | * Inputs: |
---|
1338 | * ------ |
---|
1339 | * buttonEvent = pointer to a button press event |
---|
1340 | * |
---|
1341 | * pCD = pointer to client data (identifies client window) |
---|
1342 | * |
---|
1343 | * context = root/window/icon context for the event |
---|
1344 | * |
---|
1345 | * subContext = subcontext for the event (title, system button, etc.) |
---|
1346 | * |
---|
1347 | * |
---|
1348 | * Outputs: |
---|
1349 | * ------- |
---|
1350 | * (wmGD.clickData) = click processing information |
---|
1351 | * |
---|
1352 | * (wmGD.clickData.doubleClickContext) = set if double click occured |
---|
1353 | * |
---|
1354 | *************************************<->***********************************/ |
---|
1355 | |
---|
1356 | #ifdef _NO_PROTO |
---|
1357 | void ProcessClickBPress (buttonEvent, pCD, context, subContext) |
---|
1358 | XButtonEvent *buttonEvent; |
---|
1359 | ClientData *pCD; |
---|
1360 | Context context; |
---|
1361 | Context subContext; |
---|
1362 | |
---|
1363 | #else /* _NO_PROTO */ |
---|
1364 | void ProcessClickBPress (XButtonEvent *buttonEvent, ClientData *pCD, Context context, Context subContext) |
---|
1365 | #endif /* _NO_PROTO */ |
---|
1366 | { |
---|
1367 | Time timeDiff; |
---|
1368 | Boolean passButton; |
---|
1369 | |
---|
1370 | |
---|
1371 | /* |
---|
1372 | * Check for a double-click. If a double click has occurred then |
---|
1373 | * save the double-click context. |
---|
1374 | */ |
---|
1375 | |
---|
1376 | wmGD.clickData.doubleClickContext = F_SUBCONTEXT_NONE; |
---|
1377 | if (wmGD.clickData.doubleClickPending && |
---|
1378 | (buttonEvent->button == wmGD.clickData.button) && |
---|
1379 | (buttonEvent->state == wmGD.clickData.state) && |
---|
1380 | (pCD == wmGD.clickData.pCD) && |
---|
1381 | (context == wmGD.clickData.context)) |
---|
1382 | { |
---|
1383 | /* |
---|
1384 | * Check the time between button release events. |
---|
1385 | */ |
---|
1386 | |
---|
1387 | if (buttonEvent->time > wmGD.clickData.time) |
---|
1388 | { |
---|
1389 | timeDiff = buttonEvent->time - wmGD.clickData.time; |
---|
1390 | } |
---|
1391 | else |
---|
1392 | { |
---|
1393 | timeDiff = ~wmGD.clickData.time + buttonEvent->time + 1; |
---|
1394 | } |
---|
1395 | |
---|
1396 | if (timeDiff < wmGD.doubleClickTime) |
---|
1397 | { |
---|
1398 | /* |
---|
1399 | * A double-click has been done; save the context. |
---|
1400 | */ |
---|
1401 | |
---|
1402 | wmGD.clickData.doubleClickContext = subContext | |
---|
1403 | wmGD.clickData.subContext; |
---|
1404 | } |
---|
1405 | } |
---|
1406 | |
---|
1407 | |
---|
1408 | /* |
---|
1409 | * Save state data for click checking. If a button binding match |
---|
1410 | * occurs for a double-click then clear out the clickData (don't |
---|
1411 | * do any click/double-click matches for the following button press |
---|
1412 | * and release). If the button press is done on the client area and |
---|
1413 | * is used to set the focus to the window then don't use it in |
---|
1414 | * setting up clickData. |
---|
1415 | */ |
---|
1416 | |
---|
1417 | if ((buttonEvent->button == SELECT_BUTTON) && (buttonEvent->state == 0)) |
---|
1418 | { |
---|
1419 | passButton = wmGD.passSelectButton; |
---|
1420 | } |
---|
1421 | else |
---|
1422 | { |
---|
1423 | passButton = wmGD.passButtons; |
---|
1424 | } |
---|
1425 | |
---|
1426 | if (!(pCD && (buttonEvent->window == pCD->clientBaseWin) && passButton)) |
---|
1427 | { |
---|
1428 | wmGD.clickData.button = buttonEvent->button; |
---|
1429 | wmGD.clickData.state = buttonEvent->state; |
---|
1430 | /* add in event button mask (this will show up in the button release */ |
---|
1431 | wmGD.clickData.releaseState = buttonEvent->state | |
---|
1432 | buttonModifierMasks[buttonEvent->button]; |
---|
1433 | wmGD.clickData.pCD = pCD; |
---|
1434 | wmGD.clickData.context = context; |
---|
1435 | wmGD.clickData.subContext = subContext; |
---|
1436 | wmGD.clickData.time = buttonEvent->time; |
---|
1437 | wmGD.clickData.clickPending = True; |
---|
1438 | wmGD.clickData.doubleClickPending = True; |
---|
1439 | } |
---|
1440 | |
---|
1441 | |
---|
1442 | } /* END OF FUNCTION ProcessClickBPress */ |
---|
1443 | |
---|
1444 | |
---|
1445 | |
---|
1446 | /*************************************<->************************************* |
---|
1447 | * |
---|
1448 | * ProcessClickBRelease (buttonEvent, pCD, context, subContext) |
---|
1449 | * |
---|
1450 | * |
---|
1451 | * Description: |
---|
1452 | * ----------- |
---|
1453 | * This function checks to see if a "click" was done. The button release |
---|
1454 | * completes a click if there is a click pending and the button release |
---|
1455 | * context is the same as the button press context. Configuration or |
---|
1456 | * menu activity cancels a pending click. |
---|
1457 | * |
---|
1458 | * |
---|
1459 | * Inputs: |
---|
1460 | * ------ |
---|
1461 | * buttonEvent = pointer to a button press event |
---|
1462 | * |
---|
1463 | * pCD = pointer to client data (identifies client window) |
---|
1464 | * |
---|
1465 | * context = root/window/icon context for the event |
---|
1466 | * |
---|
1467 | * subContext = window subcontext for the event (title, system button, etc.) |
---|
1468 | * |
---|
1469 | * (wmGD.clickData) = click processing information |
---|
1470 | * |
---|
1471 | * |
---|
1472 | * Outputs: |
---|
1473 | * ------- |
---|
1474 | * (wmGD.clickData) = click processing information |
---|
1475 | * |
---|
1476 | * (wmGD.clickData.clickContext) = set if click occured |
---|
1477 | * |
---|
1478 | *************************************<->***********************************/ |
---|
1479 | |
---|
1480 | #ifdef _NO_PROTO |
---|
1481 | void ProcessClickBRelease (buttonEvent, pCD, context, subContext) |
---|
1482 | XButtonEvent *buttonEvent; |
---|
1483 | ClientData *pCD; |
---|
1484 | Context context; |
---|
1485 | Context subContext; |
---|
1486 | |
---|
1487 | #else /* _NO_PROTO */ |
---|
1488 | void ProcessClickBRelease (XButtonEvent *buttonEvent, ClientData *pCD, Context context, Context subContext) |
---|
1489 | #endif /* _NO_PROTO */ |
---|
1490 | { |
---|
1491 | |
---|
1492 | /* |
---|
1493 | * Restore the state of the last "depressed" frame gadget |
---|
1494 | */ |
---|
1495 | |
---|
1496 | if (pCD && (wmGD.gadgetClient == pCD) && (pCD->decorFlags)) |
---|
1497 | { |
---|
1498 | PopGadgetOut(pCD, wmGD.gadgetDepressed); |
---|
1499 | } |
---|
1500 | |
---|
1501 | |
---|
1502 | /* |
---|
1503 | * Check to see if a click has been done. |
---|
1504 | */ |
---|
1505 | |
---|
1506 | wmGD.clickData.clickContext = F_SUBCONTEXT_NONE; |
---|
1507 | if (wmGD.clickData.clickPending && |
---|
1508 | (buttonEvent->button == wmGD.clickData.button) && |
---|
1509 | (buttonEvent->state == wmGD.clickData.releaseState) && |
---|
1510 | (pCD == wmGD.clickData.pCD) && |
---|
1511 | (context == wmGD.clickData.context)) |
---|
1512 | { |
---|
1513 | wmGD.clickData.clickContext = subContext | wmGD.clickData.subContext; |
---|
1514 | /* !!! check for double click time? !!! */ |
---|
1515 | } |
---|
1516 | else |
---|
1517 | { |
---|
1518 | wmGD.clickData.doubleClickPending = False; |
---|
1519 | } |
---|
1520 | |
---|
1521 | wmGD.clickData.clickPending = False; |
---|
1522 | |
---|
1523 | |
---|
1524 | } /* END OF FUNCTION ProcessClickBRelease */ |
---|
1525 | |
---|
1526 | |
---|
1527 | |
---|
1528 | /*************************************<->************************************* |
---|
1529 | * |
---|
1530 | * HandleWsEnterNotify (enterEvent) |
---|
1531 | * |
---|
1532 | * |
---|
1533 | * Description: |
---|
1534 | * ----------- |
---|
1535 | * This function processes EnterNotify events that are reported to |
---|
1536 | * the root window. |
---|
1537 | * |
---|
1538 | * |
---|
1539 | * Inputs: |
---|
1540 | * ------ |
---|
1541 | * enterEvent = pointer to an enter notify event on the root window. |
---|
1542 | * |
---|
1543 | *************************************<->***********************************/ |
---|
1544 | |
---|
1545 | #ifdef _NO_PROTO |
---|
1546 | void HandleWsEnterNotify (enterEvent) |
---|
1547 | XEnterWindowEvent *enterEvent; |
---|
1548 | |
---|
1549 | #else /* _NO_PROTO */ |
---|
1550 | void HandleWsEnterNotify (XEnterWindowEvent *enterEvent) |
---|
1551 | #endif /* _NO_PROTO */ |
---|
1552 | { |
---|
1553 | WmScreenData *pSD; |
---|
1554 | |
---|
1555 | /* |
---|
1556 | * If the pointer entered a screen that we manage, then set the |
---|
1557 | * new active screen. |
---|
1558 | */ |
---|
1559 | if (wmGD.queryScreen && |
---|
1560 | (!XFindContext (DISPLAY, enterEvent->window, wmGD.screenContextType, |
---|
1561 | (XPointer *)&pSD))) |
---|
1562 | { |
---|
1563 | SetActiveScreen (pSD); |
---|
1564 | } |
---|
1565 | |
---|
1566 | /* |
---|
1567 | * The root window was entered; do focus processing |
---|
1568 | * if necessary: |
---|
1569 | */ |
---|
1570 | |
---|
1571 | |
---|
1572 | if (!wmGD.menuActive && |
---|
1573 | ((enterEvent->mode == NotifyNormal) || |
---|
1574 | (enterEvent->mode == NotifyUngrab) || |
---|
1575 | (enterEvent->mode == NotifyWhileGrabbed))) |
---|
1576 | { |
---|
1577 | if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) |
---|
1578 | { |
---|
1579 | Do_Focus_Key ((ClientData *) NULL, enterEvent->time, |
---|
1580 | ALWAYS_SET_FOCUS); |
---|
1581 | } |
---|
1582 | else if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) && |
---|
1583 | ((enterEvent->detail == NotifyNonlinearVirtual) || |
---|
1584 | (enterEvent->detail == NotifyNonlinear)) && |
---|
1585 | (wmGD.keyboardFocus == NULL) && |
---|
1586 | enterEvent->focus) |
---|
1587 | { |
---|
1588 | /* |
---|
1589 | * Reset the explicit selection focus to the workspace |
---|
1590 | * window. |
---|
1591 | */ |
---|
1592 | |
---|
1593 | Do_Focus_Key ((ClientData *) NULL, CurrentTime, |
---|
1594 | ALWAYS_SET_FOCUS); |
---|
1595 | } |
---|
1596 | |
---|
1597 | if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER) |
---|
1598 | { |
---|
1599 | SetColormapFocus (ACTIVE_PSD, (ClientData *) NULL); |
---|
1600 | } |
---|
1601 | } |
---|
1602 | |
---|
1603 | } /* END OF FUNCTION HandleWsEnterNotify */ |
---|
1604 | |
---|
1605 | |
---|
1606 | |
---|
1607 | /*************************************<->************************************* |
---|
1608 | * |
---|
1609 | * HandleWsLeaveNotify (leaveEvent) |
---|
1610 | * |
---|
1611 | * |
---|
1612 | * Description: |
---|
1613 | * ----------- |
---|
1614 | * This function processes LeaveNotify events that are reported to |
---|
1615 | * the root window. |
---|
1616 | * |
---|
1617 | * |
---|
1618 | * Inputs: |
---|
1619 | * ------ |
---|
1620 | * enterEvent = pointer to an leave notify event on the root window. |
---|
1621 | * |
---|
1622 | *************************************<->***********************************/ |
---|
1623 | |
---|
1624 | #ifdef _NO_PROTO |
---|
1625 | void HandleWsLeaveNotify (leaveEvent) |
---|
1626 | XLeaveWindowEvent *leaveEvent; |
---|
1627 | |
---|
1628 | #else /* _NO_PROTO */ |
---|
1629 | void HandleWsLeaveNotify (XLeaveWindowEvent *leaveEvent) |
---|
1630 | #endif /* _NO_PROTO */ |
---|
1631 | { |
---|
1632 | WmScreenData *pSD; |
---|
1633 | |
---|
1634 | /* |
---|
1635 | * The root window was exited; do focus processing |
---|
1636 | * if necessary: |
---|
1637 | */ |
---|
1638 | |
---|
1639 | if (!wmGD.menuActive && |
---|
1640 | ((leaveEvent->detail == NotifyNonlinear) || |
---|
1641 | (leaveEvent->detail == NotifyNonlinearVirtual))) |
---|
1642 | { |
---|
1643 | /* |
---|
1644 | * The pointer has moved to another screen. Fix the |
---|
1645 | * focus on the screen controlled by the window manager. |
---|
1646 | */ |
---|
1647 | |
---|
1648 | if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) || |
---|
1649 | (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)) |
---|
1650 | { |
---|
1651 | if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) |
---|
1652 | { |
---|
1653 | Do_Focus_Key ((ClientData *) NULL, leaveEvent->time, |
---|
1654 | (SCREEN_SWITCH_FOCUS | ALWAYS_SET_FOCUS)); |
---|
1655 | } |
---|
1656 | if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER) |
---|
1657 | { |
---|
1658 | SetColormapFocus (ACTIVE_PSD, (ClientData *) NULL); |
---|
1659 | } |
---|
1660 | } |
---|
1661 | |
---|
1662 | /* Set new active screen */ |
---|
1663 | |
---|
1664 | if (!XFindContext (DISPLAY, leaveEvent->root, wmGD.screenContextType, |
---|
1665 | (XPointer *)&pSD)) |
---|
1666 | { |
---|
1667 | /* moved to another screen we manage! */ |
---|
1668 | SetActiveScreen (pSD); |
---|
1669 | } |
---|
1670 | else |
---|
1671 | { |
---|
1672 | /* off onto an unmanaged screen */ |
---|
1673 | wmGD.queryScreen = True; |
---|
1674 | |
---|
1675 | /* set input focus to pointer root */ |
---|
1676 | XSetInputFocus (DISPLAY, PointerRoot, |
---|
1677 | RevertToPointerRoot, leaveEvent->time); |
---|
1678 | } |
---|
1679 | } |
---|
1680 | } /* END OF FUNCTION HandleWsLeaveNotify */ |
---|
1681 | |
---|
1682 | |
---|
1683 | |
---|
1684 | /*************************************<->************************************* |
---|
1685 | * |
---|
1686 | * HandleWsConfigureRequest (focusEvent) |
---|
1687 | * |
---|
1688 | * |
---|
1689 | * Description: |
---|
1690 | * ----------- |
---|
1691 | * This function processes ConfigureRequest events that are reported to |
---|
1692 | * the root window. |
---|
1693 | * |
---|
1694 | * |
---|
1695 | * Inputs: |
---|
1696 | * ------ |
---|
1697 | * focusEvent = pointer to a configure request event on the root window. |
---|
1698 | * |
---|
1699 | *************************************<->***********************************/ |
---|
1700 | |
---|
1701 | #ifdef _NO_PROTO |
---|
1702 | void HandleWsConfigureRequest (configureEvent) |
---|
1703 | XConfigureRequestEvent *configureEvent; |
---|
1704 | |
---|
1705 | #else /* _NO_PROTO */ |
---|
1706 | void HandleWsConfigureRequest (XConfigureRequestEvent *configureEvent) |
---|
1707 | #endif /* _NO_PROTO */ |
---|
1708 | { |
---|
1709 | ClientData *pCD; |
---|
1710 | XConfigureEvent notifyEvent; |
---|
1711 | Boolean configChanged; |
---|
1712 | XWindowChanges values; |
---|
1713 | |
---|
1714 | |
---|
1715 | /* |
---|
1716 | * A window that is a child of the root window is being |
---|
1717 | * configured. Either it is an un-managed window or it is a |
---|
1718 | * managed window that did the configuration before it was |
---|
1719 | * reparented. |
---|
1720 | */ |
---|
1721 | |
---|
1722 | if (XFindContext (DISPLAY, configureEvent->window, wmGD.windowContextType, |
---|
1723 | (XPointer *)&pCD)) |
---|
1724 | { |
---|
1725 | /* |
---|
1726 | * Get window attribute information; this is used later on |
---|
1727 | * to decide if a synthetic ConfigureNotify event should |
---|
1728 | * be send to the client. |
---|
1729 | */ |
---|
1730 | |
---|
1731 | if (WmGetWindowAttributes (configureEvent->window)) |
---|
1732 | { |
---|
1733 | configChanged = |
---|
1734 | (wmGD.windowAttributes.x != configureEvent->x) || |
---|
1735 | (wmGD.windowAttributes.y != configureEvent->y) || |
---|
1736 | (wmGD.windowAttributes.width != configureEvent->width) || |
---|
1737 | (wmGD.windowAttributes.height != configureEvent->height) || |
---|
1738 | (wmGD.windowAttributes.border_width != |
---|
1739 | configureEvent->border_width) || |
---|
1740 | (configureEvent->value_mask & (CWSibling|CWStackMode)); |
---|
1741 | |
---|
1742 | /* |
---|
1743 | * The window is not (yet) managed. Do the window |
---|
1744 | * configuration. |
---|
1745 | */ |
---|
1746 | |
---|
1747 | if (configChanged) |
---|
1748 | { |
---|
1749 | values.x = configureEvent->x; |
---|
1750 | values.y = configureEvent->y; |
---|
1751 | values.width = configureEvent->width; |
---|
1752 | values.height = configureEvent->height; |
---|
1753 | values.border_width = configureEvent->border_width; |
---|
1754 | values.sibling = configureEvent->above; |
---|
1755 | values.stack_mode = configureEvent->detail; |
---|
1756 | XConfigureWindow (DISPLAY, configureEvent->window, |
---|
1757 | (unsigned int) (configureEvent->value_mask), &values); |
---|
1758 | } |
---|
1759 | |
---|
1760 | /* |
---|
1761 | * Some clients expect a ConfigureNotify event even if the |
---|
1762 | * XConfigureWindow call has NO effect. Send a synthetic |
---|
1763 | * ConfigureNotify event just to be sure. |
---|
1764 | */ |
---|
1765 | |
---|
1766 | if (!configChanged) |
---|
1767 | { |
---|
1768 | notifyEvent.type = ConfigureNotify; |
---|
1769 | notifyEvent.display = DISPLAY; |
---|
1770 | notifyEvent.event = configureEvent->window; |
---|
1771 | notifyEvent.window = configureEvent->window; |
---|
1772 | notifyEvent.x = configureEvent->x; |
---|
1773 | notifyEvent.y = configureEvent->y; |
---|
1774 | notifyEvent.width = configureEvent->width; |
---|
1775 | notifyEvent.height = configureEvent->height; |
---|
1776 | notifyEvent.border_width = configureEvent->border_width; |
---|
1777 | notifyEvent.above = None; |
---|
1778 | notifyEvent.override_redirect = False; |
---|
1779 | |
---|
1780 | XSendEvent (DISPLAY, configureEvent->window, False, |
---|
1781 | StructureNotifyMask, (XEvent *)¬ifyEvent); |
---|
1782 | } |
---|
1783 | } |
---|
1784 | } |
---|
1785 | else |
---|
1786 | { |
---|
1787 | /* |
---|
1788 | * The context information on the window WAS found. |
---|
1789 | * The window is already managed by the window manager |
---|
1790 | * so this is a configuration request that was made before |
---|
1791 | * the window was reparented. |
---|
1792 | */ |
---|
1793 | |
---|
1794 | HandleCConfigureRequest (pCD, configureEvent); |
---|
1795 | } |
---|
1796 | |
---|
1797 | } /* END OF FUNCTION HandleWsConfigureRequest */ |
---|
1798 | |
---|
1799 | |
---|
1800 | |
---|
1801 | /*************************************<->************************************* |
---|
1802 | * |
---|
1803 | * HandleWsFocusIn (focusEvent) |
---|
1804 | * |
---|
1805 | * |
---|
1806 | * Description: |
---|
1807 | * ----------- |
---|
1808 | * This function processes FocusIn events that are reported to the root |
---|
1809 | * window. |
---|
1810 | * |
---|
1811 | * |
---|
1812 | * Inputs: |
---|
1813 | * ------ |
---|
1814 | * focusEvent = pointer to a focus in event on the root window. |
---|
1815 | * |
---|
1816 | *************************************<->***********************************/ |
---|
1817 | |
---|
1818 | #ifdef _NO_PROTO |
---|
1819 | void HandleWsFocusIn (focusEvent) |
---|
1820 | XFocusInEvent *focusEvent; |
---|
1821 | |
---|
1822 | #else /* _NO_PROTO */ |
---|
1823 | void HandleWsFocusIn (XFocusInEvent *focusEvent) |
---|
1824 | #endif /* _NO_PROTO */ |
---|
1825 | { |
---|
1826 | ClientData *pCD; |
---|
1827 | Boolean sameScreen; |
---|
1828 | |
---|
1829 | /* |
---|
1830 | * This code is used to handle the case of the focus being |
---|
1831 | * set to pointer root (either explicitly by some client, by the window |
---|
1832 | * manager or as a result of a "revert to" action). |
---|
1833 | * It also handles the case where the focus is manipulated by a window |
---|
1834 | * manager on another screen (in this case let the other window manager |
---|
1835 | * control the focus). Reset the focus to a client window if appropriate. |
---|
1836 | */ |
---|
1837 | |
---|
1838 | if (((focusEvent->mode == NotifyNormal) || |
---|
1839 | (focusEvent->mode == NotifyUngrab)) && |
---|
1840 | ((focusEvent->detail == NotifyPointerRoot) || |
---|
1841 | (focusEvent->detail == NotifyDetailNone) || |
---|
1842 | (focusEvent->detail == NotifyInferior))) |
---|
1843 | { |
---|
1844 | /* |
---|
1845 | * Fix the keyboard focus if it should be set to a particular client. |
---|
1846 | */ |
---|
1847 | |
---|
1848 | pCD = GetClientUnderPointer (&sameScreen); |
---|
1849 | if (wmGD.keyboardFocus && (focusEvent->detail != NotifyInferior)) |
---|
1850 | { |
---|
1851 | if (sameScreen) |
---|
1852 | { |
---|
1853 | /* |
---|
1854 | * Assume that the focus still belongs to the screen |
---|
1855 | * controlled by mwm. Repair the focus if the client |
---|
1856 | * is still active. |
---|
1857 | */ |
---|
1858 | |
---|
1859 | if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) |
---|
1860 | { |
---|
1861 | Do_Focus_Key (wmGD.keyboardFocus, GetTimestamp (), |
---|
1862 | ALWAYS_SET_FOCUS); |
---|
1863 | } |
---|
1864 | else |
---|
1865 | { |
---|
1866 | if (pCD || (focusEvent->detail == NotifyDetailNone)) |
---|
1867 | { |
---|
1868 | /* !!! check for redundant focus setting !!! */ |
---|
1869 | Do_Focus_Key (pCD, GetTimestamp (), ALWAYS_SET_FOCUS); |
---|
1870 | } |
---|
1871 | } |
---|
1872 | SetKeyboardFocus ((ClientData *) NULL, REFRESH_LAST_FOCUS); |
---|
1873 | } |
---|
1874 | else |
---|
1875 | { |
---|
1876 | /* |
---|
1877 | * Assume that the focus is now controlled by a |
---|
1878 | * window manager on another screen. Clear the |
---|
1879 | * focus locally. |
---|
1880 | */ |
---|
1881 | |
---|
1882 | SetKeyboardFocus ((ClientData *) NULL, REFRESH_LAST_FOCUS); |
---|
1883 | } |
---|
1884 | } |
---|
1885 | else |
---|
1886 | { |
---|
1887 | /* |
---|
1888 | * No client window currently has the focus. If the pointer |
---|
1889 | * is on the mwm-controlled screen set the focus to |
---|
1890 | * the window management window if the focus is explicit. |
---|
1891 | */ |
---|
1892 | |
---|
1893 | if (sameScreen) |
---|
1894 | { |
---|
1895 | if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) |
---|
1896 | { |
---|
1897 | if ((focusEvent->detail == NotifyInferior) && |
---|
1898 | (wmGD.keyboardFocus != wmGD.nextKeyboardFocus)) |
---|
1899 | { |
---|
1900 | /* |
---|
1901 | * Window that had the focus went away. Try to |
---|
1902 | * reset the window to the next keyboard focus |
---|
1903 | * client window if there is one. |
---|
1904 | */ |
---|
1905 | |
---|
1906 | Do_Focus_Key (wmGD.nextKeyboardFocus, GetTimestamp (), |
---|
1907 | ALWAYS_SET_FOCUS); |
---|
1908 | } |
---|
1909 | else |
---|
1910 | { |
---|
1911 | /* Re: CR 4896 */ |
---|
1912 | /* The previous version would pass NULL widget to this */ |
---|
1913 | /* this routine. This doesn't seem to make sense. NULL */ |
---|
1914 | /* has been replaced by pCD which seems to fix the icon */ |
---|
1915 | /* focus problem. */ |
---|
1916 | /* Another related patch is made in WmCEvent.c. */ |
---|
1917 | Do_Focus_Key ((ClientData *) pCD, CurrentTime, |
---|
1918 | ALWAYS_SET_FOCUS); |
---|
1919 | } |
---|
1920 | } |
---|
1921 | else /*KEYBOARD_FOCUS_POINTER*/ |
---|
1922 | { |
---|
1923 | if (pCD || focusEvent->detail != NotifyPointerRoot) |
---|
1924 | { |
---|
1925 | Do_Focus_Key (pCD, GetTimestamp (), ALWAYS_SET_FOCUS); |
---|
1926 | } |
---|
1927 | } |
---|
1928 | } |
---|
1929 | } |
---|
1930 | } |
---|
1931 | |
---|
1932 | } /* END OF FUNCTION HandleWsFocusIn */ |
---|
1933 | |
---|
1934 | |
---|
1935 | |
---|
1936 | /*************************************<->************************************* |
---|
1937 | * |
---|
1938 | * GetTimestamp () |
---|
1939 | * |
---|
1940 | * |
---|
1941 | * Description: |
---|
1942 | * ----------- |
---|
1943 | * This function is used to provide a timestamp for use with X calls that |
---|
1944 | * require a timestamp (and a timestamp is not available from a prior |
---|
1945 | * X event). |
---|
1946 | * |
---|
1947 | * |
---|
1948 | * Outputs: |
---|
1949 | * ------- |
---|
1950 | * Return = a timestamp value |
---|
1951 | * |
---|
1952 | *************************************<->***********************************/ |
---|
1953 | |
---|
1954 | #ifdef _NO_PROTO |
---|
1955 | Time GetTimestamp () |
---|
1956 | |
---|
1957 | #else /* _NO_PROTO */ |
---|
1958 | Time GetTimestamp (void) |
---|
1959 | #endif /* _NO_PROTO */ |
---|
1960 | { |
---|
1961 | /* |
---|
1962 | * !!! get a timestamp ... !!! |
---|
1963 | * !!! do a 0-len append to some wm property and get the event from !!! |
---|
1964 | * !!! the property notify !!! |
---|
1965 | */ |
---|
1966 | |
---|
1967 | return (CurrentTime); |
---|
1968 | |
---|
1969 | } /* END OF FUNCTION GetTimestamp */ |
---|
1970 | |
---|
1971 | |
---|
1972 | |
---|
1973 | /*************************************<->************************************* |
---|
1974 | * |
---|
1975 | * PullExposureEvents () |
---|
1976 | * |
---|
1977 | * |
---|
1978 | * Description: |
---|
1979 | * ----------- |
---|
1980 | * Pull in and process all outstanding exposure events |
---|
1981 | * |
---|
1982 | * |
---|
1983 | * Inputs: |
---|
1984 | * ------ |
---|
1985 | * |
---|
1986 | * Outputs: |
---|
1987 | * ------- |
---|
1988 | * |
---|
1989 | * Comments: |
---|
1990 | * -------- |
---|
1991 | * Useful for cleaning up display after menu popdown |
---|
1992 | * |
---|
1993 | *************************************<->***********************************/ |
---|
1994 | #ifdef _NO_PROTO |
---|
1995 | void PullExposureEvents () |
---|
1996 | #else /* _NO_PROTO */ |
---|
1997 | void PullExposureEvents (void) |
---|
1998 | #endif /* _NO_PROTO */ |
---|
1999 | { |
---|
2000 | XEvent event; |
---|
2001 | Boolean dispatchEvent; |
---|
2002 | |
---|
2003 | /* |
---|
2004 | * Force the exposure events into the queue |
---|
2005 | */ |
---|
2006 | XSync (DISPLAY, False); |
---|
2007 | |
---|
2008 | /* |
---|
2009 | * Selectively extract the exposure events |
---|
2010 | */ |
---|
2011 | while (XCheckMaskEvent (DISPLAY, ExposureMask, &event)) |
---|
2012 | { |
---|
2013 | /* |
---|
2014 | * Check for, and process non-widget events. The events may be |
---|
2015 | * reported to the root window, to some client frame window, |
---|
2016 | * to an icon window, or to a "special" window management window. |
---|
2017 | */ |
---|
2018 | |
---|
2019 | if (event.xany.window == ACTIVE_ROOT) |
---|
2020 | { |
---|
2021 | dispatchEvent = WmDispatchWsEvent (&event); |
---|
2022 | } |
---|
2023 | else |
---|
2024 | { |
---|
2025 | dispatchEvent = WmDispatchClientEvent (&event); |
---|
2026 | } |
---|
2027 | |
---|
2028 | if (dispatchEvent) |
---|
2029 | { |
---|
2030 | /* |
---|
2031 | * Dispatch widget related event: |
---|
2032 | */ |
---|
2033 | |
---|
2034 | XtDispatchEvent (&event); |
---|
2035 | } |
---|
2036 | } |
---|
2037 | |
---|
2038 | } /* END OF FUNCTION PullExposureEvents */ |
---|
2039 | |
---|