This is mainly a copy of XKeysymToString() from libX11. We've also added a wrapper that still gives a string, even if there is no name for the requested keysym. This grows the binaries a bit, but not with any extreme amount so is hopefully worth it to get better debug logging.pull/1705/head
#include <rfb/CMsgWriter.h> | #include <rfb/CMsgWriter.h> | ||||
#include <rfb/CSecurity.h> | #include <rfb/CSecurity.h> | ||||
#include <rfb/Decoder.h> | #include <rfb/Decoder.h> | ||||
#include <rfb/KeysymStr.h> | |||||
#include <rfb/Security.h> | #include <rfb/Security.h> | ||||
#include <rfb/SecurityClient.h> | #include <rfb/SecurityClient.h> | ||||
#include <rfb/CConnection.h> | #include <rfb/CConnection.h> |
JpegCompressor.cxx | JpegCompressor.cxx | ||||
JpegDecompressor.cxx | JpegDecompressor.cxx | ||||
KeyRemapper.cxx | KeyRemapper.cxx | ||||
KeysymStr.c | |||||
LogWriter.cxx | LogWriter.cxx | ||||
Logger.cxx | Logger.cxx | ||||
Logger_file.cxx | Logger_file.cxx |
/* | |||||
Copyright 1990, 1998 The Open Group | |||||
Permission to use, copy, modify, distribute, and sell this software and its | |||||
documentation for any purpose is hereby granted without fee, provided that | |||||
the above copyright notice appear in all copies and that both that | |||||
copyright notice and this permission notice appear in supporting | |||||
documentation. | |||||
The above copyright notice and this permission notice shall be included in | |||||
all copies or substantial portions of the Software. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||||
Except as contained in this notice, the name of The Open Group shall not be | |||||
used in advertising or otherwise to promote the sale, use or other dealings | |||||
in this Software without prior written authorization from The Open Group. | |||||
*/ | |||||
#ifdef HAVE_CONFIG_H | |||||
#include <config.h> | |||||
#endif | |||||
#include <stdlib.h> | |||||
#include "keysymdef.h" | |||||
#include "KeysymStr.h" | |||||
#define NEEDKTABLE | |||||
#define NEEDVTABLE | |||||
#include "ks_tables.h" | |||||
static const char *_XKeysymToString(unsigned ks) | |||||
{ | |||||
if (!ks || (ks & ((unsigned long) ~0x1fffffff)) != 0) | |||||
return ((char *)NULL); | |||||
if (ks == XK_VoidSymbol) | |||||
ks = 0; | |||||
if (ks <= 0x1fffffff) | |||||
{ | |||||
unsigned char val1 = ks >> 24; | |||||
unsigned char val2 = (ks >> 16) & 0xff; | |||||
unsigned char val3 = (ks >> 8) & 0xff; | |||||
unsigned char val4 = ks & 0xff; | |||||
int i = ks % VTABLESIZE; | |||||
int h = i + 1; | |||||
int n = VMAXHASH; | |||||
int idx; | |||||
while ((idx = hashKeysym[i])) | |||||
{ | |||||
const unsigned char *entry = &_XkeyTable[idx]; | |||||
if ((entry[0] == val1) && (entry[1] == val2) && | |||||
(entry[2] == val3) && (entry[3] == val4)) | |||||
return ((char *)entry + 4); | |||||
if (!--n) | |||||
break; | |||||
i += h; | |||||
if (i >= VTABLESIZE) | |||||
i -= VTABLESIZE; | |||||
} | |||||
} | |||||
if (ks >= 0x01000100 && ks <= 0x0110ffff) { | |||||
unsigned val = ks & 0xffffff; | |||||
char *s; | |||||
int i; | |||||
if (val & 0xff0000) | |||||
i = 10; | |||||
else | |||||
i = 6; | |||||
s = malloc(i); | |||||
if (s == NULL) | |||||
return s; | |||||
i--; | |||||
s[i--] = '\0'; | |||||
for (; i; i--){ | |||||
unsigned char val1 = val & 0xf; | |||||
val >>= 4; | |||||
if (val1 < 10) | |||||
s[i] = '0'+ val1; | |||||
else | |||||
s[i] = 'A'+ val1 - 10; | |||||
} | |||||
s[i] = 'U'; | |||||
return s; | |||||
} | |||||
return ((char *) NULL); | |||||
} | |||||
const char* KeySymName(unsigned keysym) | |||||
{ | |||||
const char* name; | |||||
name = _XKeysymToString(keysym); | |||||
if (name == NULL) | |||||
return "[unknown keysym]"; | |||||
return name; | |||||
} | |||||
/* Copyright 2021 Pierre Ossman for Cendio AB | |||||
* | |||||
* This is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation; either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This software is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with this software; if not, write to the Free Software | |||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
* USA. | |||||
*/ | |||||
#ifndef __RFB_KEYSYMSTR_H__ | |||||
#define __RFB_KEYSYMSTR_H__ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
const char* KeySymName(unsigned keysym); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif |
#include <rfb/Encoder.h> | #include <rfb/Encoder.h> | ||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
#include <rfb/KeyRemapper.h> | #include <rfb/KeyRemapper.h> | ||||
#include <rfb/KeysymStr.h> | |||||
#include <rfb/LogWriter.h> | #include <rfb/LogWriter.h> | ||||
#include <rfb/Security.h> | #include <rfb/Security.h> | ||||
#include <rfb/ServerCore.h> | #include <rfb/ServerCore.h> | ||||
keycode = pressedKeys.begin()->first; | keycode = pressedKeys.begin()->first; | ||||
pressedKeys.erase(pressedKeys.begin()); | pressedKeys.erase(pressedKeys.begin()); | ||||
vlog.debug("Releasing key 0x%x / 0x%x on client disconnect", | |||||
keysym, keycode); | |||||
vlog.debug("Releasing key 0x%04x / XK_%s (0x%04x) on client disconnect", | |||||
keycode, KeySymName(keysym), keysym); | |||||
server->keyEvent(keysym, keycode, false); | server->keyEvent(keysym, keycode, false); | ||||
} | } | ||||
if (!rfb::Server::acceptKeyEvents) return; | if (!rfb::Server::acceptKeyEvents) return; | ||||
if (down) | if (down) | ||||
vlog.debug("Key pressed: 0x%x / 0x%x", keysym, keycode); | |||||
vlog.debug("Key pressed: 0x%04x / XK_%s (0x%04x)", | |||||
keycode, KeySymName(keysym), keysym); | |||||
else | else | ||||
vlog.debug("Key released: 0x%x / 0x%x", keysym, keycode); | |||||
vlog.debug("Key released: 0x%04x / XK_%s (0x%04x)", | |||||
keycode, KeySymName(keysym), keysym); | |||||
// Avoid lock keys if we don't know the server state | // Avoid lock keys if we don't know the server state | ||||
if ((server->getLEDState() == ledUnknown) && | if ((server->getLEDState() == ledUnknown) && |
#include <rfb/ComparingUpdateTracker.h> | #include <rfb/ComparingUpdateTracker.h> | ||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
#include <rfb/KeyRemapper.h> | #include <rfb/KeyRemapper.h> | ||||
#include <rfb/KeysymStr.h> | |||||
#include <rfb/LogWriter.h> | #include <rfb/LogWriter.h> | ||||
#include <rfb/Security.h> | #include <rfb/Security.h> | ||||
#include <rfb/ServerCore.h> | #include <rfb/ServerCore.h> | ||||
uint32_t newkey; | uint32_t newkey; | ||||
newkey = keyRemapper->remapKey(keysym); | newkey = keyRemapper->remapKey(keysym); | ||||
if (newkey != keysym) { | if (newkey != keysym) { | ||||
slog.debug("Key remapped to 0x%x", newkey); | |||||
slog.debug("Key remapped to XK_%s (0x%x)", | |||||
KeySymName(newkey), newkey); | |||||
keysym = newkey; | keysym = newkey; | ||||
} | } | ||||
} | } |
#include "vncExtInit.h" | #include "vncExtInit.h" | ||||
#include "RFBGlue.h" | #include "RFBGlue.h" | ||||
/* This is a C header, so safe to include */ | |||||
#include <rfb/KeysymStr.h> | |||||
#include "inputstr.h" | #include "inputstr.h" | ||||
#include "inpututils.h" | #include "inpututils.h" | ||||
#include "mi.h" | #include "mi.h" | ||||
* This can happen quite often as we ignore some | * This can happen quite often as we ignore some | ||||
* key presses. | * key presses. | ||||
*/ | */ | ||||
LOG_DEBUG("Unexpected release of keysym 0x%x", keysym); | |||||
LOG_DEBUG("Unexpected release of keysym XK_%s (0x%04x)", | |||||
KeySymName(keysym), keysym); | |||||
return; | return; | ||||
} | } | ||||
if (keycode == 0) { | if (keycode == 0) { | ||||
keycode = vncAddKeysym(keysym, state); | keycode = vncAddKeysym(keysym, state); | ||||
if (keycode == 0) { | if (keycode == 0) { | ||||
LOG_ERROR("Failure adding new keysym 0x%x", keysym); | |||||
LOG_ERROR("Failure adding new keysym XK_%s (0x%x)", | |||||
KeySymName(keysym), keysym); | |||||
return; | return; | ||||
} | } | ||||
LOG_INFO("Added keysym 0x%x to keycode %d", | |||||
keysym, keycode); | |||||
LOG_INFO("Added keysym XK_%s (0x%04x) to keycode %d", | |||||
KeySymName(keysym), keysym, keycode); | |||||
/* | /* | ||||
* The state given to addKeysym() is just a hint and | * The state given to addKeysym() is just a hint and | ||||
*/ | */ | ||||
keycode = vncKeysymToKeycode(keysym, state, &new_state); | keycode = vncKeysymToKeycode(keysym, state, &new_state); | ||||
if (keycode == 0) { | if (keycode == 0) { | ||||
LOG_ERROR("Newly added keysym 0x%x cannot be generated", keysym); | |||||
LOG_ERROR("Newly added keysym XK_%s (0x%x) cannot be generated", | |||||
KeySymName(keysym), keysym); | |||||
return; | return; | ||||
} | } | ||||
} | } | ||||
KeyCode keycode2; | KeyCode keycode2; | ||||
unsigned new_state2; | unsigned new_state2; | ||||
LOG_DEBUG("Finding alternative to keysym 0x%x to avoid fake shift for numpad", keysym); | |||||
LOG_DEBUG("Finding alternative to keysym XK_%s (0x%x) to avoid fake shift for numpad", | |||||
KeySymName(keysym), keysym); | |||||
for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) { | for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) { | ||||
KeySym altsym; | KeySym altsym; | ||||
if (i == keycode) | if (i == keycode) | ||||
continue; | continue; | ||||
if (pressedKeys[i] == keysym) { | if (pressedKeys[i] == keysym) { | ||||
LOG_ERROR("Keysym 0x%x generated by both keys %d and %d", keysym, i, keycode); | |||||
LOG_ERROR("Keysym XK_%s (0x%04x) generated by both keys %d and %d", | |||||
KeySymName(keysym), keysym, i, keycode); | |||||
pressedKeys[i] = NoSymbol; | pressedKeys[i] = NoSymbol; | ||||
} | } | ||||
} | } |
#include <rfb/CMsgWriter.h> | #include <rfb/CMsgWriter.h> | ||||
#include <rfb/LogWriter.h> | #include <rfb/LogWriter.h> | ||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
#include <rfb/KeysymStr.h> | |||||
#include <rfb/ledStates.h> | #include <rfb/ledStates.h> | ||||
#include <rfb/util.h> | #include <rfb/util.h> | ||||
// and send the same on release. | // and send the same on release. | ||||
downKeySym[keyCode] = keySym; | downKeySym[keyCode] = keySym; | ||||
#if defined(WIN32) || defined(__APPLE__) | |||||
vlog.debug("Key pressed: 0x%04x => 0x%04x", keyCode, keySym); | |||||
#else | |||||
vlog.debug("Key pressed: 0x%04x => XK_%s (0x%04x)", | vlog.debug("Key pressed: 0x%04x => XK_%s (0x%04x)", | ||||
keyCode, XKeysymToString(keySym), keySym); | |||||
#endif | |||||
keyCode, KeySymName(keySym), keySym); | |||||
try { | try { | ||||
// Fake keycode? | // Fake keycode? | ||||
return; | return; | ||||
} | } | ||||
#if defined(WIN32) || defined(__APPLE__) | |||||
vlog.debug("Key released: 0x%04x => 0x%04x", keyCode, iter->second); | |||||
#else | |||||
vlog.debug("Key released: 0x%04x => XK_%s (0x%04x)", | vlog.debug("Key released: 0x%04x => XK_%s (0x%04x)", | ||||
keyCode, XKeysymToString(iter->second), iter->second); | |||||
#endif | |||||
keyCode, KeySymName(iter->second), iter->second); | |||||
try { | try { | ||||
if (keyCode > 0xff) | if (keyCode > 0xff) |