/* -*-c-*- */
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* FvwmBanner
*
* Show Fvwm Banner
*
*/
#include "config.h"
#ifdef HAVE_SYS_BSDTYPES_H
#include <sys/bsdtypes.h> /* Saul */
#endif
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/wait.h>
#include "libs/ftime.h"
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <ctype.h>
#include <X11/Xlib.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include "libs/fvwmlib.h"
#include "libs/Picture.h"
#include "libs/Module.h"
#include "libs/FScreen.h"
#include "libs/FShape.h"
#include "libs/FRenderInit.h"
#include "libs/Graphics.h"
#include "libs/Parse.h"
#include "libs/Strings.h"
/* migo (16-Sep-1999): How about to do this configurable? */
/*#include "fvwm-logo-old.xpm"*/
/*#include "fvwm-logo-colorful.xpm"*/
#include "fvwm-logo-current.xpm"
#include "fvwm-logo-current.xbm"
typedef struct _PImageIcon {
Pixmap pixmap;
Pixmap mask;
int width;
int height;
int depth;
} PImageIcon;
/*
* A few function prototypes
*/
void RedrawWindow(void);
void GetXPMData(char **);
void GetXBMData(void);
void GetImageFile(char *,char *);
void change_window_name(char *str);
static void parseOptions (int fd[2]);
PImageIcon view;
Window win;
char *imagePath = NULL;
char *imageName = NULL;
static char *MyName = NULL;
static int MyNameLen;
int timeout = 3000000; /* default time of 3 seconds */
Display *dpy; /* which display are we talking to */
Window Root;
int screen;
int x_fd;
XSizeHints mysizehints;
Pixel back_pix, fore_pix;
GC NormalGC,FGC;
static Atom wm_del_win;
Bool no_wm = False;
#define MW_EVENTS (ExposureMask | ButtonReleaseMask)
/*
*
* Creates an icon window as needed
*
*/
int main(int argc, char **argv)
{
char *display_name = NULL, *string = NULL;
int retval = 0;
XEvent Event;
fd_set in_fdset;
struct timeval value;
int fd[2];
XSetWindowAttributes attr;
int wx;
int wy;
/* Save our program name - for error messages */
string = strrchr (argv[0], '/');
if (string != (char *) 0) string++;
MyNameLen=strlen(string)+1; /* account for '*' */
MyName = safemalloc(MyNameLen+1); /* account for \0 */
*MyName='*';
strcpy (MyName+1, string);
if(argc>=3)
{
/* sever our connection with fvwm, if we have one. */
fd[0] = atoi(argv[1]);
fd[1] = atoi(argv[2]);
}
else
{
fprintf (stderr,
"%s: Version "VERSION" should only be executed by fvwm!\n",
MyName+1);
exit(1);
}
if (argc > 6) {
imageName = safemalloc (strlen (argv[6]) + 1);
strcpy (imageName, argv[6]);
}
/* Open the display */
if (!(dpy = XOpenDisplay(display_name)))
{
fprintf(stderr,"FvwmBanner: can't open display %s",
XDisplayName(display_name));
exit (1);
}
screen= DefaultScreen(dpy);
Root = RootWindow(dpy, screen);
x_fd = XConnectionNumber(dpy);
flib_init_graphics(dpy);
/* SetMessageMask(fd, M_CONFIG_INFO | M_END_CONFIG_INFO | M_SENDCONFIG); */
SetMessageMask(fd, M_CONFIG_INFO | M_END_CONFIG_INFO);
parseOptions(fd);
/* chick in the neck situation:
* can't load pixmaps into non-default visual without a window
* don't know what size the window should be until pixmap is loaded
*/
attr.background_pixmap = None;
attr.border_pixel = 0;
attr.colormap = Pcmap;
attr.override_redirect = no_wm;
win = XCreateWindow(dpy, Root, -20, -20, 10, 10, 0, Pdepth, InputOutput,
Pvisual,
CWColormap|CWBackPixmap|CWBorderPixel|CWOverrideRedirect,
&attr);
/* Get the xpm banner */
if (imageName)
GetImageFile(imageName,imagePath);
else
GetXPMData(fvwm_logo_xpm);
if (view.depth != Pdepth)
{
XGCValues gcv;
GC gc;
Pixmap temp;
gcv.background= PictureWhitePixel();
gcv.foreground= PictureBlackPixel();
gc = fvwmlib_XCreateGC(dpy, win,
GCForeground | GCBackground, &gcv);
temp = XCreatePixmap(dpy, win, view.width, view.height, Pdepth);
XCopyPlane(dpy, view.pixmap, temp, gc,
0,0,view.width,view.height, 0,0,1);
XFreePixmap(dpy, view.pixmap);
XFreeGC(dpy,gc);
view.pixmap = temp;
}
XSetWindowBackgroundPixmap(dpy, win, view.pixmap);
/* Create a window to hold the banner */
mysizehints.flags = USSize | USPosition | PWinGravity | PResizeInc
| PBaseSize | PMinSize | PMaxSize;
mysizehints.width = view.width;
mysizehints.height = view.height;
mysizehints.width_inc = 1;
mysizehints.height_inc = 1;
mysizehints.base_height = mysizehints.height;
mysizehints.base_width = mysizehints.width;
mysizehints.min_height = mysizehints.height;
mysizehints.min_width = mysizehints.width;
mysizehints.max_height = mysizehints.height;
mysizehints.max_width = mysizehints.width;
mysizehints.win_gravity = NorthWestGravity;
FScreenCenterOnScreen(
NULL, FSCREEN_PRIMARY, &wx, &wy, view.width, view.height);
FScreenMangleScreenIntoUSPosHints(FSCREEN_PRIMARY, &mysizehints);
wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False);
XSetWMProtocols(dpy,win,&wm_del_win,1);
XSetWMNormalHints(dpy,win,&mysizehints);
change_window_name("FvwmBanner");
XMoveResizeWindow(dpy, win, wx, wy, mysizehints.width, mysizehints.height);
if (FHaveShapeExtension && view.mask != None)
FShapeCombineMask(dpy, win, FShapeBounding, 0, 0, view.mask, FShapeSet);
XMapWindow(dpy,win);
XSync(dpy,0);
XSelectInput(dpy,win,ButtonReleaseMask);
/* tell fvwm we're running */
SendFinishedStartupNotification(fd);
/* Display the window */
value.tv_usec = timeout % 1000000;
value.tv_sec = timeout / 1000000;
while(1)
{
FD_ZERO(&in_fdset);
FD_SET(x_fd,&in_fdset);
if(!FPending(dpy))
retval=select(x_fd + 1,SELECT_FD_SET_CAST &in_fdset, 0, 0, &value);
if (retval==0)
{
XDestroyWindow(dpy,win);
XSync(dpy,0);
exit(0);
}
if (FD_ISSET(x_fd, &in_fdset))
{
/* read a packet */
FNextEvent(dpy,&Event);
switch(Event.type)
{
case ButtonRelease:
XDestroyWindow(dpy,win);
XSync(dpy,0);
exit(0);
case ClientMessage:
if (Event.xclient.format==32 && Event.xclient.data.l[0]==wm_del_win)
{
XDestroyWindow(dpy,win);
XSync(dpy,0);
exit(0);
}
default:
break;
}
}
}
return 0;
}
/*
*
* Looks for a color XPM icon file
*
*/
void GetXBMData(void)
{
if ((view.pixmap =
XCreatePixmapFromBitmapData(dpy, win, (char *)fvwm_logo_xbm_bits,
fvwm_logo_xbm_width, fvwm_logo_xbm_height,
BlackPixel(dpy,screen),
WhitePixel(dpy,screen),
Pdepth)) == None)
{
fprintf(stderr,"FvwmBanner: ERROR couldn't convert data to pixmap\n");
exit(1);
}
view.width = fvwm_logo_xbm_width;
view.height = fvwm_logo_xbm_height;
view.depth = Pdepth;
view.mask = None;
}
void GetXPMData(char **data)
{
if(!PImageLoadPixmapFromXpmData(
dpy, win, 0, data, &view.pixmap, &view.mask,
&view.width, &view.height, &view.depth))
{
GetXBMData();
}
}
void GetImageFile(char *file, char *path)
{
char *full_file = NULL;
FvwmPictureAttributes fpa;
fpa.mask = FPAM_NO_ALLOC_PIXELS | FPAM_DITHER | FPAM_NO_ALPHA;
if (file)
full_file = PictureFindImageFile(file,path,R_OK);
if (full_file)
{
if(PImageLoadPixmapFromFile(
dpy, Root, full_file, &view.pixmap, &view.mask, None,
&view.width, &view.height, &view.depth, 0, NULL, 0,
fpa))
{
return;
}
fprintf(stderr,"FvwmBanner: ERROR loading image file\n");
}
else
{
fprintf(stderr,
"FvwmBanner: ERROR finding image file in ImagePath\n");
GetXPMData(fvwm_logo_xpm);
}
}
static void parseOptions(int fd[2])
{
char *tline= NULL;
char *tok;
InitGetConfigLine(fd,MyName);
while (GetConfigLine (fd, &tline),tline != NULL)
{
if (strlen(tline) > 1)
{
tok = PeekToken(tline, &tline);
if (StrEquals(tok, XINERAMA_CONFIG_STRING))
{
FScreenConfigureModule(tline);
continue;
}
if (StrEquals(tok, "ImagePath"))
{
CopyString(&imagePath, tline);
if (imagePath[0] == 0)
{
free (imagePath);
imagePath = (char *) 0;
}
continue;
}
if (strncasecmp(tok,MyName,MyNameLen))
{
/* if not for me: ignore it*/
continue;
}
/* start of interesting part */
tok += MyNameLen;
if (StrEquals(tok, "Pixmap"))
{
if (imageName == (char *) 0)
{
CopyString(&imageName, tline);
if (imageName[0] == 0)
{
free (imageName);
imageName = (char *) 0;
}
}
continue;
}
if (StrEquals(tok, "NoDecor"))
{
no_wm = True;
continue;
}
if (StrEquals(tok, "Timeout"))
{
timeout = atoi(tline) * 1000000;
continue;
}
}
}
return;
}
/*
* Change the window name displayed in the title bar.
*/
void change_window_name(char *str)
{
XTextProperty name;
if (XStringListToTextProperty(&str,1,&name) == 0)
{
fprintf(stderr,"FvwmBanner: cannot allocate window name");
return;
}
XSetWMName(dpy,win,&name);
XSetWMIconName(dpy,win,&name);
XFree(name.value);
}
/*
*
* Procedure:
* SIGPIPE handler - SIGPIPE means fvwm is dying
*
*/
/*ARGSUSED*/
RETSIGTYPE DeadPipe (int nonsense)
{
exit (0);
SIGNAL_RETURN;
}
syntax highlighted by Code2HTML, v. 0.9.1