devdraw: control+click = button 2, alt/shift+click = button 3

For single-button mouse users.

R=rsc
https://codereview.appspot.com/7620043
This commit is contained in:
Russ Cox 2013-03-07 22:40:47 -05:00
parent 17934beda0
commit 36bb28dc63
3 changed files with 111 additions and 26 deletions

View file

@ -32,3 +32,4 @@
#undef Visual #undef Visual
#undef Window #undef Window
void sendalt(void);

View file

@ -114,8 +114,7 @@ __xtoplan9kbd(XEvent *e)
case XK_Alt_R: case XK_Alt_R:
case XK_Meta_R: /* Shift Alt on PCs */ case XK_Meta_R: /* Shift Alt on PCs */
case XK_Multi_key: case XK_Multi_key:
k = Kalt; return -1;
break;
default: /* not ISO-1 or tty control */ default: /* not ISO-1 or tty control */
if(k>0xff) { if(k>0xff) {
k = _p9keysym2ucs(k); k = _p9keysym2ucs(k);
@ -128,7 +127,7 @@ __xtoplan9kbd(XEvent *e)
if(k == XK_hyphen) if(k == XK_hyphen)
k = XK_minus; k = XK_minus;
/* Do control mapping ourselves if translator doesn't */ /* Do control mapping ourselves if translator doesn't */
if(e->xkey.state&ControlMask && k != Kalt) if(e->xkey.state&ControlMask)
k &= 0x9f; k &= 0x9f;
if(k == NoSymbol) { if(k == NoSymbol) {
return -1; return -1;
@ -145,18 +144,33 @@ abortcompose(void)
alting = 0; alting = 0;
} }
static Rune* sendrune(Rune);
extern int _latin1(Rune*, int); extern int _latin1(Rune*, int);
static Rune* static Rune*
xtoplan9latin1(XEvent *e) xtoplan9latin1(XEvent *e)
{ {
static Rune k[10]; Rune r;
static int nk;
int n;
int r;
r = __xtoplan9kbd(e); r = __xtoplan9kbd(e);
if(r < 0) if(r < 0)
return nil; 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){ if(alting){
/* /*
* Kludge for Mac's X11 3-button emulation. * Kludge for Mac's X11 3-button emulation.
@ -228,6 +242,7 @@ _xtoplan9mouse(XEvent *e, Mouse *m)
switch(e->type){ switch(e->type){
case ButtonPress: case ButtonPress:
be = (XButtonEvent*)e; be = (XButtonEvent*)e;
/* /*
* Fake message, just sent to make us announce snarf. * Fake message, just sent to make us announce snarf.
* Apparently state and button are 16 and 8 bits on * Apparently state and button are 16 and 8 bits on
@ -292,7 +307,7 @@ _xtoplan9mouse(XEvent *e, Mouse *m)
m->xy.x = me->x; m->xy.x = me->x;
m->xy.y = me->y; m->xy.y = me->y;
m->msec = me->time; m->msec = me->time;
break; return 0; // do not set buttons
default: default:
return -1; return -1;

View file

@ -36,7 +36,7 @@
Button2MotionMask|\ Button2MotionMask|\
Button3MotionMask) 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 Kbdbuf Kbdbuf;
typedef struct Mousebuf Mousebuf; typedef struct Mousebuf Mousebuf;
@ -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. * Handle an incoming X event.
*/ */
@ -472,6 +494,8 @@ runxevent(XEvent *xev)
int c; int c;
KeySym k; KeySym k;
static Mouse m; static Mouse m;
XButtonEvent *be;
XKeyEvent *ke;
#ifdef SHOWEVENT #ifdef SHOWEVENT
static int first = 1; static int first = 1;
@ -504,41 +528,86 @@ runxevent(XEvent *xev)
if(_xconfigure(xev)){ if(_xconfigure(xev)){
mouse.resized = 1; mouse.resized = 1;
_xreplacescreenimage(); _xreplacescreenimage();
goto addmouse; sendmouse(m);
} }
break; break;
case ButtonPress: 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: case ButtonRelease:
altdown = 0;
// fall through
case MotionNotify: case MotionNotify:
if(mouse.stall) if(mouse.stall)
return; return;
if(_xtoplan9mouse(xev, &m) < 0) if(_xtoplan9mouse(xev, &m) < 0)
return; return;
addmouse: sendmouse(m);
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();
break; break;
case KeyRelease:
case KeyPress: case KeyPress:
if(kbd.stall) ke = (XKeyEvent*)xev;
return; XLookupString(ke, NULL, 0, &k, NULL);
XLookupString((XKeyEvent*)xev, 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){ if(k == XK_F11){
fullscreen = !fullscreen; fullscreen = !fullscreen;
_xmovewindow(fullscreen ? screenrect : windowrect); _xmovewindow(fullscreen ? screenrect : windowrect);
return; return;
} }
if(kbd.stall)
return;
if((c = _xtoplan9kbd(xev)) < 0) if((c = _xtoplan9kbd(xev)) < 0)
return; return;
kbd.r[kbd.wi++] = c; kbd.r[kbd.wi++] = c;