WmBackdrop.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  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 1987,1988,1989,1990,1992,1993,1994 HEWLETT-PACKARD COMPANY
  25. * (c) Copyright 1993, 1994 International Business Machines Corp.
  26. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  27. * (c) Copyright 1993, 1994 Novell, Inc.
  28. */
  29. #define BANDWIDTH 16
  30. #define BOTTOM 0
  31. #define CHANGE_BACKDROP (1L << 0)
  32. #include "WmGlobal.h"
  33. #include "WmResource.h"
  34. #include "WmResNames.h"
  35. #include "WmWrkspace.h"
  36. #define DTWM_NEED_BACKBITS
  37. #include "WmIBitmap.h"
  38. #include "WmBackdrop.h"
  39. #include "WmError.h"
  40. #include "WmProperty.h"
  41. #include <X11/Core.h>
  42. #include <X11/StringDefs.h>
  43. #include <X11/Intrinsic.h>
  44. #include <X11/Xatom.h>
  45. #include <X11/Shell.h>
  46. #include <Dt/Message.h>
  47. #include <Dt/DtP.h>
  48. #include <Dt/WsmM.h>
  49. #include <Xm/Xm.h>
  50. #include <Xm/AtomMgr.h>
  51. #include <errno.h>
  52. #include <signal.h>
  53. #include <stdio.h>
  54. #include <sys/types.h>
  55. #include <sys/stat.h>
  56. #include <stdlib.h>
  57. #include "WmIPC.h" /* must be after DtP.h */
  58. /**************************************
  59. Functions
  60. **/
  61. /******** Static Function Declarations ********/
  62. static Pixmap WmXmGetPixmap2(
  63. Screen *screen,
  64. char *pchName,
  65. Pixel fg,
  66. Pixel bg
  67. ) ;
  68. /******** End Static Function Declarations ********/
  69. /*
  70. * externals
  71. */
  72. #include "WmImage.h"
  73. #include "WmResParse.h"
  74. /********************************************
  75. Globals
  76. **/
  77. /* maximum band width in tile units */
  78. #define MAX_BAND_WIDTH 3
  79. #define TOP_BAND_WIDTH 2
  80. static int bottom = BOTTOM;
  81. static int xa_NO_BACKDROP;
  82. /******************************<->*************************************
  83. *
  84. * ChangeBackdrop ( pWS )
  85. *
  86. *
  87. * Description:
  88. * -----------
  89. *
  90. * Inputs:
  91. * ------
  92. *
  93. * Outputs:
  94. * -------
  95. *
  96. *************************************<->***********************************/
  97. void
  98. ChangeBackdrop(
  99. WmWorkspaceData *pWS )
  100. {
  101. int iwin;
  102. if (pWS->backdrop.window)
  103. {
  104. if (pWS->backdrop.window == pWS->pSD->lastBackdropWin)
  105. {
  106. /* re-expose the window */
  107. XClearWindow (DISPLAY, pWS->backdrop.window);
  108. }
  109. else
  110. {
  111. /*
  112. * The old and new backdrops are different.
  113. * Map the new backdrop and unmap the old.
  114. */
  115. XLowerWindow(DISPLAY, pWS->backdrop.window);
  116. XMapWindow(DISPLAY, pWS->backdrop.window);
  117. }
  118. }
  119. if (pWS->pSD->lastBackdropWin &&
  120. (pWS->backdrop.window != pWS->pSD->lastBackdropWin))
  121. {
  122. XUnmapWindow(DISPLAY, pWS->pSD->lastBackdropWin);
  123. }
  124. pWS->pSD->lastBackdropWin = pWS->backdrop.window;
  125. }
  126. /******************************<->*************************************
  127. *
  128. * ProcessBackdropResources (pWS, callFlags)
  129. *
  130. * Description:
  131. * -----------
  132. * Processes a backdrop for a particular workspace
  133. *
  134. * Inputs:
  135. * ------
  136. * pWS = pointer to screen data (backdrop data in particular)
  137. * callFlags = processing flags
  138. * CHANGE_BACKDROP - the pixmap has already been created.
  139. *
  140. * Outputs:
  141. * -------
  142. * pWS = modifies the backdrop data that's part of this structure
  143. *
  144. * Comments:
  145. * ---------
  146. * This routine interprets the backdrop.image field and converts
  147. * it from a string to the appropriate bitmap/pixmap images.
  148. * It also creates windows necessary for the backdrop.
  149. *
  150. *************************************<->***********************************/
  151. void
  152. ProcessBackdropResources(
  153. WmWorkspaceData *pWS,
  154. unsigned long callFlags )
  155. {
  156. XSetWindowAttributes xswa;
  157. unsigned int xswamask;
  158. unsigned char *pchImageName = NULL;
  159. unsigned char *pchL = NULL;
  160. unsigned char *pch, *pLine;
  161. Pixmap tmpPix;
  162. int x, y;
  163. unsigned int w, h, bw, depth;
  164. Window root;
  165. unsigned long oldFlags;
  166. static String none_string = NULL;
  167. static String no_backdrop_string = NULL;
  168. Boolean bNone = False;
  169. unsigned int chlen;
  170. if (callFlags & CHANGE_BACKDROP)
  171. {
  172. oldFlags = pWS->backdrop.flags;
  173. }
  174. if (!no_backdrop_string &&
  175. (no_backdrop_string = XtNewString (DTWM_REQP_BACKDROP_NONE)))
  176. {
  177. ToLower(no_backdrop_string);
  178. xa_NO_BACKDROP = XmInternAtom (DISPLAY, no_backdrop_string, False);
  179. /* for compatiblity with DT 2.01 */
  180. none_string = XtNewString ("none");
  181. }
  182. if (!no_backdrop_string)
  183. {
  184. Warning(((char *)GETMESSAGE(6, 4, "Insufficient memory for backdrop window.")));
  185. return;
  186. }
  187. pWS->backdrop.flags = BACKDROP_NONE; /* by default */
  188. /*
  189. * see if we're using a bitmap
  190. */
  191. if (pWS->backdrop.image)
  192. {
  193. /*
  194. * Strip off leading '@', if any
  195. */
  196. pch = (unsigned char *) pWS->backdrop.image;
  197. chlen = mblen ((char *)pch, MB_CUR_MAX);
  198. if (chlen == 1 && *pch++ == '@')
  199. {
  200. chlen = mblen ((char *)pch, MB_CUR_MAX);
  201. if (chlen >= 1)
  202. {
  203. int j;
  204. int il = 1+strlen ((char *)pch);
  205. unsigned char *pchD = (unsigned char *)pWS->backdrop.image;
  206. while (il)
  207. {
  208. *pchD++ = *pch++;
  209. il--;
  210. }
  211. }
  212. }
  213. /*
  214. * Use a copy of the string because our parsing routines
  215. * destroy the thing being parsed.
  216. */
  217. if ((pLine = pchImageName = (unsigned char *)
  218. strdup (pWS->backdrop.image)) &&
  219. (pch = GetString(&pLine)))
  220. {
  221. pchL = (unsigned char *) strdup ((char *)pch);
  222. if (*pchL)
  223. ToLower((char *)pchL);
  224. if (!(strcmp ((char *)pchL, (char *)no_backdrop_string)) ||
  225. !(strcmp ((char *)pchL, (char *)none_string)))
  226. {
  227. /*
  228. * No backdrop (root window shows through)
  229. */
  230. pWS->backdrop.window = None;
  231. pWS->backdrop.nameAtom = xa_NO_BACKDROP;
  232. bNone = True;
  233. }
  234. if (pch && !bNone)
  235. {
  236. /*
  237. * Bitmap backdrop
  238. * Load in the bitmap, create a pixmap of
  239. * the right depth, and make the backdrop
  240. * window if necessary.
  241. */
  242. if ((callFlags & CHANGE_BACKDROP))
  243. {
  244. GC gc;
  245. Display *display;
  246. Window win;
  247. int status, x, y;
  248. unsigned int bw, depth, h, w, junk;
  249. /*
  250. * We're changing the backdrop, so the
  251. * imagePixmap actually contains a depth 1
  252. * pixmap. Convert it into a pixmap of the
  253. * proper depth.
  254. */
  255. tmpPix = pWS->backdrop.imagePixmap;
  256. if (XmUNSPECIFIED_PIXMAP != tmpPix)
  257. {
  258. display = XtDisplay(pWS->workspaceTopLevelW);
  259. XGetGeometry(
  260. display, tmpPix,
  261. &win, &x, &y, &w, &h, &bw, &depth);
  262. pWS->backdrop.imagePixmap =
  263. XCreatePixmap(display, tmpPix, w, h, depth);
  264. gc = XCreateGC(display, tmpPix, 0, NULL);
  265. status = XCopyArea(
  266. XtDisplay(pWS->workspaceTopLevelW),
  267. tmpPix, pWS->backdrop.imagePixmap, gc,
  268. 0, 0, w, h, 0, 0);
  269. XFreeGC(display, gc);
  270. }
  271. if (XmUNSPECIFIED_PIXMAP == tmpPix || BadDrawable == status)
  272. pWS->backdrop.imagePixmap =
  273. WmXmGetPixmap2 (XtScreen(pWS->workspaceTopLevelW),
  274. (char *)pch,
  275. pWS->backdrop.foreground,
  276. pWS->backdrop.background);
  277. }
  278. else
  279. {
  280. pWS->backdrop.imagePixmap =
  281. WmXmGetPixmap2 (XtScreen(pWS->workspaceTopLevelW),
  282. (char *)pch,
  283. pWS->backdrop.foreground,
  284. pWS->backdrop.background);
  285. }
  286. if ((callFlags & CHANGE_BACKDROP) &&
  287. (pWS->backdrop.window))
  288. {
  289. if (pWS->backdrop.imagePixmap !=
  290. XmUNSPECIFIED_PIXMAP)
  291. {
  292. XSetWindowBackgroundPixmap (DISPLAY,
  293. pWS->backdrop.window,
  294. pWS->backdrop.imagePixmap);
  295. }
  296. else
  297. {
  298. /*
  299. * Failed to find bitmap
  300. * set background to "background"
  301. */
  302. XSetWindowBackground (DISPLAY,
  303. pWS->backdrop.window,
  304. pWS->backdrop.background);
  305. }
  306. }
  307. else
  308. {
  309. if (pWS->backdrop.imagePixmap !=
  310. XmUNSPECIFIED_PIXMAP)
  311. {
  312. xswa.override_redirect = True;
  313. xswa.background_pixmap =
  314. pWS->backdrop.imagePixmap;
  315. xswamask = CWOverrideRedirect | CWBackPixmap;
  316. }
  317. else
  318. {
  319. xswa.override_redirect = True;
  320. xswa.background_pixel =
  321. pWS->backdrop.background;
  322. xswamask = CWOverrideRedirect | CWBackPixel;
  323. }
  324. if ((wmGD.keyboardFocusPolicy ==
  325. KEYBOARD_FOCUS_POINTER) ||
  326. (wmGD.colormapFocusPolicy ==
  327. CMAP_FOCUS_POINTER))
  328. {
  329. /*
  330. * Listen for enter/levae events if we
  331. * have a pointer tracking focus policy
  332. */
  333. xswamask |= CWEventMask;
  334. xswa.event_mask = EnterWindowMask |
  335. LeaveWindowMask;
  336. }
  337. xswa.backing_store = NotUseful;
  338. xswa.save_under = False;
  339. xswamask |= (CWBackingStore | CWSaveUnder);
  340. pWS->backdrop.window = XCreateWindow(DISPLAY,
  341. pWS->pSD->rootWindow,
  342. 0, 0,
  343. DisplayWidth(DISPLAY, pWS->pSD->screen),
  344. DisplayHeight(DISPLAY, pWS->pSD->screen),
  345. 0,
  346. XDefaultDepth(DISPLAY,pWS->pSD->screen),
  347. CopyFromParent,
  348. CopyFromParent,
  349. xswamask,
  350. &xswa);
  351. }
  352. if (pch &&
  353. (pWS->backdrop.imagePixmap != XmUNSPECIFIED_PIXMAP) &&
  354. (pWS->backdrop.window))
  355. {
  356. /*
  357. * Succeeded in setting up a bitmap backdrop.
  358. */
  359. pWS->backdrop.flags |= BACKDROP_BITMAP;
  360. pWS->backdrop.nameAtom = XmInternAtom (DISPLAY,
  361. pWS->backdrop.image, False);
  362. }
  363. else
  364. {
  365. char msg[MAXWMPATH+1];
  366. sprintf ((char *)msg,
  367. ((char *)GETMESSAGE(6, 3, "Unable to get image %s for workspace %s.")),
  368. pWS->backdrop.image, pWS->name);
  369. Warning(msg);
  370. }
  371. pch = NULL;
  372. }
  373. free (pchImageName); /* temporary string */
  374. pchImageName = NULL;
  375. free (pchL); /* temporary string */
  376. }
  377. }
  378. free (pchImageName);
  379. }
  380. /******************************<->*************************************
  381. *
  382. * static Pixmap WmXmGetPixmap2
  383. *
  384. * Description:
  385. * -----------
  386. * Tries twice to get a pixmap from a file name
  387. *
  388. * Inputs:
  389. * ------
  390. * screen - ptr to screen
  391. * pchName - image file name
  392. * fg - foreground color
  393. * bg - background color
  394. *
  395. * Outputs:
  396. * -------
  397. * Return - pixmap if found, XmUNSPECIFIED_PIXMAP if not
  398. *
  399. * Comments:
  400. * ---------
  401. * This routine performs some backward compatibility checks.
  402. *
  403. * Do a two stage lookup for backdrop files. If a full path
  404. * is specified, but XmGetPixmap fails, the get the basename
  405. * of the file and try again.
  406. *
  407. *************************************<->***********************************/
  408. static Pixmap
  409. WmXmGetPixmap2 (
  410. Screen *screen,
  411. char *pchName,
  412. Pixel fg,
  413. Pixel bg)
  414. {
  415. Pixmap pixReturn;
  416. char *pch;
  417. if (pchName && *pchName)
  418. {
  419. pixReturn = XmGetPixmap (screen, pchName, fg, bg);
  420. if (pixReturn == XmUNSPECIFIED_PIXMAP)
  421. {
  422. /*
  423. * Use our bitmap lookup paths by using only the
  424. * basename of the file path.
  425. */
  426. pch = strrchr (pchName, '/');
  427. if (pch &&
  428. (pch < (pchName + strlen(pchName) - 1)))
  429. {
  430. pch++;
  431. pixReturn = XmGetPixmap (screen, pch, fg, bg);
  432. }
  433. }
  434. }
  435. else
  436. {
  437. pixReturn = XmUNSPECIFIED_PIXMAP;
  438. }
  439. return (pixReturn);
  440. }
  441. /******************************<->*************************************
  442. *
  443. * FullBitmapFilePath (pch)
  444. *
  445. * Description:
  446. * -----------
  447. * Takes a bitmap file name turns it into a full path name.
  448. *
  449. * Inputs:
  450. * ------
  451. * pch = ptr to bitmap file name
  452. *
  453. * Outputs:
  454. * -------
  455. * Return = ptr to a string containing full path name
  456. * or NULL on failure
  457. *
  458. * Comments:
  459. * ---------
  460. *
  461. *************************************<->***********************************/
  462. String
  463. FullBitmapFilePath(
  464. String pch )
  465. {
  466. String pchR;
  467. struct stat buf;
  468. if (*pch != '/')
  469. {
  470. pchR = (String) BitmapPathName (pch);
  471. if ((stat(pchR, &buf) == -1) &&
  472. (*pch != '~'))
  473. {
  474. /* file not there! */
  475. pchR = pch;
  476. }
  477. }
  478. else
  479. {
  480. pchR = pch;
  481. }
  482. return (pchR);
  483. }
  484. /******************************<->*************************************
  485. *
  486. * SetNewBackdrop (pWS, pixmap, aName)
  487. *
  488. * Description:
  489. * -----------
  490. * Sets a new backdrop for a workspace
  491. *
  492. * Inputs:
  493. * ------
  494. * pWS = pointer to workspace data
  495. * pixmap = pixmap for the backdrop (if any)
  496. * aName = atomized name for the backdrop (either file name or "none")
  497. *
  498. * Outputs:
  499. * -------
  500. * Return = ptr to a string containing full path name
  501. * or NULL on failure
  502. *
  503. * Comments:
  504. * ---------
  505. *
  506. *************************************<->***********************************/
  507. void
  508. SetNewBackdrop(
  509. WmWorkspaceData *pWS,
  510. Pixmap pixmap,
  511. String bitmapFile )
  512. {
  513. String pchNewBitmap = NULL;
  514. if (!bitmapFile || !strlen(bitmapFile) ||
  515. !strcmp(bitmapFile, DTWM_REQP_BACKDROP_NONE))
  516. {
  517. pixmap = None;
  518. }
  519. if (bitmapFile)
  520. {
  521. pchNewBitmap = (String) XtNewString (bitmapFile);
  522. }
  523. /*
  524. * Free up old resources
  525. */
  526. if ((pWS->backdrop.imagePixmap) &&
  527. (pWS->backdrop.imagePixmap != pixmap))
  528. {
  529. if (!XmDestroyPixmap (XtScreen(pWS->workspaceTopLevelW),
  530. pWS->backdrop.imagePixmap))
  531. {
  532. /* not in Xm pixmap cache */
  533. }
  534. pWS->backdrop.imagePixmap = None;
  535. }
  536. /* free pWS->backdrop.image */
  537. if ((pWS->backdrop.flags & BACKDROP_IMAGE_ALLOCED) &&
  538. (pWS->backdrop.image))
  539. {
  540. free (pWS->backdrop.image);
  541. }
  542. pWS->backdrop.imagePixmap = pixmap;
  543. pWS->backdrop.image = pchNewBitmap;
  544. ProcessBackdropResources (pWS, CHANGE_BACKDROP);
  545. if (pchNewBitmap)
  546. {
  547. pWS->backdrop.flags |= BACKDROP_IMAGE_ALLOCED;
  548. }
  549. ChangeBackdrop (pWS);
  550. SaveWorkspaceResources (pWS, WM_RES_BACKDROP_IMAGE);
  551. SetWorkspaceInfoProperty (pWS);
  552. /*
  553. * Inform the world of the new workspace title
  554. */
  555. dtSendWorkspaceModifyNotification(pWS->pSD, pWS->id,
  556. DtWSM_REASON_BACKDROP);
  557. }
  558. /******************************<->*************************************
  559. *
  560. * Boolean IsBackdropWindow (pSD, win)
  561. *
  562. * Description:
  563. * -----------
  564. * Tests a window to see if it is a backdrop window
  565. *
  566. * Inputs:
  567. * ------
  568. * pSD = pointer to screen data
  569. * win = window to test.
  570. *
  571. * Outputs:
  572. * -------
  573. * Return = True if win is a backdrop window.
  574. * False otherwise.
  575. *
  576. * Comments:
  577. * ---------
  578. *
  579. *************************************<->***********************************/
  580. Boolean
  581. IsBackdropWindow(
  582. WmScreenData *pSD,
  583. Window win )
  584. {
  585. Boolean rval = False;
  586. int i;
  587. /*
  588. * Is it one of the backdrop windows for a workspace?
  589. */
  590. for (i=0; (i < pSD->numWorkspaces) && !rval; i++)
  591. {
  592. if (pSD->pWS[i].backdrop.window == win)
  593. {
  594. rval = True;
  595. }
  596. }
  597. return (rval);
  598. }
  599. /********************* eof ***************************/