WmProtocol.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  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 OPEN SOFTWARE FOUNDATION, INC.
  25. * ALL RIGHTS RESERVED
  26. */
  27. /*
  28. * Motif Release 1.2.3
  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. /*
  38. * include extern functions
  39. */
  40. #include "WmError.h"
  41. #include "WmFunction.h"
  42. #include "WmKeyFocus.h"
  43. #include "WmMenu.h"
  44. #include "WmWinInfo.h"
  45. #include "WmEvent.h"
  46. #include "WmPanelP.h"
  47. /*
  48. * Function Declarations:
  49. */
  50. #include "WmProtocol.h"
  51. static Boolean wmq_convert (Widget w, Atom *pSelection, Atom *pTarget,
  52. Atom *pType_return, XtPointer *pValue_return, unsigned long *pLength_return,
  53. int *pFormat_return);
  54. static Boolean wmq_convert_all_clients (Widget w, int screen,
  55. Atom *pType_return, XtPointer *pValue_return, unsigned long *pLength_return,
  56. int *pFormat_return);
  57. static void wmq_list_subtree (ClientData *pCD);
  58. static void wmq_add_xid (XID win);
  59. static void wmq_done (Widget w, Atom *pSelection, Atom *pTarget);
  60. static void wmq_lose (Widget w, Atom *pSelection);
  61. static void wmq_bump_xids(void);
  62. /*
  63. * Global Variables:
  64. */
  65. Atom *xa_WM_QUERY = NULL;
  66. Atom xa_WM_POINTER_WINDOW;
  67. Atom xa_WM_CLIENT_WINDOW;
  68. Atom xa_WM_ALL_CLIENTS;
  69. XID *pXids = NULL;
  70. int numXids = -1;
  71. int curXids = 0;
  72. /*************************************<->*************************************
  73. *
  74. * SetupWmICCC ()
  75. *
  76. *
  77. * Description:
  78. * -----------
  79. * This function sets up the window manager handling of the inter-client
  80. * communications conventions.
  81. *
  82. *
  83. * Outputs:
  84. * -------
  85. * (wmGD) = Atoms id's are setup.
  86. *
  87. *************************************<->***********************************/
  88. void SetupWmICCC (void)
  89. {
  90. enum {
  91. XA_PREMATURE_XCLIENTMESSAGEEVENT_LIST,
  92. XA_WM_STATE, XA_WM_PROTOCOLS, XA_WM_CHANGE_STATE,
  93. XA_WM_SAVE_YOURSELF, XA_WM_DELETE_WINDOW,
  94. XA_WM_COLORMAP_WINDOWS, XA_WM_TAKE_FOCUS, XA_MWM_HINTS,
  95. XA_MWM_MENU, XA_MWM_MESSAGES, XA_MOTIF_WM_OFFSET,
  96. XA_MOTIF_WM_CLIENT_WINDOW, XA_MOTIF_WM_POINTER_WINDOW,
  97. XA_MOTIF_WM_ALL_CLIENTS,
  98. XA_COMPOUND_TEXT, NUM_ATOMS };
  99. static char *atom_names[] = {
  100. _XA_PREMATURE_XCLIENTMESSAGEEVENT_LIST,
  101. _XA_WM_STATE, _XA_WM_PROTOCOLS, _XA_WM_CHANGE_STATE,
  102. _XA_WM_SAVE_YOURSELF, _XA_WM_DELETE_WINDOW,
  103. _XA_WM_COLORMAP_WINDOWS, _XA_WM_TAKE_FOCUS, _XA_MWM_HINTS,
  104. _XA_MWM_MENU, _XA_MWM_MESSAGES, _XA_MOTIF_WM_OFFSET,
  105. # ifdef _XA_MOTIF_WM_CLIENT_WINDOW
  106. _XA_MOTIF_WM_CLIENT_WINDOW, _XA_MOTIF_WM_POINTER_WINDOW,
  107. _XA_MOTIF_WM_ALL_CLIENTS,
  108. # else
  109. "_MOTIF_WM_CLIENT_WINDOW", "_MOTIF_WM_POINTER_WINDOW",
  110. "_MOTIF_WM_ALL_CLIENTS",
  111. # endif
  112. "COMPOUND_TEXT"
  113. };
  114. XIconSize sizeList;
  115. int scr;
  116. Atom atoms[XtNumber(atom_names) + 1];
  117. /*
  118. * Make atoms that are required by the ICCC and mwm. The atom for
  119. * _MOTIF_WM_INFO is intern'ed in ProcessMotifWmInfo.
  120. */
  121. XInternAtoms(DISPLAY, atom_names, XtNumber(atom_names), False, atoms);
  122. wmGD.xa_PREMATURE_XCLIENTMESSAGEEVENT_LIST =
  123. atoms[XA_PREMATURE_XCLIENTMESSAGEEVENT_LIST];
  124. wmGD.xa_WM_STATE = atoms[XA_WM_STATE];
  125. wmGD.xa_WM_PROTOCOLS = atoms[XA_WM_PROTOCOLS];
  126. wmGD.xa_WM_CHANGE_STATE = atoms[XA_WM_CHANGE_STATE];
  127. wmGD.xa_WM_SAVE_YOURSELF = atoms[XA_WM_SAVE_YOURSELF];
  128. wmGD.xa_WM_DELETE_WINDOW = atoms[XA_WM_DELETE_WINDOW];
  129. wmGD.xa_WM_COLORMAP_WINDOWS = atoms[XA_WM_COLORMAP_WINDOWS];
  130. wmGD.xa_WM_TAKE_FOCUS = atoms[XA_WM_TAKE_FOCUS];
  131. wmGD.xa_MWM_HINTS = atoms[XA_MWM_HINTS];
  132. wmGD.xa_MWM_MENU = atoms[XA_MWM_MENU];
  133. wmGD.xa_MWM_MESSAGES = atoms[XA_MWM_MESSAGES];
  134. wmGD.xa_MWM_OFFSET = atoms[XA_MOTIF_WM_OFFSET];
  135. wmGD.xa_COMPOUND_TEXT = atoms[XA_COMPOUND_TEXT];
  136. if (!(xa_WM_QUERY = (Atom *) XtMalloc (wmGD.numScreens * (sizeof (Atom)))))
  137. {
  138. Warning (((char *)GETMESSAGE(56, 2, "Insufficient memory to XInternAtom _MOTIF_WM_QUERY_nn")));
  139. }
  140. for (scr = 0; scr < wmGD.numScreens; scr++)
  141. {
  142. if (wmGD.Screens[scr].managed)
  143. {
  144. char wm_query_scr[32];
  145. sprintf(wm_query_scr, "_MOTIF_WM_QUERY_%d",
  146. wmGD.Screens[scr].screen);
  147. xa_WM_QUERY[scr] = XInternAtom(DISPLAY, wm_query_scr, False);
  148. }
  149. else
  150. {
  151. xa_WM_QUERY[scr] = 0;
  152. }
  153. }
  154. xa_WM_CLIENT_WINDOW = atoms[XA_MOTIF_WM_CLIENT_WINDOW];
  155. xa_WM_POINTER_WINDOW = atoms[XA_MOTIF_WM_POINTER_WINDOW];
  156. xa_WM_ALL_CLIENTS = atoms[XA_MOTIF_WM_ALL_CLIENTS];
  157. /*
  158. * Setup the icon size property on the root window.
  159. */
  160. sizeList.width_inc = 1;
  161. sizeList.height_inc = 1;
  162. for (scr = 0; scr < wmGD.numScreens; scr++)
  163. {
  164. if (wmGD.Screens[scr].managed)
  165. {
  166. sizeList.min_width = wmGD.Screens[scr].iconImageMinimum.width;
  167. sizeList.min_height = wmGD.Screens[scr].iconImageMinimum.height;
  168. sizeList.max_width = wmGD.Screens[scr].iconImageMaximum.width;
  169. sizeList.max_height = wmGD.Screens[scr].iconImageMaximum.height;
  170. XSetIconSizes (DISPLAY, wmGD.Screens[scr].rootWindow,
  171. &sizeList, 1);
  172. }
  173. }
  174. /*
  175. * Assert ownership of the WM_QUERY selection
  176. */
  177. for (scr = 0; scr < wmGD.numScreens; scr++)
  178. {
  179. if (wmGD.Screens[scr].managed)
  180. {
  181. if (!XtOwnSelection(wmGD.topLevelW,
  182. xa_WM_QUERY[scr],
  183. GetTimestamp(),
  184. wmq_convert,
  185. wmq_lose,
  186. wmq_done))
  187. {
  188. Warning (((char *)GETMESSAGE(56, 3, "Failed to own _MOTIF_WM_QUERY_nn selection")));
  189. }
  190. }
  191. }
  192. } /* END OF FUNCTION SetupWmICCC */
  193. /*************************************<->*************************************
  194. *
  195. * SendConfigureNotify (pCD)
  196. *
  197. *
  198. * Description:
  199. * -----------
  200. * This function is used to send a synthetic ConfigureNotify event when
  201. * a client window is reconfigured in certain ways (e.g., the window is
  202. * moved without being resized).
  203. *
  204. *
  205. * Inputs:
  206. * ------
  207. * pCD = pointer to client data (window id and client size data)
  208. *
  209. *************************************<->***********************************/
  210. void SendConfigureNotify (ClientData *pCD)
  211. {
  212. XConfigureEvent notifyEvent;
  213. /*
  214. * Send a synthetic ConfigureNotify message:
  215. */
  216. notifyEvent.type = ConfigureNotify;
  217. notifyEvent.display = DISPLAY;
  218. notifyEvent.event = pCD->client;
  219. notifyEvent.window = pCD->client;
  220. if (pCD->pECD)
  221. {
  222. int rootX, rootY;
  223. Window wChild;
  224. WmFpEmbeddedClientData *pECD = (WmFpEmbeddedClientData *)pCD->pECD;
  225. /*
  226. * The front panel uses clientX, clientY for position in
  227. * front panel. Translate to root coords for client's
  228. * information.
  229. */
  230. XTranslateCoordinates (DISPLAY, pECD->winParent,
  231. ROOT_FOR_CLIENT(pCD), pCD->clientX, pCD->clientY,
  232. &rootX, &rootY, &wChild);
  233. notifyEvent.x = rootX;
  234. notifyEvent.y = rootY;
  235. notifyEvent.width = pCD->clientWidth;
  236. notifyEvent.height = pCD->clientHeight;
  237. }
  238. else
  239. if (pCD->maxConfig)
  240. {
  241. notifyEvent.x = pCD->maxX;
  242. notifyEvent.y = pCD->maxY;
  243. notifyEvent.width = pCD->maxWidth;
  244. notifyEvent.height = pCD->maxHeight;
  245. }
  246. else
  247. {
  248. notifyEvent.x = pCD->clientX;
  249. notifyEvent.y = pCD->clientY;
  250. notifyEvent.width = pCD->clientWidth;
  251. notifyEvent.height = pCD->clientHeight;
  252. }
  253. notifyEvent.border_width = 0;
  254. notifyEvent.above = None;
  255. notifyEvent.override_redirect = False;
  256. XSendEvent (DISPLAY, pCD->client, False, StructureNotifyMask,
  257. (XEvent *)&notifyEvent);
  258. } /* END OF FUNCTION SendConfigureNotify */
  259. /*************************************<->*************************************
  260. *
  261. * SendClientOffsetMessage (pCD)
  262. *
  263. *
  264. * Description:
  265. * -----------
  266. * This function is used to send a client message containing the offset
  267. * between the window position reported to the user and the actual
  268. * window position of the client over the root.
  269. *
  270. * This can be used by clients that map and unmap windows to help them
  271. * work with the window manager to place the window in the same location
  272. * when remapped.
  273. *
  274. * Inputs:
  275. * ------
  276. * pCD = pointer to client data (frame geometry info)
  277. *
  278. *************************************<->***********************************/
  279. void SendClientOffsetMessage (ClientData *pCD)
  280. {
  281. long borderWidth = (long)pCD->xBorderWidth;
  282. long offsetX = pCD->clientOffset.x;
  283. long offsetY = pCD->clientOffset.y;
  284. XClientMessageEvent clientMsgEvent;
  285. clientMsgEvent.type = ClientMessage;
  286. clientMsgEvent.window = pCD->client;
  287. clientMsgEvent.message_type = wmGD.xa_MWM_MESSAGES;
  288. clientMsgEvent.format = 32;
  289. clientMsgEvent.data.l[0] = wmGD.xa_MWM_OFFSET;
  290. /*
  291. * Use window gravity to allow the user to specify the window
  292. * position on the screen without having to know the dimensions
  293. * of the decoration that mwm is adding.
  294. */
  295. switch (pCD->windowGravity)
  296. {
  297. case NorthWestGravity:
  298. default:
  299. {
  300. clientMsgEvent.data.l[1] = offsetX;
  301. clientMsgEvent.data.l[2] = offsetY;
  302. break;
  303. }
  304. case NorthGravity:
  305. {
  306. clientMsgEvent.data.l[1] = borderWidth;
  307. clientMsgEvent.data.l[2] = offsetY;
  308. break;
  309. }
  310. case NorthEastGravity:
  311. {
  312. clientMsgEvent.data.l[1] = -(offsetX - (2 * borderWidth));
  313. clientMsgEvent.data.l[2] = offsetY;
  314. break;
  315. }
  316. case EastGravity:
  317. {
  318. clientMsgEvent.data.l[1] = -(offsetX - (2 * borderWidth));
  319. clientMsgEvent.data.l[2] = borderWidth + (offsetY - offsetX)/2;
  320. break;
  321. }
  322. case SouthEastGravity:
  323. {
  324. clientMsgEvent.data.l[1] = -(offsetX - (2 * borderWidth));
  325. clientMsgEvent.data.l[2] = -(offsetX - (2 * borderWidth));
  326. break;
  327. }
  328. case SouthGravity:
  329. {
  330. clientMsgEvent.data.l[1] = borderWidth;
  331. clientMsgEvent.data.l[2] = -(offsetX - (2 * borderWidth));
  332. break;
  333. }
  334. case SouthWestGravity:
  335. {
  336. clientMsgEvent.data.l[1] = offsetX;
  337. clientMsgEvent.data.l[2] = -(offsetX - (2 * borderWidth));
  338. break;
  339. }
  340. case WestGravity:
  341. {
  342. clientMsgEvent.data.l[1] = offsetX;
  343. clientMsgEvent.data.l[2] = borderWidth + (offsetY - offsetX)/2;
  344. break;
  345. }
  346. case CenterGravity:
  347. {
  348. clientMsgEvent.data.l[2] = (offsetY - offsetX)/2;
  349. break;
  350. }
  351. }
  352. XSendEvent (DISPLAY, pCD->client, False, NoEventMask,
  353. (XEvent *)&clientMsgEvent);
  354. } /* END OF FUNCTION SendClientOffsetMessage */
  355. /*************************************<->*************************************
  356. *
  357. * SendClientMsg (window, type, data0, time, pData, dataLen)
  358. *
  359. *
  360. * Description:
  361. * -----------
  362. * This function is used to send a client message event that to a client
  363. * window. The message may be sent as part of a protocol arranged for by
  364. * the client with the WM_PROTOCOLS property.
  365. *
  366. *
  367. * Inputs:
  368. * ------
  369. * window = destination window for the client message event
  370. *
  371. * type = client message type
  372. *
  373. * data0 = data0 value in the client message
  374. *
  375. * time = timestamp to be used in the event
  376. *
  377. * pData = pointer to data to be used in the event
  378. *
  379. * dataLen = len of data (in 32 bit units)
  380. *
  381. *************************************<->***********************************/
  382. void SendClientMsg (Window window, long type, long data0, Time time, long *pData, int dataLen)
  383. {
  384. XClientMessageEvent clientMsgEvent;
  385. int i;
  386. clientMsgEvent.type = ClientMessage;
  387. clientMsgEvent.window = window;
  388. clientMsgEvent.message_type = type;
  389. clientMsgEvent.format = 32;
  390. clientMsgEvent.data.l[0] = data0;
  391. clientMsgEvent.data.l[1] = (long)time;
  392. if (pData)
  393. {
  394. /*
  395. * Fill in the rest of the ClientMessage event (that holds up to
  396. * 5 words of data).
  397. */
  398. if (dataLen > 3)
  399. {
  400. dataLen = 3;
  401. }
  402. for (i = 2; i < (2 + dataLen); i++)
  403. {
  404. clientMsgEvent.data.l[i] = pData[i];
  405. }
  406. }
  407. XSendEvent (DISPLAY, window, False, NoEventMask,
  408. (XEvent *)&clientMsgEvent);
  409. XFlush(DISPLAY);
  410. } /* END OF FUNCTION SendClientMsg */
  411. /*************************************<->*************************************
  412. *
  413. * AddWmTimer (timerType, timerInterval, pCD)
  414. *
  415. *
  416. * Description:
  417. * -----------
  418. * This function sets a window manager timer of the specified type.
  419. *
  420. *
  421. * Inputs:
  422. * ------
  423. * timerType = type of timer to be set
  424. *
  425. * timerInterval = length of timeout in ms
  426. *
  427. * pCD = pointer to client data associated with the timer
  428. *
  429. * return = True if timer could be set
  430. *
  431. *************************************<->***********************************/
  432. Boolean AddWmTimer (unsigned int timerType, unsigned long timerInterval, ClientData *pCD)
  433. {
  434. WmTimer *pWmTimer;
  435. if (!(pWmTimer = (WmTimer *)XtMalloc (sizeof (WmTimer))))
  436. {
  437. Warning (((char *)GETMESSAGE(56, 1, "Insufficient memory for window manager data")));
  438. return (False);
  439. }
  440. /* !!! handle for XtAppAddTimeOut error !!! */
  441. pWmTimer->timerId = XtAppAddTimeOut (wmGD.mwmAppContext,
  442. timerInterval, (XtTimerCallbackProc)TimeoutProc, (caddr_t)pCD);
  443. pWmTimer->timerCD = pCD;
  444. pWmTimer->timerType = timerType;
  445. pWmTimer->nextWmTimer = wmGD.wmTimers;
  446. wmGD.wmTimers = pWmTimer;
  447. return(True);
  448. } /* END OF FUNCTION AddWmTimer */
  449. /*************************************<->*************************************
  450. *
  451. * DeleteClientWmTimers (pCD)
  452. *
  453. *
  454. * Description:
  455. * -----------
  456. * This function deletes all window manager timers that are associated with
  457. * the specified client window.
  458. *
  459. *
  460. * Inputs:
  461. * ------
  462. * pCD = pointer to client data for client whose timers are to be deleted
  463. *
  464. * wmGD = (wmTimers)
  465. *
  466. *************************************<->***********************************/
  467. void DeleteClientWmTimers (ClientData *pCD)
  468. {
  469. WmTimer *pPrevTimer;
  470. WmTimer *pWmTimer;
  471. WmTimer *pRemoveTimer;
  472. pPrevTimer = NULL;
  473. pWmTimer = wmGD.wmTimers;
  474. while (pWmTimer)
  475. {
  476. if (pWmTimer->timerCD == pCD)
  477. {
  478. if (pPrevTimer)
  479. {
  480. pPrevTimer->nextWmTimer = pWmTimer->nextWmTimer;
  481. }
  482. else
  483. {
  484. wmGD.wmTimers = pWmTimer->nextWmTimer;
  485. }
  486. pRemoveTimer = pWmTimer;
  487. pWmTimer = pWmTimer->nextWmTimer;
  488. XtRemoveTimeOut (pRemoveTimer->timerId);
  489. XtFree ((char *)pRemoveTimer);
  490. }
  491. else
  492. {
  493. pPrevTimer = pWmTimer;
  494. pWmTimer = pWmTimer->nextWmTimer;
  495. }
  496. }
  497. } /* END OF FUNCTION DeleteClientWmTimers */
  498. /*************************************<->*************************************
  499. *
  500. * TimeoutProc (client_data, id)
  501. *
  502. *
  503. * Description:
  504. * -----------
  505. * This function is an Xtk timeout handler. It is used to handle various
  506. * window manager timers (i.e. WM_SAVE_YOURSELF quit timeout).
  507. *
  508. *
  509. * Inputs:
  510. * ------
  511. * client_data = pointer to window manager client data
  512. *
  513. * id = Xtk timer id
  514. *
  515. *************************************<->***********************************/
  516. void TimeoutProc (caddr_t client_data, XtIntervalId *id)
  517. {
  518. WmTimer *pPrevTimer;
  519. WmTimer *pWmTimer;
  520. /*
  521. * Find out if the timer still needs to be serviced.
  522. */
  523. pPrevTimer = NULL;
  524. pWmTimer = wmGD.wmTimers;
  525. while (pWmTimer)
  526. {
  527. if (pWmTimer->timerId == *id)
  528. {
  529. break;
  530. }
  531. pPrevTimer = pWmTimer;
  532. pWmTimer = pWmTimer->nextWmTimer;
  533. }
  534. if (pWmTimer)
  535. {
  536. /*
  537. * Do the timer related action.
  538. */
  539. switch (pWmTimer->timerType)
  540. {
  541. case TIMER_QUIT:
  542. {
  543. XKillClient (DISPLAY, pWmTimer->timerCD->client);
  544. break;
  545. }
  546. case TIMER_RAISE:
  547. {
  548. Boolean sameScreen;
  549. if ((wmGD.keyboardFocus == pWmTimer->timerCD) &&
  550. (pWmTimer->timerCD->focusPriority ==
  551. (PSD_FOR_CLIENT(pWmTimer->timerCD))->focusPriority) &&
  552. (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) &&
  553. (pWmTimer->timerCD == GetClientUnderPointer(&sameScreen)))
  554. {
  555. Do_Raise (pWmTimer->timerCD, (ClientListEntry *)NULL, STACK_NORMAL);
  556. }
  557. break;
  558. }
  559. }
  560. /*
  561. * Remove the timer from the wm timer list.
  562. */
  563. if (pPrevTimer)
  564. {
  565. pPrevTimer->nextWmTimer = pWmTimer->nextWmTimer;
  566. }
  567. else
  568. {
  569. wmGD.wmTimers = pWmTimer->nextWmTimer;
  570. }
  571. XtFree ((char *)pWmTimer);
  572. }
  573. /*
  574. * Free up the timer.
  575. */
  576. XtRemoveTimeOut (*id);
  577. } /* END OF FUNCTION TimeoutProc */
  578. /*************************************<->*************************************
  579. *
  580. * Boolean wmq_convert (w, pSelection, pTarget, pType_return,
  581. * pValue_return, pLength_return, pFormat_return)
  582. *
  583. *
  584. * Description:
  585. * -----------
  586. * This function converts WM_QUERY selections
  587. *
  588. * Inputs:
  589. * ------
  590. * w - widget
  591. * pSelection - pointer to selection type (atom)
  592. * pTarget - pointer to requested target type (atom)
  593. *
  594. * Outputs:
  595. * ------
  596. * pType_return - pointer to type of data returned (atom)
  597. * pValue_return - pointer to pointer to data returned
  598. * pLength_return - ptr to length of data returned
  599. * pFormat_return - ptr to format of data returned
  600. *
  601. * Comments:
  602. * --------
  603. *
  604. *************************************<->***********************************/
  605. static Boolean
  606. wmq_convert (
  607. Widget w,
  608. Atom *pSelection,
  609. Atom *pTarget,
  610. Atom *pType_return,
  611. XtPointer *pValue_return,
  612. unsigned long *pLength_return,
  613. int *pFormat_return
  614. )
  615. {
  616. Boolean wm_query_found = False;
  617. int scr;
  618. for (scr = 0; scr < wmGD.numScreens; scr++)
  619. {
  620. if (wmGD.Screens[scr].managed)
  621. {
  622. if (*pSelection == xa_WM_QUERY[scr])
  623. {
  624. wm_query_found = True;
  625. break;
  626. }
  627. }
  628. }
  629. if (wm_query_found)
  630. {
  631. if (*pTarget == xa_WM_POINTER_WINDOW)
  632. {
  633. return (False);
  634. }
  635. else if (*pTarget == xa_WM_CLIENT_WINDOW)
  636. {
  637. return (False);
  638. }
  639. else if (*pTarget == xa_WM_ALL_CLIENTS)
  640. {
  641. return (wmq_convert_all_clients (w, scr, pType_return,
  642. pValue_return, pLength_return,
  643. pFormat_return));
  644. }
  645. }
  646. return (wm_query_found);
  647. } /* END OF FUNCTION wmq_convert */
  648. /*************************************<->*************************************
  649. *
  650. * Boolean wmq_convert_all_clients (w, screen, pType_return,
  651. * pValue_return, pLength_return, pFormat_return)
  652. *
  653. *
  654. * Description:
  655. * -----------
  656. * This function converts the WM_QUERY selection target WM_ALL_CLIENTS
  657. *
  658. * Inputs:
  659. * ------
  660. * w - widget
  661. * screen - screen number
  662. *
  663. * Outputs:
  664. * ------
  665. * pType_return - pointer to type of data returned (atom)
  666. * pValue_return - pointer to pointer to data returned
  667. * pLength_return - ptr to length of data returned
  668. * pFormat_return - ptr to format of data returned
  669. *
  670. * Comments:
  671. * --------
  672. *
  673. *************************************<->***********************************/
  674. static Boolean
  675. wmq_convert_all_clients (
  676. Widget w,
  677. int screen,
  678. Atom *pType_return,
  679. XtPointer *pValue_return,
  680. unsigned long *pLength_return,
  681. int *pFormat_return
  682. )
  683. {
  684. WmScreenData *pSD = NULL;
  685. ClientListEntry *pEntry;
  686. ClientData *pCD;
  687. /*
  688. * Start with empty client list
  689. */
  690. curXids = 0;
  691. /*
  692. * Get all clients on the specified screen
  693. */
  694. if (wmGD.Screens[screen].managed)
  695. {
  696. pSD = &wmGD.Screens[screen];
  697. /*
  698. * Traverse the client list for this screen and
  699. * add to the list of window IDs
  700. */
  701. pEntry = pSD->clientList;
  702. while (pEntry)
  703. {
  704. /*
  705. * Filter out entries for icons
  706. */
  707. if (pEntry->type != MINIMIZED_STATE)
  708. {
  709. pCD = pEntry->pCD;
  710. if (pCD->transientChildren)
  711. {
  712. wmq_list_subtree(pCD->transientChildren);
  713. }
  714. wmq_add_xid ((XID) pCD->client);
  715. }
  716. pEntry = pEntry->nextSibling;
  717. }
  718. }
  719. *pType_return = XA_WINDOW;
  720. *pValue_return = (XtPointer) pXids;
  721. *pLength_return = curXids;
  722. *pFormat_return = 32;
  723. return (True);
  724. } /* END OF FUNCTION wmq_convert_all_clients */
  725. /*************************************<->*************************************
  726. *
  727. * void wmq_list_subtree (pCD)
  728. *
  729. *
  730. * Description:
  731. * -----------
  732. * This function adds the windows in a transient subtree to the
  733. * global window list
  734. *
  735. * Inputs:
  736. * ------
  737. * pCD - client data for "leftmost" child of a subtree
  738. *
  739. * Outputs:
  740. * ------
  741. *
  742. * Comments:
  743. * --------
  744. *
  745. *************************************<->***********************************/
  746. static void
  747. wmq_list_subtree (
  748. ClientData *pCD
  749. )
  750. {
  751. /*
  752. * Do children first
  753. */
  754. if (pCD->transientChildren)
  755. {
  756. wmq_list_subtree(pCD->transientChildren);
  757. }
  758. /*
  759. * Do me
  760. */
  761. wmq_add_xid ((XID) pCD->client);
  762. /*
  763. * Do siblings
  764. */
  765. if (pCD->transientSiblings)
  766. {
  767. wmq_list_subtree(pCD->transientSiblings);
  768. }
  769. } /* END OF FUNCTION wmq_list_subtree */
  770. /*************************************<->*************************************
  771. *
  772. * void wmq_add_xid (win)
  773. *
  774. *
  775. * Description:
  776. * -----------
  777. * This function adds an xid to the list
  778. *
  779. * Inputs:
  780. * ------
  781. * win - xid to add
  782. *
  783. * Outputs:
  784. * ------
  785. *
  786. * Comments:
  787. * --------
  788. *
  789. *************************************<->***********************************/
  790. static void
  791. wmq_add_xid (
  792. XID win
  793. )
  794. {
  795. if (curXids >= numXids)
  796. {
  797. wmq_bump_xids();
  798. }
  799. if (curXids < numXids)
  800. {
  801. pXids[curXids++] = win;
  802. }
  803. } /* END OF FUNCTION wmq_add_xid */
  804. /*************************************<->*************************************
  805. *
  806. * void wmq_lose (w, pSelection)
  807. *
  808. *
  809. * Description:
  810. * -----------
  811. * This function is called when we lose the WM_QUERY selection
  812. *
  813. * Inputs:
  814. * ------
  815. * w - widget
  816. * pSelection - pointer to selection type (atom)
  817. *
  818. * Outputs:
  819. * ------
  820. *
  821. * Comments:
  822. * --------
  823. * This shouldn't happen!
  824. *
  825. *************************************<->***********************************/
  826. static void
  827. wmq_lose (
  828. Widget w,
  829. Atom *pSelection
  830. )
  831. {
  832. Warning (((char *)GETMESSAGE(56, 4, "Lost _MOTIF_WM_QUERY_nn selection")));
  833. } /* END OF FUNCTION wmq_lose */
  834. /*************************************<->*************************************
  835. *
  836. * void wmq_done (w, pSelection, pTarget)
  837. *
  838. *
  839. * Description:
  840. * -----------
  841. * This function is called when selection conversion is done.
  842. *
  843. * Inputs:
  844. * ------
  845. * w - widget
  846. * pSelection - pointer to selection type (atom)
  847. * pTarget - pointer to requested target type (atom)
  848. *
  849. * Outputs:
  850. * ------
  851. *
  852. * Comments:
  853. * --------
  854. * This is here to prevent Xt from freeing our buffers.
  855. *
  856. *************************************<->***********************************/
  857. static void
  858. wmq_done (
  859. Widget w,
  860. Atom *pSelection,
  861. Atom *pTarget
  862. )
  863. {
  864. } /* END OF FUNCTION wmq_done */
  865. /*************************************<->*************************************
  866. *
  867. * static void wmq_bump_xids ()
  868. *
  869. *
  870. * Description:
  871. * -----------
  872. * This function allocates more xids in our local buffer
  873. *
  874. * Inputs:
  875. * ------
  876. * w - widget
  877. * pSelection - pointer to selection type (atom)
  878. * pTarget - pointer to requested target type (atom)
  879. *
  880. * Outputs:
  881. * ------
  882. *
  883. * Comments:
  884. * --------
  885. * This is here to prevent Xt from freeing our buffers.
  886. *
  887. *************************************<->***********************************/
  888. static void
  889. wmq_bump_xids ( void )
  890. {
  891. XID *px;
  892. if (pXids)
  893. {
  894. if (!(px = (XID *)
  895. XtRealloc ((char *) pXids, (numXids + 32) * (sizeof (XID)))))
  896. {
  897. Warning (((char *)GETMESSAGE(56, 5, "Insufficient memory to convert _MOTIF_WM_QUERY_nn selection")));
  898. }
  899. else
  900. {
  901. pXids = px;
  902. numXids += 32;
  903. }
  904. }
  905. else
  906. {
  907. if (!(pXids = (XID *)
  908. XtMalloc (32 * (sizeof (XID)))))
  909. {
  910. Warning (((char *)GETMESSAGE(56, 5, "Insufficient memory to convert _MOTIF_WM_QUERY_nn selection")));
  911. }
  912. else
  913. {
  914. numXids = 32;
  915. }
  916. }
  917. }