Fix changelog email address
[freerdp-ubuntu-pcb-backport.git] / client / Windows / wf_event.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * Event Handling
4  *
5  * Copyright 2009-2011 Jay Sorg
6  * Copyright 2010-2011 Vic Lee
7  * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
8  *
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
12  *
13  *     http://www.apache.org/licenses/LICENSE-2.0
14  *
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.
20  */
21
22 #include <stdio.h>
23 #include <freerdp/freerdp.h>
24 #include "wfreerdp.h"
25
26 #include "wf_event.h"
27
28 static HWND g_focus_hWnd;
29 extern HCURSOR g_default_cursor;
30
31 #define X_POS(lParam) (lParam & 0xffff)
32 #define Y_POS(lParam) ((lParam >> 16) & 0xffff)
33
34 LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam)
35 {
36         DWORD flags;
37         wfInfo* wfi;
38         uint8 scanCode;
39         rdpInput* input;
40         uint16 kbdFlags;
41         PKBDLLHOOKSTRUCT p;
42
43         DEBUG_KBD("Low-level keyboard hook, hWnd %X nCode %X wParam %X\n", g_focus_hWnd, nCode, wParam);
44
45         if (g_focus_hWnd && (nCode == HC_ACTION))
46         {
47                 switch (wParam)
48                 {
49                         case WM_KEYDOWN:
50                         case WM_SYSKEYDOWN:
51                         case WM_KEYUP:
52                         case WM_SYSKEYUP:
53                                 wfi = (wfInfo*) GetWindowLongPtr(g_focus_hWnd, GWLP_USERDATA);
54                                 p = (PKBDLLHOOKSTRUCT) lParam;
55                                 scanCode = (uint8) p->scanCode;
56                                 input = wfi->instance->input;
57                                 flags = p->flags;
58                                 kbdFlags = 0;
59
60                                 DEBUG_KBD("keydown %d scanCode %04X flags %02X vkCode %02X\n",
61                                         (wParam == WM_KEYDOWN), scanCode, flags, p->vkCode);
62
63                                 if (wfi->fs_toggle &&
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 */
67                                 {
68                                         if (wParam == WM_KEYDOWN)
69                                                 //wf_toggle_fullscreen(wfi);
70                                         return 1;
71                                 }
72
73                                 if (scanCode == 0x45) /* NumLock-ish */
74                                 {
75                                         if (flags & LLKHF_EXTENDED)
76                                         {
77                                                 /* Windows sends NumLock as extended - rdp doesn't */
78                                                 DEBUG_KBD("hack: NumLock (x45) should not be extended\n");
79                                                 flags &= ~LLKHF_EXTENDED;
80                                         }
81                                         else
82                                         {
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)
86                                                 {
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 */
92                                                 }
93                                                 else
94                                                 {
95                                                         DEBUG_KBD("Pause up\n");
96                                                 }
97
98                                                 return 1;
99                                         }
100                                 }
101
102                                 if ((scanCode == 0x36) && (flags & LLKHF_EXTENDED))
103                                 {
104                                         DEBUG_KBD("hack: right shift (x36) should not be extended\n");
105                                         flags &= ~LLKHF_EXTENDED;
106                                 }
107
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);
111
112                                 if (p->vkCode == VK_CAPITAL)
113                                         DEBUG_KBD("caps lock is processed on client side too to toggle caps lock indicator\n");
114                                 else
115                                         return 1;
116
117                                 break;
118                 }
119         }
120
121         return CallNextHookEx(NULL, nCode, wParam, lParam);
122 }
123
124 LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
125 {
126         HDC hdc;
127         LONG ptr;
128         wfInfo* wfi;
129         int x, y, w, h;
130         PAINTSTRUCT ps;
131         rdpInput* input;
132         boolean processed;
133
134         processed = true;
135         ptr = GetWindowLongPtr(hWnd, GWLP_USERDATA);
136         wfi = (wfInfo*) ptr;
137
138         if (wfi != NULL)
139         {
140                 input = wfi->instance->input;
141
142                 switch (Msg)
143                 {
144                         case WM_PAINT:
145                                 hdc = BeginPaint(hWnd, &ps);
146                                 
147                                 x = ps.rcPaint.left;
148                                 y = ps.rcPaint.top;
149                                 w = ps.rcPaint.right - ps.rcPaint.left + 1;
150                                 h = ps.rcPaint.bottom - ps.rcPaint.top + 1;
151
152                                 //printf("WM_PAINT: x:%d y:%d w:%d h:%d\n", x, y, w, h);
153
154                                 BitBlt(hdc, x, y, w, h, wfi->primary->hdc, x, y, SRCCOPY);
155
156                                 EndPaint(hWnd, &ps);
157                                 break;
158
159                         case WM_LBUTTONDOWN:
160                                 input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam), Y_POS(lParam));
161                                 break;
162
163                         case WM_LBUTTONUP:
164                                 input->MouseEvent(input, PTR_FLAGS_BUTTON1, X_POS(lParam), Y_POS(lParam));
165                                 break;
166
167                         case WM_RBUTTONDOWN:
168                                 input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, X_POS(lParam), Y_POS(lParam));
169                                 break;
170
171                         case WM_RBUTTONUP:
172                                 input->MouseEvent(input, PTR_FLAGS_BUTTON2, X_POS(lParam), Y_POS(lParam));
173                                 break;
174
175                         case WM_MOUSEMOVE:
176                                 input->MouseEvent(input, PTR_FLAGS_MOVE, X_POS(lParam), Y_POS(lParam));
177                                 break;
178
179                         case WM_SETCURSOR:
180                                 SetCursor(wfi->cursor);
181                                 break;
182
183                         default:
184                                 processed = false;
185                                 break;
186                 }
187         }
188         else
189         {
190                 processed = false;
191         }
192
193         if (processed)
194                 return 0;
195
196         switch (Msg)
197         {
198                 case WM_DESTROY:
199                         PostQuitMessage(WM_QUIT);
200                         break;
201
202                 case WM_SETCURSOR:
203                         SetCursor(g_default_cursor);
204                         break;
205
206                 case WM_SETFOCUS:
207                         DEBUG_KBD("getting focus %X\n", hWnd);
208                         g_focus_hWnd = hWnd;
209                         break;
210
211                 case WM_KILLFOCUS:
212                         DEBUG_KBD("loosing focus %X\n", hWnd);
213                         if (g_focus_hWnd == hWnd)
214                                 g_focus_hWnd = NULL;
215                         break;
216
217                 default:
218                         return DefWindowProc(hWnd, Msg, wParam, lParam);
219                         break;
220         }
221
222         return 0;
223 }