/**************************************************************************** * This module is based on Twm, but has been siginificantly modified * by Rob Nation * * later modified for BowMan * by Bo Yang * * modified slightly for AfterStep * by Frank Fejes * * small modifications for textured backgrounds * by Alfredo Kojima ****************************************************************************/ /*****************************************************************************/ /** 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. **/ /*****************************************************************************/ /*********************************************************************** * AfterStep: WM with NEXTSTEP look and feel ***********************************************************************/ #include "../configure.h" #include #include #include #include #include #include #include "afterstep.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 #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" #ifdef ENABLE_TEXTURE TextureInfo Textures; /* texture information */ #endif ScreenInfo Scr; /* structures for the screen */ Display *dpy; /* which display are we talking to */ extern char *config_file; XErrorHandler CatchRedirectError(Display *, XErrorEvent *); XErrorHandler ASErrorHandler(Display *, XErrorEvent *); void newhandler(int sig); void InitModifiers(void); void CreateCursors(void); void NoisyExit(int); void ChildDied(int nonsense); void SaveDesktopState(void); XContext ASContext; /* context for afterstep windows */ XContext MenuContext; /* context for afterstep 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 afterstep * *********************************************************************** */ int 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, "AfterStep Version %s\n", VERSION); } else { fprintf(stderr, "afterstep: 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))) { afterstep_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) { afterstep_err("close-on-exec failed",NULL,NULL,NULL); exit (1); } Scr.screen= DefaultScreen(dpy); Scr.NumberOfScreens = ScreenCount(dpy); if(!single) { for(i=0;iflags & 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 afterstep 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 afterstep cursors * *********************************************************************** */ void CreateCursors(void) { /* define cursors */ Scr.ASCursors[POSITION] = XCreateFontCursor(dpy,XC_left_ptr); /* Scr.ASCursors[DEFAULT] = XCreateFontCursor(dpy, XC_top_left_arrow); */ Scr.ASCursors[DEFAULT] = XCreateFontCursor(dpy,XC_left_ptr); Scr.ASCursors[SYS] = XCreateFontCursor(dpy, XC_left_ptr); Scr.ASCursors[TITLE_CURSOR] = XCreateFontCursor(dpy, XC_left_ptr); Scr.ASCursors[MOVE] = XCreateFontCursor(dpy, XC_fleur); Scr.ASCursors[MENU] = XCreateFontCursor(dpy, XC_left_ptr); Scr.ASCursors[WAIT] = XCreateFontCursor(dpy, XC_watch); Scr.ASCursors[SELECT] = XCreateFontCursor(dpy, XC_dot); Scr.ASCursors[DESTROY] = XCreateFontCursor(dpy, XC_pirate); Scr.ASCursors[LEFT] = XCreateFontCursor(dpy, XC_left_side); Scr.ASCursors[RIGHT] = XCreateFontCursor(dpy, XC_right_side); Scr.ASCursors[TOP] = XCreateFontCursor(dpy, XC_top_side); Scr.ASCursors[BOTTOM] = XCreateFontCursor(dpy, XC_bottom_side); Scr.ASCursors[TOP_LEFT] = XCreateFontCursor(dpy,XC_top_left_corner); Scr.ASCursors[TOP_RIGHT] = XCreateFontCursor(dpy,XC_top_right_corner); Scr.ASCursors[BOTTOM_LEFT] = XCreateFontCursor(dpy,XC_bottom_left_corner); Scr.ASCursors[BOTTOM_RIGHT] =XCreateFontCursor(dpy,XC_bottom_right_corner); } /*********************************************************************** * * Procedure: * InitVariables - initialize afterstep variables * ************************************************************************/ void InitVariables(void) { ASContext = XUniqueContext(); MenuContext = XUniqueContext(); NoClass.res_name = NoName; NoClass.res_class = NoName; Scr.d_depth = DefaultDepth(dpy, Scr.screen); Scr.ASRoot.w = Scr.Root; Scr.ASRoot.next = 0; XGetWindowAttributes(dpy,Scr.Root,&(Scr.ASRoot.attr)); Scr.root_pushes = 0; Scr.pushed_window = &Scr.ASRoot; Scr.ASRoot.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; Scr.RaiseButtons = 0; /* set major operating modes */ Scr.flags = 0; Scr.NumBoxes = 0; Scr.randomx = Scr.randomy = 0; Scr.buttons2grab = 7; Scr.next_focus_sequence = 0; #ifndef NO_PAGER Scr.PagerFont.name = NULL; Scr.PagerFont.height = 0; Scr.PagerFont.y = 0; Scr.ASPager = (ASWindow *)0; Scr.Pager_w = None; Scr.CPagerWin = None; #endif Scr.InitFunction = NULL; Scr.RestartFunction = NULL; InitModifiers(); return; } /* Read the server modifier mapping */ void InitModifiers(void) { int m, i, knl; char* kn; KeySym ks; KeyCode kc, *kp; unsigned lockmask, *mp; XModifierKeymap* mm = XGetModifierMapping(dpy); lockmask = LockMask; if (mm) { kp = mm->modifiermap; for (m = 0; m < 8; m++) { for (i = 0; i < mm->max_keypermod; i++) { if ((kc = *kp++) && ((ks = XkbKeycodeToKeysym(dpy, kc, 0, 0)) != NoSymbol)) { kn = XKeysymToString(ks); knl = strlen(kn); if ((knl > 6) && (strcasecmp(kn + knl - 4, "lock") == 0)) lockmask |= (1 << m); } } } XFreeModifiermap(mm); } lockmask &= ~(ShiftMask | ControlMask); /* forget shift & control locks */ Scr.nonlock_mods = ((ShiftMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask| Mod4Mask| Mod5Mask) & ~lockmask); if (Scr.lock_mods == NULL) Scr.lock_mods = (unsigned*) safemalloc(256 * sizeof(unsigned)); mp = Scr.lock_mods; for (m = 0, i = 1; i < 256; i++) { if ((i & lockmask) > m) m = *mp++ = (i & lockmask); } *mp = 0; } /*********************************************************************** * * Procedure: * Reborder - Removes afterstep border windows * ************************************************************************/ void Reborder_unmap(ASWindow* t) { if (t->next) Reborder_unmap(t->next); XUnmapWindow(dpy, t->frame); RestoreWithdrawnLocation(t, True); XDestroyWindow(dpy, t->frame); } void Reborder(void) { ASWindow *tmp; /* temp afterstep 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.ASRoot); /* force reinstall */ Reborder_unmap(Scr.ASRoot.next); 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; afterstep_err("Seg Fault",NULL,NULL,NULL); event.error_code = 0; event.request_code = 0; ASErrorHandler(dpy, &event); /* Attempt to do a re-start of afterstep */ Done(0,NULL); } /*********************************************************************** * * Procedure: * Done - cleanup and exit afterstep * *********************************************************************** */ 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 *afterstep_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(afterstep_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,"afterstep")!= 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, "AfterStep: Call of '%s' failed!!!!\n",command); execvp(g_argv[0], g_argv); /* that _should_ work */ fprintf(stderr, "AfterStep: 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) { afterstep_err("another WM is running",NULL,NULL,NULL); exit(1); } /*********************************************************************** * * Procedure: * ASErrorHandler - displays info on internal errors * ************************************************************************/ XErrorHandler ASErrorHandler(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 ; afterstep_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 afterstep_err(char *message, char *arg1, char *arg2, char *arg3) { fprintf(stderr,"AfterStep: "); fprintf(stderr,message,arg1,arg2,arg3); fprintf(stderr,"\n"); } void usage(void) { #ifdef M4 #define USAGE "AfterStep Ver %s\n\nusage: afterstep [-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 "AfterStep Ver %s\n\nusage: afterstep [-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.ASCursors[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.ASCursors[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.ASCursors[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.ASCursors[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() { ASWindow *t; unsigned long data[1]; for (t = Scr.ASRoot.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); }