~ubuntu-branches/ubuntu/vivid/freerdp/vivid

« back to all changes in this revision

Viewing changes to libfreerdp/locale/keyboard_xkbfile.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-11-11 12:20:50 UTC
  • mfrom: (1.1.9) (9.1.17 sid)
  • Revision ID: package-import@ubuntu.com-20141111122050-wyr8hrnwco9fcmum
Tags: 1.1.0~git20140921.1.440916e+dfsg1-2ubuntu1
* Merge with Debian unstable, remaining changes
  - Disable ffmpeg support
* Disable gstreamer support, this relies on gstreamer 0.10 and we don't want
  to add any more deps on that.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * FreeRDP: A Remote Desktop Protocol Implementation
 
3
 * XKB Keyboard Mapping
 
4
 *
 
5
 * Copyright 2009-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
 
6
 *
 
7
 * Licensed under the Apache License, Version 2.0 (the "License");
 
8
 * you may not use this file except in compliance with the License.
 
9
 * You may obtain a copy of the License at
 
10
 *
 
11
 *     http://www.apache.org/licenses/LICENSE-2.0
 
12
 *
 
13
 * Unless required by applicable law or agreed to in writing, software
 
14
 * distributed under the License is distributed on an "AS IS" BASIS,
 
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
16
 * See the License for the specific language governing permissions and
 
17
 * limitations under the License.
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include "keyboard_xkbfile.h"
 
25
 
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
 
 
30
#include <winpr/crt.h>
 
31
#include <winpr/input.h>
 
32
 
 
33
#include <freerdp/locale/keyboard.h>
 
34
 
 
35
#include "keyboard_x11.h"
 
36
#include "xkb_layout_ids.h"
 
37
#include "liblocale.h"
 
38
 
 
39
#include <X11/Xlib.h>
 
40
#include <X11/XKBlib.h>
 
41
#include <X11/extensions/XKBfile.h>
 
42
#include <X11/extensions/XKBrules.h>
 
43
 
 
44
struct _XKB_KEY_NAME_SCANCODE
 
45
{
 
46
        const char* xkb_keyname; /* XKB keyname */
 
47
        DWORD rdp_scancode;
 
48
};
 
49
typedef struct _XKB_KEY_NAME_SCANCODE XKB_KEY_NAME_SCANCODE;
 
50
 
 
51
XKB_KEY_NAME_SCANCODE XKB_KEY_NAME_SCANCODE_TABLE[] =
 
52
{
 
53
        { "BKSP",       RDP_SCANCODE_BACKSPACE},
 
54
        { "TAB",        RDP_SCANCODE_TAB},
 
55
        { "RTRN",       RDP_SCANCODE_RETURN}, // not KP
 
56
        { "LFSH",       RDP_SCANCODE_LSHIFT},
 
57
        { "LALT",       RDP_SCANCODE_LMENU},
 
58
        { "CAPS",       RDP_SCANCODE_CAPSLOCK},
 
59
        { "ESC",        RDP_SCANCODE_ESCAPE},
 
60
        { "SPCE",       RDP_SCANCODE_SPACE},
 
61
        { "AE10",       RDP_SCANCODE_KEY_0},
 
62
        { "AE01",       RDP_SCANCODE_KEY_1},
 
63
        { "AE02",       RDP_SCANCODE_KEY_2},
 
64
        { "AE03",       RDP_SCANCODE_KEY_3},
 
65
        { "AE04",       RDP_SCANCODE_KEY_4},
 
66
        { "AE05",       RDP_SCANCODE_KEY_5},
 
67
        { "AE06",       RDP_SCANCODE_KEY_6},
 
68
        { "AE07",       RDP_SCANCODE_KEY_7},
 
69
        { "AE08",       RDP_SCANCODE_KEY_8},
 
70
        { "AE09",       RDP_SCANCODE_KEY_9},
 
71
        { "AC01",       RDP_SCANCODE_KEY_A},
 
72
        { "AB05",       RDP_SCANCODE_KEY_B},
 
73
        { "AB03",       RDP_SCANCODE_KEY_C},
 
74
        { "AC03",       RDP_SCANCODE_KEY_D},
 
75
        { "AD03",       RDP_SCANCODE_KEY_E},
 
76
        { "AC04",       RDP_SCANCODE_KEY_F},
 
77
        { "AC05",       RDP_SCANCODE_KEY_G},
 
78
        { "AC06",       RDP_SCANCODE_KEY_H},
 
79
        { "AD08",       RDP_SCANCODE_KEY_I},
 
80
        { "AC07",       RDP_SCANCODE_KEY_J},
 
81
        { "AC08",       RDP_SCANCODE_KEY_K},
 
82
        { "AC09",       RDP_SCANCODE_KEY_L},
 
83
        { "AB07",       RDP_SCANCODE_KEY_M},
 
84
        { "AB06",       RDP_SCANCODE_KEY_N},
 
85
        { "AD09",       RDP_SCANCODE_KEY_O},
 
86
        { "AD10",       RDP_SCANCODE_KEY_P},
 
87
        { "AD01",       RDP_SCANCODE_KEY_Q},
 
88
        { "AD04",       RDP_SCANCODE_KEY_R},
 
89
        { "AC02",       RDP_SCANCODE_KEY_S},
 
90
        { "AD05",       RDP_SCANCODE_KEY_T},
 
91
        { "AD07",       RDP_SCANCODE_KEY_U},
 
92
        { "AB04",       RDP_SCANCODE_KEY_V},
 
93
        { "AD02",       RDP_SCANCODE_KEY_W},
 
94
        { "AB02",       RDP_SCANCODE_KEY_X},
 
95
        { "AD06",       RDP_SCANCODE_KEY_Y},
 
96
        { "AB01",       RDP_SCANCODE_KEY_Z},
 
97
        { "KP0",        RDP_SCANCODE_NUMPAD0},
 
98
        { "KP1",        RDP_SCANCODE_NUMPAD1},
 
99
        { "KP2",        RDP_SCANCODE_NUMPAD2},
 
100
        { "KP3",        RDP_SCANCODE_NUMPAD3},
 
101
        { "KP4",        RDP_SCANCODE_NUMPAD4},
 
102
        { "KP5",        RDP_SCANCODE_NUMPAD5},
 
103
        { "KP6",        RDP_SCANCODE_NUMPAD6},
 
104
        { "KP7",        RDP_SCANCODE_NUMPAD7},
 
105
        { "KP8",        RDP_SCANCODE_NUMPAD8},
 
106
        { "KP9",        RDP_SCANCODE_NUMPAD9},
 
107
        { "KPMU",       RDP_SCANCODE_MULTIPLY},
 
108
        { "KPAD",       RDP_SCANCODE_ADD},
 
109
        { "KPSU",       RDP_SCANCODE_SUBTRACT},
 
110
        { "KPDL",       RDP_SCANCODE_DECIMAL},
 
111
        { "AB10",       RDP_SCANCODE_OEM_2}, // not KP, not RDP_SCANCODE_DIVIDE
 
112
        { "FK01",       RDP_SCANCODE_F1},
 
113
        { "FK02",       RDP_SCANCODE_F2},
 
114
        { "FK03",       RDP_SCANCODE_F3},
 
115
        { "FK04",       RDP_SCANCODE_F4},
 
116
        { "FK05",       RDP_SCANCODE_F5},
 
117
        { "FK06",       RDP_SCANCODE_F6},
 
118
        { "FK07",       RDP_SCANCODE_F7},
 
119
        { "FK08",       RDP_SCANCODE_F8},
 
120
        { "FK09",       RDP_SCANCODE_F9},
 
121
        { "FK10",       RDP_SCANCODE_F10},
 
122
        { "FK11",       RDP_SCANCODE_F11},
 
123
        { "FK12",       RDP_SCANCODE_F12},
 
124
        { "NMLK",       RDP_SCANCODE_NUMLOCK},
 
125
        { "SCLK",       RDP_SCANCODE_SCROLLLOCK},
 
126
        { "RTSH",       RDP_SCANCODE_RSHIFT},
 
127
        { "LCTL",       RDP_SCANCODE_LCONTROL},
 
128
        { "AC10",       RDP_SCANCODE_OEM_1},
 
129
        { "AE12",       RDP_SCANCODE_OEM_PLUS},
 
130
        { "AB08",       RDP_SCANCODE_OEM_COMMA},
 
131
        { "AE11",       RDP_SCANCODE_OEM_MINUS},
 
132
        { "AB09",       RDP_SCANCODE_OEM_PERIOD},
 
133
        { "TLDE",       RDP_SCANCODE_OEM_3},
 
134
        { "AB11",       RDP_SCANCODE_ABNT_C1},
 
135
        { "I129",       RDP_SCANCODE_ABNT_C2},
 
136
        { "AD11",       RDP_SCANCODE_OEM_4},
 
137
        { "BKSL",       RDP_SCANCODE_OEM_5},
 
138
        { "AD12",       RDP_SCANCODE_OEM_6},
 
139
        { "AC11",       RDP_SCANCODE_OEM_7},
 
140
        { "LSGT",       RDP_SCANCODE_OEM_102},
 
141
        { "KPEN",       RDP_SCANCODE_RETURN_KP}, // KP!
 
142
        { "PAUS",       RDP_SCANCODE_PAUSE},
 
143
        { "PGUP",       RDP_SCANCODE_PRIOR},
 
144
        { "PGDN",       RDP_SCANCODE_NEXT},
 
145
        { "END",        RDP_SCANCODE_END},
 
146
        { "HOME",       RDP_SCANCODE_HOME},
 
147
        { "LEFT",       RDP_SCANCODE_LEFT},
 
148
        { "UP",         RDP_SCANCODE_UP},
 
149
        { "RGHT",       RDP_SCANCODE_RIGHT},
 
150
        { "DOWN",       RDP_SCANCODE_DOWN},
 
151
        { "PRSC",       RDP_SCANCODE_PRINTSCREEN},
 
152
        { "INS",        RDP_SCANCODE_INSERT},
 
153
        { "DELE",       RDP_SCANCODE_DELETE},
 
154
        { "LWIN",       RDP_SCANCODE_LWIN},
 
155
        { "RWIN",       RDP_SCANCODE_RWIN},
 
156
        { "COMP",       RDP_SCANCODE_APPS},
 
157
        { "MENU",       RDP_SCANCODE_APPS}, // WinMenu in xfree86 layout
 
158
        { "KPDV",       RDP_SCANCODE_DIVIDE}, // KP!
 
159
        { "RCTL",       RDP_SCANCODE_RCONTROL},
 
160
        { "RALT",       RDP_SCANCODE_RMENU},
 
161
        { "AE13",       RDP_SCANCODE_BACKSLASH_JP}, // JP
 
162
        { "HKTG",       RDP_SCANCODE_HIRAGANA}, // JP
 
163
        { "HENK",       RDP_SCANCODE_CONVERT_JP}, // JP
 
164
        { "MUHE",       RDP_SCANCODE_NONCONVERT_JP} // JP
 
165
/*      { "LVL3",       0x54} */
 
166
};
 
167
 
 
168
void* freerdp_keyboard_xkb_init()
 
169
{
 
170
        int status;
 
171
 
 
172
        Display* display = XOpenDisplay(NULL);
 
173
 
 
174
        if (!display)
 
175
                return NULL;
 
176
 
 
177
        status = XkbQueryExtension(display, NULL, NULL, NULL, NULL, NULL);
 
178
 
 
179
        if (!status)
 
180
                return NULL;
 
181
 
 
182
        return (void*) display;
 
183
}
 
184
 
 
185
int freerdp_keyboard_init_xkbfile(DWORD* keyboardLayoutId, DWORD x11_keycode_to_rdp_scancode[256])
 
186
{
 
187
        void* display;
 
188
 
 
189
        ZeroMemory(x11_keycode_to_rdp_scancode, sizeof(DWORD) * 256);
 
190
 
 
191
        display = freerdp_keyboard_xkb_init();
 
192
 
 
193
        if (!display)
 
194
        {
 
195
                DEBUG_KBD("Error initializing xkb");
 
196
                return -1;
 
197
        }
 
198
 
 
199
        if (*keyboardLayoutId == 0)
 
200
        {
 
201
                detect_keyboard_layout_from_xkbfile(display, keyboardLayoutId);
 
202
                DEBUG_KBD("detect_keyboard_layout_from_xkb: %X", keyboardLayoutId);
 
203
        }
 
204
 
 
205
        freerdp_keyboard_load_map_from_xkbfile(display, x11_keycode_to_rdp_scancode);
 
206
 
 
207
        XCloseDisplay(display);
 
208
 
 
209
        return 0;
 
210
}
 
211
 
 
212
/* return substring starting after nth comma, ending at following comma */
 
213
static char* comma_substring(char* s, int n)
 
214
{
 
215
        char* p;
 
216
 
 
217
        if (!s)
 
218
                return "";
 
219
 
 
220
        while (n-- > 0)
 
221
        {
 
222
                if (!(p = strchr(s, ',')))
 
223
                        break;
 
224
 
 
225
                s = p + 1;
 
226
        }
 
227
 
 
228
        if ((p = strchr(s, ',')))
 
229
                *p = 0;
 
230
 
 
231
        return s;
 
232
}
 
233
 
 
234
int detect_keyboard_layout_from_xkbfile(void* display, DWORD* keyboardLayoutId)
 
235
{
 
236
        char* layout;
 
237
        char* variant;
 
238
        DWORD group = 0;
 
239
        XkbStateRec state;
 
240
        XKeyboardState coreKbdState;
 
241
        XkbRF_VarDefsRec rules_names;
 
242
 
 
243
        DEBUG_KBD("display: %p", display);
 
244
 
 
245
        if (display && XkbRF_GetNamesProp(display, NULL, &rules_names))
 
246
        {
 
247
                DEBUG_KBD("layouts: %s", rules_names.layout ? rules_names.layout : "");
 
248
                DEBUG_KBD("variants: %s", rules_names.variant ? rules_names.variant : "");
 
249
 
 
250
                XGetKeyboardControl(display, &coreKbdState);
 
251
 
 
252
                if (XkbGetState(display, XkbUseCoreKbd, &state) == Success)
 
253
                        group = state.group;
 
254
 
 
255
                DEBUG_KBD("group: %d", state.group);
 
256
 
 
257
                layout = comma_substring(rules_names.layout, group);
 
258
                variant = comma_substring(rules_names.variant, group);
 
259
 
 
260
                DEBUG_KBD("layout: %s", layout ? layout : "");
 
261
                DEBUG_KBD("variant: %s", variant ? variant : "");
 
262
 
 
263
                *keyboardLayoutId = find_keyboard_layout_in_xorg_rules(layout, variant);
 
264
 
 
265
                free(rules_names.model);
 
266
                free(rules_names.layout);
 
267
                free(rules_names.variant);
 
268
                free(rules_names.options);
 
269
        }
 
270
 
 
271
        return 0;
 
272
}
 
273
 
 
274
int freerdp_keyboard_load_map_from_xkbfile(void* display, DWORD x11_keycode_to_rdp_scancode[256])
 
275
{
 
276
        int i, j;
 
277
        BOOL found;
 
278
        XkbDescPtr xkb;
 
279
        BOOL status = FALSE;
 
280
 
 
281
        if (display && (xkb = XkbGetMap(display, 0, XkbUseCoreKbd)))
 
282
        {
 
283
                if (XkbGetNames(display, XkbKeyNamesMask, xkb) == Success)
 
284
                {
 
285
                        char xkb_keyname[5] = { 42, 42, 42, 42, 0 }; /* end-of-string at index 5 */
 
286
 
 
287
                        for (i = xkb->min_key_code; i <= xkb->max_key_code; i++)
 
288
                        {
 
289
                                found = FALSE;
 
290
                                CopyMemory(xkb_keyname, xkb->names->keys[i].name, 4);
 
291
 
 
292
                                if (strlen(xkb_keyname) < 1)
 
293
                                        continue;
 
294
 
 
295
                                for (j = 0; j < ARRAYSIZE(XKB_KEY_NAME_SCANCODE_TABLE); j++)
 
296
                                {
 
297
                                        if (!strcmp(xkb_keyname, XKB_KEY_NAME_SCANCODE_TABLE[j].xkb_keyname))
 
298
                                        {
 
299
                                                DEBUG_KBD("%4s: keycode: 0x%02X -> rdp scancode: 0x%04X",
 
300
                                                                xkb_keyname, i, XKB_KEY_NAME_SCANCODE_TABLE[j].rdp_scancode);
 
301
 
 
302
                                                if (found)
 
303
                                                {
 
304
                                                        DEBUG_KBD("Internal error! duplicate key %s!", xkb_keyname);
 
305
                                                }
 
306
 
 
307
                                                x11_keycode_to_rdp_scancode[i] = XKB_KEY_NAME_SCANCODE_TABLE[j].rdp_scancode;
 
308
                                                found = TRUE;
 
309
                                        }
 
310
                                }
 
311
 
 
312
                                if (!found)
 
313
                                {
 
314
                                        DEBUG_KBD("%4s: keycode: 0x%02X -> no RDP scancode found", xkb_keyname, i);
 
315
                                }
 
316
                        }
 
317
 
 
318
                        status = TRUE;
 
319
                }
 
320
 
 
321
                XkbFreeKeyboard(xkb, 0, 1);
 
322
        }
 
323
 
 
324
        return status;
 
325
}