Skip to content

Commit

Permalink
TEMP: Sync keyboard classes
Browse files Browse the repository at this point in the history
  • Loading branch information
CendioOssman committed Oct 1, 2024
1 parent dbcf0ce commit cba3b33
Show file tree
Hide file tree
Showing 19 changed files with 399 additions and 388 deletions.
87 changes: 87 additions & 0 deletions common/rfb/CConnection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
#include <rfb/CConnection.h>
#include <rfb/util.h>

#define XK_MISCELLANY
#define XK_XKB_KEYS
#include <rfb/keysymdef.h>

#include <rfb/LogWriter.h>

#include <rdr/InStream.h>
Expand Down Expand Up @@ -693,6 +697,89 @@ void CConnection::sendClipboardData(const char* data)
}
}

void CConnection::sendKeyPress(int systemKeyCode,
uint32_t keyCode, uint32_t keySym)
{
// For the first few years, there wasn't a good consensus on what the
// Windows keys should be mapped to for X11. So we need to help out a
// bit and map all variants to the same key...
switch (keySym) {
case XK_Hyper_L:
keySym = XK_Super_L;
break;
case XK_Hyper_R:
keySym = XK_Super_R;
break;
// There has been several variants for Shift-Tab over the years.
// RFB states that we should always send a normal tab.
case XK_ISO_Left_Tab:
keySym = XK_Tab;
break;
}

#ifdef __APPLE__
// Alt on OS X behaves more like AltGr on other systems, and to get
// sane behaviour we should translate things in that manner for the
// remote VNC server. However that means we lose the ability to use
// Alt as a shortcut modifier. Do what RealVNC does and hijack the
// left command key as an Alt replacement.
switch (keySym) {
case XK_Super_L:
keySym = XK_Alt_L;
break;
case XK_Super_R:
keySym = XK_Super_L;
break;
case XK_Alt_L:
keySym = XK_Mode_switch;
break;
case XK_Alt_R:
keySym = XK_ISO_Level3_Shift;
break;
}
#endif

// Because of the way keyboards work, we cannot expect to have the same
// symbol on release as when pressed. This breaks the VNC protocol however,
// so we need to keep track of what keysym a key _code_ generated on press
// and send the same on release.
downKeys[systemKeyCode].keyCode = keyCode;
downKeys[systemKeyCode].keySym = keySym;

vlog.debug("Key pressed: %d => 0x%02x / XK_%s (0x%04x)",
systemKeyCode, keyCode, KeySymName(keySym), keySym);

writer()->writeKeyEvent(keySym, keyCode, true);
}

void CConnection::sendKeyRelease(int systemKeyCode)
{
DownMap::iterator iter;

iter = downKeys.find(systemKeyCode);
if (iter == downKeys.end()) {
// These occur somewhat frequently so let's not spam them unless
// logging is turned up.
vlog.debug("Unexpected release of key code %d", systemKeyCode);
return;
}

vlog.debug("Key released: %d => 0x%02x / XK_%s (0x%04x)",
systemKeyCode, iter->second.keyCode,
KeySymName(iter->second.keySym), iter->second.keySym);

writer()->writeKeyEvent(iter->second.keySym,
iter->second.keyCode, false);

downKeys.erase(iter);
}

void CConnection::releaseAllKeys()
{
while (!downKeys.empty())
sendKeyRelease(downKeys.begin()->first);
}

void CConnection::refreshFramebuffer()
{
forceNonincremental = true;
Expand Down
20 changes: 20 additions & 0 deletions common/rfb/CConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#ifndef __RFB_CCONNECTION_H__
#define __RFB_CCONNECTION_H__

#include <map>
#include <string>

#include <rfb/CMsgHandler.h>
Expand Down Expand Up @@ -196,6 +197,18 @@ namespace rfb {
// clipboard via handleClipboardRequest().
virtual void sendClipboardData(const char* data);

// sendKeyPress()/sendKeyRelease() send keyboard events to the
// server
void sendKeyPress(int systemKeyCode, uint32_t keyCode, uint32_t keySym);
void sendKeyRelease(int systemKeyCode);

// releaseAllKeys() sends keyboard release events to the server for
// all keys that are currently pressed down by this client,
// avoiding keys getting stuck. This can be useful if the client
// loses keyboard focus or otherwise no longer gets keyboard events
// from the system.
void releaseAllKeys();

// refreshFramebuffer() forces a complete refresh of the entire
// framebuffer
void refreshFramebuffer();
Expand Down Expand Up @@ -313,6 +326,13 @@ namespace rfb {
bool hasRemoteClipboard;
bool hasLocalClipboard;
bool unsolicitedClipboardAttempt;

struct DownKey {
uint32_t keyCode;
uint32_t keySym;
};
typedef std::map<int, DownKey> DownMap;
DownMap downKeys;
};
}
#endif
102 changes: 2 additions & 100 deletions vncviewer/Keyboard.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

static rfb::LogWriter vlog("Keyboard");

Keyboard::Keyboard(QObject* parent)
: QObject(parent)
Keyboard::Keyboard(KeyboardHandler* handler_, QObject* parent)
: QObject(parent), handler(handler_)
{
}

Expand All @@ -33,97 +33,6 @@ void Keyboard::ungrabKeyboard()
keyboardGrabbed = false;
}

bool Keyboard::handleKeyPress(int keyCode, quint32 keySym, bool menuShortCutMode)
{
vlog.debug("Keyboard::handleKeyPress");

int menuKeyCode;
quint32 menuKeySym;
::getMenuKey(&menuKeyCode, &menuKeySym);

if (menuKeySym && keySym == menuKeySym) {
if (!menuShortCutMode) {
emit contextMenuKeyPressed(menuShortCutMode);
return true;
}
}

if (::viewOnly)
return false;

if (keyCode == 0) {
vlog.error(_("No key code specified on key press"));
return false;
}

// Because of the way keyboards work, we cannot expect to have the same
// symbol on release as when pressed. This breaks the VNC protocol however,
// so we need to keep track of what keysym a key _code_ generated on press
// and send the same on release.
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)",
keyCode, XKeysymToString(keySym), keySym);
#endif


try {
QVNCConnection* cc = AppManager::instance()->getConnection();
// Fake keycode?
if (keyCode > 0xff)
emit cc->writeKeyEvent(keySym, 0, true);
else
emit cc->writeKeyEvent(keySym, keyCode, true);
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
throw;
}

return true;
}

bool Keyboard::handleKeyRelease(int keyCode)
{
vlog.debug("Keyboard::handleKeyRelease");
DownMap::iterator iter;

if (::viewOnly)
return false;

iter = downKeySym.find(keyCode);
if (iter == downKeySym.end()) {
// These occur somewhat frequently so let's not spam them unless
// logging is turned up.
vlog.debug("Unexpected release of key code %d", keyCode);
return false;
}

#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)",
keyCode, XKeysymToString(iter->second), iter->second);
#endif

try {
QVNCConnection* cc = AppManager::instance()->getConnection();
if (keyCode > 0xff)
emit cc->writeKeyEvent(iter->second, 0, false);
else
emit cc->writeKeyEvent(iter->second, keyCode, false);
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
throw;
}

downKeySym.erase(iter);

return true;
}

void Keyboard::setMenuKeyStatus(quint32 keysym, bool checked)
{
if (keysym == XK_Control_L) {
Expand Down Expand Up @@ -152,10 +61,3 @@ bool Keyboard::isKeyboardGrabbed() const
{
return keyboardGrabbed;
}

void Keyboard::resetKeyboard()
{
while (!downKeySym.empty()) {
handleKeyRelease(downKeySym.begin()->first);
}
}
25 changes: 14 additions & 11 deletions vncviewer/Keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,27 @@
#define XK_XKB_KEYS
#include "rfb/keysymdef.h"

using DownMap = std::map<int, quint32>;
class KeyboardHandler {
public:
virtual void handleKeyPress(int systemKeyCode,
uint32_t keyCode, uint32_t keySym) = 0;
virtual void handleKeyRelease(int systemKeyCode) = 0;
};

class Keyboard : public QObject, public QAbstractNativeEventFilter
class Keyboard : public QObject
{
Q_OBJECT

public:
Keyboard(QObject* parent = nullptr);
Keyboard(KeyboardHandler* handler, QObject* parent = nullptr);

virtual bool handleEvent(const char* eventType, void* message) = 0;

virtual void grabKeyboard();
virtual void ungrabKeyboard();

virtual void setLEDState(unsigned int state) = 0;
virtual void pushLEDState() = 0;

virtual bool handleKeyPress(int keyCode, quint32 keySym, bool menuShortCutMode = false);
virtual bool handleKeyRelease(int keyCode);
void resetKeyboard();
virtual unsigned getLEDState() = 0;
virtual void setLEDState(unsigned state) = 0;

void setMenuKeyStatus(quint32 keysym, bool checked);

Expand All @@ -44,9 +47,9 @@ class Keyboard : public QObject, public QAbstractNativeEventFilter
void contextMenuKeyPressed(bool menuShortCutMode);

protected:
bool keyboardGrabbed = false;
KeyboardHandler* handler;

DownMap downKeySym;
bool keyboardGrabbed = false;

bool menuCtrlKey = false;
bool menuAltKey = false;
Expand Down
Loading

0 comments on commit cba3b33

Please sign in to comment.