269 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			6.5 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)
 | |
| {
 | |
|   KeySym *keymap;
 | |
|   int mapWidth;
 | |
|   int min_keycode, max_keycode;
 | |
|   KeySymsRec keySyms;
 | |
|   int i;
 | |
|   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 i, len;
 | |
| 	keymap64 = XGetKeyboardMapping(xnestDisplay,
 | |
| 				     min_keycode,
 | |
| 				     max_keycode - min_keycode + 1,
 | |
| 				     &mapWidth);
 | |
| 	len = (max_keycode - min_keycode + 1) * mapWidth;
 | |
| 	keymap = (KeySym *)xalloc(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
 | |
|       
 | |
|       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);
 | |
|       XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls);
 | |
|       XkbFreeKeyboard(xkb, 0, False);
 | |
|       xfree(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->public, &keySyms,
 | |
|                            xnestBell, xnestChangeKeyboardControl);
 | |
|   xfree(keymap);
 | |
|   return Success;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| LegalModifier(unsigned int key, DeviceIntPtr pDev)
 | |
| {
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| void
 | |
| xnestUpdateModifierState(unsigned int state)
 | |
| {
 | |
| #if 0
 | |
|   DeviceIntPtr pDev = xnestKeyboardDevice;
 | |
|   KeyClassPtr keyc = pDev->key;
 | |
|   int i;
 | |
|   CARD8 mask;
 | |
| 
 | |
|   if (!pDev)
 | |
|       return;
 | |
| 
 | |
| /* This is pretty broken.
 | |
|  *
 | |
|  * What should happen is that focus out should do as a VT switch does in
 | |
|  * traditional servers: fake releases for all keys (and buttons too, come
 | |
|  * to think of it) currently down.  Then, on focus in, get the state from
 | |
|  * the host, and fake keypresses for everything currently down.
 | |
|  *
 | |
|  * So I'm leaving this broken for a little while.  Sorry, folks.
 | |
|  *
 | |
|  * -daniels
 | |
|  */
 | |
|   state = state & 0xff;
 | |
| 
 | |
|   if (keyc->state == state)
 | |
|     return;
 | |
| 
 | |
|   for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
 | |
|     int key;
 | |
| 
 | |
|     /* Modifier is down, but shouldn't be
 | |
|      */
 | |
|     if ((keyc->state & mask) && !(state & mask)) {
 | |
|       int count = keyc->modifierKeyCount[i];
 | |
| 
 | |
|       for (key = 0; key < MAP_LENGTH; key++)
 | |
| 	if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
 | |
| 	  int bit;
 | |
| 	  BYTE *kptr;
 | |
| 
 | |
| 	  kptr = &keyc->down[key >> 3];
 | |
| 	  bit = 1 << (key & 7);
 | |
| 
 | |
| 	  if (*kptr & bit)
 | |
| 	    xnestQueueKeyEvent(KeyRelease, key);
 | |
| 
 | |
| 	  if (--count == 0)
 | |
| 	    break;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     /* Modifier shoud be down, but isn't
 | |
|      */
 | |
|     if (!(keyc->state & mask) && (state & mask))
 | |
|       for (key = 0; key < MAP_LENGTH; key++)
 | |
| 	if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
 | |
| 	  xnestQueueKeyEvent(KeyPress, key);
 | |
| 	  break;
 | |
| 	}
 | |
|   }
 | |
| #endif
 | |
| }
 |