diff options
-rw-r--r-- | vncviewer/CViewOptions.cxx | 9 | ||||
-rw-r--r-- | vncviewer/CViewOptions.h | 1 | ||||
-rw-r--r-- | vncviewer/OptionsDialog.cxx | 2 | ||||
-rw-r--r-- | vncviewer/cview.cxx | 67 | ||||
-rw-r--r-- | vncviewer/cview.h | 3 | ||||
-rw-r--r-- | vncviewer/resource.h | 1 | ||||
-rw-r--r-- | vncviewer/vncviewer.rc | 14 |
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 |