summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnon Gilboa <agilboa@redhat.com>2009-12-30 12:19:54 +0200
committerYaniv Kamay <ykamay@redhat.com>2010-01-03 17:51:17 +0200
commit8ce343daa08d2807428f71f552e22ab5319f8aea (patch)
treefb319753001d23fda2cb174de30db4d1b6539f8f
parentd8a3c2c12a306eb814cebe8dac894950652f441a (diff)
downloadspice-8ce343daa08d2807428f71f552e22ab5319f8aea.tar.gz
spice-8ce343daa08d2807428f71f552e22ab5319f8aea.tar.xz
spice-8ce343daa08d2807428f71f552e22ab5319f8aea.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.cpp57
-rw-r--r--client/application.h2
-rw-r--r--client/red_window.h1
-rw-r--r--client/windows/red_window.cpp50
-rw-r--r--client/x11/red_window.cpp4
5 files changed, 66 insertions, 48 deletions
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<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 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<RedKey> 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()
+{
+}
+