wined3d: Don't create a pbo for system memory surfaces.
[wine/winequartzdrv.git] / dlls / user32 / caret.c
blob8487f0ce29cb299b53a7f52fa7cfe65955b035d4
1 /*
2 * Caret functions
4 * Copyright 1993 David Metcalfe
5 * Copyright 1996 Frans van Dorsselaer
6 * Copyright 2001 Eric Pouech
7 * Copyright 2002 Alexandre Julliard
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "wine/server.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(caret);
38 typedef struct
40 HBITMAP hBmp;
41 UINT timeout;
42 } CARET;
44 static CARET Caret = { 0, 500 };
46 #define TIMERID 0xffff /* system timer id for the caret */
49 /*****************************************************************
50 * CARET_DisplayCaret
52 static void CARET_DisplayCaret( HWND hwnd, const RECT *r )
54 HDC hdc;
55 HDC hCompDC;
57 /* do not use DCX_CACHE here, for x,y,width,height are in logical units */
58 if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE /*| DCX_CACHE*/ ))) return;
59 hCompDC = CreateCompatibleDC(hdc);
60 if (hCompDC)
62 HBITMAP hPrevBmp;
64 hPrevBmp = SelectObject(hCompDC, Caret.hBmp);
65 BitBlt(hdc, r->left, r->top, r->right-r->left, r->bottom-r->top, hCompDC, 0, 0, SRCINVERT);
66 SelectObject(hCompDC, hPrevBmp);
67 DeleteDC(hCompDC);
69 ReleaseDC( hwnd, hdc );
73 /*****************************************************************
74 * CARET_Callback
76 static void CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT_PTR id, DWORD ctime)
78 BOOL ret;
79 RECT r;
80 int old_state = 0;
81 int hidden = 0;
83 SERVER_START_REQ( set_caret_info )
85 req->flags = SET_CARET_STATE;
86 req->handle = hwnd;
87 req->x = 0;
88 req->y = 0;
89 req->hide = 0;
90 req->state = -1; /* toggle current state */
91 if ((ret = !wine_server_call( req )))
93 hwnd = reply->full_handle;
94 r.left = reply->old_rect.left;
95 r.top = reply->old_rect.top;
96 r.right = reply->old_rect.right;
97 r.bottom = reply->old_rect.bottom;
98 old_state = reply->old_state;
99 hidden = reply->old_hide;
102 SERVER_END_REQ;
104 if (ret && !hidden) CARET_DisplayCaret( hwnd, &r );
108 /*****************************************************************
109 * CreateCaret (USER32.@)
111 BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap, INT width, INT height )
113 BOOL ret;
114 RECT r;
115 int old_state = 0;
116 int hidden = 0;
117 HBITMAP hBmp = 0;
118 HWND prev = 0;
120 TRACE("hwnd=%p\n", hwnd);
122 if (!hwnd) return FALSE;
124 if (bitmap && (bitmap != (HBITMAP)1))
126 BITMAP bmp;
127 if (!GetObjectA( bitmap, sizeof(bmp), &bmp )) return FALSE;
128 width = bmp.bmWidth;
129 height = bmp.bmHeight;
130 bmp.bmBits = NULL;
131 hBmp = CreateBitmapIndirect(&bmp);
132 if (hBmp)
134 /* copy the bitmap */
135 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, bmp.bmWidthBytes * bmp.bmHeight);
136 GetBitmapBits(bitmap, bmp.bmWidthBytes * bmp.bmHeight, buf);
137 SetBitmapBits(hBmp, bmp.bmWidthBytes * bmp.bmHeight, buf);
138 HeapFree(GetProcessHeap(), 0, buf);
141 else
143 HDC hdc;
145 if (!width) width = GetSystemMetrics(SM_CXBORDER);
146 if (!height) height = GetSystemMetrics(SM_CYBORDER);
148 /* create the uniform bitmap on the fly */
149 hdc = GetDC(hwnd);
150 if (hdc)
152 HDC hMemDC = CreateCompatibleDC(hdc);
153 if (hMemDC)
155 if ((hBmp = CreateCompatibleBitmap(hMemDC, width, height )))
157 HBITMAP hPrevBmp = SelectObject(hMemDC, hBmp);
158 SetRect( &r, 0, 0, width, height );
159 FillRect(hMemDC, &r, ULongToHandle((bitmap ? COLOR_GRAYTEXT : COLOR_WINDOW) + 1));
160 SelectObject(hMemDC, hPrevBmp);
162 DeleteDC(hMemDC);
164 ReleaseDC(hwnd, hdc);
167 if (!hBmp) return FALSE;
169 SERVER_START_REQ( set_caret_window )
171 req->handle = hwnd;
172 req->width = width;
173 req->height = height;
174 if ((ret = !wine_server_call_err( req )))
176 prev = reply->previous;
177 r.left = reply->old_rect.left;
178 r.top = reply->old_rect.top;
179 r.right = reply->old_rect.right;
180 r.bottom = reply->old_rect.bottom;
181 old_state = reply->old_state;
182 hidden = reply->old_hide;
185 SERVER_END_REQ;
186 if (!ret) return FALSE;
188 if (prev && !hidden) /* hide the previous one */
190 /* FIXME: won't work if prev belongs to a different process */
191 KillSystemTimer( prev, TIMERID );
192 if (old_state) CARET_DisplayCaret( prev, &r );
195 if (Caret.hBmp) DeleteObject( Caret.hBmp );
196 Caret.hBmp = hBmp;
197 Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 );
198 return TRUE;
202 /*****************************************************************
203 * DestroyCaret (USER32.@)
205 BOOL WINAPI DestroyCaret(void)
207 BOOL ret;
208 HWND prev = 0;
209 RECT r;
210 int old_state = 0;
211 int hidden = 0;
213 SERVER_START_REQ( set_caret_window )
215 req->handle = 0;
216 req->width = 0;
217 req->height = 0;
218 if ((ret = !wine_server_call_err( req )))
220 prev = reply->previous;
221 r.left = reply->old_rect.left;
222 r.top = reply->old_rect.top;
223 r.right = reply->old_rect.right;
224 r.bottom = reply->old_rect.bottom;
225 old_state = reply->old_state;
226 hidden = reply->old_hide;
229 SERVER_END_REQ;
231 if (ret && prev && !hidden)
233 /* FIXME: won't work if prev belongs to a different process */
234 KillSystemTimer( prev, TIMERID );
235 if (old_state) CARET_DisplayCaret( prev, &r );
237 if (Caret.hBmp) DeleteObject( Caret.hBmp );
238 Caret.hBmp = 0;
239 return ret;
243 /*****************************************************************
244 * SetCaretPos (USER32.@)
246 BOOL WINAPI SetCaretPos( INT x, INT y )
248 BOOL ret;
249 HWND hwnd = 0;
250 RECT r;
251 int old_state = 0;
252 int hidden = 0;
254 SERVER_START_REQ( set_caret_info )
256 req->flags = SET_CARET_POS|SET_CARET_STATE;
257 req->handle = 0;
258 req->x = x;
259 req->y = y;
260 req->hide = 0;
261 req->state = 1;
262 if ((ret = !wine_server_call_err( req )))
264 hwnd = reply->full_handle;
265 r.left = reply->old_rect.left;
266 r.top = reply->old_rect.top;
267 r.right = reply->old_rect.right;
268 r.bottom = reply->old_rect.bottom;
269 old_state = reply->old_state;
270 hidden = reply->old_hide;
273 SERVER_END_REQ;
274 if (ret && !hidden)
276 if (old_state) CARET_DisplayCaret( hwnd, &r );
277 r.right += x - r.left;
278 r.bottom += y - r.top;
279 r.left = x;
280 r.top = y;
281 CARET_DisplayCaret( hwnd, &r );
282 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
284 return ret;
288 /*****************************************************************
289 * HideCaret (USER32.@)
291 BOOL WINAPI HideCaret( HWND hwnd )
293 BOOL ret;
294 RECT r;
295 int old_state = 0;
296 int hidden = 0;
298 SERVER_START_REQ( set_caret_info )
300 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
301 req->handle = hwnd;
302 req->x = 0;
303 req->y = 0;
304 req->hide = 1;
305 req->state = 0;
306 if ((ret = !wine_server_call_err( req )))
308 hwnd = reply->full_handle;
309 r.left = reply->old_rect.left;
310 r.top = reply->old_rect.top;
311 r.right = reply->old_rect.right;
312 r.bottom = reply->old_rect.bottom;
313 old_state = reply->old_state;
314 hidden = reply->old_hide;
317 SERVER_END_REQ;
319 if (ret && !hidden)
321 if (old_state) CARET_DisplayCaret( hwnd, &r );
322 KillSystemTimer( hwnd, TIMERID );
324 return ret;
328 /*****************************************************************
329 * ShowCaret (USER32.@)
331 BOOL WINAPI ShowCaret( HWND hwnd )
333 BOOL ret;
334 RECT r;
335 int old_state = 0;
336 int hidden = 0;
338 SERVER_START_REQ( set_caret_info )
340 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
341 req->handle = hwnd;
342 req->x = 0;
343 req->y = 0;
344 req->hide = -1;
345 req->state = 1;
346 if ((ret = !wine_server_call_err( req )))
348 hwnd = reply->full_handle;
349 r.left = reply->old_rect.left;
350 r.top = reply->old_rect.top;
351 r.right = reply->old_rect.right;
352 r.bottom = reply->old_rect.bottom;
353 old_state = reply->old_state;
354 hidden = reply->old_hide;
357 SERVER_END_REQ;
359 if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */
361 CARET_DisplayCaret( hwnd, &r );
362 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
364 return ret;
368 /*****************************************************************
369 * GetCaretPos (USER32.@)
371 BOOL WINAPI GetCaretPos( LPPOINT pt )
373 BOOL ret;
375 SERVER_START_REQ( set_caret_info )
377 req->flags = 0; /* don't set anything */
378 req->handle = 0;
379 req->x = 0;
380 req->y = 0;
381 req->hide = 0;
382 req->state = 0;
383 if ((ret = !wine_server_call_err( req )))
385 pt->x = reply->old_rect.left;
386 pt->y = reply->old_rect.top;
389 SERVER_END_REQ;
390 return ret;
394 /*****************************************************************
395 * SetCaretBlinkTime (USER32.@)
397 BOOL WINAPI SetCaretBlinkTime( UINT msecs )
399 TRACE("msecs=%d\n", msecs);
401 Caret.timeout = msecs;
402 /* if (Caret.hwnd) CARET_SetTimer(); FIXME */
403 return TRUE;
407 /*****************************************************************
408 * GetCaretBlinkTime (USER32.@)
410 UINT WINAPI GetCaretBlinkTime(void)
412 return Caret.timeout;