1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun Copyright 1993 by Davor Matic
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software
6*4882a593Smuzhiyun and its documentation for any purpose is hereby granted without fee,
7*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
8*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
9*4882a593Smuzhiyun supporting documentation. Davor Matic makes no representations about
10*4882a593Smuzhiyun the suitability of this software for any purpose. It is provided "as
11*4882a593Smuzhiyun is" without express or implied warranty.
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #ifdef HAVE_XNEST_CONFIG_H
16*4882a593Smuzhiyun #include <xnest-config.h>
17*4882a593Smuzhiyun #endif
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #ifdef WIN32
20*4882a593Smuzhiyun #include <X11/Xwindows.h>
21*4882a593Smuzhiyun #endif
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include <X11/X.h>
24*4882a593Smuzhiyun #include <X11/Xproto.h>
25*4882a593Smuzhiyun #include <X11/keysym.h>
26*4882a593Smuzhiyun #include "screenint.h"
27*4882a593Smuzhiyun #include "inputstr.h"
28*4882a593Smuzhiyun #include "misc.h"
29*4882a593Smuzhiyun #include "scrnintstr.h"
30*4882a593Smuzhiyun #include "servermd.h"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #include "Xnest.h"
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include "Display.h"
35*4882a593Smuzhiyun #include "Screen.h"
36*4882a593Smuzhiyun #include "Keyboard.h"
37*4882a593Smuzhiyun #include "Args.h"
38*4882a593Smuzhiyun #include "Events.h"
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #include <X11/extensions/XKB.h>
41*4882a593Smuzhiyun #include "xkbsrv.h"
42*4882a593Smuzhiyun #include <X11/extensions/XKBconfig.h>
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun extern Bool
45*4882a593Smuzhiyun XkbQueryExtension(Display * /* dpy */ ,
46*4882a593Smuzhiyun int * /* opcodeReturn */ ,
47*4882a593Smuzhiyun int * /* eventBaseReturn */ ,
48*4882a593Smuzhiyun int * /* errorBaseReturn */ ,
49*4882a593Smuzhiyun int * /* majorRtrn */ ,
50*4882a593Smuzhiyun int * /* minorRtrn */
51*4882a593Smuzhiyun );
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun extern XkbDescPtr XkbGetKeyboard(Display * /* dpy */ ,
54*4882a593Smuzhiyun unsigned int /* which */ ,
55*4882a593Smuzhiyun unsigned int /* deviceSpec */
56*4882a593Smuzhiyun );
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun extern Status XkbGetControls(Display * /* dpy */ ,
59*4882a593Smuzhiyun unsigned long /* which */ ,
60*4882a593Smuzhiyun XkbDescPtr /* desc */
61*4882a593Smuzhiyun );
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun DeviceIntPtr xnestKeyboardDevice = NULL;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun void
xnestBell(int volume,DeviceIntPtr pDev,void * ctrl,int cls)66*4882a593Smuzhiyun xnestBell(int volume, DeviceIntPtr pDev, void *ctrl, int cls)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun XBell(xnestDisplay, volume);
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun void
DDXRingBell(int volume,int pitch,int duration)72*4882a593Smuzhiyun DDXRingBell(int volume, int pitch, int duration)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun XBell(xnestDisplay, volume);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun void
xnestChangeKeyboardControl(DeviceIntPtr pDev,KeybdCtrl * ctrl)78*4882a593Smuzhiyun xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl * ctrl)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun #if 0
81*4882a593Smuzhiyun unsigned long value_mask;
82*4882a593Smuzhiyun XKeyboardControl values;
83*4882a593Smuzhiyun int i;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun value_mask = KBKeyClickPercent |
86*4882a593Smuzhiyun KBBellPercent | KBBellPitch | KBBellDuration | KBAutoRepeatMode;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun values.key_click_percent = ctrl->click;
89*4882a593Smuzhiyun values.bell_percent = ctrl->bell;
90*4882a593Smuzhiyun values.bell_pitch = ctrl->bell_pitch;
91*4882a593Smuzhiyun values.bell_duration = ctrl->bell_duration;
92*4882a593Smuzhiyun values.auto_repeat_mode = ctrl->autoRepeat ?
93*4882a593Smuzhiyun AutoRepeatModeOn : AutoRepeatModeOff;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun XChangeKeyboardControl(xnestDisplay, value_mask, &values);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /*
98*4882a593Smuzhiyun value_mask = KBKey | KBAutoRepeatMode;
99*4882a593Smuzhiyun At this point, we need to walk through the vector and compare it
100*4882a593Smuzhiyun to the current server vector. If there are differences, report them.
101*4882a593Smuzhiyun */
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun value_mask = KBLed | KBLedMode;
104*4882a593Smuzhiyun for (i = 1; i <= 32; i++) {
105*4882a593Smuzhiyun values.led = i;
106*4882a593Smuzhiyun values.led_mode =
107*4882a593Smuzhiyun (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff;
108*4882a593Smuzhiyun XChangeKeyboardControl(xnestDisplay, value_mask, &values);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun #endif
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun int
xnestKeyboardProc(DeviceIntPtr pDev,int onoff)114*4882a593Smuzhiyun xnestKeyboardProc(DeviceIntPtr pDev, int onoff)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun XModifierKeymap *modifier_keymap;
117*4882a593Smuzhiyun KeySym *keymap;
118*4882a593Smuzhiyun int mapWidth;
119*4882a593Smuzhiyun int min_keycode, max_keycode;
120*4882a593Smuzhiyun KeySymsRec keySyms;
121*4882a593Smuzhiyun CARD8 modmap[MAP_LENGTH];
122*4882a593Smuzhiyun int i, j;
123*4882a593Smuzhiyun XKeyboardState values;
124*4882a593Smuzhiyun XkbDescPtr xkb;
125*4882a593Smuzhiyun int op, event, error, major, minor;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun switch (onoff) {
128*4882a593Smuzhiyun case DEVICE_INIT:
129*4882a593Smuzhiyun XDisplayKeycodes(xnestDisplay, &min_keycode, &max_keycode);
130*4882a593Smuzhiyun #ifdef _XSERVER64
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun KeySym64 *keymap64;
133*4882a593Smuzhiyun int len;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun keymap64 = XGetKeyboardMapping(xnestDisplay,
136*4882a593Smuzhiyun min_keycode,
137*4882a593Smuzhiyun max_keycode - min_keycode + 1,
138*4882a593Smuzhiyun &mapWidth);
139*4882a593Smuzhiyun len = (max_keycode - min_keycode + 1) * mapWidth;
140*4882a593Smuzhiyun keymap = xallocarray(len, sizeof(KeySym));
141*4882a593Smuzhiyun for (i = 0; i < len; ++i)
142*4882a593Smuzhiyun keymap[i] = keymap64[i];
143*4882a593Smuzhiyun XFree(keymap64);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun #else
146*4882a593Smuzhiyun keymap = XGetKeyboardMapping(xnestDisplay,
147*4882a593Smuzhiyun min_keycode,
148*4882a593Smuzhiyun max_keycode - min_keycode + 1, &mapWidth);
149*4882a593Smuzhiyun #endif
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun memset(modmap, 0, sizeof(modmap));
152*4882a593Smuzhiyun modifier_keymap = XGetModifierMapping(xnestDisplay);
153*4882a593Smuzhiyun for (j = 0; j < 8; j++)
154*4882a593Smuzhiyun for (i = 0; i < modifier_keymap->max_keypermod; i++) {
155*4882a593Smuzhiyun CARD8 keycode;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun if ((keycode =
158*4882a593Smuzhiyun modifier_keymap->modifiermap[j *
159*4882a593Smuzhiyun modifier_keymap->
160*4882a593Smuzhiyun max_keypermod + i]))
161*4882a593Smuzhiyun modmap[keycode] |= 1 << j;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun XFreeModifiermap(modifier_keymap);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun keySyms.minKeyCode = min_keycode;
166*4882a593Smuzhiyun keySyms.maxKeyCode = max_keycode;
167*4882a593Smuzhiyun keySyms.mapWidth = mapWidth;
168*4882a593Smuzhiyun keySyms.map = keymap;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun if (XkbQueryExtension(xnestDisplay, &op, &event, &error, &major, &minor)
171*4882a593Smuzhiyun == 0) {
172*4882a593Smuzhiyun ErrorF("Unable to initialize XKEYBOARD extension.\n");
173*4882a593Smuzhiyun goto XkbError;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun xkb =
176*4882a593Smuzhiyun XkbGetKeyboard(xnestDisplay, XkbGBN_AllComponentsMask,
177*4882a593Smuzhiyun XkbUseCoreKbd);
178*4882a593Smuzhiyun if (xkb == NULL || xkb->geom == NULL) {
179*4882a593Smuzhiyun ErrorF("Couldn't get keyboard.\n");
180*4882a593Smuzhiyun goto XkbError;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun InitKeyboardDeviceStruct(pDev, NULL,
185*4882a593Smuzhiyun xnestBell, xnestChangeKeyboardControl);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode,
188*4882a593Smuzhiyun keySyms.maxKeyCode - keySyms.minKeyCode + 1,
189*4882a593Smuzhiyun modmap, serverClient);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls);
192*4882a593Smuzhiyun XkbFreeKeyboard(xkb, 0, False);
193*4882a593Smuzhiyun free(keymap);
194*4882a593Smuzhiyun break;
195*4882a593Smuzhiyun case DEVICE_ON:
196*4882a593Smuzhiyun xnestEventMask |= XNEST_KEYBOARD_EVENT_MASK;
197*4882a593Smuzhiyun for (i = 0; i < xnestNumScreens; i++)
198*4882a593Smuzhiyun XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask);
199*4882a593Smuzhiyun break;
200*4882a593Smuzhiyun case DEVICE_OFF:
201*4882a593Smuzhiyun xnestEventMask &= ~XNEST_KEYBOARD_EVENT_MASK;
202*4882a593Smuzhiyun for (i = 0; i < xnestNumScreens; i++)
203*4882a593Smuzhiyun XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask);
204*4882a593Smuzhiyun break;
205*4882a593Smuzhiyun case DEVICE_CLOSE:
206*4882a593Smuzhiyun break;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun return Success;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun XkbError:
211*4882a593Smuzhiyun XGetKeyboardControl(xnestDisplay, &values);
212*4882a593Smuzhiyun memmove((char *) defaultKeyboardControl.autoRepeats,
213*4882a593Smuzhiyun (char *) values.auto_repeats, sizeof(values.auto_repeats));
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun InitKeyboardDeviceStruct(pDev, NULL, xnestBell, xnestChangeKeyboardControl);
216*4882a593Smuzhiyun free(keymap);
217*4882a593Smuzhiyun return Success;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun Bool
LegalModifier(unsigned int key,DeviceIntPtr pDev)221*4882a593Smuzhiyun LegalModifier(unsigned int key, DeviceIntPtr pDev)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun return TRUE;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun void
xnestUpdateModifierState(unsigned int state)227*4882a593Smuzhiyun xnestUpdateModifierState(unsigned int state)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun DeviceIntPtr pDev = xnestKeyboardDevice;
230*4882a593Smuzhiyun KeyClassPtr keyc = pDev->key;
231*4882a593Smuzhiyun int i;
232*4882a593Smuzhiyun CARD8 mask;
233*4882a593Smuzhiyun int xkb_state;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun if (!pDev)
236*4882a593Smuzhiyun return;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state);
239*4882a593Smuzhiyun state = state & 0xff;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun if (xkb_state == state)
242*4882a593Smuzhiyun return;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
245*4882a593Smuzhiyun int key;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /* Modifier is down, but shouldn't be
248*4882a593Smuzhiyun */
249*4882a593Smuzhiyun if ((xkb_state & mask) && !(state & mask)) {
250*4882a593Smuzhiyun int count = keyc->modifierKeyCount[i];
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun for (key = 0; key < MAP_LENGTH; key++)
253*4882a593Smuzhiyun if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
254*4882a593Smuzhiyun if (mask == LockMask) {
255*4882a593Smuzhiyun xnestQueueKeyEvent(KeyPress, key);
256*4882a593Smuzhiyun xnestQueueKeyEvent(KeyRelease, key);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun else if (key_is_down(pDev, key, KEY_PROCESSED))
259*4882a593Smuzhiyun xnestQueueKeyEvent(KeyRelease, key);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if (--count == 0)
262*4882a593Smuzhiyun break;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /* Modifier shoud be down, but isn't
267*4882a593Smuzhiyun */
268*4882a593Smuzhiyun if (!(xkb_state & mask) && (state & mask))
269*4882a593Smuzhiyun for (key = 0; key < MAP_LENGTH; key++)
270*4882a593Smuzhiyun if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
271*4882a593Smuzhiyun xnestQueueKeyEvent(KeyPress, key);
272*4882a593Smuzhiyun if (mask == LockMask)
273*4882a593Smuzhiyun xnestQueueKeyEvent(KeyRelease, key);
274*4882a593Smuzhiyun break;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun }
278