387 lines
9.6 KiB
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);
|
||
|
}
|
||
|
|
||
|
}
|