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