WmCEvent.c 70 KB

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