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