/**************************************************************************** * 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 #include #include #include #include #include #include "fvwm.h" #include "menus.h" #include "misc.h" #include "screen.h" #include "parse.h" #include #include /* need to get prototype for XrmUniqueQuark for XUniqueContext call */ #include #ifdef SHAPE #include #endif /* SHAPE */ #if defined (sparc) && defined (SVR4) /* Solaris has sysinfo instead of gethostname. */ #include #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); static void cleanup(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 int cleanupDone=0; /* have we cleaned up yet ? */ #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;iascent+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;iw != 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; } /* called by atexit */ void atexit_cleanup(void) { if (!cleanupDone) Done(0, NULL); } void Done(int restart, char *command) { cleanupDone=1; #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 #ifndef NON_VIRTUAL MoveViewport(0,0,False); #endif /* Close all my pipes */ ClosePipes(); Reborder (); 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); }