cdesktopenv/cde/programs/dtwm/WmBackdrop.c

673 lines
15 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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);
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 ***************************/