Skip to content

Instantly share code, notes, and snippets.

@javiercantero
Created July 10, 2014 17:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save javiercantero/ae87e91896870062981d to your computer and use it in GitHub Desktop.
Save javiercantero/ae87e91896870062981d to your computer and use it in GitHub Desktop.
Little app to lock the keyboard input of a libOIS linked application (this include games like FreeOrion but also the OISConsole demo packed with the library). You can restore the keyboard input simply by terminate the app killing it or sending a ESC key. This program simulates the functionality of xscreensaver to eaversdrop theKeyPress events of…
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
/* taken from xscreensaver's timers.c */
/* ---------------------------------------------------------------------------
* this function tries to eavesdrop all the keyboard activity of any window of
* the X server (to determine if a user is active or not and launch the
* screensaver if needed). The comment inside is from xscreensaver author. See
* xscreensaver sources for more info. -- jcantero
-----------------------------------------------------------------------------*/
void notice_events(Display *display, Window window, Window this_app, Bool top_p)
{
XWindowAttributes attrs;
unsigned long events;
Window root, parent, *kids;
unsigned int nkids;
if ( window == this_app )
return; /* don't touch this app */
if ( !XQueryTree(display, window, &root, &parent, &kids, &nkids) )
return;
/*if (window == root)
top_p = False;*/
XGetWindowAttributes(display, window, &attrs);
events = ((attrs.all_event_masks | attrs.do_not_propagate_mask)
& KeyPressMask);
/* Select for SubstructureNotify on all windows.
Select for KeyPress on all windows that already have it selected.
Note that we can't select for ButtonPress, because of X braindamage:
only one client at a time may select for ButtonPress on a given
window, though any number can select for KeyPress. Someone explain
*that* to me.
So, if the user spends a while clicking the mouse without ever moving
the mouse or touching the keyboard, we won't know that they've been
active, and the screensaver will come on. That sucks, but I don't
know how to get around it.
Since X presents mouse wheels as clicks, this applies to those, too:
scrolling through a document using only the mouse wheel doesn't
count as activity... Fortunately, /proc/interrupts helps, on
systems that have it. Oh, if it's a PS/2 mouse, not serial or USB.
This sucks!
*/
XSelectInput( display, window, SubstructureNotifyMask | events );
if ( top_p && (events & KeyPressMask) )
{
/* Only mention one window per tree (hack hack). */
printf( "selected KeyPress on 0x%lX\n", (unsigned long) window);
/*top_p = False;*/
}
if ( kids )
{
while ( nkids )
notice_events(display, kids[--nkids], this_app, top_p);
XFree((char *) kids);
}
}
/* ---------------------------------------------------------------------------
* this is a pretty stardard example of the most simple X application with
* keyboard events, plus a call to the previous function notice_events().
* Note that notice_events() is launched inmediately here, while in
* xscreensaver there is a delay due to the timer (see notice_events_timer()
* and start_notice_events_timer() in timers.c) -- jcantero
-----------------------------------------------------------------------------*/
int main()
{
Display *display;
Window window;
Window root;
XEvent event;
int s;
display = XOpenDisplay(NULL);
if (display == NULL)
{
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(display);
root = DefaultRootWindow(display);
window = XCreateSimpleWindow(display, RootWindow(display, s), 10, 10, 200, 100, 1,
BlackPixel(display, s), WhitePixel(display, s));
XSelectInput(display, window, KeyPressMask | KeyReleaseMask );
XMapWindow(display, window);
notice_events(display, root, window, True);
/* event loop */
while (1)
{
if ( XPending(display) > 0 )
{
XNextEvent(display, &event);
/* keyboard events */
if (event.type == KeyPress)
{
printf( "KeyPress: %x\n", event.xkey.keycode );
/* exit on ESC key press */
if ( event.xkey.keycode == 0x09 )
break;
}
else if (event.type == KeyRelease)
{
printf( "KeyRelease: %x\n", event.xkey.keycode );
}
}
}
XDestroyWindow( display, window );
XCloseDisplay( display );
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment