Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. | |
3 | * | |
4 | *Permission is hereby granted, free of charge, to any person obtaining | |
5 | * a copy of this software and associated documentation files (the | |
6 | *"Software"), to deal in the Software without restriction, including | |
7 | *without limitation the rights to use, copy, modify, merge, publish, | |
8 | *distribute, sublicense, and/or sell copies of the Software, and to | |
9 | *permit persons to whom the Software is furnished to do so, subject to | |
10 | *the following conditions: | |
11 | * | |
12 | *The above copyright notice and this permission notice shall be | |
13 | *included in all copies or substantial portions of the Software. | |
14 | * | |
15 | *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
16 | *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
17 | *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
18 | *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR | |
19 | *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
20 | *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
21 | *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | *Except as contained in this notice, the name of the XFree86 Project | |
24 | *shall not be used in advertising or otherwise to promote the sale, use | |
25 | *or other dealings in this Software without prior written authorization | |
26 | *from the XFree86 Project. | |
27 | * | |
28 | * Authors: Dakshinamurthy Karra | |
29 | * Suhaib M Siddiqi | |
30 | * Peter Busch | |
31 | * Harold L Hunt II | |
32 | */ | |
33 | ||
34 | #ifdef HAVE_XWIN_CONFIG_H | |
35 | #include <xwin-config.h> | |
36 | #endif | |
37 | #include "win.h" | |
38 | #include "winmsg.h" | |
39 | #include <cursorstr.h> | |
40 | #include <mipointrst.h> | |
41 | #include <servermd.h> | |
42 | #include "misc.h" | |
43 | ||
44 | #define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114) | |
45 | ||
46 | #if 0 | |
47 | #define WIN_DEBUG_MSG winDebug | |
48 | #else | |
49 | #define WIN_DEBUG_MSG(...) | |
50 | #endif | |
51 | ||
52 | /* | |
53 | * Local function prototypes | |
54 | */ | |
55 | ||
56 | static void | |
57 | winPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); | |
58 | ||
59 | static Bool | |
60 | winCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y); | |
61 | ||
62 | static void | |
63 | winCrossScreen(ScreenPtr pScreen, Bool fEntering); | |
64 | ||
65 | miPointerScreenFuncRec g_winPointerCursorFuncs = { | |
66 | winCursorOffScreen, | |
67 | winCrossScreen, | |
68 | winPointerWarpCursor | |
69 | }; | |
70 | ||
71 | static void | |
72 | winPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) | |
73 | { | |
74 | winScreenPriv(pScreen); | |
75 | RECT rcClient; | |
76 | static Bool s_fInitialWarp = TRUE; | |
77 | ||
78 | /* Discard first warp call */ | |
79 | if (s_fInitialWarp) { | |
80 | /* First warp moves mouse to center of window, just ignore it */ | |
81 | ||
82 | /* Don't ignore subsequent warps */ | |
83 | s_fInitialWarp = FALSE; | |
84 | ||
85 | winErrorFVerb(2, | |
86 | "winPointerWarpCursor - Discarding first warp: %d %d\n", | |
87 | x, y); | |
88 | ||
89 | return; | |
90 | } | |
91 | ||
92 | /* | |
93 | Only update the Windows cursor position if root window is active, | |
94 | or we are in a rootless mode | |
95 | */ | |
96 | if ((pScreenPriv->hwndScreen == GetForegroundWindow()) | |
97 | || pScreenPriv->pScreenInfo->fRootless | |
98 | #ifdef XWIN_MULTIWINDOW | |
99 | || pScreenPriv->pScreenInfo->fMultiWindow | |
100 | #endif | |
101 | ) { | |
102 | /* Get the client area coordinates */ | |
103 | GetClientRect(pScreenPriv->hwndScreen, &rcClient); | |
104 | ||
105 | /* Translate the client area coords to screen coords */ | |
106 | MapWindowPoints(pScreenPriv->hwndScreen, | |
107 | HWND_DESKTOP, (LPPOINT) &rcClient, 2); | |
108 | ||
109 | /* | |
110 | * Update the Windows cursor position so that we don't | |
111 | * immediately warp back to the current position. | |
112 | */ | |
113 | SetCursorPos(rcClient.left + x, rcClient.top + y); | |
114 | } | |
115 | ||
116 | /* Call the mi warp procedure to do the actual warping in X. */ | |
117 | miPointerWarpCursor(pDev, pScreen, x, y); | |
118 | } | |
119 | ||
120 | static Bool | |
121 | winCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) | |
122 | { | |
123 | return FALSE; | |
124 | } | |
125 | ||
126 | static void | |
127 | winCrossScreen(ScreenPtr pScreen, Bool fEntering) | |
128 | { | |
129 | } | |
130 | ||
131 | static unsigned char | |
132 | reverse(unsigned char c) | |
133 | { | |
134 | int i; | |
135 | unsigned char ret = 0; | |
136 | ||
137 | for (i = 0; i < 8; ++i) { | |
138 | ret |= ((c >> i) & 1) << (7 - i); | |
139 | } | |
140 | return ret; | |
141 | } | |
142 | ||
143 | /* | |
144 | * Convert X cursor to Windows cursor | |
145 | * FIXME: Perhaps there are more smart code | |
146 | */ | |
147 | static HCURSOR | |
148 | winLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int screen) | |
149 | { | |
150 | winScreenPriv(pScreen); | |
151 | HCURSOR hCursor = NULL; | |
152 | unsigned char *pAnd; | |
153 | unsigned char *pXor; | |
154 | int nCX, nCY; | |
155 | int nBytes; | |
156 | double dForeY, dBackY; | |
157 | BOOL fReverse; | |
158 | HBITMAP hAnd, hXor; | |
159 | ICONINFO ii; | |
160 | unsigned char *pCur; | |
161 | unsigned char bit; | |
162 | HDC hDC; | |
163 | BITMAPV4HEADER bi; | |
164 | BITMAPINFO *pbmi; | |
165 | uint32_t *lpBits; | |
166 | ||
167 | WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d hotspot: %d,%d\n", | |
168 | pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, | |
169 | pCursor->bits->width, pCursor->bits->height, | |
170 | pCursor->bits->xhot, pCursor->bits->yhot); | |
171 | ||
172 | /* We can use only White and Black, so calc brightness of color | |
173 | * Also check if the cursor is inverted */ | |
174 | dForeY = BRIGHTNESS(pCursor->fore); | |
175 | dBackY = BRIGHTNESS(pCursor->back); | |
176 | fReverse = dForeY < dBackY; | |
177 | ||
178 | /* Check wether the X11 cursor is bigger than the win32 cursor */ | |
179 | if (pScreenPriv->cursor.sm_cx < pCursor->bits->width || | |
180 | pScreenPriv->cursor.sm_cy < pCursor->bits->height) { | |
181 | winErrorFVerb(3, | |
182 | "winLoadCursor - Windows requires %dx%d cursor but X requires %dx%d\n", | |
183 | pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, | |
184 | pCursor->bits->width, pCursor->bits->height); | |
185 | } | |
186 | ||
187 | /* Get the number of bytes required to store the whole cursor image | |
188 | * This is roughly (sm_cx * sm_cy) / 8 | |
189 | * round up to 8 pixel boundary so we can convert whole bytes */ | |
190 | nBytes = | |
191 | bits_to_bytes(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy; | |
192 | ||
193 | /* Get the effective width and height */ | |
194 | nCX = min(pScreenPriv->cursor.sm_cx, pCursor->bits->width); | |
195 | nCY = min(pScreenPriv->cursor.sm_cy, pCursor->bits->height); | |
196 | ||
197 | /* Allocate memory for the bitmaps */ | |
198 | pAnd = malloc(nBytes); | |
199 | memset(pAnd, 0xFF, nBytes); | |
200 | pXor = calloc(1, nBytes); | |
201 | ||
202 | /* Convert the X11 bitmap to a win32 bitmap | |
203 | * The first is for an empty mask */ | |
204 | if (pCursor->bits->emptyMask) { | |
205 | int x, y, xmax = bits_to_bytes(nCX); | |
206 | ||
207 | for (y = 0; y < nCY; ++y) | |
208 | for (x = 0; x < xmax; ++x) { | |
209 | int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; | |
210 | int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; | |
211 | ||
212 | pAnd[nWinPix] = 0; | |
213 | if (fReverse) | |
214 | pXor[nWinPix] = reverse(~pCursor->bits->source[nXPix]); | |
215 | else | |
216 | pXor[nWinPix] = reverse(pCursor->bits->source[nXPix]); | |
217 | } | |
218 | } | |
219 | else { | |
220 | int x, y, xmax = bits_to_bytes(nCX); | |
221 | ||
222 | for (y = 0; y < nCY; ++y) | |
223 | for (x = 0; x < xmax; ++x) { | |
224 | int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; | |
225 | int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; | |
226 | ||
227 | unsigned char mask = pCursor->bits->mask[nXPix]; | |
228 | ||
229 | pAnd[nWinPix] = reverse(~mask); | |
230 | if (fReverse) | |
231 | pXor[nWinPix] = | |
232 | reverse(~pCursor->bits->source[nXPix] & mask); | |
233 | else | |
234 | pXor[nWinPix] = | |
235 | reverse(pCursor->bits->source[nXPix] & mask); | |
236 | } | |
237 | } | |
238 | ||
239 | /* prepare the pointers */ | |
240 | hCursor = NULL; | |
241 | lpBits = NULL; | |
242 | ||
243 | /* We have a truecolor alpha-blended cursor and can use it! */ | |
244 | if (pCursor->bits->argb) { | |
245 | WIN_DEBUG_MSG("winLoadCursor: Trying truecolor alphablended cursor\n"); | |
246 | memset(&bi, 0, sizeof(BITMAPV4HEADER)); | |
247 | bi.bV4Size = sizeof(BITMAPV4HEADER); | |
248 | bi.bV4Width = pScreenPriv->cursor.sm_cx; | |
249 | bi.bV4Height = -(pScreenPriv->cursor.sm_cy); /* right-side up */ | |
250 | bi.bV4Planes = 1; | |
251 | bi.bV4BitCount = 32; | |
252 | bi.bV4V4Compression = BI_BITFIELDS; | |
253 | bi.bV4RedMask = 0x00FF0000; | |
254 | bi.bV4GreenMask = 0x0000FF00; | |
255 | bi.bV4BlueMask = 0x000000FF; | |
256 | bi.bV4AlphaMask = 0xFF000000; | |
257 | ||
258 | lpBits = | |
259 | (uint32_t *) calloc(pScreenPriv->cursor.sm_cx * | |
260 | pScreenPriv->cursor.sm_cy, | |
261 | sizeof(uint32_t)); | |
262 | ||
263 | if (lpBits) { | |
264 | int y; | |
265 | for (y = 0; y < nCY; y++) { | |
266 | void *src, *dst; | |
267 | src = &(pCursor->bits->argb[y * pCursor->bits->width]); | |
268 | dst = &(lpBits[y * pScreenPriv->cursor.sm_cx]); | |
269 | memcpy(dst, src, 4 * nCX); | |
270 | } | |
271 | } | |
272 | } /* End if-truecolor-icon */ | |
273 | ||
274 | if (!lpBits) { | |
275 | RGBQUAD *pbmiColors; | |
276 | /* Bicolor, use a palettized DIB */ | |
277 | WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n"); | |
278 | pbmi = (BITMAPINFO *) &bi; | |
279 | pbmiColors = &(pbmi->bmiColors[0]); | |
280 | ||
281 | memset(pbmi, 0, sizeof(BITMAPINFOHEADER)); | |
282 | pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); | |
283 | pbmi->bmiHeader.biWidth = pScreenPriv->cursor.sm_cx; | |
284 | pbmi->bmiHeader.biHeight = -abs(pScreenPriv->cursor.sm_cy); /* right-side up */ | |
285 | pbmi->bmiHeader.biPlanes = 1; | |
286 | pbmi->bmiHeader.biBitCount = 8; | |
287 | pbmi->bmiHeader.biCompression = BI_RGB; | |
288 | pbmi->bmiHeader.biSizeImage = 0; | |
289 | pbmi->bmiHeader.biClrUsed = 3; | |
290 | pbmi->bmiHeader.biClrImportant = 3; | |
291 | ||
292 | pbmiColors[0].rgbRed = 0; /* Empty */ | |
293 | pbmiColors[0].rgbGreen = 0; | |
294 | pbmiColors[0].rgbBlue = 0; | |
295 | pbmiColors[0].rgbReserved = 0; | |
296 | pbmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */ | |
297 | pbmiColors[1].rgbGreen = pCursor->backGreen >> 8; | |
298 | pbmiColors[1].rgbBlue = pCursor->backBlue >> 8; | |
299 | pbmiColors[1].rgbReserved = 0; | |
300 | pbmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */ | |
301 | pbmiColors[2].rgbGreen = pCursor->foreGreen >> 8; | |
302 | pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8; | |
303 | pbmiColors[2].rgbReserved = 0; | |
304 | ||
305 | lpBits = | |
306 | (uint32_t *) calloc(pScreenPriv->cursor.sm_cx * | |
307 | pScreenPriv->cursor.sm_cy, sizeof(char)); | |
308 | ||
309 | pCur = (unsigned char *) lpBits; | |
310 | if (lpBits) { | |
311 | int x, y; | |
312 | for (y = 0; y < pScreenPriv->cursor.sm_cy; y++) { | |
313 | for (x = 0; x < pScreenPriv->cursor.sm_cx; x++) { | |
314 | if (x >= nCX || y >= nCY) /* Outside of X11 icon bounds */ | |
315 | (*pCur++) = 0; | |
316 | else { /* Within X11 icon bounds */ | |
317 | ||
318 | int nWinPix = | |
319 | bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + | |
320 | (x / 8); | |
321 | ||
322 | bit = pAnd[nWinPix]; | |
323 | bit = bit & (1 << (7 - (x & 7))); | |
324 | if (!bit) { /* Within the cursor mask? */ | |
325 | int nXPix = | |
326 | BitmapBytePad(pCursor->bits->width) * y + | |
327 | (x / 8); | |
328 | bit = | |
329 | ~reverse(~pCursor->bits-> | |
330 | source[nXPix] & pCursor->bits-> | |
331 | mask[nXPix]); | |
332 | bit = bit & (1 << (7 - (x & 7))); | |
333 | if (bit) /* Draw foreground */ | |
334 | (*pCur++) = 2; | |
335 | else /* Draw background */ | |
336 | (*pCur++) = 1; | |
337 | } | |
338 | else /* Outside the cursor mask */ | |
339 | (*pCur++) = 0; | |
340 | } | |
341 | } /* end for (x) */ | |
342 | } /* end for (y) */ | |
343 | } /* end if (lpbits) */ | |
344 | } | |
345 | ||
346 | /* If one of the previous two methods gave us the bitmap we need, make a cursor */ | |
347 | if (lpBits) { | |
348 | WIN_DEBUG_MSG("winLoadCursor: Creating bitmap cursor: hotspot %d,%d\n", | |
349 | pCursor->bits->xhot, pCursor->bits->yhot); | |
350 | ||
351 | hAnd = NULL; | |
352 | hXor = NULL; | |
353 | ||
354 | hAnd = | |
355 | CreateBitmap(pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, | |
356 | 1, 1, pAnd); | |
357 | ||
358 | hDC = GetDC(NULL); | |
359 | if (hDC) { | |
360 | hXor = | |
361 | CreateCompatibleBitmap(hDC, pScreenPriv->cursor.sm_cx, | |
362 | pScreenPriv->cursor.sm_cy); | |
363 | SetDIBits(hDC, hXor, 0, pScreenPriv->cursor.sm_cy, lpBits, | |
364 | (BITMAPINFO *) &bi, DIB_RGB_COLORS); | |
365 | ReleaseDC(NULL, hDC); | |
366 | } | |
367 | free(lpBits); | |
368 | ||
369 | if (hAnd && hXor) { | |
370 | ii.fIcon = FALSE; | |
371 | ii.xHotspot = pCursor->bits->xhot; | |
372 | ii.yHotspot = pCursor->bits->yhot; | |
373 | ii.hbmMask = hAnd; | |
374 | ii.hbmColor = hXor; | |
375 | hCursor = (HCURSOR) CreateIconIndirect(&ii); | |
376 | ||
377 | if (hCursor == NULL) | |
378 | winW32Error(2, "winLoadCursor - CreateIconIndirect failed:"); | |
379 | else { | |
380 | if (GetIconInfo(hCursor, &ii)) { | |
381 | if (ii.fIcon) { | |
382 | WIN_DEBUG_MSG | |
383 | ("winLoadCursor: CreateIconIndirect returned no cursor. Trying again.\n"); | |
384 | ||
385 | DestroyCursor(hCursor); | |
386 | ||
387 | ii.fIcon = FALSE; | |
388 | ii.xHotspot = pCursor->bits->xhot; | |
389 | ii.yHotspot = pCursor->bits->yhot; | |
390 | hCursor = (HCURSOR) CreateIconIndirect(&ii); | |
391 | ||
392 | if (hCursor == NULL) | |
393 | winW32Error(2, | |
394 | "winLoadCursor - CreateIconIndirect failed:"); | |
395 | } | |
396 | /* GetIconInfo creates new bitmaps. Destroy them again */ | |
397 | if (ii.hbmMask) | |
398 | DeleteObject(ii.hbmMask); | |
399 | if (ii.hbmColor) | |
400 | DeleteObject(ii.hbmColor); | |
401 | } | |
402 | } | |
403 | } | |
404 | ||
405 | if (hAnd) | |
406 | DeleteObject(hAnd); | |
407 | if (hXor) | |
408 | DeleteObject(hXor); | |
409 | } | |
410 | ||
411 | if (!hCursor) { | |
412 | /* We couldn't make a color cursor for this screen, use | |
413 | black and white instead */ | |
414 | hCursor = CreateCursor(g_hInstance, | |
415 | pCursor->bits->xhot, pCursor->bits->yhot, | |
416 | pScreenPriv->cursor.sm_cx, | |
417 | pScreenPriv->cursor.sm_cy, pAnd, pXor); | |
418 | if (hCursor == NULL) | |
419 | winW32Error(2, "winLoadCursor - CreateCursor failed:"); | |
420 | } | |
421 | free(pAnd); | |
422 | free(pXor); | |
423 | ||
424 | return hCursor; | |
425 | } | |
426 | ||
427 | /* | |
428 | =========================================================================== | |
429 | ||
430 | Pointer sprite functions | |
431 | ||
432 | =========================================================================== | |
433 | */ | |
434 | ||
435 | /* | |
436 | * winRealizeCursor | |
437 | * Convert the X cursor representation to native format if possible. | |
438 | */ | |
439 | static Bool | |
440 | winRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) | |
441 | { | |
442 | if (pCursor == NULL || pCursor->bits == NULL) | |
443 | return FALSE; | |
444 | ||
445 | /* FIXME: cache ARGB8888 representation? */ | |
446 | ||
447 | return TRUE; | |
448 | } | |
449 | ||
450 | /* | |
451 | * winUnrealizeCursor | |
452 | * Free the storage space associated with a realized cursor. | |
453 | */ | |
454 | static Bool | |
455 | winUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) | |
456 | { | |
457 | return TRUE; | |
458 | } | |
459 | ||
460 | /* | |
461 | * winSetCursor | |
462 | * Set the cursor sprite and position. | |
463 | */ | |
464 | static void | |
465 | winSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, | |
466 | int y) | |
467 | { | |
468 | POINT ptCurPos, ptTemp; | |
469 | HWND hwnd; | |
470 | RECT rcClient; | |
471 | BOOL bInhibit; | |
472 | ||
473 | winScreenPriv(pScreen); | |
474 | WIN_DEBUG_MSG("winSetCursor: cursor=%p\n", pCursor); | |
475 | ||
476 | /* Inhibit changing the cursor if the mouse is not in a client area */ | |
477 | bInhibit = FALSE; | |
478 | if (GetCursorPos(&ptCurPos)) { | |
479 | hwnd = WindowFromPoint(ptCurPos); | |
480 | if (hwnd) { | |
481 | if (GetClientRect(hwnd, &rcClient)) { | |
482 | ptTemp.x = rcClient.left; | |
483 | ptTemp.y = rcClient.top; | |
484 | if (ClientToScreen(hwnd, &ptTemp)) { | |
485 | rcClient.left = ptTemp.x; | |
486 | rcClient.top = ptTemp.y; | |
487 | ptTemp.x = rcClient.right; | |
488 | ptTemp.y = rcClient.bottom; | |
489 | if (ClientToScreen(hwnd, &ptTemp)) { | |
490 | rcClient.right = ptTemp.x; | |
491 | rcClient.bottom = ptTemp.y; | |
492 | if (!PtInRect(&rcClient, ptCurPos)) | |
493 | bInhibit = TRUE; | |
494 | } | |
495 | } | |
496 | } | |
497 | } | |
498 | } | |
499 | ||
500 | if (pCursor == NULL) { | |
501 | if (pScreenPriv->cursor.visible) { | |
502 | if (!bInhibit && g_fSoftwareCursor) | |
503 | ShowCursor(FALSE); | |
504 | pScreenPriv->cursor.visible = FALSE; | |
505 | } | |
506 | } | |
507 | else { | |
508 | if (pScreenPriv->cursor.handle) { | |
509 | if (!bInhibit) | |
510 | SetCursor(NULL); | |
511 | DestroyCursor(pScreenPriv->cursor.handle); | |
512 | pScreenPriv->cursor.handle = NULL; | |
513 | } | |
514 | pScreenPriv->cursor.handle = | |
515 | winLoadCursor(pScreen, pCursor, pScreen->myNum); | |
516 | WIN_DEBUG_MSG("winSetCursor: handle=%p\n", pScreenPriv->cursor.handle); | |
517 | ||
518 | if (!bInhibit) | |
519 | SetCursor(pScreenPriv->cursor.handle); | |
520 | ||
521 | if (!pScreenPriv->cursor.visible) { | |
522 | if (!bInhibit && g_fSoftwareCursor) | |
523 | ShowCursor(TRUE); | |
524 | pScreenPriv->cursor.visible = TRUE; | |
525 | } | |
526 | } | |
527 | } | |
528 | ||
529 | /* | |
530 | * winMoveCursor | |
531 | * Move the cursor. This is a noop for us. | |
532 | */ | |
533 | static void | |
534 | winMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) | |
535 | { | |
536 | } | |
537 | ||
538 | static Bool | |
539 | winDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) | |
540 | { | |
541 | winScreenPriv(pScr); | |
542 | return pScreenPriv->cursor.spriteFuncs->DeviceCursorInitialize(pDev, pScr); | |
543 | } | |
544 | ||
545 | static void | |
546 | winDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) | |
547 | { | |
548 | winScreenPriv(pScr); | |
549 | pScreenPriv->cursor.spriteFuncs->DeviceCursorCleanup(pDev, pScr); | |
550 | } | |
551 | ||
552 | static miPointerSpriteFuncRec winSpriteFuncsRec = { | |
553 | winRealizeCursor, | |
554 | winUnrealizeCursor, | |
555 | winSetCursor, | |
556 | winMoveCursor, | |
557 | winDeviceCursorInitialize, | |
558 | winDeviceCursorCleanup | |
559 | }; | |
560 | ||
561 | /* | |
562 | =========================================================================== | |
563 | ||
564 | Other screen functions | |
565 | ||
566 | =========================================================================== | |
567 | */ | |
568 | ||
569 | /* | |
570 | * winCursorQueryBestSize | |
571 | * Handle queries for best cursor size | |
572 | */ | |
573 | static void | |
574 | winCursorQueryBestSize(int class, unsigned short *width, | |
575 | unsigned short *height, ScreenPtr pScreen) | |
576 | { | |
577 | winScreenPriv(pScreen); | |
578 | ||
579 | if (class == CursorShape) { | |
580 | *width = pScreenPriv->cursor.sm_cx; | |
581 | *height = pScreenPriv->cursor.sm_cy; | |
582 | } | |
583 | else { | |
584 | if (pScreenPriv->cursor.QueryBestSize) | |
585 | (*pScreenPriv->cursor.QueryBestSize) (class, width, height, | |
586 | pScreen); | |
587 | } | |
588 | } | |
589 | ||
590 | /* | |
591 | * winInitCursor | |
592 | * Initialize cursor support | |
593 | */ | |
594 | Bool | |
595 | winInitCursor(ScreenPtr pScreen) | |
596 | { | |
597 | winScreenPriv(pScreen); | |
598 | miPointerScreenPtr pPointPriv; | |
599 | ||
600 | /* override some screen procedures */ | |
601 | pScreenPriv->cursor.QueryBestSize = pScreen->QueryBestSize; | |
602 | pScreen->QueryBestSize = winCursorQueryBestSize; | |
603 | ||
604 | pPointPriv = (miPointerScreenPtr) | |
605 | dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); | |
606 | ||
607 | pScreenPriv->cursor.spriteFuncs = pPointPriv->spriteFuncs; | |
608 | pPointPriv->spriteFuncs = &winSpriteFuncsRec; | |
609 | ||
610 | pScreenPriv->cursor.handle = NULL; | |
611 | pScreenPriv->cursor.visible = FALSE; | |
612 | ||
613 | pScreenPriv->cursor.sm_cx = GetSystemMetrics(SM_CXCURSOR); | |
614 | pScreenPriv->cursor.sm_cy = GetSystemMetrics(SM_CYCURSOR); | |
615 | ||
616 | return TRUE; | |
617 | } |