xenocara/app/fvwm/modules/FvwmWinList/FvwmWinList.c

1077 lines
30 KiB
C

/* 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;
}