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