ipcUtils.c
/*
$Header: ipcUtils.c,v 1.10 97/04/14 16:18:35 doomer Exp $
$Revision: 1.10 $
$Date: 97/04/14 16:18:35 $
$Author: doomer $
Copyright (c) 1997 John Dumais. All rights reserved.
*/
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <Xm/Xm.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <stdio.h>
/*
This file is the source for a library of routines that allows
us to do some interesting stuff with the window a VEE process
creates.
*/
/*
The operations we supply to manipulate the VEE window. We
give ourselves the capability to push VEE's run, stop, pause,
and step buttons.
*/
enum VeeOperation{
vOperNotDefined = -1,
vRun,
vPause,
vStepInto,
vContinue
};
/*
We define a table that associates a given action with the series
of keystrokes we send to the VEE window to make that action happen.
*/
struct{
enum VeeOperation op;
KeySym keySym;
unsigned char sendControl :1;
} VeeOperationStruct[]={
{vRun, XK_g, 1},
{vPause, XK_p, 1},
{vStepInto, XK_t, 1},
{vOperNotDefined, 0, 0}
};
/*
A utility function that gives us the index into a table
of keystrokes we need to send to a VEE program to get
some action to take place.
*/
int tableIndexForOperation(veeOp)
enum VeeOperation veeOp;{
int returnVal = -1;
int index=0;
while(VeeOperationStruct[index].op != vOperNotDefined){
if(VeeOperationStruct[index].op == veeOp){
returnVal=index;
break;
}
index++;
}
return returnVal;
}
/*
Set up a function to be called when X errors occur. The most
likely time for this is when we ask for a VEE window handle
when there is no VEE window. We don't want our application to
terminate, we would rather handle this case gracefully.
*/
static errorHandler=0;
int xErrorHandler(aDisplay, xError)
Display *aDisplay;
XErrorEvent *xError;{
return 0;
}
/*
When a VEE process starts, it puts its window id in an atom.
We read this atom to find a VEE window we can control.
*/
Atom wmVeeWindow=(Atom)0;
/*
When a VEE process starts, it takes ownership of an atom.
Taking ownership means that the X window system associates
a window id with the atom. If we find out who owns the atom,
we have identified a VEE window. We find out who owns an atom
by making the X call XGetSelectionOwner().
Because only one window can own an atom at a time, and because
a VEE process only asserts ownership of the atom at startup
time, we can only identify the last VEE window created.
*/
Window findVeeWin(aDisplay)
Display *aDisplay;{
Window selectionOwner;
if(!errorHandler){
XSetErrorHandler(xErrorHandler);
}
wmVeeWindow=XInternAtom(aDisplay, "WM_VEEWINDOW", True);
if(!wmVeeWindow){
return((Window) 0);
}
selectionOwner=XGetSelectionOwner(aDisplay, wmVeeWindow);
if(selectionOwner == (Window)None){
return((Window)0);
}
return(selectionOwner);
}
/*
Send a keystroke event to a VEE window.
*/
Status sendKeyEvent(aDisplay, keySym, sendControl)
Display *aDisplay;
KeySym keySym;
unsigned char sendControl;{
Window aWindow;
XEvent anEvent;
Status sendEventStatus;
aWindow=findVeeWin(aDisplay);
if(!aWindow){
return(0);
}
memset(&anEvent, '\0', sizeof(XEvent));
anEvent.type=KeyPress;
anEvent.xkey.type=KeyPress;
anEvent.xkey.send_event=True;
anEvent.xkey.display=aDisplay;
anEvent.xkey.window=aWindow;
anEvent.xkey.root=RootWindow(aDisplay, 0);
anEvent.xkey.subwindow=aWindow;
anEvent.xkey.time=CurrentTime;
anEvent.xkey.x=0;
anEvent.xkey.y=0;
anEvent.xkey.x_root=0;
anEvent.xkey.y_root=0;
if(sendControl){
anEvent.xkey.state=ControlMask;
}
else{
anEvent.xkey.state=0;
}
anEvent.xkey.keycode=XKeysymToKeycode(aDisplay, keySym);
anEvent.xkey.same_screen=True;
sendEventStatus=XSendEvent(aDisplay, aWindow, True, KeyPressMask, &anEvent);
return(sendEventStatus);
}
/*
Press VEE's 'Run' button, which also happens to be the 'Resume' button.
*/
Status sendGoKeyEvent(aDisplay)
Display *aDisplay;{
int tableIndex;
tableIndex=tableIndexForOperation(vRun);
if(tableIndex >= 0){
return(sendKeyEvent(aDisplay, VeeOperationStruct[tableIndex].keySym,
VeeOperationStruct[tableIndex].sendControl));
}
return 0;
}
/*
Press VEE's 'Pause' button.
*/
Status sendPauseKeyEvent(aDisplay)
Display *aDisplay;{
int tableIndex;
tableIndex=tableIndexForOperation(vPause);
if(tableIndex >= 0){
return(sendKeyEvent(aDisplay, VeeOperationStruct[tableIndex].keySym,
VeeOperationStruct[tableIndex].sendControl));
}
return 0;
}
/*
Press VEE's 'Step Into' button.
*/
Status sendStepKeyEvent(aDisplay)
Display *aDisplay;{
int tableIndex;
tableIndex=tableIndexForOperation(vStepInto);
if(tableIndex >= 0){
return(sendKeyEvent(aDisplay, VeeOperationStruct[tableIndex].keySym,
VeeOperationStruct[tableIndex].sendControl));
}
return 0;
}
/*
Press VEE's 'Run' button, which also happens to be the 'Resume' button.
*/
Status sendContKeyEvent(aDisplay)
Display *aDisplay;{
return(sendGoKeyEvent(aDisplay));
}
/*
Send an 'F1' keystroke to a VEE window. You can modify this function
to send any keystroke value.
*/
Status sendF1KeyEvent(aDisplay)
Display *aDisplay;{
return(sendKeyEvent(aDisplay, XK_F1, 0 /* control key? */));
}
/*
Remove VEE's window and its associated icon from the workspace.
*/
Status hideWindow(aDisplay)
Display *aDisplay;{
Window aWindow;
aWindow=findVeeWin(aDisplay);
if(!aWindow){
return(0);
}
XUnmapWindow(aDisplay, aWindow);
return(0);
}
/*
Remove VEE's main window from the workspace and display its
icon window.
*/
Status iconizeWindow(aDisplay)
Display *aDisplay;{
Window aWindow;
aWindow=findVeeWin(aDisplay);
if(!aWindow){
return(0);
}
return(XIconifyWindow(aDisplay, aWindow, DefaultScreen(aDisplay)));
}
/*
Show VEE's main window in its last known location.
*/
Status restoreWindow(aDisplay)
Display *aDisplay;{
Window aWindow;
aWindow=findVeeWin(aDisplay);
if(!aWindow){
return(0);
}
return(XMapRaised(aDisplay, aWindow, DefaultScreen(aDisplay)));
}
/*
This is a callback function that gets called when you press the
'Run' button in our example application.
*/
void run(widget, clientData, cbs)
Widget widget;
XtPointer clientData;
XmPushButtonCallbackStruct *cbs;{
sendGoKeyEvent(XtDisplay(widget));
return;
}
/*
This is a callback function that gets called when you press the
'Pause' button in our example application.
*/
void pauseVee(widget, clientData, cbs)
Widget widget;
XtPointer clientData;
XmPushButtonCallbackStruct *cbs;{
sendPauseKeyEvent(XtDisplay(widget));
return;
}
/*
This is a callback function that gets called when you press the
'Step' button in our example application.
*/
void step(widget, clientData, cbs)
Widget widget;
XtPointer clientData;
XmPushButtonCallbackStruct *cbs;{
sendStepKeyEvent(XtDisplay(widget));
return;
}
/*
This is a callback function that gets called when you press the
'Cont' button in our example application.
*/
void cont(widget, clientData, cbs)
Widget widget;
XtPointer clientData;
XmPushButtonCallbackStruct *cbs;{
sendContKeyEvent(XtDisplay(widget));
return;
}
/*
This is a callback function that gets called when you press the
'F1' button in our example application.
*/
void f1(widget, clientData, cbs)
Widget widget;
XtPointer clientData;
XmPushButtonCallbackStruct *cbs;{
sendF1KeyEvent(XtDisplay(widget));
return;
}
/*
This is a callback function that gets called when you press the
'Hide' button in our example application.
*/
void hide(widget, clientData, cbs)
Widget widget;
XtPointer clientData;
XmPushButtonCallbackStruct *cbs;{
hideWindow(XtDisplay(widget));
return;
}
/*
This is a callback function that gets called when you press the
'Iconize' button in our example application.
*/
void iconize(widget, clientData, cbs)
Widget widget;
XtPointer clientData;
XmPushButtonCallbackStruct *cbs;{
iconizeWindow(XtDisplay(widget));
return;
}
/*
This is a callback function that gets called when you press the
'Restore' button in our example application.
*/
void restore(widget, clientData, cbs)
Widget widget;
XtPointer clientData;
XmPushButtonCallbackStruct *cbs;{
restoreWindow(XtDisplay(widget));
return;
}
/*
$Log: ipcUtils.c,v $
* Revision 1.10 97/04/14 16:18:35 16:18:35 doomer (John Dumais)
* documentation.
*
*/