10bbfda8aSnia/* 20bbfda8aSnia * Forward key and mouse button events from one window to another. 30bbfda8aSnia * 40bbfda8aSnia * This is useful to use a Desktop window as a Root window. 50bbfda8aSnia */ 60bbfda8aSnia 70bbfda8aSnia#include <stdio.h> 80bbfda8aSnia#include <stdlib.h> 90bbfda8aSnia#include <X11/Xlocale.h> 100bbfda8aSnia#include <X11/Xlib.h> 110bbfda8aSnia 120bbfda8aSniachar *ProgramName; 130bbfda8aSniaDisplay *dpy; 140bbfda8aSniaint screen; 150bbfda8aSnia 160bbfda8aSniastatic void 170bbfda8aSniausage(void) 180bbfda8aSnia{ 190bbfda8aSnia static const char *msg[] = { 200bbfda8aSnia " -display displayname X server to contact", 210bbfda8aSnia " -id windowid use existing window", 220bbfda8aSnia " -root use root window", 230bbfda8aSnia " -name string window name", 240bbfda8aSnia "", 250bbfda8aSnia NULL 260bbfda8aSnia }; 270bbfda8aSnia const char **cpp; 280bbfda8aSnia 290bbfda8aSnia fprintf(stderr, "usage: %s [-options ...]\n", ProgramName); 300bbfda8aSnia fprintf(stderr, "where options include:\n"); 310bbfda8aSnia 320bbfda8aSnia for(cpp = msg; *cpp; cpp++) { 330bbfda8aSnia fprintf(stderr, "%s\n", *cpp); 340bbfda8aSnia } 350bbfda8aSnia 360bbfda8aSnia exit(1); 370bbfda8aSnia} 380bbfda8aSnia 390bbfda8aSniaint 400bbfda8aSniamain(int argc, char **argv) 410bbfda8aSnia{ 420bbfda8aSnia char *displayname = NULL; 430bbfda8aSnia int i; 440bbfda8aSnia Window w; 450bbfda8aSnia XWindowAttributes wattr; 460bbfda8aSnia long event_mask; 470bbfda8aSnia int done; 480bbfda8aSnia Window ws[2]; /* from-window, to-window */ 490bbfda8aSnia int wi = 0; 500bbfda8aSnia char *name; 510bbfda8aSnia 520bbfda8aSnia ProgramName = argv[0]; 530bbfda8aSnia 540bbfda8aSnia if(setlocale(LC_ALL, "") == NULL) { 550bbfda8aSnia fprintf(stderr, "%s: warning: could not set default locale\n", 560bbfda8aSnia ProgramName); 570bbfda8aSnia } 580bbfda8aSnia 590bbfda8aSnia w = 0; 600bbfda8aSnia for(i = 1; i < argc; i++) { 610bbfda8aSnia char *arg = argv[i]; 620bbfda8aSnia 630bbfda8aSnia if(arg[0] == '-') { 640bbfda8aSnia switch(arg[1]) { 650bbfda8aSnia case 'd': /* -display host:dpy */ 660bbfda8aSnia if(++i >= argc) { 670bbfda8aSnia usage(); 680bbfda8aSnia } 690bbfda8aSnia displayname = argv[i]; 700bbfda8aSnia continue; 710bbfda8aSnia case 'i': /* -id */ 720bbfda8aSnia if(++i >= argc || wi > 1) { 730bbfda8aSnia usage(); 740bbfda8aSnia } 750bbfda8aSnia sscanf(argv[i], "0x%lx", &w); 760bbfda8aSnia if(!w) { 770bbfda8aSnia sscanf(argv[i], "%lu", &w); 780bbfda8aSnia } 790bbfda8aSnia if(!w) { 800bbfda8aSnia usage(); 810bbfda8aSnia } 820bbfda8aSnia ws[wi++] = w; 830bbfda8aSnia continue; 840bbfda8aSnia case 'n': /* -name */ 850bbfda8aSnia if(++i >= argc || wi > 1) { 860bbfda8aSnia usage(); 870bbfda8aSnia } 880bbfda8aSnia name = argv[i]; /* not implemented yet */ 890bbfda8aSnia (void)name; // Silence unused warning 900bbfda8aSnia continue; 910bbfda8aSnia case 'r': 920bbfda8aSnia switch(arg[2]) { 930bbfda8aSnia case 'o': /* -root */ 940bbfda8aSnia if(wi > 1) { 950bbfda8aSnia usage(); 960bbfda8aSnia } 970bbfda8aSnia ws[wi++] = -1; 980bbfda8aSnia continue; 990bbfda8aSnia default: 1000bbfda8aSnia usage(); 1010bbfda8aSnia } 1020bbfda8aSnia continue; 1030bbfda8aSnia default: 1040bbfda8aSnia usage(); 1050bbfda8aSnia } /* end switch on - */ 1060bbfda8aSnia } 1070bbfda8aSnia else { 1080bbfda8aSnia usage(); 1090bbfda8aSnia } 1100bbfda8aSnia } /* end for over argc */ 1110bbfda8aSnia 1120bbfda8aSnia dpy = XOpenDisplay(displayname); 1130bbfda8aSnia if(!dpy) { 1140bbfda8aSnia fprintf(stderr, "%s: unable to open display '%s'\n", 1150bbfda8aSnia ProgramName, XDisplayName(displayname)); 1160bbfda8aSnia exit(1); 1170bbfda8aSnia } 1180bbfda8aSnia screen = DefaultScreen(dpy); 1190bbfda8aSnia 1200bbfda8aSnia if(ws[0] == -1) { 1210bbfda8aSnia ws[0] = RootWindow(dpy, screen); 1220bbfda8aSnia } 1230bbfda8aSnia if(ws[1] == -1) { 1240bbfda8aSnia ws[1] = RootWindow(dpy, screen); 1250bbfda8aSnia } 1260bbfda8aSnia 1270bbfda8aSnia if(ws[0] == ws[1]) { 1280bbfda8aSnia fprintf(stderr, "error: from-window and to-window must differ.\n"); 1290bbfda8aSnia exit(1); 1300bbfda8aSnia } 1310bbfda8aSnia 1320bbfda8aSnia event_mask = KeyPressMask | KeyReleaseMask | 1330bbfda8aSnia ButtonPressMask | ButtonReleaseMask; 1340bbfda8aSnia 1350bbfda8aSnia if(ws[0]) { 1360bbfda8aSnia XGetWindowAttributes(dpy, ws[0], &wattr); 1370bbfda8aSnia /* We can't select on button presses if someone else already does... */ 1380bbfda8aSnia if(wattr.all_event_masks & ButtonPressMask) { 1390bbfda8aSnia event_mask &= ~ButtonPressMask; 1400bbfda8aSnia fprintf(stderr, "warning: can't forward button presses.\n"); 1410bbfda8aSnia } 1420bbfda8aSnia event_mask &= ~SubstructureRedirectMask; 1430bbfda8aSnia printf("XSelectInput 0x%x %lx\n", (unsigned int)ws[0], event_mask); 1440bbfda8aSnia XSelectInput(dpy, ws[0], event_mask); 1450bbfda8aSnia } 1460bbfda8aSnia 1470bbfda8aSnia for(done = 0; !done;) { 1480bbfda8aSnia XEvent event; 1490bbfda8aSnia 1500bbfda8aSnia XNextEvent(dpy, &event); 1510bbfda8aSnia 1520bbfda8aSnia switch(event.type) { 1530bbfda8aSnia case KeyPress: 1540bbfda8aSnia case KeyRelease: 1550bbfda8aSnia printf("KeyPress/KeyRelease\n"); 1560bbfda8aSnia event.xkey.window = ws[1]; 1570bbfda8aSnia XSendEvent(dpy, ws[1], False, KeyPressMask, &event); 1580bbfda8aSnia break; 1590bbfda8aSnia case ButtonPress: 1600bbfda8aSnia case ButtonRelease: 1610bbfda8aSnia printf("ButtonPress/ButtonRelease\n"); 1620bbfda8aSnia event.xbutton.window = ws[1]; 1630bbfda8aSnia XSendEvent(dpy, ws[1], False, KeyPressMask, &event); 1640bbfda8aSnia break; 1650bbfda8aSnia default: 1660bbfda8aSnia printf("some other event\n"); 1670bbfda8aSnia } 1680bbfda8aSnia } 1690bbfda8aSnia 1700bbfda8aSnia XCloseDisplay(dpy); 1710bbfda8aSnia return 0; 1720bbfda8aSnia} 173