VirtualBox

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

Last change on this file since 52727 was 52727, checked in by vboxsync, 11 years ago

FE/Qt: file header cleanups.

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