WmManage.c 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906
  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, 1992, 1993 HEWLETT-PACKARD COMPANY
  32. */
  33. /*
  34. * Included Files:
  35. */
  36. #include "WmGlobal.h"
  37. #include "WmICCC.h"
  38. /*
  39. * include extern functions
  40. */
  41. #include "WmCDecor.h"
  42. #include "WmCEvent.h"
  43. #include "WmColormap.h"
  44. #include "WmError.h"
  45. #include "WmEvent.h"
  46. #include "WmFunction.h"
  47. #include "WmGraphics.h"
  48. #include "WmIDecor.h"
  49. #include "WmIconBox.h"
  50. #include "WmImage.h"
  51. #include "WmInstantTitle.h"
  52. #include "WmKeyFocus.h"
  53. #include "WmPanelP.h" /* typedef needed in WmManage.h */
  54. #include <Dt/Message.h>
  55. #include "WmIPC.h"
  56. #include "WmManage.h"
  57. #include "WmMenu.h"
  58. #include "WmProperty.h"
  59. #include "WmProtocol.h"
  60. #include "WmWinInfo.h"
  61. #include "WmWinList.h"
  62. #include "WmWinState.h"
  63. #include "WmPresence.h"
  64. #include "WmWrkspace.h"
  65. #include "WmXSMP.h"
  66. /*
  67. * Function Declarations:
  68. */
  69. Boolean IsEmbeddedClient (
  70. ClientData *pCD,
  71. WmFpEmbeddedClientData **ppECD);
  72. Boolean ManageEmbeddedClient (
  73. ClientData *pCD,
  74. WmFpEmbeddedClientData *pECD,
  75. long manageFlags);
  76. Boolean IsPushRecallClient (
  77. ClientData *pCD,
  78. WmFpPushRecallClientData **ppPRCD);
  79. static void HandleSubstructEvents(
  80. Widget w,
  81. caddr_t ptr,
  82. XEvent *event );
  83. Boolean UpdateEmbeddedClientsProperty(
  84. WmScreenData *pSD );
  85. static void ForceSubpanelWMState(Window win);
  86. static void ReManageWindow (ClientData *pCD);
  87. static void CheckPushRecallClient (ClientData *pCD);
  88. /*
  89. * Global Variables:
  90. */
  91. static void ApplyPrematureClientMessages (ClientData *pCD)
  92. {
  93. unsigned long i, nitems, leftover;
  94. int actualFormat;
  95. Atom actualType;
  96. Atom property = wmGD.xa_PREMATURE_XCLIENTMESSAGEEVENT_LIST;
  97. XClientMessageEvent *messages = NULL;
  98. if (!HasProperty (pCD, property)) goto err;
  99. if (XGetWindowProperty (DISPLAY, pCD->client, property, 0L, 1000000L, True,
  100. property, &actualType, &actualFormat, &nitems,
  101. &leftover, (unsigned char **)&messages) != Success)
  102. goto err;
  103. if (actualType != property) goto err;
  104. nitems /= sizeof (XClientMessageEvent);
  105. if (!nitems) goto err;
  106. for (i = 0; i < nitems; ++i) HandleClientMessage (pCD, &messages[i]);
  107. err:
  108. if (messages) XFree (messages);
  109. }
  110. /*************************************<->*************************************
  111. *
  112. * AdoptInitialClients (pSD)
  113. *
  114. * Inputs:
  115. * -------
  116. * pSD = pointer to screen data
  117. *
  118. *
  119. * Description:
  120. * -----------
  121. * This function is called to find client windows that were mapped prior to
  122. * starting (or restarting) the window manager. These windows are included
  123. * in the set of windows managed by the window manager.
  124. *
  125. *************************************<->***********************************/
  126. void AdoptInitialClients (WmScreenData *pSD)
  127. {
  128. Window root;
  129. Window parent;
  130. Window *clients;
  131. int nAncillaries, iAnc;
  132. Window *pAncillaryWindows, *pWin1;
  133. WmWorkspaceData *pWS0;
  134. unsigned int nclients;
  135. ClientData *pcd = NULL;
  136. PropWMState *wmStateProp;
  137. Boolean manageOnRestart;
  138. int i,j;
  139. long manageFlags;
  140. /*
  141. * Generate list of ancillary windows (not to be managed)
  142. */
  143. nAncillaries = 2 + pSD->numWorkspaces;
  144. pAncillaryWindows = (Window *) XtMalloc (sizeof(Window)*(nAncillaries));
  145. if (!pAncillaryWindows)
  146. {
  147. Warning (((char *)GETMESSAGE(46, 1, "Insufficient memory to adopt initial clients")));
  148. ExitWM (WM_ERROR_EXIT_VALUE);
  149. }
  150. pWS0 = pSD->pWS;
  151. pWin1 = pAncillaryWindows;
  152. for (iAnc = 0; iAnc < pSD->numWorkspaces; iAnc++)
  153. {
  154. *pWin1 = XtWindow((pWS0)->workspaceTopLevelW);
  155. pWin1++;
  156. pWS0++;
  157. }
  158. *pWin1++ = XtWindow (pSD->screenTopLevelW);
  159. *pWin1 = pSD->activeIconTextWin;
  160. /*
  161. * Look for mapped top-level windows and start managing them:
  162. */
  163. if (XQueryTree (DISPLAY, pSD->rootWindow, &root, &parent, &clients,
  164. &nclients))
  165. {
  166. /*
  167. * Filter out icon windows so they don't get managed as a client
  168. * window. Icon windows will be process in SetupClientIconWindow().
  169. */
  170. XWMHints *tmphint;
  171. for (i = 0; i < nclients; i++) {
  172. if (clients[i]) {
  173. if ((tmphint = XGetWMHints (DISPLAY, clients[i])) != NULL) {
  174. if (tmphint->flags & IconWindowHint) {
  175. for (j = 0; j < nclients; j++) {
  176. if (clients[j] == tmphint->icon_window) {
  177. clients[j] = None;
  178. break;
  179. }
  180. }
  181. }
  182. XFree ((char *) tmphint);
  183. }
  184. }
  185. }
  186. for (i = 0; i < nclients; i++)
  187. {
  188. /* determine if the client window should be managed by wm */
  189. if (InWindowList (clients[i], pAncillaryWindows, nAncillaries))
  190. {
  191. /* don't manage ancillary window manager windows */
  192. continue;
  193. }
  194. if (!XFindContext (DISPLAY, clients[i], wmGD.windowContextType,
  195. (caddr_t *)&pcd))
  196. {
  197. /* don't manage a window we've already established a
  198. context for (e.g. icon windows) */
  199. continue;
  200. }
  201. if (!WmGetWindowAttributes (clients[i]))
  202. {
  203. /* can't access the window; ignore it */
  204. continue;
  205. }
  206. /* window attributes are put into the global cache */
  207. /*
  208. * Get the window WM_STATE property value to determine the
  209. * initial window state if the wm is being restarted.
  210. */
  211. manageFlags = MANAGEW_WM_STARTUP;
  212. manageOnRestart = True;
  213. if (wmGD.wmRestarted)
  214. {
  215. manageFlags |= MANAGEW_WM_RESTART;
  216. if ((wmStateProp = GetWMState (clients[i])) != NULL)
  217. {
  218. if (wmStateProp->state == IconicState)
  219. {
  220. manageFlags |= MANAGEW_WM_RESTART_ICON;
  221. }
  222. else if (wmStateProp->state != NormalState)
  223. {
  224. manageOnRestart = False;
  225. }
  226. XFree ((char *)wmStateProp);
  227. }
  228. else
  229. {
  230. manageOnRestart = False;
  231. }
  232. }
  233. /*
  234. * Don't manage any override_redirect windows (mapped or not).
  235. * Manage an unmapped window if it has a WM_STATE property
  236. * and it is not Withdrawn.
  237. * Manage any window that is mapped.
  238. */
  239. if ((wmGD.windowAttributes.override_redirect != True) &&
  240. ((wmGD.wmRestarted && manageOnRestart) ||
  241. (wmGD.windowAttributes.map_state != IsUnmapped)))
  242. {
  243. ManageWindow (pSD, clients[i], manageFlags);
  244. }
  245. }
  246. if (nclients)
  247. {
  248. XFree ((char *)clients);
  249. }
  250. }
  251. if (pAncillaryWindows)
  252. {
  253. XtFree ((char *) pAncillaryWindows);
  254. }
  255. } /* END OF FUNCTION AdoptInitialClients */
  256. /*************************************<->*************************************
  257. *
  258. * ManageWindow (pSD, clientWindow, manageFlags)
  259. *
  260. *
  261. * Description:
  262. * -----------
  263. * This is the highlevel function that is used to include a window in
  264. * the set of windows that are managed by the window manager. The window
  265. * gets reparented and decorated, gets an icon, is setup for window
  266. * management event handling, etc. Client windows that are controlled
  267. * by the window manager (e.g., the icon box) are also managed with
  268. * this function.
  269. *
  270. *
  271. * Inputs:
  272. * ------
  273. * clientWindow = window of the client that we should manage
  274. *
  275. * manageFlags = additional control information
  276. *
  277. *
  278. * Outputs:
  279. * -------
  280. * pCD = initialized client data
  281. *
  282. *************************************<->***********************************/
  283. void
  284. ManageWindow (WmScreenData *pSD, Window clientWindow, long manageFlags)
  285. {
  286. ClientData *pCD;
  287. int initialState;
  288. int i;
  289. Boolean sendConfigNotify;
  290. WmWorkspaceData *pwsi;
  291. WmFpEmbeddedClientData *pECD;
  292. /*
  293. * Get client information including window attributes and window
  294. * property values. Use this information to determine how the window
  295. * is to be managed.
  296. */
  297. if (!(pCD = GetClientInfo (pSD, clientWindow, manageFlags)))
  298. {
  299. /* error getting client info; do not manage the client window */
  300. return;
  301. }
  302. /*
  303. * Handle case of transients that derive from embedded clients.
  304. */
  305. if (wmGD.dtSD && (wmGD.dtSD == pCD->pSD))
  306. {
  307. if (pCD->transientLeader && pCD->transientLeader->pECD)
  308. {
  309. WmPanelistObject pPanelist;
  310. ClientData *pCDfp = NULL;
  311. pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
  312. (void) XFindContext (DISPLAY, XtWindow(O_Shell (pPanelist)),
  313. wmGD.windowContextType, (caddr_t *)&pCDfp);
  314. pCD->transientLeader = pCDfp;
  315. }
  316. }
  317. if (IsEmbeddedClient (pCD, &pECD))
  318. {
  319. /*
  320. * This client is embedded in the front panel
  321. */
  322. if (ManageEmbeddedClient(pCD, pECD, manageFlags))
  323. {
  324. /*
  325. * ...then we've embedded it in the front
  326. * panel--no further processing required.
  327. */
  328. if (smAckState == SM_START_ACK)
  329. {
  330. SendClientMsg( wmGD.dtSmWindow,
  331. (long) wmGD.xa_DT_SM_WM_PROTOCOL,
  332. (long) wmGD.xa_DT_WM_WINDOW_ACK,
  333. CurrentTime, NULL, 0);
  334. }
  335. return;
  336. }
  337. }
  338. /*
  339. * Handle case of transients that derive from embedded clients.
  340. * !!!!
  341. */
  342. #if 0
  343. if (pCD->transientLeader && pCD->transientLeader->pAccessPanel)
  344. {
  345. pCD->transientLeader =
  346. pCD->transientLeader->pAccessPanel->pCD_accessPanel;
  347. }
  348. #endif
  349. if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
  350. {
  351. /*
  352. * Put system modal windows in all workspaces to
  353. * avoid the race condition of the window coming up
  354. * just as the user switches workspaces.
  355. */
  356. pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
  357. F_AddToAllWorkspaces(0, pCD, 0);
  358. pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
  359. }
  360. if (manageFlags & MANAGEW_WM_RESTART)
  361. {
  362. if (manageFlags & MANAGEW_WM_RESTART_ICON)
  363. {
  364. pCD->clientState = MINIMIZED_STATE;
  365. }
  366. else
  367. {
  368. pCD->clientState = NORMAL_STATE;
  369. }
  370. }
  371. /*
  372. * Setup the initial placement of the client window. Do interactive
  373. * placement if configured.
  374. */
  375. sendConfigNotify = InitClientPlacement (pCD, manageFlags);
  376. /*
  377. * Make a window frame for the client window and reparent the client
  378. * window.
  379. */
  380. if (!FrameWindow (pCD))
  381. {
  382. /*
  383. * Error in framing the window; clean up the wm resources made
  384. * up to this point for the client window. Do not manage the
  385. * client window.
  386. */
  387. UnManageWindow (pCD);
  388. return;
  389. }
  390. ApplyPrematureClientMessages (pCD);
  391. if (!HasProperty (pCD, wmGD.xa__NET_WM_STATE))
  392. UpdateNetWmState (pCD->client, NULL, 0, _NET_WM_STATE_REMOVE);
  393. /*
  394. * Send config notify if the client's been moved/resized
  395. */
  396. if (sendConfigNotify)
  397. {
  398. SendConfigureNotify (pCD);
  399. }
  400. /*
  401. * Send client offset message if:
  402. *
  403. * 1. The client is interested.
  404. * 2. The position we report to the user is not the client's real
  405. * position.
  406. * 3. There is a client offset to report.
  407. */
  408. if ((pCD->protocolFlags & PROTOCOL_MWM_OFFSET) &&
  409. (wmGD.positionIsFrame) &&
  410. ((pCD->clientOffset.x != 0) ||
  411. (pCD->clientOffset.y != 0)))
  412. {
  413. SendClientOffsetMessage (pCD);
  414. }
  415. /*
  416. * Make an icon for the client window if it is not a valid transient
  417. * window.
  418. */
  419. if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
  420. (pCD->transientLeader == NULL))
  421. {
  422. /*
  423. * Make icons frames
  424. * Only make one icon frame for root icons.
  425. * Make one per workspace for icon box icons.
  426. */
  427. for (i = 0; i < pCD->numInhabited; i++)
  428. {
  429. if ((pwsi = GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID)))
  430. {
  431. if ((pCD->pSD->useIconBox &&
  432. !(manageFlags & MANAGEW_WM_CLIENTS) &&
  433. !(pCD->clientFlags & FRONT_PANEL_BOX)) || (i == 0))
  434. {
  435. /*
  436. * Make icon inside an icon box for non-root case
  437. */
  438. if (!MakeIcon (pwsi, pCD))
  439. {
  440. /*
  441. * Error in making an icon for the client window;
  442. * clean up the wm resources; do not manage the
  443. * client window.
  444. */
  445. UnManageWindow (pCD);
  446. return;
  447. }
  448. else
  449. {
  450. XSaveContext (DISPLAY, pCD->pWsList[i].iconFrameWin,
  451. wmGD.windowContextType, (caddr_t)pCD);
  452. if (pCD->iconWindow && pCD->pWsList[i].iconFrameWin)
  453. {
  454. XGrabButton (DISPLAY, AnyButton, AnyModifier,
  455. pCD->pWsList[i].iconFrameWin, True,
  456. ButtonPressMask|ButtonReleaseMask|
  457. ButtonMotionMask,
  458. GrabModeAsync, GrabModeAsync, None,
  459. wmGD.workspaceCursor);
  460. }
  461. }
  462. }
  463. else
  464. {
  465. /*
  466. * Make root icons for a client
  467. */
  468. if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
  469. (pCD->transientLeader == NULL))
  470. {
  471. if ((i == 0) &&
  472. (!MakeIcon (pwsi, pCD)))
  473. {
  474. /*
  475. * Error in making an icon for the client
  476. * window; clean up the wm resources; do
  477. * not manage the client window.
  478. */
  479. UnManageWindow (pCD);
  480. return;
  481. }
  482. else
  483. {
  484. /* copy root icon frame reference to other
  485. * workspaces
  486. */
  487. pCD->pWsList[i].iconFrameWin =
  488. pCD->pWsList[0].iconFrameWin;
  489. }
  490. }
  491. }
  492. }
  493. }
  494. }
  495. /*
  496. * Register window contexts to facilitate event handling:
  497. */
  498. XSaveContext (DISPLAY, pCD->clientFrameWin, wmGD.windowContextType,
  499. (caddr_t)pCD);
  500. XSaveContext (DISPLAY, pCD->clientBaseWin, wmGD.windowContextType,
  501. (caddr_t)pCD);
  502. if (DECOUPLE_TITLE_APPEARANCE(pCD) && pCD->clientTitleWin)
  503. {
  504. /*
  505. * handle exposures on title bar if it has its own appearance
  506. */
  507. XSaveContext (DISPLAY, pCD->clientTitleWin, wmGD.windowContextType,
  508. (caddr_t)pCD);
  509. }
  510. if (pCD->clientCmapCount > 0)
  511. {
  512. for (i = 0; i < pCD->clientCmapCount; i++)
  513. {
  514. if (pCD->cmapWindows[i] != pCD->client)
  515. {
  516. #ifndef IBM_169380
  517. AddColormapWindowReference(pCD, pCD->cmapWindows[i]);
  518. #else
  519. XSaveContext (DISPLAY, pCD->cmapWindows[i],
  520. wmGD.windowContextType, (caddr_t)pCD);
  521. #endif
  522. }
  523. }
  524. }
  525. pCD->clientFlags |= CLIENT_CONTEXT_SAVED;
  526. /*
  527. * Setup button binding handling for actions that apply to the client
  528. * window.
  529. */
  530. if (BUTTON_SPECS(pCD))
  531. {
  532. SetupCButtonBindings (pCD->clientBaseWin, BUTTON_SPECS(pCD));
  533. }
  534. /*
  535. * Setup key binding handling for system menu accelerators.
  536. */
  537. if (pCD->systemMenuSpec &&
  538. (pCD->systemMenuSpec->accelKeySpecs))
  539. {
  540. SetupKeyBindings (pCD->systemMenuSpec->accelKeySpecs,
  541. pCD->clientFrameWin, GrabModeSync, F_CONTEXT_ALL);
  542. for (i = 0; i < pCD->numInhabited; i++)
  543. {
  544. if (!pCD->pWsList[i].pIconBox && pCD->pWsList[i].iconFrameWin)
  545. {
  546. SetupKeyBindings (pCD->systemMenuSpec->accelKeySpecs,
  547. pCD->pWsList[i].iconFrameWin, GrabModeSync,
  548. F_CONTEXT_ALL);
  549. }
  550. }
  551. }
  552. for (i = 0; i < pCD->numInhabited; i++)
  553. {
  554. if (!pCD->pWsList[i].pIconBox && pCD->pWsList[i].iconFrameWin)
  555. {
  556. static int iconKeySpec = 1;
  557. static int iconAccelSpec = 1;
  558. if ((iconKeySpec != 0) && KEY_SPECS(pCD))
  559. {
  560. iconKeySpec = SetupKeyBindings (KEY_SPECS(pCD),
  561. pCD->pWsList[i].iconFrameWin,
  562. GrabModeSync, F_CONTEXT_ICON);
  563. }
  564. if ((iconAccelSpec != 0) && ACCELERATOR_MENU_COUNT(pCD))
  565. {
  566. int n;
  567. iconAccelSpec = 0;
  568. for (n= 0; n < pSD->acceleratorMenuCount; n++)
  569. {
  570. iconAccelSpec += SetupKeyBindings (
  571. ACCELERATOR_MENU_SPECS(pCD)[n]->accelKeySpecs,
  572. pCD->pWsList[i].iconFrameWin, GrabModeSync,
  573. F_CONTEXT_ICON);
  574. }
  575. }
  576. }
  577. }
  578. /*
  579. * Setup keyboard focus handling if policy is "explicit".
  580. */
  581. if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
  582. {
  583. DoExplicitSelectGrab (pCD->clientBaseWin);
  584. }
  585. UpdateWorkspacePresenceProperty(pCD);
  586. /*
  587. * Make sure the client window has been reparented ...
  588. */
  589. if (!(manageFlags & MANAGEW_WM_CLIENTS))
  590. {
  591. XSync (DISPLAY, False);
  592. if (pCD->clientFlags & CLIENT_DESTROYED)
  593. {
  594. UnManageWindow (pCD);
  595. return;
  596. }
  597. }
  598. /*
  599. * Setup the initial display state for the client window:
  600. */
  601. initialState = pCD->clientState;
  602. if (!ClientInWorkspace (pSD->pActiveWS, pCD))
  603. {
  604. initialState |= UNSEEN_STATE;
  605. }
  606. pCD->clientState = WITHDRAWN_STATE;
  607. pCD->clientFlags &= ~WM_INITIALIZATION;
  608. /*
  609. * Add to stacking list using the client's zero'th workspace
  610. * instead of the current one because it may not be in
  611. * the current one.
  612. */
  613. AddClientToList (GetWorkspaceData (pSD, pCD->pWsList[0].wsID),
  614. pCD, True /*on top*/);
  615. SetClientState (pCD, initialState, GetTimestamp());
  616. /*
  617. * Set the keyboard input focus to the newly managed window if appropriate:
  618. * - focus is automatically set only if the focus policy is explicit
  619. * - if there is a system modal window active then set the focus only
  620. * if the new window is in the system modal hierarchy
  621. * - focus is automatically set if startupKeyFocus is selected or
  622. * the new window is a system modal window or the current focus window
  623. * has the new window as an application modal subordinate
  624. * - don't automatically set the focus if the window is minimized or
  625. * is a window that generally doesn't take input
  626. */
  627. if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
  628. ((pCD->inputMode == MWM_INPUT_SYSTEM_MODAL) ||
  629. ((!wmGD.systemModalActive ||
  630. (wmGD.systemModalClient == FindTransientTreeLeader (pCD))) &&
  631. (wmGD.startupKeyFocus ||
  632. (wmGD.keyboardFocus && (IS_APP_MODALIZED(wmGD.keyboardFocus)))) &&
  633. !(manageFlags &
  634. (MANAGEW_WM_STARTUP | MANAGEW_WM_RESTART | MANAGEW_WM_CLIENTS)) &&
  635. (pCD->clientState != MINIMIZED_STATE) &&
  636. !(pCD->clientState & UNSEEN_STATE) &&
  637. (pCD->inputFocusModel ||
  638. (pCD->protocolFlags & PROTOCOL_WM_TAKE_FOCUS)))))
  639. {
  640. Do_Focus_Key (pCD, GetTimestamp() , ALWAYS_SET_FOCUS);
  641. }
  642. else if ((pCD->inputMode == MWM_INPUT_SYSTEM_MODAL) ||
  643. (wmGD.keyboardFocus && IS_APP_MODALIZED(wmGD.keyboardFocus)))
  644. {
  645. Do_Focus_Key ((ClientData *)NULL, GetTimestamp() , ALWAYS_SET_FOCUS);
  646. }
  647. if (smAckState == SM_START_ACK)
  648. {
  649. SendClientMsg( wmGD.dtSmWindow, (long) wmGD.xa_DT_SM_WM_PROTOCOL,
  650. (long) wmGD.xa_DT_WM_WINDOW_ACK,
  651. CurrentTime, NULL, 0);
  652. }
  653. /*
  654. * Free the initial property list. This will force
  655. * reads of properties that change after the initial
  656. * management (see HasProperty() function.)
  657. */
  658. DiscardInitialPropertyList (pCD);
  659. CheckPushRecallClient (pCD);
  660. } /* END OF FUNCTION ManageWindow */
  661. /*************************************<->*************************************
  662. *
  663. * UnManageWindow (pCD)
  664. *
  665. *
  666. * Description:
  667. * -----------
  668. * This function removes a top-level client window and it's transients
  669. * from the set of windows that is managed by the window manager.
  670. *
  671. *
  672. * Inputs:
  673. * ------
  674. * pCD - pointer to client data of window to unmanage
  675. *
  676. *************************************<->***********************************/
  677. void UnManageWindow (ClientData *pCD)
  678. {
  679. if (pCD->pECD)
  680. {
  681. WmFpEmbeddedClientData *pECD;
  682. pECD = (WmFpEmbeddedClientData *) pCD->pECD;
  683. XtRemoveEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
  684. (SubstructureRedirectMask | SubstructureNotifyMask),
  685. False,
  686. (XtEventHandler)HandleSubstructEvents,
  687. (XtPointer)(pCD));
  688. pECD->pCD = NULL;
  689. UpdateEmbeddedClientsProperty (pCD->pSD);
  690. }
  691. if (pCD->pPRCD)
  692. {
  693. WmFpPushRecallClientData *pPRCD;
  694. int j;
  695. pPRCD = (WmFpPushRecallClientData *) pCD->pSD->pPRCD;
  696. for (j = 0;
  697. j < pCD->pSD->numPushRecallClients;
  698. j++, pPRCD++)
  699. {
  700. /*
  701. * Clean out all slots used by this client.
  702. */
  703. if ((!strcmp ((char *)pCD->clientName,
  704. (char *)(pPRCD->pchResName))) &&
  705. (pPRCD->pCD == pCD))
  706. {
  707. pPRCD->pCD = NULL;
  708. }
  709. }
  710. pCD->pPRCD = NULL;
  711. }
  712. /*
  713. * Withdraw all the transient children of this window.
  714. */
  715. if (pCD->transientChildren != NULL)
  716. {
  717. WithdrawTransientChildren (pCD);
  718. }
  719. /*
  720. * If this is a transient window, then delete it from the leader's
  721. * list of transients.
  722. */
  723. if (pCD->transientLeader)
  724. {
  725. DeleteTransient (pCD);
  726. /* If this was a modal dialog box, then replay the event. */
  727. if ( wmGD.replayEnterEvent )
  728. {
  729. XPutBackEvent( DISPLAY, (XEvent*)&wmGD.savedEnterEvent );
  730. /* Reset event flag to false */
  731. wmGD.replayEnterEvent = False;
  732. }
  733. }
  734. /*
  735. * Withdraw this window
  736. */
  737. WithdrawWindow (pCD);
  738. } /* END OF FUNCTION UnManageWindow */
  739. /*************************************<->*************************************
  740. *
  741. * WithdrawTransientChildren (pCD)
  742. *
  743. *
  744. * Description:
  745. * -----------
  746. * This function withdraws all transient children of the specified window.
  747. *
  748. *
  749. * Inputs:
  750. * ------
  751. * pCD = pointer to client data of the leader of the transient tree.
  752. *
  753. *************************************<->***********************************/
  754. void WithdrawTransientChildren (ClientData *pCD)
  755. {
  756. ClientData *pcdNext;
  757. ClientData *pcdThis;
  758. pcdNext = pCD->transientChildren;
  759. while (pcdNext)
  760. {
  761. if (pcdNext->transientChildren)
  762. {
  763. WithdrawTransientChildren (pcdNext);
  764. }
  765. pcdThis = pcdNext;
  766. pcdNext = pcdThis->transientSiblings;
  767. DeleteTransient(pcdThis);
  768. WithdrawWindow (pcdThis);
  769. }
  770. } /* END OF FUNCTION WithdrawTransientChildren */
  771. /*************************************<->*************************************
  772. *
  773. * WithdrawWindow (pCD)
  774. *
  775. *
  776. * Description:
  777. * -----------
  778. * This function removes a top-level client window from the set of windows
  779. * that is managed by the window manager. All window manager resources
  780. * associtated with the client window are freed up (possibly cached for
  781. * reuse). Any custom system menu is destroyed.
  782. *
  783. *
  784. * Inputs:
  785. * ------
  786. * pCD - pointer to client data of window to withdraw
  787. *
  788. *************************************<->***********************************/
  789. void WithdrawWindow (ClientData *pCD)
  790. {
  791. int x;
  792. int y;
  793. int i;
  794. XWindowChanges xwc;
  795. /*
  796. * Put the client window into a withdrawn state:
  797. *
  798. * - remove the icon/client window from the screen
  799. * - make sure the input focus no longer is associted with the window
  800. * - free the icon placement (if necessary)
  801. */
  802. SetClientWsIndex (pCD);
  803. if (!(pCD->clientFlags & WM_INITIALIZATION))
  804. {
  805. if (!pCD->transientLeader)
  806. {
  807. DeleteClientFromList (pCD->pSD->pActiveWS, pCD);
  808. }
  809. ResetWithdrawnFocii (pCD);
  810. if (pCD->clientState & MINIMIZED_STATE)
  811. {
  812. if (wmGD.iconAutoPlace && (!(P_ICON_BOX(pCD))))
  813. {
  814. WmWorkspaceData *pWsTmp;
  815. WsClientData *pWsc;
  816. int j;
  817. /*
  818. * Clean up icon placement data in all inhabited
  819. * workspaces
  820. */
  821. for (j = 0; j< pCD->numInhabited; j++)
  822. {
  823. pWsc = &(pCD->pWsList[j]);
  824. if (pWsc->iconPlace != NO_ICON_PLACE)
  825. {
  826. if ((pWsTmp=GetWorkspaceData(pCD->pSD, pWsc->wsID)))
  827. {
  828. pWsTmp->IPData.placeList[pWsc->iconPlace].pCD
  829. = NULL;
  830. }
  831. }
  832. }
  833. }
  834. if (ICON_FRAME_WIN(pCD))
  835. {
  836. XUnmapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
  837. }
  838. XFlush (DISPLAY);
  839. }
  840. else if ((pCD->clientState == NORMAL_STATE) ||
  841. (pCD->clientState == MAXIMIZED_STATE))
  842. {
  843. XUnmapWindow (DISPLAY, pCD->clientFrameWin);
  844. XFlush (DISPLAY);
  845. }
  846. }
  847. /*
  848. * Clean up the workspace presence dialog if it's
  849. * connected to this client.
  850. */
  851. if ((pCD->pSD->presence.shellW) &&
  852. (pCD->pSD->presence.pCDforClient == pCD))
  853. {
  854. if (pCD->pSD->presence.onScreen)
  855. {
  856. HidePresenceBox (pCD->pSD, True);
  857. }
  858. pCD->pSD->presence.pCDforClient = NULL;
  859. }
  860. InstantTitleHideDialog (pCD);
  861. /*
  862. * Check to see if the window is being unmanaged because the window
  863. * was destroyed.
  864. */
  865. if (!(pCD->clientFlags & CLIENT_DESTROYED))
  866. {
  867. XEvent eventReturn;
  868. if (XCheckTypedWindowEvent (DISPLAY, pCD->clientBaseWin, DestroyNotify,
  869. &eventReturn))
  870. {
  871. pCD->clientFlags |= CLIENT_DESTROYED;
  872. }
  873. }
  874. /*
  875. * Reparent the client window back to root if the window has been
  876. * reparented by the window manager. Remove the window from the
  877. * window managers save-set if necessary.
  878. */
  879. if ((pCD->clientFlags & CLIENT_REPARENTED) &&
  880. !(pCD->clientFlags & CLIENT_DESTROYED))
  881. {
  882. SetWMState (pCD->client, WithdrawnSTATE,
  883. pCD->pWsList[0].iconFrameWin);
  884. if (pCD->maxConfig)
  885. {
  886. x = pCD->maxX;
  887. y = pCD->maxY;
  888. }
  889. else
  890. {
  891. int xoff, yoff;
  892. if(wmGD.positionIsFrame)
  893. {
  894. CalculateGravityOffset (pCD, &xoff, &yoff);
  895. x = pCD->clientX - xoff;
  896. y = pCD->clientY - yoff;
  897. }
  898. else
  899. {
  900. x = pCD->clientX;
  901. y = pCD->clientY;
  902. }
  903. }
  904. XDeleteProperty (DISPLAY, pCD->client, wmGD.xa__NET_WM_STATE);
  905. XDeleteProperty (DISPLAY, pCD->client,
  906. wmGD.xa_PREMATURE_XCLIENTMESSAGEEVENT_LIST);
  907. XUnmapWindow (DISPLAY, pCD->client);
  908. XReparentWindow (DISPLAY, pCD->client, ROOT_FOR_CLIENT(pCD), x, y);
  909. /* give the window back it's X border */
  910. xwc.border_width = pCD->xBorderWidth;
  911. XConfigureWindow(DISPLAY, pCD->client, CWBorderWidth, &xwc);
  912. if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
  913. {
  914. XUnmapWindow (DISPLAY, pCD->iconWindow);
  915. XReparentWindow (DISPLAY, pCD->iconWindow, ROOT_FOR_CLIENT(pCD),
  916. pCD->pWsList[0].iconX, pCD->pWsList[0].iconY);
  917. }
  918. }
  919. if ((pCD->clientFlags & CLIENT_IN_SAVE_SET) &&
  920. !(pCD->clientFlags & CLIENT_DESTROYED))
  921. {
  922. XRemoveFromSaveSet (DISPLAY, pCD->client);
  923. if (pCD->iconWindow && (pCD->clientFlags & ICON_IN_SAVE_SET))
  924. {
  925. XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
  926. }
  927. }
  928. /*
  929. * Free a custom system menu if one was created.
  930. */
  931. FreeCustomMenuSpec (pCD->systemMenuSpec);
  932. /*
  933. * Free the client window frame:
  934. */
  935. if (pCD->clientFrameWin)
  936. {
  937. FreeClientFrame (pCD);
  938. }
  939. /*
  940. * Free the icon associated with the client window:
  941. */
  942. if ((pCD->iconFlags & ICON_HINTS_PIXMAP) && pCD->iconPixmap)
  943. {
  944. XFreePixmap (DISPLAY, pCD->iconPixmap);
  945. }
  946. if ((pCD->numInhabited > 0) && ICON_FRAME_WIN(pCD))
  947. {
  948. FreeIcon (pCD);
  949. }
  950. /*
  951. * Free up the client protocol list:
  952. */
  953. if (pCD->clientProtocols)
  954. {
  955. XtFree ((char *)pCD->clientProtocols);
  956. }
  957. /*
  958. * Free up the mwm messages list:
  959. */
  960. if (pCD->mwmMessages)
  961. {
  962. XtFree ((char *)pCD->mwmMessages);
  963. }
  964. /*
  965. * Delete client window manager timers:
  966. */
  967. DeleteClientWmTimers (pCD);
  968. /*
  969. * Free up window context associations.
  970. */
  971. DeleteClientContext (pCD);
  972. /*
  973. * Count backward for efficiency --
  974. * removes from end of list.
  975. */
  976. for (i = pCD->numInhabited - 1; i >= 0; i--)
  977. {
  978. TakeClientOutOfWorkspace (
  979. GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID),
  980. pCD);
  981. }
  982. /*
  983. * Free up window manager resources:
  984. */
  985. if (!(pCD->clientFlags & CLIENT_WM_CLIENTS))
  986. {
  987. if (pCD->clientName)
  988. {
  989. XFree ((char *) (pCD->clientName));
  990. }
  991. if (pCD->clientClass)
  992. {
  993. XFree ((char *) (pCD->clientClass));
  994. }
  995. }
  996. if ((pCD->clientFlags & CLIENT_HINTS_TITLE) && pCD->clientTitle)
  997. {
  998. XmStringFree (pCD->clientTitle);
  999. }
  1000. if ((pCD->iconFlags & ICON_HINTS_TITLE) && pCD->iconTitle)
  1001. {
  1002. XmStringFree (pCD->iconTitle);
  1003. }
  1004. if (pCD->instantTitle)
  1005. {
  1006. XmStringFree (pCD->instantTitle);
  1007. }
  1008. if (pCD->clientCmapCount > 0)
  1009. {
  1010. for (i = 0; i < pCD->clientCmapCount; i++)
  1011. {
  1012. if (pCD->cmapWindows[i] != pCD->client)
  1013. {
  1014. #ifndef IBM_169380
  1015. RemoveColormapWindowReference(pCD, pCD->cmapWindows[i]);
  1016. #else
  1017. XDeleteContext (DISPLAY, pCD->cmapWindows[i],
  1018. wmGD.windowContextType);
  1019. #endif
  1020. }
  1021. }
  1022. XtFree ((char *) (pCD->cmapWindows));
  1023. XtFree ((char *) (pCD->clientCmapList));
  1024. XtFree ((char *) (pCD->clientCmapFlags));
  1025. }
  1026. /*
  1027. * Insure list of initial properties has been freed.
  1028. */
  1029. DiscardInitialPropertyList (pCD);
  1030. /*
  1031. * free up list of workspace specific data
  1032. */
  1033. if ((pCD)->pWsList)
  1034. {
  1035. XtFree ((char *) (pCD->pWsList));
  1036. }
  1037. /*
  1038. * free up workspace hints
  1039. */
  1040. if (pCD->pWorkspaceHints)
  1041. {
  1042. XtFree ((char *)pCD->pWorkspaceHints);
  1043. }
  1044. if (pCD->smClientID)
  1045. XFree (pCD->smClientID);
  1046. /*
  1047. * Clean up references to this data before we free it.
  1048. */
  1049. if (wmGD.menuClient == pCD) {
  1050. wmGD.menuClient = NULL;
  1051. }
  1052. if (wmGD.gadgetClient == pCD) {
  1053. wmGD.gadgetClient = NULL;
  1054. wmGD.gadgetDepressed = 0;
  1055. }
  1056. if (wmGD.clickData.pCD == pCD) {
  1057. wmGD.clickData.pCD = NULL;
  1058. }
  1059. if (wmGD.nextKeyboardFocus == pCD)
  1060. wmGD.nextKeyboardFocus = NULL;
  1061. if (wmGD.keyboardFocus == pCD)
  1062. wmGD.keyboardFocus = NULL;
  1063. /*
  1064. * Fix for 5325 - Delete reference by dirty stack
  1065. */
  1066. ClearDirtyStackEntry(pCD);
  1067. XtFree ((char *)pCD);
  1068. } /* END OF FUNCTION WithdrawWindow */
  1069. /*************************************<->*************************************
  1070. *
  1071. * DeleteClientContext (pCD)
  1072. *
  1073. *
  1074. * Description:
  1075. * -----------
  1076. * This function deletes the client from the X context manager
  1077. *
  1078. *
  1079. * Inputs:
  1080. * ------
  1081. * pCD - pointer to client data
  1082. *
  1083. * Outputs:
  1084. * -------
  1085. *
  1086. * Comments:
  1087. * --------
  1088. *
  1089. *************************************<->***********************************/
  1090. void DeleteClientContext (ClientData *pCD)
  1091. {
  1092. /*
  1093. * Free up window context associations. The context for the client
  1094. * window is always set if there is a client data structure.
  1095. */
  1096. XDeleteContext (DISPLAY, pCD->client, wmGD.windowContextType);
  1097. if (pCD->clientFlags & CLIENT_CONTEXT_SAVED)
  1098. {
  1099. XDeleteContext (DISPLAY, pCD->clientFrameWin, wmGD.windowContextType);
  1100. XDeleteContext (DISPLAY, pCD->clientBaseWin, wmGD.windowContextType);
  1101. if (DECOUPLE_TITLE_APPEARANCE(pCD))
  1102. {
  1103. XDeleteContext (DISPLAY, pCD->clientTitleWin,
  1104. wmGD.windowContextType);
  1105. }
  1106. if (ICON_FRAME_WIN(pCD))
  1107. {
  1108. int k;
  1109. for (k=0; k < pCD->numInhabited; k++)
  1110. {
  1111. XDeleteContext (DISPLAY, pCD->pWsList[k].iconFrameWin,
  1112. wmGD.windowContextType);
  1113. }
  1114. }
  1115. pCD->clientFlags &= ~CLIENT_CONTEXT_SAVED;
  1116. }
  1117. } /* END OF FUNCTION DeleteClientContext */
  1118. /*************************************<->*************************************
  1119. *
  1120. * ResetWitdrawnFocii (pCD)
  1121. *
  1122. *
  1123. * Description:
  1124. * -----------
  1125. * This function resets the various types of focus if they are set to a
  1126. * window being withdrawn.
  1127. *
  1128. *
  1129. *
  1130. * Inputs:
  1131. * ------
  1132. * pCD - pointer to client data
  1133. *
  1134. * Outputs:
  1135. * -------
  1136. *
  1137. * Comments:
  1138. * --------
  1139. *
  1140. *************************************<->***********************************/
  1141. void ResetWithdrawnFocii (ClientData *pCD)
  1142. {
  1143. if ((wmGD.keyboardFocus == pCD) ||
  1144. /* BEGIN fix for CDExc21090 */
  1145. ((wmGD.keyboardFocus == (ClientData *)NULL) &&
  1146. (wmGD.nextKeyboardFocus == pCD) &&
  1147. (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)))
  1148. /* END fix for CDExc21090 */
  1149. {
  1150. if (wmGD.autoKeyFocus &&
  1151. (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
  1152. {
  1153. /* local hack: if we've already received a map for a new
  1154. ** focus window, be sure to use wmGD.nextKeyboardFocus; otherwise
  1155. ** AutoResetKeyFocus chooses an essentially arbitrary window to
  1156. ** set focus to.
  1157. */
  1158. if (wmGD.nextKeyboardFocus == pCD)
  1159. AutoResetKeyFocus (pCD, GetTimestamp());
  1160. else
  1161. Do_Focus_Key ((ClientData *)wmGD.nextKeyboardFocus,
  1162. GetTimestamp(), ALWAYS_SET_FOCUS);
  1163. }
  1164. else
  1165. {
  1166. /*
  1167. * Set the focus to the default state if the focus is not in
  1168. * the process of being set (i.e. a FocusIn event will be
  1169. * coming along shortly.
  1170. */
  1171. if (wmGD.nextKeyboardFocus == wmGD.keyboardFocus)
  1172. {
  1173. Do_Focus_Key ((ClientData *)NULL, GetTimestamp(),
  1174. ALWAYS_SET_FOCUS | WORKSPACE_IF_NULL);
  1175. }
  1176. }
  1177. SetKeyboardFocus ((ClientData *)NULL, 0);
  1178. }
  1179. if (((pCD->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL) ||
  1180. (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)) &&
  1181. (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER))
  1182. {
  1183. /*
  1184. * Repair the focus if an application modal dialog went
  1185. * away. We may not see an enter event and have the focus
  1186. * set to the wrong place.
  1187. */
  1188. RepairFocus ();
  1189. }
  1190. if (wmGD.nextKeyboardFocus == pCD)
  1191. {
  1192. wmGD.nextKeyboardFocus = NULL;
  1193. }
  1194. if (ACTIVE_PSD->colormapFocus == pCD)
  1195. {
  1196. SetColormapFocus (ACTIVE_PSD, (ClientData *)NULL);
  1197. }
  1198. } /* END OF FUNCTION ResetWithdrawnFocii */
  1199. /*************************************<->*************************************
  1200. *
  1201. * FreeClientFrame (pCD)
  1202. *
  1203. *
  1204. * Description:
  1205. * -----------
  1206. * This function frees up frame windows and associated resources.
  1207. *
  1208. *
  1209. * Inputs:
  1210. * ------
  1211. * pCD - pointer to client data
  1212. *
  1213. *************************************<->***********************************/
  1214. void FreeClientFrame (ClientData *pCD)
  1215. {
  1216. if (pCD->pclientTopShadows) {
  1217. FreeRList (pCD->pclientTopShadows);
  1218. pCD->pclientTopShadows = NULL;
  1219. }
  1220. if (pCD->pclientBottomShadows) {
  1221. FreeRList (pCD->pclientBottomShadows);
  1222. pCD->pclientBottomShadows = NULL;
  1223. }
  1224. if (pCD->pclientTitleTopShadows) {
  1225. FreeRList (pCD->pclientTitleTopShadows);
  1226. pCD->pclientTitleTopShadows = NULL;
  1227. }
  1228. if (pCD->pclientTitleBottomShadows) {
  1229. FreeRList (pCD->pclientTitleBottomShadows);
  1230. pCD->pclientTitleBottomShadows = NULL;
  1231. }
  1232. if (pCD->pclientMatteTopShadows) {
  1233. FreeRList (pCD->pclientMatteTopShadows);
  1234. pCD->pclientMatteTopShadows = NULL;
  1235. }
  1236. if (pCD->pclientMatteBottomShadows) {
  1237. FreeRList (pCD->pclientMatteBottomShadows);
  1238. pCD->pclientMatteBottomShadows = NULL;
  1239. }
  1240. if (pCD->pTitleGadgets) {
  1241. XtFree ((char *)pCD->pTitleGadgets);
  1242. pCD->pTitleGadgets = NULL;
  1243. pCD->cTitleGadgets = 0;
  1244. }
  1245. if (pCD->pResizeGadgets) {
  1246. XtFree ((char *)pCD->pResizeGadgets);
  1247. pCD->pResizeGadgets = NULL;
  1248. }
  1249. /* destroy frame window & all children */
  1250. XDestroyWindow (DISPLAY, pCD->clientFrameWin);
  1251. } /* END OF FUNCTION FreeClientFrame */
  1252. /*************************************<->*************************************
  1253. *
  1254. * FreeIcon (pCD)
  1255. *
  1256. *
  1257. * Description:
  1258. * -----------
  1259. * This function frees up icon windows and associated resources.
  1260. *
  1261. *
  1262. * Inputs:
  1263. * ------
  1264. * pCD - pointer to client data
  1265. *
  1266. *************************************<->***********************************/
  1267. void FreeIcon (ClientData *pCD)
  1268. {
  1269. WmWorkspaceData *pWsTmp;
  1270. int i;
  1271. if (pCD->piconTopShadows) {
  1272. FreeRList (pCD->piconTopShadows);
  1273. pCD->piconTopShadows = NULL;
  1274. }
  1275. if (pCD->piconBottomShadows) {
  1276. FreeRList (pCD->piconBottomShadows);
  1277. pCD->piconBottomShadows = NULL;
  1278. }
  1279. /*
  1280. * destroy frame window & all children
  1281. */
  1282. if ((pCD->pSD->useIconBox) && pCD->pWsList[0].pIconBox)
  1283. {
  1284. /*
  1285. * We're using icon boxes and it's in at least one ...
  1286. * Delete from all workspaces we live in
  1287. */
  1288. for (i = 0; i< pCD->numInhabited; i++)
  1289. {
  1290. if ((pWsTmp = GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID)))
  1291. {
  1292. DeleteIconFromBox (pWsTmp->pIconBox, pCD);
  1293. }
  1294. }
  1295. }
  1296. else
  1297. {
  1298. /* only one window, so destroying its first reference will
  1299. * clean it up adequately
  1300. */
  1301. if (pCD->pWsList[0].iconFrameWin)
  1302. {
  1303. XDestroyWindow (DISPLAY, pCD->pWsList[0].iconFrameWin);
  1304. }
  1305. }
  1306. } /* END OF FUNCTION FreeIcon */
  1307. /*************************************<->*************************************
  1308. *
  1309. * WithdrawDialog (dialogboxW)
  1310. *
  1311. *
  1312. * Description:
  1313. * -----------
  1314. * This function removes a DialogBox widget "client" from the set of windows
  1315. * that are managed by the window manager.
  1316. *
  1317. *
  1318. * Inputs:
  1319. * ------
  1320. * dialogboxW = DialogBox widget to withdraw.
  1321. *
  1322. * Comments:
  1323. * --------
  1324. * Does not maintain the WM_STATE property on the dialog "client".
  1325. *
  1326. *************************************<->***********************************/
  1327. void WithdrawDialog (Widget dialogboxW)
  1328. {
  1329. int i;
  1330. ClientData *pCD = NULL;
  1331. /*
  1332. * Get the dialog shell window client data.
  1333. */
  1334. if (XFindContext (DISPLAY, XtWindow (XtParent (dialogboxW)),
  1335. wmGD.windowContextType, (caddr_t *)&pCD))
  1336. return;
  1337. XtUnmanageChild (dialogboxW);
  1338. DeleteClientFromList (ACTIVE_WS, pCD);
  1339. /* TakeClientOutOfWorkspace (ACTIVE_WS, pCD); */
  1340. /*
  1341. * Count backward for efficiency --
  1342. * removes from end of list.
  1343. */
  1344. for (i = pCD->numInhabited - 1; i >= 0; i--)
  1345. {
  1346. TakeClientOutOfWorkspace (
  1347. GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID),
  1348. pCD);
  1349. }
  1350. ResetWithdrawnFocii (pCD);
  1351. XUnmapWindow (DISPLAY, pCD->clientFrameWin);
  1352. } /* END OF FUNCTION WithdrawDialog */
  1353. /*************************************<->*************************************
  1354. *
  1355. * ReManageDialog (pSD, dialogboxW)
  1356. *
  1357. *
  1358. * Description:
  1359. * -----------
  1360. * This function remanages a DialogBox "client" that was unmanaged via
  1361. * WithdrawDialog ().
  1362. *
  1363. *
  1364. * Inputs:
  1365. * ------
  1366. * pSD = pointer to screen data
  1367. * dialogboxW = DialogBox widget to remanage.
  1368. *
  1369. *
  1370. * Outputs:
  1371. * -------
  1372. * Does not maintain the WM_STATE property on the dialog "client".
  1373. *
  1374. *************************************<->***********************************/
  1375. void ReManageDialog (WmScreenData *pSD, Widget dialogboxW)
  1376. {
  1377. ClientData *pCD = NULL;
  1378. /*
  1379. * Get the dialog shell window client data.
  1380. */
  1381. if (XFindContext (DISPLAY, XtWindow (XtParent (dialogboxW)),
  1382. wmGD.windowContextType, (caddr_t *)&pCD))
  1383. return;
  1384. /*
  1385. * The order is important here:
  1386. */
  1387. /*
  1388. * Put system modal windows in all workspaces to
  1389. * avoid the race condition of the window coming up
  1390. * just as the user switches workspaces OR when
  1391. * the window is up and a user switces workspaces
  1392. * with a key binding. We may want to eventually short
  1393. * circuit F_Functions any time there is a modal
  1394. * window up, but for now, we will just make sure
  1395. * the modal window appears in all workspaces
  1396. */
  1397. pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
  1398. F_AddToAllWorkspaces(0, pCD, 0);
  1399. pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
  1400. if (pSD->clientList)
  1401. {
  1402. StackWindow (pSD->pActiveWS, &pCD->clientEntry,
  1403. TRUE, (ClientListEntry *) NULL);
  1404. }
  1405. AddClientToList (pSD->pActiveWS, pCD, True /*on top*/);
  1406. XMapWindow (DISPLAY, pCD->clientFrameWin);
  1407. XtManageChild (dialogboxW);
  1408. if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
  1409. {
  1410. Do_Focus_Key (pCD, GetTimestamp() , ALWAYS_SET_FOCUS);
  1411. }
  1412. } /* END OF FUNCTION ReManageDialog */
  1413. /*************************************<->*************************************
  1414. *
  1415. * RegisterEmbeddedClients (wPanelist, pECD, count)
  1416. *
  1417. *
  1418. * Description:
  1419. * -----------
  1420. * This function registers a list of clients to be embedded in the
  1421. * front panel subsystem.
  1422. *
  1423. *
  1424. * Inputs:
  1425. * ------
  1426. * wPanelist = front panel object (widget)
  1427. * pECD = pointer to list of data for clients to embed
  1428. * count = number of elements in the list
  1429. *
  1430. *
  1431. * Outputs:
  1432. * -------
  1433. *
  1434. *************************************<->***********************************/
  1435. void
  1436. RegisterEmbeddedClients (
  1437. Widget wPanelist,
  1438. WmFpEmbeddedClientList pECD,
  1439. int count)
  1440. {
  1441. WmScreenData *pSD;
  1442. int i;
  1443. for (i= 0; i < wmGD.numScreens; i++)
  1444. {
  1445. pSD = &(wmGD.Screens[i]);
  1446. if (pSD->managed)
  1447. {
  1448. if (pSD->wPanelist == wPanelist)
  1449. break;
  1450. }
  1451. }
  1452. if (i < wmGD.numScreens)
  1453. {
  1454. pSD->pECD = (struct _WmFpEmbeddedClientData *) pECD;
  1455. pSD->numEmbeddedClients = count;
  1456. }
  1457. #ifdef DEBUG
  1458. else
  1459. {
  1460. fprintf (stderr, "Couldn't match wPanelist to screen data\n");
  1461. }
  1462. #endif /* DEBUG */
  1463. } /* END OF FUNCTION RegisterEmbeddedClients */
  1464. #define LTT_INCREMENT 16
  1465. /*************************************<->*************************************
  1466. *
  1467. * ListTransientSubtree (pCD, ppWins, pSize, pCount)
  1468. *
  1469. *
  1470. * Description:
  1471. * -----------
  1472. * This function returns the list of windows in a transient window
  1473. * tree.
  1474. *
  1475. *
  1476. * Inputs:
  1477. * ------
  1478. * pCD - pointer to client data of a window.
  1479. * ppWins - address of a pointer to a list of windows
  1480. * (this must be in the heap -- XtMalloc).
  1481. * pSize - address of variable with size of list
  1482. * pCount - address of variable with number of windows in list
  1483. *
  1484. * Outputs:
  1485. * -------
  1486. * *ppWins - may point to a new area of memory if list grows
  1487. * *pSize - if list has to grow, this may be bigger
  1488. * *pCount - number of windows in the list
  1489. *
  1490. * Comments
  1491. * --------
  1492. * The list should be freed when done with XtFree().
  1493. *
  1494. *************************************<->***********************************/
  1495. static void
  1496. ListTransientSubtree (
  1497. ClientData *pCD,
  1498. Window **ppWins,
  1499. int *pSize,
  1500. int *pCount)
  1501. {
  1502. /*
  1503. * Check size
  1504. */
  1505. if (*pCount == *pSize)
  1506. {
  1507. *pSize += LTT_INCREMENT;
  1508. *ppWins = (Window *)
  1509. XtRealloc ((char *) *ppWins, (*pSize * sizeof(Window)));
  1510. }
  1511. /*
  1512. * Add this window to the list
  1513. */
  1514. (*ppWins)[*pCount] = pCD->client;
  1515. *pCount += 1;
  1516. /*
  1517. * Add siblings
  1518. */
  1519. if (pCD->transientSiblings)
  1520. ListTransientSubtree (pCD->transientSiblings, ppWins, pSize, pCount);
  1521. /*
  1522. * Add children
  1523. */
  1524. if (pCD->transientChildren)
  1525. ListTransientSubtree (pCD->transientChildren, ppWins, pSize, pCount);
  1526. } /* END OF FUNCTION ListTransientSubtree */
  1527. /*************************************<->*************************************
  1528. *
  1529. * ListTransientTree (pCD)
  1530. *
  1531. *
  1532. * Description:
  1533. * -----------
  1534. * This function returns the list of windows in a transient window
  1535. * tree.
  1536. *
  1537. *
  1538. * Inputs:
  1539. * ------
  1540. * pCD - pointer to client data of a primary window.
  1541. *
  1542. * Outputs:
  1543. * -------
  1544. * none
  1545. *
  1546. * Comments
  1547. * --------
  1548. * The list should be freed when done with XtFree().
  1549. *
  1550. *************************************<->***********************************/
  1551. static Window *
  1552. ListTransientTree (
  1553. ClientData *pCD)
  1554. {
  1555. Window *pWins;
  1556. int count;
  1557. int iSize;
  1558. /*
  1559. * Initial allocation
  1560. */
  1561. iSize = LTT_INCREMENT;
  1562. pWins = (Window *) XtMalloc (iSize * sizeof(Window));
  1563. count = 0;
  1564. /*
  1565. * Add this window to the list
  1566. */
  1567. ListTransientSubtree (pCD, &pWins, &iSize, &count);
  1568. /*
  1569. * Add terminator to end of window list
  1570. */
  1571. if (count == iSize)
  1572. {
  1573. iSize += LTT_INCREMENT;
  1574. pWins = (Window *)
  1575. XtRealloc ((char *)pWins, (iSize * sizeof(Window)));
  1576. }
  1577. pWins[count++] = None;
  1578. /*
  1579. * Return the list of windows found
  1580. */
  1581. return (pWins);
  1582. } /* END OF FUNCTION ListTransientTree */
  1583. /*************************************<->*************************************
  1584. *
  1585. * ReManageWindow (pCD)
  1586. *
  1587. *
  1588. * Description:
  1589. * -----------
  1590. * This function unmanages and remanages a window and it's associated
  1591. * transients.
  1592. *
  1593. *
  1594. * Inputs:
  1595. * ------
  1596. * pCD - pointer to client data of a primary window.
  1597. *
  1598. * Outputs:
  1599. * -------
  1600. * none
  1601. *
  1602. * Comments
  1603. * --------
  1604. * The pointer pCD is invalid after calling this function -- a
  1605. * side-effect of unmanaging the client before remanaging it.
  1606. *
  1607. *************************************<->***********************************/
  1608. static void
  1609. ReManageWindow (
  1610. ClientData *pCD)
  1611. {
  1612. long manageFlags = MANAGEW_NORMAL;
  1613. Window *pWins, *pW;
  1614. WmScreenData *pSD;
  1615. /*
  1616. * Get the list of windows in the transient window tree.
  1617. */
  1618. pWins = ListTransientTree (pCD);
  1619. pSD = pCD->pSD;
  1620. /*
  1621. * Unmanage this window and associated transients
  1622. */
  1623. UnManageWindow (pCD);
  1624. /*** pCD is no longer a valid pointer!!! ***/
  1625. /*
  1626. * Remanage this window and its secondaries
  1627. */
  1628. pW = pWins;
  1629. while (*pW != None)
  1630. {
  1631. ManageWindow (pSD, *pW, manageFlags);
  1632. pW++;
  1633. }
  1634. XtFree ((char *) pWins);
  1635. } /* END OF FUNCTION ReManageWindow */
  1636. /*************************************<->*************************************
  1637. *
  1638. * ScanForEmbeddedClients (pSD)
  1639. *
  1640. *
  1641. * Description:
  1642. * -----------
  1643. * This function scans the managed windows and identifies those that
  1644. * should be embedded clients in the front panel
  1645. *
  1646. *
  1647. * Inputs:
  1648. * ------
  1649. * pSD - pointer to screen data.
  1650. *
  1651. * Outputs:
  1652. * -------
  1653. *
  1654. *************************************<->***********************************/
  1655. void
  1656. ScanForEmbeddedClients (
  1657. WmScreenData *pSD)
  1658. {
  1659. ClientData *pCD;
  1660. ClientListEntry *pCLE;
  1661. WmFpEmbeddedClientData *pECD;
  1662. Boolean bReset;
  1663. /*
  1664. * Search through all the windows we're managing right now to
  1665. * see if any should be embedded in a front/sub panel.
  1666. */
  1667. pCLE = pSD->clientList;
  1668. bReset = False;
  1669. while (pCLE != NULL)
  1670. {
  1671. /*
  1672. * See if this is an previously unrecognized embedded client
  1673. */
  1674. pCD = pCLE->pCD;
  1675. if ((pCD->pECD == NULL ) && IsEmbeddedClient (pCD, &pECD))
  1676. {
  1677. /*
  1678. * Remanage this window and associated transients
  1679. */
  1680. ReManageWindow (pCD);
  1681. /*
  1682. * At this point pCD is no longer valid and the
  1683. * pSD->clientList has been changed.
  1684. */
  1685. bReset = True;
  1686. }
  1687. /*
  1688. * Test for exit condition
  1689. */
  1690. if (pCLE == pSD->lastClient)
  1691. {
  1692. /*
  1693. * Gone all the way through the list without finding
  1694. * anything -- time to quit
  1695. */
  1696. break;
  1697. }
  1698. else if (bReset)
  1699. {
  1700. /*
  1701. * Remanaging a client restructures the client list.
  1702. * Start over at the beginning.
  1703. */
  1704. bReset = False;
  1705. pCLE = pSD->clientList;
  1706. }
  1707. else
  1708. {
  1709. /*
  1710. * Move to next client.
  1711. */
  1712. pCLE = pCLE->nextSibling;
  1713. }
  1714. }
  1715. } /* END OF FUNCTION ScanForEmbeddedClients */
  1716. /*************************************<->*************************************
  1717. *
  1718. * IsEmbeddedClient (pCD, ppECD)
  1719. *
  1720. *
  1721. * Description:
  1722. * -----------
  1723. * This function tests a a client to see if it should be embedded
  1724. * in the front panel.
  1725. *
  1726. *
  1727. * Inputs:
  1728. * ------
  1729. * pCD = ptr to Client Data
  1730. * ppECD = ptr to returned embedded client data ptr
  1731. *
  1732. *
  1733. * Outputs:
  1734. * -------
  1735. * *ppECD = ptr to embedded client data
  1736. *
  1737. *************************************<->***********************************/
  1738. Boolean
  1739. IsEmbeddedClient (ClientData *pCD, WmFpEmbeddedClientData **ppECD)
  1740. {
  1741. WmScreenData *pSD;
  1742. int i;
  1743. Boolean bFoundMatch = False;
  1744. WmFpEmbeddedClientData *pECD;
  1745. pSD = pCD->pSD;
  1746. pECD = (WmFpEmbeddedClientData *) pSD->pECD;
  1747. for (i = 0; i < pSD->numEmbeddedClients && !bFoundMatch; i++, pECD++)
  1748. {
  1749. /*
  1750. * It's an embedded client if
  1751. * the resource name matches a slot and
  1752. * it's not a subpanel and
  1753. * the slot isn't already filled.
  1754. */
  1755. if ((!strcmp ((char *)pCD->clientName,
  1756. (char *)(pECD->pchResName))) &&
  1757. (!(pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)) &&
  1758. (!pECD->pCD))
  1759. {
  1760. *ppECD = pECD;
  1761. bFoundMatch = True;
  1762. }
  1763. }
  1764. return (bFoundMatch);
  1765. } /* END OF FUNCTION IsEmbeddedClient */
  1766. /******************************<->*************************************
  1767. *
  1768. * ManageEmbeddedClient (pCD, pECD, manageFlags)
  1769. *
  1770. *
  1771. * Description:
  1772. * -----------
  1773. * This is the function that is used to setup a client window
  1774. * in the front panel.
  1775. *
  1776. * Inputs:
  1777. * ------
  1778. * pCD = initialized client data, including window of client that
  1779. * we want to manage.
  1780. * pECD = ptr to embedded client entry for this client
  1781. *
  1782. * manageFlags = additional control information
  1783. *
  1784. * Outputs:
  1785. * -------
  1786. * Returns False if normal client processing needs to be done.
  1787. *
  1788. * Returns True if this client has been embedded directly in the
  1789. * front panel and is NOT to be managed as a normal top level
  1790. * window--no further processing required.
  1791. ******************************<->***********************************/
  1792. Boolean
  1793. ManageEmbeddedClient (
  1794. ClientData *pCD,
  1795. WmFpEmbeddedClientData *pECD,
  1796. long manageFlags)
  1797. {
  1798. XWindowChanges windowChanges;
  1799. unsigned int mask;
  1800. WmFpPushRecallClientData *pPRCD;
  1801. if (!pECD || !pCD)
  1802. {
  1803. return (False);
  1804. }
  1805. /*
  1806. * Add to all workspaces
  1807. */
  1808. pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
  1809. F_AddToAllWorkspaces(0, pCD, 0);
  1810. pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
  1811. /*
  1812. * Set client list entries
  1813. * (in a list by itself)
  1814. */
  1815. pCD->clientEntry.type = NORMAL_STATE;
  1816. pCD->clientEntry.pCD = pCD;
  1817. pCD->clientEntry.nextSibling = NULL;
  1818. pCD->clientEntry.prevSibling = NULL;
  1819. pCD->iconEntry.type = MINIMIZED_STATE;
  1820. pCD->iconEntry.pCD = pCD;
  1821. pCD->iconEntry.nextSibling = NULL;
  1822. pCD->iconEntry.prevSibling = NULL;
  1823. /*
  1824. * Save context for event processing.
  1825. *
  1826. */
  1827. XSaveContext (DISPLAY, pCD->client, wmGD.windowContextType,
  1828. (caddr_t)pCD);
  1829. if (!(pCD->clientFlags & CLIENT_WM_CLIENTS))
  1830. {
  1831. XChangeSaveSet (DISPLAY, pCD->client, SetModeInsert);
  1832. XChangeSaveSet (DISPLAY1, pCD->client, SetModeInsert);
  1833. pCD->clientFlags |= CLIENT_IN_SAVE_SET;
  1834. }
  1835. if (!(manageFlags & MANAGEW_WM_CLIENTS))
  1836. {
  1837. XSync (DISPLAY1, False);
  1838. if (pCD->clientFlags & CLIENT_DESTROYED)
  1839. {
  1840. UnManageWindow (pCD);
  1841. return (True);
  1842. }
  1843. }
  1844. XtAddEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
  1845. (SubstructureRedirectMask | SubstructureNotifyMask),
  1846. False,
  1847. (XtEventHandler)HandleSubstructEvents,
  1848. (XtPointer)(pCD));
  1849. /*
  1850. * Fill in more client data
  1851. */
  1852. pCD->clientX = pECD->x;
  1853. pCD->clientY = pECD->y;
  1854. pCD->clientWidth = pECD->width;
  1855. pCD->clientHeight = pECD->height;
  1856. pCD->clientFrameWin = 0;
  1857. pCD->clientBaseWin = pECD->winParent;
  1858. pECD->pCD = pCD;
  1859. pCD->pECD = (void *) pECD;
  1860. SetClientWsIndex(pCD);
  1861. SetClientWMState (pCD, NormalState, NORMAL_STATE);
  1862. /*
  1863. * Set state on subpanel in case it never gets mapped
  1864. * to prevent session manager from finding an embedded
  1865. * client on its own.
  1866. */
  1867. ForceSubpanelWMState (pECD->winParent);
  1868. XReparentWindow (DISPLAY1, pCD->client,
  1869. pECD->winParent,
  1870. pECD->x, pECD->y);
  1871. pCD->clientFlags |= CLIENT_REPARENTED;
  1872. windowChanges.width = pECD->width;
  1873. windowChanges.height = pECD->height;
  1874. windowChanges.border_width = 0;
  1875. mask = (CWWidth | CWHeight | CWBorderWidth);
  1876. XConfigureWindow (DISPLAY1, pCD->client, mask, &windowChanges);
  1877. XMapWindow (DISPLAY1, pCD->client);
  1878. if (pCD->iconWindow)
  1879. {
  1880. XUnmapWindow (DISPLAY, pCD->iconWindow);
  1881. }
  1882. UpdateEmbeddedClientsProperty (pCD->pSD);
  1883. SendConfigureNotify (pCD);
  1884. if (IsPushRecallClient (pCD, &pPRCD))
  1885. {
  1886. /*
  1887. * There should only be one instance of this
  1888. * client started from a front panel button.
  1889. */
  1890. pPRCD->pCD = pCD;
  1891. pCD->pPRCD = (void *) pPRCD;
  1892. }
  1893. WmStopWaiting();
  1894. return(True); /* successful embedation */
  1895. } /* END OF FUNCTION ManageEmbeddedClient */
  1896. /******************************<->*************************************
  1897. *
  1898. * ReparentEmbeddedClient (pECD, newControl, newWin, x, y, width, height)
  1899. *
  1900. *
  1901. * Description:
  1902. * -----------
  1903. *
  1904. * Inputs:
  1905. * ------
  1906. * pECD = ptr to embedded client entry for this client
  1907. * newControl = widget for new "parent" widget
  1908. * newWin = window ID of window that this embedded client will be
  1909. * a parent of. This is needed in case the control is a
  1910. * gadget.
  1911. * x = x-coord position within newWin where UL corner of the embedded
  1912. * client will go.
  1913. * y = y-coord as described above.
  1914. * width = desired width of embedded client in this new location
  1915. * height = desired height as above.
  1916. *
  1917. *
  1918. * Outputs:
  1919. * -------
  1920. * Returns False if embedded client was is not moved to the new
  1921. * location.
  1922. *
  1923. * Returns True if this client has been reparented to the new
  1924. * control.
  1925. ******************************<->***********************************/
  1926. Boolean
  1927. ReparentEmbeddedClient (
  1928. WmFpEmbeddedClientData *pECD,
  1929. Widget newControl,
  1930. Window newWin,
  1931. int x,
  1932. int y,
  1933. unsigned int width,
  1934. unsigned int height
  1935. )
  1936. {
  1937. XWindowChanges windowChanges;
  1938. unsigned int mask;
  1939. ClientData *pCD;
  1940. /*
  1941. * If we have bogus data or if we're asked
  1942. * to reparent to our current parent, then just
  1943. * say no.
  1944. */
  1945. if ((pECD == NULL) ||
  1946. (pECD->pCD == NULL) ||
  1947. (pECD->winParent == newWin))
  1948. {
  1949. return (False);
  1950. }
  1951. pCD=pECD->pCD;
  1952. /*
  1953. * Need event handler on new parent window?
  1954. */
  1955. if (newWin != pECD->winParent)
  1956. {
  1957. XtRemoveEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
  1958. (SubstructureRedirectMask | SubstructureNotifyMask),
  1959. False,
  1960. (XtEventHandler)HandleSubstructEvents,
  1961. (XtPointer)(pCD));
  1962. XtAddEventHandler(XtWindowToWidget (DISPLAY1, newWin),
  1963. (SubstructureRedirectMask | SubstructureNotifyMask),
  1964. False,
  1965. (XtEventHandler)HandleSubstructEvents,
  1966. (XtPointer)(pCD));
  1967. }
  1968. /*
  1969. * Update embedding and client data
  1970. */
  1971. pECD->wControl = newControl;
  1972. pECD->winParent = newWin;
  1973. pCD->clientX = pECD->x = x;
  1974. pCD->clientY = pECD->y = y;
  1975. pCD->clientWidth = pECD->width = width;
  1976. pCD->clientHeight = pECD->height = height;
  1977. pCD->clientBaseWin = pECD->winParent;
  1978. /*
  1979. * Set state on subpanel in case it never gets mapped
  1980. * to prevent session manager from finding an embedded
  1981. * client on its own.
  1982. */
  1983. ForceSubpanelWMState (pECD->winParent);
  1984. /*
  1985. * Do the actual reparent
  1986. */
  1987. XReparentWindow (DISPLAY1, pCD->client,
  1988. pECD->winParent,
  1989. pECD->x, pECD->y);
  1990. /*
  1991. * Configure the embedded client
  1992. */
  1993. windowChanges.width = pECD->width;
  1994. windowChanges.height = pECD->height;
  1995. windowChanges.border_width = 0;
  1996. mask = (CWWidth | CWHeight | CWBorderWidth);
  1997. XConfigureWindow (DISPLAY1, pCD->client, mask, &windowChanges);
  1998. XMapWindow (DISPLAY1, pCD->client);
  1999. UpdateEmbeddedClientsProperty (pCD->pSD);
  2000. SendConfigureNotify (pCD);
  2001. return(True); /* successful reparent */
  2002. } /* END OF FUNCTION ReparentEmbeddedClient */
  2003. /*************************************<->*************************************
  2004. *
  2005. * ForceSubpanelWMState (win)
  2006. *
  2007. *
  2008. * Description:
  2009. * -----------
  2010. * This function forces a WM_STATE property on a subpanel window
  2011. * so that the session manager doesn't save multiple copies
  2012. * of embedded clients for subpanels that never get mapped.
  2013. *
  2014. *
  2015. * Inputs:
  2016. * ------
  2017. * win = window ID of a subpanel window (not necessarily the top level!)
  2018. *
  2019. *
  2020. * Outputs:
  2021. * -------
  2022. *
  2023. *************************************<->***********************************/
  2024. static void
  2025. ForceSubpanelWMState (Window win)
  2026. {
  2027. ClientData *pCD = NULL;
  2028. Window root, parent;
  2029. Window *children = NULL;
  2030. unsigned int numChildren;
  2031. PropWMState *wmStateProp;
  2032. Boolean bDone = False;
  2033. while (!bDone)
  2034. {
  2035. if (!XQueryTree (DISPLAY, win, &root, &parent,
  2036. &children, &numChildren))
  2037. {
  2038. break;
  2039. }
  2040. if (!XFindContext(DISPLAY, win, wmGD.windowContextType,
  2041. (caddr_t *)&pCD))
  2042. {
  2043. /*
  2044. * Only continue if we're not already managing this subpanel.
  2045. */
  2046. bDone = True;
  2047. }
  2048. else if (parent == root)
  2049. {
  2050. if ((wmStateProp = GetWMState (win)))
  2051. {
  2052. /*
  2053. * Already has a WM_STATE.
  2054. */
  2055. XFree ((char *)wmStateProp);
  2056. }
  2057. else
  2058. {
  2059. /*
  2060. * Add a dummy WM_STATE to foil the session manager
  2061. * search.
  2062. */
  2063. SetWMState (win, WITHDRAWN_STATE, 0);
  2064. }
  2065. bDone = True;
  2066. }
  2067. else
  2068. {
  2069. /* continue ascent up to root */
  2070. win = parent;
  2071. }
  2072. XFree ((char *) children);
  2073. }
  2074. } /* END OF FUNCTION ForceSubpanelWMState */
  2075. /*************************************<->*************************************
  2076. *
  2077. * RegisterPushRecallClients (wPanelist, pPRCD, count)
  2078. *
  2079. *
  2080. * Description:
  2081. * -----------
  2082. * This function registers a list of push_recallclients for the
  2083. * front panel subsystem.
  2084. *
  2085. *
  2086. * Inputs:
  2087. * ------
  2088. * wPanelist = front panel object (widget)
  2089. * pPRCD = pointer to list of data for clients
  2090. * count = number of elements in the list
  2091. *
  2092. *
  2093. * Outputs:
  2094. * -------
  2095. *
  2096. *************************************<->***********************************/
  2097. void
  2098. RegisterPushRecallClients (
  2099. Widget wPanelist,
  2100. WmFpPushRecallClientList pPRCD,
  2101. int count)
  2102. {
  2103. WmScreenData *pSD = NULL;
  2104. int i;
  2105. for (i= 0; i < wmGD.numScreens; i++)
  2106. {
  2107. pSD = &(wmGD.Screens[i]);
  2108. if (pSD->managed)
  2109. {
  2110. if (pSD->wPanelist == wPanelist)
  2111. break;
  2112. }
  2113. }
  2114. if (i < wmGD.numScreens)
  2115. {
  2116. pSD->pPRCD = (struct _WmFpPushRecallClientData *) pPRCD;
  2117. pSD->numPushRecallClients = count;
  2118. }
  2119. #ifdef DEBUG
  2120. else
  2121. {
  2122. fprintf (stderr, "Couldn't match wPanelist to screen data\n");
  2123. }
  2124. #endif /* DEBUG */
  2125. for (i = 0; i < pSD->numPushRecallClients ; i++, pPRCD++)
  2126. {
  2127. /*
  2128. * Initialize data in each slot
  2129. */
  2130. pPRCD->tvTimeout.tv_sec = 0;
  2131. }
  2132. } /* END OF FUNCTION RegisterPushRecallClients */
  2133. /*************************************<->*************************************
  2134. *
  2135. * IsPushRecallClient (pCD, ppPRCD)
  2136. *
  2137. *
  2138. * Description:
  2139. * -----------
  2140. * This function tests a a client to see if it should be embedded
  2141. * in the front panel.
  2142. *
  2143. *
  2144. * Inputs:
  2145. * ------
  2146. * pCD = ptr to Client Data
  2147. * ppPRCD = ptr to returned embedded client data ptr
  2148. *
  2149. *
  2150. * Outputs:
  2151. * -------
  2152. * *ppPRCD = ptr to embedded client data
  2153. *
  2154. *************************************<->***********************************/
  2155. Boolean
  2156. IsPushRecallClient (ClientData *pCD, WmFpPushRecallClientData **ppPRCD)
  2157. {
  2158. WmScreenData *pSD;
  2159. int i;
  2160. Boolean bFoundMatch = False;
  2161. WmFpPushRecallClientData *pPRCD;
  2162. pSD = pCD->pSD;
  2163. pPRCD = (WmFpPushRecallClientData *) pSD->pPRCD;
  2164. for (i = 0; i < pSD->numPushRecallClients && !bFoundMatch; i++, pPRCD++)
  2165. {
  2166. /*
  2167. * It's a push_recall client if the resource name matches
  2168. * a slot and the slot isn't already filled.
  2169. */
  2170. if ((!strcmp ((char *)pCD->clientName,
  2171. (char *)(pPRCD->pchResName))) &&
  2172. (!pPRCD->pCD))
  2173. {
  2174. *ppPRCD = pPRCD;
  2175. bFoundMatch = True;
  2176. }
  2177. }
  2178. return (bFoundMatch);
  2179. } /* END OF FUNCTION IsPushRecallClient */
  2180. /*************************************<->*************************************
  2181. *
  2182. * ScanForPushRecallClients (pSD)
  2183. *
  2184. *
  2185. * Description:
  2186. * -----------
  2187. * This function scans the managed windows and identifies those that
  2188. * should be push recall clients of the front panel
  2189. *
  2190. *
  2191. * Inputs:
  2192. * ------
  2193. * pSD - pointer to screen data.
  2194. *
  2195. * Outputs:
  2196. * -------
  2197. *
  2198. *************************************<->***********************************/
  2199. void
  2200. ScanForPushRecallClients (
  2201. WmScreenData *pSD)
  2202. {
  2203. ClientData *pCD;
  2204. ClientListEntry *pCLE;
  2205. WmFpPushRecallClientData *pPRCD;
  2206. /*
  2207. * Search through all the windows we're managing right now
  2208. */
  2209. pCLE = pSD->clientList;
  2210. while (pCLE != NULL)
  2211. {
  2212. /*
  2213. * See if this is an previously unrecognized push recall client
  2214. */
  2215. pCD = pCLE->pCD;
  2216. if ((pCD->pPRCD == NULL ) && IsPushRecallClient (pCD, &pPRCD))
  2217. {
  2218. CheckPushRecallClient (pCD);
  2219. }
  2220. /*
  2221. * Test for exit condition
  2222. */
  2223. if (pCLE == pSD->lastClient)
  2224. {
  2225. /*
  2226. * Gone all the way through the list without finding
  2227. * anything -- time to quit
  2228. */
  2229. break;
  2230. }
  2231. else
  2232. {
  2233. /*
  2234. * Move to next client.
  2235. */
  2236. pCLE = pCLE->nextSibling;
  2237. }
  2238. }
  2239. } /* END OF FUNCTION ScanForPushRecallClients */
  2240. /******************************<->*************************************
  2241. *
  2242. * static void CheckPushRecallClient (pCD)
  2243. *
  2244. *
  2245. * Description:
  2246. * -----------
  2247. * Checks a client against the list of push recall clients to see
  2248. * if there are any matches. All matches are marked.
  2249. *
  2250. * Inputs:
  2251. * ------
  2252. * pCD - pointer to the Client Data structure
  2253. *
  2254. * Outputs:
  2255. * -------
  2256. *
  2257. * Comments:
  2258. * --------
  2259. *
  2260. ******************************<->***********************************/
  2261. static void
  2262. CheckPushRecallClient(
  2263. ClientData *pCD)
  2264. {
  2265. WmFpPushRecallClientData *pPRCD;
  2266. while (IsPushRecallClient (pCD, &pPRCD))
  2267. {
  2268. /*
  2269. * There should only be one instance of this
  2270. * client started from a front panel button.
  2271. */
  2272. pPRCD->pCD = pCD;
  2273. pPRCD->tvTimeout.tv_sec = 0;
  2274. if (!pCD->pPRCD)
  2275. pCD->pPRCD = (void *) pPRCD;
  2276. }
  2277. }
  2278. /******************************<->*************************************
  2279. *
  2280. * static void HandleSubstructEvents (Widget w, caddr_t pCD, XEvent *event)
  2281. *
  2282. *
  2283. * Description:
  2284. * -----------
  2285. * Causes death of embedded clients to run through UnManageWindow()
  2286. * for proper cleanup.
  2287. *
  2288. * Note there is one of these event handlers instantiated for
  2289. * each live client window in the front panel. Hence, for each
  2290. * live client window death, each of the event handlers gets called
  2291. * once. We need to ensure that we've got the right pCD before
  2292. * calling UnManageWindow() on it.
  2293. *
  2294. *
  2295. * Inputs:
  2296. * ------
  2297. * w - not used
  2298. * pCD - pointer to the Client Data structure
  2299. * event - we only care about UnMapNotify
  2300. *
  2301. * Outputs:
  2302. * -------
  2303. *
  2304. * Comments:
  2305. * --------
  2306. * This routine is called LOTS of times, for all types of events.
  2307. *
  2308. ******************************<->***********************************/
  2309. static void
  2310. HandleSubstructEvents(
  2311. Widget w,
  2312. caddr_t ptr,
  2313. XEvent *event )
  2314. {
  2315. struct _ClientData *pCD = (struct _ClientData *)ptr;
  2316. switch (event->type)
  2317. {
  2318. case UnmapNotify:
  2319. {
  2320. if (pCD->client == event->xunmap.window)
  2321. {
  2322. UnManageWindow (pCD);
  2323. }
  2324. break;
  2325. }
  2326. }
  2327. } /* END OF FUNCTION HandleSubstructEvents */
  2328. /*******************************<->*************************************
  2329. *
  2330. * UpdateEmbeddedClientsProperty (pSD)
  2331. *
  2332. * Description:
  2333. * -----------
  2334. *
  2335. * Inputs:
  2336. * ------
  2337. * pSD - pointer to the screen data
  2338. *
  2339. * Outputs:
  2340. * -------
  2341. * True if successful, False otherwise.
  2342. *
  2343. * Comments:
  2344. * --------
  2345. * The _DT_WORKSPACE_EMBEDDED_CLIENTS property on the
  2346. * root window for the screen will be updated to reflect the
  2347. * current contents of the front panel
  2348. *
  2349. *
  2350. ******************************<->***********************************/
  2351. Boolean
  2352. UpdateEmbeddedClientsProperty(
  2353. WmScreenData *pSD )
  2354. {
  2355. unsigned int numClients = 0;
  2356. Window *pClients = NULL;
  2357. Boolean rval = True;
  2358. int i;
  2359. WmFpEmbeddedClientData *pECD;
  2360. pECD = (WmFpEmbeddedClientData *) pSD->pECD;
  2361. for (i = 0; i < pSD->numEmbeddedClients; i++, pECD++)
  2362. {
  2363. if (pECD->pCD)
  2364. {
  2365. numClients += 1;
  2366. if (!pClients)
  2367. {
  2368. pClients = (Window *) XtMalloc (sizeof(Window));
  2369. }
  2370. else
  2371. {
  2372. pClients = (Window *) XtRealloc ((char *)pClients,
  2373. (numClients * (sizeof(Window))));
  2374. }
  2375. if (!pClients)
  2376. {
  2377. Warning (
  2378. ((char *)GETMESSAGE(4, 17, "Insufficient memory to write _DT_WORKSPACE_EMBEDDED_CLIENTS."))
  2379. );
  2380. rval = False;
  2381. break;
  2382. }
  2383. else
  2384. {
  2385. pClients[numClients-1] = pECD->pCD->client;
  2386. }
  2387. }
  2388. }
  2389. SetEmbeddedClientsProperty (pSD->rootWindow, pClients,
  2390. numClients);
  2391. if (pClients != NULL)
  2392. {
  2393. XtFree ((char *)pClients);
  2394. }
  2395. return (rval);
  2396. } /* END OF FUNCTION UpdateEmbeddedClientsProperty */
  2397. /*******************************<->*************************************
  2398. *
  2399. * UnParentControls (pSD, unmap)
  2400. *
  2401. * Description:
  2402. * -----------
  2403. *
  2404. * Inputs:
  2405. * ------
  2406. * pSD - pointer to the screen data
  2407. * unmap - if True, then unmap the windows after reparenting to root
  2408. *
  2409. * Outputs:
  2410. * -------
  2411. * none
  2412. *
  2413. * Comments:
  2414. * --------
  2415. * Reparents clients embedded in the front panel back to the
  2416. * root window
  2417. *
  2418. ******************************<->***********************************/
  2419. void
  2420. UnParentControls(
  2421. WmScreenData *pSD,
  2422. Boolean unmap )
  2423. {
  2424. int i;
  2425. ClientData *pCD;
  2426. WmFpEmbeddedClientData *pECD;
  2427. if (pSD && pSD->managed)
  2428. {
  2429. pECD = (WmFpEmbeddedClientData *) pSD->pECD;
  2430. for (i = 0; i < pSD->numEmbeddedClients; i++, pECD++)
  2431. {
  2432. pCD = pECD->pCD;
  2433. if (pCD)
  2434. {
  2435. if ((pCD->clientFlags & CLIENT_IN_SAVE_SET) &&
  2436. !(pCD->clientFlags & CLIENT_DESTROYED))
  2437. {
  2438. XRemoveFromSaveSet (DISPLAY, pCD->client);
  2439. XRemoveFromSaveSet (DISPLAY1, pCD->client);
  2440. }
  2441. XReparentWindow (DISPLAY,
  2442. pCD->client,
  2443. pSD->rootWindow,
  2444. pCD->clientX,
  2445. pCD->clientY);
  2446. if (unmap)
  2447. {
  2448. XUnmapWindow (DISPLAY, pCD->client);
  2449. if (pCD->iconWindow)
  2450. {
  2451. if (pCD->clientFlags & ICON_IN_SAVE_SET)
  2452. {
  2453. XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
  2454. pCD->clientFlags &= ~ICON_IN_SAVE_SET;
  2455. }
  2456. XUnmapWindow (DISPLAY, pCD->iconWindow);
  2457. }
  2458. }
  2459. }
  2460. }
  2461. }
  2462. } /* END OF FUNCTION UnParentControl */
  2463. /*************************************<->*************************************
  2464. *
  2465. * RegisterIconBoxControl (wPanelist)
  2466. *
  2467. *
  2468. * Description:
  2469. * -----------
  2470. * This function registers the icon box control in a front panel
  2471. *
  2472. *
  2473. * Inputs:
  2474. * ------
  2475. * wPanelist = front panel object (widget)
  2476. *
  2477. * Outputs:
  2478. * -------
  2479. *
  2480. *************************************<->***********************************/
  2481. void
  2482. RegisterIconBoxControl (Widget wPanelist)
  2483. {
  2484. WmScreenData *pSD;
  2485. int i;
  2486. for (i= 0; i < wmGD.numScreens; i++)
  2487. {
  2488. pSD = &(wmGD.Screens[i]);
  2489. if (pSD->managed)
  2490. {
  2491. if (pSD->wPanelist == wPanelist)
  2492. break;
  2493. }
  2494. }
  2495. if (i < wmGD.numScreens)
  2496. {
  2497. pSD->iconBoxControl = True;
  2498. pSD->useIconBox = True;
  2499. }
  2500. #ifdef DEBUG
  2501. else
  2502. {
  2503. fprintf (stderr, "Couldn't match wPanelist to screen data\n");
  2504. }
  2505. #endif /* DEBUG */
  2506. } /* END OF FUNCTION RegisterIconBoxControl */