VirtualBox

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

Last change on this file since 69500 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use