WmFP.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  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. *
  25. * File: WmFP.c
  26. *
  27. * Project: CDE
  28. *
  29. * Description: This file contains functions used between the window manager
  30. * and front panel.
  31. *
  32. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  33. * (c) Copyright 1993, 1994 International Business Machines Corp.
  34. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  35. * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
  36. *
  37. ****************************************************************************/
  38. #include "WmGlobal.h"
  39. #include <Dt/DtP.h>
  40. #include <Dt/DbReader.h>
  41. #include <Dt/Control.h>
  42. #include <Dt/ControlP.h>
  43. #include <Dt/IconFile.h>
  44. #include <Dt/Icon.h>
  45. #include <Dt/Wsm.h>
  46. #include <Dt/MacrosP.h>
  47. #include <Xm/Form.h>
  48. #include <Xm/ToggleBG.h>
  49. #include <Xm/MwmUtil.h>
  50. #include <Xm/AtomMgr.h>
  51. #include <Xm/DrawingA.h>
  52. #include <Xm/RowColumn.h>
  53. #include <Xm/SeparatoG.h>
  54. #include <Xm/DialogS.h>
  55. #include <X11/Xatom.h>
  56. #include <X11/keysymdef.h>
  57. #include "PanelSP.h"
  58. #include "DataBaseLoad.h"
  59. #include "UI.h"
  60. #include "WmPanelP.h"
  61. #include "WmManage.h"
  62. #include <pwd.h>
  63. #include <fcntl.h>
  64. #include <stdint.h>
  65. #include <sys/stat.h>
  66. extern void SubpanelTornEventHandler (Widget, XtPointer, XEvent *, Boolean *);
  67. extern void WorkspaceModifyCB (Widget, Atom, int, XtPointer);
  68. extern void SessionRestoreData (void);
  69. extern void UnManageWindow (ClientData *pCD);
  70. extern void WorkspaceAdjustPanelPosition (Position x,
  71. Position y,
  72. Dimension width,
  73. Dimension height);
  74. static void PushRecallSetData ();
  75. static void EmbeddedClientSetData ();
  76. static void EmbeddedClientSetGeometry (WmFpEmbeddedClientData *);
  77. /************************************************************************
  78. *
  79. * EmbeddedClientReposition
  80. * This function moves client windows within the main panel after
  81. * controls have been resized.
  82. *
  83. * Inputs: icon - the icon of the embedded client to be repositioned
  84. * x - the position of the resized control
  85. * adjust - how much to move the window
  86. *
  87. ************************************************************************/
  88. void
  89. EmbeddedClientReposition (Widget icon,
  90. Position x,
  91. Dimension adjust)
  92. {
  93. WmFpEmbeddedClientList embedded_client_list =
  94. (WmFpEmbeddedClientList) panel.embedded_client_list;
  95. int i;
  96. for (i = 0; i < panel.embedded_client_count; i++)
  97. {
  98. if (XtParent (icon) == XtParent (embedded_client_list[i].wControl) &&
  99. embedded_client_list[i].x > x)
  100. {
  101. if (embedded_client_list[i].pCD != NULL)
  102. {
  103. embedded_client_list[i].x += adjust;
  104. XMoveWindow (XtDisplay (panel.shell),
  105. embedded_client_list[i].pCD->client,
  106. embedded_client_list[i].x, embedded_client_list[i].y);
  107. }
  108. else
  109. embedded_client_list[i].x += adjust;
  110. }
  111. }
  112. }
  113. /************************************************************************
  114. *
  115. * EmbeddedClientReparent
  116. * This function sets of the data necessary to call the window
  117. * manager function which reparents an embedded client to a new
  118. * control.
  119. *
  120. * Inputs: client_name - the name of the client to be reparented.
  121. * icon - the widget that is to contain the client.
  122. * parent_win - the parent win to reparent the client to.
  123. *
  124. ************************************************************************/
  125. void
  126. EmbeddedClientReparent (char * client_name,
  127. Widget icon)
  128. {
  129. WmFpEmbeddedClientList embedded_client_list =
  130. (WmFpEmbeddedClientList) panel.embedded_client_list;
  131. int i;
  132. for (i = 0; i < panel.embedded_client_count; i++)
  133. {
  134. if (strcmp (client_name, embedded_client_list[i].pchResName) == 0)
  135. break;
  136. }
  137. /* Try to reparent the client to/from the main panel. If this */
  138. /* fails, it is because of a dtwm restart and the clients have */
  139. /* not yet been grabbed. So just reset the embedded client data */
  140. if (ReparentEmbeddedClient (&embedded_client_list[i], icon,
  141. XtWindow (XtParent (icon)),
  142. XtX (icon) + 3, XtY (icon) + 3,
  143. XtWidth(icon) - 6, XtHeight(icon) - 6) == False)
  144. {
  145. embedded_client_list[i].wControl = icon;
  146. embedded_client_list[i].winParent = XtWindow (XtParent (icon));
  147. embedded_client_list[i].x = XtX (icon) + 3;
  148. embedded_client_list[i].y = XtY (icon) + 3;
  149. embedded_client_list[i].width = XtWidth (icon) - 6;
  150. embedded_client_list[i].height = XtHeight (icon) - 6;
  151. }
  152. }
  153. /************************************************************************
  154. *
  155. * EmbeddedClientRegister
  156. * This function adds a control to the list of embedded client controls
  157. * and resets, if necessary, the Window Managers pointers to the list.
  158. *
  159. * Inputs:
  160. * control_data - the pointer to the ControlData * structure of
  161. * the control to be installed or removed.
  162. *
  163. * install - Boolean indicating whether to add or remove the control
  164. * from the push recall list.
  165. *
  166. ************************************************************************/
  167. void
  168. EmbeddedClientRegister (ControlData * control_data,
  169. Boolean install)
  170. {
  171. char * client_name;
  172. Window client_window;
  173. int i, j;
  174. WmFpEmbeddedClientList embedded_client_list =
  175. (WmFpEmbeddedClientList) panel.embedded_client_list;
  176. WmFpEmbeddedClientData * embedded_client = NULL;
  177. if ((intptr_t) control_data->
  178. element_values[CONTROL_TYPE].parsed_value != CONTROL_CLIENT)
  179. return;
  180. /* If this is a control installation, increase the list size, if */
  181. /* needed, and initialize the embedded client structure. If it is */
  182. /* a removal, find the control in the list and remove it by sliding */
  183. /* each subsequent structure down one element in array. */
  184. client_name = (char *)
  185. control_data->element_values[CONTROL_CLIENT_NAME].parsed_value;
  186. if (client_name == NULL)
  187. client_name = (char *)
  188. control_data->element_values[CONTROL_LABEL].parsed_value;
  189. if (install)
  190. {
  191. /* First see if this is an update to an already installed */
  192. /* embedded client. If so, simply update the icon field */
  193. for (i = 0; i < panel.embedded_client_count; i++)
  194. {
  195. if (strcmp (client_name, embedded_client_list[i].pchResName) == 0)
  196. {
  197. embedded_client_list[i].wControl = control_data->icon;
  198. break;
  199. }
  200. }
  201. if (i >= panel.embedded_client_count)
  202. {
  203. if (panel.embedded_client_count == panel.max_embedded_client_count)
  204. {
  205. panel.max_embedded_client_count += 10;
  206. embedded_client_list = (WmFpEmbeddedClientList)
  207. XtRealloc ((char *) embedded_client_list,
  208. sizeof (WmFpEmbeddedClientData) *
  209. panel.max_embedded_client_count);
  210. panel.embedded_client_list = (XtPointer) embedded_client_list;
  211. }
  212. embedded_client = &embedded_client_list[panel.embedded_client_count];
  213. panel.embedded_client_count++;
  214. embedded_client->pchResName = XtNewString (client_name);
  215. embedded_client->wControl = control_data->icon;
  216. embedded_client->winParent = None;
  217. embedded_client->pCD = NULL;
  218. }
  219. for (i = 0; i < panel.embedded_client_count - 1; i++)
  220. {
  221. embedded_client = &embedded_client_list[i];
  222. if (embedded_client->pCD != NULL)
  223. embedded_client->pCD->pECD = (void *) embedded_client;
  224. }
  225. }
  226. else
  227. {
  228. for (i = 0; i < panel.embedded_client_count; i++)
  229. {
  230. if (embedded_client_list[i].wControl == control_data->icon)
  231. {
  232. Position remove_y;
  233. Dimension adjust_y = 0;
  234. /* This block will reparent the client window, move it */
  235. /* to a new window location, and remap the window. */
  236. if (embedded_client_list[i].pCD != NULL)
  237. {
  238. client_window = embedded_client_list[i].pCD->client;
  239. UnManageWindow (embedded_client_list[i].pCD);
  240. XSync (XtDisplay (panel.shell), False);
  241. XMoveWindow (XtDisplay (panel.shell), client_window, 0, 0);
  242. XMapWindow (XtDisplay (panel.shell), client_window);
  243. }
  244. remove_y = embedded_client_list[i].y;
  245. /* deleted control height plus 5 pixels of form offset */
  246. if(control_data->icon) {
  247. adjust_y = XtHeight (control_data->icon) + 5;
  248. }
  249. panel.embedded_client_count--;
  250. XtFree (embedded_client_list[i].pchResName);
  251. for (j = i; j < panel.embedded_client_count; j++)
  252. {
  253. embedded_client_list[j] = embedded_client_list[j + 1];
  254. embedded_client = &embedded_client_list[j];
  255. if (embedded_client_list[i].pCD != NULL)
  256. {
  257. embedded_client->pCD->pECD = (void *) embedded_client;
  258. if (control_data->icon && XtParent(control_data->icon) ==
  259. XtParent(embedded_client->wControl) &&
  260. remove_y < embedded_client->y)
  261. {
  262. embedded_client->y -= adjust_y;
  263. XMoveWindow(XtDisplay(panel.shell),
  264. embedded_client->pCD->client,
  265. embedded_client->x, embedded_client->y);
  266. }
  267. }
  268. }
  269. break;
  270. }
  271. }
  272. }
  273. /* Set the embedded client list and count into the window manager's */
  274. /* screen global data. */
  275. EmbeddedClientSetData ();
  276. }
  277. /************************************************************************
  278. *
  279. * EmbeddedClientSetData
  280. * Set the embedded client list and count into the window manager's
  281. * screen global data.
  282. *
  283. ************************************************************************/
  284. static void
  285. EmbeddedClientSetData (void)
  286. {
  287. WmScreenData *pSD;
  288. int i;
  289. /* Find the screen which contains the front panel and set it */
  290. /* embedded client list and count. */
  291. for (i = 0; i < wmGD.numScreens; i++)
  292. {
  293. pSD = &(wmGD.Screens[i]);
  294. if (pSD->managed)
  295. {
  296. if (pSD->wPanelist == panel.form)
  297. {
  298. pSD->pECD = (struct _WmFpEmbeddedClientData *) panel.embedded_client_list;
  299. pSD->numEmbeddedClients = panel.embedded_client_count;
  300. break;
  301. }
  302. }
  303. }
  304. }
  305. /************************************************************************
  306. *
  307. * EmbeddedClientSetGeometry
  308. * Set the geometry and parenting window information for an
  309. * embedded client control.
  310. *
  311. * Inputs: embedded_client_data - a pointer to the structure containing
  312. * the embedded client information for a control.
  313. *
  314. * NOTE: Simplistic setting of position and size information. May need
  315. * to base on resolution and component parent.
  316. *
  317. ************************************************************************/
  318. static void
  319. EmbeddedClientSetGeometry (WmFpEmbeddedClientData * embedded_client_data)
  320. {
  321. Widget control;
  322. control = embedded_client_data->wControl;
  323. embedded_client_data->winParent = XtWindow (XtParent (control));
  324. embedded_client_data->x = XtX (control) + 3;
  325. embedded_client_data->y = XtY (control) + 3;
  326. embedded_client_data->width = XtWidth (control) - 6;
  327. embedded_client_data->height = XtHeight (control) - 6;
  328. }
  329. /************************************************************************
  330. *
  331. * PushRecallRegister
  332. * This function adds a control to the list of push recall controls
  333. * and resets, if necessary, the Window Managers pointers to the list.
  334. *
  335. * Inputs:
  336. * control_data - the pointer to the ControlData * structure of
  337. * the control to be installed or removed.
  338. *
  339. * install - Boolean indicating whether to add or remove the control
  340. * from the push recall list.
  341. *
  342. ************************************************************************/
  343. void
  344. PushRecallRegister (ControlData * control_data,
  345. Boolean install)
  346. {
  347. char * client_name;
  348. int i, j;
  349. WmFpPushRecallClientList push_recall_list =
  350. (WmFpPushRecallClientList) panel.push_recall_list;
  351. WmFpPushRecallClientData * push_recall = NULL;
  352. /* If this is a control installation, increase the list size, if */
  353. /* needed, and initialize the push recall structure. If it is a */
  354. /* removal, find the control in the push recall list and remove */
  355. /* it by sliding each subsequent structure down one element in */
  356. /* array. */
  357. if (install)
  358. {
  359. client_name = (char *) control_data->element_values[CONTROL_CLIENT_NAME].parsed_value;
  360. if (client_name == NULL)
  361. client_name = (char *) control_data->element_values[CONTROL_LABEL].parsed_value;
  362. /* First see if this is an update to an already installed */
  363. /* push recall client. If so, simply update the icon field */
  364. for (i = 0; i < panel.push_recall_count; i++)
  365. {
  366. if (strcmp (client_name, push_recall_list[i].pchResName) == 0)
  367. {
  368. push_recall_list[i].wControl = control_data->icon;
  369. break;
  370. }
  371. }
  372. if (i >= panel.push_recall_count)
  373. {
  374. if (panel.push_recall_count == panel.max_push_recall_count)
  375. {
  376. panel.max_push_recall_count += 10;
  377. push_recall_list = (WmFpPushRecallClientList)
  378. XtRealloc ((char *) push_recall_list,
  379. sizeof (WmFpPushRecallClientData) *
  380. panel.max_push_recall_count);
  381. panel.push_recall_list = (XtPointer) push_recall_list;
  382. }
  383. push_recall = &push_recall_list[panel.push_recall_count];
  384. panel.push_recall_count++;
  385. push_recall->pchResName = XtNewString (client_name);
  386. push_recall->wControl = control_data->icon;
  387. push_recall->pCD = NULL;
  388. push_recall->tvTimeout.tv_sec = 0;
  389. }
  390. for (i = 0; i < panel.push_recall_count - 1; i++)
  391. {
  392. push_recall = &push_recall_list[i];
  393. if (push_recall->pCD != NULL)
  394. push_recall->pCD->pPRCD = (void *) push_recall;
  395. }
  396. }
  397. else
  398. {
  399. for (i = 0; i < panel.push_recall_count; i++)
  400. {
  401. if (push_recall_list[i].wControl == control_data->icon)
  402. {
  403. panel.push_recall_count--;
  404. XtFree (push_recall_list[i].pchResName);
  405. for (j = i; j < panel.push_recall_count; j++)
  406. {
  407. push_recall_list[j] = push_recall_list[j + 1];
  408. push_recall = &push_recall_list[j];
  409. if (push_recall->pCD != NULL)
  410. push_recall->pCD->pPRCD = (void *) push_recall;
  411. }
  412. break;
  413. }
  414. }
  415. }
  416. /* Set the push recall list and count into the window manager's */
  417. /* screen global data. */
  418. PushRecallSetData ();
  419. }
  420. /************************************************************************
  421. *
  422. * PushRecallSetData
  423. * Set the push recall list and count into the window manager's
  424. * screen global data.
  425. *
  426. ************************************************************************/
  427. static void
  428. PushRecallSetData (void)
  429. {
  430. WmScreenData *pSD;
  431. int i;
  432. /* Find the screen which contains the front panel and set it */
  433. /* push recall list and count. */
  434. for (i = 0; i < wmGD.numScreens; i++)
  435. {
  436. pSD = &(wmGD.Screens[i]);
  437. if (pSD->managed)
  438. {
  439. if (pSD->wPanelist == panel.form)
  440. {
  441. pSD->pPRCD = (struct _WmFpPushRecallClientData *) panel.push_recall_list;
  442. pSD->numPushRecallClients = panel.push_recall_count;
  443. break;
  444. }
  445. }
  446. }
  447. }
  448. /************************************************************************
  449. *
  450. * PushRecallGetData
  451. * Find the index within the push recall list of the entry which
  452. * contains the passed client name.
  453. *
  454. * Inputs:
  455. * client_name - contains the name of the push recall client to
  456. * be used for the lookup.
  457. *
  458. ************************************************************************/
  459. int
  460. PushRecallGetData (char * client_name)
  461. {
  462. WmFpPushRecallClientList push_recall_list =
  463. (WmFpPushRecallClientList) panel.push_recall_list;
  464. int i;
  465. for (i = 0; i < panel.push_recall_count; i++)
  466. if (strcmp (client_name, push_recall_list[i].pchResName) == 0)
  467. return (i);
  468. /* Should never get here */
  469. return 0;
  470. }
  471. /************************************************************************
  472. *
  473. * WmPanelistWindowToSubpanel
  474. * Get a panel widget given its shell window.
  475. *
  476. ************************************************************************/
  477. Widget
  478. WmPanelistWindowToSubpanel (Display *dpy, Window win)
  479. {
  480. Widget subpanel_shell;
  481. Widget * child_list;
  482. int num_children;
  483. Arg al[2];
  484. int ac;
  485. /* Get the widget for the subpanel (Should be only child of the shell!) */
  486. subpanel_shell = XtWindowToWidget (dpy, win);
  487. ac = 0;
  488. XtSetArg (al[ac], XmNchildren, &child_list); ac++;
  489. XtSetArg (al[ac], XmNnumChildren, &num_children); ac++;
  490. XtGetValues (subpanel_shell, al, ac);
  491. return ((num_children > 0) ? child_list[0] : (Widget)NULL);
  492. }
  493. /************************************************************************
  494. *
  495. * WmPanelistSetBusy
  496. * Turn on or off the busy light.
  497. *
  498. ************************************************************************/
  499. void
  500. WmFrontPanelSetBusy (Boolean on)
  501. {
  502. if (panel.busy_light_data != NULL)
  503. _DtControlSetBusy (panel.busy_light_data->icon, on);
  504. }
  505. /************************************************************************
  506. *
  507. * SetGeometry
  508. * set x and y based on given geometry
  509. *
  510. ************************************************************************/
  511. static void
  512. SetGeometry (Widget w, String geometry, Position * x, Position * y)
  513. {
  514. int x_return, y_return;
  515. unsigned int width_return, height_return;
  516. long flags;
  517. flags = XParseGeometry (geometry, &x_return, &y_return,
  518. &width_return, &height_return);
  519. if (flags)
  520. {
  521. if (flags & XValue)
  522. *x = (Position) x_return;
  523. if (flags & XNegative)
  524. *x = (Position) (WidthOfScreen (XtScreen (w)) - XtWidth(w))
  525. + x_return;
  526. if (flags & YValue)
  527. *y = (Position) y_return;
  528. if (flags & YNegative)
  529. {
  530. *y = (Position) (HeightOfScreen (XtScreen (w)) - XtHeight(w))
  531. + y_return;
  532. }
  533. if (flags & XValue || flags & YValue || flags & XNegative ||
  534. flags & YNegative)
  535. {
  536. XtMoveWidget (w, *x, *y);
  537. }
  538. }
  539. }
  540. /************************************************************************
  541. *
  542. * WmPanelistShow
  543. *
  544. ************************************************************************/
  545. void
  546. WmPanelistShow (Widget w)
  547. {
  548. SwitchData * switch_data;
  549. Dimension switch_rc_height;
  550. Dimension switch_button_height;
  551. Dimension width = XtWidth(panel.shell);
  552. Dimension height = XtHeight(panel.shell);
  553. Position x = XtX(panel.shell);
  554. Position y = XtY(panel.shell);
  555. Dimension screen_width;
  556. Display * display;
  557. CompositeWidget cw;
  558. Widget * widget_list;
  559. DtWmHints vHints;
  560. String shell_geometry = NULL;
  561. char geometry_buffer[32];
  562. XSizeHints hints;
  563. long supplied;
  564. int i;
  565. Arg al[20];
  566. int ac;
  567. /* Find the switch data for later processing */
  568. switch_data = NULL;
  569. for (i = 0; i < panel.box_data_count; i++)
  570. {
  571. if (panel.box_data[i]->switch_data != NULL)
  572. {
  573. switch_data = panel.box_data[i]->switch_data;
  574. break;
  575. }
  576. }
  577. /* Realize the shell so that it is sized properly for later */
  578. /* positioning and child repositioning. */
  579. XtRealizeWidget (panel.shell);
  580. /* See if a geometry has been set. */
  581. ac = 0;
  582. XtSetArg (al[ac], XmNgeometry, &shell_geometry); ac++;
  583. XtGetValues (panel.shell, al, ac);
  584. /* If the shell has no default geometry, construct a default */
  585. /* which will center the panel along the bottom of the display */
  586. width = XtWidth (panel.shell);
  587. screen_width = WidthOfScreen (XtScreen (panel.shell));
  588. display = XtDisplay (panel.shell);
  589. if (shell_geometry == NULL)
  590. {
  591. Position x;
  592. if (panel.element_values[PANEL_GEOMETRY].string_value != NULL)
  593. {
  594. shell_geometry = panel.element_values[PANEL_GEOMETRY].parsed_value;
  595. }
  596. else
  597. {
  598. x = (screen_width > width) ? (Position)(screen_width - width) / 2 : 0;
  599. snprintf (geometry_buffer, 32 - 1, "+%d-0", x);
  600. shell_geometry = geometry_buffer;
  601. }
  602. XtSetArg (al[0], XmNgeometry, shell_geometry);
  603. XtSetValues (panel.shell, al, 1);
  604. }
  605. /* Adjust the positions of the buttons within the switch */
  606. /* so that they are spaced nicely. */
  607. if (switch_data != NULL)
  608. {
  609. UpdateSwitchGeometry (switch_data->box_data);
  610. /* Reposition or adjust the front panel if it is either off */
  611. /* the right edge of the screen or larger than the screen */
  612. if (width > screen_width)
  613. {
  614. Arg al[1];
  615. while (width > screen_width &&
  616. panel.switch_row_count < switch_data->switch_count)
  617. {
  618. panel.switch_row_count++;
  619. XtSetArg (al[0], XmNnumColumns, panel.switch_row_count);
  620. XtSetValues (switch_data->rc, al, 1);
  621. width = XtWidth (panel.shell);
  622. }
  623. }
  624. }
  625. SetGeometry (panel.shell, shell_geometry, &x, &y);
  626. WorkspaceAdjustPanelPosition (x, y, XtWidth (panel.shell),
  627. XtHeight (panel.shell));
  628. /* Set hints to avoid interactive placement */
  629. if (XGetWMNormalHints(display, XtWindow(panel.shell),
  630. &hints, &supplied) != 0)
  631. {
  632. hints.flags |= USPosition|USSize;
  633. XSetWMNormalHints(display, XtWindow(panel.shell), &hints);
  634. }
  635. /* Set the shells icon and title for when it is minimized */
  636. if (switch_data != NULL)
  637. {
  638. int current_workspace = switch_data->active_switch;
  639. XtSetArg (al[0], XmNiconName, switch_data->switch_names[current_workspace]);
  640. XtSetArg (al[1], XmNtitle, switch_data->switch_names[current_workspace]);
  641. XtSetValues (panel.shell, al, 2);
  642. }
  643. /* Set panel's window manager hints. */
  644. vHints.flags = DtWM_HINTS_BEHAVIORS;
  645. vHints.behaviors = DtWM_BEHAVIOR_PANEL;
  646. _DtWsmSetDtWmHints (XtDisplay(panel.shell), XtWindow (panel.shell), &vHints);
  647. /* Set the subpanel's transientShell to update transientFor and */
  648. /* Set the subpanel hints. */
  649. vHints.behaviors |= DtWM_BEHAVIOR_SUBPANEL;
  650. vHints.flags |= DtWM_HINTS_ATTACH_WINDOW;
  651. vHints.attachWindow = XtWindow (panel.shell);
  652. for (i = 0, widget_list = M_PopupList (panel.shell);
  653. i < M_NumPopups (panel.shell); i++)
  654. {
  655. cw = (CompositeWidget) widget_list[i];
  656. ac = 0;
  657. XtSetArg (al[ac], XmNtransientFor, NULL); ac++;
  658. XtSetValues ((Widget) cw, al, ac);
  659. ac = 0;
  660. XtSetArg (al[ac], XmNtransientFor, panel.shell); ac++;
  661. XtSetValues ((Widget) cw, al, ac);
  662. if (M_NumChildren (cw) > 0)
  663. {
  664. XtRealizeWidget ((M_Children (cw))[0]);
  665. _DtWsmSetDtWmHints (XtDisplay (panel.shell),
  666. XtWindow (widget_list[i]), &vHints);
  667. }
  668. }
  669. /* Set the push recall list and count into the window manager's */
  670. /* screen global data. */
  671. PushRecallSetData ();
  672. /* Set up the callback ot the workspace management API for */
  673. /* catching changes in workspace configuration. */
  674. DtWsmAddWorkspaceModifiedCallback(panel.shell,
  675. WorkspaceModifyCB, (XtPointer)switch_data);
  676. /* Get the front panel displayed */
  677. XtSetMappedWhenManaged (panel.shell, True);
  678. XtPopup (panel.shell, XtGrabNone);
  679. /* Restore the session information */
  680. SessionRestoreData ();
  681. /* Set up the window and geometry information for the embedded clients */
  682. for (i = 0; i < panel.embedded_client_count; i++)
  683. EmbeddedClientSetGeometry (&(((WmFpEmbeddedClientList) panel.embedded_client_list)[i]));
  684. /* Set the embedded client list and count into the window manager's */
  685. /* screen global data. */
  686. EmbeddedClientSetData ();
  687. }
  688. /************************************************************************
  689. *
  690. * WmPanelistAllocate
  691. *
  692. ************************************************************************/
  693. Widget
  694. WmPanelistAllocate (Widget w,
  695. XtPointer global_data,
  696. XtPointer screen_data)
  697. {
  698. Boolean create_fp;
  699. panel.app_name = wmGD.mwmName;
  700. create_fp = FrontPanelReadDatabases ();
  701. if (create_fp)
  702. {
  703. #ifdef DT_PERFORMANCE
  704. _DtPerfChkpntMsgSend("Begin creating front panel");
  705. #endif
  706. FrontPanelCreate (w);
  707. #ifdef DT_PERFORMANCE
  708. _DtPerfChkpntMsgSend("End creating front panel");
  709. #endif
  710. panel.global_data = global_data;
  711. panel.screen_data = screen_data;
  712. return (panel.form);
  713. }
  714. else
  715. return(NULL);
  716. }
  717. /************************************************************************
  718. *
  719. * WmSubpanelPosted
  720. * Add an event handler to catch when the subpanel is torn off. The
  721. * event handler will then change the subpanel's behavior to remain
  722. * displayed after a control is selected.
  723. *
  724. ************************************************************************/
  725. void
  726. WmSubpanelPosted (Display * display,
  727. Window shell_window)
  728. {
  729. BoxData * box_data;
  730. ControlData * main_control_data;
  731. SubpanelData * subpanel_data;
  732. int i, j;
  733. /* Loop through the main controls to find the subpanel whose */
  734. /* window matches the parameter shell window and then add the */
  735. /* event handler for tear off behavoir. */
  736. for (i = 0; i < panel.box_data_count; i++)
  737. {
  738. box_data = panel.box_data[i];
  739. for (j = 0; j < box_data->control_data_count; j++)
  740. {
  741. main_control_data = box_data->control_data[j];
  742. if (main_control_data->subpanel_data != NULL &&
  743. XtWindow (main_control_data->subpanel_data->shell) == shell_window)
  744. {
  745. subpanel_data = main_control_data->subpanel_data;
  746. subpanel_data->posted_x = XtX (subpanel_data->shell);
  747. XtAddEventHandler (subpanel_data->shell, StructureNotifyMask, False,
  748. (XtEventHandler) SubpanelTornEventHandler,
  749. (XtPointer) main_control_data);
  750. break;
  751. }
  752. }
  753. }
  754. }