[WIN32K]
[reactos.git] / reactos / win32ss / user / ntuser / caret.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Caret functions
5 * FILE: subsystems/win32/win32k/ntuser/caret.c
6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
7 */
8
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserCaret);
11
12 /* DEFINES *****************************************************************/
13
14 #define MIN_CARETBLINKRATE 100
15 #define MAX_CARETBLINKRATE 10000
16
17 /* FUNCTIONS *****************************************************************/
18
19 static
20 BOOL FASTCALL
21 co_IntHideCaret(PTHRDCARETINFO CaretInfo)
22 {
23 PWND pWnd;
24 if(CaretInfo->hWnd && CaretInfo->Visible && CaretInfo->Showing)
25 {
26 pWnd = UserGetWindowObject(CaretInfo->hWnd);
27 co_IntSendMessage(CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
28 CaretInfo->Showing = 0;
29 IntNotifyWinEvent(EVENT_OBJECT_HIDE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
30 return TRUE;
31 }
32 return FALSE;
33 }
34
35 BOOL FASTCALL
36 co_IntDestroyCaret(PTHREADINFO Win32Thread)
37 {
38 PUSER_MESSAGE_QUEUE ThreadQueue;
39 PWND pWnd;
40 ThreadQueue = (PUSER_MESSAGE_QUEUE)Win32Thread->MessageQueue;
41
42 if(!ThreadQueue || !ThreadQueue->CaretInfo)
43 return FALSE;
44
45 pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
46 co_IntHideCaret(ThreadQueue->CaretInfo);
47 ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0;
48 ThreadQueue->CaretInfo->hWnd = (HWND)0;
49 ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0;
50 ThreadQueue->CaretInfo->Showing = 0;
51 ThreadQueue->CaretInfo->Visible = 0;
52 IntNotifyWinEvent(EVENT_OBJECT_DESTROY, pWnd, OBJID_CARET, CHILDID_SELF, 0);
53 return TRUE;
54 }
55
56 BOOL FASTCALL
57 IntSetCaretBlinkTime(UINT uMSeconds)
58 {
59 /* Don't save the new value to the registry! */
60
61 /* Windows doesn't do this check */
62 if((uMSeconds < MIN_CARETBLINKRATE) || (uMSeconds > MAX_CARETBLINKRATE))
63 {
64 EngSetLastError(ERROR_INVALID_PARAMETER);
65 return FALSE;
66 }
67
68 gpsi->dtCaretBlink = uMSeconds;
69
70 return TRUE;
71 }
72
73 BOOL FASTCALL
74 co_IntSetCaretPos(int X, int Y)
75 {
76 PTHREADINFO pti;
77 PWND pWnd;
78 PUSER_MESSAGE_QUEUE ThreadQueue;
79
80 pti = PsGetCurrentThreadWin32Thread();
81 ThreadQueue = pti->MessageQueue;
82
83 if(ThreadQueue->CaretInfo->hWnd)
84 {
85 pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
86 if(ThreadQueue->CaretInfo->Pos.x != X || ThreadQueue->CaretInfo->Pos.y != Y)
87 {
88 co_IntHideCaret(ThreadQueue->CaretInfo);
89 ThreadQueue->CaretInfo->Showing = 0;
90 ThreadQueue->CaretInfo->Pos.x = X;
91 ThreadQueue->CaretInfo->Pos.y = Y;
92 co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
93 IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, gpsi->dtCaretBlink, NULL, TMRF_SYSTEM);
94 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
95 }
96 return TRUE;
97 }
98
99 return FALSE;
100 }
101
102 BOOL FASTCALL
103 IntSwitchCaretShowing(PVOID Info)
104 {
105 PTHREADINFO pti;
106 PUSER_MESSAGE_QUEUE ThreadQueue;
107
108 pti = PsGetCurrentThreadWin32Thread();
109 ThreadQueue = pti->MessageQueue;
110
111 if(ThreadQueue->CaretInfo->hWnd)
112 {
113 ThreadQueue->CaretInfo->Showing = (ThreadQueue->CaretInfo->Showing ? 0 : 1);
114 MmCopyToCaller(Info, ThreadQueue->CaretInfo, sizeof(THRDCARETINFO));
115 return TRUE;
116 }
117
118 return FALSE;
119 }
120
121 #if 0 // Unused
122 static
123 VOID FASTCALL
124 co_IntDrawCaret(HWND hWnd)
125 {
126 PTHREADINFO pti;
127 PUSER_MESSAGE_QUEUE ThreadQueue;
128
129 pti = PsGetCurrentThreadWin32Thread();
130 ThreadQueue = pti->MessageQueue;
131
132 if(ThreadQueue->CaretInfo->hWnd && ThreadQueue->CaretInfo->Visible &&
133 ThreadQueue->CaretInfo->Showing)
134 {
135 co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
136 ThreadQueue->CaretInfo->Showing = 1;
137 }
138 }
139 #endif
140
141
142
143 BOOL FASTCALL co_UserHideCaret(PWND Window OPTIONAL)
144 {
145 PTHREADINFO pti;
146 PUSER_MESSAGE_QUEUE ThreadQueue;
147
148 if (Window) ASSERT_REFS_CO(Window);
149
150 if(Window && Window->head.pti->pEThread != PsGetCurrentThread())
151 {
152 EngSetLastError(ERROR_ACCESS_DENIED);
153 return FALSE;
154 }
155
156 pti = PsGetCurrentThreadWin32Thread();
157 ThreadQueue = pti->MessageQueue;
158
159 if(Window && ThreadQueue->CaretInfo->hWnd != Window->head.h)
160 {
161 EngSetLastError(ERROR_ACCESS_DENIED);
162 return FALSE;
163 }
164
165 if(ThreadQueue->CaretInfo->Visible)
166 {
167 PWND pwnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
168 IntKillTimer(pwnd, IDCARETTIMER, TRUE);
169
170 co_IntHideCaret(ThreadQueue->CaretInfo);
171 ThreadQueue->CaretInfo->Visible = 0;
172 ThreadQueue->CaretInfo->Showing = 0;
173 }
174
175 return TRUE;
176 }
177
178
179 BOOL FASTCALL co_UserShowCaret(PWND Window OPTIONAL)
180 {
181 PTHREADINFO pti;
182 PWND pWnd;
183 PUSER_MESSAGE_QUEUE ThreadQueue;
184
185 if (Window) ASSERT_REFS_CO(Window);
186
187 if(Window && Window->head.pti->pEThread != PsGetCurrentThread())
188 {
189 EngSetLastError(ERROR_ACCESS_DENIED);
190 return FALSE;
191 }
192
193 pti = PsGetCurrentThreadWin32Thread();
194 ThreadQueue = pti->MessageQueue;
195
196 if(Window && ThreadQueue->CaretInfo->hWnd != Window->head.h)
197 {
198 EngSetLastError(ERROR_ACCESS_DENIED);
199 return FALSE;
200 }
201
202 if(!ThreadQueue->CaretInfo->Visible)
203 {
204 ThreadQueue->CaretInfo->Visible = 1;
205 if(!ThreadQueue->CaretInfo->Showing)
206 {
207 pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
208 co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
209 IntNotifyWinEvent(EVENT_OBJECT_SHOW, pWnd, OBJID_CARET, OBJID_CARET, 0);
210 }
211 IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, gpsi->dtCaretBlink, NULL, TMRF_SYSTEM);
212 }
213 return TRUE;
214 }
215
216
217 /* SYSCALLS *****************************************************************/
218
219 BOOL
220 APIENTRY
221 NtUserCreateCaret(
222 HWND hWnd,
223 HBITMAP hBitmap,
224 int nWidth,
225 int nHeight)
226 {
227 PWND Window;
228 PTHREADINFO pti;
229 PUSER_MESSAGE_QUEUE ThreadQueue;
230 DECLARE_RETURN(BOOL);
231
232 TRACE("Enter NtUserCreateCaret\n");
233 UserEnterExclusive();
234
235 if(!(Window = UserGetWindowObject(hWnd)))
236 {
237 RETURN(FALSE);
238 }
239
240 if(Window->head.pti->pEThread != PsGetCurrentThread())
241 {
242 EngSetLastError(ERROR_ACCESS_DENIED);
243 RETURN(FALSE);
244 }
245
246 pti = PsGetCurrentThreadWin32Thread();
247 ThreadQueue = pti->MessageQueue;
248
249 if (ThreadQueue->CaretInfo->Visible)
250 {
251 PWND pwnd = UserGetWindowObject(hWnd);
252 IntKillTimer(pwnd, IDCARETTIMER, TRUE);
253 co_IntHideCaret(ThreadQueue->CaretInfo);
254 }
255
256 ThreadQueue->CaretInfo->hWnd = hWnd;
257 if(hBitmap)
258 {
259 ThreadQueue->CaretInfo->Bitmap = hBitmap;
260 ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0;
261 }
262 else
263 {
264 if (nWidth == 0)
265 {
266 nWidth = UserGetSystemMetrics(SM_CXBORDER);
267 }
268 if (nHeight == 0)
269 {
270 nHeight = UserGetSystemMetrics(SM_CYBORDER);
271 }
272 ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0;
273 ThreadQueue->CaretInfo->Size.cx = nWidth;
274 ThreadQueue->CaretInfo->Size.cy = nHeight;
275 }
276 ThreadQueue->CaretInfo->Visible = 0;
277 ThreadQueue->CaretInfo->Showing = 0;
278 IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_CARET, CHILDID_SELF, 0);
279 RETURN(TRUE);
280
281 CLEANUP:
282 TRACE("Leave NtUserCreateCaret, ret=%i\n",_ret_);
283 UserLeave();
284 END_CLEANUP;
285 }
286
287 UINT
288 APIENTRY
289 NtUserGetCaretBlinkTime(VOID)
290 {
291 UINT ret;
292
293 UserEnterShared();
294
295 ret = gpsi->dtCaretBlink;
296
297 UserLeave();
298
299 return ret;
300 }
301
302 BOOL
303 APIENTRY
304 NtUserGetCaretPos(
305 LPPOINT lpPoint)
306 {
307 PTHREADINFO pti;
308 PUSER_MESSAGE_QUEUE ThreadQueue;
309 NTSTATUS Status;
310 DECLARE_RETURN(BOOL);
311
312 TRACE("Enter NtUserGetCaretPos\n");
313 UserEnterShared();
314
315 pti = PsGetCurrentThreadWin32Thread();
316 ThreadQueue = pti->MessageQueue;
317
318 Status = MmCopyToCaller(lpPoint, &(ThreadQueue->CaretInfo->Pos), sizeof(POINT));
319 if(!NT_SUCCESS(Status))
320 {
321 SetLastNtError(Status);
322 RETURN(FALSE);
323 }
324
325 RETURN(TRUE);
326
327 CLEANUP:
328 TRACE("Leave NtUserGetCaretPos, ret=%i\n",_ret_);
329 UserLeave();
330 END_CLEANUP;
331 }
332
333 BOOL
334 APIENTRY
335 NtUserShowCaret(HWND hWnd OPTIONAL)
336 {
337 PWND Window = NULL;
338 USER_REFERENCE_ENTRY Ref;
339 DECLARE_RETURN(BOOL);
340 BOOL ret;
341
342 TRACE("Enter NtUserShowCaret\n");
343 UserEnterExclusive();
344
345 if(hWnd && !(Window = UserGetWindowObject(hWnd)))
346 {
347 RETURN(FALSE);
348 }
349
350 if (Window) UserRefObjectCo(Window, &Ref);
351
352 ret = co_UserShowCaret(Window);
353
354 if (Window) UserDerefObjectCo(Window);
355
356 RETURN(ret);
357
358 CLEANUP:
359 TRACE("Leave NtUserShowCaret, ret=%i\n",_ret_);
360 UserLeave();
361 END_CLEANUP;
362 }
363
364 BOOL
365 APIENTRY
366 NtUserHideCaret(HWND hWnd OPTIONAL)
367 {
368 PWND Window = NULL;
369 USER_REFERENCE_ENTRY Ref;
370 DECLARE_RETURN(BOOL);
371 BOOL ret;
372
373 TRACE("Enter NtUserHideCaret\n");
374 UserEnterExclusive();
375
376 if(hWnd && !(Window = UserGetWindowObject(hWnd)))
377 {
378 RETURN(FALSE);
379 }
380
381 if (Window) UserRefObjectCo(Window, &Ref);
382
383 ret = co_UserHideCaret(Window);
384
385 if (Window) UserDerefObjectCo(Window);
386
387 RETURN(ret);
388
389 CLEANUP:
390 TRACE("Leave NtUserHideCaret, ret=%i\n",_ret_);
391 UserLeave();
392 END_CLEANUP;
393 }