tdevdraw: control+click = button 2, alt/shift+click = button 3 - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 36bb28dc638bb3091e05996156b5fbecbc67dcd5
 (DIR) parent 17934beda0895d1b584e09f0253b8205b7fd6de2
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Thu,  7 Mar 2013 22:40:47 -0500
       
       devdraw: control+click = button 2, alt/shift+click = button 3
       
       For single-button mouse users.
       
       R=rsc
       https://codereview.appspot.com/7620043
       
       Diffstat:
         M src/cmd/devdraw/x11-inc.h           |       1 +
         M src/cmd/devdraw/x11-itrans.c        |      31 +++++++++++++++++++++++--------
         M src/cmd/devdraw/x11-srv.c           |     105 +++++++++++++++++++++++++------
       
       3 files changed, 111 insertions(+), 26 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/devdraw/x11-inc.h b/src/cmd/devdraw/x11-inc.h
       t@@ -32,3 +32,4 @@
        #undef Visual
        #undef Window
        
       +void        sendalt(void);
 (DIR) diff --git a/src/cmd/devdraw/x11-itrans.c b/src/cmd/devdraw/x11-itrans.c
       t@@ -114,8 +114,7 @@ __xtoplan9kbd(XEvent *e)
                        case XK_Alt_R:
                        case XK_Meta_R:        /* Shift Alt on PCs */
                        case XK_Multi_key:
       -                        k = Kalt;
       -                        break;
       +                        return -1;
                        default:                /* not ISO-1 or tty control */
                                if(k>0xff) {
                                        k = _p9keysym2ucs(k);
       t@@ -128,7 +127,7 @@ __xtoplan9kbd(XEvent *e)
                if(k == XK_hyphen)
                        k = XK_minus;
                /* Do control mapping ourselves if translator doesn't */
       -        if(e->xkey.state&ControlMask && k != Kalt)
       +        if(e->xkey.state&ControlMask)
                        k &= 0x9f;
                if(k == NoSymbol) {
                        return -1;
       t@@ -145,18 +144,33 @@ abortcompose(void)
                alting = 0;
        }
        
       +static Rune* sendrune(Rune);
       +
        extern int _latin1(Rune*, int);
        static Rune*
        xtoplan9latin1(XEvent *e)
        {
       -        static Rune k[10];
       -        static int nk;
       -        int n;
       -        int r;
       +        Rune r;
        
                r = __xtoplan9kbd(e);
                if(r < 0)
                        return nil;
       +        return sendrune(r);
       +}
       +
       +void
       +sendalt(void)
       +{
       +        sendrune(Kalt);
       +}
       +
       +static Rune*
       +sendrune(Rune r)
       +{
       +        static Rune k[10];
       +        static int nk;
       +        int n;
       +
                if(alting){
                        /*
                         * Kludge for Mac's X11 3-button emulation.
       t@@ -228,6 +242,7 @@ _xtoplan9mouse(XEvent *e, Mouse *m)
                switch(e->type){
                case ButtonPress:
                        be = (XButtonEvent*)e;
       +
                        /* 
                         * Fake message, just sent to make us announce snarf.
                         * Apparently state and button are 16 and 8 bits on
       t@@ -292,7 +307,7 @@ _xtoplan9mouse(XEvent *e, Mouse *m)
                        m->xy.x = me->x;
                        m->xy.y = me->y;
                        m->msec = me->time;
       -                break;
       +                return 0; // do not set buttons
        
                default:
                        return -1;
 (DIR) diff --git a/src/cmd/devdraw/x11-srv.c b/src/cmd/devdraw/x11-srv.c
       t@@ -36,7 +36,7 @@
                Button2MotionMask|\
                Button3MotionMask)
        
       -#define Mask MouseMask|ExposureMask|StructureNotifyMask|KeyPressMask|EnterWindowMask|LeaveWindowMask|FocusChangeMask
       +#define Mask MouseMask|ExposureMask|StructureNotifyMask|KeyPressMask|KeyReleaseMask|EnterWindowMask|LeaveWindowMask|FocusChangeMask
        
        typedef struct Kbdbuf Kbdbuf;
        typedef struct Mousebuf Mousebuf;
       t@@ -463,6 +463,28 @@ matchmouse(void)
                }
        }
        
       +static int kbuttons;
       +static int altdown;
       +static int kstate;
       +
       +static void
       +sendmouse(Mouse m)
       +{
       +        m.buttons |= kbuttons;
       +        mouse.m[mouse.wi] = m;
       +        mouse.wi++;
       +        if(mouse.wi == nelem(mouse.m))
       +                mouse.wi = 0;
       +        if(mouse.wi == mouse.ri){
       +                mouse.stall = 1;
       +                mouse.ri = 0;
       +                mouse.wi = 1;
       +                mouse.m[0] = m;
       +                /* fprint(2, "mouse stall\n"); */
       +        }
       +        matchmouse();
       +}
       +
        /*
         * Handle an incoming X event.
         */
       t@@ -472,6 +494,8 @@ runxevent(XEvent *xev)
                int c;
                KeySym k;
                static Mouse m;
       +        XButtonEvent *be;
       +        XKeyEvent *ke;
        
        #ifdef SHOWEVENT
                static int first = 1;
       t@@ -504,41 +528,86 @@ runxevent(XEvent *xev)
                        if(_xconfigure(xev)){
                                mouse.resized = 1;
                                _xreplacescreenimage();
       -                        goto addmouse;
       +                        sendmouse(m);
                        }
                        break;
        
                case ButtonPress:
       +                be = (XButtonEvent*)xev;
       +                if(be->button == 1) {
       +                        if(kstate & ControlMask)
       +                                be->button = 2;
       +                        else if(kstate & Mod1Mask)
       +                                be->button = 3;
       +                }
       +                // fall through
                case ButtonRelease:
       +                altdown = 0;
       +                // fall through
                case MotionNotify:
                        if(mouse.stall)
                                return;
                        if(_xtoplan9mouse(xev, &m) < 0)
                                return;
       -        addmouse:
       -                mouse.m[mouse.wi] = m;
       -                mouse.wi++;
       -                if(mouse.wi == nelem(mouse.m))
       -                        mouse.wi = 0;
       -                if(mouse.wi == mouse.ri){
       -                        mouse.stall = 1;
       -                        mouse.ri = 0;
       -                        mouse.wi = 1;
       -                        mouse.m[0] = m;
       -                        /* fprint(2, "mouse stall\n"); */
       -                }
       -                matchmouse();
       +                sendmouse(m);
                        break;
                
       +        case KeyRelease:
                case KeyPress:
       -                if(kbd.stall)
       -                        return;
       -                XLookupString((XKeyEvent*)xev, NULL, 0, &k, NULL);
       +                ke = (XKeyEvent*)xev;
       +                XLookupString(ke, NULL, 0, &k, NULL);
       +                c = ke->state;
       +                switch(k) {
       +                case XK_Alt_L:
       +                case XK_Meta_L:        /* Shift Alt on PCs */
       +                case XK_Alt_R:
       +                case XK_Meta_R:        /* Shift Alt on PCs */
       +                case XK_Multi_key:
       +                        if(xev->type == KeyPress)
       +                                altdown = 1;
       +                        else if(altdown) {
       +                                altdown = 0;
       +                                sendalt();
       +                        }
       +                        break;
       +                }
       +
       +                switch(k) {
       +                case XK_Control_L:
       +                        if(xev->type == KeyPress)
       +                                c |= ControlMask;
       +                        else
       +                                c &= ~ControlMask;
       +                        goto kbutton;
       +                case XK_Alt_L:
       +                case XK_Shift_L:
       +                        if(xev->type == KeyPress)
       +                                c |= Mod1Mask;
       +                        else
       +                                c &= ~Mod1Mask;
       +                kbutton:
       +                        kstate = c;
       +                        if(m.buttons || kbuttons) {
       +                                altdown = 0; // used alt
       +                                kbuttons = 0;
       +                                if(c & ControlMask)
       +                                        kbuttons |= 2;
       +                                if(c & Mod1Mask)
       +                                        kbuttons |= 4;
       +                                sendmouse(m);
       +                                break;
       +                        }
       +                }
       +
       +                if(xev->type != KeyPress)
       +                        break;
                        if(k == XK_F11){
                                fullscreen = !fullscreen;
                                _xmovewindow(fullscreen ? screenrect : windowrect);
                                return;
                        }
       +                if(kbd.stall)
       +                        return;
                        if((c = _xtoplan9kbd(xev)) < 0)
                                return;
                        kbd.r[kbd.wi++] = c;