/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include #include #include #include #include using namespace rfb; using namespace win32; static LogWriter vlog("LowLevelKeyEvents"); HHOOK hook = 0; std::list windows; Mutex windowLock; static bool filterKeyEvent(int vkCode) { switch (vkCode) { case VK_LWIN: case VK_RWIN: case VK_SNAPSHOT: return true; case VK_TAB: if (GetAsyncKeyState(VK_MENU) & 0x8000) return true; case VK_ESCAPE: if (GetAsyncKeyState(VK_MENU) & 0x8000) return true; if (GetAsyncKeyState(VK_CONTROL) & 0x8000) return true; } return false; } LRESULT CALLBACK LowLevelKeyEventProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode >= 0) { Lock l(windowLock); HWND foreground = GetForegroundWindow(); std::list::iterator i; for (i=windows.begin(); i!=windows.end(); i++) { if (*i == foreground) { UINT msgType = wParam; KBDLLHOOKSTRUCT* msgInfo = (KBDLLHOOKSTRUCT*)lParam; if (filterKeyEvent(msgInfo->vkCode)) { vlog.debug("filtered event %lx(%lu) %lu", msgInfo->vkCode, msgInfo->vkCode, msgType); PostMessage(*i, wParam, msgInfo->vkCode, (msgInfo->scanCode & 0xff) << 16); return 1; } } } } return CallNextHookEx(hook, nCode, wParam, lParam); } bool rfb::win32::enableLowLevelKeyEvents(HWND hwnd) { // *** return false; // *** THIS CODE IS EXPERIMENTAL, SO DISABLED BY DEFAULT! Lock l(windowLock); if (windows.empty() && !hook) hook = SetWindowsHookEx(WH_KEYBOARD_LL, &LowLevelKeyEventProc, GetModuleHandle(0), 0); if (hook) windows.push_back(hwnd); vlog.debug("enable %p -> %s", hwnd, hook ? "success" : "failure"); return hook != 0; } void rfb::win32::disableLowLevelKeyEvents(HWND hwnd) { vlog.debug("disable %p", hwnd); Lock l(windowLock); windows.remove(hwnd); if (windows.empty() && hook) { UnhookWindowsHookEx(hook); hook = 0; } }