#include "xf86.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#ifdef XINPUT
#include "XI.h"
#include "XIproto.h"
#include "xf86Xinput.h"
#else
#include "inputstr.h"
#endif
#ifdef XFreeXDGA
#include "dgaproc.h"
#endif
#include <sys/vuid_event.h>
#include <sys/kbd.h>
#include "atKeynames.h"
extern int sun_ktype;
#ifdef XKB
extern Bool noXkbExtension;
#endif
#define XE_POINTER 1
#define XE_KEYBOARD 2
#ifdef XTESTEXT1
#define XTestSERVER_SIDE
#include "xtestext1.h"
extern short xtest_mousex;
extern short xtest_mousey;
extern int on_steal_input;
extern Bool XTestStealKeyData();
extern void XTestStealMotionData();
#ifdef XINPUT
#define ENQUEUE(ev, code, direction, dev_type) \
(ev)->u.u.detail = (code); \
(ev)->u.u.type = (direction); \
if (!on_steal_input || \
XTestStealKeyData((ev)->u.u.detail, (ev)->u.u.type, dev_type, \
xtest_mousex, xtest_mousey)) \
xf86eqEnqueue((ev))
#else
#define ENQUEUE(ev, code, direction, dev_type) \
(ev)->u.u.detail = (code); \
(ev)->u.u.type = (direction); \
if (!on_steal_input || \
XTestStealKeyData((ev)->u.u.detail, (ev)->u.u.type, dev_type, \
xtest_mousex, xtest_mousey)) \
mieqEnqueue((ev))
#endif
#else
#ifdef XINPUT
#define ENQUEUE(ev, code, direction, dev_type) \
(ev)->u.u.detail = (code); \
(ev)->u.u.type = (direction); \
xf86eqEnqueue((ev))
#else
#define ENQUEUE(ev, code, direction, dev_type) \
(ev)->u.u.detail = (code); \
(ev)->u.u.type = (direction); \
mieqEnqueue((ev))
#endif
#endif
static void startautorepeat(long keycode);
static CARD32 processautorepeat(OsTimerPtr timer, CARD32 now, pointer arg);
static OsTimerPtr sunTimer = NULL;
static unsigned char map[256] = {
#if defined(i386) || defined(__i386) || defined(__i386__)
KEY_NOTUSED,
KEY_Tilde,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_Minus,
KEY_Equal,
0x7D,
KEY_BackSpace,
KEY_Tab,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_LBrace,
KEY_RBrace,
KEY_BSlash,
KEY_CapsLock,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_SemiColon,
KEY_Quote,
KEY_UNKNOWN,
KEY_Enter,
KEY_ShiftL,
KEY_Less,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
KEY_Comma,
KEY_Period,
KEY_Slash,
KEY_BSlash2,
KEY_ShiftR,
KEY_LCtrl,
KEY_LMeta,
KEY_Alt,
KEY_Space,
KEY_AltLang,
KEY_RMeta,
KEY_RCtrl,
KEY_Menu,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_Insert,
KEY_Delete,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_Left,
KEY_Home,
KEY_End,
KEY_UNKNOWN,
KEY_Up,
KEY_Down,
KEY_PgUp,
KEY_PgDown,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_Right,
KEY_NumLock,
KEY_KP_7,
KEY_KP_4,
KEY_KP_1,
KEY_UNKNOWN,
KEY_KP_Divide,
KEY_KP_8,
KEY_KP_5,
KEY_KP_2,
KEY_KP_0,
KEY_KP_Multiply,
KEY_KP_9,
KEY_KP_6,
KEY_KP_3,
KEY_KP_Decimal,
KEY_KP_Minus,
KEY_KP_Plus,
KEY_UNKNOWN,
KEY_KP_Enter,
KEY_UNKNOWN,
KEY_Escape,
KEY_UNKNOWN,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEY_Print,
KEY_ScrollLock,
KEY_Pause,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_NFER,
KEY_XFER,
KEY_HKTG,
KEY_UNKNOWN,
#elif defined(sparc) || defined(__sparc__)
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_F1,
KEY_F2,
KEY_F10,
KEY_F3,
KEY_F11,
KEY_F4,
KEY_F12,
KEY_F5,
KEY_UNKNOWN,
KEY_F6,
KEY_UNKNOWN,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_Alt,
KEY_Up,
KEY_Pause,
KEY_SysReqest,
KEY_ScrollLock,
KEY_Left,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_Down,
KEY_Right,
KEY_Escape,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_Minus,
KEY_Equal,
KEY_Tilde,
KEY_BackSpace,
KEY_Insert,
KEY_UNKNOWN,
KEY_KP_Divide,
KEY_KP_Multiply,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_KP_Decimal,
KEY_UNKNOWN,
KEY_Home,
KEY_Tab,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_LBrace,
KEY_RBrace,
KEY_Delete,
KEY_UNKNOWN,
KEY_KP_7,
KEY_KP_8,
KEY_KP_9,
KEY_KP_Minus,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_End,
KEY_UNKNOWN,
KEY_LCtrl,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_SemiColon,
KEY_Quote,
KEY_BSlash,
KEY_Enter,
KEY_KP_Enter,
KEY_KP_4,
KEY_KP_5,
KEY_KP_6,
KEY_KP_0,
KEY_UNKNOWN,
KEY_PgUp,
KEY_UNKNOWN,
KEY_NumLock,
KEY_ShiftL,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
KEY_Comma,
KEY_Period,
KEY_Slash,
KEY_ShiftR,
KEY_UNKNOWN,
KEY_KP_1,
KEY_KP_2,
KEY_KP_3,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_UNKNOWN,
KEY_CapsLock,
KEY_LMeta,
KEY_Space,
KEY_RMeta,
KEY_PgDown,
KEY_UNKNOWN,
KEY_KP_Plus,
KEY_UNKNOWN,
KEY_UNKNOWN,
#endif
};
#if defined(KB_USB)
static unsigned char usbmap[256] = {
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_A,
KEY_B,
KEY_C,
KEY_D,
KEY_E,
KEY_F,
KEY_G,
KEY_H,
KEY_I,
KEY_J,
KEY_K,
KEY_L,
KEY_M,
KEY_N,
KEY_O,
KEY_P,
KEY_Q,
KEY_R,
KEY_S,
KEY_T,
KEY_U,
KEY_V,
KEY_W,
KEY_X,
KEY_Y,
KEY_Z,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_Enter,
KEY_Escape,
KEY_BackSpace,
KEY_Tab,
KEY_Space,
KEY_Minus,
KEY_Equal,
KEY_LBrace,
KEY_RBrace,
KEY_BSlash,
KEY_BSlash,
KEY_SemiColon,
KEY_Quote,
KEY_Tilde,
KEY_Comma,
KEY_Period,
KEY_Slash,
KEY_CapsLock,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEY_Print,
KEY_ScrollLock,
KEY_Pause,
KEY_Insert,
KEY_Home,
KEY_PgUp,
KEY_Delete,
KEY_End,
KEY_PgDown,
KEY_Right,
KEY_Left,
KEY_Down,
KEY_Up,
KEY_NumLock,
KEY_KP_Divide,
KEY_KP_Multiply,
KEY_KP_Minus,
KEY_KP_Plus,
KEY_KP_Enter,
KEY_KP_1,
KEY_KP_2,
KEY_KP_3,
KEY_KP_4,
KEY_KP_5,
KEY_KP_6,
KEY_KP_7,
KEY_KP_8,
KEY_KP_9,
KEY_KP_0,
KEY_KP_Decimal,
KEY_Less,
KEY_Menu,
KEY_Power,
KEY_KP_Equal,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_L7,
KEY_Help,
KEY_L3,
KEY_L5,
KEY_L1,
KEY_L2,
KEY_L4,
KEY_L10,
KEY_L6,
KEY_L8,
KEY_L9,
KEY_Mute,
KEY_AudioRaise,
KEY_AudioLower,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_NOTUSED,
KEY_LCtrl,
KEY_ShiftL,
KEY_Alt,
KEY_LMeta,
KEY_RCtrl,
KEY_ShiftR,
KEY_AltLang,
KEY_RMeta,
};
#endif
static void
sunPostKbdEvent(Firm_event *event)
{
Bool down;
KeyClassRec *keyc = ((DeviceIntPtr)xf86Info.pKeyboard)->key;
Bool updateLeds = FALSE;
xEvent kevent;
KeySym *keysym;
int keycode;
static int lockkeys = 0;
if (event->value == VKEY_DOWN)
down = TRUE;
else
down = FALSE;
#if defined(KB_USB)
if(sun_ktype == KB_USB)
keycode = usbmap[event->id];
else
#endif
keycode = map[event->id];
if ((ModifierDown(ControlMask | AltMask)) ||
(ModifierDown(ControlMask | AltLangMask)))
{
switch (keycode) {
case KEY_BackSpace:
if (!xf86Info.dontZap) {
DGAShutdown();
GiveUp(0);
}
break;
case KEY_KP_Divide:
if (!xf86Info.grabInfo.disabled &&
xf86Info.grabInfo.allowDeactivate) {
if (inputInfo.pointer && inputInfo.pointer->grab != NULL &&
inputInfo.pointer->DeactivateGrab)
(*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer);
if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL &&
inputInfo.keyboard->DeactivateGrab)
(*inputInfo.keyboard->DeactivateGrab)(inputInfo.keyboard);
}
break;
case KEY_KP_Multiply:
if (!xf86Info.grabInfo.disabled &&
xf86Info.grabInfo.allowClosedown) {
ClientPtr pointer, keyboard, server;
pointer = keyboard = server = NULL;
if (inputInfo.pointer && inputInfo.pointer->grab != NULL)
pointer =
clients[CLIENT_ID(inputInfo.pointer->grab->resource)];
if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL) {
keyboard =
clients[CLIENT_ID(inputInfo.keyboard->grab->resource)];
if (keyboard == pointer)
keyboard = NULL;
}
if ((xf86Info.grabInfo.server.grabstate == SERVER_GRABBED) &&
(((server = xf86Info.grabInfo.server.client) == pointer) ||
(server == keyboard)))
server = NULL;
if (pointer)
CloseDownClient(pointer);
if (keyboard)
CloseDownClient(keyboard);
if (server)
CloseDownClient(server);
}
break;
case KEY_KP_Minus:
if (!xf86Info.dontZoom) {
if (down)
xf86ZoomViewport(xf86Info.currentScreen, -1);
return;
}
break;
case KEY_KP_Plus:
if (!xf86Info.dontZoom) {
if (down)
xf86ZoomViewport(xf86Info.currentScreen, 1);
return;
}
break;
}
}
if (keycode == KEY_NOTUSED) {
xf86MsgVerb(X_INFO, 0,
"raw code %d mapped to KEY_NOTUSED -- please report\n", event->id);
return;
}
if (keycode == KEY_UNKNOWN) {
xf86MsgVerb(X_INFO, 0,
"raw code %d mapped to KEY_UNKNOWN -- please report\n", event->id);
return;
}
keycode += MIN_KEYCODE;
keysym = keyc->curKeySyms.map +
(keyc->curKeySyms.mapWidth *
(keycode - keyc->curKeySyms.minKeyCode));
#ifdef XKB
if (noXkbExtension)
#endif
{
#define CAPSFLAG 0x01
#define NUMFLAG 0x02
#define SCROLLFLAG 0x04
#define MODEFLAG 0x08
if (down) {
switch (keysym[0]) {
case XK_Caps_Lock:
if (lockkeys & CAPSFLAG) {
lockkeys &= ~CAPSFLAG;
return;
}
lockkeys |= CAPSFLAG;
updateLeds = TRUE;
xf86Info.capsLock = down;
break;
case XK_Num_Lock:
if (lockkeys & NUMFLAG) {
lockkeys &= ~NUMFLAG;
return;
}
lockkeys |= NUMFLAG;
updateLeds = TRUE;
xf86Info.numLock = down;
break;
case XK_Scroll_Lock:
if (lockkeys & SCROLLFLAG) {
lockkeys &= ~SCROLLFLAG;
return;
}
lockkeys |= SCROLLFLAG;
updateLeds = TRUE;
xf86Info.scrollLock = down;
break;
}
} else {
switch (keysym[0]) {
case XK_Caps_Lock:
if (lockkeys & CAPSFLAG)
return;
updateLeds = TRUE;
xf86Info.capsLock = down;
break;
case XK_Num_Lock:
if (lockkeys & NUMFLAG)
return;
updateLeds = TRUE;
xf86Info.numLock = down;
break;
case XK_Scroll_Lock:
if (lockkeys & SCROLLFLAG)
return;
updateLeds = TRUE;
xf86Info.scrollLock = down;
break;
}
}
if (updateLeds)
xf86KbdLeds();
if (!keyc->modifierMap[keycode]) {
if (down) {
startautorepeat(keycode);
} else {
TimerFree(sunTimer);
sunTimer = NULL;
}
}
}
xf86Info.lastEventTime =
kevent.u.keyButtonPointer.time =
GetTimeInMillis();
ENQUEUE(&kevent, keycode, (down ? KeyPress : KeyRelease), XE_KEYBOARD);
}
void
xf86KbdEvents()
{
Firm_event event[64];
int nBytes, i;
if ((nBytes = read(xf86Info.kbdFd, (char *)event, sizeof(event))) > 0)
{
for (i = 0; i < (nBytes / sizeof(Firm_event)); i++)
sunPostKbdEvent(&event[i]);
}
}
void
startautorepeat(long keycode)
{
sunTimer = TimerSet(sunTimer,
0,
xf86Info.kbdDelay,
processautorepeat,
(pointer) keycode);
}
CARD32
processautorepeat(OsTimerPtr timer, CARD32 now, pointer arg)
{
xEvent kevent;
int keycode;
keycode = (long)arg;
xf86Info.lastEventTime =
kevent.u.keyButtonPointer.time =
GetTimeInMillis();
ENQUEUE(&kevent, keycode, KeyRelease, XE_KEYBOARD);
ENQUEUE(&kevent, keycode, KeyPress, XE_KEYBOARD);
return xf86Info.kbdRate;
}