# HG changeset patch
# User Mads Kiilerich <m...@kiilerich.com>
# Date 1300226300 -3600
# Node ID 2760f5e8d4b601f360ac76ac2e74be058be27873
# Parent  d1714a5c82b3d77f8c3c979703cd32629448b0c7
wfreerdp: use LowLevelKeyboardProc hook for keyboard input

It seems like this is better for our purpose than processing ordinary events.

This also makes it possible to intercept Alt+Tab and process it remotely.

The low level events are not tied to a window or to having focus, so we have to
keep a global telling us where we have focus.

diff --git a/win/wfreerdp/wf_event.cpp b/win/wfreerdp/wf_event.cpp
--- a/win/wfreerdp/wf_event.cpp
+++ b/win/wfreerdp/wf_event.cpp
@@ -23,12 +23,54 @@
 #include "wf_event.h"
 
 extern HCURSOR g_default_cursor;
+extern HWND g_hWnd;
 
 #define X_POS(lParam) (lParam & 0xffff)
 #define Y_POS(lParam) ((lParam >> 16) & 0xffff)
 #define SCANCODE(lParam) ((lParam >> 16) & 0xff)
 
 LRESULT CALLBACK
+wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+       HWND hWnd = g_hWnd;
+       wfInfo * wfi;
+       DWORD scanCode, flags;
+
+       DEBUG_KBD("hWnd %X nCode %X\n", hWnd, nCode);
+       if (hWnd && (nCode == HC_ACTION)) {
+               switch (wParam) {
+               case WM_KEYDOWN:
+               case WM_SYSKEYDOWN:
+               case WM_KEYUP:
+               case WM_SYSKEYUP:
+                       wfi = (wfInfo *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+                       PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
+                       scanCode = p->scanCode;
+                       flags = p->flags;
+                       DEBUG_KBD("wParam %04X scanCode %04X flags %02X vkCode 
%02X\n",
+                                       wParam, scanCode, flags, p->vkCode);
+
+                       if ((scanCode == 0x36) && (flags & 1))
+                       {
+                               DEBUG_KBD("hack: sending extended right shift 
(x36) as plain left shift (0x2a)\n");
+                               scanCode = 0x2a;
+                               flags &= ~1;
+                       }
+
+                       wfi->inst->rdp_send_input(wfi->inst, RDP_INPUT_SCANCODE,
+                                       ((flags & 0x80) ? KBD_FLAG_UP : 0) |
+                                       ((flags & 1) ? KBD_FLAG_EXT : 0),
+                                       scanCode, 0);
+                       if (p->vkCode == VK_CAPITAL)
+                               DEBUG_KBD("caps lock is processed on client 
side too to toggle caps lock indicator\n");
+                       else
+                               return 1;
+               }
+       }
+       return CallNextHookEx(NULL, nCode, wParam, lParam);
+}
+
+LRESULT CALLBACK
 wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
        wfInfo * wfi;
@@ -98,36 +140,6 @@
                }
                break;
 
-       case WM_KEYDOWN:
-               if (wfi != NULL)
-               {
-#ifdef WITH_DEBUG_KBD
-                       printf("key down: lParam=0x%08X = %3d\n", lParam, 
SCANCODE(lParam));
-#endif
-                       wfi->inst->rdp_send_input(wfi->inst, RDP_INPUT_SCANCODE,
-                               RDP_KEYPRESS, SCANCODE(lParam), 0);
-               }
-               break;
-
-       case WM_KEYUP:
-               if (wfi != NULL)
-               {
-#ifdef WITH_DEBUG_KBD
-                       printf("key up:   lParam=0x%08X = %3d\n", lParam, 
SCANCODE(lParam));
-#endif
-                       wfi->inst->rdp_send_input(wfi->inst, RDP_INPUT_SCANCODE,
-                               RDP_KEYRELEASE, SCANCODE(lParam), 0);
-                       if (SCANCODE(lParam) == 56)
-                       {
-#ifdef WITH_DEBUG_KBD
-                               printf("faking key up for left ctrl = 29 for 
key up of AltGr = 56\n");
-#endif
-                               wfi->inst->rdp_send_input(wfi->inst, 
RDP_INPUT_SCANCODE,
-                                       RDP_KEYRELEASE, 29, 0);
-                       }
-               }
-               break;
-
        case WM_SETCURSOR:
                if (wfi != NULL)
                {
@@ -139,10 +151,19 @@
                }
                break;
 
+       case WM_SETFOCUS:
+               DEBUG_KBD("getting focus %X\n", hWnd);
+               g_hWnd = hWnd;
+               break;
+
+       case WM_KILLFOCUS:
+               DEBUG_KBD("loosing focus %X\n", hWnd);
+               if (g_hWnd == hWnd)
+                       g_hWnd = NULL; // racy - but probably not in a fatal way
+               break;
+
        default:
-               // Process the left-over messages
                return DefWindowProc(hWnd, Msg, wParam, lParam);
        }
-       // If something was not done, let it go
        return 0;
 }
diff --git a/win/wfreerdp/wf_event.h b/win/wfreerdp/wf_event.h
--- a/win/wfreerdp/wf_event.h
+++ b/win/wfreerdp/wf_event.h
@@ -23,6 +23,8 @@
 #include <windows.h>
 
 LRESULT CALLBACK
+wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK
 wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
 
 #endif
diff --git a/win/wfreerdp/wf_win.cpp b/win/wfreerdp/wf_win.cpp
--- a/win/wfreerdp/wf_win.cpp
+++ b/win/wfreerdp/wf_win.cpp
@@ -27,6 +27,7 @@
 extern LPCTSTR g_wnd_class_name;
 extern HINSTANCE g_hInstance;
 extern HCURSOR g_default_cursor;
+extern HWND g_hWnd;
 
 // See http://msdn.microsoft.com/en-us/library/dd145130(VS.85).aspx
 static const DWORD rop3_code_table[] =
@@ -1189,6 +1190,7 @@
        }
        wfi->drw = wfi->backstore;
 
+       g_hWnd = wfi->hwnd;
        ShowWindow(wfi->hwnd, SW_SHOWNORMAL);
        UpdateWindow(wfi->hwnd);
 
diff --git a/win/wfreerdp/wfreerdp.cpp b/win/wfreerdp/wfreerdp.cpp
--- a/win/wfreerdp/wfreerdp.cpp
+++ b/win/wfreerdp/wfreerdp.cpp
@@ -39,6 +39,7 @@
 HCURSOR g_default_cursor;
 volatile int g_thread_count = 0;
 HANDLE g_done_event;
+HWND g_hWnd;
 
 static int
 create_console(void)
@@ -588,6 +589,40 @@
        return NULL;
 }
 
+static DWORD WINAPI
+kbd_thread_func(LPVOID lpParam)
+{
+       HHOOK hook_handle;
+       MSG msg;
+       BOOL bRet;
+
+       DEBUG("keyboard thread started\n");
+
+       hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, wf_ll_kbd_proc, NULL, 0);
+       if (hook_handle)
+       {
+               while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
+               {
+                       if (bRet == -1)
+                       {
+                               printf("keyboard thread error getting 
message\n");
+                               break;
+                       }
+                       else
+                       {
+                               TranslateMessage(&msg);
+                               DispatchMessage(&msg);
+                       }
+               }
+               DEBUG("keyboard thread ended\n");
+               UnhookWindowsHookEx(hook_handle);
+       }
+       else
+               printf("failed to install keyboard hook\n");
+
+       return NULL;
+}
+
 INT WINAPI
 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int 
nCmdShow)
 {
@@ -627,11 +662,13 @@
        wnd_cls.lpszClassName = g_wnd_class_name;
        wnd_cls.hInstance     = hInstance;
        wnd_cls.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
-
        RegisterClassEx(&wnd_cls);
 
        g_hInstance = hInstance;
 
+       if (!CreateThread(NULL, 0, kbd_thread_func, NULL, 0, NULL))
+               printf("error creating keyboard handler thread");
+
        argv = CommandLineToArgvW(GetCommandLine(), &argc);
 
        while (1)

------------------------------------------------------------------------------
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d
_______________________________________________
Freerdp-devel mailing list
Freerdp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freerdp-devel

Reply via email to