BoolParameter rfb::win32::SKeyboard::deadKeyAware("DeadKeyAware",
"Whether to assume the viewer has already interpreted dead key sequences "
"into latin-1 characters", true);
+BoolParameter rfb::win32::SKeyboard::rawKeyboard("RawKeyboard",
+ "Send keyboard events straight through and avoid mapping them to the "
+ "current keyboard layout", false);
// The keysymToAscii table transforms a couple of awkward keysyms into their
// ASCII equivalents.
keybd_event(vkCode, MapVirtualKey(vkCode, 0), flags, 0);
}
+inline void doScanCodeEvent(BYTE scancode, bool down) {
+ INPUT evt;
+
+ evt.type = INPUT_KEYBOARD;
+ evt.ki.wVk = 0;
+ evt.ki.dwFlags = KEYEVENTF_SCANCODE;
+
+ if (!down)
+ evt.ki.dwFlags |= KEYEVENTF_KEYUP;
+
+ if (scancode & 0x80) {
+ evt.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
+ scancode &= ~0x80;
+ }
+
+ evt.ki.wScan = scancode;
+ evt.ki.dwExtraInfo = 0;
+ evt.ki.time = 0;
+ vlog.debug("SendInput ScanCode: 0x%x Flags: 0x%lx %s", scancode,
+ evt.ki.dwFlags, down ? "Down" : "Up");
+
+ if (SendInput(1, &evt, sizeof(evt)) != 1)
+ vlog.error("SendInput %lu", GetLastError());
+}
+
// KeyStateModifier is a class which helps simplify generating a "fake" press
// or release of shift, ctrl, alt, etc. An instance of the class is created
// for every key which may need to be pressed or released. Then either press()
void win32::SKeyboard::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
{
+ // If scan code is available use that directly as windows uses
+ // compatible scancodes
+ if (keycode && rawKeyboard) {
+ doScanCodeEvent(keycode, down);
+ return;
+ }
+
for (unsigned int i = 0; i < sizeof(keysymToAscii) / sizeof(keysymToAscii_t); i++) {
if (keysymToAscii[i].keysym == keysym) {
keysym = keysymToAscii[i].ascii;
SKeyboard();
void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
static BoolParameter deadKeyAware;
+ static BoolParameter rawKeyboard;
private:
std::map<rdr::U32,rdr::U8> vkMap;
std::map<rdr::U32,bool> extendedMap;
regKey(rk), enableAffectSSaver(true) {}
void initDialog() {
setItemChecked(IDC_ACCEPT_KEYS, rfb::Server::acceptKeyEvents);
+ setItemChecked(IDC_RAW_KEYBOARD, SKeyboard::rawKeyboard);
setItemChecked(IDC_ACCEPT_PTR, rfb::Server::acceptPointerEvents);
setItemChecked(IDC_ACCEPT_CUTTEXT, rfb::Server::acceptCutText);
setItemChecked(IDC_SEND_CUTTEXT, rfb::Server::sendCutText);
BOOL inputResetsBlocked;
SystemParametersInfo(SPI_GETBLOCKSENDINPUTRESETS, 0, &inputResetsBlocked, 0);
setChanged((rfb::Server::acceptKeyEvents != isItemChecked(IDC_ACCEPT_KEYS)) ||
+ (SKeyboard::rawKeyboard != isItemChecked(IDC_RAW_KEYBOARD)) ||
(rfb::Server::acceptPointerEvents != isItemChecked(IDC_ACCEPT_PTR)) ||
(rfb::Server::acceptCutText != isItemChecked(IDC_ACCEPT_CUTTEXT)) ||
(rfb::Server::sendCutText != isItemChecked(IDC_SEND_CUTTEXT)) ||
}
bool onOk() {
regKey.setBool(_T("AcceptKeyEvents"), isItemChecked(IDC_ACCEPT_KEYS));
+ regKey.setBool(_T("RawKeyboard"), isItemChecked(IDC_RAW_KEYBOARD));
regKey.setBool(_T("AcceptPointerEvents"), isItemChecked(IDC_ACCEPT_PTR));
regKey.setBool(_T("AcceptCutText"), isItemChecked(IDC_ACCEPT_CUTTEXT));
regKey.setBool(_T("SendCutText"), isItemChecked(IDC_SEND_CUTTEXT));
#define IDC_RFB_ENABLE 1082
#define IDC_LOAD_CERT 1087
#define IDC_LOAD_CERTKEY 1088
+#define IDC_RAW_KEYBOARD 1089
#define ID_OPTIONS 40001
#define ID_CLOSE 40002
#define ID_ABOUT 40003
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,10,172,15
CONTROL "Accept keyboard events from clients",IDC_ACCEPT_KEYS,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,25,172,15
+ CONTROL "Send raw keyboard events to applications",IDC_RAW_KEYBOARD,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,40,172,15
CONTROL "Accept clipboard updates from clients",
IDC_ACCEPT_CUTTEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
- 7,40,172,15
+ 7,55,172,15
CONTROL "Send clipboard updates to clients",IDC_SEND_CUTTEXT,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,55,172,15
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,70,172,15
CONTROL "Allow input events to affect the screen-saver",
IDC_AFFECT_SCREENSAVER,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,7,70,172,15
+ WS_TABSTOP,7,85,172,15
CONTROL "Disable local inputs while server is in use",
IDC_DISABLE_LOCAL_INPUTS,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,7,95,172,15
+ WS_TABSTOP,7,110,172,15
END
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 300, 92