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
)
26 hdc
= UserGetDCEx(pWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
29 ERR("GetDC failed\n");
38 if(CaretInfo
->Bitmap
&& NtGdiGetBitmapDimension(CaretInfo
->Bitmap
, &CaretInfo
->Size
))
40 hdcMem
= NtGdiCreateCompatibleDC(hdc
);
43 hbmOld
= NtGdiSelectBitmap(hdcMem
, CaretInfo
->Bitmap
);
44 bDone
= NtGdiBitBlt(hdc
,
55 NtGdiSelectBitmap(hdcMem
, hbmOld
);
56 GreDeleteObject(hdcMem
);
72 NtGdiRestoreDC(hdc
, -1);
75 UserReleaseDC(pWnd
, hdc
, FALSE
);
80 CaretSystemTimerProc(HWND hwnd
,
86 PUSER_MESSAGE_QUEUE ThreadQueue
;
89 pti
= PsGetCurrentThreadWin32Thread();
90 ThreadQueue
= pti
->MessageQueue
;
92 if (ThreadQueue
->CaretInfo
->hWnd
!= hwnd
)
94 ERR("Not the same caret window!\n");
100 pWnd
= UserGetWindowObject(hwnd
);
103 ERR("Caret System Timer Proc has invalid window handle! %p Id: %u\n", hwnd
, idEvent
);
109 TRACE( "Windowless Caret Timer Running!\n" );
117 ThreadQueue
->CaretInfo
->Showing
= (ThreadQueue
->CaretInfo
->Showing
? 0 : 1);
118 co_IntDrawCaret(pWnd
, ThreadQueue
->CaretInfo
);
126 co_IntHideCaret(PTHRDCARETINFO CaretInfo
)
129 if(CaretInfo
->hWnd
&& CaretInfo
->Visible
&& CaretInfo
->Showing
)
131 pWnd
= UserGetWindowObject(CaretInfo
->hWnd
);
132 CaretInfo
->Showing
= 0;
134 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
141 co_IntDestroyCaret(PTHREADINFO Win32Thread
)
143 PUSER_MESSAGE_QUEUE ThreadQueue
;
145 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)Win32Thread
->MessageQueue
;
147 if(!ThreadQueue
|| !ThreadQueue
->CaretInfo
)
150 pWnd
= ValidateHwndNoErr(ThreadQueue
->CaretInfo
->hWnd
);
151 co_IntHideCaret(ThreadQueue
->CaretInfo
);
152 ThreadQueue
->CaretInfo
->Bitmap
= (HBITMAP
)0;
153 ThreadQueue
->CaretInfo
->hWnd
= (HWND
)0;
154 ThreadQueue
->CaretInfo
->Size
.cx
= ThreadQueue
->CaretInfo
->Size
.cy
= 0;
155 ThreadQueue
->CaretInfo
->Showing
= 0;
156 ThreadQueue
->CaretInfo
->Visible
= 0;
159 IntNotifyWinEvent(EVENT_OBJECT_DESTROY
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
165 IntSetCaretBlinkTime(UINT uMSeconds
)
167 /* Don't save the new value to the registry! */
169 /* Windows doesn't do this check */
170 if((uMSeconds
< MIN_CARETBLINKRATE
) || (uMSeconds
> MAX_CARETBLINKRATE
))
172 EngSetLastError(ERROR_INVALID_PARAMETER
);
176 gpsi
->dtCaretBlink
= uMSeconds
;
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
;
201 IntSetTimer(pWnd
, IDCARETTIMER
, gpsi
->dtCaretBlink
, CaretSystemTimerProc
, TMRF_SYSTEM
);
202 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
210 BOOL FASTCALL
co_UserHideCaret(PWND Window OPTIONAL
)
213 PUSER_MESSAGE_QUEUE ThreadQueue
;
215 if (Window
) ASSERT_REFS_CO(Window
);
217 if(Window
&& Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
219 EngSetLastError(ERROR_ACCESS_DENIED
);
223 pti
= PsGetCurrentThreadWin32Thread();
224 ThreadQueue
= pti
->MessageQueue
;
226 if(Window
&& ThreadQueue
->CaretInfo
->hWnd
!= Window
->head
.h
)
228 EngSetLastError(ERROR_ACCESS_DENIED
);
232 if(ThreadQueue
->CaretInfo
->Visible
)
234 PWND pwnd
= UserGetWindowObject(ThreadQueue
->CaretInfo
->hWnd
);
235 IntKillTimer(pwnd
, IDCARETTIMER
, TRUE
);
237 co_IntHideCaret(ThreadQueue
->CaretInfo
);
238 ThreadQueue
->CaretInfo
->Visible
= 0;
239 ThreadQueue
->CaretInfo
->Showing
= 0;
245 BOOL FASTCALL
co_UserShowCaret(PWND Window OPTIONAL
)
248 PUSER_MESSAGE_QUEUE ThreadQueue
;
251 if (Window
) ASSERT_REFS_CO(Window
);
253 if(Window
&& Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
255 EngSetLastError(ERROR_ACCESS_DENIED
);
259 pti
= PsGetCurrentThreadWin32Thread();
260 ThreadQueue
= pti
->MessageQueue
;
262 if(Window
&& ThreadQueue
->CaretInfo
->hWnd
!= Window
->head
.h
)
264 EngSetLastError(ERROR_ACCESS_DENIED
);
268 if (!ThreadQueue
->CaretInfo
->Visible
)
270 ThreadQueue
->CaretInfo
->Visible
= 1;
271 pWnd
= ValidateHwndNoErr(ThreadQueue
->CaretInfo
->hWnd
);
272 if (!ThreadQueue
->CaretInfo
->Showing
&& pWnd
)
274 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, pWnd
, OBJID_CARET
, OBJID_CARET
, 0);
276 IntSetTimer(pWnd
, IDCARETTIMER
, gpsi
->dtCaretBlink
, CaretSystemTimerProc
, TMRF_SYSTEM
);
281 /* SYSCALLS *****************************************************************/
293 PUSER_MESSAGE_QUEUE ThreadQueue
;
294 DECLARE_RETURN(BOOL
);
296 TRACE("Enter NtUserCreateCaret\n");
297 UserEnterExclusive();
299 if(!(Window
= UserGetWindowObject(hWnd
)))
304 if(Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
306 EngSetLastError(ERROR_ACCESS_DENIED
);
310 pti
= PsGetCurrentThreadWin32Thread();
311 ThreadQueue
= pti
->MessageQueue
;
313 if (ThreadQueue
->CaretInfo
->Visible
)
315 IntKillTimer(Window
, IDCARETTIMER
, TRUE
);
316 co_IntHideCaret(ThreadQueue
->CaretInfo
);
319 ThreadQueue
->CaretInfo
->hWnd
= hWnd
;
322 ThreadQueue
->CaretInfo
->Bitmap
= hBitmap
;
323 ThreadQueue
->CaretInfo
->Size
.cx
= ThreadQueue
->CaretInfo
->Size
.cy
= 0;
329 nWidth
= UserGetSystemMetrics(SM_CXBORDER
);
333 nHeight
= UserGetSystemMetrics(SM_CYBORDER
);
335 ThreadQueue
->CaretInfo
->Bitmap
= (HBITMAP
)0;
336 ThreadQueue
->CaretInfo
->Size
.cx
= nWidth
;
337 ThreadQueue
->CaretInfo
->Size
.cy
= nHeight
;
339 ThreadQueue
->CaretInfo
->Visible
= 0;
340 ThreadQueue
->CaretInfo
->Showing
= 0;
342 IntSetTimer( Window
, IDCARETTIMER
, gpsi
->dtCaretBlink
, CaretSystemTimerProc
, TMRF_SYSTEM
);
344 IntNotifyWinEvent(EVENT_OBJECT_CREATE
, Window
, OBJID_CARET
, CHILDID_SELF
, 0);
349 TRACE("Leave NtUserCreateCaret, ret=%i\n",_ret_
);
356 NtUserGetCaretBlinkTime(VOID
)
362 ret
= gpsi
->dtCaretBlink
;
375 PUSER_MESSAGE_QUEUE ThreadQueue
;
377 DECLARE_RETURN(BOOL
);
379 TRACE("Enter NtUserGetCaretPos\n");
382 pti
= PsGetCurrentThreadWin32Thread();
383 ThreadQueue
= pti
->MessageQueue
;
385 Status
= MmCopyToCaller(lpPoint
, &(ThreadQueue
->CaretInfo
->Pos
), sizeof(POINT
));
386 if(!NT_SUCCESS(Status
))
388 SetLastNtError(Status
);
395 TRACE("Leave NtUserGetCaretPos, ret=%i\n",_ret_
);
402 NtUserShowCaret(HWND hWnd OPTIONAL
)
405 USER_REFERENCE_ENTRY Ref
;
406 DECLARE_RETURN(BOOL
);
409 TRACE("Enter NtUserShowCaret\n");
410 UserEnterExclusive();
412 if(hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
417 if (Window
) UserRefObjectCo(Window
, &Ref
);
419 ret
= co_UserShowCaret(Window
);
421 if (Window
) UserDerefObjectCo(Window
);
426 TRACE("Leave NtUserShowCaret, ret=%i\n",_ret_
);
433 NtUserHideCaret(HWND hWnd OPTIONAL
)
436 USER_REFERENCE_ENTRY Ref
;
437 DECLARE_RETURN(BOOL
);
440 TRACE("Enter NtUserHideCaret\n");
441 UserEnterExclusive();
443 if(hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
448 if (Window
) UserRefObjectCo(Window
, &Ref
);
450 ret
= co_UserHideCaret(Window
);
452 if (Window
) UserDerefObjectCo(Window
);
457 TRACE("Leave NtUserHideCaret, ret=%i\n",_ret_
);