|
/* Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
*
* All Rights Reserved
*
*/
/*
* program : multi.c
* Author : Rob Watson NRMACP::WATSON @BIO
* DTN 841-3115
* Date : February 1990
Program written to test capability of handling multiple displays with a
single mouse (and keyboard) with standard X server, requiring no special
hardware.
Not yet fully working, just an experimental hack.
Usage: Run the program on the "master" workstation (the one whose
mouse will be used), enter the name of the "slave" display.
A small window will appear in top right of each display.
Click MB3 on this window to toggle the "active" display (i.e. the
one the mouse is driving). When the slave display is active, the
cursor will change and the pointer will track the pointer on the
master. MB1 and MB2 clicks SHOULD be passed through to the
applications.
Problems:
"Pure" X programs work OK when no window manager is running.
When the DECwindows window manager is running, events do not get sent
to the application. Same for Motif WM. The HPWM sometimes works.
Events do not get passed to DECwindows toolkit or Motif applications.
I have not yet tried to pass keyboard events, but this should be trivial
once the above issues are sorted.
*/
#include "decw$include:Xlib.h"
#include stdio
Display *CurrentDisp; /* display currently active */
Display *disp1, *disp2; /* The two displays */
Screen *scrp1, *scrp2; /* The only screen on them */
int scn1, scn2; /* Default screen number */
Window CurrentWin;
Window win1, win2; /* Top level windows */
Window root1, root2; /* root windows */
unsigned xdim = 100, ydim = 100; /* Of window */
unsigned white1, white2; /* Pixel value */
unsigned black1, black2; /* Colour */
XSetWindowAttributes winat1,winat2; /* Window attributes */
unsigned x,y; /* pointer coords */
unsigned status;
Window pointer_root, pointer_window, child;
int root_x, root_y, pointer_x, pointer_y;
unsigned int pointer_mask;
main(argc,argv)
char *argv[];
{
XEvent evt;
int button = 0;
unsigned lx, ly; /* Last reported pointer */
char ch; /* Character typed */
Cursor cursor1, cursor2, xcursor1, xcursor2;
/* Initialise */
startup(argc, argv);
/* do this to display the windows */
XFlush (disp1);
XFlush (disp2);
xcursor1 = XCreateFontCursor (disp1, 0);
xcursor2 = XCreateFontCursor (disp2, 0);
cursor1 = XCreateFontCursor (disp1, 38);
cursor2 = XCreateFontCursor (disp2, 38);
printf("DISPLAY 1 CURRENT\n");
CurrentDisp = disp1;
CurrentWin = win1;
XWarpPointer (disp1, None, win1, 0, 0, 100, 100, 0, 0);
XWarpPointer (disp2, None, win2, 0, 0, 100, 100, 0, 0);
XDefineCursor (disp1, win1, xcursor1);
XDefineCursor (disp2, win2, cursor2);
for (;;) {
/* only look at events in disp1 */
XNextEvent(disp1, &evt);
if ( ((evt.type == ButtonPress) || (evt.type == ButtonRelease))
&& (evt.xbutton.window == win1) )
{
button = evt.xbutton.button;
printf("ButtonPress/release in window 1 Button = %d \n", button);
/* use button 3 to toggle display */
if (button == 3)
{
if ( (CurrentDisp == disp1)
&& (evt.type == ButtonPress) )
/* only for button press, or just switches back */
{
printf ("Current Display = 2\n");
CurrentDisp = disp2;
CurrentWin = win2;
/* change cursors */
XDefineCursor (disp1, win1, cursor1);
XDefineCursor (disp2, win2, xcursor2);
XWarpPointer (disp1, None, win1, 0, 0, 100, 100, 0, 0);
XWarpPointer (disp2, None, win2, 0, 0, 100, 100, 0, 0);
printf("Grabbing pointer now...\n");
XGrabPointer
(disp1, win1,
True,
winat1.event_mask,
GrabModeAsync,
GrabModeAsync,
None,
cursor1,
CurrentTime);
}
/* if button 3 and disp2 current */
else if ( (CurrentDisp == disp2)
&& (evt.type == ButtonPress) )
{
printf ("Current Display = 1\n");
CurrentDisp = disp1;
CurrentWin = win1;
/* change cursors */
XDefineCursor (disp1, win1, xcursor1);
XDefineCursor (disp2, win2, cursor2);
XWarpPointer (disp1, None, win1, 0, 0, 100, 100, 0, 0);
XWarpPointer (disp2, None, win2, 0, 0, 100, 100, 0, 0);
printf("UNGrabbing pointer now...\n");
XUngrabPointer
(disp1,
CurrentTime);
}
}
else if (CurrentDisp == disp2)
/* CHECK FOR BUTTON 1 and 2 */
{
printf ("Sending Button event to disp 2\n");
status = XQueryPointer
(disp2,
root2,
&pointer_root,
&pointer_window,
&root_x,
&root_y,
&pointer_x,
&pointer_y,
&pointer_mask );
/* translate to pointer_window coordinates */
XTranslateCoordinates
(disp2,
root2,
pointer_window,
root_x, root_y,
&pointer_x, &pointer_y,
&child );
evt.xbutton.display = disp2;
evt.xbutton.window = pointer_window;
evt.xbutton.root = root2;
evt.xbutton.subwindow = pointer_window; /*??*/
evt.xbutton.x = pointer_x;
evt.xbutton.y = pointer_y;
evt.xbutton.x_root = root_x;
evt.xbutton.y_root = root_y;
status =
XSendEvent (CurrentDisp,
/* PointerWindow, */
pointer_window,
1, /* propagate ?? */
~NoEventMask,
&evt);
/* printf ("status=%d\n",status); */
}
}
else if ( (evt.type == KeyPress)
&& (evt.xkey.window == win1) )
{
XLookupString(&evt, &ch, 1, NULL, NULL);
if (ch == '\3') return; /* Control-C */
if (ch == '\031') return; /* Ctrl-Y */
}
/* track cursor motion on display 2 */
else if ( (evt.type == MotionNotify)
&& (CurrentDisp == disp2) )
{
x = evt.xmotion.x_root;
y = evt.xmotion.y_root;
/* printf("Motion Notify %d %d\n",x,y); */
/* warp the mouse */
XWarpPointer (disp2, None, root2, 0, 0, 0, 0, x, y);
/* send the event to the current display */
status =
XSendEvent (CurrentDisp,
PointerWindow,
1, /* propagate ?? */
~NoEventMask,
&evt);
/* printf ("status=%d\n",status); */
}
else
{
/* printf ("sending some event\n"); */
/* send the event to the current display */
XSendEvent (CurrentDisp,
PointerWindow,
1, /* propagate ?? */
~NoEventMask,
&evt);
}
}
}
/* Startup routine, processes arguments and initialises window */
startup(argc,argv)
char *argv[];
{
char *dispnm1 = 0; /* Name of display 1 */
char dispnm2[20]; /* Name of display 2 */
/* Open the displays.*/
disp1 = XOpenDisplay(dispnm1);
scrp1 = DefaultScreenOfDisplay(disp1);
scn1 = DefaultScreen(disp1);
printf ("Display NODE::SERVER.SCREEN?");
scanf ("%s", &dispnm2);
printf ("\nSlave display on %s\n", dispnm2);
disp2 = XOpenDisplay(dispnm2);
scrp2 = DefaultScreenOfDisplay(disp2);
scn2 = DefaultScreen(disp2);
/* Synchronize with server for debugging */
XSynchronize(disp1, 1);
XSynchronize(disp2, 1);
root1 = DefaultRootWindow(disp1);
root2 = DefaultRootWindow(disp2);
/* Create the top-level window */
black1 = BlackPixel(disp1, scn1);
white1 = WhitePixel(disp1, scn1);
winat1.background_pixel = black1;
winat1.border_pixel = white1;
winat1.event_mask =
Button1MotionMask | Button2MotionMask | Button3MotionMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | KeyPressMask ;
win1 = XCreateWindow(disp1, /* Display */
root1, /* parent */
0, 0, /* x, y */
xdim, ydim, 2, /* width, height, border */
0, InputOutput, /* depth, class */
DefaultVisual(disp1, scn1),
CWBackPixel|CWBorderPixel|CWEventMask,
&winat1); /* Mask and attributes */
XStoreName (disp1, win1, "Window 1");
black2 = BlackPixel(disp2, scn2);
white2 = WhitePixel(disp2, scn2);
winat2.background_pixel = black2;
winat2.border_pixel = white2;
winat2.event_mask =
Button1MotionMask | Button2MotionMask | Button3MotionMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | KeyPressMask ;
win2 = XCreateWindow(disp2, /* Display */
root2, /* parent */
0, 0, /* x, y */
xdim, ydim, 2, /* width, height, border */
0, InputOutput, /* depth, class */
DefaultVisual(disp2, scn2),
CWBackPixel|CWBorderPixel|CWEventMask,
&winat2); /* Mask and attributes */
XStoreName (disp2, win2, "Window 2");
/* Map the window to start the event cycle */
XMapRaised(disp1, win1);
XMapRaised(disp2, win2);
}
|