269 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 | 
						|
Copyright 1993 by Davor Matic
 | 
						|
 | 
						|
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.  Davor Matic makes no representations about
 | 
						|
the suitability of this software for any purpose.  It is provided "as
 | 
						|
is" without express or implied warranty.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
#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 *		/* dpy */,
 | 
						|
	int *			/* opcodeReturn */,
 | 
						|
	int *			/* eventBaseReturn */,
 | 
						|
	int *			/* errorBaseReturn */,
 | 
						|
	int *			/* majorRtrn */,
 | 
						|
	int *			/* minorRtrn */
 | 
						|
);
 | 
						|
 | 
						|
extern	XkbDescPtr XkbGetKeyboard(
 | 
						|
	Display *		/* dpy */,
 | 
						|
	unsigned int		/* which */,
 | 
						|
	unsigned int		/* deviceSpec */
 | 
						|
);
 | 
						|
 | 
						|
extern	Status	XkbGetControls(
 | 
						|
	Display *		/* dpy */,
 | 
						|
	unsigned long		/* which */,
 | 
						|
	XkbDescPtr		/* desc */
 | 
						|
);
 | 
						|
 | 
						|
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 = KBKey | KBAutoRepeatMode;
 | 
						|
  At this point, we need to walk through the vector and compare it
 | 
						|
  to the current server vector.  If there are differences, report them.
 | 
						|
  */
 | 
						|
 | 
						|
  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;
 | 
						|
 | 
						|
    /* Modifier is down, but shouldn't be
 | 
						|
     */
 | 
						|
    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;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    /* Modifier shoud be down, but isn't
 | 
						|
     */
 | 
						|
    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;
 | 
						|
	}
 | 
						|
  }
 | 
						|
}
 |