dtfile: Add missing prototypes
[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 String none_string = NULL;
199     static String 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 = XtNewString (DTWM_REQP_BACKDROP_NONE)))
212     {
213         ToLower(no_backdrop_string);
214         xa_NO_BACKDROP = XmInternAtom (DISPLAY, no_backdrop_string, False);
215
216         /* for compatiblity with DT 2.01 */
217         none_string = XtNewString ("none");
218     }
219     if (!no_backdrop_string)
220     {
221         Warning(((char *)GETMESSAGE(6, 4, "Insufficient memory for backdrop window.")));
222         return;
223     }
224
225     pWS->backdrop.flags = BACKDROP_NONE;        /* by default */
226
227     /*
228      *  see if we're using a bitmap 
229      */
230     if (pWS->backdrop.image)
231     {
232         /*
233          * Strip off leading '@', if any
234          */
235         pch = (unsigned char *) pWS->backdrop.image;
236 #ifndef NO_MULTIBYTE
237         chlen = mblen ((char *)pch, MB_CUR_MAX);
238         if (chlen == 1 && *pch++ == '@')
239         {
240             chlen = mblen ((char *)pch, MB_CUR_MAX);
241             if (chlen >= 1)
242             {
243                 int j;
244                 int il = 1+strlen ((char *)pch);
245                 unsigned char *pchD = (unsigned char *)pWS->backdrop.image;
246
247                 while (il)
248                 {
249                     *pchD++ = *pch++;
250                     il--;
251                 }
252             }
253         }
254 #else /* NO_MULTIBYTE */
255         if (*pch++ == '@' && *pch)
256         {
257                 int il = 1+strlen ((char *)pch);
258                 unsigned char *pchD = (unsigned char *)pWS->backdrop.image;
259
260                 while (il)
261                 {
262                     *pchD++ = *pch++;
263                     il--;
264                 }
265         }
266 #endif /* NO_MULTIBYTE */
267
268         /*
269          * Use a copy of the string because our parsing routines
270          * destroy the thing being parsed. 
271          */
272
273         if ((pLine = pchImageName = (unsigned char *) 
274                             strdup (pWS->backdrop.image)) &&
275             (pch = GetString(&pLine)))
276         {
277             pchL = (unsigned char *) strdup ((char *)pch);
278
279             if (*pchL) 
280                 ToLower((char *)pchL);
281         
282             if (!(strcmp ((char *)pchL, (char *)no_backdrop_string)) ||
283                 !(strcmp ((char *)pchL, (char *)none_string)))
284             {
285                 /*
286                  * No backdrop (root window shows through)
287                  */
288                 pWS->backdrop.window = None;
289                 pWS->backdrop.nameAtom = xa_NO_BACKDROP;
290                 bNone = True;
291             }
292
293             if (pch && !bNone)
294             {
295                 /*
296                  * Bitmap backdrop 
297                  * Load in the bitmap, create a pixmap of
298                  * the right depth, and make the backdrop
299                  * window if necessary.
300                  */
301                 if ((callFlags & CHANGE_BACKDROP))
302                 {
303                     GC gc;
304                     Display *display;
305                     Window win;
306                     int status, x, y;
307                     unsigned int bw, depth, h, w, junk;
308
309                     /*
310                      * We're changing the backdrop, so the
311                      * imagePixmap actually contains a depth 1
312                      * pixmap. Convert it into a pixmap of the
313                      * proper depth.
314                      */
315                     tmpPix = pWS->backdrop.imagePixmap;
316                     if (XmUNSPECIFIED_PIXMAP != tmpPix)
317                     {
318                         display = XtDisplay(pWS->workspaceTopLevelW);
319                         XGetGeometry(
320                             display, tmpPix,
321                             &win, &x, &y, &w, &h, &bw, &depth);
322                         pWS->backdrop.imagePixmap =
323                           XCreatePixmap(display, tmpPix, w, h, depth);
324                         gc = XCreateGC(display, tmpPix, 0, NULL);
325                         status = XCopyArea(
326                                 XtDisplay(pWS->workspaceTopLevelW),
327                                 tmpPix, pWS->backdrop.imagePixmap, gc,
328                                 0, 0, w, h, 0, 0);
329                         XFreeGC(display, gc);
330                     }
331
332                     if (XmUNSPECIFIED_PIXMAP == tmpPix || BadDrawable == status)
333                       pWS->backdrop.imagePixmap = 
334                         WmXmGetPixmap2 (XtScreen(pWS->workspaceTopLevelW),
335                                  (char *)pch,
336                                  pWS->backdrop.foreground,
337                                  pWS->backdrop.background);
338                 }
339                 else 
340                 {
341                     pWS->backdrop.imagePixmap =
342                         WmXmGetPixmap2 (XtScreen(pWS->workspaceTopLevelW),
343                                  (char *)pch,
344                                  pWS->backdrop.foreground,
345                                  pWS->backdrop.background);
346                 }
347
348                 if ((callFlags & CHANGE_BACKDROP) &&
349                     (pWS->backdrop.window))
350                 {
351                     if (pWS->backdrop.imagePixmap !=
352                             XmUNSPECIFIED_PIXMAP)
353                     {
354                         XSetWindowBackgroundPixmap (DISPLAY,
355                             pWS->backdrop.window,
356                             pWS->backdrop.imagePixmap);
357                     }
358                     else
359                     {
360                         /*
361                          * Failed to find bitmap
362                          * set background to "background"
363                          */
364                         XSetWindowBackground (DISPLAY, 
365                             pWS->backdrop.window, 
366                             pWS->backdrop.background);
367                     }
368                 }
369                 else
370                 {
371                     if (pWS->backdrop.imagePixmap !=
372                             XmUNSPECIFIED_PIXMAP)
373                     {
374                         xswa.override_redirect = True;    
375                         xswa.background_pixmap = 
376                             pWS->backdrop.imagePixmap; 
377                         xswamask = CWOverrideRedirect | CWBackPixmap;
378                     }
379                     else
380                     {
381                         xswa.override_redirect = True;    
382                         xswa.background_pixel = 
383                             pWS->backdrop.background; 
384                         xswamask = CWOverrideRedirect | CWBackPixel;
385                     }
386
387                     if ((wmGD.keyboardFocusPolicy == 
388                                         KEYBOARD_FOCUS_POINTER) ||
389                         (wmGD.colormapFocusPolicy == 
390                                         CMAP_FOCUS_POINTER))
391                     {
392                         /*
393                          * Listen for enter/levae events if we
394                          * have a pointer tracking focus policy
395                          */
396                         xswamask |= CWEventMask;
397                         xswa.event_mask = EnterWindowMask | 
398                                                 LeaveWindowMask;
399                     }
400
401                     xswa.backing_store = NotUseful;
402                     xswa.save_under = False;
403                     xswamask |= (CWBackingStore | CWSaveUnder);
404
405                     pWS->backdrop.window = XCreateWindow(DISPLAY, 
406                        pWS->pSD->rootWindow, 
407                        0, 0, 
408                        DisplayWidth(DISPLAY, pWS->pSD->screen), 
409                        DisplayHeight(DISPLAY, pWS->pSD->screen),
410                        0, 
411                        XDefaultDepth(DISPLAY,pWS->pSD->screen), 
412                        CopyFromParent,
413                        CopyFromParent, 
414                        xswamask, 
415                        &xswa);
416
417                 }
418
419                 if (pch &&
420                     (pWS->backdrop.imagePixmap != XmUNSPECIFIED_PIXMAP) &&
421                     (pWS->backdrop.window))
422                 {
423                     /* 
424                      * Succeeded in setting up a bitmap backdrop.
425                      */
426                     pWS->backdrop.flags |= BACKDROP_BITMAP;
427
428                     pWS->backdrop.nameAtom = XmInternAtom (DISPLAY, 
429                                             pWS->backdrop.image, False);
430                 }
431                 else
432                 {
433                     char msg[MAXWMPATH+1];
434
435                     sprintf ((char *)msg, 
436                         ((char *)GETMESSAGE(6, 3, "Unable to get image %s for workspace %s.")),
437                         pWS->backdrop.image, pWS->name);
438
439                     Warning(msg);
440                 }
441                 pch = NULL;
442             }
443             if (pchImageName)
444             {
445                 free (pchImageName);    /* temporary string */
446             }
447             if (pchL)
448             {
449                 free (pchL);    /* temporary string */
450             }
451         }
452     }
453 }
454
455 \f
456 /******************************<->*************************************
457  *
458  *  static Pixmap WmXmGetPixmap2 
459  *
460  *  Description:
461  *  -----------
462  *  Tries twice to get a pixmap from a file name
463  *
464  *  Inputs:
465  *  ------
466  *  screen      - ptr to screen
467  *  pchName     - image file name
468  *  fg          - foreground color
469  *  bg          - background color
470  * 
471  *  Outputs:
472  *  -------
473  *  Return      -  pixmap if found, XmUNSPECIFIED_PIXMAP if not
474  *
475  *  Comments:
476  *  ---------
477  *  This routine performs some backward compatibility checks.
478  *
479  *  Do a two stage lookup for backdrop files. If a full path
480  *  is specified, but XmGetPixmap fails, the get the basename
481  *  of the file and try again. 
482  *
483  *************************************<->***********************************/
484 static Pixmap 
485 WmXmGetPixmap2 (
486         Screen          *screen,
487         char            *pchName,
488         Pixel           fg,
489         Pixel           bg)
490 {
491     Pixmap pixReturn;
492     char *pch;
493
494     if (pchName && *pchName) 
495     {
496         pixReturn = XmGetPixmap (screen, pchName, fg, bg);
497
498         if (pixReturn == XmUNSPECIFIED_PIXMAP)
499         {
500             /* 
501              * Use our bitmap lookup paths by using only the 
502              * basename of the file path.
503              */
504             pch = strrchr (pchName, '/');
505             if (pch && 
506                 (pch < (pchName + strlen(pchName) - 1)))
507             {
508                 pch++;
509                 pixReturn = XmGetPixmap (screen, pch, fg, bg);
510             }
511         }
512     }
513     else
514     {
515         pixReturn = XmUNSPECIFIED_PIXMAP;
516     }
517
518     return (pixReturn);
519 }
520
521
522 \f
523 /******************************<->*************************************
524  *
525  *  FullBitmapFilePath (pch)
526  *
527  *  Description:
528  *  -----------
529  *  Takes a bitmap file name turns it into a full path name.
530  *
531  *  Inputs:
532  *  ------
533  *  pch = ptr to bitmap file name
534  * 
535  *  Outputs:
536  *  -------
537  *  Return = ptr to a string containing full path name
538  *           or NULL on failure
539  *
540  *  Comments:
541  *  ---------
542  *
543  *************************************<->***********************************/
544 String 
545 FullBitmapFilePath(
546         String pch )
547 {
548     String pchR;
549     struct stat buf;
550
551     if (*pch != '/')
552     {
553         pchR = (String) BitmapPathName (pch);
554
555         if ((stat(pchR, &buf) == -1) &&
556             (*pch != '~'))
557         {
558             /* file not there! */
559             pchR = pch;
560         }
561     }
562     else
563     {
564         pchR = pch;
565     }
566     return (pchR);
567 }
568
569 \f
570 /******************************<->*************************************
571  *
572  *  SetNewBackdrop (pWS, pixmap, aName)
573  *
574  *  Description:
575  *  -----------
576  *  Sets a new backdrop for a workspace
577  *
578  *  Inputs:
579  *  ------
580  *  pWS = pointer to workspace data
581  *  pixmap = pixmap for the backdrop (if any)
582  *  aName = atomized name for the backdrop (either file name or "none")
583  * 
584  *  Outputs:
585  *  -------
586  *  Return = ptr to a string containing full path name
587  *           or NULL on failure
588  *
589  *  Comments:
590  *  ---------
591  *
592  *************************************<->***********************************/
593 void 
594 SetNewBackdrop(
595         WmWorkspaceData *pWS,
596         Pixmap pixmap,
597         String bitmapFile )
598 {
599     String pchNewBitmap = NULL;
600
601     if (!bitmapFile || !strlen(bitmapFile) || 
602         !strcmp(bitmapFile, DTWM_REQP_BACKDROP_NONE))
603     {
604         pixmap = None;
605     }
606
607     if (bitmapFile) 
608     {
609         pchNewBitmap = (String) XtNewString (bitmapFile);
610     }
611
612     /*
613      * Free up old resources 
614      */
615     if ((pWS->backdrop.imagePixmap) &&
616         (pWS->backdrop.imagePixmap != pixmap))
617     {
618         if (!XmDestroyPixmap (XtScreen(pWS->workspaceTopLevelW), 
619                         pWS->backdrop.imagePixmap))
620         {
621             /* not in Xm pixmap cache */
622         }
623         pWS->backdrop.imagePixmap = None;
624     }
625
626     /* free pWS->backdrop.image */
627     if ((pWS->backdrop.flags & BACKDROP_IMAGE_ALLOCED) &&
628         (pWS->backdrop.image))
629     {
630         free (pWS->backdrop.image);
631     }
632         
633     pWS->backdrop.imagePixmap = pixmap;
634     pWS->backdrop.image = pchNewBitmap;
635
636     ProcessBackdropResources (pWS, CHANGE_BACKDROP);
637
638     if (pchNewBitmap)
639     {
640         pWS->backdrop.flags |= BACKDROP_IMAGE_ALLOCED;
641     }
642
643     ChangeBackdrop (pWS);
644     SaveWorkspaceResources (pWS, WM_RES_BACKDROP_IMAGE);
645
646 #ifdef HP_VUE
647     UpdateWorkspaceInfoProperty (pWS->pSD); /* to be backward compatible */
648 #endif /* HP_VUE */
649     SetWorkspaceInfoProperty (pWS);
650
651     /*
652      * Inform the world of the new workspace title
653      */
654     dtSendWorkspaceModifyNotification(pWS->pSD, pWS->id, 
655                                                 DtWSM_REASON_BACKDROP);
656 }
657
658 \f
659 /******************************<->*************************************
660  *
661  *  Boolean IsBackdropWindow (pSD, win)
662  *
663  *  Description:
664  *  -----------
665  *  Tests a window to see if it is a backdrop window
666  *
667  *  Inputs:
668  *  ------
669  *  pSD = pointer to screen data
670  *  win = window to test.
671  * 
672  *  Outputs:
673  *  -------
674  *  Return = True if win is a backdrop window.
675  *           False otherwise.
676  *
677  *  Comments:
678  *  ---------
679  *
680  *************************************<->***********************************/
681 Boolean 
682 IsBackdropWindow(
683         WmScreenData *pSD,
684         Window win )
685 {
686     Boolean rval = False;
687     int i;
688
689     /*
690      * Is it one of the backdrop windows for a workspace?
691      */
692     for (i=0; (i < pSD->numWorkspaces) && !rval; i++)
693     {
694         if (pSD->pWS[i].backdrop.window == win)
695         {
696             rval = True;
697         }
698     }
699
700     return (rval);
701 }
702
703 #endif /* WSM */
704 /*********************        eof     ***************************/