676 lines
15 KiB
C
676 lines
15 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
* (c) Copyright 1987,1988,1989,1990,1992,1993,1994 HEWLETT-PACKARD COMPANY
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp.
|
|
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
* (c) Copyright 1993, 1994 Novell, Inc.
|
|
*/
|
|
|
|
#define BANDWIDTH 16
|
|
#define BOTTOM 0
|
|
#define CHANGE_BACKDROP (1L << 0)
|
|
|
|
#include "WmGlobal.h"
|
|
#include "WmResource.h"
|
|
#include "WmResNames.h"
|
|
#include "WmWrkspace.h"
|
|
#define DTWM_NEED_BACKBITS
|
|
#include "WmIBitmap.h"
|
|
#include "WmBackdrop.h"
|
|
#include "WmError.h"
|
|
#include "WmProperty.h"
|
|
#include <X11/Core.h>
|
|
#include <X11/StringDefs.h>
|
|
#include <X11/Intrinsic.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Shell.h>
|
|
#include <Dt/Message.h>
|
|
#include <Dt/DtP.h>
|
|
#include <Dt/WsmM.h>
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/AtomMgr.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <stdlib.h>
|
|
#include "WmIPC.h" /* must be after DtP.h */
|
|
|
|
/**************************************
|
|
Functions
|
|
**/
|
|
/******** Static Function Declarations ********/
|
|
|
|
static Pixmap WmXmGetPixmap2(
|
|
Screen *screen,
|
|
char *pchName,
|
|
Pixel fg,
|
|
Pixel bg
|
|
) ;
|
|
|
|
/******** End Static Function Declarations ********/
|
|
|
|
/*
|
|
* externals
|
|
*/
|
|
#include "WmImage.h"
|
|
#include "WmResParse.h"
|
|
|
|
/********************************************
|
|
Globals
|
|
**/
|
|
|
|
/* maximum band width in tile units */
|
|
#define MAX_BAND_WIDTH 3
|
|
#define TOP_BAND_WIDTH 2
|
|
|
|
static int bottom = BOTTOM;
|
|
|
|
static int xa_NO_BACKDROP;
|
|
|
|
|
|
|
|
|
|
/******************************<->*************************************
|
|
*
|
|
* ChangeBackdrop ( pWS )
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*************************************<->***********************************/
|
|
void
|
|
ChangeBackdrop(
|
|
WmWorkspaceData *pWS )
|
|
{
|
|
int iwin;
|
|
|
|
|
|
if (pWS->backdrop.window)
|
|
{
|
|
if (pWS->backdrop.window == pWS->pSD->lastBackdropWin)
|
|
{
|
|
/* re-expose the window */
|
|
XClearWindow (DISPLAY, pWS->backdrop.window);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The old and new backdrops are different.
|
|
* Map the new backdrop and unmap the old.
|
|
*/
|
|
XLowerWindow(DISPLAY, pWS->backdrop.window);
|
|
|
|
XMapWindow(DISPLAY, pWS->backdrop.window);
|
|
}
|
|
}
|
|
|
|
if (pWS->pSD->lastBackdropWin &&
|
|
(pWS->backdrop.window != pWS->pSD->lastBackdropWin))
|
|
{
|
|
XUnmapWindow(DISPLAY, pWS->pSD->lastBackdropWin);
|
|
}
|
|
|
|
pWS->pSD->lastBackdropWin = pWS->backdrop.window;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************<->*************************************
|
|
*
|
|
* ProcessBackdropResources (pWS, callFlags)
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Processes a backdrop for a particular workspace
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pWS = pointer to screen data (backdrop data in particular)
|
|
* callFlags = processing flags
|
|
* CHANGE_BACKDROP - the pixmap has already been created.
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* pWS = modifies the backdrop data that's part of this structure
|
|
*
|
|
* Comments:
|
|
* ---------
|
|
* This routine interprets the backdrop.image field and converts
|
|
* it from a string to the appropriate bitmap/pixmap images.
|
|
* It also creates windows necessary for the backdrop.
|
|
*
|
|
*************************************<->***********************************/
|
|
void
|
|
ProcessBackdropResources(
|
|
WmWorkspaceData *pWS,
|
|
unsigned long callFlags )
|
|
{
|
|
XSetWindowAttributes xswa;
|
|
unsigned int xswamask;
|
|
unsigned char *pchImageName = NULL;
|
|
unsigned char *pchL = NULL;
|
|
unsigned char *pch, *pLine;
|
|
Pixmap tmpPix;
|
|
int x, y;
|
|
unsigned int w, h, bw, depth;
|
|
Window root;
|
|
unsigned long oldFlags;
|
|
static String none_string = NULL;
|
|
static String no_backdrop_string = NULL;
|
|
Boolean bNone = False;
|
|
unsigned int chlen;
|
|
|
|
if (callFlags & CHANGE_BACKDROP)
|
|
{
|
|
oldFlags = pWS->backdrop.flags;
|
|
}
|
|
|
|
if (!no_backdrop_string &&
|
|
(no_backdrop_string = XtNewString (DTWM_REQP_BACKDROP_NONE)))
|
|
{
|
|
ToLower(no_backdrop_string);
|
|
xa_NO_BACKDROP = XmInternAtom (DISPLAY, no_backdrop_string, False);
|
|
|
|
/* for compatiblity with DT 2.01 */
|
|
none_string = XtNewString ("none");
|
|
}
|
|
if (!no_backdrop_string)
|
|
{
|
|
Warning(((char *)GETMESSAGE(6, 4, "Insufficient memory for backdrop window.")));
|
|
return;
|
|
}
|
|
|
|
pWS->backdrop.flags = BACKDROP_NONE; /* by default */
|
|
|
|
/*
|
|
* see if we're using a bitmap
|
|
*/
|
|
if (pWS->backdrop.image)
|
|
{
|
|
/*
|
|
* Strip off leading '@', if any
|
|
*/
|
|
pch = (unsigned char *) pWS->backdrop.image;
|
|
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
|
if (chlen == 1 && *pch++ == '@')
|
|
{
|
|
chlen = mblen ((char *)pch, MB_CUR_MAX);
|
|
if (chlen >= 1)
|
|
{
|
|
int j;
|
|
int il = 1+strlen ((char *)pch);
|
|
unsigned char *pchD = (unsigned char *)pWS->backdrop.image;
|
|
|
|
while (il)
|
|
{
|
|
*pchD++ = *pch++;
|
|
il--;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Use a copy of the string because our parsing routines
|
|
* destroy the thing being parsed.
|
|
*/
|
|
|
|
if ((pLine = pchImageName = (unsigned char *)
|
|
strdup (pWS->backdrop.image)) &&
|
|
(pch = GetString(&pLine)))
|
|
{
|
|
pchL = (unsigned char *) strdup ((char *)pch);
|
|
|
|
if (*pchL)
|
|
ToLower((char *)pchL);
|
|
|
|
if (!(strcmp ((char *)pchL, (char *)no_backdrop_string)) ||
|
|
!(strcmp ((char *)pchL, (char *)none_string)))
|
|
{
|
|
/*
|
|
* No backdrop (root window shows through)
|
|
*/
|
|
pWS->backdrop.window = None;
|
|
pWS->backdrop.nameAtom = xa_NO_BACKDROP;
|
|
bNone = True;
|
|
}
|
|
|
|
if (pch && !bNone)
|
|
{
|
|
/*
|
|
* Bitmap backdrop
|
|
* Load in the bitmap, create a pixmap of
|
|
* the right depth, and make the backdrop
|
|
* window if necessary.
|
|
*/
|
|
if ((callFlags & CHANGE_BACKDROP))
|
|
{
|
|
GC gc;
|
|
Display *display;
|
|
Window win;
|
|
int status, x, y;
|
|
unsigned int bw, depth, h, w, junk;
|
|
|
|
/*
|
|
* We're changing the backdrop, so the
|
|
* imagePixmap actually contains a depth 1
|
|
* pixmap. Convert it into a pixmap of the
|
|
* proper depth.
|
|
*/
|
|
tmpPix = pWS->backdrop.imagePixmap;
|
|
if (XmUNSPECIFIED_PIXMAP != tmpPix)
|
|
{
|
|
display = XtDisplay(pWS->workspaceTopLevelW);
|
|
XGetGeometry(
|
|
display, tmpPix,
|
|
&win, &x, &y, &w, &h, &bw, &depth);
|
|
pWS->backdrop.imagePixmap =
|
|
XCreatePixmap(display, tmpPix, w, h, depth);
|
|
gc = XCreateGC(display, tmpPix, 0, NULL);
|
|
status = XCopyArea(
|
|
XtDisplay(pWS->workspaceTopLevelW),
|
|
tmpPix, pWS->backdrop.imagePixmap, gc,
|
|
0, 0, w, h, 0, 0);
|
|
XFreeGC(display, gc);
|
|
}
|
|
|
|
if (XmUNSPECIFIED_PIXMAP == tmpPix || BadDrawable == status)
|
|
pWS->backdrop.imagePixmap =
|
|
WmXmGetPixmap2 (XtScreen(pWS->workspaceTopLevelW),
|
|
(char *)pch,
|
|
pWS->backdrop.foreground,
|
|
pWS->backdrop.background);
|
|
}
|
|
else
|
|
{
|
|
pWS->backdrop.imagePixmap =
|
|
WmXmGetPixmap2 (XtScreen(pWS->workspaceTopLevelW),
|
|
(char *)pch,
|
|
pWS->backdrop.foreground,
|
|
pWS->backdrop.background);
|
|
}
|
|
|
|
if ((callFlags & CHANGE_BACKDROP) &&
|
|
(pWS->backdrop.window))
|
|
{
|
|
if (pWS->backdrop.imagePixmap !=
|
|
XmUNSPECIFIED_PIXMAP)
|
|
{
|
|
XSetWindowBackgroundPixmap (DISPLAY,
|
|
pWS->backdrop.window,
|
|
pWS->backdrop.imagePixmap);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Failed to find bitmap
|
|
* set background to "background"
|
|
*/
|
|
XSetWindowBackground (DISPLAY,
|
|
pWS->backdrop.window,
|
|
pWS->backdrop.background);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pWS->backdrop.imagePixmap !=
|
|
XmUNSPECIFIED_PIXMAP)
|
|
{
|
|
xswa.override_redirect = True;
|
|
xswa.background_pixmap =
|
|
pWS->backdrop.imagePixmap;
|
|
xswamask = CWOverrideRedirect | CWBackPixmap;
|
|
}
|
|
else
|
|
{
|
|
xswa.override_redirect = True;
|
|
xswa.background_pixel =
|
|
pWS->backdrop.background;
|
|
xswamask = CWOverrideRedirect | CWBackPixel;
|
|
}
|
|
|
|
if ((wmGD.keyboardFocusPolicy ==
|
|
KEYBOARD_FOCUS_POINTER) ||
|
|
(wmGD.colormapFocusPolicy ==
|
|
CMAP_FOCUS_POINTER))
|
|
{
|
|
/*
|
|
* Listen for enter/levae events if we
|
|
* have a pointer tracking focus policy
|
|
*/
|
|
xswamask |= CWEventMask;
|
|
xswa.event_mask = EnterWindowMask |
|
|
LeaveWindowMask;
|
|
}
|
|
|
|
xswa.backing_store = NotUseful;
|
|
xswa.save_under = False;
|
|
xswamask |= (CWBackingStore | CWSaveUnder);
|
|
|
|
pWS->backdrop.window = XCreateWindow(DISPLAY,
|
|
pWS->pSD->rootWindow,
|
|
0, 0,
|
|
DisplayWidth(DISPLAY, pWS->pSD->screen),
|
|
DisplayHeight(DISPLAY, pWS->pSD->screen),
|
|
0,
|
|
XDefaultDepth(DISPLAY,pWS->pSD->screen),
|
|
CopyFromParent,
|
|
CopyFromParent,
|
|
xswamask,
|
|
&xswa);
|
|
|
|
}
|
|
|
|
if (pch &&
|
|
(pWS->backdrop.imagePixmap != XmUNSPECIFIED_PIXMAP) &&
|
|
(pWS->backdrop.window))
|
|
{
|
|
/*
|
|
* Succeeded in setting up a bitmap backdrop.
|
|
*/
|
|
pWS->backdrop.flags |= BACKDROP_BITMAP;
|
|
|
|
pWS->backdrop.nameAtom = XmInternAtom (DISPLAY,
|
|
pWS->backdrop.image, False);
|
|
}
|
|
else
|
|
{
|
|
char msg[MAXWMPATH+1];
|
|
|
|
sprintf ((char *)msg,
|
|
((char *)GETMESSAGE(6, 3, "Unable to get image %s for workspace %s.")),
|
|
pWS->backdrop.image, pWS->name);
|
|
|
|
Warning(msg);
|
|
}
|
|
pch = NULL;
|
|
}
|
|
free (pchImageName); /* temporary string */
|
|
pchImageName = NULL;
|
|
free (pchL); /* temporary string */
|
|
}
|
|
}
|
|
|
|
free (pchImageName);
|
|
}
|
|
|
|
|
|
/******************************<->*************************************
|
|
*
|
|
* static Pixmap WmXmGetPixmap2
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Tries twice to get a pixmap from a file name
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* screen - ptr to screen
|
|
* pchName - image file name
|
|
* fg - foreground color
|
|
* bg - background color
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return - pixmap if found, XmUNSPECIFIED_PIXMAP if not
|
|
*
|
|
* Comments:
|
|
* ---------
|
|
* This routine performs some backward compatibility checks.
|
|
*
|
|
* Do a two stage lookup for backdrop files. If a full path
|
|
* is specified, but XmGetPixmap fails, the get the basename
|
|
* of the file and try again.
|
|
*
|
|
*************************************<->***********************************/
|
|
static Pixmap
|
|
WmXmGetPixmap2 (
|
|
Screen *screen,
|
|
char *pchName,
|
|
Pixel fg,
|
|
Pixel bg)
|
|
{
|
|
Pixmap pixReturn;
|
|
char *pch;
|
|
|
|
if (pchName && *pchName)
|
|
{
|
|
pixReturn = XmGetPixmap (screen, pchName, fg, bg);
|
|
|
|
if (pixReturn == XmUNSPECIFIED_PIXMAP)
|
|
{
|
|
/*
|
|
* Use our bitmap lookup paths by using only the
|
|
* basename of the file path.
|
|
*/
|
|
pch = strrchr (pchName, '/');
|
|
if (pch &&
|
|
(pch < (pchName + strlen(pchName) - 1)))
|
|
{
|
|
pch++;
|
|
pixReturn = XmGetPixmap (screen, pch, fg, bg);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pixReturn = XmUNSPECIFIED_PIXMAP;
|
|
}
|
|
|
|
return (pixReturn);
|
|
}
|
|
|
|
|
|
|
|
/******************************<->*************************************
|
|
*
|
|
* FullBitmapFilePath (pch)
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Takes a bitmap file name turns it into a full path name.
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pch = ptr to bitmap file name
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return = ptr to a string containing full path name
|
|
* or NULL on failure
|
|
*
|
|
* Comments:
|
|
* ---------
|
|
*
|
|
*************************************<->***********************************/
|
|
String
|
|
FullBitmapFilePath(
|
|
String pch )
|
|
{
|
|
String pchR;
|
|
struct stat buf;
|
|
|
|
if (*pch != '/')
|
|
{
|
|
pchR = (String) BitmapPathName (pch);
|
|
|
|
if ((stat(pchR, &buf) == -1) &&
|
|
(*pch != '~'))
|
|
{
|
|
/* file not there! */
|
|
pchR = pch;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pchR = pch;
|
|
}
|
|
return (pchR);
|
|
}
|
|
|
|
|
|
/******************************<->*************************************
|
|
*
|
|
* SetNewBackdrop (pWS, pixmap, aName)
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Sets a new backdrop for a workspace
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pWS = pointer to workspace data
|
|
* pixmap = pixmap for the backdrop (if any)
|
|
* aName = atomized name for the backdrop (either file name or "none")
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return = ptr to a string containing full path name
|
|
* or NULL on failure
|
|
*
|
|
* Comments:
|
|
* ---------
|
|
*
|
|
*************************************<->***********************************/
|
|
void
|
|
SetNewBackdrop(
|
|
WmWorkspaceData *pWS,
|
|
Pixmap pixmap,
|
|
String bitmapFile )
|
|
{
|
|
String pchNewBitmap = NULL;
|
|
|
|
if (!bitmapFile || !strlen(bitmapFile) ||
|
|
!strcmp(bitmapFile, DTWM_REQP_BACKDROP_NONE))
|
|
{
|
|
pixmap = None;
|
|
}
|
|
|
|
if (bitmapFile)
|
|
{
|
|
pchNewBitmap = (String) XtNewString (bitmapFile);
|
|
}
|
|
|
|
/*
|
|
* Free up old resources
|
|
*/
|
|
if ((pWS->backdrop.imagePixmap) &&
|
|
(pWS->backdrop.imagePixmap != pixmap))
|
|
{
|
|
if (!XmDestroyPixmap (XtScreen(pWS->workspaceTopLevelW),
|
|
pWS->backdrop.imagePixmap))
|
|
{
|
|
/* not in Xm pixmap cache */
|
|
}
|
|
pWS->backdrop.imagePixmap = None;
|
|
}
|
|
|
|
/* free pWS->backdrop.image */
|
|
if ((pWS->backdrop.flags & BACKDROP_IMAGE_ALLOCED) &&
|
|
(pWS->backdrop.image))
|
|
{
|
|
free (pWS->backdrop.image);
|
|
}
|
|
|
|
pWS->backdrop.imagePixmap = pixmap;
|
|
pWS->backdrop.image = pchNewBitmap;
|
|
|
|
ProcessBackdropResources (pWS, CHANGE_BACKDROP);
|
|
|
|
if (pchNewBitmap)
|
|
{
|
|
pWS->backdrop.flags |= BACKDROP_IMAGE_ALLOCED;
|
|
}
|
|
|
|
ChangeBackdrop (pWS);
|
|
SaveWorkspaceResources (pWS, WM_RES_BACKDROP_IMAGE);
|
|
|
|
#ifdef HP_VUE
|
|
UpdateWorkspaceInfoProperty (pWS->pSD); /* to be backward compatible */
|
|
#endif /* HP_VUE */
|
|
SetWorkspaceInfoProperty (pWS);
|
|
|
|
/*
|
|
* Inform the world of the new workspace title
|
|
*/
|
|
dtSendWorkspaceModifyNotification(pWS->pSD, pWS->id,
|
|
DtWSM_REASON_BACKDROP);
|
|
}
|
|
|
|
|
|
/******************************<->*************************************
|
|
*
|
|
* Boolean IsBackdropWindow (pSD, win)
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Tests a window to see if it is a backdrop window
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pSD = pointer to screen data
|
|
* win = window to test.
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return = True if win is a backdrop window.
|
|
* False otherwise.
|
|
*
|
|
* Comments:
|
|
* ---------
|
|
*
|
|
*************************************<->***********************************/
|
|
Boolean
|
|
IsBackdropWindow(
|
|
WmScreenData *pSD,
|
|
Window win )
|
|
{
|
|
Boolean rval = False;
|
|
int i;
|
|
|
|
/*
|
|
* Is it one of the backdrop windows for a workspace?
|
|
*/
|
|
for (i=0; (i < pSD->numWorkspaces) && !rval; i++)
|
|
{
|
|
if (pSD->pWS[i].backdrop.window == win)
|
|
{
|
|
rval = True;
|
|
}
|
|
}
|
|
|
|
return (rval);
|
|
}
|
|
|
|
/********************* eof ***************************/
|