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