#ifdef HAVE_XNEST_CONFIG_H
#include <xnest-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include <X11/keysym.h>
#include "screenint.h"
#include "inputstr.h"
#include "misc.h"
#include "scrnintstr.h"
#include "servermd.h"
#include "Xnest.h"
#include "Display.h"
#include "Screen.h"
#include "Keyboard.h"
#include "Args.h"
#include "Events.h"
#include <X11/extensions/XKB.h>
#include "xkbsrv.h"
#include <X11/extensions/XKBconfig.h>
extern Bool
XkbQueryExtension(
Display * ,
int * ,
int * ,
int * ,
int * ,
int *
);
extern XkbDescPtr XkbGetKeyboard(
Display * ,
unsigned int ,
unsigned int
);
extern Status XkbGetControls(
Display * ,
unsigned long ,
XkbDescPtr
);
DeviceIntPtr xnestKeyboardDevice = NULL;
void
xnestBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls)
{
XBell(xnestDisplay, volume);
}
void
DDXRingBell(int volume, int pitch, int duration)
{
XBell(xnestDisplay, volume);
}
void
xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
{
#if 0
unsigned long value_mask;
XKeyboardControl values;
int i;
value_mask = KBKeyClickPercent |
KBBellPercent |
KBBellPitch |
KBBellDuration |
KBAutoRepeatMode;
values.key_click_percent = ctrl->click;
values.bell_percent = ctrl->bell;
values.bell_pitch = ctrl->bell_pitch;
values.bell_duration = ctrl->bell_duration;
values.auto_repeat_mode = ctrl->autoRepeat ?
AutoRepeatModeOn : AutoRepeatModeOff;
XChangeKeyboardControl(xnestDisplay, value_mask, &values);
value_mask = KBLed | KBLedMode;
for (i = 1; i <= 32; i++) {
values.led = i;
values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff;
XChangeKeyboardControl(xnestDisplay, value_mask, &values);
}
#endif
}
int
xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
{
XModifierKeymap *modifier_keymap;
KeySym *keymap;
int mapWidth;
int min_keycode, max_keycode;
KeySymsRec keySyms;
CARD8 modmap[MAP_LENGTH];
int i, j;
XKeyboardState values;
XkbDescPtr xkb;
int op, event, error, major, minor;
switch (onoff)
{
case DEVICE_INIT:
XDisplayKeycodes(xnestDisplay, &min_keycode, &max_keycode);
#ifdef _XSERVER64
{
KeySym64 *keymap64;
int len;
keymap64 = XGetKeyboardMapping(xnestDisplay,
min_keycode,
max_keycode - min_keycode + 1,
&mapWidth);
len = (max_keycode - min_keycode + 1) * mapWidth;
keymap = (KeySym *)malloc(len * sizeof(KeySym));
for(i = 0; i < len; ++i)
keymap[i] = keymap64[i];
XFree(keymap64);
}
#else
keymap = XGetKeyboardMapping(xnestDisplay,
min_keycode,
max_keycode - min_keycode + 1,
&mapWidth);
#endif
memset(modmap, 0, sizeof(modmap));
modifier_keymap = XGetModifierMapping(xnestDisplay);
for (j = 0; j < 8; j++)
for(i = 0; i < modifier_keymap->max_keypermod; i++) {
CARD8 keycode;
if ((keycode = modifier_keymap->modifiermap[j * modifier_keymap->max_keypermod + i]))
modmap[keycode] |= 1<<j;
}
XFreeModifiermap(modifier_keymap);
keySyms.minKeyCode = min_keycode;
keySyms.maxKeyCode = max_keycode;
keySyms.mapWidth = mapWidth;
keySyms.map = keymap;
if (XkbQueryExtension(xnestDisplay, &op, &event, &error, &major, &minor) == 0) {
ErrorF("Unable to initialize XKEYBOARD extension.\n");
goto XkbError;
}
xkb = XkbGetKeyboard(xnestDisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd);
if (xkb == NULL || xkb->geom == NULL) {
ErrorF("Couldn't get keyboard.\n");
goto XkbError;
}
XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb);
InitKeyboardDeviceStruct(pDev, NULL,
xnestBell, xnestChangeKeyboardControl);
XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode,
keySyms.maxKeyCode - keySyms.minKeyCode + 1,
modmap, serverClient);
XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls);
XkbFreeKeyboard(xkb, 0, False);
free(keymap);
break;
case DEVICE_ON:
xnestEventMask |= XNEST_KEYBOARD_EVENT_MASK;
for (i = 0; i < xnestNumScreens; i++)
XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask);
break;
case DEVICE_OFF:
xnestEventMask &= ~XNEST_KEYBOARD_EVENT_MASK;
for (i = 0; i < xnestNumScreens; i++)
XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask);
break;
case DEVICE_CLOSE:
break;
}
return Success;
XkbError:
XGetKeyboardControl(xnestDisplay, &values);
memmove((char *)defaultKeyboardControl.autoRepeats,
(char *)values.auto_repeats,
sizeof(values.auto_repeats));
InitKeyboardDeviceStruct(pDev, NULL,
xnestBell, xnestChangeKeyboardControl);
free(keymap);
return Success;
}
Bool
LegalModifier(unsigned int key, DeviceIntPtr pDev)
{
return TRUE;
}
void
xnestUpdateModifierState(unsigned int state)
{
DeviceIntPtr pDev = xnestKeyboardDevice;
KeyClassPtr keyc = pDev->key;
int i;
CARD8 mask;
int xkb_state;
if (!pDev)
return;
xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state);
state = state & 0xff;
if (xkb_state == state)
return;
for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
int key;
if ((xkb_state & mask) && !(state & mask)) {
int count = keyc->modifierKeyCount[i];
for (key = 0; key < MAP_LENGTH; key++)
if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
if (key_is_down(pDev, key, KEY_PROCESSED))
xnestQueueKeyEvent(KeyRelease, key);
if (--count == 0)
break;
}
}
if (!(xkb_state & mask) && (state & mask))
for (key = 0; key < MAP_LENGTH; key++)
if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
xnestQueueKeyEvent(KeyPress, key);
break;
}
}
}