/* FvwmWinList Module for Fvwm. * * Copyright 1994, Mike Finger (mfinger@mermaid.micro.umn.edu or * Mike_Finger@atk.com) * * The author makes not guarantees or warantees, either express or * implied. Feel free to use any contained here for any purpose, as long * and this and any other applicible copyrights are kept intact. * The functions in this source file that are based on part of the FvwmIdent * module for Fvwm are noted by a small copyright atop that function, all others * are copyrighted by Mike Finger. For those functions modified/used, here is * the full, origonal copyright: * * Copyright 1994, Robert Nation and Nobutaka Suzuki. * No guarantees or warantees or anything * are provided or implied in any way whatsoever. Use this program at your * own risk. Permission to use this program for any purpose is given, * as long as the copyright is kept intact. * Modifications Done to Add Pixmaps, focus highlighting and Current Desk Only * By Don Mahurin, 1996, Some of this Code was taken from FvwmTaskBar * Bug Notes:(Don Mahurin) * Moving a window doesnt send M_CONFIGURE, as I thought it should. Desktop * for that button is not updated. */ #define TRUE 1 #define FALSE 0 #ifndef NO_CONSOLE #define NO_CONSOLE #endif #define YES "Yes" #define NO "No" #include "config.h" #include #include #include #include #include #include #include #if HAVE_SYS_SELECT_H #include #endif #include #include #ifdef HAVE_SYS_BSDTYPES_H #include /* Saul */ #endif #include #include #include #include #include #include #include #include "../../fvwm/module.h" #include "FvwmWinList.h" #include "ButtonArray.h" #include "List.h" #include "Colors.h" #include "Mallocs.h" #define GRAB_EVENTS (ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|EnterWindowMask|LeaveWindowMask) #define SomeButtonDown(a) ((a)&Button1Mask||(a)&Button2Mask||(a)&Button3Mask) /* File type information */ FILE *console; int fd_width; int Fvwm_fd[2]; int x_fd; /* X related things */ Display *dpy; Window Root, win; int screen,d_depth,ScreenWidth,ScreenHeight; Pixel back[MAX_COLOUR_SETS], fore[MAX_COLOUR_SETS]; GC graph[MAX_COLOUR_SETS],shadow[MAX_COLOUR_SETS],hilite[MAX_COLOUR_SETS]; GC background[MAX_COLOUR_SETS]; XFontStruct *ButtonFont; int fontheight; static Atom wm_del_win; Atom MwmAtom = None; /* Module related information */ char *Module; int WindowIsUp=0,win_width=5,win_height=5,win_grav,win_x,win_y,win_title,win_border; int Clength,Transient=0,Pressed=0,ButPressed,Checked=0; int MinWidth=DEFMINWIDTH,MaxWidth=DEFMAXWIDTH; ButtonArray buttons; List windows; char *ClickAction[3]={"Iconify -1,Raise","Iconify","Lower"},*EnterAction, *BackColor[MAX_COLOUR_SETS] = { "white" }, *ForeColor[MAX_COLOUR_SETS] = { "black" }, *geometry=""; char *font_string = "fixed"; int UseSkipList=0,Anchor=1,UseIconNames=0,LeftJustify=0,TruncateLeft=0,ShowFocus=1; long CurrentDesk = 0; int ShowCurrentDesk = 0; static volatile sig_atomic_t isTerminated = False; static RETSIGTYPE TerminateHandler(int sig); /*************************************************************************** * TerminateHandler - reentrant signal handler that ends the main event loop ***************************************************************************/ static RETSIGTYPE TerminateHandler(int sig) { isTerminated = True; } int ItemCountD(List *list ) { if(!ShowCurrentDesk) return ItemCount(list); /* else */ return ItemCountDesk(list, CurrentDesk); } /****************************************************************************** Main - Setup the XConnection,request the window list and loop forever Based on main() from FvwmIdent: Copyright 1994, Robert Nation and Nobutaka Suzuki. ******************************************************************************/ int main(int argc, char **argv) { char *temp, *s; #ifdef HAVE_SIGACTION struct sigaction sigact; #endif /* Save the program name for error messages and config parsing */ temp = argv[0]; s=strrchr(argv[0], '/'); if (s != NULL) temp = s + 1; /* Setup my name */ Module = safemalloc(strlen(temp)+2); strcpy(Module,"*"); strcat(Module, temp); Clength = strlen(Module); /* Open the console for messages */ OpenConsole(); if((argc != 6)&&(argc != 7)) { fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",Module, VERSION); ConsoleMessage("%s Version %s should only be executed by fvwm!\n",Module, VERSION); exit(1); } if ((argc==7)&&(!strcasecmp(argv[6],"Transient"))) Transient=1; Fvwm_fd[0] = atoi(argv[1]); Fvwm_fd[1] = atoi(argv[2]); #ifdef HAVE_SIGACTION #ifdef SA_INTERRUPT sigact.sa_flags = SA_INTERRUPT; #else sigact.sa_flags = 0; #endif sigemptyset(&sigact.sa_mask); sigact.sa_handler = TerminateHandler; sigaction(SIGPIPE, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); #else signal(SIGPIPE, TerminateHandler); signal(SIGTERM, TerminateHandler); #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGPIPE, True); siginterrupt(SIGTERM, True); #endif #endif /* Parse the config file */ ParseConfig(); /* Setup the XConnection */ StartMeUp(); XSetErrorHandler(ErrorHandler); InitPictureCMap(dpy, Root); InitArray(&buttons,0,0,win_width, fontheight+6); InitList(&windows); fd_width = GetFdWidth(); /* Request a list of all windows, * wait for ConfigureWindow packets */ SetMessageMask(Fvwm_fd,M_CONFIGURE_WINDOW | M_RES_CLASS | M_RES_NAME | M_ADD_WINDOW | M_DESTROY_WINDOW | M_ICON_NAME | M_DEICONIFY | M_ICONIFY | M_END_WINDOWLIST | M_NEW_DESK | M_NEW_PAGE | M_FOCUS_CHANGE | M_WINDOW_NAME | #ifdef MINI_ICONS M_MINI_ICON | #endif M_STRING); SendFvwmPipe("Send_WindowList",0); /* Recieve all messages from Fvwm */ atexit(ShutMeDown); MainEventLoop(); return 0; } /****************************************************************************** MainEventLoop - Read and redraw until we die, blocking when can't read ******************************************************************************/ void MainEventLoop(void) { fd_set readset; while( !isTerminated ) { FD_ZERO(&readset); FD_SET(Fvwm_fd[1],&readset); FD_SET(x_fd,&readset); /* This code restyled after FvwmIconMan, which is simpler. * The biggest advantage over the original approach is * having one fewer select statements */ XFlush(dpy); if (select(fd_width,SELECT_TYPE_ARG234 &readset,NULL,NULL,NULL) > 0) { if (FD_ISSET(x_fd,&readset) || XPending(dpy)) LoopOnEvents(); if (FD_ISSET(Fvwm_fd[1],&readset)) ReadFvwmPipe(); } } /* while */ } /****************************************************************************** ReadFvwmPipe - Read a single message from the pipe from Fvwm Originally Loop() from FvwmIdent: Copyright 1994, Robert Nation and Nobutaka Suzuki. ******************************************************************************/ void ReadFvwmPipe(void) { unsigned long header[HEADER_SIZE],*body; if(ReadFvwmPacket(Fvwm_fd[1],header,&body) > 0) { ProcessMessage(header[1],body); free(body); } } /****************************************************************************** ProcessMessage - Process the message coming from Fvwm Skeleton based on processmessage() from FvwmIdent: Copyright 1994, Robert Nation and Nobutaka Suzuki. ******************************************************************************/ void ProcessMessage(unsigned long type,unsigned long *body) { int redraw=0,i; long flags; char *name,*string; static int current_focus=-1; Picture p; switch(type) { case M_ADD_WINDOW: case M_CONFIGURE_WINDOW: if ((i = FindItem(&windows,body[0]))!=-1) { if(UpdateItemDesk(&windows, i, body[7]) > 0) { AdjustWindow(); RedrawWindow(1); } break; } if (!(body[8]&WINDOWLISTSKIP) || !UseSkipList) AddItem(&windows,body[0],body[8], body[7] /* desk */); break; case M_DESTROY_WINDOW: if ((i=DeleteItem(&windows,body[0]))==-1) break; RemoveButton(&buttons,i); if (WindowIsUp) AdjustWindow(); redraw=1; break; #ifdef MINI_ICONS case M_MINI_ICON: if ((i=FindItem(&windows,body[0]))==-1) break; if (UpdateButton(&buttons,i,NULL,-1)!=-1) { p.width = body[3]; p.height = body[4]; p.depth = body[5]; p.picture = body[6]; p.mask = body[7]; UpdateButtonPicture(&buttons, i, &p); redraw = 0; } break; #endif case M_WINDOW_NAME: case M_ICON_NAME: if ((type==M_ICON_NAME && !UseIconNames) || (type==M_WINDOW_NAME && UseIconNames)) break; if ((i=UpdateItemName(&windows,body[0],(char *)&body[3]))==-1) break; string=(char *)&body[3]; name=makename(string,ItemFlags(&windows,body[0])); if (UpdateButton(&buttons,i,name,-1)==-1) { AddButton(&buttons, name, NULL, 1); UpdateButtonSet(&buttons,i,ItemFlags(&windows,body[0])&ICONIFIED?1:0); UpdateButtonDesk(&buttons,i,ItemDesk(&windows, body[0])); } free(name); if (WindowIsUp) AdjustWindow(); redraw=1; break; case M_DEICONIFY: case M_ICONIFY: if ((i=FindItem(&windows,body[0]))==-1) break; flags=ItemFlags(&windows,body[0]); if (type==M_DEICONIFY && !(flags&ICONIFIED)) break; if (type==M_ICONIFY && flags&ICONIFIED) break; flags^=ICONIFIED; UpdateItemFlags(&windows,body[0],flags); string=ItemName(&windows,i); name=makename(string,flags); if (UpdateButton(&buttons,i,name,-1)!=-1) redraw=1; if (i!=current_focus||(flags&ICONIFIED)) if (UpdateButtonSet(&buttons,i,(flags&ICONIFIED) ? 1 : 0)!=-1) redraw=1; free(name); break; case M_FOCUS_CHANGE: if ((i=FindItem(&windows,body[0]))!=-1) { flags=ItemFlags(&windows,body[0]); UpdateItemFlags(&windows,body[0],flags); RadioButton(&buttons,i); } else RadioButton(&buttons,-1); redraw = 1; break; case M_END_WINDOWLIST: if (!WindowIsUp) MakeMeWindow(); redraw = 1; break; case M_NEW_DESK: CurrentDesk = body[0]; if(ShowCurrentDesk) { AdjustWindow(); RedrawWindow(1); } break; case M_NEW_PAGE: break; } if (redraw && WindowIsUp==1) RedrawWindow(0); } /****************************************************************************** SendFvwmPipe - Send a message back to fvwm Based on SendInfo() from FvwmIdent: Copyright 1994, Robert Nation and Nobutaka Suzuki. ******************************************************************************/ void SendFvwmPipe(char *message,unsigned long window) { int w; char *hold,*temp,*temp_msg; hold=message; while(1) { temp=strchr(hold,','); if (temp!=NULL) { temp_msg=safemalloc(temp-hold+1); strncpy(temp_msg,hold,(temp-hold)); temp_msg[(temp-hold)]='\0'; hold=temp+1; } else temp_msg=hold; write(Fvwm_fd[0],&window, sizeof(unsigned long)); w=strlen(temp_msg); write(Fvwm_fd[0],&w,sizeof(int)); write(Fvwm_fd[0],temp_msg,w); /* keep going */ w=1; write(Fvwm_fd[0],&w,sizeof(int)); if(temp_msg!=hold) free(temp_msg); else break; } } /*********************************************************************** Detected a broken pipe - time to exit Based on DeadPipe() from FvwmIdent: Copyright 1994, Robert Nation and Nobutaka Suzuki. **********************************************************************/ void DeadPipe(int nonsense) { /* ShutMeDown(1); */ /* * do not call ShutMeDown, it may make X calls which are not allowed * in a signal hander. * * THIS IS NO LONGER A SIGNAL HANDLER - we may now shut down gracefully * NOTE: ShutMeDown will now be called automatically by exit(). */ exit(1); } /****************************************************************************** WaitForExpose - Used to wait for expose event so we don't draw too early ******************************************************************************/ void WaitForExpose(void) { XEvent Event; while(1) { /* * Temporary solution to stop the process blocking * in XNextEvent once we have been asked to quit. * There is still a small race condition between * checking the flag and calling the X-Server, but * we can fix that ... */ if (isTerminated) { /* Just exit - the installed exit-procedure will clean up */ exit(0); } /**/ XNextEvent(dpy,&Event); if (Event.type==Expose) { if (Event.xexpose.count==0) break; } } } /****************************************************************************** RedrawWindow - Update the needed lines and erase any old ones ******************************************************************************/ void RedrawWindow(int force) { DrawButtonArray(&buttons, force); if (XQLength(dpy) && !force) LoopOnEvents(); } /****************************************************************************** ConsoleMessage - Print a message on the console. Works like printf. ******************************************************************************/ void ConsoleMessage(const char *fmt, ...) { #ifndef NO_CONSOLE va_list args; FILE *filep; if (console==NULL) filep=stderr; else filep=console; va_start(args,fmt); vfprintf(filep,fmt,args); va_end(args); #endif } /****************************************************************************** OpenConsole - Open the console as a way of sending messages ******************************************************************************/ int OpenConsole(void) { #ifndef NO_CONSOLE if ((console=fopen("/dev/console","w"))==NULL) { fprintf(stderr,"%s: cannot open console\n",Module); return 0; } #endif return 1; } /****************************************************************************** ParseConfig - Parse the configuration file fvwm to us to use Based on part of main() from FvwmIdent: Copyright 1994, Robert Nation and Nobutaka Suzuki. ******************************************************************************/ void ParseConfig(void) { char *tline; GetConfigLine(Fvwm_fd,&tline); while(tline != (char *)0) { if(strlen(tline)>1) { if(strncasecmp(tline, CatString3(Module, "Font",""),Clength+4)==0) CopyString(&font_string,&tline[Clength+4]); else if(strncasecmp(tline,CatString3(Module,"Fore",""), Clength+4)==0) CopyString(&ForeColor[0],&tline[Clength+4]); else if(strncasecmp(tline,CatString3(Module,"IconFore",""), Clength+8)==0) CopyString(&ForeColor[1],&tline[Clength+8]); else if(strncasecmp(tline,CatString3(Module,"FocusFore",""), Clength+9)==0) { CopyString(&ForeColor[2],&tline[Clength+9]); CopyString(&ForeColor[3],&tline[Clength+9]); } else if(strncasecmp(tline,CatString3(Module, "Geometry",""), Clength+8)==0) CopyString(&geometry,&tline[Clength+8]); else if(strncasecmp(tline,CatString3(Module, "Back",""), Clength+4)==0) CopyString(&BackColor[0],&tline[Clength+4]); else if(strncasecmp(tline,CatString3(Module,"IconBack",""), Clength+8)==0) CopyString(&BackColor[1],&tline[Clength+8]); else if(strncasecmp(tline,CatString3(Module,"FocusBack",""), Clength+9)==0) { CopyString(&BackColor[2],&tline[Clength+9]); CopyString(&BackColor[3],&tline[Clength+9]); } else if(strncasecmp(tline,CatString3(Module, "NoAnchor",""), Clength+8)==0) Anchor=0; else if(strncasecmp(tline,CatString3(Module, "Action",""), Clength+6)==0) LinkAction(&tline[Clength+6]); else if(strncasecmp(tline,CatString3(Module, "UseSkipList",""), Clength+11)==0) UseSkipList=1; else if(strncasecmp(tline,CatString3(Module, "UseIconNames",""), Clength+12)==0) UseIconNames=1; else if(strncasecmp(tline,CatString3(Module, "ShowCurrentDesk",""), Clength+15)==0) ShowCurrentDesk=1; else if(strncasecmp(tline,CatString3(Module, "LeftJustify",""), Clength+11)==0) LeftJustify=1; else if(strncasecmp(tline,CatString3(Module, "TruncateLeft",""), Clength+12)==0) TruncateLeft=1; else if(strncasecmp(tline,CatString3(Module, "MinWidth",""), Clength+8)==0) MinWidth=atoi(&tline[Clength+8]); else if(strncasecmp(tline,CatString3(Module, "MaxWidth",""), Clength+8)==0) MaxWidth=atoi(&tline[Clength+8]); else if(strncasecmp(tline,CatString3(Module, "DontDepressFocus",""), Clength+16)==0) ShowFocus=0; } GetConfigLine(Fvwm_fd,&tline); } } /****************************************************************************** LoopOnEvents - Process all the X events we get ******************************************************************************/ void LoopOnEvents(void) { int num; char buffer[10]; XEvent Event; Window dummyroot,dummychild; int x,x1,y,y1; unsigned int dummy1; if (Transient && !Checked) { XQueryPointer(dpy,win,&dummyroot,&dummychild,&x1,&y1,&x,&y,&dummy1); num=WhichButton(&buttons,x,y); if (num!=-1) { Pressed=1; ButPressed=num; SwitchButton(&buttons,num); } else Pressed=0; Checked=1; } while(XPending(dpy)) { XNextEvent(dpy,&Event); switch(Event.type) { case ButtonRelease: if (Pressed) { num=WhichButton(&buttons,Event.xbutton.x,Event.xbutton.y); if (num!=-1) { SendFvwmPipe(ClickAction[(Transient) ? 0:Event.xbutton.button-1], ItemID(&windows,num)); SwitchButton(&buttons,num); } } if (Transient) exit(0); Pressed=0; ButPressed=-1; break; case ButtonPress: num=WhichButton(&buttons,Event.xbutton.x,Event.xbutton.y); if (num != -1) { SwitchButton(&buttons,num); ButPressed=num; } else ButPressed=-1; Pressed=1; break; case Expose: if (Event.xexpose.count==0) RedrawWindow(1); break; case KeyPress: num=XLookupString(&Event.xkey,buffer,10,NULL,0); if (num==1) { if (buffer[0]=='q' || buffer[0]=='Q') exit(0); else if (buffer[0]=='i' || buffer[0]=='I') PrintList(&windows); else if (buffer[0]=='b' || buffer[0]=='B') PrintButtons(&buttons); } break; case ClientMessage: if ((Event.xclient.format==32) && (Event.xclient.data.l[0]==wm_del_win)) exit(0); case EnterNotify: if (!SomeButtonDown(Event.xcrossing.state)) break; num=WhichButton(&buttons,Event.xcrossing.x,Event.xcrossing.y); if (num!=-1) { SwitchButton(&buttons,num); ButPressed=num; } else ButPressed=-1; Pressed=1; break; case LeaveNotify: if (!SomeButtonDown(Event.xcrossing.state)) break; if (ButPressed!=-1) SwitchButton(&buttons,ButPressed); Pressed=0; break; case MotionNotify: if (!Pressed) break; num=WhichButton(&buttons,Event.xmotion.x,Event.xmotion.y); if (num==ButPressed) break; if (ButPressed!=-1) SwitchButton(&buttons,ButPressed); if (num!=-1) { SwitchButton(&buttons,num); ButPressed=num; } else ButPressed=-1; break; } } } /****************************************************************************** find_frame_window - looks for ancestor that is a child of the root Cribbed from FvwmIconMan/x.c - maybe should be in a library Returns the root-child and fills in off_x, off_y to give offset ******************************************************************************/ Window find_frame_window (Window win, int *off_x, int *off_y) { Window root, parent, *junkw; int junki; XWindowAttributes attr; while (1) { XQueryTree (dpy, win, &root, &parent, &junkw, &junki); if (junkw) XFree (junkw); if (parent == root) break; XGetWindowAttributes (dpy, win, &attr); *off_x += attr.x + attr.border_width; *off_y += attr.y + attr.border_width; win = parent; } return win; } /****************************************************************************** AdjustWindow - Resize the window according to maxwidth by number of buttons ******************************************************************************/ void AdjustWindow(void) { int new_width=0,new_height=0,tw,i,total,off_x,off_y; char *temp; Window frame; XWindowAttributes win_attr, frame_attr; total = ItemCountD(&windows ); if (!total) { if (WindowIsUp==1) { XUnmapWindow(dpy,win); WindowIsUp=2; } return; } for(i=0;i0) win_height = new_height; if (new_width>0) win_width = new_width; if (WindowIsUp==2) { XMapWindow(dpy,win); WindowIsUp=1; WaitForExpose(); } } /****************************************************************************** makename - Based on the flags return me '(name)' or 'name' ******************************************************************************/ char *makename(const char *string,long flags) { char *ptr; ptr=safemalloc(strlen(string)+3); *ptr = '\0'; if (flags&ICONIFIED) strcpy(ptr,"("); strcat(ptr,string); if (flags&ICONIFIED) strcat(ptr,")"); return ptr; } /****************************************************************************** LinkAction - Link an response to a users action ******************************************************************************/ void LinkAction(char *string) { char *temp; temp=string; while(isspace(*temp)) temp++; if(strncasecmp(temp, "Click1", 6)==0) CopyString(&ClickAction[0],&temp[6]); else if(strncasecmp(temp, "Click2", 6)==0) CopyString(&ClickAction[1],&temp[6]); else if(strncasecmp(temp, "Click3", 6)==0) CopyString(&ClickAction[2],&temp[6]); else if(strncasecmp(temp, "Enter", 5)==0) CopyString(&EnterAction,&temp[5]); } /****************************************************************************** MakeMeWindow - Create and setup the window we will need ******************************************************************************/ void MakeMeWindow(void) { XSizeHints hints; XGCValues gcval; unsigned long gcmask; unsigned int dummy1, dummy2; int x, y, ret, count; Window dummyroot, dummychild; int i; if ((count = ItemCountD(&windows))==0 && Transient) exit(0); AdjustWindow(); hints.width=win_width; hints.height=win_height; hints.win_gravity=NorthWestGravity; hints.flags=PSize|PWinGravity|PResizeInc; hints.width_inc=0; hints.height_inc=0; if (geometry!= NULL) { ret=XParseGeometry(geometry,&x,&y,&dummy1,&dummy2); if (ret&XValue && ret &YValue) { hints.x=x; if (ret&XNegative) hints.x+=XDisplayWidth(dpy,screen)-win_width; hints.y=y; if (ret&YNegative) hints.y+=XDisplayHeight(dpy,screen)-win_height; hints.flags|=USPosition; } if (ret&XNegative) { if (ret&YNegative) hints.win_gravity=SouthEastGravity; else hints.win_gravity=NorthEastGravity; } else { if (ret&YNegative) hints.win_gravity=SouthWestGravity; else hints.win_gravity=NorthWestGravity; } } if (Transient) { XQueryPointer(dpy,Root,&dummyroot,&dummychild,&hints.x,&hints.y,&x,&y,&dummy1); hints.win_gravity=NorthWestGravity; hints.flags |= USPosition; } win_grav=hints.win_gravity; win_x=hints.x; win_y=hints.y; for (i = 0; i != MAX_COLOUR_SETS; i++) if(d_depth < 2) { back[i] = GetColor("white"); fore[i] = GetColor("black"); } else { back[i] = GetColor(BackColor[i] == NULL ? BackColor[0] : BackColor[i]); fore[i] = GetColor(ForeColor[i] == NULL ? ForeColor[0] : ForeColor[i]); } win=XCreateSimpleWindow(dpy,Root,hints.x,hints.y,hints.width,hints.height,0, fore[0],back[0]); wm_del_win=XInternAtom(dpy,"WM_DELETE_WINDOW",False); XSetWMProtocols(dpy,win,&wm_del_win,1); XSetWMNormalHints(dpy,win,&hints); if (!Transient) { XGrabButton(dpy,1,AnyModifier,win,True,GRAB_EVENTS,GrabModeAsync, GrabModeAsync,None,None); XGrabButton(dpy,2,AnyModifier,win,True,GRAB_EVENTS,GrabModeAsync, GrabModeAsync,None,None); XGrabButton(dpy,3,AnyModifier,win,True,GRAB_EVENTS,GrabModeAsync, GrabModeAsync,None,None); SetMwmHints(MWM_DECOR_ALL|MWM_DECOR_RESIZEH|MWM_DECOR_MAXIMIZE|MWM_DECOR_MINIMIZE, MWM_FUNC_ALL|MWM_FUNC_RESIZE|MWM_FUNC_MAXIMIZE|MWM_FUNC_MINIMIZE, MWM_INPUT_MODELESS); } else { SetMwmHints(0,MWM_FUNC_ALL,MWM_INPUT_MODELESS); } for (i = 0; i != MAX_COLOUR_SETS; i++) { gcval.foreground=fore[i]; gcval.background=back[i]; gcval.font=ButtonFont->fid; gcmask=GCForeground|GCBackground|GCFont; graph[i]=XCreateGC(dpy,Root,gcmask,&gcval); if(d_depth < 2) gcval.foreground=GetShadow(fore[i]); else gcval.foreground=GetShadow(back[i]); gcval.background=back[i]; gcmask=GCForeground|GCBackground; shadow[i]=XCreateGC(dpy,Root,gcmask,&gcval); gcval.foreground=GetHilite(back[i]); gcval.background=back[i]; gcmask=GCForeground|GCBackground; hilite[i]=XCreateGC(dpy,Root,gcmask,&gcval); gcval.foreground=back[i]; gcmask=GCForeground; background[i]=XCreateGC(dpy,Root,gcmask,&gcval); } XSelectInput(dpy,win,(ExposureMask | KeyPressMask)); ChangeWindowName(&Module[1]); if (ItemCountD(&windows) > 0) { XMapRaised(dpy,win); WaitForExpose(); WindowIsUp=1; } else WindowIsUp=2; if (Transient) { if ( XGrabPointer(dpy,win,True,GRAB_EVENTS,GrabModeAsync,GrabModeAsync, None,None,CurrentTime)!=GrabSuccess) exit(1); XQueryPointer(dpy,Root,&dummyroot,&dummychild,&hints.x,&hints.y,&x,&y,&dummy1); if (!SomeButtonDown(dummy1)) exit(0); } } /****************************************************************************** StartMeUp - Do X initialization things ******************************************************************************/ void StartMeUp(void) { if (!(dpy = XOpenDisplay(""))) { fprintf(stderr,"%s: can't open display %s", Module, XDisplayName("")); exit (1); } x_fd = XConnectionNumber(dpy); screen= DefaultScreen(dpy); Root = RootWindow(dpy, screen); d_depth = DefaultDepth(dpy, screen); ScreenHeight = DisplayHeight(dpy,screen); ScreenWidth = DisplayWidth(dpy,screen); if ((ButtonFont=XLoadQueryFont(dpy,font_string))==NULL) { if ((ButtonFont=XLoadQueryFont(dpy,"fixed"))==NULL) exit(1); } fontheight = ButtonFont->ascent+ButtonFont->descent; win_width=XTextWidth(ButtonFont,"XXXXXXXXXXXXXXX",10); } /****************************************************************************** ShutMeDown - Do X client cleanup ******************************************************************************/ void ShutMeDown(void) { FreeList(&windows); FreeAllButtons(&buttons); /* XFreeGC(dpy,graph);*/ if (WindowIsUp) XDestroyWindow(dpy,win); XCloseDisplay(dpy); } /****************************************************************************** ChangeWindowName - Self explanitory Original work from FvwmIdent: Copyright 1994, Robert Nation and Nobutaka Suzuki. ******************************************************************************/ void ChangeWindowName(char *str) { XTextProperty name; if (XStringListToTextProperty(&str,1,&name) == 0) { fprintf(stderr,"%s: cannot allocate window name.\n",Module); return; } XSetWMName(dpy,win,&name); XSetWMIconName(dpy,win,&name); XFree(name.value); } /************************************************************************** * * Sets mwm hints * *************************************************************************/ /* * Now, if we (hopefully) have MWW - compatible window manager , * say, mwm, ncdwm, or else, we will set useful decoration style. * Never check for MWM_RUNNING property.May be considered bad. */ void SetMwmHints(unsigned int value, unsigned int funcs, unsigned int input) { PropMwmHints prop; if (MwmAtom==None) { MwmAtom=XInternAtom(dpy,"_MOTIF_WM_HINTS",False); } if (MwmAtom!=None) { /* sh->mwm.decorations contains OR of the MWM_DECOR_XXXXX */ prop.decorations= value; prop.functions = funcs; prop.inputMode = input; prop.flags = MWM_HINTS_DECORATIONS| MWM_HINTS_FUNCTIONS | MWM_HINTS_INPUT_MODE; /* HOP - LA! */ XChangeProperty (dpy,win, MwmAtom, MwmAtom, 32, PropModeReplace, (unsigned char *)&prop, PROP_MWM_HINTS_ELEMENTS); } } /************************************************************************ X Error Handler ************************************************************************/ int ErrorHandler(Display *d, XErrorEvent *event) { char errmsg[256]; XGetErrorText(d, event->error_code, errmsg, sizeof(errmsg)); ConsoleMessage("%s failed request: %s\n", Module, errmsg); ConsoleMessage("Major opcode: 0x%x, resource id: 0x%x\n", event->request_code, (unsigned int)event->resourceid); return 0; }