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)
10 DBG_DEFAULT_CHANNEL(UserCaret
);
12 /* DEFINES *****************************************************************/
14 #define MIN_CARETBLINKRATE 100
15 #define MAX_CARETBLINKRATE 10000
17 /* FUNCTIONS *****************************************************************/
20 co_IntDrawCaret(PWND pWnd
, PTHRDCARETINFO CaretInfo
)
28 TRACE("Null Window!\n");
32 hdc
= UserGetDCEx(pWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
35 ERR("GetDC failed\n");
44 if (CaretInfo
->Bitmap
)
46 if (!NtGdiGetBitmapDimension(CaretInfo
->Bitmap
, &CaretInfo
->Size
))
48 ERR("Failed to get bitmap dimensions\n");
52 hdcMem
= NtGdiCreateCompatibleDC(hdc
);
55 hbmOld
= NtGdiSelectBitmap(hdcMem
, CaretInfo
->Bitmap
);
56 bDone
= NtGdiBitBlt(hdc
,
67 NtGdiSelectBitmap(hdcMem
, hbmOld
);
68 GreDeleteObject(hdcMem
);
84 NtGdiRestoreDC(hdc
, -1);
87 UserReleaseDC(pWnd
, hdc
, FALSE
);
92 CaretSystemTimerProc(HWND hwnd
,
98 PUSER_MESSAGE_QUEUE ThreadQueue
;
101 pti
= PsGetCurrentThreadWin32Thread();
102 ThreadQueue
= pti
->MessageQueue
;
104 if (ThreadQueue
->CaretInfo
->hWnd
!= hwnd
)
106 TRACE("Not the same caret window!\n");
112 pWnd
= UserGetWindowObject(hwnd
);
115 ERR("Caret System Timer Proc has invalid window handle! %p Id: %u\n", hwnd
, idEvent
);
121 TRACE( "Windowless Caret Timer Running!\n" );
129 ThreadQueue
->CaretInfo
->Showing
= (ThreadQueue
->CaretInfo
->Showing
? 0 : 1);
130 co_IntDrawCaret(pWnd
, ThreadQueue
->CaretInfo
);
138 co_IntHideCaret(PTHRDCARETINFO CaretInfo
)
141 if(CaretInfo
->hWnd
&& CaretInfo
->Visible
&& CaretInfo
->Showing
)
143 pWnd
= UserGetWindowObject(CaretInfo
->hWnd
);
144 CaretInfo
->Showing
= 0;
146 co_IntDrawCaret(pWnd
, CaretInfo
);
147 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
154 co_IntDestroyCaret(PTHREADINFO Win32Thread
)
156 PUSER_MESSAGE_QUEUE ThreadQueue
;
158 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)Win32Thread
->MessageQueue
;
160 if(!ThreadQueue
|| !ThreadQueue
->CaretInfo
)
163 pWnd
= ValidateHwndNoErr(ThreadQueue
->CaretInfo
->hWnd
);
164 co_IntHideCaret(ThreadQueue
->CaretInfo
);
165 ThreadQueue
->CaretInfo
->Bitmap
= (HBITMAP
)0;
166 ThreadQueue
->CaretInfo
->hWnd
= (HWND
)0;
167 ThreadQueue
->CaretInfo
->Size
.cx
= ThreadQueue
->CaretInfo
->Size
.cy
= 0;
168 ThreadQueue
->CaretInfo
->Showing
= 0;
169 ThreadQueue
->CaretInfo
->Visible
= 0;
172 IntNotifyWinEvent(EVENT_OBJECT_DESTROY
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
178 IntSetCaretBlinkTime(UINT uMSeconds
)
180 /* Don't save the new value to the registry! */
182 /* Windows doesn't do this check */
183 if((uMSeconds
< MIN_CARETBLINKRATE
) || (uMSeconds
> MAX_CARETBLINKRATE
))
185 EngSetLastError(ERROR_INVALID_PARAMETER
);
189 gpsi
->dtCaretBlink
= uMSeconds
;
195 co_IntSetCaretPos(int X
, int Y
)
199 PUSER_MESSAGE_QUEUE ThreadQueue
;
201 pti
= PsGetCurrentThreadWin32Thread();
202 ThreadQueue
= pti
->MessageQueue
;
204 if(ThreadQueue
->CaretInfo
->hWnd
)
206 pWnd
= UserGetWindowObject(ThreadQueue
->CaretInfo
->hWnd
);
207 if(ThreadQueue
->CaretInfo
->Pos
.x
!= X
|| ThreadQueue
->CaretInfo
->Pos
.y
!= Y
)
209 co_IntHideCaret(ThreadQueue
->CaretInfo
);
210 ThreadQueue
->CaretInfo
->Showing
= 1;
211 ThreadQueue
->CaretInfo
->Pos
.x
= X
;
212 ThreadQueue
->CaretInfo
->Pos
.y
= Y
;
213 co_IntDrawCaret(pWnd
, ThreadQueue
->CaretInfo
);
215 IntSetTimer(pWnd
, IDCARETTIMER
, gpsi
->dtCaretBlink
, CaretSystemTimerProc
, TMRF_SYSTEM
);
216 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
224 BOOL FASTCALL
co_UserHideCaret(PWND Window OPTIONAL
)
227 PUSER_MESSAGE_QUEUE ThreadQueue
;
229 if (Window
) ASSERT_REFS_CO(Window
);
231 if(Window
&& Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
233 EngSetLastError(ERROR_ACCESS_DENIED
);
237 pti
= PsGetCurrentThreadWin32Thread();
238 ThreadQueue
= pti
->MessageQueue
;
240 if(Window
&& ThreadQueue
->CaretInfo
->hWnd
!= Window
->head
.h
)
242 EngSetLastError(ERROR_ACCESS_DENIED
);
246 if(ThreadQueue
->CaretInfo
->Visible
)
248 PWND pwnd
= UserGetWindowObject(ThreadQueue
->CaretInfo
->hWnd
);
249 IntKillTimer(pwnd
, IDCARETTIMER
, TRUE
);
251 co_IntHideCaret(ThreadQueue
->CaretInfo
);
252 ThreadQueue
->CaretInfo
->Visible
= 0;
253 ThreadQueue
->CaretInfo
->Showing
= 0;
259 BOOL FASTCALL
co_UserShowCaret(PWND Window OPTIONAL
)
262 PUSER_MESSAGE_QUEUE ThreadQueue
;
265 if (Window
) ASSERT_REFS_CO(Window
);
267 if(Window
&& Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
269 EngSetLastError(ERROR_ACCESS_DENIED
);
273 pti
= PsGetCurrentThreadWin32Thread();
274 ThreadQueue
= pti
->MessageQueue
;
276 if(Window
&& ThreadQueue
->CaretInfo
->hWnd
!= Window
->head
.h
)
278 EngSetLastError(ERROR_ACCESS_DENIED
);
282 if (!ThreadQueue
->CaretInfo
->Visible
)
284 ThreadQueue
->CaretInfo
->Visible
= 1;
285 pWnd
= ValidateHwndNoErr(ThreadQueue
->CaretInfo
->hWnd
);
286 if (!ThreadQueue
->CaretInfo
->Showing
&& pWnd
)
288 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, pWnd
, OBJID_CARET
, OBJID_CARET
, 0);
290 IntSetTimer(pWnd
, IDCARETTIMER
, gpsi
->dtCaretBlink
, CaretSystemTimerProc
, TMRF_SYSTEM
);
295 /* SYSCALLS *****************************************************************/
307 PUSER_MESSAGE_QUEUE ThreadQueue
;
308 DECLARE_RETURN(BOOL
);
310 TRACE("Enter NtUserCreateCaret\n");
311 UserEnterExclusive();
313 if(!(Window
= UserGetWindowObject(hWnd
)))
318 if(Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
320 EngSetLastError(ERROR_ACCESS_DENIED
);
324 pti
= PsGetCurrentThreadWin32Thread();
325 ThreadQueue
= pti
->MessageQueue
;
327 if (ThreadQueue
->CaretInfo
->Visible
)
329 IntKillTimer(Window
, IDCARETTIMER
, TRUE
);
330 co_IntHideCaret(ThreadQueue
->CaretInfo
);
333 ThreadQueue
->CaretInfo
->hWnd
= hWnd
;
336 ThreadQueue
->CaretInfo
->Bitmap
= hBitmap
;
337 ThreadQueue
->CaretInfo
->Size
.cx
= ThreadQueue
->CaretInfo
->Size
.cy
= 0;
343 nWidth
= UserGetSystemMetrics(SM_CXBORDER
);
347 nHeight
= UserGetSystemMetrics(SM_CYBORDER
);
349 ThreadQueue
->CaretInfo
->Bitmap
= (HBITMAP
)0;
350 ThreadQueue
->CaretInfo
->Size
.cx
= nWidth
;
351 ThreadQueue
->CaretInfo
->Size
.cy
= nHeight
;
353 ThreadQueue
->CaretInfo
->Visible
= 0;
354 ThreadQueue
->CaretInfo
->Showing
= 0;
356 IntSetTimer( Window
, IDCARETTIMER
, gpsi
->dtCaretBlink
, CaretSystemTimerProc
, TMRF_SYSTEM
);
358 IntNotifyWinEvent(EVENT_OBJECT_CREATE
, Window
, OBJID_CARET
, CHILDID_SELF
, 0);
363 TRACE("Leave NtUserCreateCaret, ret=%i\n",_ret_
);
370 NtUserGetCaretBlinkTime(VOID
)
376 ret
= gpsi
->dtCaretBlink
;
389 PUSER_MESSAGE_QUEUE ThreadQueue
;
391 DECLARE_RETURN(BOOL
);
393 TRACE("Enter NtUserGetCaretPos\n");
396 pti
= PsGetCurrentThreadWin32Thread();
397 ThreadQueue
= pti
->MessageQueue
;
399 Status
= MmCopyToCaller(lpPoint
, &(ThreadQueue
->CaretInfo
->Pos
), sizeof(POINT
));
400 if(!NT_SUCCESS(Status
))
402 SetLastNtError(Status
);
409 TRACE("Leave NtUserGetCaretPos, ret=%i\n",_ret_
);
416 NtUserShowCaret(HWND hWnd OPTIONAL
)
419 USER_REFERENCE_ENTRY Ref
;
420 DECLARE_RETURN(BOOL
);
423 TRACE("Enter NtUserShowCaret\n");
424 UserEnterExclusive();
426 if(hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
431 if (Window
) UserRefObjectCo(Window
, &Ref
);
433 ret
= co_UserShowCaret(Window
);
435 if (Window
) UserDerefObjectCo(Window
);
440 TRACE("Leave NtUserShowCaret, ret=%i\n",_ret_
);
447 NtUserHideCaret(HWND hWnd OPTIONAL
)
450 USER_REFERENCE_ENTRY Ref
;
451 DECLARE_RETURN(BOOL
);
454 TRACE("Enter NtUserHideCaret\n");
455 UserEnterExclusive();
457 if(hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
462 if (Window
) UserRefObjectCo(Window
, &Ref
);
464 ret
= co_UserHideCaret(Window
);
466 if (Window
) UserDerefObjectCo(Window
);
471 TRACE("Leave NtUserHideCaret, ret=%i\n",_ret_
);