3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Caret functions
6 * FILE: subsys/win32k/ntuser/caret.c
7 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
12 /* INCLUDES ******************************************************************/
19 /* DEFINES *****************************************************************/
21 #define MIN_CARETBLINKRATE 100
22 #define MAX_CARETBLINKRATE 10000
23 #define DEFAULT_CARETBLINKRATE 530
24 #define CARET_REGKEY L"\\Registry\\User\\.Default\\Control Panel\\Desktop"
25 #define CARET_VALUENAME L"CursorBlinkRate"
27 /* FUNCTIONS *****************************************************************/
31 co_IntHideCaret(PTHRDCARETINFO CaretInfo
)
34 if(CaretInfo
->hWnd
&& CaretInfo
->Visible
&& CaretInfo
->Showing
)
36 pWnd
= UserGetWindowObject(CaretInfo
->hWnd
);
37 co_IntSendMessage(CaretInfo
->hWnd
, WM_SYSTIMER
, IDCARETTIMER
, 0);
38 CaretInfo
->Showing
= 0;
39 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
46 co_IntDestroyCaret(PTHREADINFO Win32Thread
)
48 PUSER_MESSAGE_QUEUE ThreadQueue
;
50 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)Win32Thread
->MessageQueue
;
52 if(!ThreadQueue
|| !ThreadQueue
->CaretInfo
)
55 pWnd
= UserGetWindowObject(ThreadQueue
->CaretInfo
->hWnd
);
56 co_IntHideCaret(ThreadQueue
->CaretInfo
);
57 ThreadQueue
->CaretInfo
->Bitmap
= (HBITMAP
)0;
58 ThreadQueue
->CaretInfo
->hWnd
= (HWND
)0;
59 ThreadQueue
->CaretInfo
->Size
.cx
= ThreadQueue
->CaretInfo
->Size
.cy
= 0;
60 ThreadQueue
->CaretInfo
->Showing
= 0;
61 ThreadQueue
->CaretInfo
->Visible
= 0;
62 IntNotifyWinEvent(EVENT_OBJECT_DESTROY
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
67 IntSetCaretBlinkTime(UINT uMSeconds
)
69 /* Don't save the new value to the registry! */
70 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
71 PWINSTATION_OBJECT WinStaObject
= pti
->rpdesk
->rpwinstaParent
;
73 /* windows doesn't do this check */
74 if((uMSeconds
< MIN_CARETBLINKRATE
) || (uMSeconds
> MAX_CARETBLINKRATE
))
76 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
77 ObDereferenceObject(WinStaObject
);
81 WinStaObject
->CaretBlinkRate
= uMSeconds
;
82 gpsi
->dtCaretBlink
= uMSeconds
;
89 IntQueryCaretBlinkRate(VOID
)
91 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(CARET_REGKEY
);
92 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(CARET_VALUENAME
);
94 HANDLE KeyHandle
= NULL
;
95 OBJECT_ATTRIBUTES KeyAttributes
;
96 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
101 InitializeObjectAttributes(&KeyAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
,
104 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &KeyAttributes
);
105 if(!NT_SUCCESS(Status
))
110 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
, KeyValuePartialInformation
,
112 if((Status
!= STATUS_BUFFER_TOO_SMALL
))
118 ResLength
+= sizeof(KEY_VALUE_PARTIAL_INFORMATION
);
119 KeyValuePartialInfo
= ExAllocatePoolWithTag(PagedPool
, ResLength
, TAG_STRING
);
122 if(!KeyValuePartialInfo
)
128 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
, KeyValuePartialInformation
,
129 (PVOID
)KeyValuePartialInfo
, Length
, &ResLength
);
130 if(!NT_SUCCESS(Status
) || (KeyValuePartialInfo
->Type
!= REG_SZ
))
133 ExFreePoolWithTag(KeyValuePartialInfo
, TAG_STRING
);
137 ValueName
.Length
= KeyValuePartialInfo
->DataLength
;
138 ValueName
.MaximumLength
= KeyValuePartialInfo
->DataLength
;
139 ValueName
.Buffer
= (PWSTR
)KeyValuePartialInfo
->Data
;
141 Status
= RtlUnicodeStringToInteger(&ValueName
, 0, &Val
);
142 if(!NT_SUCCESS(Status
))
147 ExFreePoolWithTag(KeyValuePartialInfo
, TAG_STRING
);
155 IntGetCaretBlinkTime(VOID
)
158 PWINSTATION_OBJECT WinStaObject
;
161 pti
= PsGetCurrentThreadWin32Thread();
162 WinStaObject
= pti
->rpdesk
->rpwinstaParent
;
164 Ret
= WinStaObject
->CaretBlinkRate
;
167 /* load it from the registry the first call only! */
168 Ret
= WinStaObject
->CaretBlinkRate
= IntQueryCaretBlinkRate();
171 /* windows doesn't do this check */
172 if((Ret
< MIN_CARETBLINKRATE
) || (Ret
> MAX_CARETBLINKRATE
))
174 Ret
= DEFAULT_CARETBLINKRATE
;
182 co_IntSetCaretPos(int X
, int Y
)
186 PUSER_MESSAGE_QUEUE ThreadQueue
;
188 pti
= PsGetCurrentThreadWin32Thread();
189 ThreadQueue
= pti
->MessageQueue
;
191 if(ThreadQueue
->CaretInfo
->hWnd
)
193 pWnd
= UserGetWindowObject(ThreadQueue
->CaretInfo
->hWnd
);
194 if(ThreadQueue
->CaretInfo
->Pos
.x
!= X
|| ThreadQueue
->CaretInfo
->Pos
.y
!= Y
)
196 co_IntHideCaret(ThreadQueue
->CaretInfo
);
197 ThreadQueue
->CaretInfo
->Showing
= 0;
198 ThreadQueue
->CaretInfo
->Pos
.x
= X
;
199 ThreadQueue
->CaretInfo
->Pos
.y
= Y
;
200 co_IntSendMessage(ThreadQueue
->CaretInfo
->hWnd
, WM_SYSTIMER
, IDCARETTIMER
, 0);
201 IntSetTimer(UserGetWindowObject(ThreadQueue
->CaretInfo
->hWnd
), IDCARETTIMER
, IntGetCaretBlinkTime(), NULL
, TMRF_SYSTEM
);
202 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
211 IntSwitchCaretShowing(PVOID Info
)
214 PUSER_MESSAGE_QUEUE ThreadQueue
;
216 pti
= PsGetCurrentThreadWin32Thread();
217 ThreadQueue
= pti
->MessageQueue
;
219 if(ThreadQueue
->CaretInfo
->hWnd
)
221 ThreadQueue
->CaretInfo
->Showing
= (ThreadQueue
->CaretInfo
->Showing
? 0 : 1);
222 MmCopyToCaller(Info
, ThreadQueue
->CaretInfo
, sizeof(THRDCARETINFO
));
232 co_IntDrawCaret(HWND hWnd
)
235 PUSER_MESSAGE_QUEUE ThreadQueue
;
237 pti
= PsGetCurrentThreadWin32Thread();
238 ThreadQueue
= pti
->MessageQueue
;
240 if(ThreadQueue
->CaretInfo
->hWnd
&& ThreadQueue
->CaretInfo
->Visible
&&
241 ThreadQueue
->CaretInfo
->Showing
)
243 co_IntSendMessage(ThreadQueue
->CaretInfo
->hWnd
, WM_SYSTIMER
, IDCARETTIMER
, 0);
244 ThreadQueue
->CaretInfo
->Showing
= 1;
251 BOOL FASTCALL
co_UserHideCaret(PWND Window OPTIONAL
)
254 PUSER_MESSAGE_QUEUE ThreadQueue
;
256 if (Window
) ASSERT_REFS_CO(Window
);
258 if(Window
&& Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
260 SetLastWin32Error(ERROR_ACCESS_DENIED
);
264 pti
= PsGetCurrentThreadWin32Thread();
265 ThreadQueue
= pti
->MessageQueue
;
267 if(Window
&& ThreadQueue
->CaretInfo
->hWnd
!= Window
->head
.h
)
269 SetLastWin32Error(ERROR_ACCESS_DENIED
);
273 if(ThreadQueue
->CaretInfo
->Visible
)
275 IntKillTimer(ThreadQueue
->CaretInfo
->hWnd
, IDCARETTIMER
, TRUE
);
277 co_IntHideCaret(ThreadQueue
->CaretInfo
);
278 ThreadQueue
->CaretInfo
->Visible
= 0;
279 ThreadQueue
->CaretInfo
->Showing
= 0;
286 BOOL FASTCALL
co_UserShowCaret(PWND Window OPTIONAL
)
290 PUSER_MESSAGE_QUEUE ThreadQueue
;
292 if (Window
) ASSERT_REFS_CO(Window
);
294 if(Window
&& Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
296 SetLastWin32Error(ERROR_ACCESS_DENIED
);
300 pti
= PsGetCurrentThreadWin32Thread();
301 ThreadQueue
= pti
->MessageQueue
;
303 if(Window
&& ThreadQueue
->CaretInfo
->hWnd
!= Window
->head
.h
)
305 SetLastWin32Error(ERROR_ACCESS_DENIED
);
309 if(!ThreadQueue
->CaretInfo
->Visible
)
311 ThreadQueue
->CaretInfo
->Visible
= 1;
312 if(!ThreadQueue
->CaretInfo
->Showing
)
314 pWnd
= UserGetWindowObject(ThreadQueue
->CaretInfo
->hWnd
);
315 co_IntSendMessage(ThreadQueue
->CaretInfo
->hWnd
, WM_SYSTIMER
, IDCARETTIMER
, 0);
316 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, pWnd
, OBJID_CARET
, OBJID_CARET
, 0);
318 IntSetTimer(UserGetWindowObject(ThreadQueue
->CaretInfo
->hWnd
), IDCARETTIMER
, IntGetCaretBlinkTime(), NULL
, TMRF_SYSTEM
);
324 /* SYSCALLS *****************************************************************/
336 PUSER_MESSAGE_QUEUE ThreadQueue
;
337 DECLARE_RETURN(BOOL
);
339 DPRINT("Enter NtUserCreateCaret\n");
340 UserEnterExclusive();
342 if(!(Window
= UserGetWindowObject(hWnd
)))
347 if(Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
349 SetLastWin32Error(ERROR_ACCESS_DENIED
);
353 pti
= PsGetCurrentThreadWin32Thread();
354 ThreadQueue
= pti
->MessageQueue
;
356 if (ThreadQueue
->CaretInfo
->Visible
)
358 IntKillTimer(hWnd
, IDCARETTIMER
, TRUE
);
359 co_IntHideCaret(ThreadQueue
->CaretInfo
);
362 ThreadQueue
->CaretInfo
->hWnd
= hWnd
;
365 ThreadQueue
->CaretInfo
->Bitmap
= hBitmap
;
366 ThreadQueue
->CaretInfo
->Size
.cx
= ThreadQueue
->CaretInfo
->Size
.cy
= 0;
372 nWidth
= UserGetSystemMetrics(SM_CXBORDER
);
376 nHeight
= UserGetSystemMetrics(SM_CYBORDER
);
378 ThreadQueue
->CaretInfo
->Bitmap
= (HBITMAP
)0;
379 ThreadQueue
->CaretInfo
->Size
.cx
= nWidth
;
380 ThreadQueue
->CaretInfo
->Size
.cy
= nHeight
;
382 ThreadQueue
->CaretInfo
->Visible
= 0;
383 ThreadQueue
->CaretInfo
->Showing
= 0;
384 IntNotifyWinEvent(EVENT_OBJECT_CREATE
, Window
, OBJID_CARET
, CHILDID_SELF
, 0);
388 DPRINT("Leave NtUserCreateCaret, ret=%i\n",_ret_
);
395 NtUserGetCaretBlinkTime(VOID
)
397 DECLARE_RETURN(UINT
);
399 DPRINT("Enter NtUserGetCaretBlinkTime\n");
402 RETURN(IntGetCaretBlinkTime());
405 DPRINT("Leave NtUserGetCaretBlinkTime, ret=%i\n",_ret_
);
416 PUSER_MESSAGE_QUEUE ThreadQueue
;
418 DECLARE_RETURN(BOOL
);
420 DPRINT("Enter NtUserGetCaretPos\n");
423 pti
= PsGetCurrentThreadWin32Thread();
424 ThreadQueue
= pti
->MessageQueue
;
426 Status
= MmCopyToCaller(lpPoint
, &(ThreadQueue
->CaretInfo
->Pos
), sizeof(POINT
));
427 if(!NT_SUCCESS(Status
))
429 SetLastNtError(Status
);
436 DPRINT("Leave NtUserGetCaretPos, ret=%i\n",_ret_
);
443 NtUserShowCaret(HWND hWnd OPTIONAL
)
446 USER_REFERENCE_ENTRY Ref
;
447 DECLARE_RETURN(BOOL
);
450 DPRINT("Enter NtUserShowCaret\n");
451 UserEnterExclusive();
453 if(hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
458 if (Window
) UserRefObjectCo(Window
, &Ref
);
460 ret
= co_UserShowCaret(Window
);
462 if (Window
) UserDerefObjectCo(Window
);
467 DPRINT("Leave NtUserShowCaret, ret=%i\n",_ret_
);
474 NtUserHideCaret(HWND hWnd OPTIONAL
)
477 USER_REFERENCE_ENTRY Ref
;
478 DECLARE_RETURN(BOOL
);
481 DPRINT("Enter NtUserHideCaret\n");
482 UserEnterExclusive();
484 if(hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
489 if (Window
) UserRefObjectCo(Window
, &Ref
);
491 ret
= co_UserHideCaret(Window
);
493 if (Window
) UserDerefObjectCo(Window
);
498 DPRINT("Leave NtUserHideCaret, ret=%i\n",_ret_
);