VirtualBox

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

Last change on this file since 74942 was 71540, checked in by vboxsync, 6 years ago

FE/Qt: bugref:9049: Heavy cleanup for XKeyboard stuff.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use