diff options
author | Arnon Gilboa <agilboa@redhat.com> | 2009-12-30 12:19:54 +0200 |
---|---|---|
committer | Yaniv Kamay <ykamay@redhat.com> | 2009-12-30 22:09:25 +0200 |
commit | 02a07b2c067e629749cbe8a9f9cfbfb487a512d7 (patch) | |
tree | e73f6dc72a73b158369aa62e7220bd787eafcdc2 | |
parent | c57bcf6f4433446b858867712ece4abec4fb5c3d (diff) | |
download | spice-02a07b2c067e629749cbe8a9f9cfbfb487a512d7.tar.gz spice-02a07b2c067e629749cbe8a9f9cfbfb487a512d7.tar.xz spice-02a07b2c067e629749cbe8a9f9cfbfb487a512d7.zip |
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()
-rw-r--r-- | client/application.cpp | 57 | ||||
-rw-r--r-- | client/application.h | 2 | ||||
-rw-r--r-- | client/red_window.h | 1 | ||||
-rw-r--r-- | client/windows/red_window.cpp | 50 | ||||
-rw-r--r-- | client/x11/red_window.cpp | 4 |
5 files changed, 66 insertions, 48 deletions
diff --git a/client/application.cpp b/client/application.cpp index 2f24307d..ac5877c4 100644 --- a/client/application.cpp +++ b/client/application.cpp @@ -1062,6 +1062,32 @@ void Application::reset_sticky() _sticky_info.key = REDKEY_INVALID; } +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) { @@ -1179,6 +1205,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) @@ -1380,6 +1407,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]) { @@ -1396,27 +1424,16 @@ void Application::exit_full_screen() restore_screens_size(); show(); _main_screen->activate(); + _changing_screens = false; } bool Application::toggle_full_screen() { - RedKey shift_pressed = REDKEY_INVALID; - - if (_keyboard_state[REDKEY_L_SHIFT]) { - shift_pressed = REDKEY_L_SHIFT; - } else if (_keyboard_state[REDKEY_R_SHIFT]) { - 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; } @@ -1978,15 +1995,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<Application> 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 5c607025..5fa93358 100644 --- a/client/application.h +++ b/client/application.h @@ -265,9 +265,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 3c7ac77b..5721c53a 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 8716b073..14a7d291 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<RedKey> KeysList; static KeysList filtered_up_keys; @@ -714,30 +715,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: @@ -750,34 +735,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() @@ -807,6 +783,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 @@ -850,6 +833,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 2f17cb1d..ee43b5a5 100644 --- a/client/x11/red_window.cpp +++ b/client/x11/red_window.cpp @@ -2046,3 +2046,7 @@ void RedWindow::init() #endif } +void RedWindow::cleanup() +{ +} + |