#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "evdev.h"
static signed char stateTab[11][5][3] = {
{
{ 0, 0, 0 },
{ 0, 0, 1 },
{ 0, 0, 2 },
{ 2, 0, 3 },
{ 0, 0, -1 }
},
{
{ 1, -1, 0 },
{ 0, 0, 1 },
{ 1, -1, 2 },
{ 2, 0, 3 },
{ 1, 0, 4 },
},
{
{ 3, -3, 0 },
{ 3, -3, 1 },
{ 0, 0, 2 },
{ 2, 0, 3 },
{ 3, 0, 5 },
},
{
{ -2, 0, 0 },
{ 0, 0, 7 },
{ 0, 0, 6 },
{ 0, 0, 3 },
{ 0, 0, -1 },
},
{
{ -1, 0, 0 },
{ 0, 0, 4 },
{ -1, 0, 2 },
{ 3, 0, 10 },
{ 0, 0, -1 },
},
{
{ -3, 0, 0 },
{ -3, 0, 1 },
{ 0, 0, 5 },
{ 1, 0, 10 },
{ 0, 0, -1 },
},
{
{ -2, 0, 0 },
{ -2, 0, 1 },
{ 0, 0, 6 },
{ 1, 0, 8 },
{ 0, 0, -1 },
},
{
{ -2, 0, 0 },
{ 0, 0, 7 },
{ -2, 0, 2 },
{ 3, 0, 9 },
{ 0, 0, -1 },
},
{
{ -2, -1, 0 },
{ -2, 0, 4 },
{ -1, 0, 6 },
{ 0, 0, 8 },
{ 0, 0, -1 },
},
{
{ -2, -3, 0 },
{ -3, 0, 7 },
{ -2, 0, 5 },
{ 0, 0, 9 },
{ 0, 0, -1 },
},
{
{ -1, -3, 0 },
{ -3, 0, 4 },
{ -1, 0, 5 },
{ 0, 0, 10 },
{ 0, 0, -1 },
},
};
int
EvdevMBEmuTimer(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = pInfo->private;
int sigstate;
int id;
sigstate = xf86BlockSIGIO ();
pEvdev->emulateMB.pending = FALSE;
if ((id = stateTab[pEvdev->emulateMB.state][4][0]) != 0) {
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
pEvdev->emulateMB.state =
stateTab[pEvdev->emulateMB.state][4][2];
} else {
ErrorF("Got unexpected buttonTimer in state %d\n",
pEvdev->emulateMB.state);
}
xf86UnblockSIGIO (sigstate);
return 0;
}
BOOL
EvdevMBEmuFilterEvent(InputInfoPtr pInfo, int code, BOOL press)
{
EvdevPtr pEvdev = pInfo->private;
int id;
int *btstate;
int ret = FALSE;
if (!pEvdev->emulateMB.enabled)
return ret;
if (code != BTN_LEFT && code != BTN_RIGHT)
return ret;
btstate = &pEvdev->emulateMB.buttonstate;
if (press)
*btstate |= (code == BTN_LEFT) ? 0x1 : 0x2;
else
*btstate &= (code == BTN_LEFT) ? ~0x1 : ~0x2;
if ((id = stateTab[pEvdev->emulateMB.state][*btstate][0]) != 0)
{
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
ret = TRUE;
}
if ((id = stateTab[pEvdev->emulateMB.state][*btstate][1]) != 0)
{
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
ret = TRUE;
}
pEvdev->emulateMB.state =
stateTab[pEvdev->emulateMB.state][*btstate][2];
if (stateTab[pEvdev->emulateMB.state][4][0] != 0) {
pEvdev->emulateMB.expires = GetTimeInMillis () + pEvdev->emulateMB.timeout;
pEvdev->emulateMB.pending = TRUE;
ret = TRUE;
} else {
pEvdev->emulateMB.pending = FALSE;
}
return ret;
}
void EvdevMBEmuWakeupHandler(pointer data,
int i,
pointer LastSelectMask)
{
InputInfoPtr pInfo = (InputInfoPtr)data;
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
int ms;
if (pEvdev->emulateMB.pending)
{
ms = pEvdev->emulateMB.expires - GetTimeInMillis();
if (ms <= 0)
EvdevMBEmuTimer(pInfo);
}
}
void EvdevMBEmuBlockHandler(pointer data,
struct timeval **waitTime,
pointer LastSelectMask)
{
InputInfoPtr pInfo = (InputInfoPtr) data;
EvdevPtr pEvdev= (EvdevPtr) pInfo->private;
int ms;
if (pEvdev->emulateMB.pending)
{
ms = pEvdev->emulateMB.expires - GetTimeInMillis ();
if (ms <= 0)
ms = 0;
AdjustWaitForDelay (waitTime, ms);
}
}
void
EvdevMBEmuPreInit(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
"Emulate3Buttons", TRUE);
pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options,
"Emulate3Timeout", 50);
RegisterBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
EvdevMBEmuWakeupHandler,
(pointer)pInfo);
}
void
EvdevMBEmuFinalize(InputInfoPtr pInfo)
{
RemoveBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
EvdevMBEmuWakeupHandler,
(pointer)pInfo);
}
void
EvdevMBEmuEnable(InputInfoPtr pInfo, BOOL enable)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
pEvdev->emulateMB.enabled = enable;
}