WmCEvent.c 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789
  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 HEWLETT-PACKARD COMPANY */
  32. /*
  33. * Included Files:
  34. */
  35. #include "WmGlobal.h"
  36. #include "WmICCC.h"
  37. #include <X11/Xatom.h>
  38. /*
  39. * include extern functions
  40. */
  41. #include "WmCEvent.h"
  42. #include "WmCDecor.h"
  43. #include "WmCDInfo.h"
  44. #include "WmColormap.h"
  45. #include "WmEvent.h"
  46. #include "WmEwmh.h"
  47. #include "WmFeedback.h"
  48. #include "WmFunction.h"
  49. #include "WmIDecor.h"
  50. #include "WmKeyFocus.h"
  51. #include "WmPanelP.h"
  52. #include "WmManage.h"
  53. #include "WmMenu.h"
  54. #include "WmProperty.h"
  55. #include "WmProtocol.h"
  56. #include "WmWinConf.h"
  57. #include "WmWinInfo.h"
  58. #include "WmWinList.h"
  59. #include "WmWinState.h"
  60. #include "WmWrkspace.h"
  61. /*
  62. * Global Variables:
  63. */
  64. extern unsigned int buttonModifierMasks[];
  65. static void AcceptPrematureClientMessage (XClientMessageEvent *clientEvent)
  66. {
  67. XChangeProperty (DISPLAY, clientEvent->window,
  68. wmGD.xa_PREMATURE_XCLIENTMESSAGEEVENT_LIST,
  69. wmGD.xa_PREMATURE_XCLIENTMESSAGEEVENT_LIST, 8,
  70. PropModeAppend, (unsigned char *) clientEvent,
  71. sizeof(XClientMessageEvent));
  72. }
  73. /*************************************<->*************************************
  74. *
  75. * SetupCButtonBindings (window, buttonSpecs)
  76. *
  77. *
  78. * Description:
  79. * -----------
  80. * This function sets up the event handling necessary to support user
  81. * specified button bindings for window manager functions that apply to
  82. * the client window.
  83. *
  84. *
  85. * Inputs:
  86. * ------
  87. * window = grab window id
  88. *
  89. * buttonSpecs = list of button bindings for window manager functions
  90. *
  91. *************************************<->***********************************/
  92. void SetupCButtonBindings (Window window, ButtonSpec *buttonSpecs)
  93. {
  94. ButtonSpec *buttonSpec;
  95. unsigned int eventMask;
  96. unsigned int grabState;
  97. /*
  98. * If the context of the button binding includes "window" do button
  99. * grabs to get the button events that invoke window manger functions.
  100. * !!! don't do redundant grabs !!!
  101. */
  102. buttonSpec = buttonSpecs;
  103. while (buttonSpec)
  104. {
  105. if ((buttonSpec->context & F_CONTEXT_WINDOW) &&
  106. (buttonSpec->subContext & F_SUBCONTEXT_W_CLIENT))
  107. {
  108. eventMask = ButtonMotionMask | ButtonReleaseMask;
  109. if (buttonSpec->eventType == ButtonRelease)
  110. {
  111. /*
  112. * Don't include the button down in the grab state.
  113. */
  114. grabState = buttonSpec->state &
  115. ~(buttonModifierMasks[buttonSpec->button]);
  116. }
  117. else
  118. {
  119. grabState = buttonSpec->state;
  120. }
  121. WmGrabButton (DISPLAY, buttonSpec->button, grabState,
  122. window, False, eventMask, GrabModeSync,
  123. GrabModeAsync, None, None);
  124. }
  125. /*
  126. * If the window context is not "window" a general grab is not
  127. * necessary.
  128. */
  129. buttonSpec = buttonSpec->nextButtonSpec;
  130. }
  131. } /* END OF FUNCTION SetupCButtonBindings */
  132. /*************************************<->*************************************
  133. *
  134. * WmDispatchClientEvent (event)
  135. *
  136. *
  137. * Description:
  138. * -----------
  139. * This function detects and dispatches events that are reported to a client
  140. * frame or icon window that are not widget-related (i.e. they would not be
  141. * dispatched by the Xtk intrinsics).
  142. *
  143. *
  144. * Inputs:
  145. * ------
  146. * event = This is an X event that has been retrieved by XtNextEvent.
  147. *
  148. *
  149. * Outputs:
  150. * -------
  151. * RETURN = If True the event should be dispatched by the toolkit,
  152. * otherwise the event should not be dispatched.
  153. *
  154. *************************************<->***********************************/
  155. Boolean WmDispatchClientEvent (XEvent *event)
  156. {
  157. ClientData * pCD = NULL;
  158. #ifndef IBM_169380
  159. ClientData **cmap_window_data = NULL;
  160. #endif
  161. Boolean dispatchEvent = False;
  162. /*
  163. * Detect and dispatch non-widget events that have been reported to
  164. * an icon or a client window frame.
  165. */
  166. #ifndef IBM_169380
  167. if ((XFindContext (DISPLAY, event->xany.window, wmGD.windowContextType,
  168. (caddr_t *)&pCD)) &&
  169. (XFindContext (DISPLAY, event->xany.window, wmGD.cmapWindowContextType,
  170. (caddr_t *)&cmap_window_data)))
  171. #else
  172. if (XFindContext (DISPLAY, event->xany.window, wmGD.windowContextType,
  173. (caddr_t *)&pCD))
  174. #endif
  175. {
  176. /*
  177. * Set active screen if we're not sure.
  178. */
  179. if (wmGD.queryScreen)
  180. DetermineActiveScreen (event);
  181. /*
  182. * Handle events on windows that are made by mwm for
  183. * non-client-specific functions. Also handle "leftover"
  184. * events on windows that used to be managed by mwm
  185. * (e.g. ConfigureRequest events).
  186. */
  187. return (HandleEventsOnSpecialWindows (event));
  188. }
  189. #ifndef IBM_169380
  190. if (cmap_window_data)
  191. /*
  192. * Event is on a subwindow that is specified in one or more toplevel
  193. * window's WM_COLORMAP_WINDOWS property. (Most likely this is a
  194. * ColormapNotify event.) It could have more than one pCD associated
  195. * with it, so we have to choose one. If one of the pCD's currently has
  196. * the Colormap Focus, then let's use that one. Otherwise, just use
  197. * the 1st one.
  198. */
  199. {
  200. int j;
  201. for (j = 0; cmap_window_data[j]; j++)
  202. {
  203. if (ACTIVE_PSD->colormapFocus == cmap_window_data[j])
  204. {
  205. pCD = cmap_window_data[j];
  206. break;
  207. }
  208. }
  209. /*
  210. * None of the pCD's in the list have Colormap Focus. So, just
  211. * set pCD to the 1st one in the list.
  212. */
  213. if (!pCD)
  214. pCD = cmap_window_data[0];
  215. }
  216. #endif
  217. /*
  218. * Set active screen if this is not a FocusOut event.
  219. * We don't need to set it on focus out AND we use
  220. * (SCREEN_FOR_CLIENT(pCD) != ACTIVE_SCREEN) in
  221. * in HandleCFocusOut to determine if a new colormap needs
  222. * to be installed.
  223. */
  224. if (!(event->type == FocusOut))
  225. {
  226. SetActiveScreen (PSD_FOR_CLIENT(pCD));
  227. }
  228. /* Get workspace specific client data */
  229. SetClientWsIndex (pCD);
  230. /*
  231. * Handle events on top-level client windows.
  232. */
  233. if (event->xany.window == pCD->client)
  234. {
  235. return (HandleEventsOnClientWindow (pCD, event));
  236. }
  237. /*
  238. * Handle events on windows created by mwm (for icons and client window
  239. * frames) and on non-top-level client windows (e.g., colormap
  240. * windows).
  241. */
  242. switch (event->type)
  243. {
  244. case ButtonPress:
  245. {
  246. dispatchEvent = HandleCButtonPress (pCD, (XButtonEvent *)event);
  247. break;
  248. }
  249. case ButtonRelease:
  250. {
  251. if (wmGD.menuActive)
  252. {
  253. dispatchEvent = True; /* have the toolkit dispatch the event */
  254. }
  255. else
  256. {
  257. HandleCButtonRelease (pCD, (XButtonEvent *)event);
  258. }
  259. break;
  260. }
  261. case KeyPress:
  262. {
  263. dispatchEvent = HandleCKeyPress (pCD, (XKeyEvent *)event);
  264. break;
  265. }
  266. case MotionNotify:
  267. {
  268. HandleCMotionNotify (pCD, (XMotionEvent *)event);
  269. break;
  270. }
  271. case Expose:
  272. {
  273. /*
  274. * If multiple expose events, wait for last one.
  275. */
  276. if (event->xexpose.count == 0)
  277. {
  278. if (event->xexpose.window == ICON_FRAME_WIN(pCD))
  279. {
  280. IconExposureProc (pCD, True);
  281. if (P_ICON_BOX(pCD))
  282. {
  283. dispatchEvent = True;
  284. }
  285. }
  286. else if (event->xexpose.window ==
  287. pCD->pSD->activeIconTextWin)
  288. {
  289. PaintActiveIconText (pCD, FALSE);
  290. }
  291. else if (!(pCD->clientFlags & CLIENT_DESTROYED))
  292. {
  293. if ((event->xexpose.window == pCD->clientFrameWin) ||
  294. (event->xexpose.window == pCD->clientTitleWin))
  295. {
  296. FrameExposureProc (pCD);
  297. }
  298. if (event->xexpose.window == pCD->clientBaseWin)
  299. {
  300. BaseWinExposureProc (pCD);
  301. }
  302. }
  303. else if (pCD->clientFlags & FRONT_PANEL_BOX)
  304. {
  305. /*
  306. *
  307. * Then this client is the shell for the
  308. * front panel and we want the toolkit to repaint
  309. * it.
  310. *
  311. */
  312. dispatchEvent = True;
  313. }
  314. }
  315. break;
  316. }
  317. case EnterNotify:
  318. {
  319. HandleCEnterNotify (pCD, (XEnterWindowEvent *)event);
  320. break;
  321. }
  322. case LeaveNotify:
  323. {
  324. HandleCLeaveNotify (pCD, (XLeaveWindowEvent *)event);
  325. break;
  326. }
  327. case FocusIn:
  328. {
  329. dispatchEvent = HandleCFocusIn (pCD, (XFocusChangeEvent *)event);
  330. break;
  331. }
  332. case FocusOut:
  333. {
  334. dispatchEvent = HandleCFocusOut (pCD, (XFocusChangeEvent *)event);
  335. break;
  336. }
  337. case DestroyNotify:
  338. {
  339. if (((XDestroyWindowEvent *)event)->window == pCD->client)
  340. {
  341. pCD->clientFlags |= CLIENT_DESTROYED;
  342. UnManageWindow (pCD);
  343. }
  344. break;
  345. }
  346. case UnmapNotify:
  347. {
  348. /*
  349. * This event is generated when a managed client window is
  350. * unmapped by the client or when the window manager unmaps the
  351. * client window; check the wmMapCount to determine if this is
  352. * the result of a window manager unmap. If this is a client
  353. * unmap then the window is to be withdrawn from window manager
  354. * control.
  355. */
  356. if (((XUnmapEvent *)event)->window == pCD->client)
  357. {
  358. if (pCD->wmUnmapCount)
  359. {
  360. pCD->wmUnmapCount--;
  361. }
  362. else
  363. {
  364. UnManageWindow (pCD);
  365. }
  366. }
  367. break;
  368. }
  369. case MapRequest:
  370. {
  371. /*
  372. * This is a request to change the state of the client window from
  373. * iconic (minimized) to normal.
  374. */
  375. if (!ClientInWorkspace (ACTIVE_WS, pCD))
  376. {
  377. if (pCD->absentMapBehavior == AMAP_BEHAVIOR_IGNORE)
  378. {
  379. SetClientState (pCD, NORMAL_STATE|UNSEEN_STATE,
  380. GetTimestamp ());
  381. }
  382. else
  383. {
  384. HonorAbsentMapBehavior(pCD);
  385. SetClientState (pCD, NORMAL_STATE, GetTimestamp ());
  386. }
  387. }
  388. else
  389. {
  390. SetClientState (pCD, NORMAL_STATE, GetTimestamp ());
  391. }
  392. break;
  393. }
  394. case ConfigureRequest:
  395. {
  396. HandleCConfigureRequest (pCD, (XConfigureRequestEvent *)event);
  397. break;
  398. }
  399. case ColormapNotify:
  400. {
  401. /*
  402. * Process changes to client window colormaps:
  403. */
  404. HandleCColormapNotify (pCD, (XColormapEvent *)event);
  405. break;
  406. }
  407. case ClientMessage:
  408. {
  409. /*
  410. * Handle client message events.
  411. */
  412. HandleClientMessage (pCD, (XClientMessageEvent *)event);
  413. break;
  414. }
  415. case ReparentNotify:
  416. {
  417. if ((((XReparentEvent *)event)->window == pCD->client) &&
  418. (((XReparentEvent *)event)->parent != pCD->clientBaseWin))
  419. {
  420. /*
  421. * The window was reparented away from the frame.
  422. * Unmanage to clean up the now empty frame.
  423. *
  424. * Note: We get here when the reparent is done while
  425. * the client is unmapped (e.g. iconified). Otherwise
  426. * the reparent will generate an UnmapNotify which
  427. * will also cause us to unmanage the client.
  428. */
  429. UnManageWindow (pCD);
  430. }
  431. break;
  432. }
  433. } /* end of event.type switch */
  434. return (dispatchEvent);
  435. } /* END OF FUNCTION WmDispatchClientEvent */
  436. /*************************************<->*************************************
  437. *
  438. * HandleEventsOnSpecialWindows (pEvent)
  439. *
  440. *
  441. * Description:
  442. * -----------
  443. * Handles events on special window manager windows and "leftover" events
  444. * from destroyed client window frames.
  445. *
  446. *
  447. * Inputs:
  448. * ------
  449. * pEvent = pointer to an XEvent structure
  450. *
  451. *
  452. * Outputs:
  453. * -------
  454. * RETURN = If True the event should be dispatched by the toolkit,
  455. * otherwise the event should not be dispatched.
  456. *
  457. *************************************<->***********************************/
  458. Boolean HandleEventsOnSpecialWindows (XEvent *pEvent)
  459. {
  460. Boolean dispatchEvent = True;
  461. WmScreenData *pSD;
  462. /*
  463. * The window is not a root window or a client frame window. Check for
  464. * a special window manager window. Have the toolkit dispatch the event
  465. * if the event is not on a special window.
  466. */
  467. if (pEvent->xany.window == ACTIVE_ROOT)
  468. {
  469. if (pEvent->type == FocusIn)
  470. {
  471. SetKeyboardFocus ((ClientData *) NULL, REFRESH_LAST_FOCUS);
  472. }
  473. }
  474. else if (pEvent->xany.window == ACTIVE_PSD->feedbackWin)
  475. {
  476. if (pEvent->type == Expose)
  477. {
  478. if (pEvent->xexpose.count == 0)
  479. {
  480. PaintFeedbackWindow(ACTIVE_PSD);
  481. }
  482. }
  483. dispatchEvent = False; /* don't have the toolkit dispatch the event */
  484. }
  485. else if (pEvent->xany.window == ACTIVE_PSD->inputScreenWindow)
  486. {
  487. if (pEvent->type == ButtonPress)
  488. {
  489. F_Beep (NULL, (ClientData *) NULL, (XEvent *) NULL);
  490. }
  491. else if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) &&
  492. (pEvent->type == EnterNotify))
  493. {
  494. HandleWsEnterNotify ((XEnterWindowEvent *)pEvent);
  495. }
  496. dispatchEvent = False; /* don't have the toolkit dispatch the event */
  497. }
  498. else if (!XFindContext (DISPLAY, pEvent->xany.window,
  499. wmGD.mwmWindowContextType, (caddr_t *)&pSD))
  500. {
  501. if ((pEvent->type == PropertyNotify) &&
  502. (pEvent->xproperty.atom == wmGD.xa_DT_WM_REQUEST) &&
  503. (pEvent->xproperty.state == PropertyNewValue))
  504. {
  505. HandleDtWmRequest (pSD, pEvent);
  506. }
  507. if (pEvent->type == ClientMessage)
  508. {
  509. HandleDtWmClientMessage ((XClientMessageEvent *)pEvent);
  510. }
  511. }
  512. else
  513. {
  514. /*
  515. * Events may come in for a client frame base window that no
  516. * longer exists (the client window was just unmanaged but the
  517. * the client did some action before the un-reparenting was
  518. * actually done). Confirm that this is the case and then
  519. * handle the request as if it came in as a root window event.
  520. */
  521. switch (pEvent->type)
  522. {
  523. case ConfigureRequest:
  524. {
  525. if (GetParentWindow (pEvent->xconfigurerequest.window) ==
  526. ACTIVE_ROOT)
  527. {
  528. /*
  529. * This is an event for a client base window that
  530. * no longer exists. Handle the event as if it is a
  531. * root window event.
  532. */
  533. dispatchEvent = WmDispatchWsEvent (pEvent);
  534. }
  535. break;
  536. }
  537. case MapRequest:
  538. {
  539. if (GetParentWindow (pEvent->xmaprequest.window) ==
  540. ACTIVE_ROOT)
  541. {
  542. /*
  543. * This is an event for a client base window that
  544. * no longer exists. Handle the event as if it is a
  545. * root window event.
  546. */
  547. dispatchEvent = WmDispatchWsEvent (pEvent);
  548. }
  549. break;
  550. }
  551. case ClientMessage:
  552. {
  553. AcceptPrematureClientMessage ((XClientMessageEvent *)pEvent);
  554. break;
  555. }
  556. }
  557. }
  558. return (dispatchEvent);
  559. } /* END OF FUNCTION HandleEventsOnSpecialWindows */
  560. /*************************************<->*************************************
  561. *
  562. * HandleEventsOnClientWindow (pCD, pEvent)
  563. *
  564. *
  565. * Description:
  566. * -----------
  567. * Handles events on a client top-level window.
  568. *
  569. *
  570. * Inputs:
  571. * ------
  572. * pCD = pointer to client data
  573. *
  574. * pEvent = pointer to an XEvent structure
  575. *
  576. *
  577. * Outputs:
  578. * -------
  579. * RETURN = If True the event should be dispatched by the toolkit,
  580. * otherwise the event should not be dispatched.
  581. *
  582. *************************************<->***********************************/
  583. Boolean HandleEventsOnClientWindow (ClientData *pCD, XEvent *pEvent)
  584. {
  585. Boolean doXtDispatchEvent = True;
  586. if (pEvent->type == (wmGD.shapeEventBase+ShapeNotify))
  587. {
  588. HandleCShapeNotify (pCD, (XShapeEvent *)pEvent);
  589. }
  590. else
  591. switch (pEvent->type)
  592. {
  593. case ColormapNotify:
  594. {
  595. /*
  596. * Process changes to top-level client window colormaps:
  597. */
  598. HandleCColormapNotify (pCD, (XColormapEvent *)pEvent);
  599. doXtDispatchEvent = False;
  600. break;
  601. }
  602. case PropertyNotify:
  603. {
  604. /*
  605. * Process property changes on managed client windows:
  606. */
  607. HandleCPropertyNotify (pCD, (XPropertyEvent *)pEvent);
  608. doXtDispatchEvent = False;
  609. break;
  610. }
  611. case ClientMessage:
  612. {
  613. /*
  614. * Handle client message events.
  615. */
  616. HandleClientMessage (pCD, (XClientMessageEvent *)pEvent);
  617. break;
  618. }
  619. }
  620. return (doXtDispatchEvent);
  621. } /* END OF FUNCTION HandleEventsOnClientWindow */
  622. /*************************************<->*************************************
  623. *
  624. * HandleCPropertyNotify (pCD, propertyEvent)
  625. *
  626. *
  627. * Description:
  628. * -----------
  629. * This function handles propertyNotify events (indicating window property
  630. * changes) that are reported to the client window.
  631. *
  632. *
  633. * Inputs:
  634. * ------
  635. * pCD = pointer to the client data for the client window that got the event
  636. *
  637. * propertyEvent = propertyNotify event that was received
  638. *
  639. *************************************<->***********************************/
  640. void HandleCPropertyNotify (ClientData *pCD, XPropertyEvent *propertyEvent)
  641. {
  642. switch (propertyEvent->atom)
  643. {
  644. case XA_WM_HINTS:
  645. {
  646. ProcessWmHints (pCD, FALSE /*not first time*/);
  647. break;
  648. }
  649. case XA_WM_NORMAL_HINTS:
  650. {
  651. ProcessWmNormalHints (pCD, FALSE /*not first time*/, 0);
  652. break;
  653. }
  654. case XA_WM_CLASS:
  655. {
  656. break;
  657. }
  658. case XA_WM_COMMAND:
  659. {
  660. if (pCD->clientFlags & CLIENT_TERMINATING)
  661. {
  662. DeleteClientWmTimers (pCD);
  663. XKillClient (DISPLAY, pCD->client);
  664. }
  665. break;
  666. }
  667. case XA_WM_TRANSIENT_FOR:
  668. {
  669. /*
  670. * here we handle the special case of dialogs that are
  671. * mapped before the windows they are transient for are
  672. * mapped. Xm handles this case by waiting for the
  673. * transient_for window to appear before setting the
  674. * WM_TRANSIENT_FOR property on the dialog. Mwm has to
  675. * notice this property change and re-organize things
  676. * so the dialog is treated as a transient window.
  677. *
  678. * Note that we also handle the case of the WM_TRANSIENT_FOR
  679. * property being removed.
  680. */
  681. DeleteClientFromList (pCD->pSD->pActiveWS, pCD);
  682. ProcessWmTransientFor(pCD);
  683. AddClientToList(pCD->pSD->pActiveWS, pCD, True);
  684. if (pCD->transientLeader != NULL)
  685. StackTransientWindow(pCD);
  686. break;
  687. }
  688. default:
  689. {
  690. if (propertyEvent->atom == wmGD.xa_WM_PROTOCOLS)
  691. {
  692. ProcessWmProtocols (pCD);
  693. }
  694. else if (propertyEvent->atom == wmGD.xa_DT_WORKSPACE_HINTS)
  695. {
  696. (void) ProcessWorkspaceHints (pCD);
  697. }
  698. else if (propertyEvent->atom == wmGD.xa_MWM_MESSAGES)
  699. {
  700. if (pCD->protocolFlags & PROTOCOL_MWM_MESSAGES)
  701. {
  702. ProcessMwmMessages (pCD);
  703. }
  704. }
  705. else if (propertyEvent->atom == wmGD.xa_SM_CLIENT_ID)
  706. {
  707. ProcessSmClientID(pCD);
  708. }
  709. else if (propertyEvent->atom == wmGD.xa_WMSAVE_HINT)
  710. {
  711. ProcessWmSaveHint(pCD);
  712. }
  713. else if (propertyEvent->atom == wmGD.xa_WM_COLORMAP_WINDOWS)
  714. {
  715. if (propertyEvent->state == PropertyNewValue)
  716. {
  717. ProcessWmColormapWindows (pCD);
  718. }
  719. else
  720. {
  721. /* property was deleted */
  722. ResetColormapData (pCD, NULL, 0);
  723. }
  724. if ((ACTIVE_PSD->colormapFocus == pCD) &&
  725. ((pCD->clientState == NORMAL_STATE) ||
  726. (pCD->clientState == MAXIMIZED_STATE)))
  727. {
  728. /*
  729. * The client window has the colormap focus, install the
  730. * colormap.
  731. */
  732. /*
  733. * We just changed the colormaps list,
  734. * so we need to re-run the whole thing.
  735. */
  736. pCD->clientCmapFlagsInitialized = 0;
  737. ProcessColormapList (ACTIVE_PSD, pCD);
  738. }
  739. }
  740. else if (propertyEvent->atom == wmGD.xa_MWM_HINTS)
  741. {
  742. long suppliedReturn;
  743. XSizeHints hintsReturn = {0};
  744. XGetWMNormalHints (DISPLAY, pCD->client, &hintsReturn,
  745. &suppliedReturn);
  746. hintsReturn.flags |= P_MAX_SIZE;
  747. hintsReturn.max_width = -1;
  748. hintsReturn.max_height = -1;
  749. XSetWMNormalHints (DISPLAY, pCD->client, &hintsReturn);
  750. ProcessMwmHints (pCD);
  751. SetClientOffset (pCD);
  752. }
  753. else if (propertyEvent->atom == XA_WM_NAME ||
  754. propertyEvent->atom == wmGD.xa__NET_WM_NAME)
  755. {
  756. ProcessWmWindowTitle (pCD, FALSE /*not first time*/);
  757. }
  758. else if (propertyEvent->atom == XA_WM_ICON_NAME ||
  759. propertyEvent->atom == wmGD.xa__NET_WM_ICON_NAME)
  760. {
  761. ProcessWmIconTitle (pCD, FALSE /*not first time*/);
  762. }
  763. break;
  764. }
  765. }
  766. } /* END OF FUNCTION HandleCPropertyNotify */
  767. /*************************************<->*************************************
  768. *
  769. * HandleCButtonPress (pCD, buttonEvent)
  770. *
  771. *
  772. * Description:
  773. * -----------
  774. * This function does window management actions associated with a button
  775. * press event on the client window (including frame) or icon.
  776. *
  777. *
  778. * Inputs:
  779. * ------
  780. * pCD = pointer to client data (identifies client window)
  781. *
  782. * buttonEvent = ButtonPress event on client window
  783. *
  784. *
  785. * Outputs:
  786. * -------
  787. * RETURN = True if the event should be dispatched by XtDispatchEvent
  788. *
  789. *************************************<->***********************************/
  790. Boolean HandleCButtonPress (ClientData *pCD, XButtonEvent *buttonEvent)
  791. {
  792. Boolean dispatchEvent = False;
  793. Boolean replayEvent = True;
  794. Context context;
  795. int partContext;
  796. Context subContext;
  797. static Time baseWinTime = 0;
  798. static unsigned int baseWinButton = 0;
  799. wmGD.passButtonsCheck = True;
  800. /*
  801. * Find out the event context and process the event accordingly.
  802. * If the event is due to a key focus selection grab or an application
  803. * modal grab then handle the grab (only these types of grabs are
  804. * done on the client window frame base window)..
  805. */
  806. if (wmGD.menuActive)
  807. {
  808. dispatchEvent = True; /* have the toolkit dispatch the event */
  809. }
  810. else
  811. {
  812. IdentifyEventContext (buttonEvent, pCD, &context, &partContext);
  813. subContext = (1L << partContext);
  814. if (buttonEvent->window == pCD->clientBaseWin)
  815. {
  816. /* save time of event caught by base window grab */
  817. baseWinTime = buttonEvent->time;
  818. baseWinButton = buttonEvent->button;
  819. }
  820. /*
  821. * If this event was caught by the base window grab and
  822. * replayed, then don't reprocess if caught by the frame
  823. * window. (Replayed events have the same time.)
  824. */
  825. if (!((buttonEvent->window == pCD->clientFrameWin) &&
  826. (buttonEvent->button == baseWinButton) &&
  827. (buttonEvent->time == baseWinTime)))
  828. {
  829. /*
  830. * Motif 1.2, ignore replayed events UNPOST_AND_REPLAY events
  831. * generated from the menu system (time stamps are exactly
  832. * the same for the replayed event)
  833. */
  834. if (wmGD.clickData.time == buttonEvent->time)
  835. {
  836. dispatchEvent = False;
  837. }
  838. else
  839. {
  840. ProcessClickBPress (buttonEvent, pCD, context, subContext);
  841. }
  842. if (CheckForButtonAction (buttonEvent, context, subContext, pCD))
  843. {
  844. /*
  845. * Button bindings have been processed, now check for bindings
  846. * that associated with the built-in semantics of the window
  847. * frame decorations.
  848. */
  849. CheckButtonPressBuiltin (buttonEvent, context, subContext,
  850. partContext, pCD);
  851. /*
  852. * For case where button action causes lower, but
  853. * builtin causes focus - disable auto raise until
  854. * we receive focusIn or focusOut.
  855. */
  856. pCD->focusAutoRaiseDisablePending = False;
  857. }
  858. else
  859. {
  860. /*
  861. * Else skip built-in processing due to execution of a function
  862. * that does on-going event processing or that has changed the
  863. * client state (e.g., f.move or f.minimize).
  864. */
  865. replayEvent = False;
  866. }
  867. }
  868. }
  869. if (buttonEvent->window == pCD->clientBaseWin)
  870. {
  871. ProcessButtonGrabOnClient (pCD, buttonEvent, replayEvent);
  872. }
  873. return (dispatchEvent);
  874. } /* END OF FUNCTION HandleCButtonPress */
  875. /*************************************<->*************************************
  876. *
  877. * ProcessButtonGrabOnClient (pCD, buttonEvent, replayEvent)
  878. *
  879. *
  880. * Description:
  881. * -----------
  882. * This function handles an activated button grab on the client window
  883. * frame base window.
  884. *
  885. *
  886. * Inputs:
  887. * ------
  888. * pCD = pointer to client data of window associated with the grab
  889. *
  890. * buttonEvent = ButtonPress event on client window
  891. *
  892. * replayEvent = True if event should be replayed
  893. *
  894. *************************************<->***********************************/
  895. void ProcessButtonGrabOnClient (ClientData *pCD, XButtonEvent *buttonEvent, Boolean replayEvent)
  896. {
  897. ButtonSpec *buttonSpec;
  898. Boolean passButton;
  899. if ((buttonEvent->button == SELECT_BUTTON) &&
  900. ((buttonEvent->state == 0) ||
  901. (NOLOCKMOD(buttonEvent->state) == 0)))
  902. {
  903. passButton = wmGD.passSelectButton;
  904. }
  905. else
  906. {
  907. passButton = wmGD.passButtons;
  908. }
  909. if (IS_APP_MODALIZED(pCD) || !passButton)
  910. {
  911. replayEvent = False;
  912. }
  913. else if (replayEvent)
  914. {
  915. /*
  916. * Replay the event as long as there is not another button binding
  917. * for the button release.
  918. */
  919. buttonSpec = ACTIVE_PSD->buttonSpecs;
  920. while (buttonSpec)
  921. {
  922. if ((buttonSpec->eventType == ButtonRelease) &&
  923. ((buttonEvent->state == buttonSpec->state) ||
  924. (NOLOCKMOD(buttonEvent->state) == buttonSpec->state)) &&
  925. (buttonEvent->button == buttonSpec->button))
  926. {
  927. replayEvent = False;
  928. break;
  929. }
  930. buttonSpec = buttonSpec->nextButtonSpec;
  931. }
  932. }
  933. if (replayEvent && wmGD.passButtonsCheck)
  934. {
  935. XAllowEvents (DISPLAY, ReplayPointer, CurrentTime);
  936. }
  937. else
  938. {
  939. if (IS_APP_MODALIZED(pCD))
  940. {
  941. /*
  942. * The grab is done on a window that has an application modal
  943. * secondary window. Beep to indicate no client processing of
  944. * the event.
  945. */
  946. F_Beep (NULL, pCD, (XEvent *) NULL);
  947. }
  948. XAllowEvents (DISPLAY, AsyncPointer, CurrentTime);
  949. }
  950. XAllowEvents (DISPLAY, AsyncKeyboard, CurrentTime);
  951. } /* END OF FUNCTION ProcessButtonGrabOnClient */
  952. /*************************************<->*************************************
  953. *
  954. * CheckButtonPressBuiltin (buttonEvent, context, subContext, partContext, pCD)
  955. *
  956. *
  957. * Description:
  958. * -----------
  959. * This function checks to see if a built-in window manager function
  960. * has been selected. If yes, then the function is done.
  961. *
  962. *
  963. * Inputs:
  964. * ------
  965. * buttonEvent = pointer to button event
  966. *
  967. * context = button event context (root, icon, window)
  968. *
  969. * subContext = button event subcontext (title, system button, ...)
  970. *
  971. * partContext = part context within a window manager component
  972. *
  973. *************************************<->***********************************/
  974. void CheckButtonPressBuiltin (XButtonEvent *buttonEvent, Context context, Context subContext, int partContext, ClientData *pCD)
  975. {
  976. /*
  977. * All builtin button bindings are based on button 1 with no
  978. * modifiers. (Ignore locking modifiers)
  979. */
  980. if (((buttonEvent->button != SELECT_BUTTON) &&
  981. (buttonEvent->button != DMANIP_BUTTON)) ||
  982. NOLOCKMOD(buttonEvent->state))
  983. {
  984. return;
  985. }
  986. /*
  987. * Process the builtin button bindings based on the window manager
  988. * component that was selected.
  989. */
  990. if (context & F_CONTEXT_ICON)
  991. {
  992. HandleIconButtonPress (pCD, buttonEvent);
  993. }
  994. else if (context & F_CONTEXT_ICONBOX)
  995. {
  996. HandleIconBoxButtonPress (pCD, buttonEvent, subContext);
  997. }
  998. else if (context & F_CONTEXT_WINDOW)
  999. {
  1000. /*
  1001. * A client window frame component was selected.
  1002. */
  1003. /*
  1004. * If the keyboard focus policy is explicit then all window frame
  1005. * components set the keyboard input focus when selected.
  1006. */
  1007. if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
  1008. {
  1009. /* If we've just done f.lower, disable focusAutoRaise. */
  1010. if (pCD && pCD->focusAutoRaiseDisablePending)
  1011. pCD->focusAutoRaiseDisabled = True;
  1012. Do_Focus_Key (pCD, buttonEvent->time,
  1013. (long)((partContext == FRAME_CLIENT) ? CLIENT_AREA_FOCUS : 0));
  1014. }
  1015. /*
  1016. * Process the builtin button bindings based on the client window
  1017. * frame component that was selected.
  1018. */
  1019. if ((buttonEvent->button == SELECT_BUTTON) &&
  1020. (subContext == F_SUBCONTEXT_W_SYSTEM))
  1021. {
  1022. int flags = 0;
  1023. /*
  1024. * System menu button component:
  1025. * SELECT_BUTTON Press - post the system menu.
  1026. * SELECT_BUTTON double-click - close the window.
  1027. */
  1028. PushGadgetIn (pCD, partContext);
  1029. if ((wmGD.clickData.doubleClickContext == F_SUBCONTEXT_W_SYSTEM) &&
  1030. wmGD.systemButtonClick2 &&
  1031. (pCD->clientFunctions & MWM_FUNC_CLOSE))
  1032. {
  1033. /*
  1034. * Close the client window. Don't do any of the other
  1035. * system menu button actions.
  1036. */
  1037. wmGD.clickData.clickPending = False;
  1038. wmGD.clickData.doubleClickPending = False;
  1039. F_Kill (NULL, pCD, (XEvent *) buttonEvent);
  1040. return;
  1041. }
  1042. if (pCD->clientState == NORMAL_STATE)
  1043. {
  1044. context = F_CONTEXT_NORMAL;
  1045. }
  1046. else if (pCD->clientState == MAXIMIZED_STATE)
  1047. {
  1048. context = F_CONTEXT_MAXIMIZE;
  1049. }
  1050. else
  1051. {
  1052. context = F_CONTEXT_ICON;
  1053. }
  1054. /*
  1055. * Set up for "sticky" menu processing if specified.
  1056. */
  1057. if (wmGD.systemButtonClick)
  1058. {
  1059. wmGD.checkHotspot = True;
  1060. flags |= POST_STICKY;
  1061. }
  1062. pCD->grabContext = context;
  1063. PostMenu (pCD->systemMenuSpec, pCD, 0, 0, SELECT_BUTTON,
  1064. context, flags, (XEvent *)buttonEvent);
  1065. }
  1066. else if (subContext == F_SUBCONTEXT_W_TITLE)
  1067. {
  1068. /*
  1069. * Title component:
  1070. * SELECT_BUTTON or DMANIP_BUTTON Press -
  1071. * start looking for a move.
  1072. */
  1073. PushGadgetIn (pCD, partContext);
  1074. /*
  1075. * Fix for 5075 - Check to make sure that MWM_FUNC_MOVE is set in the
  1076. * clientFunctions. This is necessary because the title
  1077. * bar is added based on a number of decorations even if
  1078. * the resources or the user has specifically requested
  1079. * that "move" not be one of them.
  1080. */
  1081. if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
  1082. {
  1083. wmGD.preMove = True;
  1084. wmGD.preMoveX = buttonEvent->x_root;
  1085. wmGD.preMoveY = buttonEvent->y_root;
  1086. wmGD.configButton = buttonEvent->button;
  1087. wmGD.configAction = MOVE_CLIENT;
  1088. }
  1089. /*
  1090. * End fix 5075
  1091. */
  1092. }
  1093. else if (subContext & F_SUBCONTEXT_W_RBORDER)
  1094. {
  1095. /*
  1096. * Resize border handle components:
  1097. * SELECT_BUTTON or DMANIP_BUTTON Press -
  1098. * start looking for a resize.
  1099. */
  1100. wmGD.preMove = True;
  1101. wmGD.preMoveX = buttonEvent->x_root;
  1102. wmGD.preMoveY = buttonEvent->y_root;
  1103. wmGD.configButton = buttonEvent->button;
  1104. wmGD.configAction = RESIZE_CLIENT;
  1105. wmGD.configPart = partContext;
  1106. wmGD.configSet = True;
  1107. }
  1108. else if ((buttonEvent->button == SELECT_BUTTON) &&
  1109. (subContext & (F_SUBCONTEXT_W_MINIMIZE|F_SUBCONTEXT_W_MAXIMIZE)))
  1110. {
  1111. /*
  1112. * Minimize and maximize button components:
  1113. * SELECT_BUTTON Press - start of a click.
  1114. */
  1115. PushGadgetIn (pCD, partContext);
  1116. }
  1117. /*
  1118. * Other components: no action
  1119. */
  1120. }
  1121. } /* END OF FUNCTION CheckButtonPressBuiltin */
  1122. /*************************************<->*************************************
  1123. *
  1124. * HandleIconButtonPress (pCD, buttonEvent)
  1125. *
  1126. *
  1127. * Description:
  1128. * -----------
  1129. * This function handles builtin functions in the icon context.
  1130. *
  1131. *
  1132. * Inputs:
  1133. * ------
  1134. * pCD = pointer to client data of the icon that received the button event
  1135. *
  1136. * buttonEvent = pointer to the button event that occurred
  1137. *
  1138. *************************************<->***********************************/
  1139. void HandleIconButtonPress (ClientData *pCD, XButtonEvent *buttonEvent)
  1140. {
  1141. int newState;
  1142. /*
  1143. * Do icon component button press actions:
  1144. * Button 1 press - set the keyboard input focus if policy is explicit
  1145. * Button 1 double-click - normalize the icon
  1146. */
  1147. if (wmGD.clickData.doubleClickContext == F_SUBCONTEXT_I_ALL)
  1148. {
  1149. /*
  1150. * A double-click was done, normalize the icon.
  1151. */
  1152. if (pCD->maxConfig)
  1153. {
  1154. newState = MAXIMIZED_STATE;
  1155. }
  1156. else
  1157. {
  1158. newState = NORMAL_STATE;
  1159. }
  1160. SetClientState (pCD, newState, buttonEvent->time);
  1161. wmGD.clickData.clickPending = False;
  1162. wmGD.clickData.doubleClickPending = False;
  1163. }
  1164. else
  1165. {
  1166. /*
  1167. * This is a regular button press (it may be the start of a
  1168. * double-click). Set the focus and top the icon if appropriate.
  1169. */
  1170. if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
  1171. {
  1172. Do_Focus_Key (pCD, buttonEvent->time, ALWAYS_SET_FOCUS);
  1173. }
  1174. /*
  1175. * Indicate that a move may be starting; wait for button motion
  1176. * events before moving the icon.
  1177. */
  1178. wmGD.preMove = True;
  1179. wmGD.preMoveX = buttonEvent->x_root;
  1180. wmGD.preMoveY = buttonEvent->y_root;
  1181. wmGD.configButton = buttonEvent->button;
  1182. wmGD.configAction = MOVE_CLIENT;
  1183. }
  1184. } /* END OF FUNCTION HandleIconButtonPress */
  1185. /*************************************<->*************************************
  1186. *
  1187. * HandleIconBoxButtonPress (pCD, buttonEvent, subContext)
  1188. *
  1189. *
  1190. * Description:
  1191. * -----------
  1192. * This function handles builtin functions in the iconbox context.
  1193. *
  1194. *
  1195. * Inputs:
  1196. * ------
  1197. * pCD = pointer to client data of the icon that received the button event
  1198. *
  1199. * buttonEvent = pointer to the button event that occurred
  1200. *
  1201. * subContext = context id of event location inside icon box
  1202. *
  1203. *************************************<->***********************************/
  1204. void HandleIconBoxButtonPress (ClientData *pCD, XButtonEvent *buttonEvent, Context subContext)
  1205. {
  1206. /*
  1207. * Do iconbox icon component button press actions:
  1208. * Button 1 press - select the icon
  1209. * Button 1 double-click - normalize the icon or raise the window
  1210. */
  1211. if ((wmGD.clickData.doubleClickContext == F_SUBCONTEXT_IB_IICON) ||
  1212. (wmGD.clickData.doubleClickContext == F_SUBCONTEXT_IB_WICON))
  1213. {
  1214. F_Restore_And_Raise ((String)NULL, pCD, (XEvent *)NULL);
  1215. }
  1216. else if ((subContext == F_SUBCONTEXT_IB_IICON) ||
  1217. (subContext == F_SUBCONTEXT_IB_WICON))
  1218. {
  1219. /*
  1220. * Indicate that a move may be starting; wait for button motion
  1221. * events before moving the icon.
  1222. */
  1223. wmGD.preMove = True;
  1224. wmGD.preMoveX = buttonEvent->x_root;
  1225. wmGD.preMoveY = buttonEvent->y_root;
  1226. wmGD.configButton = buttonEvent->button;
  1227. wmGD.configAction = MOVE_CLIENT;
  1228. }
  1229. /*
  1230. * Do icon box icon actions:
  1231. * Button 1 press - select the icon in the icon box
  1232. */
  1233. /*
  1234. * XmProcessTraversal will move the selection cursor to the
  1235. * widget that was "boinked" with the mouse
  1236. */
  1237. if ((P_ICON_BOX(pCD)->pCD_iconBox == wmGD.keyboardFocus) ||
  1238. (P_ICON_BOX(pCD)->pCD_iconBox == wmGD.nextKeyboardFocus))
  1239. {
  1240. XmProcessTraversal (XtWindowToWidget(DISPLAY, ICON_FRAME_WIN(pCD)),
  1241. XmTRAVERSE_CURRENT);
  1242. }
  1243. } /* END OF FUNCTION HandleIconBoxButtonPress */
  1244. /*************************************<->*************************************
  1245. *
  1246. * HandleCButtonRelease (pCD, buttonEvent)
  1247. *
  1248. *
  1249. * Description:
  1250. * -----------
  1251. * This function does window management actions associated with a button
  1252. * release event on the client window (including frame) or icon.
  1253. *
  1254. *
  1255. * Inputs:
  1256. * ------
  1257. * pCD = pointer to client data for the window/icon that got the event
  1258. *
  1259. * buttonEvent = pointer to the button event that occurred
  1260. *
  1261. * Comments:
  1262. * ---------
  1263. * Skip builtin processing if move or resize button actions were started
  1264. * due to button-up bindings.
  1265. *
  1266. *************************************<->***********************************/
  1267. void HandleCButtonRelease (ClientData *pCD, XButtonEvent *buttonEvent)
  1268. {
  1269. Context context;
  1270. Context subContext;
  1271. int partContext;
  1272. /*
  1273. * Find out whether the event was on the client window frame or the icon
  1274. * and process the event accordingly.
  1275. */
  1276. IdentifyEventContext (buttonEvent, pCD, &context, &partContext);
  1277. subContext = (1L << partContext);
  1278. ProcessClickBRelease (buttonEvent, pCD, context, subContext);
  1279. if (CheckForButtonAction (buttonEvent, context, subContext, pCD) && pCD)
  1280. {
  1281. /*
  1282. * Button bindings have been processed, now check for bindings
  1283. * that associated with the built-in semantics of the window
  1284. * frame decorations.
  1285. */
  1286. CheckButtonReleaseBuiltin (buttonEvent, context, subContext, pCD);
  1287. }
  1288. /*
  1289. * Else skip built-in processing due to execution of a function that
  1290. * does on-going event processing or that has changed the client state
  1291. * (e.g., f.move or f.minimize).
  1292. */
  1293. /* clear preMove state */
  1294. wmGD.preMove = False;
  1295. } /* END OF FUNCTION HandleCButtonRelease */
  1296. /*************************************<->*************************************
  1297. *
  1298. * HandleCKeyPress (pCD, keyEvent)
  1299. *
  1300. *
  1301. * Description:
  1302. * -----------
  1303. * This function does window management actions associated with a key
  1304. * press event on the client window (including frame) or icon.
  1305. *
  1306. *
  1307. * Inputs:
  1308. * ------
  1309. * pCD = pointer to client data for the window/icon that got the event
  1310. *
  1311. * keyEvent = pointer to the key event that occurred
  1312. *
  1313. *
  1314. * Outputs:
  1315. * -------
  1316. * RETURN = True if the event should be dispatched by XtDispatchEvent
  1317. *
  1318. *************************************<->***********************************/
  1319. Boolean HandleCKeyPress (ClientData *pCD, XKeyEvent *keyEvent)
  1320. {
  1321. Boolean dispatchEvent = False;
  1322. Boolean checkKeyEvent = True;
  1323. if (wmGD.menuActive)
  1324. {
  1325. /*
  1326. * The active menu accelerators have been checked and keyEvent was
  1327. * not one of them. We will check for an iconbox icon widget key and
  1328. * for pass keys mode and then have the toolkit dispatch the event,
  1329. * without rechecking the client accelerator list.
  1330. */
  1331. dispatchEvent = True;
  1332. checkKeyEvent = False;
  1333. }
  1334. /*
  1335. * If pass keys is active then only check for getting out of the pass
  1336. * keys mode if the event is on the client frame or icon frame window.
  1337. * Unfreeze the keyboard and replay the key if pass keys is active.
  1338. */
  1339. if (((keyEvent->window == ICON_FRAME_WIN(pCD)) ||
  1340. (keyEvent->window == pCD->pSD->activeIconTextWin)) &&
  1341. P_ICON_BOX(pCD))
  1342. {
  1343. /*
  1344. * This is a non-grabbed key that is intended for the icon widget
  1345. * in the iconbox.
  1346. */
  1347. dispatchEvent = True; /* have the toolkit dispatch the event */
  1348. checkKeyEvent = False;
  1349. if (keyEvent->window == pCD->pSD->activeIconTextWin)
  1350. {
  1351. /*
  1352. * The event is really for the icon, not the active
  1353. * label, so ... correct the window id
  1354. */
  1355. keyEvent->window = ICON_FRAME_WIN(pCD);
  1356. }
  1357. }
  1358. else if (wmGD.passKeysActive)
  1359. {
  1360. if (wmGD.passKeysKeySpec &&
  1361. ((wmGD.passKeysKeySpec->state == keyEvent->state) ||
  1362. (wmGD.passKeysKeySpec->state == NOLOCKMOD(keyEvent->state))) &&
  1363. (wmGD.passKeysKeySpec->keycode == keyEvent->keycode))
  1364. {
  1365. /*
  1366. * Get out of the pass keys mode.
  1367. */
  1368. F_Pass_Key (NULL, (ClientData *) NULL, (XEvent *) NULL);
  1369. XAllowEvents (DISPLAY, AsyncKeyboard, CurrentTime);
  1370. }
  1371. else
  1372. {
  1373. XAllowEvents (DISPLAY, ReplayKeyboard, CurrentTime);
  1374. }
  1375. checkKeyEvent = False;
  1376. }
  1377. else
  1378. {
  1379. XAllowEvents (DISPLAY, AsyncKeyboard, CurrentTime);
  1380. }
  1381. /*
  1382. * Check for a "general" key binding that has been set only for the
  1383. * icon context. These key bindings are set with the keyBinding
  1384. * resource or as accelerators in icon context menus.
  1385. */
  1386. if (checkKeyEvent && (keyEvent->window == ICON_FRAME_WIN(pCD)))
  1387. {
  1388. if ((checkKeyEvent = HandleKeyPress (keyEvent,
  1389. ACTIVE_PSD->keySpecs, True,
  1390. F_CONTEXT_ICON, False,
  1391. (ClientData *)NULL))
  1392. && ACTIVE_PSD->acceleratorMenuCount)
  1393. {
  1394. int n;
  1395. for (n = 0; ((keyEvent->keycode != 0) &&
  1396. (n < ACTIVE_PSD->acceleratorMenuCount)); n++)
  1397. {
  1398. if (!HandleKeyPress (keyEvent,
  1399. ACTIVE_PSD->acceleratorMenuSpecs[n]->accelKeySpecs,
  1400. True, F_CONTEXT_ICON, True,(ClientData *)NULL))
  1401. {
  1402. checkKeyEvent = False;
  1403. break;
  1404. }
  1405. }
  1406. }
  1407. }
  1408. /*
  1409. * Check for a key binding that has been set as an accelerator in the
  1410. * system menu. We only do the first accelerator found.
  1411. */
  1412. if (checkKeyEvent && pCD->systemMenuSpec &&
  1413. (pCD->systemMenuSpec->accelKeySpecs))
  1414. {
  1415. HandleKeyPress (keyEvent, pCD->systemMenuSpec->accelKeySpecs,
  1416. FALSE, 0, TRUE,(ClientData *)NULL );
  1417. }
  1418. return (dispatchEvent);
  1419. } /* END OF FUNCTION HandleCKeyPress */
  1420. /*************************************<->*************************************
  1421. *
  1422. * CheckButtonReleaseBuiltin (buttonEvent, context, subContext, pCD)
  1423. *
  1424. *
  1425. * Description:
  1426. * -----------
  1427. * This function checks to see if a built-in window manager function
  1428. * has been activated as a result of a button release. If yes, then the
  1429. * associated function is done.
  1430. *
  1431. *
  1432. * Inputs:
  1433. * ------
  1434. * buttonEvent = pointer to a button release event
  1435. *
  1436. * context = button event context (root, icon, window)
  1437. *
  1438. * subContext = button event subcontext (title, system button, ...)
  1439. *
  1440. * pCD = pointer to client data for the window/icon that got the event
  1441. *
  1442. *************************************<->***********************************/
  1443. void CheckButtonReleaseBuiltin (XButtonEvent *buttonEvent, Context context, Context subContext, ClientData *pCD)
  1444. {
  1445. /*
  1446. * All builtin button buindings are based on button 1 with no modifiers.
  1447. * (Ignore locking modifiers).
  1448. *
  1449. * Test the event for a ``button up'' transition on buttons we are
  1450. * interested in.
  1451. */
  1452. if (!((buttonEvent->button == SELECT_BUTTON) &&
  1453. (NOLOCKMOD(buttonEvent->state) == SELECT_BUTTON_MASK)) &&
  1454. !((buttonEvent->button == DMANIP_BUTTON) &&
  1455. (NOLOCKMOD(buttonEvent->state) == DMANIP_BUTTON_MASK)))
  1456. {
  1457. return;
  1458. }
  1459. /*
  1460. * Process the builtin button bindings based on the window manager
  1461. * component that was selected.
  1462. */
  1463. if ((buttonEvent->button == SELECT_BUTTON) &&
  1464. (context & F_CONTEXT_ICON))
  1465. {
  1466. /*
  1467. * Do the icon component button release actions:
  1468. * SELECT_BUTTON click - post the system menu if specified.
  1469. */
  1470. if (wmGD.iconClick &&
  1471. (wmGD.clickData.clickContext == F_SUBCONTEXT_I_ALL))
  1472. {
  1473. wmGD.checkHotspot = True;
  1474. /*
  1475. * Post the system menu with traversal on (Button 1 should be
  1476. * used to manipulate the menu).
  1477. */
  1478. pCD->grabContext = F_CONTEXT_ICON;
  1479. PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton,
  1480. F_CONTEXT_ICON, POST_STICKY, (XEvent *)buttonEvent);
  1481. }
  1482. }
  1483. /* post menu from icon in iconbox */
  1484. else if ((buttonEvent->button == SELECT_BUTTON) &&
  1485. (context & F_CONTEXT_ICONBOX))
  1486. {
  1487. if ((wmGD.iconClick) &&
  1488. (((pCD->clientState == MINIMIZED_STATE) &&
  1489. (wmGD.clickData.clickContext == F_SUBCONTEXT_IB_IICON)) ||
  1490. (wmGD.clickData.clickContext == F_SUBCONTEXT_IB_WICON)) )
  1491. {
  1492. wmGD.checkHotspot = True;
  1493. /*
  1494. * Post the system menu with traversal on (Button 1 should be
  1495. * used to manipulate the menu.
  1496. */
  1497. if ((wmGD.clickData.clickContext == F_SUBCONTEXT_IB_IICON) &&
  1498. (pCD->clientState == MINIMIZED_STATE))
  1499. {
  1500. pCD->grabContext = F_SUBCONTEXT_IB_IICON;
  1501. PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton,
  1502. F_SUBCONTEXT_IB_IICON, POST_STICKY, (XEvent *)buttonEvent);
  1503. }
  1504. else
  1505. {
  1506. pCD->grabContext = F_SUBCONTEXT_IB_WICON;
  1507. PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton,
  1508. F_SUBCONTEXT_IB_WICON, POST_STICKY, (XEvent *)buttonEvent);
  1509. }
  1510. }
  1511. }
  1512. /* end of post menu from icon in iconbox */
  1513. else if (context & F_CONTEXT_WINDOW)
  1514. {
  1515. /*
  1516. * The button release is on a client window frame component.
  1517. */
  1518. if ((buttonEvent->button == SELECT_BUTTON) &&
  1519. (subContext == F_SUBCONTEXT_W_MINIMIZE))
  1520. {
  1521. /*
  1522. * Minimize button:
  1523. * Button 1 click - minimize the window.
  1524. */
  1525. if (wmGD.clickData.clickContext == F_SUBCONTEXT_W_MINIMIZE)
  1526. {
  1527. SetClientState (pCD, MINIMIZED_STATE, buttonEvent->time);
  1528. }
  1529. }
  1530. else if ((buttonEvent->button == SELECT_BUTTON) &&
  1531. (subContext == F_SUBCONTEXT_W_MAXIMIZE))
  1532. {
  1533. /*
  1534. * Maximize button:
  1535. * Button 1 click - maximize the window.
  1536. */
  1537. if (wmGD.clickData.clickContext == F_SUBCONTEXT_W_MAXIMIZE)
  1538. {
  1539. if (pCD->clientState == NORMAL_STATE)
  1540. {
  1541. SetClientState (pCD, MAXIMIZED_STATE, buttonEvent->time);
  1542. }
  1543. else
  1544. {
  1545. SetClientState (pCD, NORMAL_STATE, buttonEvent->time);
  1546. }
  1547. }
  1548. }
  1549. }
  1550. /*
  1551. * Clear the pre-configuration info that supports the move threshold.
  1552. */
  1553. wmGD.preMove = False;
  1554. } /* END OF FUNCTION CheckButtonReleaseBuiltin */
  1555. /*************************************<->*************************************
  1556. *
  1557. * HandleCMotionNotify (pCD, motionEvent)
  1558. *
  1559. *
  1560. * Description:
  1561. * -----------
  1562. * This function does window management actions associated with a motion
  1563. * notify event on the client window (including frame) or icon.
  1564. *
  1565. *
  1566. * Inputs:
  1567. * ------
  1568. * pCD = pointer to the client data for the window/icon that got the motion
  1569. *
  1570. * motionEvent = pointer to the motion event
  1571. *
  1572. *************************************<->***********************************/
  1573. void HandleCMotionNotify (ClientData *pCD, XMotionEvent *motionEvent)
  1574. {
  1575. int diffX;
  1576. int diffY;
  1577. /*
  1578. * Do pre-move processing (to support the move threshold) if appropriate:
  1579. */
  1580. if (wmGD.preMove)
  1581. {
  1582. diffX = motionEvent->x_root - wmGD.preMoveX;
  1583. if (diffX < 0) diffX = -diffX;
  1584. diffY = motionEvent->y_root - wmGD.preMoveY;
  1585. if (diffY < 0) diffY = -diffY;
  1586. if ((diffX >= wmGD.moveThreshold) || (diffY >= wmGD.moveThreshold))
  1587. {
  1588. /*
  1589. * The move threshold has been exceeded; start the config action.
  1590. */
  1591. wmGD.clickData.clickPending = False;
  1592. wmGD.clickData.doubleClickPending = False;
  1593. wmGD.preMove = False;
  1594. if (wmGD.configAction == MOVE_CLIENT)
  1595. {
  1596. HandleClientFrameMove (pCD, (XEvent *) motionEvent);
  1597. }
  1598. else if (wmGD.configAction == RESIZE_CLIENT)
  1599. {
  1600. HandleClientFrameResize (pCD, (XEvent *) motionEvent);
  1601. }
  1602. }
  1603. }
  1604. } /* END OF FUNCTION HandleCMotionNotify */
  1605. /*************************************<->*************************************
  1606. *
  1607. * HandleCEnterNotify (pCD, enterEvent)
  1608. *
  1609. *
  1610. * Description:
  1611. * -----------
  1612. * This function does window management actions associated with an enter
  1613. * window event on the client window.
  1614. *
  1615. *
  1616. * Inputs:
  1617. * ------
  1618. * pCD = pointer to the client data for the window/icon that was entered
  1619. *
  1620. * enterEvent = pointer to the enter event
  1621. *
  1622. *************************************<->***********************************/
  1623. void HandleCEnterNotify (ClientData *pCD, XEnterWindowEvent *enterEvent)
  1624. {
  1625. XEvent report;
  1626. Boolean MatchFound;
  1627. Window enterWindow;
  1628. /*
  1629. * If a client is being configured don't change the keyboard input
  1630. * focus. The input focus is "fixed" after the configuration has been
  1631. * completed.
  1632. */
  1633. if (pCD->clientState == MINIMIZED_STATE)
  1634. {
  1635. enterWindow = ICON_FRAME_WIN(pCD);
  1636. }
  1637. else
  1638. {
  1639. enterWindow = pCD->clientFrameWin;
  1640. }
  1641. MatchFound = XCheckTypedWindowEvent(DISPLAY, enterWindow,
  1642. LeaveNotify, &report);
  1643. /*
  1644. * NOTE: Handle focus change for when user clicks button in the
  1645. * process of moving focus the matching event will be NotifyGrab.
  1646. *
  1647. * IF (((no_match) ||
  1648. * (another window has focus and button grabbed)) &&
  1649. * pointer_mode)
  1650. */
  1651. if ((enterEvent->detail != NotifyInferior) &&
  1652. (((!MatchFound || (report.xcrossing.detail == NotifyInferior)) &&
  1653. ((enterEvent->mode == NotifyNormal) ||
  1654. (enterEvent->mode == NotifyUngrab)) &&
  1655. !wmGD.menuActive) ||
  1656. (wmGD.keyboardFocus &&
  1657. (wmGD.keyboardFocus->clientFrameWin != enterWindow) &&
  1658. (enterEvent->mode == NotifyGrab))) &&
  1659. ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) ||
  1660. (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)))
  1661. {
  1662. /*
  1663. * Make sure that EnterNotify is applicable; don't do anything if
  1664. * the window is minimized (not currently visible) or the event is
  1665. * associated with an icon in the icon box.
  1666. */
  1667. if (!(((enterEvent->window == pCD->clientFrameWin) &&
  1668. (pCD->clientState == MINIMIZED_STATE)) ||
  1669. (((enterEvent->window == ICON_FRAME_WIN(pCD)) &&
  1670. P_ICON_BOX(pCD)) ||
  1671. (enterEvent->window == pCD->pSD->activeIconTextWin))))
  1672. {
  1673. if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
  1674. {
  1675. /*
  1676. * Set the focus only if the window does not currently have
  1677. * or if another window is in the process of getting the
  1678. * focus (this check avoids redundant focus setting).
  1679. */
  1680. if ((pCD != wmGD.keyboardFocus) ||
  1681. (pCD != wmGD.nextKeyboardFocus))
  1682. {
  1683. Do_Focus_Key (pCD, enterEvent->time, ALWAYS_SET_FOCUS);
  1684. /* Does the event need to be replayed for modalized windows ? */
  1685. if ( wmGD.replayEnterEvent )
  1686. /* Yes, save the event. */
  1687. memcpy( &wmGD.savedEnterEvent, enterEvent,
  1688. sizeof( XEnterWindowEvent ) );
  1689. /*
  1690. * The original code counted on getting a focus out event as a result
  1691. * of setting the input focus in Do_Focus_key. That would cause
  1692. * SetkeyboardFocus to get called. Unfortunately, you cannot depend on
  1693. * getting a focus out. You may have already had focus yourself.
  1694. *
  1695. * This bug can be produced by:
  1696. * * bring up a menu and leave it posted
  1697. * * move to a different window and click
  1698. * * the menu comes unposted, the new window has input focus, but no
  1699. * client active decorations are changed.
  1700. */
  1701. }
  1702. }
  1703. if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
  1704. {
  1705. SetColormapFocus (ACTIVE_PSD, pCD);
  1706. }
  1707. }
  1708. }
  1709. } /* END OF FUNCTION HandleCEnterNotify */
  1710. /*************************************<->*************************************
  1711. *
  1712. * HandleCLeaveNotify (pCD, leaveEvent)
  1713. *
  1714. *
  1715. * Description:
  1716. * -----------
  1717. * This function does window management actions associated with an leave
  1718. * window event on the client window.
  1719. *
  1720. *
  1721. * Inputs:
  1722. * ------
  1723. * pCD = pointer to the client data for the window/icon that was leaveed
  1724. *
  1725. * leaveEvent = pointer to the leave event
  1726. *
  1727. *************************************<->***********************************/
  1728. void HandleCLeaveNotify (ClientData *pCD, XLeaveWindowEvent *leaveEvent)
  1729. {
  1730. XEvent report;
  1731. Window leaveWindow;
  1732. if (pCD->clientState == MINIMIZED_STATE)
  1733. {
  1734. leaveWindow = ICON_FRAME_WIN(pCD);
  1735. }
  1736. else
  1737. {
  1738. leaveWindow = pCD->clientFrameWin;
  1739. }
  1740. /*
  1741. * Don't remove enterEvents when user double clicks on an icon in
  1742. * an iconbox. Otherwise the window that gets normalized will get
  1743. * matching enter events and not get the focus.
  1744. */
  1745. if (P_ICON_BOX(pCD) &&
  1746. (P_ICON_BOX(pCD)->pCD_iconBox != wmGD.keyboardFocus) &&
  1747. (P_ICON_BOX(pCD)->pCD_iconBox != wmGD.nextKeyboardFocus))
  1748. {
  1749. XCheckTypedWindowEvent(DISPLAY, leaveWindow, EnterNotify, &report);
  1750. }
  1751. } /* END OF FUNCTION HandleCLeaveNotify */
  1752. /*************************************<->*************************************
  1753. *
  1754. * HandleCFocusIn (pCD, focusChangeEvent)
  1755. *
  1756. *
  1757. * Description:
  1758. * -----------
  1759. * This function does window management actions associated with a focus
  1760. * in event.
  1761. *
  1762. *
  1763. * Inputs:
  1764. * ------
  1765. * pCD = pointer to the client data for the window/icon that was entered
  1766. *
  1767. * enterEvent = pointer to the focus in event
  1768. *
  1769. *
  1770. * Outputs:
  1771. * -------
  1772. * RETURN = True if event is to be dispatched by the toolkit
  1773. *
  1774. *************************************<->***********************************/
  1775. Boolean HandleCFocusIn (ClientData *pCD, XFocusChangeEvent *focusChangeEvent)
  1776. {
  1777. Boolean setupNextFocus;
  1778. Boolean doXtDispatchEvent = False;
  1779. /*
  1780. * Ignore the event if it is for a window that is no longer viewable.
  1781. * This is the case for a client window FocusIn event that is being
  1782. * processed for a window that has been minimized.
  1783. */
  1784. if ((focusChangeEvent->window == ICON_FRAME_WIN(pCD)) &&
  1785. P_ICON_BOX(pCD))
  1786. {
  1787. doXtDispatchEvent = True;
  1788. }
  1789. else if (((focusChangeEvent->mode == NotifyNormal) ||
  1790. (focusChangeEvent->mode == NotifyWhileGrabbed)) &&
  1791. !((focusChangeEvent->window == pCD->clientBaseWin) &&
  1792. (pCD->clientState == MINIMIZED_STATE)) &&
  1793. !((focusChangeEvent->window == ICON_FRAME_WIN(pCD)) &&
  1794. (pCD->clientState != MINIMIZED_STATE)))
  1795. {
  1796. setupNextFocus = (wmGD.keyboardFocus == wmGD.nextKeyboardFocus);
  1797. if (wmGD.keyboardFocus != pCD)
  1798. {
  1799. if ((focusChangeEvent->detail == NotifyNonlinear) ||
  1800. (focusChangeEvent->detail == NotifyNonlinearVirtual))
  1801. {
  1802. SetKeyboardFocus (pCD, REFRESH_LAST_FOCUS);
  1803. if (setupNextFocus)
  1804. {
  1805. wmGD.nextKeyboardFocus = wmGD.keyboardFocus;
  1806. }
  1807. }
  1808. /* Re: CR 4896 */
  1809. /* this part added to try and fix the %#$!@!!&* focus bug. */
  1810. /* this seems to solve most of the problem. This still leaves */
  1811. /* times when clicking on an icon toggles the focus back to the */
  1812. /* the previous focus window. */
  1813. /* Another patch was added to WmEvent.c to fix that problem. */
  1814. else
  1815. {
  1816. SetKeyboardFocus (pCD, REFRESH_LAST_FOCUS);
  1817. if (setupNextFocus) wmGD.nextKeyboardFocus = wmGD.keyboardFocus;
  1818. }
  1819. }
  1820. else if ((focusChangeEvent->detail == NotifyInferior) &&
  1821. (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
  1822. {
  1823. /*
  1824. * The client window was withdrawn (unmapped or destroyed).
  1825. * Reset the focus.
  1826. * !!! pointer focus !!!
  1827. */
  1828. if (wmGD.autoKeyFocus)
  1829. {
  1830. /* !!! fix this up to handle transient windows !!! */
  1831. AutoResetKeyFocus (wmGD.keyboardFocus, GetTimestamp ());
  1832. }
  1833. else
  1834. {
  1835. Do_Focus_Key ((ClientData *) NULL, GetTimestamp (),
  1836. ALWAYS_SET_FOCUS);
  1837. }
  1838. }
  1839. }
  1840. pCD->focusAutoRaiseDisabled = False;
  1841. return (doXtDispatchEvent);
  1842. } /* END OF FUNCTION HandleCFocusIn */
  1843. /*************************************<->*************************************
  1844. *
  1845. * HandleCFocusOut (pCD, focusChangeEvent)
  1846. *
  1847. *
  1848. * Description:
  1849. * -----------
  1850. * This function does window management actions associated with a focus
  1851. * out event that applies to a client window.
  1852. *
  1853. *
  1854. * Inputs:
  1855. * ------
  1856. * pCD = pointer to the client data for the window/icon that was entered
  1857. *
  1858. * enterEvent = pointer to the focus out event
  1859. *
  1860. *
  1861. * Outputs:
  1862. * -------
  1863. * RETURN = True if event is to be dispatched by the toolkit
  1864. *
  1865. *************************************<->***********************************/
  1866. Boolean HandleCFocusOut (ClientData *pCD, XFocusChangeEvent *focusChangeEvent)
  1867. {
  1868. Boolean doXtDispatchEvent = False;
  1869. long focusFlags = REFRESH_LAST_FOCUS ;
  1870. pCD->focusAutoRaiseDisabled = False;
  1871. /*
  1872. * Ignore the event if it is for a window that is no longer viewable.
  1873. * This is the case for a client window FocusOut event that is being
  1874. * processed for a window that has been minimized. Also, ignore focus
  1875. * out events for clients that aren't on the current screen.
  1876. */
  1877. if (((focusChangeEvent->window == ICON_FRAME_WIN(pCD)) &&
  1878. P_ICON_BOX(pCD)) ||
  1879. (SCREEN_FOR_CLIENT(pCD) != ACTIVE_SCREEN))
  1880. {
  1881. doXtDispatchEvent = True;
  1882. }
  1883. else if ((wmGD.keyboardFocus == pCD) &&
  1884. (focusChangeEvent->mode == NotifyNormal) &&
  1885. ((focusChangeEvent->detail == NotifyNonlinear) ||
  1886. (focusChangeEvent->detail == NotifyNonlinearVirtual)) &&
  1887. !((focusChangeEvent->window == pCD->clientBaseWin) &&
  1888. (pCD->clientState == MINIMIZED_STATE)) &&
  1889. !((focusChangeEvent->window == ICON_FRAME_WIN(pCD)) &&
  1890. (pCD->clientState != MINIMIZED_STATE)))
  1891. {
  1892. /*
  1893. * The keyboard focus was shifted to another window, maybe on
  1894. * another screen. Clear the focus indication and reset focus
  1895. * handling for the client window.
  1896. */
  1897. /*
  1898. * use SCREEN_SWITCH_FOCUS in SetKeyboardFocus to
  1899. * not call SetColormapFocus if we are moveing
  1900. * to another screen
  1901. */
  1902. if (SCREEN_FOR_CLIENT(pCD) != ACTIVE_SCREEN)
  1903. {
  1904. focusFlags |= SCREEN_SWITCH_FOCUS;
  1905. }
  1906. SetKeyboardFocus ((ClientData *) NULL, focusFlags);
  1907. if (wmGD.nextKeyboardFocus == pCD)
  1908. {
  1909. wmGD.nextKeyboardFocus = NULL;
  1910. }
  1911. }
  1912. return (doXtDispatchEvent);
  1913. } /* END OF FUNCTION HandleCFocusOut */
  1914. /*************************************<->*************************************
  1915. *
  1916. * HandleCConfigureRequest (pCD, configureRequest)
  1917. *
  1918. *
  1919. * Description:
  1920. * -----------
  1921. * This functions handles ConfigureRequest events that are for client windows.
  1922. *
  1923. *
  1924. * Inputs:
  1925. * ------
  1926. * pCD = pointer to client data
  1927. *
  1928. * configureRequest = a pointer to a ConfigureRequest event
  1929. *
  1930. *************************************<->***********************************/
  1931. void HandleCConfigureRequest (ClientData *pCD, XConfigureRequestEvent *configureRequest)
  1932. {
  1933. unsigned int mask = configureRequest->value_mask;
  1934. int stackMode = configureRequest->detail;
  1935. unsigned int changeMask;
  1936. ClientData *pcdLeader;
  1937. ClientData *pcdSibling;
  1938. ClientListEntry *pStackEntry;
  1939. /*
  1940. * Call ProcessNewConfiguration to handle window moving and resizing.
  1941. * Send ConfigureNotify event (based on ICCCM conventions).
  1942. * Then process the request for stacking.
  1943. */
  1944. if ((configureRequest->window == pCD->client) &&
  1945. (mask & (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)))
  1946. {
  1947. if (pCD->maxConfig) {
  1948. ProcessNewConfiguration (pCD,
  1949. (mask & CWX) ? configureRequest->x : pCD->maxX,
  1950. (mask & CWY) ? configureRequest->y : pCD->maxY,
  1951. (unsigned int) ((mask & CWWidth) ?
  1952. configureRequest->width : pCD->maxWidth),
  1953. (unsigned int) ((mask & CWHeight) ?
  1954. configureRequest->height : pCD->maxHeight),
  1955. True /*client request*/);
  1956. }
  1957. else {
  1958. int xOff, yOff;
  1959. /* CDExc21094 - ProcessNewConfiguration() offsets the */
  1960. /* x and y positions passed in; in order to keep them */
  1961. /* the same, we offset them in the opposite direction. */
  1962. if (wmGD.positionIsFrame)
  1963. {
  1964. xOff = pCD->clientOffset.x;
  1965. yOff = pCD->clientOffset.y;
  1966. }
  1967. else
  1968. {
  1969. xOff = yOff = 0;
  1970. }
  1971. ProcessNewConfiguration (pCD,
  1972. (mask & CWX) ? configureRequest->x : pCD->clientX - xOff,
  1973. (mask & CWY) ? configureRequest->y : pCD->clientY - yOff,
  1974. (unsigned int) ((mask & CWWidth) ?
  1975. configureRequest->width : pCD->clientWidth),
  1976. (unsigned int) ((mask & CWHeight) ?
  1977. configureRequest->height : pCD->clientHeight),
  1978. True /*client request*/);
  1979. }
  1980. }
  1981. if (mask & CWStackMode)
  1982. {
  1983. changeMask = mask & (CWSibling | CWStackMode);
  1984. if (changeMask & CWSibling)
  1985. {
  1986. if (XFindContext (DISPLAY, configureRequest->above,
  1987. wmGD.windowContextType, (caddr_t *)&pcdSibling))
  1988. {
  1989. changeMask &= ~CWSibling;
  1990. }
  1991. else
  1992. {
  1993. /*
  1994. * For client requests only primary windows can be
  1995. * restacked relative to one another.
  1996. */
  1997. pcdLeader = FindTransientTreeLeader (pCD);
  1998. pcdSibling = FindTransientTreeLeader (pcdSibling);
  1999. if (pcdLeader == pcdSibling)
  2000. {
  2001. changeMask &= ~CWSibling;
  2002. }
  2003. else
  2004. {
  2005. pStackEntry = &pcdSibling->clientEntry;
  2006. if ((stackMode == Above) || (stackMode == TopIf))
  2007. {
  2008. /* lower the window to just above the sibling */
  2009. Do_Lower (pcdLeader, pStackEntry, STACK_NORMAL);
  2010. }
  2011. else if ((stackMode == Below) || (stackMode == BottomIf))
  2012. {
  2013. /* raise the window to just below the sibling */
  2014. Do_Raise (pcdLeader, pStackEntry, STACK_NORMAL);
  2015. }
  2016. else if (stackMode == Opposite)
  2017. {
  2018. F_Raise_Lower (NULL, pCD, (XEvent *)configureRequest);
  2019. }
  2020. }
  2021. }
  2022. }
  2023. if (!(changeMask & CWSibling))
  2024. {
  2025. if ((stackMode == Above) || (stackMode == TopIf))
  2026. {
  2027. Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
  2028. }
  2029. else if ((stackMode == Below) || (stackMode == BottomIf))
  2030. {
  2031. Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
  2032. }
  2033. else if (stackMode == Opposite)
  2034. {
  2035. F_Raise_Lower (NULL, pCD, (XEvent *) configureRequest);
  2036. }
  2037. }
  2038. /* !!! should a synthetic ConfigureNotify be sent? !!! */
  2039. if ((configureRequest->window == pCD->client) &&
  2040. !(mask & (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)))
  2041. {
  2042. SendConfigureNotify (pCD);
  2043. }
  2044. }
  2045. } /* END OF FUNCTION HandleCConfigureRequest */
  2046. /*************************************<->*************************************
  2047. *
  2048. * HandleCColormapNotify (pCD, colorEvent)
  2049. *
  2050. *
  2051. * Description:
  2052. * -----------
  2053. * This function does window management actions associated with a colormap
  2054. * notify event on the client window.
  2055. *
  2056. *
  2057. * Inputs:
  2058. * ------
  2059. * pCD = pointer to client data
  2060. *
  2061. * colorEvent = a ColormapNotify event
  2062. *
  2063. *************************************<->***********************************/
  2064. void HandleCColormapNotify (ClientData *pCD, XColormapEvent *colorEvent)
  2065. {
  2066. int i;
  2067. #ifndef IBM_169380
  2068. ClientData **cmap_window_data;
  2069. #endif
  2070. Boolean newClientColormap = False;
  2071. /*
  2072. * The colormap of the top-level client window or one of its subwindows
  2073. * has been changed.
  2074. */
  2075. if (colorEvent->new)
  2076. {
  2077. /*
  2078. * The colormap has been changed.
  2079. */
  2080. /*
  2081. * !!! when the server ColormapNotify problem is fixed !!!
  2082. * !!! use the colormap id from the event !!!
  2083. */
  2084. if (WmGetWindowAttributes (colorEvent->window))
  2085. {
  2086. colorEvent->colormap = wmGD.windowAttributes.colormap;
  2087. }
  2088. else
  2089. {
  2090. return;
  2091. }
  2092. /*
  2093. * !!! remove the above code when the problem is fixed !!!
  2094. */
  2095. /*
  2096. * Identify the colormap that the window manager has associated
  2097. * with the window.
  2098. */
  2099. #ifndef IBM_169380
  2100. if ((pCD->clientCmapCount == 0) && (colorEvent->window == pCD->client))
  2101. #endif
  2102. if (pCD->clientCmapCount == 0)
  2103. {
  2104. /* no subwindow colormaps; change top-level window colormap */
  2105. #ifdef IBM_169380
  2106. if (colorEvent->window == pCD->client)
  2107. {
  2108. #endif
  2109. if (colorEvent->colormap == None)
  2110. {
  2111. /* use the workspace colormap */
  2112. pCD->clientColormap =
  2113. ACTIVE_PSD->workspaceColormap;
  2114. }
  2115. else
  2116. {
  2117. pCD->clientColormap = colorEvent->colormap;
  2118. }
  2119. newClientColormap = True;
  2120. #ifdef IBM_169380
  2121. }
  2122. #endif
  2123. }
  2124. #ifndef IBM_169380
  2125. if (!XFindContext (DISPLAY, colorEvent->window,
  2126. wmGD.cmapWindowContextType, (caddr_t *)&cmap_window_data))
  2127. {
  2128. /*
  2129. * The WM_COLORMAP_WINDOWS property of a toplevel window may
  2130. * specify colorEvent->window. If so, we must update the
  2131. * colormap information it holds in clientCmapList.
  2132. */
  2133. ClientData *any_pCD;
  2134. int j;
  2135. for (j = 0; cmap_window_data[j] != NULL; j++)
  2136. {
  2137. any_pCD = cmap_window_data[j];
  2138. for (i = 0; i < any_pCD->clientCmapCount; i++)
  2139. {
  2140. if (any_pCD->cmapWindows[i] == colorEvent->window)
  2141. {
  2142. if (colorEvent->colormap == None)
  2143. {
  2144. /* use the workspace colormap */
  2145. any_pCD->clientCmapList[i] =
  2146. ACTIVE_PSD->workspaceColormap;
  2147. }
  2148. else
  2149. {
  2150. any_pCD->clientCmapList[i] = colorEvent->colormap;
  2151. }
  2152. if (i == any_pCD->clientCmapIndex)
  2153. {
  2154. any_pCD->clientColormap =
  2155. any_pCD->clientCmapList[i];
  2156. if (any_pCD == pCD)
  2157. {
  2158. newClientColormap = True;
  2159. }
  2160. }
  2161. break;
  2162. }
  2163. }
  2164. }
  2165. }
  2166. #else
  2167. else
  2168. {
  2169. /* there are subwindow colormaps */
  2170. for (i = 0; i < pCD->clientCmapCount; i++)
  2171. {
  2172. if (pCD->cmapWindows[i] == colorEvent->window)
  2173. {
  2174. if (colorEvent->colormap == None)
  2175. {
  2176. /* use the workspace colormap */
  2177. pCD->clientCmapList[i] =
  2178. ACTIVE_PSD->workspaceColormap;
  2179. }
  2180. else
  2181. {
  2182. pCD->clientCmapList[i] = colorEvent->colormap;
  2183. }
  2184. if (i == pCD->clientCmapIndex)
  2185. {
  2186. newClientColormap = True;
  2187. pCD->clientColormap = pCD->clientCmapList[i];
  2188. }
  2189. break;
  2190. }
  2191. }
  2192. }
  2193. #endif /* IBM_169380 */
  2194. if ((ACTIVE_PSD->colormapFocus == pCD) && newClientColormap &&
  2195. ((pCD->clientState == NORMAL_STATE) ||
  2196. (pCD->clientState == MAXIMIZED_STATE)))
  2197. {
  2198. /*
  2199. * The client window has the colormap focus, install the
  2200. * colormap.
  2201. */
  2202. WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
  2203. }
  2204. }
  2205. } /* END OF FUNCTION HandleCColormapNotify */
  2206. /*************************************<->*************************************
  2207. *
  2208. * HandleClientMessage (pCD, clientEvent)
  2209. *
  2210. *
  2211. * Description:
  2212. * -----------
  2213. * This function handles client message events that are sent to the root
  2214. * window. The window manager action that is taken depends on the
  2215. * message_type of the event.
  2216. *
  2217. *
  2218. * Inputs:
  2219. * ------
  2220. * pCD = pointer to client data
  2221. *
  2222. * clientEvent = pointer to a client message event on the root window
  2223. *
  2224. *************************************<->***********************************/
  2225. void HandleClientMessage (ClientData *pCD, XClientMessageEvent *clientEvent)
  2226. {
  2227. unsigned int newState = WITHDRAWN_STATE;
  2228. /*
  2229. * Process the client message event based on the message_type.
  2230. */
  2231. if (clientEvent->message_type == wmGD.xa_WM_CHANGE_STATE)
  2232. {
  2233. if ((clientEvent->data.l[0] == IconicState) &&
  2234. (pCD->clientFunctions & MWM_FUNC_MINIMIZE))
  2235. {
  2236. newState = MINIMIZED_STATE;
  2237. }
  2238. else if (clientEvent->data.l[0] == NormalState)
  2239. {
  2240. newState = NORMAL_STATE;
  2241. }
  2242. if (!ClientInWorkspace (ACTIVE_WS, pCD))
  2243. {
  2244. newState |= UNSEEN_STATE;
  2245. }
  2246. SetClientState (pCD, newState, GetTimestamp ());
  2247. }
  2248. else if (clientEvent->message_type == wmGD.xa__NET_WM_FULLSCREEN_MONITORS)
  2249. {
  2250. ProcessNetWmFullscreenMonitors (pCD,
  2251. clientEvent->data.l[0], clientEvent->data.l[1],
  2252. clientEvent->data.l[2], clientEvent->data.l[3]);
  2253. if (pCD->fullscreenAuto)
  2254. XDeleteProperty (DISPLAY, pCD->client, clientEvent->message_type);
  2255. else
  2256. XChangeProperty (DISPLAY, pCD->client, clientEvent->message_type,
  2257. XA_CARDINAL, 32, PropModeReplace,
  2258. (unsigned char *) clientEvent->data.l, 4);
  2259. }
  2260. else if (clientEvent->message_type == wmGD.xa__NET_WM_STATE)
  2261. {
  2262. ProcessNetWmState (pCD, clientEvent->data.l[0], clientEvent->data.l[1],
  2263. clientEvent->data.l[2]);
  2264. }
  2265. } /* END OF FUNCTION HandleClientMessage */
  2266. /*************************************<->*************************************
  2267. *
  2268. * HandleCShapeNotify (pCD, shapeEvent)
  2269. *
  2270. *
  2271. * Description:
  2272. * -----------
  2273. * Handle a shape notify event on a client window. Keeps track of
  2274. * the shaped state of the client window and calls
  2275. * SetFrameShape() to reshape the frame accordingly.
  2276. *
  2277. * Inputs:
  2278. * ------
  2279. * shapeEvent = pointer to a shape notify in event on the client window.
  2280. *
  2281. *************************************<->***********************************/
  2282. void
  2283. HandleCShapeNotify (ClientData *pCD, XShapeEvent *shapeEvent)
  2284. {
  2285. if (pCD)
  2286. {
  2287. if (shapeEvent->kind != ShapeBounding)
  2288. {
  2289. return;
  2290. }
  2291. pCD->wShaped = shapeEvent->shaped;
  2292. SetFrameShape (pCD);
  2293. }
  2294. } /* END OF FUNCTION HandleCShapeNotify */
  2295. /*************************************<->*************************************
  2296. *
  2297. * GetParentWindow (window)
  2298. *
  2299. *
  2300. * Description:
  2301. * -----------
  2302. * This function identifies the parent window of the specified window.
  2303. *
  2304. *
  2305. * Inputs:
  2306. * ------
  2307. * window = find the parent of this window
  2308. *
  2309. * Outputs:
  2310. * -------
  2311. * Return = return the window id of the parent of the specified window
  2312. *
  2313. *************************************<->***********************************/
  2314. Window GetParentWindow (Window window)
  2315. {
  2316. Window root;
  2317. Window parent;
  2318. Window *children;
  2319. unsigned int nchildren;
  2320. if (XQueryTree (DISPLAY, window, &root, &parent, &children, &nchildren))
  2321. {
  2322. if (nchildren)
  2323. {
  2324. XFree ((char *)children);
  2325. }
  2326. }
  2327. else
  2328. {
  2329. parent = (Window)0L;
  2330. }
  2331. return (parent);
  2332. } /* END OF FUNCTION GetParentWindow */
  2333. /*************************************<->*************************************
  2334. *
  2335. * DetermineActiveScreen (pEvent)
  2336. *
  2337. *
  2338. * Description:
  2339. * -----------
  2340. * This function determines the currently active screen
  2341. *
  2342. *
  2343. * Inputs:
  2344. * ------
  2345. * pEvent = pointer to an event structure
  2346. *
  2347. * Outputs:
  2348. * -------
  2349. * ACTIVE_PSD = set to point to the screen data for the currently
  2350. * active scree;
  2351. * wmGD.queryScreen = set to False if we're sure about the ACTIVE_PSD
  2352. * setting
  2353. *
  2354. *************************************<->***********************************/
  2355. void DetermineActiveScreen (XEvent *pEvent)
  2356. {
  2357. WmScreenData *pSD;
  2358. switch (pEvent->type)
  2359. {
  2360. case NoExpose:
  2361. case GraphicsExpose:
  2362. break; /* ignore these events */
  2363. default:
  2364. /*
  2365. * Get the screen that the event occurred on.
  2366. */
  2367. pSD = GetScreenForWindow (pEvent->xany.window);
  2368. if (pSD)
  2369. {
  2370. /*
  2371. * Set the ACTIVE_PSD to the event's screen to
  2372. * make sure the event gets handled correctly.
  2373. */
  2374. SetActiveScreen (pSD);
  2375. }
  2376. break;
  2377. }
  2378. } /* END OF FUNCTION DetermineActiveScreen */
  2379. /*************************************<->*************************************
  2380. *
  2381. * GetScreenForWindow (win)
  2382. *
  2383. *
  2384. * Description:
  2385. * -----------
  2386. * This function determines the screen for a window
  2387. *
  2388. *
  2389. * Inputs:
  2390. * ------
  2391. * win = window id
  2392. *
  2393. * Outputs:
  2394. * -------
  2395. * value of function = pointer to screen data (pSD) or NULL on failure
  2396. *
  2397. *************************************<->***********************************/
  2398. WmScreenData * GetScreenForWindow (Window win)
  2399. {
  2400. XWindowAttributes attribs;
  2401. WmScreenData *pSD = NULL;
  2402. /*
  2403. * Get the screen that the event occurred on.
  2404. */
  2405. if (XGetWindowAttributes (DISPLAY, win, &attribs))
  2406. {
  2407. if (!XFindContext (DISPLAY, attribs.root, wmGD.screenContextType,
  2408. (caddr_t *)&pSD))
  2409. {
  2410. if (pSD && !pSD->screenTopLevelW)
  2411. {
  2412. pSD = NULL;
  2413. }
  2414. }
  2415. }
  2416. return (pSD);
  2417. } /* END OF FUNCTION GetScreenForWindow */