aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vncviewer/CViewOptions.cxx9
-rw-r--r--vncviewer/CViewOptions.h1
-rw-r--r--vncviewer/OptionsDialog.cxx2
-rw-r--r--vncviewer/cview.cxx67
-rw-r--r--vncviewer/cview.h3
-rw-r--r--vncviewer/resource.h1
-rw-r--r--vncviewer/vncviewer.rc14
7 files changed, 86 insertions, 11 deletions
diff --git a/vncviewer/CViewOptions.cxx b/vncviewer/CViewOptions.cxx
index 13ad7cdd..39a1a5ca 100644
--- a/vncviewer/CViewOptions.cxx
+++ b/vncviewer/CViewOptions.cxx
@@ -66,6 +66,8 @@ static BoolParameter sendPtrEvents("SendPointerEvents",
"Send pointer (mouse) events to the server.", true);
static BoolParameter sendKeyEvents("SendKeyEvents",
"Send key presses (and releases) to the server.", true);
+static BoolParameter sendSysKeys("SendSysKeys",
+ "Send system keys (Alt combinations) to the server.", true);
static BoolParameter clientCutText("ClientCutText",
"Send clipboard changes to the server.", true);
@@ -110,7 +112,7 @@ static IntParameter qualityLevel("QualityLevel",
CViewOptions::CViewOptions()
: useLocalCursor(::useLocalCursor), useDesktopResize(::useDesktopResize),
autoSelect(::autoSelect), fullColour(::fullColour), fullScreen(::fullScreen),
-shared(::sharedConnection), sendPtrEvents(::sendPtrEvents), sendKeyEvents(::sendKeyEvents),
+shared(::sharedConnection), sendPtrEvents(::sendPtrEvents), sendKeyEvents(::sendKeyEvents), sendSysKeys(::sendSysKeys),
preferredEncoding(encodingZRLE), clientCutText(::clientCutText), serverCutText(::serverCutText),
protocol3_3(::protocol3_3), acceptBell(::acceptBell), lowColourLevel(::lowColourLevel),
pointerEventInterval(ptrEventInterval), emulate3(::emulate3), monitor(::monitor.getData()),
@@ -214,6 +216,8 @@ void CViewOptions::readFromFile(const char* filename) {
sendPtrEvents = atoi(value.buf);
} else if (stricmp(name.buf, "SendKeyEvents") == 0) {
sendKeyEvents = atoi(value.buf);
+ } else if (stricmp(name.buf, "SendSysKeys") == 0) {
+ sendSysKeys = atoi(value.buf);
} else if (stricmp(name.buf, "SendCutText") == 0) {
clientCutText = atoi(value.buf);
} else if (stricmp(name.buf, "AcceptCutText") == 0) {
@@ -310,6 +314,7 @@ void CViewOptions::writeToFile(const char* filename) {
fprintf(f, "Shared=%d\n", (int)shared);
fprintf(f, "SendPtrEvents=%d\n", (int)sendPtrEvents);
fprintf(f, "SendKeyEvents=%d\n", (int)sendKeyEvents);
+ fprintf(f, "SendSysKeys=%d\n", (int)sendSysKeys);
fprintf(f, "SendCutText=%d\n", (int)clientCutText);
fprintf(f, "AcceptCutText=%d\n", (int)serverCutText);
fprintf(f, "Emulate3=%d\n", (int)emulate3);
@@ -344,6 +349,7 @@ void CViewOptions::writeDefaults() {
key.setBool(_T("Shared"), shared);
key.setBool(_T("SendPointerEvents"), sendPtrEvents);
key.setBool(_T("SendKeyEvents"), sendKeyEvents);
+ key.setBool(_T("SendSysKeys"), sendSysKeys);
key.setBool(_T("ClientCutText"), clientCutText);
key.setBool(_T("ServerCutText"), serverCutText);
key.setBool(_T("Protocol3.3"), protocol3_3);
@@ -399,6 +405,7 @@ CViewOptions& CViewOptions::operator=(const CViewOptions& o) {
shared = o.shared;
sendPtrEvents = o.sendPtrEvents;
sendKeyEvents = o.sendKeyEvents;
+ sendSysKeys = o.sendSysKeys;
clientCutText = o.clientCutText;
serverCutText = o.serverCutText;
emulate3 = o.emulate3;
diff --git a/vncviewer/CViewOptions.h b/vncviewer/CViewOptions.h
index d49cab14..b19c7508 100644
--- a/vncviewer/CViewOptions.h
+++ b/vncviewer/CViewOptions.h
@@ -58,6 +58,7 @@ namespace rfb {
bool shared;
bool sendPtrEvents;
bool sendKeyEvents;
+ bool sendSysKeys;
bool clientCutText;
bool serverCutText;
bool emulate3;
diff --git a/vncviewer/OptionsDialog.cxx b/vncviewer/OptionsDialog.cxx
index 954631fe..8655dc70 100644
--- a/vncviewer/OptionsDialog.cxx
+++ b/vncviewer/OptionsDialog.cxx
@@ -188,6 +188,7 @@ public:
virtual void initDialog() {
setItemChecked(IDC_SEND_POINTER, dlg->options.sendPtrEvents);
setItemChecked(IDC_SEND_KEYS, dlg->options.sendKeyEvents);
+ setItemChecked(IDC_SEND_SYSKEYS, dlg->options.sendSysKeys);
setItemChecked(IDC_CLIENT_CUTTEXT, dlg->options.clientCutText);
setItemChecked(IDC_SERVER_CUTTEXT, dlg->options.serverCutText);
setItemChecked(IDC_EMULATE3, dlg->options.emulate3);
@@ -210,6 +211,7 @@ public:
virtual bool onOk() {
dlg->options.sendPtrEvents = isItemChecked(IDC_SEND_POINTER);
dlg->options.sendKeyEvents = isItemChecked(IDC_SEND_KEYS);
+ dlg->options.sendSysKeys = isItemChecked(IDC_SEND_SYSKEYS);
dlg->options.clientCutText = isItemChecked(IDC_CLIENT_CUTTEXT);
dlg->options.serverCutText = isItemChecked(IDC_SERVER_CUTTEXT);
dlg->options.emulate3 = isItemChecked(IDC_EMULATE3);
diff --git a/vncviewer/cview.cxx b/vncviewer/cview.cxx
index 1765493f..180119a1 100644
--- a/vncviewer/cview.cxx
+++ b/vncviewer/cview.cxx
@@ -63,6 +63,8 @@ const int TIMER_BUMPSCROLL = 1;
const int TIMER_POINTER_INTERVAL = 2;
const int TIMER_POINTER_3BUTTON = 3;
+const int HOTKEY_ALTTAB = 0;
+
IntParameter debugDelay("DebugDelay","Milliseconds to display inverted "
"pixel data - a debugging feature", 0);
@@ -174,6 +176,9 @@ CView::CView()
bumpScrollTimer.setHWND(getHandle());
bumpScrollTimer.setId(TIMER_BUMPSCROLL);
+ // Grab AltTab
+ setAltTabGrab(options.sendSysKeys);
+
// Hook the clipboard
clipboard.setNotifier(this);
@@ -290,6 +295,8 @@ CView::applyOptions(CViewOptions& opt) {
// - Inputs
options.sendPtrEvents = opt.sendPtrEvents;
options.sendKeyEvents = opt.sendKeyEvents;
+ options.sendSysKeys = opt.sendSysKeys;
+ setAltTabGrab(options.sendSysKeys);
options.clientCutText = opt.clientCutText;
options.serverCutText = opt.serverCutText;
options.emulate3 = opt.emulate3;
@@ -692,10 +699,14 @@ CView::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
case WM_SETFOCUS:
has_focus = true;
+ // Re-register AltTab hotkey
+ setAltTabGrab(options.sendSysKeys);
break;
case WM_KILLFOCUS:
has_focus = false;
cursorOutsideBuffer();
+ // Unregister AltTab hotkey
+ setAltTabGrab(false);
// Restore the remote keys to consistent states
try {
kbd.releaseAllKeys(writer());
@@ -795,6 +806,35 @@ CView::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
// -=- Handle keyboard input
+ case WM_HOTKEY:
+ if (wParam == HOTKEY_ALTTAB) {
+ writeKeyEvent(VK_TAB, 0, true);
+ writeKeyEvent(VK_TAB, 0, false);
+ return 0;
+ }
+ break;
+
+ case WM_SYSKEYDOWN:
+ // Translate Alt-Space and Alt-F4 to WM_SYSCHAR and WM_CLOSE,
+ // since we are not using TranslateMessage().
+ if (!options.sendSysKeys) {
+ switch (wParam) {
+ case VK_SPACE:
+ writeKeyEvent(VK_MENU, 0, false);
+ SendMessage(getHandle(), WM_SYSCHAR, wParam, lParam);
+ return 0;
+ case VK_F4:
+ SendMessage(getHandle(), WM_CLOSE, wParam, lParam);
+ return 0;
+ }
+ }
+
+ case WM_SYSKEYUP:
+ // When we have registered for AltTab as a hotkey, SYSKEYUPs for
+ // Tabs are sent (but no SYSKEYDOWNs). AltTab is handled by
+ // WM_HOTKEY, though.
+ if (wParam == VK_TAB) return 0;
+
case WM_KEYUP:
case WM_KEYDOWN:
// Hook the MenuKey to pop-up the window menu
@@ -818,12 +858,11 @@ CView::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
TPM_CENTERALIGN | TPM_VCENTERALIGN, pt.x, pt.y, 0, getHandle(), 0);
}
- // Ignore the MenuKey keypress for both press & release events
- return 0;
+ // Ignore the MenuKey keypress for both press & release events
+ return 0;
}
}
- case WM_SYSKEYDOWN:
- case WM_SYSKEYUP:
+
writeKeyEvent(wParam, lParam, (msg == WM_KEYDOWN) || (msg == WM_SYSKEYDOWN));
return 0;
@@ -949,6 +988,26 @@ CView::showSystemCursor() {
}
}
+void
+CView::setAltTabGrab(bool grab) {
+ BOOL hotKeyResult;
+ static bool grabstate = false;
+
+ // Do not call RegisterHotKey/UnregisterHotKey if not necessary
+ if (grabstate == grab)
+ return;
+
+ grabstate = grab;
+
+ // Only works for NT/2k/XP
+ if (grab) {
+ hotKeyResult = RegisterHotKey(hwnd, HOTKEY_ALTTAB, MOD_ALT, VK_TAB);
+ if (!hotKeyResult)
+ vlog.debug("RegisterHotkey failed with error %d", GetLastError());
+ } else {
+ hotKeyResult = UnregisterHotKey(hwnd, HOTKEY_ALTTAB);
+ }
+}
bool
CView::invalidateBufferRect(const Rect& crect) {
diff --git a/vncviewer/cview.h b/vncviewer/cview.h
index 2bee1c48..ca97cdce 100644
--- a/vncviewer/cview.h
+++ b/vncviewer/cview.h
@@ -183,6 +183,9 @@ namespace rfb {
void hideSystemCursor();
void showSystemCursor();
+ // Grab AltTab?
+ void setAltTabGrab(bool grab);
+
// cursorOutsideBuffer() is called whenever we detect that the mouse has
// moved outside the desktop. It restores the system arrow cursor.
void cursorOutsideBuffer();
diff --git a/vncviewer/resource.h b/vncviewer/resource.h
index 3a08e574..0dde1955 100644
--- a/vncviewer/resource.h
+++ b/vncviewer/resource.h
@@ -68,6 +68,7 @@
#define IDC_COMPRESSLEVEL 1056
#define IDC_ALLOW_JPEG 1057
#define IDC_QUALITYLEVEL 1058
+#define IDC_SEND_SYSKEYS 1059
#define ID_CLOSE 40002
#define ID_OPTIONS 40003
#define ID_NEW_CONNECTION 40004
diff --git a/vncviewer/vncviewer.rc b/vncviewer/vncviewer.rc
index ad25574c..3545bc21 100644
--- a/vncviewer/vncviewer.rc
+++ b/vncviewer/vncviewer.rc
@@ -232,17 +232,19 @@ BEGIN
BS_AUTOCHECKBOX | WS_TABSTOP,7,10,172,15
CONTROL "Send keyboard events to server",IDC_SEND_KEYS,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,25,172,15
- CONTROL "Send clipboard changes to server",IDC_CLIENT_CUTTEXT,
+ CONTROL "Send system keys (Alt combinations) to server",IDC_SEND_SYSKEYS,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,40,172,15
+ CONTROL "Send clipboard changes to server",IDC_CLIENT_CUTTEXT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,55,172,15
CONTROL "Accept clipboard changes from server",
IDC_SERVER_CUTTEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
- 7,55,172,15
+ 7,70,172,15
CONTROL "Enable 3-button mouse emulation",IDC_EMULATE3,"Button",
- BS_AUTOCHECKBOX | WS_TABSTOP,7,70,172,15
+ BS_AUTOCHECKBOX | WS_TABSTOP,7,85,172,15
CONTROL "Rate-limit mouse move events",IDC_POINTER_INTERVAL,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,86,172,14
- LTEXT "Menu key",IDC_STATIC,7,100,98,15,SS_CENTERIMAGE
- COMBOBOX IDC_MENU_KEY,105,100,74,105,CBS_DROPDOWNLIST | CBS_SORT |
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,100,172,14
+ LTEXT "Menu key",IDC_STATIC,7,115,98,15,SS_CENTERIMAGE
+ COMBOBOX IDC_MENU_KEY,105,115,74,105,CBS_DROPDOWNLIST | CBS_SORT |
WS_VSCROLL | WS_TABSTOP
END