2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Caret functions
5 * FILE: win32ss/user/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 (!GreGetBitmapDimension(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
);
85 NtGdiRestoreDC(hdc
, -1);
88 UserReleaseDC(pWnd
, hdc
, FALSE
);
93 CaretSystemTimerProc(HWND hwnd
,
99 PUSER_MESSAGE_QUEUE ThreadQueue
;
102 pti
= PsGetCurrentThreadWin32Thread();
103 ThreadQueue
= pti
->MessageQueue
;
105 if (ThreadQueue
->CaretInfo
.hWnd
!= hwnd
)
107 TRACE("Not the same caret window!\n");
113 pWnd
= UserGetWindowObject(hwnd
);
116 ERR("Caret System Timer Proc has invalid window handle! %p Id: %u\n", hwnd
, idEvent
);
122 TRACE( "Windowless Caret Timer Running!\n" );
130 ThreadQueue
->CaretInfo
.Showing
= (ThreadQueue
->CaretInfo
.Showing
? 0 : 1);
131 co_IntDrawCaret(pWnd
, &ThreadQueue
->CaretInfo
);
139 co_IntHideCaret(PTHRDCARETINFO CaretInfo
)
142 if(CaretInfo
->hWnd
&& CaretInfo
->Visible
&& CaretInfo
->Showing
)
144 pWnd
= UserGetWindowObject(CaretInfo
->hWnd
);
145 CaretInfo
->Showing
= 0;
147 co_IntDrawCaret(pWnd
, CaretInfo
);
148 IntNotifyWinEvent(EVENT_OBJECT_HIDE
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
155 co_IntDestroyCaret(PTHREADINFO Win32Thread
)
157 PUSER_MESSAGE_QUEUE ThreadQueue
;
159 ThreadQueue
= Win32Thread
->MessageQueue
;
164 pWnd
= ValidateHwndNoErr(ThreadQueue
->CaretInfo
.hWnd
);
165 co_IntHideCaret(&ThreadQueue
->CaretInfo
);
166 ThreadQueue
->CaretInfo
.Bitmap
= (HBITMAP
)0;
167 ThreadQueue
->CaretInfo
.hWnd
= (HWND
)0;
168 ThreadQueue
->CaretInfo
.Size
.cx
= ThreadQueue
->CaretInfo
.Size
.cy
= 0;
169 ThreadQueue
->CaretInfo
.Showing
= 0;
170 ThreadQueue
->CaretInfo
.Visible
= 0;
173 IntNotifyWinEvent(EVENT_OBJECT_DESTROY
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
179 IntSetCaretBlinkTime(UINT uMSeconds
)
181 /* Don't save the new value to the registry! */
183 /* Windows doesn't do this check */
184 if((uMSeconds
< MIN_CARETBLINKRATE
) || (uMSeconds
> MAX_CARETBLINKRATE
))
186 EngSetLastError(ERROR_INVALID_PARAMETER
);
190 gpsi
->dtCaretBlink
= uMSeconds
;
196 co_IntSetCaretPos(int X
, int Y
)
200 PUSER_MESSAGE_QUEUE ThreadQueue
;
202 pti
= PsGetCurrentThreadWin32Thread();
203 ThreadQueue
= pti
->MessageQueue
;
205 if(ThreadQueue
->CaretInfo
.hWnd
)
207 pWnd
= UserGetWindowObject(ThreadQueue
->CaretInfo
.hWnd
);
208 if(ThreadQueue
->CaretInfo
.Pos
.x
!= X
|| ThreadQueue
->CaretInfo
.Pos
.y
!= Y
)
210 co_IntHideCaret(&ThreadQueue
->CaretInfo
);
211 ThreadQueue
->CaretInfo
.Showing
= 1;
212 ThreadQueue
->CaretInfo
.Pos
.x
= X
;
213 ThreadQueue
->CaretInfo
.Pos
.y
= Y
;
214 co_IntDrawCaret(pWnd
, &ThreadQueue
->CaretInfo
);
216 IntSetTimer(pWnd
, IDCARETTIMER
, gpsi
->dtCaretBlink
, CaretSystemTimerProc
, TMRF_SYSTEM
);
217 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE
, pWnd
, OBJID_CARET
, CHILDID_SELF
, 0);
225 BOOL FASTCALL
co_UserHideCaret(PWND Window OPTIONAL
)
228 PUSER_MESSAGE_QUEUE ThreadQueue
;
230 if (Window
) ASSERT_REFS_CO(Window
);
232 if(Window
&& Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
234 EngSetLastError(ERROR_ACCESS_DENIED
);
238 pti
= PsGetCurrentThreadWin32Thread();
239 ThreadQueue
= pti
->MessageQueue
;
241 if(Window
&& ThreadQueue
->CaretInfo
.hWnd
!= Window
->head
.h
)
243 EngSetLastError(ERROR_ACCESS_DENIED
);
247 if(ThreadQueue
->CaretInfo
.Visible
)
249 PWND pwnd
= UserGetWindowObject(ThreadQueue
->CaretInfo
.hWnd
);
250 IntKillTimer(pwnd
, IDCARETTIMER
, TRUE
);
252 co_IntHideCaret(&ThreadQueue
->CaretInfo
);
253 ThreadQueue
->CaretInfo
.Visible
= 0;
254 ThreadQueue
->CaretInfo
.Showing
= 0;
260 BOOL FASTCALL
co_UserShowCaret(PWND Window OPTIONAL
)
263 PUSER_MESSAGE_QUEUE ThreadQueue
;
266 if (Window
) ASSERT_REFS_CO(Window
);
268 if(Window
&& Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
270 EngSetLastError(ERROR_ACCESS_DENIED
);
274 pti
= PsGetCurrentThreadWin32Thread();
275 ThreadQueue
= pti
->MessageQueue
;
277 if(Window
&& ThreadQueue
->CaretInfo
.hWnd
!= Window
->head
.h
)
279 EngSetLastError(ERROR_ACCESS_DENIED
);
283 if (!ThreadQueue
->CaretInfo
.Visible
)
285 ThreadQueue
->CaretInfo
.Visible
= 1;
286 pWnd
= ValidateHwndNoErr(ThreadQueue
->CaretInfo
.hWnd
);
287 if (!ThreadQueue
->CaretInfo
.Showing
&& pWnd
)
289 IntNotifyWinEvent(EVENT_OBJECT_SHOW
, pWnd
, OBJID_CARET
, OBJID_CARET
, 0);
291 IntSetTimer(pWnd
, IDCARETTIMER
, gpsi
->dtCaretBlink
, CaretSystemTimerProc
, TMRF_SYSTEM
);
296 /* SYSCALLS *****************************************************************/
308 PUSER_MESSAGE_QUEUE ThreadQueue
;
309 DECLARE_RETURN(BOOL
);
311 TRACE("Enter NtUserCreateCaret\n");
312 UserEnterExclusive();
314 if(!(Window
= UserGetWindowObject(hWnd
)))
319 if(Window
->head
.pti
->pEThread
!= PsGetCurrentThread())
321 EngSetLastError(ERROR_ACCESS_DENIED
);
325 pti
= PsGetCurrentThreadWin32Thread();
326 ThreadQueue
= pti
->MessageQueue
;
328 if (ThreadQueue
->CaretInfo
.Visible
)
330 IntKillTimer(Window
, IDCARETTIMER
, TRUE
);
331 co_IntHideCaret(&ThreadQueue
->CaretInfo
);
334 ThreadQueue
->CaretInfo
.hWnd
= hWnd
;
337 ThreadQueue
->CaretInfo
.Bitmap
= hBitmap
;
338 ThreadQueue
->CaretInfo
.Size
.cx
= ThreadQueue
->CaretInfo
.Size
.cy
= 0;
344 nWidth
= UserGetSystemMetrics(SM_CXBORDER
);
348 nHeight
= UserGetSystemMetrics(SM_CYBORDER
);
350 ThreadQueue
->CaretInfo
.Bitmap
= (HBITMAP
)0;
351 ThreadQueue
->CaretInfo
.Size
.cx
= nWidth
;
352 ThreadQueue
->CaretInfo
.Size
.cy
= nHeight
;
354 ThreadQueue
->CaretInfo
.Visible
= 0;
355 ThreadQueue
->CaretInfo
.Showing
= 0;
357 IntSetTimer( Window
, IDCARETTIMER
, gpsi
->dtCaretBlink
, CaretSystemTimerProc
, TMRF_SYSTEM
);
359 IntNotifyWinEvent(EVENT_OBJECT_CREATE
, Window
, OBJID_CARET
, CHILDID_SELF
, 0);
364 TRACE("Leave NtUserCreateCaret, ret=%i\n",_ret_
);
371 NtUserGetCaretBlinkTime(VOID
)
377 ret
= gpsi
->dtCaretBlink
;
390 PUSER_MESSAGE_QUEUE ThreadQueue
;
392 DECLARE_RETURN(BOOL
);
394 TRACE("Enter NtUserGetCaretPos\n");
397 pti
= PsGetCurrentThreadWin32Thread();
398 ThreadQueue
= pti
->MessageQueue
;
400 Status
= MmCopyToCaller(lpPoint
, &ThreadQueue
->CaretInfo
.Pos
, sizeof(POINT
));
401 if(!NT_SUCCESS(Status
))
403 SetLastNtError(Status
);
410 TRACE("Leave NtUserGetCaretPos, ret=%i\n",_ret_
);
417 NtUserShowCaret(HWND hWnd OPTIONAL
)
420 USER_REFERENCE_ENTRY Ref
;
421 DECLARE_RETURN(BOOL
);
424 TRACE("Enter NtUserShowCaret\n");
425 UserEnterExclusive();
427 if(hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
432 if (Window
) UserRefObjectCo(Window
, &Ref
);
434 ret
= co_UserShowCaret(Window
);
436 if (Window
) UserDerefObjectCo(Window
);
441 TRACE("Leave NtUserShowCaret, ret=%i\n",_ret_
);
448 NtUserHideCaret(HWND hWnd OPTIONAL
)
451 USER_REFERENCE_ENTRY Ref
;
452 DECLARE_RETURN(BOOL
);
455 TRACE("Enter NtUserHideCaret\n");
456 UserEnterExclusive();
458 if(hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
463 if (Window
) UserRefObjectCo(Window
, &Ref
);
465 ret
= co_UserHideCaret(Window
);
467 if (Window
) UserDerefObjectCo(Window
);
472 TRACE("Leave NtUserHideCaret, ret=%i\n",_ret_
);