Make GetCursorPos call XQueryPointer.
[wine] / windows / caret.c
1 /*
2  * Caret functions
3  *
4  * Copyright 1993 David Metcalfe
5  * Copyright 1996 Frans van Dorsselaer
6  */
7
8 #include "windef.h"
9 #include "winbase.h"
10 #include "wingdi.h"
11 #include "winuser.h"
12 #include "wine/wingdi16.h"
13 #include "wine/winuser16.h"
14 #include "win.h"
15 #include "debugtools.h"
16
17 DEFAULT_DEBUG_CHANNEL(caret);
18
19 typedef struct
20 {
21     HWND     hwnd;
22     UINT     hidden;
23     BOOL     on;
24     INT      x;
25     INT      y;
26     INT      width;
27     INT      height;
28     HBRUSH16   hBrush;
29     UINT     timeout;
30     UINT     timerid;
31 } CARET;
32
33 typedef enum
34 {
35     CARET_OFF = 0,
36     CARET_ON,
37     CARET_TOGGLE
38 } DISPLAY_CARET;
39
40 static CARET Caret = { 0, 0, FALSE, 0, 0, 2, 12, 0, 500, 0 };
41
42 /*****************************************************************
43  *              CARET_GetHwnd
44  */
45 HWND CARET_GetHwnd(void)
46 {
47     return Caret.hwnd;
48 }
49
50 /*****************************************************************
51  *              CARET_GetRect
52  */
53 void CARET_GetRect(LPRECT lprc)
54 {
55     lprc->right = (lprc->left = Caret.x) + Caret.width - 1;
56     lprc->bottom = (lprc->top = Caret.y) + Caret.height - 1;
57 }
58
59 /*****************************************************************
60  *               CARET_DisplayCaret
61  */
62 static void CARET_DisplayCaret( DISPLAY_CARET status )
63 {
64     HDC hdc;
65     HBRUSH16 hPrevBrush;
66
67     if (Caret.on && (status == CARET_ON)) return;
68     if (!Caret.on && (status == CARET_OFF)) return;
69
70     /* So now it's always a toggle */
71
72     Caret.on = !Caret.on;
73     /* do not use DCX_CACHE here, for x,y,width,height are in logical units */
74     if (!(hdc = GetDCEx( Caret.hwnd, 0, DCX_USESTYLE /*| DCX_CACHE*/ ))) return;
75     hPrevBrush = SelectObject( hdc, Caret.hBrush );
76     PatBlt( hdc, Caret.x, Caret.y, Caret.width, Caret.height, PATINVERT );
77     SelectObject( hdc, hPrevBrush );
78     ReleaseDC( Caret.hwnd, hdc );
79 }
80
81   
82 /*****************************************************************
83  *               CARET_Callback
84  */
85 static VOID CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT id, DWORD ctime)
86 {
87     TRACE("hwnd=%04x, timerid=%d, caret=%d\n",
88                   hwnd, id, Caret.on);
89     CARET_DisplayCaret(CARET_TOGGLE);
90 }
91
92
93 /*****************************************************************
94  *               CARET_SetTimer
95  */
96 static void CARET_SetTimer(void)
97 {
98     if (Caret.timerid) KillSystemTimer( (HWND)0, Caret.timerid );
99     Caret.timerid = SetSystemTimer( (HWND)0, 0, Caret.timeout,
100                                       CARET_Callback );
101 }
102
103
104 /*****************************************************************
105  *               CARET_ResetTimer
106  */
107 static void CARET_ResetTimer(void)
108 {
109     if (Caret.timerid) 
110     {
111         KillSystemTimer( (HWND)0, Caret.timerid );
112         Caret.timerid = SetSystemTimer( (HWND)0, 0, Caret.timeout,
113                                           CARET_Callback );
114     }
115 }
116
117
118 /*****************************************************************
119  *               CARET_KillTimer
120  */
121 static void CARET_KillTimer(void)
122 {
123     if (Caret.timerid) 
124     {
125         KillSystemTimer( (HWND)0, Caret.timerid );
126         Caret.timerid = 0;
127     }
128 }
129
130
131 /*****************************************************************
132  *              CreateCaret (USER.163)
133  */
134 void WINAPI CreateCaret16( HWND16 hwnd, HBITMAP16 bitmap,
135                            INT16 width, INT16 height )
136 {
137     CreateCaret( hwnd, bitmap, width, height );
138 }
139
140 /*****************************************************************
141  *              CreateCaret (USER32.@)
142  */
143 BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap,
144                              INT width, INT height )
145 {
146     TRACE("hwnd=%04x\n", hwnd);
147
148     if (!hwnd) return FALSE;
149
150     /* if cursor already exists, destroy it */
151     if (Caret.hwnd) DestroyCaret();
152
153     if (bitmap && (bitmap != 1))
154     {
155         BITMAP bmp;
156         if (!GetObjectA( bitmap, sizeof(bmp), &bmp )) return FALSE;
157         Caret.width = bmp.bmWidth;
158         Caret.height = bmp.bmHeight;
159         /* FIXME: we should make a copy of the bitmap instead of a brush */
160         Caret.hBrush = CreatePatternBrush( bitmap );
161     }
162     else
163     {
164         Caret.width = width ? width : GetSystemMetrics(SM_CXBORDER);
165         Caret.height = height ? height : GetSystemMetrics(SM_CYBORDER);
166         Caret.hBrush = CreateSolidBrush(bitmap ?
167                                           GetSysColor(COLOR_GRAYTEXT) :
168                                           GetSysColor(COLOR_WINDOW) );
169     }
170
171     Caret.hwnd = hwnd;
172     Caret.hidden = 1;
173     Caret.on = FALSE;
174     Caret.x = 0;
175     Caret.y = 0;
176
177     Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 );
178     return TRUE;
179 }
180    
181
182 /*****************************************************************
183  *              DestroyCaret (USER.164)
184  */
185 void WINAPI DestroyCaret16(void)
186 {
187     DestroyCaret();
188 }
189
190
191 /*****************************************************************
192  *              DestroyCaret (USER32.@)
193  */
194 BOOL WINAPI DestroyCaret(void)
195 {
196     if (!Caret.hwnd) return FALSE;
197
198     TRACE("hwnd=%04x, timerid=%d\n",
199                 Caret.hwnd, Caret.timerid);
200
201     CARET_KillTimer();
202     CARET_DisplayCaret(CARET_OFF);
203     DeleteObject( Caret.hBrush );
204     Caret.hwnd = 0;
205     return TRUE;
206 }
207
208
209 /*****************************************************************
210  *              SetCaretPos (USER.165)
211  */
212 void WINAPI SetCaretPos16( INT16 x, INT16 y )
213 {
214     SetCaretPos( x, y );
215 }
216
217
218 /*****************************************************************
219  *              SetCaretPos (USER32.@)
220  */
221 BOOL WINAPI SetCaretPos( INT x, INT y)
222 {
223     if (!Caret.hwnd) return FALSE;
224     if ((x == Caret.x) && (y == Caret.y)) return TRUE;
225
226     TRACE("x=%d, y=%d\n", x, y);
227
228     CARET_KillTimer();
229     CARET_DisplayCaret(CARET_OFF);
230     Caret.x = x;
231     Caret.y = y;
232     if (!Caret.hidden)
233     {
234         CARET_DisplayCaret(CARET_ON);
235         CARET_SetTimer();
236     }
237     return TRUE;
238 }
239
240
241 /*****************************************************************
242  *              HideCaret (USER.166)
243  */
244 void WINAPI HideCaret16( HWND16 hwnd )
245 {
246     HideCaret( hwnd );
247 }
248
249
250 /*****************************************************************
251  *              HideCaret (USER32.@)
252  */
253 BOOL WINAPI HideCaret( HWND hwnd )
254 {
255     if (!Caret.hwnd) return FALSE;
256     if (hwnd && (Caret.hwnd != hwnd)) return FALSE;
257
258     TRACE("hwnd=%04x, hidden=%d\n",
259                   hwnd, Caret.hidden);
260
261     CARET_KillTimer();
262     CARET_DisplayCaret(CARET_OFF);
263     Caret.hidden++;
264     return TRUE;
265 }
266
267
268 /*****************************************************************
269  *              ShowCaret (USER.167)
270  */
271 void WINAPI ShowCaret16( HWND16 hwnd )
272 {
273     ShowCaret( hwnd );
274 }
275
276
277 /*****************************************************************
278  *              ShowCaret (USER32.@)
279  */
280 BOOL WINAPI ShowCaret( HWND hwnd )
281 {
282     if (!Caret.hwnd) return FALSE;
283     if (hwnd && (Caret.hwnd != hwnd)) return FALSE;
284
285     TRACE("hwnd=%04x, hidden=%d\n",
286                 hwnd, Caret.hidden);
287
288     if (Caret.hidden)
289     {
290         Caret.hidden--;
291         if (!Caret.hidden)
292         {
293             CARET_DisplayCaret(CARET_ON);
294             CARET_SetTimer();
295         }
296     }
297     return TRUE;
298 }
299
300
301 /*****************************************************************
302  *              SetCaretBlinkTime (USER.168)
303  */
304 void WINAPI SetCaretBlinkTime16( UINT16 msecs )
305 {
306     SetCaretBlinkTime( msecs );
307 }
308
309 /*****************************************************************
310  *              SetCaretBlinkTime (USER32.@)
311  */
312 BOOL WINAPI SetCaretBlinkTime( UINT msecs )
313 {
314     if (!Caret.hwnd) return FALSE;
315
316     TRACE("hwnd=%04x, msecs=%d\n",
317                 Caret.hwnd, msecs);
318
319     Caret.timeout = msecs;
320     CARET_ResetTimer();
321     return TRUE;
322 }
323
324
325 /*****************************************************************
326  *              GetCaretBlinkTime (USER.169)
327  */
328 UINT16 WINAPI GetCaretBlinkTime16(void)
329 {
330     return (UINT16)GetCaretBlinkTime();
331 }
332
333
334 /*****************************************************************
335  *              GetCaretBlinkTime (USER32.@)
336  */
337 UINT WINAPI GetCaretBlinkTime(void)
338 {
339     return Caret.timeout;
340 }
341
342
343 /*****************************************************************
344  *              GetCaretPos (USER.183)
345  */
346 VOID WINAPI GetCaretPos16( LPPOINT16 pt )
347 {
348     if (!Caret.hwnd || !pt) return;
349
350     TRACE("hwnd=%04x, pt=%p, x=%d, y=%d\n",
351                   Caret.hwnd, pt, Caret.x, Caret.y);
352     pt->x = (INT16)Caret.x;
353     pt->y = (INT16)Caret.y;
354 }
355
356
357 /*****************************************************************
358  *              GetCaretPos (USER32.@)
359  */
360 BOOL WINAPI GetCaretPos( LPPOINT pt )
361 {
362     if (!Caret.hwnd || !pt) return FALSE;
363     pt->x = Caret.x;
364     pt->y = Caret.y;
365     return TRUE;
366 }