Skip to content

Commit 69a11e6

Browse files
committed
TEMP: more hot key handling
1 parent 2806cf8 commit 69a11e6

File tree

2 files changed

+178
-53
lines changed

2 files changed

+178
-53
lines changed

vncviewer/Viewport.cxx

+171-50
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include <config.h>
2222
#endif
2323

24+
#include <algorithm>
25+
2426
#include <assert.h>
2527
#include <stdio.h>
2628
#include <string.h>
@@ -113,7 +115,7 @@ static const WORD SCAN_FAKE = 0xaa;
113115

114116
Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_)
115117
: Fl_Widget(0, 0, w, h), cc(cc_), frameBuffer(NULL),
116-
lastPointerPos(0, 0), lastButtonMask(0),
118+
lastPointerPos(0, 0), lastButtonMask(0), hotKeyWedged(false),
117119
#ifdef WIN32
118120
altGrArmed(false),
119121
#endif
@@ -823,59 +825,27 @@ void Viewport::handlePointerTimeout(void *data)
823825

824826
void Viewport::handleKeyPress(int keyCode, rdr::U32 keySym)
825827
{
826-
std::set<HotKey> hotkeys;
827-
828-
hotkeys = parseHotKeyCombo(hotKeyCombo);
829-
830-
if ((hotkeys.count(hotkeyCtrl) > 0) &&
831-
((keySym == XK_Control_L) || (keySym == XK_Control_R)))
832-
downHotkeys.insert(hotkeyCtrl);
833-
else if ((hotkeys.count(hotkeyShift) > 0) &&
834-
((keySym == XK_Shift_L) || (keySym == XK_Shift_R)))
835-
downHotkeys.insert(hotkeyShift);
836-
else if ((hotkeys.count(hotkeyAlt) > 0) &&
837-
((keySym == XK_Alt_L) || (keySym == XK_Alt_R)))
838-
downHotkeys.insert(hotkeyAlt);
839-
else if ((hotkeys.count(hotkeySuper) > 0) &&
840-
((keySym == XK_Super_L) || (keySym == XK_Super_R)))
841-
downHotkeys.insert(hotkeySuper);
842-
843-
if (viewOnly)
844-
return;
845-
846828
if (keyCode == 0) {
847829
vlog.error(_("No key code specified on key press"));
848830
return;
849831
}
850832

851-
#ifdef __APPLE__
852-
// Alt on OS X behaves more like AltGr on other systems, and to get
853-
// sane behaviour we should translate things in that manner for the
854-
// remote VNC server. However that means we lose the ability to use
855-
// Alt as a shortcut modifier. Do what RealVNC does and hijack the
856-
// left command key as an Alt replacement.
857-
switch (keySym) {
858-
case XK_Super_L:
859-
keySym = XK_Alt_L;
860-
break;
861-
case XK_Super_R:
862-
keySym = XK_Super_L;
863-
break;
864-
case XK_Alt_L:
865-
keySym = XK_Mode_switch;
866-
break;
867-
case XK_Alt_R:
868-
keySym = XK_ISO_Level3_Shift;
869-
break;
870-
}
871-
#endif
833+
// Possible hot key combo?
834+
if (handleHotKeyPress(keyCode, keySym))
835+
return;
872836

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

843+
if (viewOnly)
844+
return;
845+
846+
// Platform specific adjustments
847+
keySym = adjustKeySym(keyCode, keySym);
848+
879849
#if defined(WIN32) || defined(__APPLE__)
880850
vlog.debug("Key pressed: 0x%04x => 0x%04x", keyCode, keySym);
881851
#else
@@ -900,9 +870,7 @@ void Viewport::handleKeyPress(int keyCode, rdr::U32 keySym)
900870
void Viewport::handleKeyRelease(int keyCode)
901871
{
902872
DownMap::iterator iter;
903-
904-
if (viewOnly)
905-
return;
873+
rdr::U32 keySym;
906874

907875
iter = downKeySym.find(keyCode);
908876
if (iter == downKeySym.end()) {
@@ -912,25 +880,178 @@ void Viewport::handleKeyRelease(int keyCode)
912880
return;
913881
}
914882

883+
keySym = iter->second;
884+
downKeySym.erase(iter);
885+
886+
if (downKeySym.empty())
887+
hotKeyWedged = false;
888+
889+
if (viewOnly)
890+
return;
891+
892+
// Platform specific adjustments
893+
keySym = adjustKeySym(keyCode, keySym);
894+
915895
#if defined(WIN32) || defined(__APPLE__)
916-
vlog.debug("Key released: 0x%04x => 0x%04x", keyCode, iter->second);
896+
vlog.debug("Key released: 0x%04x => 0x%04x", keyCode, keySym);
917897
#else
918898
vlog.debug("Key released: 0x%04x => XK_%s (0x%04x)",
919-
keyCode, XKeysymToString(iter->second), iter->second);
899+
keyCode, XKeysymToString(keySym), keySym);
920900
#endif
921901

922902
try {
923903
if (keyCode > 0xff)
924-
cc->writer()->writeKeyEvent(iter->second, 0, false);
904+
cc->writer()->writeKeyEvent(keySym, 0, false);
925905
else
926-
cc->writer()->writeKeyEvent(iter->second, keyCode, false);
906+
cc->writer()->writeKeyEvent(keySym, keyCode, false);
927907
} catch (rdr::Exception& e) {
928908
vlog.error("%s", e.str());
929909
exit_vncviewer(_("An unexpected error occurred when communicating "
930910
"with the server:\n\n%s"), e.str());
931911
}
912+
}
932913

933-
downKeySym.erase(iter);
914+
rdr::U32 Viewport::adjustKeySym(int keyCode, rdr::U32 keySym)
915+
{
916+
#ifdef __APPLE__
917+
// Alt on OS X behaves more like AltGr on other systems, and to get
918+
// sane behaviour we should translate things in that manner for the
919+
// remote VNC server. However that means we lose the ability to use
920+
// Alt as a shortcut modifier. Do what RealVNC does and hijack the
921+
// left command key as an Alt replacement.
922+
switch (keySym) {
923+
case XK_Super_L:
924+
keySym = XK_Alt_L;
925+
break;
926+
case XK_Super_R:
927+
keySym = XK_Super_L;
928+
break;
929+
case XK_Alt_L:
930+
keySym = XK_Mode_switch;
931+
break;
932+
case XK_Alt_R:
933+
keySym = XK_ISO_Level3_Shift;
934+
break;
935+
}
936+
#endif
937+
938+
return keySym;
939+
}
940+
941+
bool Viewport::handleHotKeyPress(int keyCode, rdr::U32 keySym)
942+
{
943+
// Already determined this isn't a hot key combo?
944+
if (hotKeyWedged)
945+
return false;
946+
947+
// Are we still collecting modifiers?
948+
if (!hotKeyReady) {
949+
std::set<HotKey> hotkeys;
950+
std::set<HotKey> downHotkeys;
951+
DownMap::iterator iter;
952+
953+
hotkeys = parseHotKeyCombo(hotKeyCombo);
954+
955+
// No hot key combo configured?
956+
if (hotkeys.empty()) {
957+
hotKeyWedged = true;
958+
return false;
959+
}
960+
961+
// Which modifiers are pressed?
962+
for (iter = downKeySym.begin(); iter != downKeySym.end(); ++iter) {
963+
switch (iter->second) {
964+
case XK_Super_L:
965+
case XK_Super_R:
966+
downHotkeys.insert(hotkeySuper);
967+
break;
968+
case XK_Alt_L:
969+
case XK_Alt_R:
970+
downHotkeys.insert(hotkeyAlt);
971+
break;
972+
case XK_Shift_L:
973+
case XK_Shift_R:
974+
downHotkeys.insert(hotkeyShift);
975+
break;
976+
case XK_Control_L:
977+
case XK_Control_R:
978+
downHotkeys.insert(hotkeyCtrl);
979+
break;
980+
default:
981+
// Something else snuck in
982+
hotKeyWedged = true;
983+
return false;
984+
}
985+
}
986+
987+
// Not enough?
988+
if (hotkeys != downHotkeys) {
989+
// Extra modifiers?
990+
if (!std::includes(hotkeys.begin(), hotkeys.end(),
991+
downHotkeys.begin(), downHotkeys.end())) {
992+
// Yes, so this is likely some other key combo we should ignore
993+
hotKeyWedged = true;
994+
}
995+
996+
return false;
997+
}
998+
999+
// Is this new key also a modifier?
1000+
switch (keySym) {
1001+
case XK_Super_L:
1002+
case XK_Super_R:
1003+
case XK_Alt_L:
1004+
case XK_Alt_R:
1005+
case XK_Shift_L:
1006+
case XK_Shift_R:
1007+
case XK_Control_L:
1008+
case XK_Control_R:
1009+
// Yes, so this is likely some other key combo we should ignore
1010+
hotKeyWedged = true;
1011+
return false;
1012+
}
1013+
1014+
if (keySym == XK_space) {
1015+
vlog.debug("Detected hot key escape sequence");
1016+
// We're not really wedged, but we want the same effect,
1017+
// i.e. that all following keys are passed through
1018+
hotKeyWedged = true;
1019+
// This space is consumed though
1020+
return true;
1021+
}
1022+
1023+
vlog.debug("Detected hot key 0x%04x", keySym);
1024+
1025+
// The remote session won't see any more keys, so release the ones
1026+
// currently down
1027+
while (!downKeySym.empty())
1028+
handleKeyRelease(downKeySym.begin()->first);
1029+
1030+
hotKeyReady = true;
1031+
}
1032+
1033+
assert(hotKeyReady);
1034+
1035+
switch (keySym) {
1036+
case XK_m:
1037+
popupContextMenu();
1038+
break;
1039+
case XK_KP_Enter:
1040+
case XK_Return:
1041+
if (window()->fullscreen_active())
1042+
window()->fullscreen_off();
1043+
else
1044+
((DesktopWindow*)window())->fullscreen_on();
1045+
break;
1046+
default:
1047+
// Unknown/Unused hot key combo
1048+
break;
1049+
}
1050+
1051+
// FIXME: Should be able to press multiple hot keys
1052+
hotKeyReady = false;
1053+
1054+
return true;
9341055
}
9351056

9361057

vncviewer/Viewport.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,11 @@
2121
#define __VIEWPORT_H__
2222

2323
#include <map>
24-
#include <set>
2524

2625
#include <rfb/Rect.h>
2726

2827
#include <FL/Fl_Widget.H>
2928

30-
#include "parameters.h"
3129
#include "EmulateMB.h"
3230

3331
class Fl_Menu_Button;
@@ -89,6 +87,11 @@ class Viewport : public Fl_Widget, public EmulateMB {
8987
void handleKeyPress(int keyCode, rdr::U32 keySym);
9088
void handleKeyRelease(int keyCode);
9189

90+
rdr::U32 adjustKeySym(int keyCode, rdr::U32 keySym);
91+
92+
bool handleHotKeyPress(int keyCode, rdr::U32 keySym);
93+
bool handleHotKeyRelease(int keyCode, rdr::U32 keySym);
94+
9295
static int handleSystemEvent(void *event, void *data);
9396

9497
#ifdef WIN32
@@ -112,7 +115,8 @@ class Viewport : public Fl_Widget, public EmulateMB {
112115
typedef std::map<int, rdr::U32> DownMap;
113116
DownMap downKeySym;
114117

115-
std::set<HotKey> downHotkeys;
118+
bool hotKeyReady;
119+
bool hotKeyWedged;
116120

117121
#ifdef WIN32
118122
bool altGrArmed;

0 commit comments

Comments
 (0)