From: Arnon Gilboa <agil...@redhat.com>

-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(-)

diff --git a/client/application.cpp b/client/application.cpp
index 2f24307..ac5877c 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 5c60702..5fa9335 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 3c7ac77..5721c53 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 8716b07..14a7d29 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 2f17cb1..ee43b5a 100644
--- a/client/x11/red_window.cpp
+++ b/client/x11/red_window.cpp
@@ -2046,3 +2046,7 @@ void RedWindow::init()
 #endif
 }
 
+void RedWindow::cleanup()
+{
+}
+
-- 
1.5.5.6


------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
Spice-space-devel mailing list
Spice-space-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spice-space-devel

Reply via email to