From 8ce343daa08d2807428f71f552e22ab5319f8aea Mon Sep 17 00:00:00 2001 From: Arnon Gilboa Date: Wed, 30 Dec 2009 12:19:54 +0200 Subject: spice: on_activate_screen generates on_key_down for any modifier pressed -call SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc...) only once, in RedWindow::init() -add Application::cleanup_globals() & RedWindow::cleanup() -cleanup LowLevelKeyboardProc() --- client/application.cpp | 57 +++++++++++++++++++++++++++++++------------ client/application.h | 2 ++ client/red_window.h | 1 + client/windows/red_window.cpp | 50 +++++++++++++------------------------ client/x11/red_window.cpp | 4 +++ 5 files changed, 66 insertions(+), 48 deletions(-) (limited to 'client') diff --git a/client/application.cpp b/client/application.cpp index fb14fff6..778d1031 100644 --- a/client/application.cpp +++ b/client/application.cpp @@ -914,6 +914,32 @@ void Application::reset_sticky() } +struct ModifierKey { + int modifier; + RedKey key; +}; + +ModifierKey modifier_keys[] = { + {Platform::L_SHIFT_MODIFIER, REDKEY_L_SHIFT}, + {Platform::R_SHIFT_MODIFIER, REDKEY_R_SHIFT}, + {Platform::L_CTRL_MODIFIER, REDKEY_L_CTRL}, + {Platform::R_CTRL_MODIFIER, REDKEY_R_CTRL}, + {Platform::L_ALT_MODIFIER, REDKEY_L_ALT}, + {Platform::R_ALT_MODIFIER, REDKEY_R_ALT}, +}; + +void Application::sync_keyboard_modifiers() +{ + uint32_t modifiers = Platform::get_keyboard_modifiers(); + for (int i = 0; i < sizeof(modifier_keys) / sizeof(modifier_keys[0]); i++) { + if (modifiers & modifier_keys[i].modifier) { + on_key_down(modifier_keys[i].key); + } else { + on_key_up(modifier_keys[i].key); + } + } +} + void Application::on_key_down(RedKey key) { if (key <= 0 || key >= REDKEY_NUM_KEYS) { @@ -1037,6 +1063,7 @@ void Application::on_activate_screen(RedScreen* screen) { ASSERT(!_active_screen || (_active_screen == screen)); _active_screen = screen; + sync_keyboard_modifiers(); } void Application::on_start_screen_key_interception(RedScreen* screen) @@ -1211,6 +1238,7 @@ void Application::exit_full_screen() return; } LOG_INFO(""); + _changing_screens = true; release_capture(); for (int i = 0; i < (int)_screens.size(); i++) { if (_screens[i]) { @@ -1226,27 +1254,16 @@ void Application::exit_full_screen() _full_screen = false; show(); _main_screen->activate(); + _changing_screens = false; } bool Application::toggle_full_screen() { - RedKey shift_pressed = REDKEY_INVALID; - - if (_key_table[REDKEY_L_SHIFT].press) { - shift_pressed = REDKEY_L_SHIFT; - } else if (_key_table[REDKEY_R_SHIFT].press) { - shift_pressed = REDKEY_R_SHIFT; - } if (_full_screen) { exit_full_screen(); } else { enter_full_screen(); } - uint32_t modifiers = Platform::get_keyboard_modifiers(); - if ((shift_pressed == REDKEY_L_SHIFT && (modifiers & Platform::L_SHIFT_MODIFIER)) || - (shift_pressed == REDKEY_R_SHIFT && (modifiers & Platform::R_SHIFT_MODIFIER))) { - on_key_down(shift_pressed); - } return _full_screen; } @@ -1774,15 +1791,25 @@ void Application::init_globals() RedWindow::init(); } +void Application::cleanup_globals() +{ + RedWindow::cleanup(); +} + int Application::main(int argc, char** argv, const char* version_str) { + int ret; + init_globals(); LOG_INFO("starting %s", version_str); std::auto_ptr app(new Application()); AutoAbort auto_abort(*app.get()); - if (!app->process_cmd_line(argc, argv)) { - return app->_exit_code; + if (app->process_cmd_line(argc, argv)) { + ret = app->run(); + } else { + ret = app->_exit_code; } - return app->run(); + cleanup_globals(); + return ret; } diff --git a/client/application.h b/client/application.h index c576dba6..38fd30ec 100644 --- a/client/application.h +++ b/client/application.h @@ -208,9 +208,11 @@ private: bool unpress_key(RedKey key); void reset_sticky(); static bool is_sticky_trace_key(RedKey key); + void sync_keyboard_modifiers(); static void init_logger(); static void init_globals(); + static void cleanup_globals(); friend class DisconnectedEvent; friend class ConnectionErrorEvent; diff --git a/client/red_window.h b/client/red_window.h index 0d3e781a..6f51f70e 100644 --- a/client/red_window.h +++ b/client/red_window.h @@ -86,6 +86,7 @@ public: void unset_type_gl(); static void init(); + static void cleanup(); Listener& get_listener() { return _listener;} diff --git a/client/windows/red_window.cpp b/client/windows/red_window.cpp index 9365c69d..554c1770 100644 --- a/client/windows/red_window.cpp +++ b/client/windows/red_window.cpp @@ -35,6 +35,7 @@ static ATOM class_atom = 0; static const LPCWSTR win_class_name = L"redc_wclass"; static HWND focus_window = NULL; static HHOOK low_keyboard_hook = NULL; +static bool low_keyboard_hook_on = false; static HHOOK msg_filter_hook = NULL; typedef std::list KeysList; static KeysList filtered_up_keys; @@ -652,30 +653,14 @@ Point RedWindow::get_size() static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { - if ((nCode == HC_ACTION)) { + if (low_keyboard_hook_on && focus_window && nCode == HC_ACTION) { KBDLLHOOKSTRUCT *hooked = (KBDLLHOOKSTRUCT*)lParam; - DWORD dwMsg = 1; - - // dwMsg shall contain the information that would be stored - // in the usual lParam argument of a WM_KEYDOWN message. - // All information like hardware scan code and other flags - // are stored within one double word at different bit offsets. - // Refer to MSDN for further information: - // - // (Keystroke Messages) - dwMsg += hooked->scanCode << 16; - dwMsg += hooked->flags << 24; - - // In some cases scan code of VK_RSHIFT is fake shift (probably a bug) so we - // convert it to non extended code. Also, QEmu doesn't expect num-lock to be - // an extended key. - if ((hooked->vkCode == VK_NUMLOCK) || (hooked->vkCode == VK_RSHIFT)) { + DWORD dwMsg = (hooked->flags << 24) | (hooked->scanCode << 16) | 1; + + if (hooked->vkCode == VK_NUMLOCK || hooked->vkCode == VK_RSHIFT) { dwMsg &= ~(1 << 24); + SendMessage(focus_window, wParam, hooked->vkCode, dwMsg); } - - SendMessage(focus_window, wParam, hooked->vkCode, dwMsg); - - // Forward all modifier key strokes to update keyboard leds & shift/ctrl/alt state switch (hooked->vkCode) { case VK_CAPITAL: case VK_SCROLL: @@ -688,34 +673,25 @@ static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lP case VK_RMENU: break; default: + SendMessage(focus_window, wParam, hooked->vkCode, dwMsg); return 1; } } - - // In all other cases, we call the next hook and return it's value. return CallNextHookEx(NULL, nCode, wParam, lParam); } void RedWindow::do_start_key_interception() { + low_keyboard_hook_on = true; _key_interception_on = true; _listener.on_start_key_interception(); - if (low_keyboard_hook) { - return; - } - low_keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, - GetModuleHandle(NULL), 0); } void RedWindow::do_stop_key_interception() { + low_keyboard_hook_on = false; _key_interception_on = false; _listener.on_stop_key_interception(); - if (!low_keyboard_hook) { - return; - } - UnhookWindowsHookEx(low_keyboard_hook); - low_keyboard_hook = NULL; } void RedWindow::start_key_interception() @@ -745,6 +721,13 @@ void RedWindow::init() if (!(class_atom = register_class(instance))) { THROW("register class failed"); } + low_keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, + GetModuleHandle(NULL), 0); +} + +void RedWindow::cleanup() +{ + UnhookWindowsHookEx(low_keyboard_hook); } #ifdef USE_OGL @@ -788,6 +771,7 @@ void RedWindow::on_focus_out() } _focused = false; + focus_window = NULL; if (_key_interception_on) { do_stop_key_interception(); diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp index 2b4228a2..1647cd4d 100644 --- a/client/x11/red_window.cpp +++ b/client/x11/red_window.cpp @@ -1998,3 +1998,7 @@ void RedWindow::init() #endif } +void RedWindow::cleanup() +{ +} + -- cgit