1/* 2 * Forward key and mouse button events from one window to another. 3 * 4 * This is useful to use a Desktop window as a Root window. 5 */ 6 7#include <stdio.h> 8#include <stdlib.h> 9#include <X11/Xlocale.h> 10#include <X11/Xlib.h> 11 12char *ProgramName; 13Display *dpy; 14int screen; 15 16static void 17usage(void) 18{ 19 static const char *msg[] = { 20 " -display displayname X server to contact", 21 " -id windowid use existing window", 22 " -root use root window", 23 " -name string window name", 24 "", 25 NULL 26 }; 27 const char **cpp; 28 29 fprintf(stderr, "usage: %s [-options ...]\n", ProgramName); 30 fprintf(stderr, "where options include:\n"); 31 32 for(cpp = msg; *cpp; cpp++) { 33 fprintf(stderr, "%s\n", *cpp); 34 } 35 36 exit(1); 37} 38 39int 40main(int argc, char **argv) 41{ 42 char *displayname = NULL; 43 int i; 44 Window w; 45 XWindowAttributes wattr; 46 long event_mask; 47 int done; 48 Window ws[2]; /* from-window, to-window */ 49 int wi = 0; 50 char *name; 51 52 ProgramName = argv[0]; 53 54 if(setlocale(LC_ALL, "") == NULL) { 55 fprintf(stderr, "%s: warning: could not set default locale\n", 56 ProgramName); 57 } 58 59 w = 0; 60 for(i = 1; i < argc; i++) { 61 char *arg = argv[i]; 62 63 if(arg[0] == '-') { 64 switch(arg[1]) { 65 case 'd': /* -display host:dpy */ 66 if(++i >= argc) { 67 usage(); 68 } 69 displayname = argv[i]; 70 continue; 71 case 'i': /* -id */ 72 if(++i >= argc || wi > 1) { 73 usage(); 74 } 75 sscanf(argv[i], "0x%lx", &w); 76 if(!w) { 77 sscanf(argv[i], "%lu", &w); 78 } 79 if(!w) { 80 usage(); 81 } 82 ws[wi++] = w; 83 continue; 84 case 'n': /* -name */ 85 if(++i >= argc || wi > 1) { 86 usage(); 87 } 88 name = argv[i]; /* not implemented yet */ 89 (void)name; // Silence unused warning 90 continue; 91 case 'r': 92 switch(arg[2]) { 93 case 'o': /* -root */ 94 if(wi > 1) { 95 usage(); 96 } 97 ws[wi++] = -1; 98 continue; 99 default: 100 usage(); 101 } 102 continue; 103 default: 104 usage(); 105 } /* end switch on - */ 106 } 107 else { 108 usage(); 109 } 110 } /* end for over argc */ 111 112 dpy = XOpenDisplay(displayname); 113 if(!dpy) { 114 fprintf(stderr, "%s: unable to open display '%s'\n", 115 ProgramName, XDisplayName(displayname)); 116 exit(1); 117 } 118 screen = DefaultScreen(dpy); 119 120 if(ws[0] == -1) { 121 ws[0] = RootWindow(dpy, screen); 122 } 123 if(ws[1] == -1) { 124 ws[1] = RootWindow(dpy, screen); 125 } 126 127 if(ws[0] == ws[1]) { 128 fprintf(stderr, "error: from-window and to-window must differ.\n"); 129 exit(1); 130 } 131 132 event_mask = KeyPressMask | KeyReleaseMask | 133 ButtonPressMask | ButtonReleaseMask; 134 135 if(ws[0]) { 136 XGetWindowAttributes(dpy, ws[0], &wattr); 137 /* We can't select on button presses if someone else already does... */ 138 if(wattr.all_event_masks & ButtonPressMask) { 139 event_mask &= ~ButtonPressMask; 140 fprintf(stderr, "warning: can't forward button presses.\n"); 141 } 142 event_mask &= ~SubstructureRedirectMask; 143 printf("XSelectInput 0x%x %lx\n", (unsigned int)ws[0], event_mask); 144 XSelectInput(dpy, ws[0], event_mask); 145 } 146 147 for(done = 0; !done;) { 148 XEvent event; 149 150 XNextEvent(dpy, &event); 151 152 switch(event.type) { 153 case KeyPress: 154 case KeyRelease: 155 printf("KeyPress/KeyRelease\n"); 156 event.xkey.window = ws[1]; 157 XSendEvent(dpy, ws[1], False, KeyPressMask, &event); 158 break; 159 case ButtonPress: 160 case ButtonRelease: 161 printf("ButtonPress/ButtonRelease\n"); 162 event.xbutton.window = ws[1]; 163 XSendEvent(dpy, ws[1], False, KeyPressMask, &event); 164 break; 165 default: 166 printf("some other event\n"); 167 } 168 } 169 170 XCloseDisplay(dpy); 171 return 0; 172} 173