Middle emulation - make the emulated button number configurable

Sometimes it may be desirable to remap physical middle button
to something else and use emulation instead. The emulation is
however hardcoded to emulate physical button 2, so the emulated
button gets remapped together with the physical one. This patch
adds the Emulate3Button configuration option to allow for user
selection of the emulated button number and a configuration
like this:

Section "InputClass"
    Identifier "Middle button emulation config"
    MatchProduct ".... some device ..."
    MatchDriver "evdev"
    Option "Emulate3Buttons" "on"
    Option "Emulate3Button" "9"
EndSection

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
master
David Strobach 9 years ago committed by Peter Hutterer
parent 7251e42dfb
commit 425ed6017a
  1. 2
      include/evdev-properties.h
  2. 8
      man/evdev.man
  3. 47
      src/emuMB.c
  4. 1
      src/evdev.h

@ -33,6 +33,8 @@
#define EVDEV_PROP_MIDBUTTON "Evdev Middle Button Emulation" #define EVDEV_PROP_MIDBUTTON "Evdev Middle Button Emulation"
/* CARD32 */ /* CARD32 */
#define EVDEV_PROP_MIDBUTTON_TIMEOUT "Evdev Middle Button Timeout" #define EVDEV_PROP_MIDBUTTON_TIMEOUT "Evdev Middle Button Timeout"
/* CARD8 */
#define EVDEV_PROP_MIDBUTTON_BUTTON "Evdev Middle Button Button"
/* Wheel emulation */ /* Wheel emulation */
/* BOOL */ /* BOOL */

@ -94,6 +94,11 @@ Sets the timeout (in milliseconds) that the driver waits before deciding
if two buttons where pressed "simultaneously" when 3 button emulation is if two buttons where pressed "simultaneously" when 3 button emulation is
enabled. Default: 50. Property: "Evdev Middle Button Timeout". enabled. Default: 50. Property: "Evdev Middle Button Timeout".
.TP 7 .TP 7
.BI "Option \*qEmulate3Button\*q \*q" integer \*q
Specifies the physical button number to be emitted if middle button emulation
is triggered.
Default: 2. Property: "Evdev Middle Button Button".
.TP 7
.BI "Option \*qEmulateWheel\*q \*q" boolean \*q .BI "Option \*qEmulateWheel\*q \*q" boolean \*q
Enable/disable "wheel" emulation. Wheel emulation means emulating button Enable/disable "wheel" emulation. Wheel emulation means emulating button
press/release events when the mouse is moved while a specific real button press/release events when the mouse is moved while a specific real button
@ -283,6 +288,9 @@ value.
.BI "Evdev Middle Button Timeout" .BI "Evdev Middle Button Timeout"
1 16-bit positive value. 1 16-bit positive value.
.TP 7 .TP 7
.BI "Evdev Middle Button Button"
1 8-bit value, allowed range 0-32, 0 disables the button.
.TP 7
.BI "Evdev Wheel Emulation" .BI "Evdev Wheel Emulation"
1 boolean value (8 bit, 0 or 1). 1 boolean value (8 bit, 0 or 1).
.TP 7 .TP 7

@ -45,6 +45,7 @@
static Atom prop_mbemu = 0; /* Middle button emulation on/off property */ static Atom prop_mbemu = 0; /* Middle button emulation on/off property */
static Atom prop_mbtimeout = 0; /* Middle button timeout property */ static Atom prop_mbtimeout = 0; /* Middle button timeout property */
static Atom prop_mbbuton = 0; /* Middle button target button property */
/* /*
* Lets create a simple finite-state machine for 3 button emulation: * Lets create a simple finite-state machine for 3 button emulation:
* *
@ -185,6 +186,7 @@ EvdevMBEmuTimer(InputInfoPtr pInfo)
{ {
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
int id; int id;
int mapped_id;
#if HAVE_THREADED_INPUT #if HAVE_THREADED_INPUT
input_lock(); input_lock();
@ -194,7 +196,10 @@ EvdevMBEmuTimer(InputInfoPtr pInfo)
pEvdev->emulateMB.pending = FALSE; pEvdev->emulateMB.pending = FALSE;
if ((id = stateTab[pEvdev->emulateMB.state][4][0]) != 0) { if ((id = stateTab[pEvdev->emulateMB.state][4][0]) != 0) {
EvdevPostButtonEvent(pInfo, abs(id), mapped_id = abs(id);
if (mapped_id == 2)
mapped_id = pEvdev->emulateMB.button;
EvdevPostButtonEvent(pInfo, mapped_id,
(id >= 0) ? BUTTON_PRESS : BUTTON_RELEASE); (id >= 0) ? BUTTON_PRESS : BUTTON_RELEASE);
pEvdev->emulateMB.state = pEvdev->emulateMB.state =
stateTab[pEvdev->emulateMB.state][4][2]; stateTab[pEvdev->emulateMB.state][4][2];
@ -226,6 +231,7 @@ EvdevMBEmuFilterEvent(InputInfoPtr pInfo, int button, BOOL press)
{ {
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
int id; int id;
int mapped_id;
int *btstate; int *btstate;
int ret = FALSE; int ret = FALSE;
@ -244,7 +250,10 @@ EvdevMBEmuFilterEvent(InputInfoPtr pInfo, int button, BOOL press)
if ((id = stateTab[pEvdev->emulateMB.state][*btstate][0]) != 0) if ((id = stateTab[pEvdev->emulateMB.state][*btstate][0]) != 0)
{ {
EvdevQueueButtonEvent(pInfo, abs(id), (id >= 0)); mapped_id = abs(id);
if (mapped_id == 2)
mapped_id = pEvdev->emulateMB.button;
EvdevQueueButtonEvent(pInfo, mapped_id, (id >= 0));
ret = TRUE; ret = TRUE;
} }
if ((id = stateTab[pEvdev->emulateMB.state][*btstate][1]) != 0) if ((id = stateTab[pEvdev->emulateMB.state][*btstate][1]) != 0)
@ -301,12 +310,23 @@ void
EvdevMBEmuPreInit(InputInfoPtr pInfo) EvdevMBEmuPreInit(InputInfoPtr pInfo)
{ {
EvdevPtr pEvdev = (EvdevPtr)pInfo->private; EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
int bt;
pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options, pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
"Emulate3Buttons", "Emulate3Buttons",
FALSE); FALSE);
pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options, pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options,
"Emulate3Timeout", 50); "Emulate3Timeout", 50);
bt = xf86SetIntOption(pInfo->options, "Emulate3Button", 2);
if (bt < 0 || bt > EVDEV_MAXBUTTONS) {
xf86IDrvMsg(pInfo, X_WARNING, "Invalid Emulate3Button value: %d\n",
bt);
xf86IDrvMsg(pInfo, X_WARNING, "Middle button emulation disabled.\n");
pEvdev->emulateMB.enabled = FALSE;
}
pEvdev->emulateMB.button = bt;
} }
void void
@ -338,6 +358,7 @@ EvdevMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
{ {
InputInfoPtr pInfo = dev->public.devicePrivate; InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
int bt;
if (atom == prop_mbemu) if (atom == prop_mbemu)
{ {
@ -353,6 +374,18 @@ EvdevMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
if (!checkonly) if (!checkonly)
pEvdev->emulateMB.timeout = *((CARD32*)val->data); pEvdev->emulateMB.timeout = *((CARD32*)val->data);
} else if (atom == prop_mbbuton)
{
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
bt = *((CARD8*)val->data);
if (bt < 0 || bt > EVDEV_MAXBUTTONS)
return BadValue;
if (!checkonly)
pEvdev->emulateMB.button = bt;
} }
return Success; return Success;
@ -390,5 +423,15 @@ EvdevMBEmuInitProperty(DeviceIntPtr dev)
return; return;
XISetDevicePropertyDeletable(dev, prop_mbtimeout, FALSE); XISetDevicePropertyDeletable(dev, prop_mbtimeout, FALSE);
prop_mbbuton = MakeAtom(EVDEV_PROP_MIDBUTTON_BUTTON,
strlen(EVDEV_PROP_MIDBUTTON_BUTTON),
TRUE);
rc = XIChangeDeviceProperty(dev, prop_mbbuton, XA_INTEGER, 8, PropModeReplace, 1,
&pEvdev->emulateMB.button, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_mbbuton, FALSE);
XIRegisterPropertyHandler(dev, EvdevMBEmuSetProperty, NULL, NULL); XIRegisterPropertyHandler(dev, EvdevMBEmuSetProperty, NULL, NULL);
} }

@ -196,6 +196,7 @@ typedef struct {
int state; /* state machine (see bt3emu.c) */ int state; /* state machine (see bt3emu.c) */
Time expires; /* time of expiry */ Time expires; /* time of expiry */
Time timeout; Time timeout;
uint8_t button; /* phys button to emit */
} emulateMB; } emulateMB;
/* Third mouse button emulation */ /* Third mouse button emulation */
struct emulate3B { struct emulate3B {

Loading…
Cancel
Save