2 * FreeRDP: A Remote Desktop Protocol Client
5 * Copyright 2009-2011 Jay Sorg
6 * Copyright 2010-2011 Vic Lee
7 * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 #include <freerdp/freerdp.h>
28 static HWND g_focus_hWnd;
29 extern HCURSOR g_default_cursor;
31 #define X_POS(lParam) (lParam & 0xffff)
32 #define Y_POS(lParam) ((lParam >> 16) & 0xffff)
34 LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam)
43 DEBUG_KBD("Low-level keyboard hook, hWnd %X nCode %X wParam %X\n", g_focus_hWnd, nCode, wParam);
45 if (g_focus_hWnd && (nCode == HC_ACTION))
53 wfi = (wfInfo*) GetWindowLongPtr(g_focus_hWnd, GWLP_USERDATA);
54 p = (PKBDLLHOOKSTRUCT) lParam;
55 scanCode = (uint8) p->scanCode;
56 input = wfi->instance->input;
60 DEBUG_KBD("keydown %d scanCode %04X flags %02X vkCode %02X\n",
61 (wParam == WM_KEYDOWN), scanCode, flags, p->vkCode);
64 ((p->vkCode == VK_RETURN) || (p->vkCode == VK_CANCEL)) &&
65 (GetAsyncKeyState(VK_CONTROL) & 0x8000) &&
66 (GetAsyncKeyState(VK_MENU) & 0x8000)) /* could also use flags & LLKHF_ALTDOWN */
68 if (wParam == WM_KEYDOWN)
69 //wf_toggle_fullscreen(wfi);
73 if (scanCode == 0x45) /* NumLock-ish */
75 if (flags & LLKHF_EXTENDED)
77 /* Windows sends NumLock as extended - rdp doesn't */
78 DEBUG_KBD("hack: NumLock (x45) should not be extended\n");
79 flags &= ~LLKHF_EXTENDED;
83 /* Windows sends Pause as if it was a RDP NumLock (handled above).
84 * It must however be sent as a one-shot Ctrl+NumLock */
85 if (wParam == WM_KEYDOWN)
87 DEBUG_KBD("Pause, sent as Ctrl+NumLock\n");
88 input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x1D); /* Ctrl down */
89 input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x45); /* NumLock down */
90 input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x1D); /* Ctrl up */
91 input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x45); /* NumLock up */
95 DEBUG_KBD("Pause up\n");
102 if ((scanCode == 0x36) && (flags & LLKHF_EXTENDED))
104 DEBUG_KBD("hack: right shift (x36) should not be extended\n");
105 flags &= ~LLKHF_EXTENDED;
108 kbdFlags |= (flags & LLKHF_UP) ? KBD_FLAGS_RELEASE : KBD_FLAGS_DOWN;
109 kbdFlags |= (flags & LLKHF_EXTENDED) ? KBD_FLAGS_EXTENDED : 0;
110 input->KeyboardEvent(input, kbdFlags, scanCode);
112 if (p->vkCode == VK_CAPITAL)
113 DEBUG_KBD("caps lock is processed on client side too to toggle caps lock indicator\n");
121 return CallNextHookEx(NULL, nCode, wParam, lParam);
124 LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
135 ptr = GetWindowLongPtr(hWnd, GWLP_USERDATA);
140 input = wfi->instance->input;
145 hdc = BeginPaint(hWnd, &ps);
149 w = ps.rcPaint.right - ps.rcPaint.left + 1;
150 h = ps.rcPaint.bottom - ps.rcPaint.top + 1;
152 //printf("WM_PAINT: x:%d y:%d w:%d h:%d\n", x, y, w, h);
154 BitBlt(hdc, x, y, w, h, wfi->primary->hdc, x, y, SRCCOPY);
160 input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam), Y_POS(lParam));
164 input->MouseEvent(input, PTR_FLAGS_BUTTON1, X_POS(lParam), Y_POS(lParam));
168 input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, X_POS(lParam), Y_POS(lParam));
172 input->MouseEvent(input, PTR_FLAGS_BUTTON2, X_POS(lParam), Y_POS(lParam));
176 input->MouseEvent(input, PTR_FLAGS_MOVE, X_POS(lParam), Y_POS(lParam));
180 SetCursor(wfi->cursor);
199 PostQuitMessage(WM_QUIT);
203 SetCursor(g_default_cursor);
207 DEBUG_KBD("getting focus %X\n", hWnd);
212 DEBUG_KBD("loosing focus %X\n", hWnd);
213 if (g_focus_hWnd == hWnd)
218 return DefWindowProc(hWnd, Msg, wParam, lParam);