/* -*-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 /* Saul */ #endif #include #include #include #include #include "libs/ftime.h" #if HAVE_SYS_SELECT_H #include #endif #include #include #include #include #include #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; }