VirtualBox

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

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

FE/Qt: do not ask for bug reports without a good reason.

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

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