2013-11-30 08:51:10 -05:00
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Copyright <EFBFBD> 1999 Keith Packard
|
|
|
|
|
*
|
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
|
* the above copyright notice appear in all copies and that both that
|
|
|
|
|
* copyright notice and this permission notice appear in supporting
|
|
|
|
|
* documentation, and that the name of Keith Packard not be used in
|
|
|
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
|
|
|
* specific, written prior permission. Keith Packard makes no
|
|
|
|
|
* representations about the suitability of this software for any purpose. It
|
|
|
|
|
* is provided "as is" without express or implied warranty.
|
|
|
|
|
*
|
|
|
|
|
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
|
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
|
|
|
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
|
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
|
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
|
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include <kdrive-config.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include "kdrive.h"
|
|
|
|
|
#include "inputstr.h"
|
|
|
|
|
|
|
|
|
|
#define XK_PUBLISHING
|
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
|
#if HAVE_X11_XF86KEYSYM_H
|
|
|
|
|
#include <X11/XF86keysym.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include "kkeymap.h"
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
static DeviceIntPtr pKdKeyboard, pKdPointer;
|
|
|
|
|
|
|
|
|
|
#define MAX_MOUSE_DRIVERS 4
|
|
|
|
|
|
|
|
|
|
static const KdMouseFuncs *kdMouseFuncs[MAX_MOUSE_DRIVERS];
|
|
|
|
|
|
|
|
|
|
static int kdNMouseFuncs;
|
|
|
|
|
static const KdKeyboardFuncs *kdKeyboardFuncs;
|
|
|
|
|
|
|
|
|
|
static int kdBellPitch;
|
|
|
|
|
static int kdBellDuration;
|
|
|
|
|
|
|
|
|
|
static int kdLeds;
|
|
|
|
|
|
|
|
|
|
static Bool kdInputEnabled;
|
|
|
|
|
|
|
|
|
|
static Bool kdOffScreen;
|
|
|
|
|
static unsigned long kdOffScreenTime;
|
|
|
|
|
|
|
|
|
|
static KdMouseMatrix kdMouseMatrix = {
|
|
|
|
|
{{1, 0, 0},
|
|
|
|
|
{0, 1, 0}}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int kdMouseButtonCount;
|
|
|
|
|
|
|
|
|
|
int kdMinScanCode;
|
|
|
|
|
int kdMaxScanCode;
|
|
|
|
|
|
|
|
|
|
static int kdMinKeyCode;
|
|
|
|
|
static int kdMaxKeyCode;
|
|
|
|
|
|
2013-12-13 07:43:16 -05:00
|
|
|
|
static const int kdKeymapWidth = KD_MAX_WIDTH;
|
2013-11-30 08:51:10 -05:00
|
|
|
|
|
|
|
|
|
KeySym kdKeymap[KD_MAX_LENGTH * KD_MAX_WIDTH];
|
|
|
|
|
|
|
|
|
|
static CARD8 kdModMap[MAP_LENGTH];
|
|
|
|
|
static KeySymsRec kdKeySyms;
|
|
|
|
|
|
|
|
|
|
void KdResetInputMachine(void);
|
|
|
|
|
|
|
|
|
|
#define KD_KEY_COUNT 248
|
|
|
|
|
|
|
|
|
|
CARD8 kdKeyState[KD_KEY_COUNT / 8];
|
|
|
|
|
|
|
|
|
|
#define IsKeyDown(key) ((kdKeyState[(key) >> 3] >> ((key) & 7)) & 1)
|
|
|
|
|
|
|
|
|
|
#define KD_MAX_INPUT_FDS 8
|
|
|
|
|
|
|
|
|
|
typedef struct _kdInputFd {
|
|
|
|
|
int type;
|
|
|
|
|
int fd;
|
|
|
|
|
void (*read) (int fd, void *closure);
|
|
|
|
|
int (*enable) (int fd, void *closure);
|
|
|
|
|
void (*disable) (int fd, void *closure);
|
|
|
|
|
void *closure;
|
|
|
|
|
} KdInputFd;
|
|
|
|
|
|
|
|
|
|
static KdInputFd kdInputFds[KD_MAX_INPUT_FDS];
|
|
|
|
|
static int kdNumInputFds;
|
|
|
|
|
static int kdInputTypeSequence;
|
|
|
|
|
|
|
|
|
|
static void KdSigio(int sig)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < kdNumInputFds; i++)
|
|
|
|
|
(*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdBlockSigio(void)
|
|
|
|
|
{
|
|
|
|
|
sigset_t set;
|
|
|
|
|
|
|
|
|
|
sigemptyset(&set);
|
|
|
|
|
sigaddset(&set, SIGIO);
|
|
|
|
|
sigprocmask(SIG_BLOCK, &set, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdUnblockSigio(void)
|
|
|
|
|
{
|
|
|
|
|
sigset_t set;
|
|
|
|
|
|
|
|
|
|
sigemptyset(&set);
|
|
|
|
|
sigaddset(&set, SIGIO);
|
|
|
|
|
sigprocmask(SIG_UNBLOCK, &set, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef VERIFY_SIGIO
|
|
|
|
|
#ifdef VERIFY_SIGIO
|
|
|
|
|
|
|
|
|
|
void KdAssertSigioBlocked(char *where)
|
|
|
|
|
{
|
|
|
|
|
sigset_t set, old;
|
|
|
|
|
|
|
|
|
|
sigemptyset(&set);
|
|
|
|
|
sigprocmask(SIG_BLOCK, &set, &old);
|
|
|
|
|
if (!sigismember(&old, SIGIO))
|
|
|
|
|
ErrorF("SIGIO not blocked at %s\n", where);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
#define KdAssertSigioBlocked(s)
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static int kdnFds;
|
|
|
|
|
|
|
|
|
|
#ifdef FNONBLOCK
|
|
|
|
|
#define NOBLOCK FNONBLOCK
|
|
|
|
|
#else
|
|
|
|
|
#define NOBLOCK FNDELAY
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void KdNonBlockFd(int fd)
|
|
|
|
|
{
|
|
|
|
|
int flags;
|
|
|
|
|
|
|
|
|
|
flags = fcntl(fd, F_GETFL);
|
|
|
|
|
flags |= FASYNC | NOBLOCK;
|
|
|
|
|
fcntl(fd, F_SETFL, flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdAddFd(int fd)
|
|
|
|
|
{
|
|
|
|
|
struct sigaction act;
|
|
|
|
|
|
|
|
|
|
sigset_t set;
|
|
|
|
|
|
|
|
|
|
kdnFds++;
|
|
|
|
|
fcntl(fd, F_SETOWN, getpid());
|
|
|
|
|
KdNonBlockFd(fd);
|
|
|
|
|
AddEnabledDevice(fd);
|
|
|
|
|
memset(&act, '\0', sizeof act);
|
|
|
|
|
act.sa_handler = KdSigio;
|
|
|
|
|
sigemptyset(&act.sa_mask);
|
|
|
|
|
sigaddset(&act.sa_mask, SIGIO);
|
|
|
|
|
sigaddset(&act.sa_mask, SIGALRM);
|
|
|
|
|
sigaddset(&act.sa_mask, SIGVTALRM);
|
|
|
|
|
sigaction(SIGIO, &act, 0);
|
|
|
|
|
sigemptyset(&set);
|
|
|
|
|
sigprocmask(SIG_SETMASK, &set, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdRemoveFd(int fd)
|
|
|
|
|
{
|
|
|
|
|
struct sigaction act;
|
|
|
|
|
|
|
|
|
|
int flags;
|
|
|
|
|
|
|
|
|
|
kdnFds--;
|
|
|
|
|
RemoveEnabledDevice(fd);
|
|
|
|
|
flags = fcntl(fd, F_GETFL);
|
|
|
|
|
flags &= ~(FASYNC | NOBLOCK);
|
|
|
|
|
fcntl(fd, F_SETFL, flags);
|
|
|
|
|
if (kdnFds == 0) {
|
|
|
|
|
memset(&act, '\0', sizeof act);
|
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
|
|
|
sigemptyset(&act.sa_mask);
|
|
|
|
|
sigaction(SIGIO, &act, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int KdAllocInputType(void)
|
|
|
|
|
{
|
|
|
|
|
return ++kdInputTypeSequence;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bool
|
|
|
|
|
KdRegisterFd(int type, int fd, void (*read) (int fd, void *closure),
|
|
|
|
|
void *closure)
|
|
|
|
|
{
|
|
|
|
|
if (kdNumInputFds == KD_MAX_INPUT_FDS)
|
|
|
|
|
return FALSE;
|
|
|
|
|
kdInputFds[kdNumInputFds].type = type;
|
|
|
|
|
kdInputFds[kdNumInputFds].fd = fd;
|
|
|
|
|
kdInputFds[kdNumInputFds].read = read;
|
|
|
|
|
kdInputFds[kdNumInputFds].enable = 0;
|
|
|
|
|
kdInputFds[kdNumInputFds].disable = 0;
|
|
|
|
|
kdInputFds[kdNumInputFds].closure = closure;
|
|
|
|
|
++kdNumInputFds;
|
|
|
|
|
if (kdInputEnabled)
|
|
|
|
|
KdAddFd(fd);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KdRegisterFdEnableDisable(int fd,
|
|
|
|
|
int (*enable) (int fd, void *closure),
|
|
|
|
|
void (*disable) (int fd, void *closure))
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < kdNumInputFds; i++)
|
|
|
|
|
if (kdInputFds[i].fd == fd) {
|
|
|
|
|
kdInputFds[i].enable = enable;
|
|
|
|
|
kdInputFds[i].disable = disable;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdUnregisterFds(int type, Bool do_close)
|
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < kdNumInputFds;) {
|
|
|
|
|
if (kdInputFds[i].type == type) {
|
|
|
|
|
if (kdInputEnabled)
|
|
|
|
|
KdRemoveFd(kdInputFds[i].fd);
|
|
|
|
|
if (do_close)
|
|
|
|
|
close(kdInputFds[i].fd);
|
|
|
|
|
--kdNumInputFds;
|
|
|
|
|
for (j = i; j < kdNumInputFds; j++)
|
|
|
|
|
kdInputFds[j] = kdInputFds[j + 1];
|
|
|
|
|
} else
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdDisableInput(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
KdBlockSigio();
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < kdNumInputFds; i++) {
|
|
|
|
|
KdRemoveFd(kdInputFds[i].fd);
|
|
|
|
|
if (kdInputFds[i].disable)
|
|
|
|
|
(*kdInputFds[i].disable) (kdInputFds[i].fd,
|
|
|
|
|
kdInputFds[i].closure);
|
|
|
|
|
}
|
|
|
|
|
kdInputEnabled = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdEnableInput(void)
|
|
|
|
|
{
|
|
|
|
|
xEvent xE;
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
kdInputEnabled = TRUE;
|
|
|
|
|
for (i = 0; i < kdNumInputFds; i++) {
|
|
|
|
|
KdNonBlockFd(kdInputFds[i].fd);
|
|
|
|
|
if (kdInputFds[i].enable)
|
|
|
|
|
kdInputFds[i].fd =
|
|
|
|
|
(*kdInputFds[i].enable) (kdInputFds[i].fd,
|
|
|
|
|
kdInputFds[i].closure);
|
|
|
|
|
KdAddFd(kdInputFds[i].fd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* reset screen saver */
|
|
|
|
|
xE.u.keyButtonPointer.time = GetTimeInMillis();
|
|
|
|
|
NoticeEventTime(&xE);
|
|
|
|
|
|
|
|
|
|
KdUnblockSigio();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int KdMouseProc(DeviceIntPtr pDevice, int onoff)
|
|
|
|
|
{
|
|
|
|
|
BYTE map[KD_MAX_BUTTON];
|
|
|
|
|
|
|
|
|
|
DevicePtr pDev = (DevicePtr) pDevice;
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!pDev)
|
|
|
|
|
return BadImplementation;
|
|
|
|
|
|
|
|
|
|
switch (onoff) {
|
|
|
|
|
case DEVICE_INIT:
|
|
|
|
|
for (i = 1; i <= kdMouseButtonCount; i++)
|
|
|
|
|
map[i] = i;
|
|
|
|
|
InitPointerDeviceStruct(pDev, map, kdMouseButtonCount,
|
|
|
|
|
miPointerGetMotionEvents,
|
|
|
|
|
(PtrCtrlProcPtr) NoopDDA,
|
|
|
|
|
miPointerGetMotionBufferSize());
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DEVICE_ON:
|
|
|
|
|
pDev->on = TRUE;
|
|
|
|
|
pKdPointer = pDevice;
|
|
|
|
|
for (i = 0; i < kdNMouseFuncs; i++)
|
|
|
|
|
(*kdMouseFuncs[i]->Init) ();
|
|
|
|
|
break;
|
|
|
|
|
case DEVICE_OFF:
|
|
|
|
|
case DEVICE_CLOSE:
|
|
|
|
|
if (pDev->on) {
|
|
|
|
|
pDev->on = FALSE;
|
|
|
|
|
pKdPointer = 0;
|
|
|
|
|
for (i = 0; i < kdNMouseFuncs; i++)
|
|
|
|
|
(*kdMouseFuncs[i]->Fini) ();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return Success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bool LegalModifier(unsigned int key, DevicePtr pDev)
|
|
|
|
|
{
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdBell(int volume, DeviceIntPtr pDev, pointer ctrl, int something)
|
|
|
|
|
{
|
|
|
|
|
if (kdInputEnabled)
|
|
|
|
|
(*kdKeyboardFuncs->Bell) (volume, kdBellPitch, kdBellDuration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdSetLeds(void)
|
|
|
|
|
{
|
|
|
|
|
if (kdInputEnabled)
|
|
|
|
|
(*kdKeyboardFuncs->Leds) (kdLeds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdSetLed(int led, Bool on)
|
|
|
|
|
{
|
|
|
|
|
NoteLedState(pKdKeyboard, led, on);
|
|
|
|
|
kdLeds = pKdKeyboard->kbdfeed->ctrl.leds;
|
|
|
|
|
KdSetLeds();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdSetMouseMatrix(KdMouseMatrix * matrix)
|
|
|
|
|
{
|
|
|
|
|
kdMouseMatrix = *matrix;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KdComputeMouseMatrix(KdMouseMatrix * m, Rotation randr, int width, int height)
|
|
|
|
|
{
|
|
|
|
|
int x_dir = 1, y_dir = 1;
|
|
|
|
|
|
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
|
|
int size[2];
|
|
|
|
|
|
|
|
|
|
size[0] = width;
|
|
|
|
|
size[1] = height;
|
|
|
|
|
if (randr & RR_Reflect_X)
|
|
|
|
|
x_dir = -1;
|
|
|
|
|
if (randr & RR_Reflect_Y)
|
|
|
|
|
y_dir = -1;
|
|
|
|
|
switch (randr & (RR_Rotate_All)) {
|
|
|
|
|
case RR_Rotate_0:
|
|
|
|
|
m->matrix[0][0] = x_dir;
|
|
|
|
|
m->matrix[0][1] = 0;
|
|
|
|
|
m->matrix[1][0] = 0;
|
|
|
|
|
m->matrix[1][1] = y_dir;
|
|
|
|
|
break;
|
|
|
|
|
case RR_Rotate_90:
|
|
|
|
|
m->matrix[0][0] = 0;
|
|
|
|
|
m->matrix[0][1] = -x_dir;
|
|
|
|
|
m->matrix[1][0] = y_dir;
|
|
|
|
|
m->matrix[1][1] = 0;
|
|
|
|
|
break;
|
|
|
|
|
case RR_Rotate_180:
|
|
|
|
|
m->matrix[0][0] = -x_dir;
|
|
|
|
|
m->matrix[0][1] = 0;
|
|
|
|
|
m->matrix[1][0] = 0;
|
|
|
|
|
m->matrix[1][1] = -y_dir;
|
|
|
|
|
break;
|
|
|
|
|
case RR_Rotate_270:
|
|
|
|
|
m->matrix[0][0] = 0;
|
|
|
|
|
m->matrix[0][1] = x_dir;
|
|
|
|
|
m->matrix[1][0] = -y_dir;
|
|
|
|
|
m->matrix[1][1] = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
|
m->matrix[i][2] = 0;
|
|
|
|
|
for (j = 0; j < 2; j++)
|
|
|
|
|
if (m->matrix[i][j] < 0)
|
|
|
|
|
m->matrix[i][2] = size[j] - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdKbdCtrl(DeviceIntPtr pDevice, KeybdCtrl * ctrl)
|
|
|
|
|
{
|
|
|
|
|
kdLeds = ctrl->leds;
|
|
|
|
|
kdBellPitch = ctrl->bell_pitch;
|
|
|
|
|
kdBellDuration = ctrl->bell_duration;
|
|
|
|
|
KdSetLeds();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int KdKeybdProc(DeviceIntPtr pDevice, int onoff)
|
|
|
|
|
{
|
|
|
|
|
Bool ret;
|
|
|
|
|
|
|
|
|
|
DevicePtr pDev = (DevicePtr) pDevice;
|
|
|
|
|
|
|
|
|
|
if (!pDev)
|
|
|
|
|
return BadImplementation;
|
|
|
|
|
|
|
|
|
|
switch (onoff) {
|
|
|
|
|
case DEVICE_INIT:
|
|
|
|
|
if (pDev != LookupKeyboardDevice()) {
|
|
|
|
|
return !Success;
|
|
|
|
|
}
|
|
|
|
|
ret = InitKeyboardDeviceStruct(pDev,
|
|
|
|
|
&kdKeySyms, kdModMap, KdBell,
|
|
|
|
|
KdKbdCtrl);
|
|
|
|
|
if (!ret)
|
|
|
|
|
return BadImplementation;
|
|
|
|
|
break;
|
|
|
|
|
case DEVICE_ON:
|
|
|
|
|
pDev->on = TRUE;
|
|
|
|
|
pKdKeyboard = pDevice;
|
|
|
|
|
if (kdKeyboardFuncs)
|
|
|
|
|
(*kdKeyboardFuncs->Init) ();
|
|
|
|
|
break;
|
|
|
|
|
case DEVICE_OFF:
|
|
|
|
|
case DEVICE_CLOSE:
|
|
|
|
|
pKdKeyboard = 0;
|
|
|
|
|
if (pDev->on) {
|
|
|
|
|
pDev->on = FALSE;
|
|
|
|
|
if (kdKeyboardFuncs)
|
|
|
|
|
(*kdKeyboardFuncs->Fini) ();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return Success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern KeybdCtrl defaultKeyboardControl;
|
|
|
|
|
|
|
|
|
|
static void KdInitAutoRepeats(void)
|
|
|
|
|
{
|
|
|
|
|
int key_code;
|
|
|
|
|
|
|
|
|
|
unsigned char mask;
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
unsigned char *repeats;
|
|
|
|
|
|
|
|
|
|
repeats = defaultKeyboardControl.autoRepeats;
|
|
|
|
|
memset(repeats, '\0', 32);
|
|
|
|
|
for (key_code = KD_MIN_KEYCODE; key_code <= KD_MAX_KEYCODE; key_code++) {
|
|
|
|
|
if (!kdModMap[key_code]) {
|
|
|
|
|
i = key_code >> 3;
|
|
|
|
|
mask = 1 << (key_code & 7);
|
|
|
|
|
repeats[i] |= mask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-13 07:43:16 -05:00
|
|
|
|
static const KdKeySymModsRec kdKeySymMods[] = {
|
2013-11-30 08:51:10 -05:00
|
|
|
|
{XK_Control_L, ControlMask},
|
|
|
|
|
{XK_Control_R, ControlMask},
|
|
|
|
|
{XK_Shift_L, ShiftMask},
|
|
|
|
|
{XK_Shift_R, ShiftMask},
|
|
|
|
|
{XK_Caps_Lock, LockMask},
|
|
|
|
|
{XK_Shift_Lock, LockMask},
|
|
|
|
|
{XK_Alt_L, Mod1Mask},
|
|
|
|
|
{XK_Alt_R, Mod1Mask},
|
|
|
|
|
{XK_Meta_L, Mod1Mask},
|
|
|
|
|
{XK_Meta_R, Mod1Mask},
|
|
|
|
|
{XK_Num_Lock, Mod2Mask},
|
|
|
|
|
{XK_Super_L, Mod3Mask},
|
|
|
|
|
{XK_Super_R, Mod3Mask},
|
|
|
|
|
{XK_Hyper_L, Mod3Mask},
|
|
|
|
|
{XK_Hyper_R, Mod3Mask},
|
|
|
|
|
{XK_Mode_switch, Mod4Mask},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define NUM_SYM_MODS (sizeof(kdKeySymMods) / sizeof(kdKeySymMods[0]))
|
|
|
|
|
|
|
|
|
|
static void KdInitModMap(void)
|
|
|
|
|
{
|
|
|
|
|
int key_code;
|
|
|
|
|
|
|
|
|
|
int row;
|
|
|
|
|
|
|
|
|
|
int width;
|
|
|
|
|
|
|
|
|
|
KeySym *syms;
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
width = kdKeySyms.mapWidth;
|
|
|
|
|
for (key_code = kdMinKeyCode; key_code <= kdMaxKeyCode; key_code++) {
|
|
|
|
|
kdModMap[key_code] = 0;
|
|
|
|
|
syms = kdKeymap + (key_code - kdMinKeyCode) * width;
|
|
|
|
|
for (row = 0; row < width; row++, syms++) {
|
|
|
|
|
for (i = 0; i < NUM_SYM_MODS; i++) {
|
|
|
|
|
if (*syms == kdKeySymMods[i].modsym)
|
|
|
|
|
kdModMap[key_code] |=
|
|
|
|
|
kdKeySymMods[i].modbit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdAddMouseDriver(const KdMouseFuncs * const pMouseFuncs)
|
|
|
|
|
{
|
|
|
|
|
if (kdNMouseFuncs < MAX_MOUSE_DRIVERS)
|
|
|
|
|
kdMouseFuncs[kdNMouseFuncs++] = pMouseFuncs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdInitInput(const KdMouseFuncs * const pMouseFuncs,
|
|
|
|
|
const KdKeyboardFuncs * const pKeyboardFuncs)
|
|
|
|
|
{
|
|
|
|
|
DeviceIntPtr pKeyboard, pPointer;
|
|
|
|
|
|
|
|
|
|
KdMouseInfo *mi;
|
|
|
|
|
|
|
|
|
|
if (!kdMouseInfo)
|
|
|
|
|
KdParseMouse(0);
|
|
|
|
|
kdMouseButtonCount = 0;
|
|
|
|
|
for (mi = kdMouseInfo; mi; mi = mi->next) {
|
|
|
|
|
if (mi->nbutton > kdMouseButtonCount)
|
|
|
|
|
kdMouseButtonCount = mi->nbutton;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kdNMouseFuncs = 0;
|
|
|
|
|
KdAddMouseDriver(pMouseFuncs);
|
|
|
|
|
kdKeyboardFuncs = pKeyboardFuncs;
|
|
|
|
|
memset(kdKeyState, '\0', sizeof(kdKeyState));
|
|
|
|
|
if (kdKeyboardFuncs)
|
|
|
|
|
(*kdKeyboardFuncs->Load) ();
|
|
|
|
|
kdMinKeyCode = kdMinScanCode + KD_KEY_OFFSET;
|
|
|
|
|
kdMaxKeyCode = kdMaxScanCode + KD_KEY_OFFSET;
|
|
|
|
|
kdKeySyms.map = kdKeymap;
|
|
|
|
|
kdKeySyms.minKeyCode = kdMinKeyCode;
|
|
|
|
|
kdKeySyms.maxKeyCode = kdMaxKeyCode;
|
|
|
|
|
kdKeySyms.mapWidth = kdKeymapWidth;
|
|
|
|
|
kdLeds = 0;
|
|
|
|
|
kdBellPitch = 1000;
|
|
|
|
|
kdBellDuration = 200;
|
|
|
|
|
kdInputEnabled = TRUE;
|
|
|
|
|
KdInitModMap();
|
|
|
|
|
KdInitAutoRepeats();
|
|
|
|
|
KdResetInputMachine();
|
|
|
|
|
pPointer = AddInputDevice(KdMouseProc, TRUE);
|
|
|
|
|
pKeyboard = AddInputDevice(KdKeybdProc, TRUE);
|
|
|
|
|
RegisterPointerDevice(pPointer);
|
|
|
|
|
RegisterKeyboardDevice(pKeyboard);
|
|
|
|
|
miRegisterPointerDevice(screenInfo.screens[0], pPointer);
|
|
|
|
|
mieqInit(&pKeyboard->public, &pPointer->public);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Middle button emulation state machine
|
|
|
|
|
*
|
|
|
|
|
* Possible transitions:
|
|
|
|
|
* Button 1 press v1
|
|
|
|
|
* Button 1 release ^1
|
|
|
|
|
* Button 2 press v2
|
|
|
|
|
* Button 2 release ^2
|
|
|
|
|
* Button 3 press v3
|
|
|
|
|
* Button 3 release ^3
|
|
|
|
|
* Button other press vo
|
|
|
|
|
* Button other release ^o
|
|
|
|
|
* Mouse motion <>
|
|
|
|
|
* Keyboard event k
|
|
|
|
|
* timeout ...
|
|
|
|
|
* outside box <->
|
|
|
|
|
*
|
|
|
|
|
* States:
|
|
|
|
|
* start
|
|
|
|
|
* button_1_pend
|
|
|
|
|
* button_1_down
|
|
|
|
|
* button_2_down
|
|
|
|
|
* button_3_pend
|
|
|
|
|
* button_3_down
|
|
|
|
|
* synthetic_2_down_13
|
|
|
|
|
* synthetic_2_down_3
|
|
|
|
|
* synthetic_2_down_1
|
|
|
|
|
*
|
|
|
|
|
* Transition diagram
|
|
|
|
|
*
|
|
|
|
|
* start
|
|
|
|
|
* v1 -> (hold) (settimeout) button_1_pend
|
|
|
|
|
* ^1 -> (deliver) start
|
|
|
|
|
* v2 -> (deliver) button_2_down
|
|
|
|
|
* ^2 -> (deliever) start
|
|
|
|
|
* v3 -> (hold) (settimeout) button_3_pend
|
|
|
|
|
* ^3 -> (deliver) start
|
|
|
|
|
* vo -> (deliver) start
|
|
|
|
|
* ^o -> (deliver) start
|
|
|
|
|
* <> -> (deliver) start
|
|
|
|
|
* k -> (deliver) start
|
|
|
|
|
*
|
|
|
|
|
* button_1_pend (button 1 is down, timeout pending)
|
|
|
|
|
* ^1 -> (release) (deliver) start
|
|
|
|
|
* v2 -> (release) (deliver) button_1_down
|
|
|
|
|
* ^2 -> (release) (deliver) button_1_down
|
|
|
|
|
* v3 -> (cleartimeout) (generate v2) synthetic_2_down_13
|
|
|
|
|
* ^3 -> (release) (deliver) button_1_down
|
|
|
|
|
* vo -> (release) (deliver) button_1_down
|
|
|
|
|
* ^o -> (release) (deliver) button_1_down
|
|
|
|
|
* <-> -> (release) (deliver) button_1_down
|
|
|
|
|
* <> -> (deliver) button_1_pend
|
|
|
|
|
* k -> (release) (deliver) button_1_down
|
|
|
|
|
* ... -> (release) button_1_down
|
|
|
|
|
*
|
|
|
|
|
* button_1_down (button 1 is down)
|
|
|
|
|
* ^1 -> (deliver) start
|
|
|
|
|
* v2 -> (deliver) button_1_down
|
|
|
|
|
* ^2 -> (deliver) button_1_down
|
|
|
|
|
* v3 -> (deliver) button_1_down
|
|
|
|
|
* ^3 -> (deliver) button_1_down
|
|
|
|
|
* vo -> (deliver) button_1_down
|
|
|
|
|
* ^o -> (deliver) button_1_down
|
|
|
|
|
* <> -> (deliver) button_1_down
|
|
|
|
|
* k -> (deliver) button_1_down
|
|
|
|
|
*
|
|
|
|
|
* button_2_down (button 2 is down)
|
|
|
|
|
* v1 -> (deliver) button_2_down
|
|
|
|
|
* ^1 -> (deliver) button_2_down
|
|
|
|
|
* ^2 -> (deliver) start
|
|
|
|
|
* v3 -> (deliver) button_2_down
|
|
|
|
|
* ^3 -> (deliver) button_2_down
|
|
|
|
|
* vo -> (deliver) button_2_down
|
|
|
|
|
* ^o -> (deliver) button_2_down
|
|
|
|
|
* <> -> (deliver) button_2_down
|
|
|
|
|
* k -> (deliver) button_2_down
|
|
|
|
|
*
|
|
|
|
|
* button_3_pend (button 3 is down, timeout pending)
|
|
|
|
|
* v1 -> (generate v2) synthetic_2_down
|
|
|
|
|
* ^1 -> (release) (deliver) button_3_down
|
|
|
|
|
* v2 -> (release) (deliver) button_3_down
|
|
|
|
|
* ^2 -> (release) (deliver) button_3_down
|
|
|
|
|
* ^3 -> (release) (deliver) start
|
|
|
|
|
* vo -> (release) (deliver) button_3_down
|
|
|
|
|
* ^o -> (release) (deliver) button_3_down
|
|
|
|
|
* <-> -> (release) (deliver) button_3_down
|
|
|
|
|
* <> -> (deliver) button_3_pend
|
|
|
|
|
* k -> (release) (deliver) button_3_down
|
|
|
|
|
* ... -> (release) button_3_down
|
|
|
|
|
*
|
|
|
|
|
* button_3_down (button 3 is down)
|
|
|
|
|
* v1 -> (deliver) button_3_down
|
|
|
|
|
* ^1 -> (deliver) button_3_down
|
|
|
|
|
* v2 -> (deliver) button_3_down
|
|
|
|
|
* ^2 -> (deliver) button_3_down
|
|
|
|
|
* ^3 -> (deliver) start
|
|
|
|
|
* vo -> (deliver) button_3_down
|
|
|
|
|
* ^o -> (deliver) button_3_down
|
|
|
|
|
* <> -> (deliver) button_3_down
|
|
|
|
|
* k -> (deliver) button_3_down
|
|
|
|
|
*
|
|
|
|
|
* synthetic_2_down_13 (button 1 and 3 are down)
|
|
|
|
|
* ^1 -> (generate ^2) synthetic_2_down_3
|
|
|
|
|
* v2 -> synthetic_2_down_13
|
|
|
|
|
* ^2 -> synthetic_2_down_13
|
|
|
|
|
* ^3 -> (generate ^2) synthetic_2_down_1
|
|
|
|
|
* vo -> (deliver) synthetic_2_down_13
|
|
|
|
|
* ^o -> (deliver) synthetic_2_down_13
|
|
|
|
|
* <> -> (deliver) synthetic_2_down_13
|
|
|
|
|
* k -> (deliver) synthetic_2_down_13
|
|
|
|
|
*
|
|
|
|
|
* synthetic_2_down_3 (button 3 is down)
|
|
|
|
|
* v1 -> (deliver) synthetic_2_down_3
|
|
|
|
|
* ^1 -> (deliver) synthetic_2_down_3
|
|
|
|
|
* v2 -> synthetic_2_down_3
|
|
|
|
|
* ^2 -> synthetic_2_down_3
|
|
|
|
|
* ^3 -> start
|
|
|
|
|
* vo -> (deliver) synthetic_2_down_3
|
|
|
|
|
* ^o -> (deliver) synthetic_2_down_3
|
|
|
|
|
* <> -> (deliver) synthetic_2_down_3
|
|
|
|
|
* k -> (deliver) synthetic_2_down_3
|
|
|
|
|
*
|
|
|
|
|
* synthetic_2_down_1 (button 1 is down)
|
|
|
|
|
* ^1 -> start
|
|
|
|
|
* v2 -> synthetic_2_down_1
|
|
|
|
|
* ^2 -> synthetic_2_down_1
|
|
|
|
|
* v3 -> (deliver) synthetic_2_down_1
|
|
|
|
|
* ^3 -> (deliver) synthetic_2_down_1
|
|
|
|
|
* vo -> (deliver) synthetic_2_down_1
|
|
|
|
|
* ^o -> (deliver) synthetic_2_down_1
|
|
|
|
|
* <> -> (deliver) synthetic_2_down_1
|
|
|
|
|
* k -> (deliver) synthetic_2_down_1
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
typedef enum _inputClass {
|
|
|
|
|
down_1, up_1,
|
|
|
|
|
down_2, up_2,
|
|
|
|
|
down_3, up_3,
|
|
|
|
|
down_o, up_o,
|
|
|
|
|
motion, outside_box,
|
|
|
|
|
keyboard, timeout,
|
|
|
|
|
num_input_class
|
|
|
|
|
} KdInputClass;
|
|
|
|
|
|
|
|
|
|
typedef enum _inputAction {
|
|
|
|
|
noop,
|
|
|
|
|
hold,
|
|
|
|
|
setto,
|
|
|
|
|
deliver,
|
|
|
|
|
release,
|
|
|
|
|
clearto,
|
|
|
|
|
gen_down_2,
|
|
|
|
|
gen_up_2
|
|
|
|
|
} KdInputAction;
|
|
|
|
|
|
|
|
|
|
#define MAX_ACTIONS 2
|
|
|
|
|
|
|
|
|
|
typedef struct _inputTransition {
|
|
|
|
|
KdInputAction actions[MAX_ACTIONS];
|
|
|
|
|
KdMouseState nextState;
|
|
|
|
|
} KdInputTransition;
|
|
|
|
|
|
|
|
|
|
static const
|
|
|
|
|
KdInputTransition kdInputMachine[num_input_states][num_input_class] = {
|
|
|
|
|
/* start */
|
|
|
|
|
{
|
|
|
|
|
{{hold, setto}, button_1_pend}, /* v1 */
|
|
|
|
|
{{deliver, noop}, start}, /* ^1 */
|
|
|
|
|
{{deliver, noop}, button_2_down}, /* v2 */
|
|
|
|
|
{{deliver, noop}, start}, /* ^2 */
|
|
|
|
|
{{hold, setto}, button_3_pend}, /* v3 */
|
|
|
|
|
{{deliver, noop}, start}, /* ^3 */
|
|
|
|
|
{{deliver, noop}, start}, /* vo */
|
|
|
|
|
{{deliver, noop}, start}, /* ^o */
|
|
|
|
|
{{deliver, noop}, start}, /* <> */
|
|
|
|
|
{{deliver, noop}, start}, /* <-> */
|
|
|
|
|
{{noop, noop}, start}, /* k */
|
|
|
|
|
{{noop, noop}, start}, /* ... */
|
|
|
|
|
},
|
|
|
|
|
/* button_1_pend */
|
|
|
|
|
{
|
|
|
|
|
{{noop, noop}, button_1_pend}, /* v1 */
|
|
|
|
|
{{release, deliver}, start}, /* ^1 */
|
|
|
|
|
{{release, deliver}, button_1_down}, /* v2 */
|
|
|
|
|
{{release, deliver}, button_1_down}, /* ^2 */
|
|
|
|
|
{{clearto, gen_down_2}, synth_2_down_13}, /* v3 */
|
|
|
|
|
{{release, deliver}, button_1_down}, /* ^3 */
|
|
|
|
|
{{release, deliver}, button_1_down}, /* vo */
|
|
|
|
|
{{release, deliver}, button_1_down}, /* ^o */
|
|
|
|
|
{{deliver, noop}, button_1_pend}, /* <> */
|
|
|
|
|
{{release, deliver}, button_1_down}, /* <-> */
|
|
|
|
|
{{noop, noop}, button_1_down}, /* k */
|
|
|
|
|
{{release, noop}, button_1_down}, /* ... */
|
|
|
|
|
},
|
|
|
|
|
/* button_1_down */
|
|
|
|
|
{
|
|
|
|
|
{{noop, noop}, button_1_down}, /* v1 */
|
|
|
|
|
{{deliver, noop}, start}, /* ^1 */
|
|
|
|
|
{{deliver, noop}, button_1_down}, /* v2 */
|
|
|
|
|
{{deliver, noop}, button_1_down}, /* ^2 */
|
|
|
|
|
{{deliver, noop}, button_1_down}, /* v3 */
|
|
|
|
|
{{deliver, noop}, button_1_down}, /* ^3 */
|
|
|
|
|
{{deliver, noop}, button_1_down}, /* vo */
|
|
|
|
|
{{deliver, noop}, button_1_down}, /* ^o */
|
|
|
|
|
{{deliver, noop}, button_1_down}, /* <> */
|
|
|
|
|
{{deliver, noop}, button_1_down}, /* <-> */
|
|
|
|
|
{{noop, noop}, button_1_down}, /* k */
|
|
|
|
|
{{noop, noop}, button_1_down}, /* ... */
|
|
|
|
|
},
|
|
|
|
|
/* button_2_down */
|
|
|
|
|
{
|
|
|
|
|
{{deliver, noop}, button_2_down}, /* v1 */
|
|
|
|
|
{{deliver, noop}, button_2_down}, /* ^1 */
|
|
|
|
|
{{noop, noop}, button_2_down}, /* v2 */
|
|
|
|
|
{{deliver, noop}, start}, /* ^2 */
|
|
|
|
|
{{deliver, noop}, button_2_down}, /* v3 */
|
|
|
|
|
{{deliver, noop}, button_2_down}, /* ^3 */
|
|
|
|
|
{{deliver, noop}, button_2_down}, /* vo */
|
|
|
|
|
{{deliver, noop}, button_2_down}, /* ^o */
|
|
|
|
|
{{deliver, noop}, button_2_down}, /* <> */
|
|
|
|
|
{{deliver, noop}, button_2_down}, /* <-> */
|
|
|
|
|
{{noop, noop}, button_2_down}, /* k */
|
|
|
|
|
{{noop, noop}, button_2_down}, /* ... */
|
|
|
|
|
},
|
|
|
|
|
/* button_3_pend */
|
|
|
|
|
{
|
|
|
|
|
{{clearto, gen_down_2}, synth_2_down_13}, /* v1 */
|
|
|
|
|
{{release, deliver}, button_3_down}, /* ^1 */
|
|
|
|
|
{{release, deliver}, button_3_down}, /* v2 */
|
|
|
|
|
{{release, deliver}, button_3_down}, /* ^2 */
|
|
|
|
|
{{release, deliver}, button_3_down}, /* v3 */
|
|
|
|
|
{{release, deliver}, start}, /* ^3 */
|
|
|
|
|
{{release, deliver}, button_3_down}, /* vo */
|
|
|
|
|
{{release, deliver}, button_3_down}, /* ^o */
|
|
|
|
|
{{deliver, noop}, button_3_pend}, /* <> */
|
|
|
|
|
{{release, deliver}, button_3_down}, /* <-> */
|
|
|
|
|
{{release, noop}, button_3_down}, /* k */
|
|
|
|
|
{{release, noop}, button_3_down}, /* ... */
|
|
|
|
|
},
|
|
|
|
|
/* button_3_down */
|
|
|
|
|
{
|
|
|
|
|
{{deliver, noop}, button_3_down}, /* v1 */
|
|
|
|
|
{{deliver, noop}, button_3_down}, /* ^1 */
|
|
|
|
|
{{deliver, noop}, button_3_down}, /* v2 */
|
|
|
|
|
{{deliver, noop}, button_3_down}, /* ^2 */
|
|
|
|
|
{{noop, noop}, button_3_down}, /* v3 */
|
|
|
|
|
{{deliver, noop}, start}, /* ^3 */
|
|
|
|
|
{{deliver, noop}, button_3_down}, /* vo */
|
|
|
|
|
{{deliver, noop}, button_3_down}, /* ^o */
|
|
|
|
|
{{deliver, noop}, button_3_down}, /* <> */
|
|
|
|
|
{{deliver, noop}, button_3_down}, /* <-> */
|
|
|
|
|
{{noop, noop}, button_3_down}, /* k */
|
|
|
|
|
{{noop, noop}, button_3_down}, /* ... */
|
|
|
|
|
},
|
|
|
|
|
/* synthetic_2_down_13 */
|
|
|
|
|
{
|
|
|
|
|
{{noop, noop}, synth_2_down_13}, /* v1 */
|
|
|
|
|
{{gen_up_2, noop}, synth_2_down_3}, /* ^1 */
|
|
|
|
|
{{noop, noop}, synth_2_down_13}, /* v2 */
|
|
|
|
|
{{noop, noop}, synth_2_down_13}, /* ^2 */
|
|
|
|
|
{{noop, noop}, synth_2_down_13}, /* v3 */
|
|
|
|
|
{{gen_up_2, noop}, synth_2_down_1}, /* ^3 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_13}, /* vo */
|
|
|
|
|
{{deliver, noop}, synth_2_down_13}, /* ^o */
|
|
|
|
|
{{deliver, noop}, synth_2_down_13}, /* <> */
|
|
|
|
|
{{deliver, noop}, synth_2_down_13}, /* <-> */
|
|
|
|
|
{{noop, noop}, synth_2_down_13}, /* k */
|
|
|
|
|
{{noop, noop}, synth_2_down_13}, /* ... */
|
|
|
|
|
},
|
|
|
|
|
/* synthetic_2_down_3 */
|
|
|
|
|
{
|
|
|
|
|
{{deliver, noop}, synth_2_down_3}, /* v1 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_3}, /* ^1 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_3}, /* v2 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_3}, /* ^2 */
|
|
|
|
|
{{noop, noop}, synth_2_down_3}, /* v3 */
|
|
|
|
|
{{noop, noop}, start}, /* ^3 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_3}, /* vo */
|
|
|
|
|
{{deliver, noop}, synth_2_down_3}, /* ^o */
|
|
|
|
|
{{deliver, noop}, synth_2_down_3}, /* <> */
|
|
|
|
|
{{deliver, noop}, synth_2_down_3}, /* <-> */
|
|
|
|
|
{{noop, noop}, synth_2_down_3}, /* k */
|
|
|
|
|
{{noop, noop}, synth_2_down_3}, /* ... */
|
|
|
|
|
},
|
|
|
|
|
/* synthetic_2_down_1 */
|
|
|
|
|
{
|
|
|
|
|
{{noop, noop}, synth_2_down_1}, /* v1 */
|
|
|
|
|
{{noop, noop}, start}, /* ^1 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_1}, /* v2 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_1}, /* ^2 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_1}, /* v3 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_1}, /* ^3 */
|
|
|
|
|
{{deliver, noop}, synth_2_down_1}, /* vo */
|
|
|
|
|
{{deliver, noop}, synth_2_down_1}, /* ^o */
|
|
|
|
|
{{deliver, noop}, synth_2_down_1}, /* <> */
|
|
|
|
|
{{deliver, noop}, synth_2_down_1}, /* <-> */
|
|
|
|
|
{{noop, noop}, synth_2_down_1}, /* k */
|
|
|
|
|
{{noop, noop}, synth_2_down_1}, /* ... */
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define EMULATION_WINDOW 10
|
|
|
|
|
#define EMULATION_TIMEOUT 100
|
|
|
|
|
|
|
|
|
|
#define EventX(e) ((e)->u.keyButtonPointer.rootX)
|
|
|
|
|
#define EventY(e) ((e)->u.keyButtonPointer.rootY)
|
|
|
|
|
|
|
|
|
|
static int KdInsideEmulationWindow(KdMouseInfo * mi, xEvent * ev)
|
|
|
|
|
{
|
|
|
|
|
if (ev->u.keyButtonPointer.pad1) {
|
|
|
|
|
mi->emulationDx += EventX(ev);
|
|
|
|
|
mi->emulationDy += EventY(ev);
|
|
|
|
|
} else {
|
|
|
|
|
mi->emulationDx = EventX(&mi->heldEvent) - EventX(ev);
|
|
|
|
|
mi->emulationDy = EventY(&mi->heldEvent) - EventY(ev);
|
|
|
|
|
}
|
|
|
|
|
return (abs(mi->emulationDx) < EMULATION_WINDOW &&
|
|
|
|
|
abs(mi->emulationDy) < EMULATION_WINDOW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static KdInputClass KdClassifyInput(KdMouseInfo * mi, xEvent * ev)
|
|
|
|
|
{
|
|
|
|
|
switch (ev->u.u.type) {
|
|
|
|
|
case ButtonPress:
|
|
|
|
|
switch (ev->u.u.detail) {
|
|
|
|
|
case 1:
|
|
|
|
|
return down_1;
|
|
|
|
|
case 2:
|
|
|
|
|
return down_2;
|
|
|
|
|
case 3:
|
|
|
|
|
return down_3;
|
|
|
|
|
default:
|
|
|
|
|
return down_o;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ButtonRelease:
|
|
|
|
|
switch (ev->u.u.detail) {
|
|
|
|
|
case 1:
|
|
|
|
|
return up_1;
|
|
|
|
|
case 2:
|
|
|
|
|
return up_2;
|
|
|
|
|
case 3:
|
|
|
|
|
return up_3;
|
|
|
|
|
default:
|
|
|
|
|
return up_o;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case MotionNotify:
|
|
|
|
|
if (mi->eventHeld && !KdInsideEmulationWindow(mi, ev))
|
|
|
|
|
return outside_box;
|
|
|
|
|
else
|
|
|
|
|
return motion;
|
|
|
|
|
default:
|
|
|
|
|
return keyboard;
|
|
|
|
|
}
|
|
|
|
|
return keyboard;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
char *kdStateNames[] = {
|
|
|
|
|
"start",
|
|
|
|
|
"button_1_pend",
|
|
|
|
|
"button_1_down",
|
|
|
|
|
"button_2_down",
|
|
|
|
|
"button_3_pend",
|
|
|
|
|
"button_3_down",
|
|
|
|
|
"synth_2_down_13",
|
|
|
|
|
"synth_2_down_3",
|
|
|
|
|
"synthetic_2_down_1",
|
|
|
|
|
"num_input_states"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
char *kdClassNames[] = {
|
|
|
|
|
"down_1", "up_1",
|
|
|
|
|
"down_2", "up_2",
|
|
|
|
|
"down_3", "up_3",
|
|
|
|
|
"motion", "ouside_box",
|
|
|
|
|
"keyboard", "timeout",
|
|
|
|
|
"num_input_class"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
char *kdActionNames[] = {
|
|
|
|
|
"noop",
|
|
|
|
|
"hold",
|
|
|
|
|
"setto",
|
|
|
|
|
"deliver",
|
|
|
|
|
"release",
|
|
|
|
|
"clearto",
|
|
|
|
|
"gen_down_2",
|
|
|
|
|
"gen_up_2",
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void KdQueueEvent(xEvent * ev)
|
|
|
|
|
{
|
|
|
|
|
KdAssertSigioBlocked("KdQueueEvent");
|
|
|
|
|
if (ev->u.u.type == MotionNotify) {
|
|
|
|
|
if (ev->u.keyButtonPointer.pad1) {
|
|
|
|
|
ev->u.keyButtonPointer.pad1 = 0;
|
|
|
|
|
miPointerDeltaCursor(ev->u.keyButtonPointer.rootX,
|
|
|
|
|
ev->u.keyButtonPointer.rootY,
|
|
|
|
|
ev->u.keyButtonPointer.time);
|
|
|
|
|
} else {
|
|
|
|
|
miPointerAbsoluteCursor(ev->u.keyButtonPointer.rootX,
|
|
|
|
|
ev->u.keyButtonPointer.rootY,
|
|
|
|
|
ev->u.keyButtonPointer.time);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
mieqEnqueue(ev);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdRunMouseMachine(KdMouseInfo * mi, KdInputClass c, xEvent * ev)
|
|
|
|
|
{
|
|
|
|
|
const KdInputTransition *t;
|
|
|
|
|
|
|
|
|
|
int a;
|
|
|
|
|
|
|
|
|
|
t = &kdInputMachine[mi->mouseState][c];
|
|
|
|
|
for (a = 0; a < MAX_ACTIONS; a++) {
|
|
|
|
|
switch (t->actions[a]) {
|
|
|
|
|
case noop:
|
|
|
|
|
break;
|
|
|
|
|
case hold:
|
|
|
|
|
mi->eventHeld = TRUE;
|
|
|
|
|
mi->emulationDx = 0;
|
|
|
|
|
mi->emulationDy = 0;
|
|
|
|
|
mi->heldEvent = *ev;
|
|
|
|
|
break;
|
|
|
|
|
case setto:
|
|
|
|
|
mi->emulationTimeout =
|
|
|
|
|
GetTimeInMillis() + EMULATION_TIMEOUT;
|
|
|
|
|
mi->timeoutPending = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case deliver:
|
|
|
|
|
KdQueueEvent(ev);
|
|
|
|
|
break;
|
|
|
|
|
case release:
|
|
|
|
|
mi->eventHeld = FALSE;
|
|
|
|
|
mi->timeoutPending = FALSE;
|
|
|
|
|
KdQueueEvent(&mi->heldEvent);
|
|
|
|
|
break;
|
|
|
|
|
case clearto:
|
|
|
|
|
mi->timeoutPending = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
case gen_down_2:
|
|
|
|
|
ev->u.u.detail = 2;
|
|
|
|
|
mi->eventHeld = FALSE;
|
|
|
|
|
KdQueueEvent(ev);
|
|
|
|
|
break;
|
|
|
|
|
case gen_up_2:
|
|
|
|
|
ev->u.u.detail = 2;
|
|
|
|
|
KdQueueEvent(ev);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mi->mouseState = t->nextState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdResetInputMachine(void)
|
|
|
|
|
{
|
|
|
|
|
KdMouseInfo *mi;
|
|
|
|
|
|
|
|
|
|
for (mi = kdMouseInfo; mi; mi = mi->next) {
|
|
|
|
|
mi->mouseState = start;
|
|
|
|
|
mi->eventHeld = FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdHandleMouseEvent(KdMouseInfo * mi, xEvent * ev)
|
|
|
|
|
{
|
|
|
|
|
if (mi->emulateMiddleButton)
|
|
|
|
|
KdRunMouseMachine(mi, KdClassifyInput(mi, ev), ev);
|
|
|
|
|
else
|
|
|
|
|
KdQueueEvent(ev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdReceiveTimeout(KdMouseInfo * mi)
|
|
|
|
|
{
|
|
|
|
|
KdRunMouseMachine(mi, timeout, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define KILL_SEQUENCE ((1L << KK_CONTROL)|(1L << KK_ALT)|(1L << KK_F8)|(1L << KK_F10))
|
|
|
|
|
#define SPECIAL_SEQUENCE ((1L << KK_CONTROL) | (1L << KK_ALT))
|
|
|
|
|
#define SETKILLKEY(b) (KdSpecialKeys |= (1L << (b)))
|
|
|
|
|
#define CLEARKILLKEY(b) (KdSpecialKeys &= ~(1L << (b)))
|
|
|
|
|
#define KEYMAP (pKdKeyboard->key->curKeySyms)
|
|
|
|
|
#define KEYCOL1(k) (KEYMAP.map[((k)-kdMinKeyCode)*KEYMAP.mapWidth])
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* kdCheckTermination
|
|
|
|
|
*
|
|
|
|
|
* This function checks for the key sequence that terminates the server. When
|
|
|
|
|
* detected, it sets the dispatchException flag and returns. The key sequence
|
|
|
|
|
* is:
|
|
|
|
|
* Control-Alt
|
|
|
|
|
* It's assumed that the server will be waken up by the caller when this
|
|
|
|
|
* function returns.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
extern int nClients;
|
|
|
|
|
|
|
|
|
|
static void KdCheckSpecialKeys(xEvent * xE)
|
|
|
|
|
{
|
|
|
|
|
KeySym sym = KEYCOL1(xE->u.u.detail);
|
|
|
|
|
|
|
|
|
|
if (!pKdKeyboard)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Ignore key releases
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (xE->u.u.type == KeyRelease)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check for control/alt pressed
|
|
|
|
|
*/
|
|
|
|
|
if ((pKdKeyboard->key->state & (ControlMask | Mod1Mask)) !=
|
|
|
|
|
(ControlMask | Mod1Mask))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Let OS function see keysym first
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (kdOsFuncs->SpecialKey)
|
|
|
|
|
if ((*kdOsFuncs->SpecialKey) (sym))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Now check for backspace or delete; these signal the
|
|
|
|
|
* X server to terminate
|
|
|
|
|
*/
|
|
|
|
|
switch (sym) {
|
|
|
|
|
case XK_BackSpace:
|
|
|
|
|
case XK_Delete:
|
|
|
|
|
case XK_KP_Delete:
|
|
|
|
|
/*
|
|
|
|
|
* Set the dispatch exception flag so the server will terminate the
|
|
|
|
|
* next time through the dispatch loop.
|
|
|
|
|
*/
|
|
|
|
|
if (kdDontZap == FALSE)
|
|
|
|
|
dispatchException |= DE_TERMINATE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* kdEnqueueKeyboardEvent
|
|
|
|
|
*
|
|
|
|
|
* This function converts hardware keyboard event information into an X event
|
|
|
|
|
* and enqueues it using MI. It wakes up the server before returning so that
|
|
|
|
|
* the event will be processed normally.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void KdHandleKeyboardEvent(xEvent * ev)
|
|
|
|
|
{
|
|
|
|
|
int key = ev->u.u.detail;
|
|
|
|
|
|
|
|
|
|
int byte;
|
|
|
|
|
|
|
|
|
|
CARD8 bit;
|
|
|
|
|
|
|
|
|
|
KdMouseInfo *mi;
|
|
|
|
|
|
|
|
|
|
byte = key >> 3;
|
|
|
|
|
bit = 1 << (key & 7);
|
|
|
|
|
switch (ev->u.u.type) {
|
|
|
|
|
case KeyPress:
|
|
|
|
|
kdKeyState[byte] |= bit;
|
|
|
|
|
break;
|
|
|
|
|
case KeyRelease:
|
|
|
|
|
kdKeyState[byte] &= ~bit;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
for (mi = kdMouseInfo; mi; mi = mi->next)
|
|
|
|
|
KdRunMouseMachine(mi, keyboard, 0);
|
|
|
|
|
KdQueueEvent(ev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdReleaseAllKeys(void)
|
|
|
|
|
{
|
|
|
|
|
xEvent xE;
|
|
|
|
|
|
|
|
|
|
int key;
|
|
|
|
|
|
|
|
|
|
KdBlockSigio();
|
|
|
|
|
for (key = 0; key < KD_KEY_COUNT; key++)
|
|
|
|
|
if (IsKeyDown(key)) {
|
|
|
|
|
xE.u.keyButtonPointer.time = GetTimeInMillis();
|
|
|
|
|
xE.u.u.type = KeyRelease;
|
|
|
|
|
xE.u.u.detail = key;
|
|
|
|
|
KdHandleKeyboardEvent(&xE);
|
|
|
|
|
}
|
|
|
|
|
KdUnblockSigio();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdCheckLock(void)
|
|
|
|
|
{
|
|
|
|
|
KeyClassPtr keyc = pKdKeyboard->key;
|
|
|
|
|
|
|
|
|
|
Bool isSet, shouldBeSet;
|
|
|
|
|
|
|
|
|
|
if (kdKeyboardFuncs->LockLed) {
|
|
|
|
|
isSet = (kdLeds & (1 << (kdKeyboardFuncs->LockLed - 1))) != 0;
|
|
|
|
|
shouldBeSet = (keyc->state & LockMask) != 0;
|
|
|
|
|
if (isSet != shouldBeSet) {
|
|
|
|
|
KdSetLed(kdKeyboardFuncs->LockLed, shouldBeSet);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdEnqueueKeyboardEvent(unsigned char scan_code, unsigned char is_up)
|
|
|
|
|
{
|
|
|
|
|
unsigned char key_code;
|
2013-12-13 07:27:06 -05:00
|
|
|
|
static unsigned int locks = 0;
|
2013-11-30 08:51:10 -05:00
|
|
|
|
|
|
|
|
|
xEvent xE;
|
|
|
|
|
|
|
|
|
|
KeyClassPtr keyc;
|
|
|
|
|
|
|
|
|
|
if (!pKdKeyboard)
|
|
|
|
|
return;
|
|
|
|
|
keyc = pKdKeyboard->key;
|
|
|
|
|
|
|
|
|
|
xE.u.keyButtonPointer.time = GetTimeInMillis();
|
|
|
|
|
|
|
|
|
|
if (kdMinScanCode <= scan_code && scan_code <= kdMaxScanCode) {
|
|
|
|
|
key_code = scan_code + KD_MIN_KEYCODE - kdMinScanCode;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set up this event -- the type may be modified below
|
|
|
|
|
*/
|
|
|
|
|
if (is_up)
|
|
|
|
|
xE.u.u.type = KeyRelease;
|
|
|
|
|
else
|
|
|
|
|
xE.u.u.type = KeyPress;
|
|
|
|
|
xE.u.u.detail = key_code;
|
|
|
|
|
|
2013-12-13 07:27:06 -05:00
|
|
|
|
// Handle toggling keys
|
|
|
|
|
if (xE.u.u.type == KeyPress) {
|
|
|
|
|
switch (KEYCOL1(key_code)) {
|
|
|
|
|
case XK_Num_Lock:
|
|
|
|
|
locks ^= Mod2Mask;
|
|
|
|
|
break;
|
|
|
|
|
case XK_Shift_Lock:
|
|
|
|
|
case XK_Caps_Lock:
|
|
|
|
|
locks ^= LockMask;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2013-11-30 08:51:10 -05:00
|
|
|
|
}
|
2013-12-13 07:27:06 -05:00
|
|
|
|
keyc->state |= locks;
|
2013-11-30 08:51:10 -05:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check pressed keys which are already down
|
|
|
|
|
*/
|
|
|
|
|
if (IsKeyDown(key_code) && xE.u.u.type == KeyPress) {
|
|
|
|
|
KeybdCtrl *ctrl = &pKdKeyboard->kbdfeed->ctrl;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check auto repeat
|
|
|
|
|
*/
|
|
|
|
|
if (!ctrl->autoRepeat || keyc->modifierMap[key_code] ||
|
|
|
|
|
!(ctrl->
|
|
|
|
|
autoRepeats[key_code >> 3] & (1 <<
|
|
|
|
|
(key_code & 7)))) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* X delivers press/release even for autorepeat
|
|
|
|
|
*/
|
|
|
|
|
xE.u.u.type = KeyRelease;
|
|
|
|
|
KdHandleKeyboardEvent(&xE);
|
|
|
|
|
xE.u.u.type = KeyPress;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Check released keys which are already up
|
|
|
|
|
*/
|
|
|
|
|
else if (!IsKeyDown(key_code) && xE.u.u.type == KeyRelease) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
KdCheckSpecialKeys(&xE);
|
|
|
|
|
KdHandleKeyboardEvent(&xE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SetButton(mi, b, v, s) \
|
|
|
|
|
{\
|
|
|
|
|
xE.u.u.detail = mi->map[b]; \
|
|
|
|
|
xE.u.u.type = v; \
|
|
|
|
|
KdHandleMouseEvent (mi, &xE); \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define Press(mi, b) SetButton(mi, b, ButtonPress, "Down")
|
|
|
|
|
#define Release(mi, b) SetButton(mi, b, ButtonRelease, "Up")
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* kdEnqueueMouseEvent
|
|
|
|
|
*
|
|
|
|
|
* This function converts hardware mouse event information into X event
|
|
|
|
|
* information. A mouse movement event is passed off to MI to generate
|
|
|
|
|
* a MotionNotify event, if appropriate. Button events are created and
|
|
|
|
|
* passed off to MI for enqueueing.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void KdMouseAccelerate(DeviceIntPtr device, int *dx, int *dy)
|
|
|
|
|
{
|
|
|
|
|
PtrCtrl *pCtrl = &device->ptrfeed->ctrl;
|
|
|
|
|
|
|
|
|
|
double speed = sqrt(*dx * *dx + *dy * *dy);
|
|
|
|
|
|
|
|
|
|
double accel;
|
|
|
|
|
|
|
|
|
|
#ifdef QUADRATIC_ACCELERATION
|
|
|
|
|
double m;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Ok, so we want it moving num/den times faster at threshold*2
|
|
|
|
|
*
|
|
|
|
|
* accel = m *threshold + b
|
|
|
|
|
* 1 = m * 0 + b -> b = 1
|
|
|
|
|
*
|
|
|
|
|
* num/den = m * (threshold * 2) + 1
|
|
|
|
|
*
|
|
|
|
|
* num / den - 1 = m * threshold * 2
|
|
|
|
|
* (num / den - 1) / threshold * 2 = m
|
|
|
|
|
*/
|
|
|
|
|
m = (((double)pCtrl->num / (double)pCtrl->den - 1.0) /
|
|
|
|
|
((double)pCtrl->threshold * 2.0));
|
|
|
|
|
accel = m * speed + 1;
|
|
|
|
|
#else
|
|
|
|
|
accel = 1.0;
|
|
|
|
|
if (speed > pCtrl->threshold)
|
|
|
|
|
accel = (double)pCtrl->num / pCtrl->den;
|
|
|
|
|
#endif
|
|
|
|
|
*dx = accel * *dx;
|
|
|
|
|
*dy = accel * *dy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdEnqueueMouseEvent(KdMouseInfo * mi, unsigned long flags, int rx, int ry)
|
|
|
|
|
{
|
|
|
|
|
CARD32 ms;
|
|
|
|
|
|
|
|
|
|
xEvent xE;
|
|
|
|
|
|
|
|
|
|
unsigned char buttons;
|
|
|
|
|
|
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
|
|
int (*matrix)[3] = kdMouseMatrix.matrix;
|
|
|
|
|
|
|
|
|
|
unsigned long button;
|
|
|
|
|
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
if (!pKdPointer)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ms = GetTimeInMillis();
|
|
|
|
|
|
|
|
|
|
if (flags & KD_MOUSE_DELTA) {
|
|
|
|
|
if (mi->transformCoordinates) {
|
|
|
|
|
x = matrix[0][0] * rx + matrix[0][1] * ry;
|
|
|
|
|
y = matrix[1][0] * rx + matrix[1][1] * ry;
|
|
|
|
|
} else {
|
|
|
|
|
x = rx;
|
|
|
|
|
y = ry;
|
|
|
|
|
}
|
|
|
|
|
KdMouseAccelerate(pKdPointer, &x, &y);
|
|
|
|
|
xE.u.keyButtonPointer.pad1 = 1;
|
|
|
|
|
} else {
|
|
|
|
|
if (mi->transformCoordinates) {
|
|
|
|
|
x = matrix[0][0] * rx + matrix[0][1] * ry +
|
|
|
|
|
matrix[0][2];
|
|
|
|
|
y = matrix[1][0] * rx + matrix[1][1] * ry +
|
|
|
|
|
matrix[1][2];
|
|
|
|
|
} else {
|
|
|
|
|
x = rx;
|
|
|
|
|
y = ry;
|
|
|
|
|
}
|
|
|
|
|
xE.u.keyButtonPointer.pad1 = 0;
|
|
|
|
|
}
|
|
|
|
|
xE.u.keyButtonPointer.time = ms;
|
|
|
|
|
xE.u.keyButtonPointer.rootX = x;
|
|
|
|
|
xE.u.keyButtonPointer.rootY = y;
|
|
|
|
|
|
|
|
|
|
xE.u.u.type = MotionNotify;
|
|
|
|
|
xE.u.u.detail = 0;
|
|
|
|
|
KdHandleMouseEvent(mi, &xE);
|
|
|
|
|
|
|
|
|
|
buttons = flags;
|
|
|
|
|
|
|
|
|
|
for (button = KD_BUTTON_1, n = 0; button <= KD_BUTTON_5;
|
|
|
|
|
button <<= 1, n++) {
|
|
|
|
|
if ((mi->buttonState & button) ^ (buttons & button)) {
|
|
|
|
|
if (buttons & button) {
|
|
|
|
|
Press(mi, n);
|
|
|
|
|
} else {
|
|
|
|
|
Release(mi, n);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mi->buttonState = buttons;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KdEnqueueMotionEvent(KdMouseInfo * mi, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
xEvent xE;
|
|
|
|
|
|
|
|
|
|
CARD32 ms;
|
|
|
|
|
|
|
|
|
|
ms = GetTimeInMillis();
|
|
|
|
|
|
|
|
|
|
xE.u.u.type = MotionNotify;
|
|
|
|
|
xE.u.keyButtonPointer.time = ms;
|
|
|
|
|
xE.u.keyButtonPointer.rootX = x;
|
|
|
|
|
xE.u.keyButtonPointer.rootY = y;
|
|
|
|
|
|
|
|
|
|
KdHandleMouseEvent(mi, &xE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KdBlockHandler(int screen, pointer blockData, pointer timeout, pointer readmask)
|
|
|
|
|
{
|
|
|
|
|
KdMouseInfo *mi;
|
|
|
|
|
|
|
|
|
|
int myTimeout = 0;
|
|
|
|
|
|
|
|
|
|
for (mi = kdMouseInfo; mi; mi = mi->next) {
|
|
|
|
|
if (mi->timeoutPending) {
|
|
|
|
|
int ms;
|
|
|
|
|
|
|
|
|
|
ms = mi->emulationTimeout - GetTimeInMillis();
|
|
|
|
|
if (ms < 1)
|
|
|
|
|
ms = 1;
|
|
|
|
|
if (ms < myTimeout || myTimeout == 0)
|
|
|
|
|
myTimeout = ms;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* if we need to poll for events, do that */
|
|
|
|
|
if (kdOsFuncs->pollEvents) {
|
|
|
|
|
(*kdOsFuncs->pollEvents) ();
|
|
|
|
|
myTimeout = 20;
|
|
|
|
|
}
|
|
|
|
|
if (myTimeout > 0)
|
|
|
|
|
AdjustWaitForDelay(timeout, myTimeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KdWakeupHandler(int screen,
|
|
|
|
|
pointer data, unsigned long lresult, pointer readmask)
|
|
|
|
|
{
|
|
|
|
|
int result = (int)lresult;
|
|
|
|
|
|
|
|
|
|
fd_set *pReadmask = (fd_set *) readmask;
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
KdMouseInfo *mi;
|
|
|
|
|
|
|
|
|
|
if (kdInputEnabled && result > 0) {
|
|
|
|
|
for (i = 0; i < kdNumInputFds; i++)
|
|
|
|
|
if (FD_ISSET(kdInputFds[i].fd, pReadmask)) {
|
|
|
|
|
KdBlockSigio();
|
|
|
|
|
(*kdInputFds[i].read) (kdInputFds[i].fd,
|
|
|
|
|
kdInputFds[i].closure);
|
|
|
|
|
KdUnblockSigio();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (mi = kdMouseInfo; mi; mi = mi->next) {
|
|
|
|
|
if (mi->timeoutPending) {
|
|
|
|
|
if ((long)(GetTimeInMillis() - mi->emulationTimeout) >=
|
|
|
|
|
0) {
|
|
|
|
|
mi->timeoutPending = FALSE;
|
|
|
|
|
KdBlockSigio();
|
|
|
|
|
KdReceiveTimeout(mi);
|
|
|
|
|
KdUnblockSigio();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (kdSwitchPending)
|
|
|
|
|
KdProcessSwitch();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin))
|
|
|
|
|
|
|
|
|
|
static Bool KdCursorOffScreen(ScreenPtr * ppScreen, int *x, int *y)
|
|
|
|
|
{
|
|
|
|
|
ScreenPtr pScreen = *ppScreen;
|
|
|
|
|
|
|
|
|
|
ScreenPtr pNewScreen;
|
|
|
|
|
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
int dx, dy;
|
|
|
|
|
|
|
|
|
|
int best_x, best_y;
|
|
|
|
|
|
|
|
|
|
int n_best_x, n_best_y;
|
|
|
|
|
|
|
|
|
|
CARD32 ms;
|
|
|
|
|
|
|
|
|
|
if (kdDisableZaphod || screenInfo.numScreens <= 1)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
ms = GetTimeInMillis();
|
|
|
|
|
if (kdOffScreen && (int)(ms - kdOffScreenTime) < 1000)
|
|
|
|
|
return FALSE;
|
|
|
|
|
kdOffScreen = TRUE;
|
|
|
|
|
kdOffScreenTime = ms;
|
|
|
|
|
n_best_x = -1;
|
|
|
|
|
best_x = 32767;
|
|
|
|
|
n_best_y = -1;
|
|
|
|
|
best_y = 32767;
|
|
|
|
|
for (n = 0; n < screenInfo.numScreens; n++) {
|
|
|
|
|
pNewScreen = screenInfo.screens[n];
|
|
|
|
|
if (pNewScreen == pScreen)
|
|
|
|
|
continue;
|
|
|
|
|
dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x;
|
|
|
|
|
dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y;
|
|
|
|
|
if (*x < 0) {
|
|
|
|
|
if (dx <= 0 && -dx < best_x) {
|
|
|
|
|
best_x = -dx;
|
|
|
|
|
n_best_x = n;
|
|
|
|
|
}
|
|
|
|
|
} else if (*x >= pScreen->width) {
|
|
|
|
|
if (dx >= 0 && dx < best_x) {
|
|
|
|
|
best_x = dx;
|
|
|
|
|
n_best_x = n;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (*y < 0) {
|
|
|
|
|
if (dy <= 0 && -dy < best_y) {
|
|
|
|
|
best_y = -dy;
|
|
|
|
|
n_best_y = n;
|
|
|
|
|
}
|
|
|
|
|
} else if (*y >= pScreen->height) {
|
|
|
|
|
if (dy >= 0 && dy < best_y) {
|
|
|
|
|
best_y = dy;
|
|
|
|
|
n_best_y = n;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (best_y < best_x)
|
|
|
|
|
n_best_x = n_best_y;
|
|
|
|
|
if (n_best_x == -1)
|
|
|
|
|
return FALSE;
|
|
|
|
|
pNewScreen = screenInfo.screens[n_best_x];
|
|
|
|
|
|
|
|
|
|
if (*x < 0)
|
|
|
|
|
*x += pNewScreen->width;
|
|
|
|
|
if (*y < 0)
|
|
|
|
|
*y += pNewScreen->height;
|
|
|
|
|
|
|
|
|
|
if (*x >= pScreen->width)
|
|
|
|
|
*x -= pScreen->width;
|
|
|
|
|
if (*y >= pScreen->height)
|
|
|
|
|
*y -= pScreen->height;
|
|
|
|
|
|
|
|
|
|
*ppScreen = pNewScreen;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void KdCrossScreen(ScreenPtr pScreen, Bool entering)
|
|
|
|
|
{
|
|
|
|
|
if (entering)
|
|
|
|
|
KdEnableScreen(pScreen);
|
|
|
|
|
else
|
|
|
|
|
KdDisableScreen(pScreen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int KdCurScreen; /* current event screen */
|
|
|
|
|
|
|
|
|
|
static void KdWarpCursor(ScreenPtr pScreen, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
KdBlockSigio();
|
|
|
|
|
KdCurScreen = pScreen->myNum;
|
|
|
|
|
miPointerWarpCursor(pScreen, x, y);
|
|
|
|
|
KdUnblockSigio();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
miPointerScreenFuncRec kdPointerScreenFuncs = {
|
|
|
|
|
KdCursorOffScreen,
|
|
|
|
|
KdCrossScreen,
|
|
|
|
|
KdWarpCursor
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void ProcessInputEvents()
|
|
|
|
|
{
|
|
|
|
|
mieqProcessInputEvents();
|
|
|
|
|
miPointerUpdate();
|
|
|
|
|
if (kdSwitchPending)
|
|
|
|
|
KdProcessSwitch();
|
|
|
|
|
KdCheckLock();
|
|
|
|
|
}
|