diff options
Diffstat (limited to 'app/fvwm/modules/FvwmWinList/FvwmWinList.c')
-rw-r--r-- | app/fvwm/modules/FvwmWinList/FvwmWinList.c | 1076 |
1 files changed, 1076 insertions, 0 deletions
diff --git a/app/fvwm/modules/FvwmWinList/FvwmWinList.c b/app/fvwm/modules/FvwmWinList/FvwmWinList.c new file mode 100644 index 000000000..9fb6aaa39 --- /dev/null +++ b/app/fvwm/modules/FvwmWinList/FvwmWinList.c @@ -0,0 +1,1076 @@ +/* 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 <stdio.h> +#include <signal.h> +#include <fcntl.h> +#include <string.h> +#include <sys/wait.h> +#include <sys/time.h> +#include <stdarg.h> + +#if HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#include <unistd.h> +#include <ctype.h> + +#ifdef HAVE_SYS_BSDTYPES_H +#include <sys/bsdtypes.h> /* Saul */ +#endif + +#include <stdlib.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xproto.h> +#include <X11/Xatom.h> +#include <X11/Intrinsic.h> +#include <X11/cursorfont.h> + +#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;i<total;i++) + { + temp=ItemName(&windows,i); + if(temp != NULL) + { + tw=10+XTextWidth(ButtonFont,temp,strlen(temp)); + tw+=XTextWidth(ButtonFont,"()",2); + +#ifdef MINI_ICONS + tw+=14; /* for title icon */ /* Magic Number ? */ +#endif + + new_width=max(new_width,tw); + } + } + new_width=max(new_width, MinWidth); + new_width=min(new_width, MaxWidth); + new_height=(total*(fontheight+6+1)); + if (WindowIsUp && (new_height!=win_height || new_width!=win_width)) + { + if (Anchor) + { + off_x = off_y = 0; + MyXGrabServer(dpy); + frame = find_frame_window(win, &off_x, &off_y); + XGetWindowAttributes(dpy, frame, &frame_attr); + XGetWindowAttributes(dpy, win, &win_attr); + win_x = frame_attr.x + frame_attr.border_width + off_x; + win_y = frame_attr.y + frame_attr.border_width + off_y; + + if (win_grav == SouthEastGravity || win_grav == NorthEastGravity) + win_x += win_attr.width - new_width; + if (win_grav == SouthEastGravity || win_grav == SouthWestGravity) + win_y += win_attr.height - new_height; + + XMoveResizeWindow(dpy, win, win_x, win_y, new_width, new_height); + MyXUngrabServer(dpy); + } + else + XResizeWindow(dpy, win, new_width, new_height); + + } + UpdateArray(&buttons,-1,-1,new_width,-1); + if (new_height>0) 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; +} + |