WmEvent.c 67 KB

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