VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/platform/x11/XKeyboard-new.cpp@ 44797

Last change on this file since 44797 was 44797, checked in by vboxsync, 12 years ago

FE/Qt and Common: fix or mark as safe deprecated use of XKeycodeToKeysym API.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1/* $Id: XKeyboard-new.cpp 44797 2013-02-21 20:40:14Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * Implementation of Linux-specific keyboard functions
6 */
7
8/*
9 * Copyright (C) 2006-2011 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#define LOG_GROUP LOG_GROUP_GUI
21
22#include <QString>
23#include <QStringList>
24#include <X11/XKBlib.h>
25#include <X11/Xlib.h>
26#include <X11/keysym.h>
27#include <XKeyboard.h>
28#include <VBox/log.h>
29#include <VBox/VBoxKeyboard.h>
30
31/* VBoxKeyboard uses the deprecated XKeycodeToKeysym(3) API, but uses it safely.
32 */
33#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
34
35static unsigned gfByLayoutOK = 1;
36static unsigned gfByTypeOK = 1;
37static unsigned gfByXkbOK = 1;
38
39/**
40 * DEBUG function
41 * Print a key to the release log in the format needed for the Wine
42 * layout tables.
43 */
44static void printKey(Display *display, int keyc)
45{
46 bool was_escape = false;
47
48 for (int i = 0; i < 2; ++i)
49 {
50 int keysym = XKeycodeToKeysym (display, keyc, i);
51
52 int val = keysym & 0xff;
53 if ('\\' == val)
54 {
55 LogRel(("\\\\"));
56 }
57 else if ('"' == val)
58 {
59 LogRel(("\\\""));
60 }
61 else if ((val > 32) && (val < 127))
62 {
63 if (
64 was_escape
65 && (
66 ((val >= '0') && (val <= '9'))
67 || ((val >= 'A') && (val <= 'F'))
68 || ((val >= 'a') && (val <= 'f'))
69 )
70 )
71 {
72 LogRel(("\"\""));
73 }
74 LogRel(("%c", (char) val));
75 }
76 else
77 {
78 LogRel(("\\x%x", val));
79 was_escape = true;
80 }
81 }
82}
83
84/**
85 * DEBUG function
86 * Dump the keyboard layout to the release log.
87 */
88static void dumpLayout(Display *display)
89{
90 LogRel(("Your keyboard layout does not appear to be fully supported by\n"
91 "VirtualBox. If you are experiencing keyboard problems this.\n"
92 "information may help us to resolve them.\n"
93 "(Note: please tell us if you are using a custom layout.)\n\n"
94 "The correct table for your layout is:\n"));
95 /* First, build up a table of scan-to-key code mappings */
96 unsigned scanToKeycode[512] = { 0 };
97 int minKey, maxKey;
98 XDisplayKeycodes(display, &minKey, &maxKey);
99 for (int i = minKey; i < maxKey; ++i)
100 scanToKeycode[X11DRV_KeyEvent(display, i)] = i;
101 LogRel(("\""));
102 printKey(display, scanToKeycode[0x29]); /* `~ */
103 for (int i = 2; i <= 0xd; ++i) /* 1! - =+ */
104 {
105 LogRel(("\",\""));
106 printKey(display, scanToKeycode[i]);
107 }
108 LogRel(("\",\n"));
109 LogRel(("\""));
110 printKey(display, scanToKeycode[0x10]); /* qQ */
111 for (int i = 0x11; i <= 0x1b; ++i) /* wW - ]} */
112 {
113 LogRel(("\",\""));
114 printKey(display, scanToKeycode[i]);
115 }
116 LogRel(("\",\n"));
117 LogRel(("\""));
118 printKey(display, scanToKeycode[0x1e]); /* aA */
119 for (int i = 0x1f; i <= 0x28; ++i) /* sS - '" */
120 {
121 LogRel(("\",\""));
122 printKey(display, scanToKeycode[i]);
123 }
124 LogRel(("\",\""));
125 printKey(display, scanToKeycode[0x2b]); /* \| */
126 LogRel(("\",\n"));
127 LogRel(("\""));
128 printKey(display, scanToKeycode[0x2c]); /* zZ */
129 for (int i = 0x2d; i <= 0x35; ++i) /* xX - /? */
130 {
131 LogRel(("\",\""));
132 printKey(display, scanToKeycode[i]);
133 }
134 LogRel(("\",\""));
135 printKey(display, scanToKeycode[0x56]); /* The 102nd key */
136 LogRel(("\",\""));
137 printKey(display, scanToKeycode[0x73]); /* The Brazilian key */
138 LogRel(("\",\""));
139 printKey(display, scanToKeycode[0x7d]); /* The Yen key */
140 LogRel(("\"\n\n"));
141}
142
143/**
144 * DEBUG function
145 * Dump the keyboard type tables to the release log.
146 */
147static void dumpType(Display *display)
148{
149 LogRel(("Your keyboard type does not appear to be known to VirtualBox. If\n"
150 "you are experiencing keyboard problems this information may help us\n"
151 "to resolve them. Please also provide information about what type\n"
152 "of keyboard you have and whether you are using a remote X server or\n"
153 "something similar.\n\n"
154 "The tables for your keyboard are:\n"));
155 for (unsigned i = 0; i < 256; ++i)
156 {
157 LogRel(("0x%x", X11DRV_KeyEvent(display, i)));
158 if (i < 255)
159 LogRel((", "));
160 if (15 == (i % 16))
161 LogRel(("\n"));
162 }
163 LogRel(("and\n"));
164 LogRel(("NULL, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x,\n0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
165 XKeysymToKeycode(display, XK_Control_L),
166 XKeysymToKeycode(display, XK_Shift_L),
167 XKeysymToKeycode(display, XK_Caps_Lock),
168 XKeysymToKeycode(display, XK_Tab),
169 XKeysymToKeycode(display, XK_Escape),
170 XKeysymToKeycode(display, XK_Return),
171 XKeysymToKeycode(display, XK_Up),
172 XKeysymToKeycode(display, XK_Down),
173 XKeysymToKeycode(display, XK_Left),
174 XKeysymToKeycode(display, XK_Right),
175 XKeysymToKeycode(display, XK_F1),
176 XKeysymToKeycode(display, XK_F2),
177 XKeysymToKeycode(display, XK_F3),
178 XKeysymToKeycode(display, XK_F4),
179 XKeysymToKeycode(display, XK_F5),
180 XKeysymToKeycode(display, XK_F6),
181 XKeysymToKeycode(display, XK_F7),
182 XKeysymToKeycode(display, XK_F8)));
183}
184
185/*
186 * This function builds a table mapping the X server's scan codes to PC
187 * keyboard scan codes. The logic of the function is that while the
188 * X server may be using a different set of scan codes (if for example
189 * it is running on a non-PC machine), the keyboard layout should be similar
190 * to a PC layout. So we look at the symbols attached to each key on the
191 * X server, find the PC layout which is closest to it and remember the
192 * mappings.
193 */
194bool initXKeyboard(Display *dpy, int (*remapScancodes)[2])
195{
196 X11DRV_InitKeyboard(dpy, &gfByLayoutOK, &gfByTypeOK, &gfByXkbOK,
197 remapScancodes);
198 /* It will almost always work to some extent */
199 return true;
200}
201
202/**
203 * Do deferred logging after initialisation
204 */
205void doXKeyboardLogging(Display *dpy)
206{
207 if (((1 == gfByTypeOK) || (1 == gfByXkbOK)) && (gfByLayoutOK != 1))
208 dumpLayout(dpy);
209 if (((1 == gfByLayoutOK) || (1 == gfByXkbOK)) && (gfByTypeOK != 1))
210 dumpType(dpy);
211 if ((gfByLayoutOK != 1) && (gfByTypeOK != 1) && (gfByXkbOK != 1))
212 {
213 LogRel(("Failed to recognize the keyboard mapping or to guess it based on\n"
214 "the keyboard layout. It is very likely that some keys will not\n"
215 "work correctly in the guest. If this is the case, please submit\n"
216 "a bug report, giving us information about your keyboard type,\n"
217 "its layout and other relevant information such as whether you\n"
218 "are using a remote X server or something similar. \n"));
219 unsigned *keyc2scan = X11DRV_getKeyc2scan();
220
221 LogRel(("The keycode-to-scancode table is: %d=%d",0,keyc2scan[0]));
222 for (int i = 1; i < 256; i++)
223 LogRel((",%d=%d",i,keyc2scan[i]));
224 LogRel(("\n"));
225 }
226 LogRel(("Using %s for keycode to scan code conversion\n",
227 gfByXkbOK ? "XKB"
228 : gfByTypeOK ? "known keycode mapping"
229 : "host keyboard layout detection"));
230}
231
232/*
233 * Translate an X server scancode to a PC keyboard scancode.
234 */
235unsigned handleXKeyEvent(XEvent *event)
236{
237 // call the WINE event handler
238 unsigned key = X11DRV_KeyEvent(event->xkey.display, event->xkey.keycode);
239 LogRel3(("VBoxKeyboard: converting keycode %d to scancode %s0x%x\n",
240 event->xkey.keycode, key > 0x100 ? "0xe0 " : "", key & 0xff));
241 return key;
242}
243
244/**
245 * Initialize X11 keyboard including the remapping specified in the
246 * global property GUI/RemapScancodes. This property is a string of
247 * comma-separated x=y pairs, where x is the X11 keycode and y is the
248 * keyboard scancode that is emitted when the key attached to the X11
249 * keycode is pressed.
250 */
251void initMappedX11Keyboard(Display *pDisplay, QString remapScancodes)
252{
253 int (*scancodes)[2] = NULL;
254 int (*scancodesTail)[2] = NULL;
255
256 if (remapScancodes != QString::null)
257 {
258 QStringList tuples = remapScancodes.split(",", QString::SkipEmptyParts);
259 scancodes = scancodesTail = new int [tuples.size()+1][2];
260 for (int i = 0; i < tuples.size(); ++i)
261 {
262 QStringList keyc2scan = tuples.at(i).split("=");
263 (*scancodesTail)[0] = keyc2scan.at(0).toUInt();
264 (*scancodesTail)[1] = keyc2scan.at(1).toUInt();
265 /* Do not advance on (ignore) identity mappings as this is
266 the stop signal to initXKeyboard and friends */
267 if ((*scancodesTail)[0] != (*scancodesTail)[1])
268 scancodesTail++;
269 }
270 (*scancodesTail)[0] = (*scancodesTail)[1] = 0;
271 }
272 /* initialize the X keyboard subsystem */
273 initXKeyboard (pDisplay ,scancodes);
274
275 if (scancodes)
276 delete scancodes;
277}
278
279unsigned long wrapXkbKeycodeToKeysym(Display *pDisplay, unsigned char cCode,
280 unsigned int cGroup, unsigned int cIndex)
281{
282 KeySym cSym = XkbKeycodeToKeysym(pDisplay, cCode, cGroup, cIndex);
283 if (cSym != NoSymbol)
284 return cSym;
285 return XKeycodeToKeysym(pDisplay, cCode, cGroup * 2 + cIndex % 2);
286}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette