/* XMonobut - Modify mouse button behaviour with keyboard.

   o Usage

   Hold selected key ( KEYSYM_TO_GRAB ) down and click mouse button for
   right click.
   Quickly press selected key once, then again holding down for middle click.

   o Compiling

   gcc -Wall XMonobut.c -o xmonobut -L/usr/X11R6/lib -lX11


   Copyright 2002 Matthew Allum <mallum@handhelds.org>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

	modified: Sat Apr  6 18:04:17 EST 2002 by dave.capella@cornell.edu
	for use on the ipaq. changed key code. replaced key codes w/macro.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xmd.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>

/* get from xev or keysym.h  */
#define KEYSYM_TO_GRAB 130   /* ipaq: calendar */
#define DCLICK_TIME    200

int main(int argc, char **argv)
{
   Display *dpy;
   char *dpy_name = NULL;
   Window root;
   XEvent ev;
   Cursor right_curs, middle_curs, orig_curs;
   Time lasttime = 0;
   unsigned char map[5];

   if ((dpy = XOpenDisplay(dpy_name)) == NULL) {
      fprintf(stderr, "can't open display! check your DISPLAY variable.\n");
      exit(1);
   }
   root = RootWindow(dpy, DefaultScreen(dpy));

   /* see http://tronche.com/gui/x/xlib/appendix/b/ for more cursors */
   right_curs  = XCreateFontCursor(dpy, XC_mouse);
   middle_curs = XCreateFontCursor(dpy, XC_gumby);    /* :) */
   orig_curs   = XCreateFontCursor(dpy, XC_left_ptr);

   XGrabKey(dpy, KEYSYM_TO_GRAB, 0 /*XKeysymToKeycode(dpy, KEYSYM_TO_GRAB), AnyModifier*/ ,
            root, True, GrabModeAsync, GrabModeAsync);

   XSelectInput(dpy, root, KeyPressMask | KeyReleaseMask );

   for (;;) {
      XNextEvent(dpy, &ev);
      switch (ev.type) {
         case KeyPress:
            if (ev.xkey.keycode != KEYSYM_TO_GRAB) break;
            XAutoRepeatOff(dpy);
            XGetPointerMapping(dpy, map, 5);
            if (lasttime && (ev.xkey.time-lasttime < DCLICK_TIME) )
            {  /* double press - remap for middle button  */
               map[0] = (unsigned char) 2;
               map[1] = (unsigned char) 3;
               map[2] = (unsigned char) 1;
               XDefineCursor(dpy, root, middle_curs);
            } else {
               map[0] = (unsigned char) 3;
               map[1] = (unsigned char) 2;
               map[2] = (unsigned char) 1;
               XDefineCursor(dpy, root, right_curs);
            }
            lasttime = ev.xkey.time;
            XSetPointerMapping(dpy, map, 5);
            break;

         case KeyRelease:
            if (ev.xkey.keycode != KEYSYM_TO_GRAB) break;
            /* Put everything back to normal */
            map[0] = (unsigned char) 1;
            map[1] = (unsigned char) 2;
            map[2] = (unsigned char) 3;
            XSetPointerMapping(dpy, map, 5);
            XDefineCursor(dpy, root, orig_curs);
            XAutoRepeatOn(dpy);
            break;

        }
    }

   XUngrabKey(dpy, KEYSYM_TO_GRAB /* XKeysymToKeycode(dpy, KEYSYM_TO_GRAB) */, AnyModifier, root);
   XCloseDisplay(dpy);
}


