xenocara/app/fvwm/modules/FvwmBacker/FvwmBacker.c

387 lines
9.6 KiB
C

/* FvwmBacker 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. */
/* Modified to directly manipulate the X server if a solid color
* background is requested. To use this, usr "-solid <color_name>"
* as the command to be executed.
*
* A. Davison
* Septmber 1994.
*/
#include "config.h"
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/time.h>
#ifdef 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 /* Saul */
#include <stdlib.h>
#include "../../fvwm/module.h"
#include "FvwmBacker.h"
#include "Mallocs.h"
#include <X11/Xlib.h>
unsigned long GetColor(char *color);
typedef struct
{
int type; /* The command type.
* -1 = no command.
* 0 = command to be spawned
* 1 = a solid color to be set */
char* cmdStr; /* The command string (Type 0) */
unsigned long solidColor; /* A solid color after X parsing (Type 1) */
} Command;
Command *commands;
int DeskCount=0;
int Fvwm_fd[2];
int fd_width;
char *Module;
/* X Display information. */
Display* dpy;
Window root;
int screen;
FILE* logFile;
/* Comment this out if you don't want a logfile. */
/* #define LOGFILE "/tmp/FvwmBacker.log"*/
int main(int argc, char **argv)
{
char *temp, *s;
char* displayName = NULL;
commands=NULL;
/* Save the program name for error messages and config parsing */
temp = argv[0];
s=strrchr(argv[0], '/');
if (s != NULL)
temp = s + 1;
Module=temp;
if((argc != 6)&&(argc != 7)) {
fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",Module,
VERSION);
exit(1);
}
Fvwm_fd[0] = atoi(argv[1]);
Fvwm_fd[1] = atoi(argv[2]);
/* Grab the X display information now. */
dpy = XOpenDisplay(displayName);
if (!dpy)
{
fprintf(stderr, "%s: unable to open display '%s'\n",
Module, XDisplayName (displayName));
exit (2);
}
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
/* Open a log file if necessary */
# ifdef LOGFILE
logFile = fopen(LOGFILE,"a");
fprintf(logFile,"Initialising FvwmBacker\n");
# endif
signal (SIGPIPE, DeadPipe);
/* Parse the config file */
ParseConfig();
fd_width = GetFdWidth();
SetMessageMask(Fvwm_fd,M_NEW_DESK|M_CONFIG_INFO|M_END_CONFIG_INFO);
/*
** we really only want the current desk, and window list sends it
*/
SendInfo(Fvwm_fd,"Send_WindowList",0);
/* Recieve all messages from Fvwm */
EndLessLoop();
/* Should never get here! */
return 1;
}
/******************************************************************************
EndLessLoop - Read until we get killed, blocking when can't read
******************************************************************************/
void EndLessLoop()
{
fd_set readset;
struct timeval tv;
while(1) {
FD_ZERO(&readset);
FD_SET(Fvwm_fd[1],&readset);
tv.tv_sec=0;
tv.tv_usec=0;
if (!select(fd_width,SELECT_TYPE_ARG234 &readset,NULL,NULL,&tv)) {
FD_ZERO(&readset);
FD_SET(Fvwm_fd[1],&readset);
select(fd_width,SELECT_TYPE_ARG234 &readset,NULL,NULL,NULL);
}
if (!FD_ISSET(Fvwm_fd[1],&readset)) continue;
ReadFvwmPipe();
}
}
/******************************************************************************
ReadFvwmPipe - Read a single message from the pipe from Fvwm
Originally Loop() from FvwmIdent:
Copyright 1994, Robert Nation and Nobutaka Suzuki.
******************************************************************************/
void ReadFvwmPipe()
{
int count;
unsigned long header[HEADER_SIZE],*body;
body = NULL;
if((count = 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)
{
if (type==M_NEW_DESK)
{
if (body[0]>DeskCount || commands[body[0]].type == -1)
{
return;
}
#ifdef LOGFILE
fprintf(logFile,"Desk: %d\n",body[0]);
fprintf(logFile,"Command type: %d\n",commands[body[0]].type);
if (commands[body[0]].type == 0)
fprintf(logFile,"Command String: %s\n",commands[body[0]].cmdStr);
else if (commands[body[0]].type == 1)
fprintf(logFile,"Color Number: %d\n",commands[body[0]].solidColor);
else if (commands[body[0]].type == -1)
fprintf(logFile,"No Command\n");
else
{
fprintf(logFile,"Illegal command type !\n");
exit(1);
}
fflush(logFile);
# endif
if (commands[body[0]].type == 1)
{
/* Process a solid color request */
XSetWindowBackground(dpy, root, commands[body[0]].solidColor);
XClearWindow(dpy, root);
XFlush(dpy);
/* XSetWindowBackground(dpy, root, commands[body[0]].solidColor);
*/
# ifdef LOGFILE
fprintf(logFile,"Color set.\n");
fflush(logFile);
# endif
}
else if(commands[body[0]].cmdStr != NULL)
{
#if 0
system(commands[body[0]].cmdStr);
#else /* much more useful: */
SendFvwmPipe(commands[body[0]].cmdStr, (unsigned long)0);
#endif
}
}
}
/******************************************************************************
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=malloc(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)
{
exit(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()
{
char line2[40];
char *tline;
sprintf(line2,"*%sDesk",Module);
GetConfigLine(Fvwm_fd,&tline);
while(tline != (char *)0)
{
if(strlen(tline)>1)
{
if(strncasecmp(tline,line2,strlen(line2))==0)
AddCommand(&tline[strlen(line2)]);
}
GetConfigLine(Fvwm_fd,&tline);
}
}
/******************************************************************************
AddCommand - Add a command to the correct spot on the dynamic array.
******************************************************************************/
void AddCommand(char *string)
{
char *temp;
int num;
temp=string;
while(isspace(*temp)) temp++;
num=atoi(temp);
while(!isspace(*temp)) temp++;
while(isspace(*temp)) temp++;
if (DeskCount<1) {
commands=(Command*)safemalloc((num+1)*sizeof(Command));
while(DeskCount<num+1) commands[DeskCount++].type= -1;
}
else {
if (num+1>DeskCount) {
commands=(Command*)realloc(commands,(num+1)*sizeof(Command));
while(DeskCount<num+1) commands[DeskCount++].type= -1;
}
}
/* commands[num]=(Command*)safemalloc(sizeof(Command));
*/
/* Now check the type of command... */
/* strcpy(commands[num],temp);*/
if (strncmp(temp,"-solid",6)==0)
{
char* color;
char* tmp;
/* Process a solid color request */
color = &temp[7];
while (isspace(*color))
color++;
tmp= color;
while (!isspace(*tmp))
tmp++;
*tmp = 0;
commands[num].type = 1;
commands[num].solidColor = (!color || !*color) ?
BlackPixel(dpy, screen) :
GetColor(color);
#ifdef LOGFILE
fprintf(logFile,"Adding color: %s as number %d to desk %d\n",
color,commands[num].solidColor, num);
fflush(logFile);
#endif
}
else
{
#ifdef LOGFILE
fprintf(logFile,"Adding command: %s to desk %d\n",temp, num);
fflush(logFile);
#endif
commands[num].type = 0;
commands[num].cmdStr = (char *)safemalloc(strlen(temp)+1);
strcpy(commands[num].cmdStr,temp);
}
}