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