frivold@san18.erg.sri.com (Thane J. Frivold) (11/06/90)
I am currently working on an application (a modified `twm' to be exact) that allows for a certain amount of `remote control' of X11 applications. Once a common application has been determined, a controlling user's host replicates the pertinent X11 events to all the listening hosts. All event delivery to the selected application is done via calls to XSendEvent(). The event capture is done by creating an InputOnly `capture window' whose parent is the selected application (target) window and whose event mask has all bits set, except `PointerMotionHintMask'. The intent is to intercept all events normally destined for the selected application in order to decide, as a function of control state, whether or not the event should be propogated to the other hosts (as well as delivered locally). Currently, the application *does* work for client applications that have a *single* X11 window, but I have been unable to deliver the events to *multiple* window applications (e.g. xcalc or xwebster). Could someone please help me see either 1) the futility of my aspirations or preferably 2) the flaw in my approach and the required solution. Here is the code I am using to select the application window: /* NOTE: Select_Window() is taken, as is, from the file `dsimple.c' * found with the standard application `xwd'. */ Window SelectWindowFromUser(display) Display *display; { Window target = Select_Window(display); if( target != None ) { Window root; int result; int idummy; unsigned int udummy; result = XGetGeometry(display, target, &root, &idummy, &idummy, &udummy, &udummy, &udummy, &udummy); /* Look for the true `client' window */ if( result && target != root) target = XmuClientWindow(display, target); /* Make sure we didn't get the `root' window lest we render * the window manager itself useless by intercepting all events. */ if( target == root ) target = None; } return target; } The code fragment that handles the control case is: . . . /* Was this event `captured' from the target application? */ if( Event.xany.window == captureWindow ) { Bool ProcessRemoteXEvent(); /* Should this event be propogated to the listeners? */ if (ProcessRemoteXEvent(&Event) ) { /* If so, deliver the event locally as well */ XSendEvent(dpy, targetWindow, False, 0L, &Event); } } /* Otherwise handle the event as usual */ else DispatchEvent(); . . . And the code to handle the listen case is: . . . /* Insert the display for the local host */ Event.xany.display = dpy; XSendEvent(dpy, targetWindow, False, 0L, &Event); . . . Thank you in advance for any light you can shed on my problem. -Thane J. Frivold Software Engineer Geoscience & Engineering Center SRI International 333 Ravenswood Avenue Menlo Park, CA 94025 Mail Stop: EJ329 Office: (415) 859-2786 FAX: (415) 325-4812 EMAIL: frivold@erg.sri.com -or- frivold@unix.sri.com -Thane J. Frivold frivold@erg.sri.com
mouse@LIGHTNING.MCRCIM.MCGILL.EDU (11/08/90)
> I am currently working on an application (a modified `twm' to be > exact) that allows for a certain amount of `remote control' of X11 > applications. Once a common application has been determined, a > controlling user's host replicates the pertinent X11 events to all > the listening hosts. All event delivery to the selected application > is done via calls to XSendEvent(). Note that not all applications listen to events sent with XSendEvent. (Not that I'm saying this is your problem; see below.) > The event capture is done by creating an InputOnly `capture window' > whose parent is the selected application (target) window and whose > event mask has all bits set, except `PointerMotionHintMask'. > Currently, the application *does* work for client applications that > have a *single* X11 window, but I have been unable to deliver the > events to *multiple* window applications (e.g. xcalc or xwebster). Well, I think I can perhaps explain the flaw. Suppose we have an application whose window structure is toplevel menu button 1 button 2 button 3 button 4 main graphics window Now, you add your blanket InputOnly window: toplevel blanket menu button 1 button 2 button 3 button 4 main graphics window This is perhaps not a great idea. Why? - This breaks if the application has set different pointer cursors on its various windows, because the pointer cursor will always be that of your blanket window. - The application may raise children of its main window with XRaiseWindow or equivalent; this will unexpectedly put them in front of your blanket. - If the application grabs the pointer, you lose your control. Similar problems exist for keyboard events, but let's not get into that. But let's ignore possible problems like those for the moment. Now, suppose the user puts the cursor over "button 1" and clicks a button. If it weren't for your blanket, the application would see a ButtonPress event generated on the "button 1" window. (Depending on the event masks, it might be received through the "menu" or "toplevel" windows, but the "event window" will be the "button 1" window.) But your blanket window is present, so the event window of the generated event is "blanket". Your program receives the event and sends it to "toplevel" with XSendEvent. If the application ignores ButtonPress events on "toplevel", expecting to receive them through "button 1" or "menu" instead, it won't see it at all. If it does see it, it will have no way of telling that the click was "over" button 1; instead, the event window will be a window it's never heard of and has no idea how to deal with. It will probably drop the event on the floor. Either way, it doesn't work right. In order to do this right, you will need to duplicate the whole window tree in a shadow tree of InputOnly windows, select for ConfigureNotify and StructureNotify (or perhaps SubstructureNotify) on the application's windows, and keep the window trees in sync (and there will always be race conditions). der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
exl@proteon.COM (Eugene Lumelsky) (11/09/90)
This message is empty.
vp01@bunny.gte.com (Vincent Phuah) (05/08/91)
Keywords:XSendEvent, PointerWindow Hi there, Wonder if someone could help me. I'm trying to simulate button press/release events using XSendEvent with the PointerWindow option, but having a lot of trouble getting it to work. Would appreciate if you could take a look at my code and tell me what I'm doing wrong. Instead of using the PointerWindow option, I tried using the window id of a command button in the event structure and the XSendEvent routine, but that didn't work either. Thanks for your help in advance. ----- /* * * Code to send an button press/release event to * a window(likely a command button window) specified by the pointer. */ #include "xbook.h" int SendButtonPress(); SendButtonPress( display, window, state) Display *display; Window window; int state; /* unused */ { XButtonEvent event; int status; event.type = ButtonPress; event.display = display; event.root = RootWindow( display, DefaultScreen( display )); event.same_screen = True; event.x = 0; event.y = 0; event.x_root = 0; event.y_root = 0; event.subwindow = (Window)None; event.time = CurrentTime; event.state = 0x00; status = XSendEvent( display, PointerWindow, False , ButtonPressMask, &event ); sleep(1); if ( status != 0 ) { event.type = ButtonRelease; event.state = Button1Mask; event.time = CurrentTime; status = XSendEvent( display, PointerWindow, False, ButtonReleaseMask, &event ); } XFlush(display); return( status ); } main(argc,argv) int argc; char **argv; { Display *display; if (argc != 2) { printf("Must specify display name.\n"); exit(0); } if ((display = XOpenDisplay(argv[1])) == NULL) { printf("Cannot open display\n"); exit(-1); } if (SendButtonPress(display, PointerWindow, 0x0100) > 0) printf("Send Button Event ok\n"); else printf("SentEvent Not OK\n"); exit(0); } -- +-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * Vincent Phuah * * GTE Laboratories Email: vphuah@gte.com * * 40 Sylvan Road Tel: (617) 466-4130 * * Waltham, MA 02254 FAX: (617) 890-9320 * +-+-+--+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+