fvwm1/fvwm/fvwm.c
2019-08-26 23:33:33 +01:00

1180 lines
33 KiB
C

/****************************************************************************
* This module is based on Twm, but has been siginificantly modified
* by Rob Nation
****************************************************************************/
/*****************************************************************************/
/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
/** Salt Lake City, Utah **/
/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/
/** Cambridge, Massachusetts **/
/** **/
/** All Rights Reserved **/
/** **/
/** Permission to use, copy, modify, and distribute this software and **/
/** its documentation for any purpose and without fee is hereby **/
/** granted, provided that the above copyright notice appear in all **/
/** copies and that both that copyright notice and this permis- **/
/** sion notice appear in supporting documentation, and that the **/
/** names of Evans & Sutherland and M.I.T. not be used in advertising **/
/** in publicity pertaining to distribution of the software without **/
/** specific, written prior permission. **/
/** **/
/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/
/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/
/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
/** OR PERFORMANCE OF THIS SOFTWARE. **/
/*****************************************************************************/
/***********************************************************************
* fvwm - "F? Virtual Window Manager"
***********************************************************************/
#include "../configure.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "fvwm.h"
#include "menus.h"
#include "misc.h"
#include "screen.h"
#include "parse.h"
#include <X11/Xproto.h>
#include <X11/Xatom.h>
/* need to get prototype for XrmUniqueQuark for XUniqueContext call */
#include <X11/Xresource.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif /* SHAPE */
#if defined (sparc) && defined (SVR4)
/* Solaris has sysinfo instead of gethostname. */
#include <sys/systeminfo.h>
#endif
#define MAXHOSTNAME 255
#include "../version.h"
ScreenInfo Scr; /* structures for the screen */
Display *dpy; /* which display are we talking to */
extern char *config_file;
XErrorHandler CatchRedirectError(Display *, XErrorEvent *);
XErrorHandler FvwmErrorHandler(Display *, XErrorEvent *);
void newhandler(int sig);
void CreateCursors(void);
void NoisyExit(int);
void ChildDied(int nonsense);
void SaveDesktopState(void);
XContext FvwmContext; /* context for fvwm windows */
XContext MenuContext; /* context for fvwm menus */
XClassHint NoClass; /* for applications with no class */
int JunkX = 0, JunkY = 0;
Window JunkRoot, JunkChild; /* junk window */
unsigned int JunkWidth, JunkHeight, JunkBW, JunkDepth, JunkMask;
/* assorted gray bitmaps for decorative borders */
#define g_width 2
#define g_height 2
static char g_bits[] = {0x02, 0x01};
#define l_g_width 4
#define l_g_height 2
static char l_g_bits[] = {0x08, 0x02};
Bool debugging = False,PPosOverride;
#define s_g_width 4
#define s_g_height 4
static char s_g_bits[] = {0x01, 0x02, 0x04, 0x08};
char **g_argv;
#ifdef M4
int m4_enable; /* use m4? */
int m4_prefix; /* Do GNU m4 prefixing (-P) */
char m4_options[BUFSIZ]; /* Command line options to m4 */
char m4_prog[BUFSIZ]; /* Name of the m4 program */
int m4_default_quotes; /* Use default m4 quotes */
char m4_startquote[16]; /* Left quote characters for m4 */
char m4_endquote[16]; /* Right quote characters for m4 */
#endif
#ifndef NO_PAGER
extern Pixel PagerForeColor;
#endif
#ifdef SHAPE
int ShapeEventBase, ShapeErrorBase;
#endif
long isIconicState = 0;
extern XEvent Event;
Bool Restarting = False;
int fd_width, x_fd;
char *display_name = NULL;
/***********************************************************************
*
* Procedure:
* main - start of fvwm
*
***********************************************************************
*/
void main(int argc, char **argv)
{
unsigned long valuemask; /* mask for create windows */
XSetWindowAttributes attributes; /* attributes for create windows */
void InternUsefulAtoms (void);
void InitVariables(void);
void enterAlarm(int);
int i;
extern int x_fd;
int len;
char *display_string;
char message[255];
char num[10];
Bool single = False;
Bool option_error = FALSE;
#ifdef M4
/* Set the defaults for m4 processing */
m4_enable = TRUE;
m4_prefix = FALSE;
strcpy(m4_prog, "m4");
*m4_options = '\0';
m4_default_quotes = 1;
strcpy(m4_startquote, "`");
strcpy(m4_endquote, "'");
#endif
for (i = 1; i < argc; i++)
{
if (mystrncasecmp(argv[i],"-debug",6)==0)
debugging = True;
else if (mystrncasecmp(argv[i],"-s",2)==0)
{
single = True;
}
else if (mystrncasecmp(argv[i],"-d",2)==0)
{
if (++i >= argc)
usage();
display_name = argv[i];
}
else if (mystrncasecmp(argv[i],"-f",2)==0)
{
if (++i >= argc)
usage();
config_file = argv[i];
}
#ifdef M4
else if (mystrncasecmp(argv[i], "-no-m4", 6) == 0)
{
m4_enable = FALSE;
}
else if (mystrncasecmp(argv[i], "-m4-prefix", 10) == 0)
{
m4_prefix = TRUE;
}
else if (mystrncasecmp(argv[i],"-m4opt", 6) == 0)
{
if (++i < argc)
{
strcat(m4_options, argv[i]);
strcat(m4_options, " ");
}
}
else if (mystrncasecmp(argv[i], "-m4-squote", 6) == 0)
{
if (++i < argc)
{
strcpy(m4_startquote, argv[i]);
m4_default_quotes = 0;
}
}
else if (mystrncasecmp(argv[i], "-m4-equote", 6) == 0)
{
if (++i < argc)
{
strcpy(m4_endquote, argv[i]);
m4_default_quotes = 0;
}
}
else if (mystrncasecmp(argv[i], "-m4prog", 7) == 0)
{
if (++i < argc)
{
strcpy(m4_prog, argv[i]);
}
}
#endif
else if (mystrncasecmp(argv[i], "-version", 8) == 0)
{
fprintf(stderr, "Fvwm Version %s\n", VERSION);
}
else
{
fprintf(stderr, "fvwm: Unknown option: `%s'\n", argv[i]);
option_error = TRUE;
}
}
if (option_error)
{
usage();
}
g_argv = argv;
newhandler (SIGINT);
newhandler (SIGHUP);
newhandler (SIGQUIT);
newhandler (SIGTERM);
signal (SIGUSR1, Restart);
signal (SIGPIPE, DeadPipe);
signal(SIGALRM,enterAlarm);
ReapChildren();
if (!(dpy = XOpenDisplay(display_name)))
{
fvwm_err("can't open display %s", XDisplayName(display_name),
NULL,NULL);
exit (1);
}
x_fd = XConnectionNumber(dpy);
if (fcntl(x_fd, F_SETFD, 1) == -1)
{
fvwm_err("close-on-exec failed",NULL,NULL,NULL);
exit (1);
}
Scr.screen= DefaultScreen(dpy);
Scr.NumberOfScreens = ScreenCount(dpy);
if(!single)
{
for(i=0;i<Scr.NumberOfScreens;i++)
{
if(i!= Scr.screen)
{
sprintf(message,"%s -d %s",argv[0],XDisplayString(dpy));
len = strlen(message);
message[len-1] = 0;
sprintf(num,"%d",i);
strcat(message,num);
strcat(message," -s ");
if(debugging)
strcat(message," -debug");
strcat(message," -f ");
strcat(message,config_file);
strcat(message," &\n");
system(message);
}
}
}
/* Add a DISPLAY entry to the environment, incase we were started
* with fvwm -display term:0.0
*/
len = strlen(XDisplayString(dpy));
display_string = safemalloc(len+10);
sprintf(display_string,"DISPLAY=%s",XDisplayString(dpy));
putenv(display_string);
/* Add a HOSTDISPLAY environment variable, which is the same as
* DISPLAY, unless display = :0.0 or unix:0.0, in which case the full
* host name will be used for ease in networking . */
if(strncmp(display_string,"DISPLAY=:",9)==0)
{
char client[MAXHOSTNAME], *rdisplay_string;
mygethostname(client,MAXHOSTNAME);
rdisplay_string = safemalloc(len+14 + strlen(client));
sprintf(rdisplay_string,"HOSTDISPLAY=%s:%s",client,&display_string[9]);
putenv(rdisplay_string);
}
else if(strncmp(display_string,"DISPLAY=unix:",13)==0)
{
char client[MAXHOSTNAME], *rdisplay_string;
mygethostname(client,MAXHOSTNAME);
rdisplay_string = safemalloc(len+14 + strlen(client));
sprintf(rdisplay_string,"HOSTDISPLAY=%s:%s",client,
&display_string[13]);
putenv(rdisplay_string);
}
else
{
char *rdisplay_string;
rdisplay_string = safemalloc(len+14);
sprintf(rdisplay_string,"HOSTDISPLAY=%s",XDisplayString(dpy));
putenv(rdisplay_string);
}
Scr.Root = RootWindow(dpy, Scr.screen);
if(Scr.Root == None)
{
fvwm_err("Screen %d is not a valid screen",(char *)Scr.screen,
NULL,NULL);
exit(1);
}
#ifdef SHAPE
XShapeQueryExtension(dpy, &ShapeEventBase, &ShapeErrorBase);
#endif /* SHAPE */
InternUsefulAtoms ();
/* Make sure property priority colors is empty */
XChangeProperty (dpy, Scr.Root, _XA_MIT_PRIORITY_COLORS,
XA_CARDINAL, 32, PropModeReplace, NULL, 0);
XSetErrorHandler((XErrorHandler)CatchRedirectError);
XSelectInput(dpy, Scr.Root,
LeaveWindowMask| EnterWindowMask | PropertyChangeMask |
SubstructureRedirectMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask );
XSync(dpy, 0);
XSetErrorHandler((XErrorHandler)FvwmErrorHandler);
CreateCursors();
InitVariables();
initModules();
XGrabServer(dpy);
Scr.gray_bitmap =
XCreateBitmapFromData(dpy,Scr.Root,g_bits, g_width,g_height);
/* read config file, set up menus, colors, fonts */
#ifdef M4
MakeMenus(display_name, m4_options);
#else
MakeMenus(display_name, NULL);
#endif
if(Scr.d_depth<2)
{
Scr.gray_pixmap =
XCreatePixmapFromBitmapData(dpy,Scr.Root,g_bits, g_width,g_height,
Scr.StdColors.fore,Scr.StdColors.back,
Scr.d_depth);
Scr.light_gray_pixmap =
XCreatePixmapFromBitmapData(dpy,Scr.Root,l_g_bits,l_g_width,l_g_height,
Scr.StdColors.fore,Scr.StdColors.back,
Scr.d_depth);
Scr.sticky_gray_pixmap =
XCreatePixmapFromBitmapData(dpy,Scr.Root,s_g_bits,s_g_width,s_g_height,
Scr.StickyColors.fore,Scr.StickyColors.back,
Scr.d_depth);
}
/* create a window which will accept the keyboard focus when no other
windows have it */
attributes.event_mask = KeyPressMask|FocusChangeMask;
attributes.override_redirect = True;
Scr.NoFocusWin=XCreateWindow(dpy,Scr.Root,-10, -10, 10, 10, 0, 0,
InputOnly,CopyFromParent,
CWEventMask|CWOverrideRedirect,
&attributes);
XMapWindow(dpy, Scr.NoFocusWin);
XSetInputFocus (dpy, Scr.NoFocusWin, RevertToParent, CurrentTime);
Scr.TitleHeight=Scr.WindowFont.font->ascent+Scr.WindowFont.font->descent+3;
XSync(dpy, 0);
if(debugging)
XSynchronize(dpy,1);
Scr.SizeStringWidth = XTextWidth (Scr.StdFont.font,
" +8888 x +8888 ", 15);
attributes.border_pixel = Scr.StdColors.fore;
attributes.background_pixel = Scr.StdColors.back;
attributes.bit_gravity = NorthWestGravity;
valuemask = (CWBorderPixel | CWBackPixel | CWBitGravity);
if(!(Scr.flags & MWMMenus))
{
Scr.SizeWindow = XCreateWindow (dpy, Scr.Root,
0, 0,
(unsigned int)(Scr.SizeStringWidth +
SIZE_HINDENT*2),
(unsigned int) (Scr.StdFont.height +
SIZE_VINDENT*2),
(unsigned int) 0, 0,
(unsigned int) CopyFromParent,
(Visual *) CopyFromParent,
valuemask, &attributes);
}
else
{
Scr.SizeWindow = XCreateWindow (dpy, Scr.Root,
Scr.MyDisplayWidth/2 -
(Scr.SizeStringWidth +
SIZE_HINDENT*2)/2,
Scr.MyDisplayHeight/2 -
(Scr.StdFont.height +
SIZE_VINDENT*2)/2,
(unsigned int)(Scr.SizeStringWidth +
SIZE_HINDENT*2),
(unsigned int) (Scr.StdFont.height +
SIZE_VINDENT*2),
(unsigned int) 0, 0,
(unsigned int) CopyFromParent,
(Visual *) CopyFromParent,
valuemask, &attributes);
}
#ifndef NON_VIRTUAL
initPanFrames();
#endif
CaptureAllWindows();
#ifndef NON_VIRTUAL
checkPanFrames();
#endif
XUngrabServer(dpy);
MoveResizeViewPortIndicator();
fd_width = GetFdWidth();
if(Restarting)
{
if(Scr.RestartFunction != NULL)
ExecuteFunction(F_FUNCTION,NULL,None,NULL,&Event,C_ROOT,0,0,
0,0,Scr.RestartFunction,-1);
}
else
{
if(Scr.InitFunction != NULL)
ExecuteFunction(F_FUNCTION,NULL,None,NULL,&Event,C_ROOT,0,0,
0,0,Scr.InitFunction,-1);
}
HandleEvents();
return;
}
/***********************************************************************
*
* Procedure:
* CaptureAllWindows
*
* Decorates all windows at start-up
*
***********************************************************************/
void CaptureAllWindows(void)
{
int i,j;
unsigned int nchildren;
Window root, parent, *children;
PPosOverride = TRUE;
if(!XQueryTree(dpy, Scr.Root, &root, &parent, &children, &nchildren))
return;
/*
* weed out icon windows
*/
for (i = 0; i < nchildren; i++)
{
if (children[i])
{
XWMHints *wmhintsp = XGetWMHints (dpy, children[i]);
if (wmhintsp)
{
if (wmhintsp->flags & IconWindowHint)
{
for (j = 0; j < nchildren; j++)
{
if (children[j] == wmhintsp->icon_window)
{
children[j] = None;
break;
}
}
}
XFree ((char *) wmhintsp);
}
}
}
/*
* map all of the non-override windows
*/
for (i = 0; i < nchildren; i++)
{
if (children[i] && MappedNotOverride(children[i]))
{
XUnmapWindow(dpy, children[i]);
Event.xmaprequest.window = children[i];
HandleMapRequest ();
}
}
isIconicState = DontCareState;
if(nchildren > 0)
XFree((char *)children);
/* after the windows already on the screen are in place,
* don't use PPosition */
PPosOverride = FALSE;
}
/***********************************************************************
*
* Procedure:
* MappedNotOverride - checks to see if we should really
* put a fvwm frame on the window
*
* Returned Value:
* TRUE - go ahead and frame the window
* FALSE - don't frame the window
*
* Inputs:
* w - the window to check
*
***********************************************************************/
int MappedNotOverride(Window w)
{
XWindowAttributes wa;
Atom atype;
int aformat;
unsigned long nitems, bytes_remain;
unsigned char *prop;
isIconicState = DontCareState;
if(!XGetWindowAttributes(dpy, w, &wa))
return False;
if(XGetWindowProperty(dpy,w,_XA_WM_STATE,0L,3L,False,_XA_WM_STATE,
&atype,&aformat,&nitems,&bytes_remain,&prop)==Success)
{
if(prop != NULL)
{
isIconicState = *(long *)prop;
XFree(prop);
}
}
#ifndef NO_PAGER
if(w == Scr.Pager_w)
return True;
#endif
return (((isIconicState == IconicState)||(wa.map_state != IsUnmapped)) &&
(wa.override_redirect != True));
}
/***********************************************************************
*
* Procedure:
* InternUsefulAtoms:
* Dont really know what it does
*
***********************************************************************
*/
Atom _XA_MIT_PRIORITY_COLORS;
Atom _XA_WM_CHANGE_STATE;
Atom _XA_WM_STATE;
Atom _XA_WM_COLORMAP_WINDOWS;
Atom _XA_WM_PROTOCOLS;
Atom _XA_WM_TAKE_FOCUS;
Atom _XA_WM_DELETE_WINDOW;
Atom _XA_WM_DESKTOP;
Atom _XA_MwmAtom;
void InternUsefulAtoms (void)
{
/*
* Create priority colors if necessary.
*/
_XA_MIT_PRIORITY_COLORS = XInternAtom(dpy, "_MIT_PRIORITY_COLORS", False);
_XA_WM_CHANGE_STATE = XInternAtom (dpy, "WM_CHANGE_STATE", False);
_XA_WM_STATE = XInternAtom (dpy, "WM_STATE", False);
_XA_WM_COLORMAP_WINDOWS = XInternAtom (dpy, "WM_COLORMAP_WINDOWS", False);
_XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
_XA_WM_TAKE_FOCUS = XInternAtom (dpy, "WM_TAKE_FOCUS", False);
_XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
_XA_WM_DESKTOP = XInternAtom (dpy, "WM_DESKTOP", False);
_XA_MwmAtom=XInternAtom(dpy,"_MOTIF_WM_HINTS",False);
return;
}
/***********************************************************************
*
* Procedure:
* newhandler: Installs new signal handler
*
************************************************************************/
void newhandler(int sig)
{
if (signal (sig, SIG_IGN) != SIG_IGN)
signal (sig, SigDone);
}
/*************************************************************************
* Restart on a signal
************************************************************************/
void Restart(int nonsense)
{
Done(1, *g_argv);
SIGNAL_RETURN;
}
/***********************************************************************
*
* Procedure:
* CreateCursors - Loads fvwm cursors
*
***********************************************************************
*/
void CreateCursors(void)
{
/* define cursors */
Scr.FvwmCursors[POSITION] = XCreateFontCursor(dpy,XC_top_left_corner);
Scr.FvwmCursors[DEFAULT] = XCreateFontCursor(dpy, XC_top_left_arrow);
Scr.FvwmCursors[SYS] = XCreateFontCursor(dpy, XC_hand2);
Scr.FvwmCursors[TITLE_CURSOR] = XCreateFontCursor(dpy, XC_top_left_arrow);
Scr.FvwmCursors[MOVE] = XCreateFontCursor(dpy, XC_fleur);
Scr.FvwmCursors[MENU] = XCreateFontCursor(dpy, XC_sb_left_arrow);
Scr.FvwmCursors[WAIT] = XCreateFontCursor(dpy, XC_watch);
Scr.FvwmCursors[SELECT] = XCreateFontCursor(dpy, XC_dot);
Scr.FvwmCursors[DESTROY] = XCreateFontCursor(dpy, XC_pirate);
Scr.FvwmCursors[LEFT] = XCreateFontCursor(dpy, XC_left_side);
Scr.FvwmCursors[RIGHT] = XCreateFontCursor(dpy, XC_right_side);
Scr.FvwmCursors[TOP] = XCreateFontCursor(dpy, XC_top_side);
Scr.FvwmCursors[BOTTOM] = XCreateFontCursor(dpy, XC_bottom_side);
Scr.FvwmCursors[TOP_LEFT] = XCreateFontCursor(dpy,XC_top_left_corner);
Scr.FvwmCursors[TOP_RIGHT] = XCreateFontCursor(dpy,XC_top_right_corner);
Scr.FvwmCursors[BOTTOM_LEFT] = XCreateFontCursor(dpy,XC_bottom_left_corner);
Scr.FvwmCursors[BOTTOM_RIGHT] =XCreateFontCursor(dpy,XC_bottom_right_corner);
}
/***********************************************************************
*
* Procedure:
* InitVariables - initialize fvwm variables
*
************************************************************************/
void InitVariables(void)
{
FvwmContext = XUniqueContext();
MenuContext = XUniqueContext();
NoClass.res_name = NoName;
NoClass.res_class = NoName;
Scr.d_depth = DefaultDepth(dpy, Scr.screen);
Scr.FvwmRoot.w = Scr.Root;
Scr.FvwmRoot.next = 0;
XGetWindowAttributes(dpy,Scr.Root,&(Scr.FvwmRoot.attr));
Scr.root_pushes = 0;
Scr.pushed_window = &Scr.FvwmRoot;
Scr.FvwmRoot.number_cmap_windows = 0;
Scr.MyDisplayWidth = DisplayWidth(dpy, Scr.screen);
Scr.MyDisplayHeight = DisplayHeight(dpy, Scr.screen);
Scr.NoBoundaryWidth = 1;
Scr.BoundaryWidth = BOUNDARY_WIDTH;
Scr.CornerWidth = CORNER_WIDTH;
Scr.Hilite = NULL;
Scr.Focus = NULL;
Scr.Ungrabbed = NULL;
Scr.StdFont.font = NULL;
Scr.StdFont.name = "fixed";
Scr.WindowFont.name = "fixed";
Scr.VScale = 32;
#ifndef NON_VIRTUAL
Scr.VxMax = 3;
Scr.VyMax = 3;
#else
Scr.VxMax = 1;
Scr.VyMax = 1;
#endif
Scr.Vx = Scr.Vy = 0;
/* Sets the current desktop number to zero */
/* Multiple desks are available even in non-virtual
* compilations */
{
Atom atype;
int aformat;
unsigned long nitems, bytes_remain;
unsigned char *prop;
Scr.CurrentDesk = 0;
if ((XGetWindowProperty(dpy, Scr.Root, _XA_WM_DESKTOP, 0L, 1L, True,
_XA_WM_DESKTOP, &atype, &aformat, &nitems,
&bytes_remain, &prop))==Success)
{
if(prop != NULL)
{
Restarting = True;
Scr.CurrentDesk = *(unsigned long *)prop;
}
}
}
Scr.EdgeScrollX = Scr.EdgeScrollY = -100000;
Scr.ScrollResistance = Scr.MoveResistance = 0;
Scr.OpaqueSize = 5;
Scr.ClickTime = 150;
Scr.AutoRaiseDelay = 0;
/* set major operating modes */
Scr.flags = 0;
Scr.NumBoxes = 0;
Scr.randomx = Scr.randomy = 0;
Scr.buttons2grab = 7;
#ifndef NO_PAGER
Scr.PagerFont.name = NULL;
Scr.PagerFont.height = 0;
Scr.PagerFont.y = 0;
Scr.FvwmPager = (FvwmWindow *)0;
Scr.Pager_w = None;
Scr.CPagerWin = None;
#endif
Scr.InitFunction = NULL;
Scr.RestartFunction = NULL;
Scr.left_button_styles[0][0] = 55;
Scr.left_button_styles[1][0] = 22;
Scr.left_button_styles[0][1] = -35;
Scr.left_button_styles[1][1] = -10;
Scr.left_button_styles[0][2] = 1;
Scr.left_button_styles[1][2] = 1;
Scr.left_button_styles[0][3] = 35;
Scr.left_button_styles[1][3] = 10;
Scr.left_button_styles[0][4] = 56;
Scr.left_button_styles[1][4] = 25;
Scr.right_button_styles[0][0] = 55;
Scr.right_button_styles[1][0] = 55;
Scr.right_button_styles[0][1] = 22;
Scr.right_button_styles[1][1] = 22;
Scr.right_button_styles[0][2] = 1;
Scr.right_button_styles[1][2] = 1;
Scr.right_button_styles[0][3] = 50;
Scr.right_button_styles[1][3] = 50;
Scr.right_button_styles[0][4] = 28;
Scr.right_button_styles[1][4] = 28;
return;
}
/***********************************************************************
*
* Procedure:
* Reborder - Removes fvwm border windows
*
************************************************************************/
void Reborder(void)
{
FvwmWindow *tmp; /* temp fvwm window structure */
int i;
extern unsigned PopupCount;
extern MenuRoot *PopupTable[MAXPOPUPS];
/* put a border back around all windows */
XGrabServer (dpy);
#ifndef NO_PAGER
if(Scr.Pager_w != None)
XDestroyWindow(dpy,Scr.Pager_w);
#endif
InstallWindowColormaps (&Scr.FvwmRoot); /* force reinstall */
for (tmp = Scr.FvwmRoot.next; tmp != NULL; tmp = tmp->next)
{
XUnmapWindow(dpy,tmp->frame);
RestoreWithdrawnLocation (tmp,True);
XDestroyWindow(dpy,tmp->frame);
}
for(i=0;i<PopupCount;i++)
if(PopupTable[i]->w != None)
XDestroyWindow(dpy,PopupTable[i]->w);
XUngrabServer (dpy);
XSetInputFocus (dpy, PointerRoot, RevertToPointerRoot,CurrentTime);
XSync(dpy,0);
}
/***********************************************************************
*
* Procedure: NoisyExit
* Print error messages and die. (segmentation violation)
*
**********************************************************************/
void NoisyExit(int nonsense)
{
XErrorEvent event;
fvwm_err("Seg Fault",NULL,NULL,NULL);
event.error_code = 0;
event.request_code = 0;
FvwmErrorHandler(dpy, &event);
/* Attempt to do a re-start of fvwm */
Done(0,NULL);
}
/***********************************************************************
*
* Procedure:
* Done - cleanup and exit fvwm
*
***********************************************************************
*/
void SigDone(int nonsense)
{
Done(0, NULL);
SIGNAL_RETURN;
}
void Done(int restart, char *command)
{
#ifndef NON_VIRTUAL
MoveViewport(0,0,False);
#endif
/* Close all my pipes */
ClosePipes();
Reborder ();
#ifdef M4
if (m4_enable)
{
extern char *fvwm_file;
/* With m4 processing, a temporary file was created to hold the
processed file. Delete the file now because we don't need it
any more. It will be created again during restart. */
unlink(fvwm_file);
}
#endif
if(restart)
{
SaveDesktopState(); /* I wonder why ... */
/* Really make sure that the connection is closed and cleared! */
XSelectInput(dpy, Scr.Root, 0 );
XSync(dpy, 0);
XCloseDisplay(dpy);
{
char *my_argv[10];
int i,done,j;
i=0;
j=0;
done = 0;
while((g_argv[j] != NULL)&&(i<8))
{
if(strcmp(g_argv[j],"-s")!=0)
{
my_argv[i] = g_argv[j];
i++;
j++;
}
else
j++;
}
if(strstr(command,"fvwm")!= NULL)
my_argv[i++] = "-s";
while(i<10)
my_argv[i++] = NULL;
/* really need to destroy all windows, explicitly,
* not sleep, but this is adequate for now */
sleep(1);
ReapChildren();
execvp(command,my_argv);
}
fprintf(stderr, "FVWM: Call of '%s' failed!!!!\n",command);
execvp(g_argv[0], g_argv); /* that _should_ work */
fprintf(stderr, "FVWM: Call of '%s' failed!!!!\n", g_argv[0]);
}
else
{
XCloseDisplay(dpy);
exit(0);
}
}
/***********************************************************************
*
* Procedure:
* CatchRedirectError - Figures out if there's another WM running
*
************************************************************************/
XErrorHandler CatchRedirectError(Display *dpy, XErrorEvent *event)
{
fvwm_err("another WM is running",NULL,NULL,NULL);
exit(1);
}
/***********************************************************************
*
* Procedure:
* FvwmErrorHandler - displays info on internal errors
*
************************************************************************/
XErrorHandler FvwmErrorHandler(Display *dpy, XErrorEvent *event)
{
extern int last_event_type;
/* some errors are acceptable, mostly they're caused by
* trying to update a lost window */
if((event->error_code == BadWindow)||(event->request_code == X_GetGeometry)||
(event->error_code==BadDrawable)||(event->request_code==X_SetInputFocus)||
(event->request_code==X_GrabButton)||
(event->request_code==X_ChangeWindowAttributes)||
(event->request_code == X_InstallColormap))
return 0 ;
fvwm_err("internal error",NULL,NULL,NULL);
fprintf(stderr," Request %d, Error %d\n", event->request_code,
event->error_code);
fprintf(stderr," EventType: %d",last_event_type);
fprintf(stderr,"\n");
return 0;
}
void fvwm_err(char *message, char *arg1, char *arg2, char *arg3)
{
fprintf(stderr,"fvwm: ");
fprintf(stderr,message,arg1,arg2,arg3);
fprintf(stderr,"\n");
}
void usage(void)
{
#ifdef M4
#define USAGE "Fvwm Ver %s\n\nusage: fvwm [-d dpy] [-debug] [-f config_file] [-s] [-no-m4] [-m4-prefix] [-m4opt option] [-m4-squote squote] [-m4-equote equote] [-m4prog m4prog]\n"
#else
#define USAGE "Fvwm Ver %s\n\nusage: fvwm [-d dpy] [-debug] [-f config_file] [-s]\n"
#endif
fprintf(stderr,USAGE,VERSION);
}
#ifndef NON_VIRTUAL
/* the root window is surrounded by four window slices, which are InputOnly.
* So you can see 'through' them, but they eat the input. An EnterEvent in
* one of these windows causes a Paging. The windows have the according cursor
* pointing in the pan direction or are hidden if there is no more panning
* in that direction. This is mostly intended to get a panning even atop
* of Motif applictions, which does not work yet. It seems Motif windows
* eat all mouse events.
*
* Hermann Dunkel, HEDU, dunkel@cul-ipn.uni-kiel.de 1/94
*/
/***************************************************************************
* checkPanFrames hides PanFrames if they are on the very border of the
* VIRTUELL screen and EdgeWrap for that direction is off.
* (A special cursor for the EdgeWrap border could be nice) HEDU
****************************************************************************/
void checkPanFrames(void)
{
extern Bool DoHandlePageing;
int wrapX = (Scr.flags & EdgeWrapX);
int wrapY = (Scr.flags & EdgeWrapY);
/* Remove Pan frames if paging by edge-scroll is permanently or
* temporarily disabled */
if((Scr.EdgeScrollY == 0)||(!DoHandlePageing))
{
XUnmapWindow(dpy,Scr.PanFrameTop.win);
Scr.PanFrameTop.isMapped=False;
XUnmapWindow (dpy,Scr.PanFrameBottom.win);
Scr.PanFrameBottom.isMapped=False;
}
if((Scr.EdgeScrollX == 0)||(!DoHandlePageing))
{
XUnmapWindow(dpy,Scr.PanFrameLeft.win);
Scr.PanFrameLeft.isMapped=False;
XUnmapWindow (dpy,Scr.PanFrameRight.win);
Scr.PanFrameRight.isMapped=False;
}
if(((Scr.EdgeScrollX == 0)&&(Scr.EdgeScrollY == 0))||(!DoHandlePageing))
return;
/* LEFT, hide only if EdgeWrap is off */
if (Scr.Vx==0 && Scr.PanFrameLeft.isMapped && (!wrapX))
{
XUnmapWindow(dpy,Scr.PanFrameLeft.win);
Scr.PanFrameLeft.isMapped=False;
}
else if (Scr.Vx > 0 && Scr.PanFrameLeft.isMapped==False)
{
XMapRaised(dpy,Scr.PanFrameLeft.win);
Scr.PanFrameLeft.isMapped=True;
}
/* RIGHT, hide only if EdgeWrap is off */
if (Scr.Vx == Scr.VxMax && Scr.PanFrameRight.isMapped && (!wrapX))
{
XUnmapWindow (dpy,Scr.PanFrameRight.win);
Scr.PanFrameRight.isMapped=False;
}
else if (Scr.Vx < Scr.VxMax && Scr.PanFrameRight.isMapped==False)
{
XMapRaised(dpy,Scr.PanFrameRight.win);
Scr.PanFrameRight.isMapped=True;
}
/* TOP, hide only if EdgeWrap is off */
if (Scr.Vy==0 && Scr.PanFrameTop.isMapped && (!wrapY))
{
XUnmapWindow(dpy,Scr.PanFrameTop.win);
Scr.PanFrameTop.isMapped=False;
}
else if (Scr.Vy > 0 && Scr.PanFrameTop.isMapped==False)
{
XMapRaised(dpy,Scr.PanFrameTop.win);
Scr.PanFrameTop.isMapped=True;
}
/* BOTTOM, hide only if EdgeWrap is off */
if (Scr.Vy == Scr.VyMax && Scr.PanFrameBottom.isMapped && (!wrapY))
{
XUnmapWindow (dpy,Scr.PanFrameBottom.win);
Scr.PanFrameBottom.isMapped=False;
}
else if (Scr.Vy < Scr.VyMax && Scr.PanFrameBottom.isMapped==False)
{
XMapRaised(dpy,Scr.PanFrameBottom.win);
Scr.PanFrameBottom.isMapped=True;
}
}
/****************************************************************************
*
* Gotta make sure these things are on top of everything else, or they
* don't work!
*
***************************************************************************/
void raisePanFrames(void)
{
if (Scr.PanFrameTop.isMapped) XRaiseWindow(dpy,Scr.PanFrameTop.win);
if (Scr.PanFrameLeft.isMapped) XRaiseWindow(dpy,Scr.PanFrameLeft.win);
if (Scr.PanFrameRight.isMapped) XRaiseWindow(dpy,Scr.PanFrameRight.win);
if (Scr.PanFrameBottom.isMapped) XRaiseWindow(dpy,Scr.PanFrameBottom.win);
}
/****************************************************************************
*
* Creates the windows for edge-scrolling
*
****************************************************************************/
void initPanFrames()
{
XSetWindowAttributes attributes; /* attributes for create */
unsigned long valuemask;
attributes.event_mask = (EnterWindowMask | LeaveWindowMask |
VisibilityChangeMask);
valuemask= (CWEventMask | CWCursor );
attributes.cursor = Scr.FvwmCursors[TOP];
Scr.PanFrameTop.win =
XCreateWindow (dpy, Scr.Root,
0,0,
Scr.MyDisplayWidth,PAN_FRAME_THICKNESS,
0, /* no border */
CopyFromParent, InputOnly,
CopyFromParent,
valuemask, &attributes);
attributes.cursor = Scr.FvwmCursors[LEFT];
Scr.PanFrameLeft.win =
XCreateWindow (dpy, Scr.Root,
0,PAN_FRAME_THICKNESS,
PAN_FRAME_THICKNESS,
Scr.MyDisplayHeight-2*PAN_FRAME_THICKNESS,
0, /* no border */
CopyFromParent, InputOnly, CopyFromParent,
valuemask, &attributes);
attributes.cursor = Scr.FvwmCursors[RIGHT];
Scr.PanFrameRight.win =
XCreateWindow (dpy, Scr.Root,
Scr.MyDisplayWidth-PAN_FRAME_THICKNESS,PAN_FRAME_THICKNESS,
PAN_FRAME_THICKNESS,
Scr.MyDisplayHeight-2*PAN_FRAME_THICKNESS,
0, /* no border */
CopyFromParent, InputOnly, CopyFromParent,
valuemask, &attributes);
attributes.cursor = Scr.FvwmCursors[BOTTOM];
Scr.PanFrameBottom.win =
XCreateWindow (dpy, Scr.Root,
0,Scr.MyDisplayHeight-PAN_FRAME_THICKNESS,
Scr.MyDisplayWidth,PAN_FRAME_THICKNESS,
0, /* no border */
CopyFromParent, InputOnly, CopyFromParent,
valuemask, &attributes);
Scr.PanFrameTop.isMapped=Scr.PanFrameLeft.isMapped=
Scr.PanFrameRight.isMapped= Scr.PanFrameBottom.isMapped=False;
Scr.usePanFrames=True;
}
#endif /* NON_VIRTUAL */
/****************************************************************************
*
* Save Desktop State
*
****************************************************************************/
void SaveDesktopState()
{
FvwmWindow *t;
unsigned long data[1];
for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
{
data[0] = (unsigned long) t->Desk;
XChangeProperty (dpy, t->w, _XA_WM_DESKTOP, _XA_WM_DESKTOP, 32,
PropModeReplace, (unsigned char *) data, 1);
}
data[0] = (unsigned long) Scr.CurrentDesk;
XChangeProperty (dpy, Scr.Root, _XA_WM_DESKTOP, _XA_WM_DESKTOP, 32,
PropModeReplace, (unsigned char *) data, 1);
XSync(dpy, 0);
}