xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

wincursor.c (19677B)


      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         || pScreenPriv->pScreenInfo->fMultiWindow
     99         ) {
    100         /* Get the client area coordinates */
    101         GetClientRect(pScreenPriv->hwndScreen, &rcClient);
    102 
    103         /* Translate the client area coords to screen coords */
    104         MapWindowPoints(pScreenPriv->hwndScreen,
    105                         HWND_DESKTOP, (LPPOINT) &rcClient, 2);
    106 
    107         /*
    108          * Update the Windows cursor position so that we don't
    109          * immediately warp back to the current position.
    110          */
    111         SetCursorPos(rcClient.left + x, rcClient.top + y);
    112     }
    113 
    114     /* Call the mi warp procedure to do the actual warping in X. */
    115     miPointerWarpCursor(pDev, pScreen, x, y);
    116 }
    117 
    118 static Bool
    119 winCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
    120 {
    121     return FALSE;
    122 }
    123 
    124 static void
    125 winCrossScreen(ScreenPtr pScreen, Bool fEntering)
    126 {
    127 }
    128 
    129 static unsigned char
    130 reverse(unsigned char c)
    131 {
    132     int i;
    133     unsigned char ret = 0;
    134 
    135     for (i = 0; i < 8; ++i) {
    136         ret |= ((c >> i) & 1) << (7 - i);
    137     }
    138     return ret;
    139 }
    140 
    141 /*
    142  * Convert X cursor to Windows cursor
    143  * FIXME: Perhaps there are more smart code
    144  */
    145 static HCURSOR
    146 winLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int screen)
    147 {
    148     winScreenPriv(pScreen);
    149     HCURSOR hCursor = NULL;
    150     unsigned char *pAnd;
    151     unsigned char *pXor;
    152     int nCX, nCY;
    153     int nBytes;
    154     double dForeY, dBackY;
    155     BOOL fReverse;
    156     HBITMAP hAnd, hXor;
    157     ICONINFO ii;
    158     unsigned char *pCur;
    159     unsigned char bit;
    160     HDC hDC;
    161     BITMAPV4HEADER bi;
    162     BITMAPINFO *pbmi;
    163     uint32_t *lpBits;
    164 
    165     WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d hotspot: %d,%d\n",
    166                   pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
    167                   pCursor->bits->width, pCursor->bits->height,
    168                   pCursor->bits->xhot, pCursor->bits->yhot);
    169 
    170     /* We can use only White and Black, so calc brightness of color
    171      * Also check if the cursor is inverted */
    172     dForeY = BRIGHTNESS(pCursor->fore);
    173     dBackY = BRIGHTNESS(pCursor->back);
    174     fReverse = dForeY < dBackY;
    175 
    176     /* Check whether the X11 cursor is bigger than the win32 cursor */
    177     if (pScreenPriv->cursor.sm_cx < pCursor->bits->width ||
    178         pScreenPriv->cursor.sm_cy < pCursor->bits->height) {
    179         winErrorFVerb(3,
    180                       "winLoadCursor - Windows requires %dx%d cursor but X requires %dx%d\n",
    181                       pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
    182                       pCursor->bits->width, pCursor->bits->height);
    183     }
    184 
    185     /* Get the number of bytes required to store the whole cursor image
    186      * This is roughly (sm_cx * sm_cy) / 8
    187      * round up to 8 pixel boundary so we can convert whole bytes */
    188     nBytes =
    189         bits_to_bytes(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy;
    190 
    191     /* Get the effective width and height */
    192     nCX = min(pScreenPriv->cursor.sm_cx, pCursor->bits->width);
    193     nCY = min(pScreenPriv->cursor.sm_cy, pCursor->bits->height);
    194 
    195     /* Allocate memory for the bitmaps */
    196     pAnd = malloc(nBytes);
    197     memset(pAnd, 0xFF, nBytes);
    198     pXor = calloc(1, nBytes);
    199 
    200     /* Convert the X11 bitmap to a win32 bitmap
    201      * The first is for an empty mask */
    202     if (pCursor->bits->emptyMask) {
    203         int x, y, xmax = bits_to_bytes(nCX);
    204 
    205         for (y = 0; y < nCY; ++y)
    206             for (x = 0; x < xmax; ++x) {
    207                 int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x;
    208                 int nXPix = BitmapBytePad(pCursor->bits->width) * y + x;
    209 
    210                 pAnd[nWinPix] = 0;
    211                 if (fReverse)
    212                     pXor[nWinPix] = reverse(~pCursor->bits->source[nXPix]);
    213                 else
    214                     pXor[nWinPix] = reverse(pCursor->bits->source[nXPix]);
    215             }
    216     }
    217     else {
    218         int x, y, xmax = bits_to_bytes(nCX);
    219 
    220         for (y = 0; y < nCY; ++y)
    221             for (x = 0; x < xmax; ++x) {
    222                 int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x;
    223                 int nXPix = BitmapBytePad(pCursor->bits->width) * y + x;
    224 
    225                 unsigned char mask = pCursor->bits->mask[nXPix];
    226 
    227                 pAnd[nWinPix] = reverse(~mask);
    228                 if (fReverse)
    229                     pXor[nWinPix] =
    230                         reverse(~pCursor->bits->source[nXPix] & mask);
    231                 else
    232                     pXor[nWinPix] =
    233                         reverse(pCursor->bits->source[nXPix] & mask);
    234             }
    235     }
    236 
    237     /* prepare the pointers */
    238     hCursor = NULL;
    239     lpBits = NULL;
    240 
    241     /* We have a truecolor alpha-blended cursor and can use it! */
    242     if (pCursor->bits->argb) {
    243         WIN_DEBUG_MSG("winLoadCursor: Trying truecolor alphablended cursor\n");
    244         memset(&bi, 0, sizeof(BITMAPV4HEADER));
    245         bi.bV4Size = sizeof(BITMAPV4HEADER);
    246         bi.bV4Width = pScreenPriv->cursor.sm_cx;
    247         bi.bV4Height = -(pScreenPriv->cursor.sm_cy);    /* right-side up */
    248         bi.bV4Planes = 1;
    249         bi.bV4BitCount = 32;
    250         bi.bV4V4Compression = BI_BITFIELDS;
    251         bi.bV4RedMask = 0x00FF0000;
    252         bi.bV4GreenMask = 0x0000FF00;
    253         bi.bV4BlueMask = 0x000000FF;
    254         bi.bV4AlphaMask = 0xFF000000;
    255 
    256         lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy,
    257                         sizeof(uint32_t));
    258 
    259         if (lpBits) {
    260             int y;
    261             for (y = 0; y < nCY; y++) {
    262                 void *src, *dst;
    263                 src = &(pCursor->bits->argb[y * pCursor->bits->width]);
    264                 dst = &(lpBits[y * pScreenPriv->cursor.sm_cx]);
    265                 memcpy(dst, src, 4 * nCX);
    266             }
    267         }
    268     }                           /* End if-truecolor-icon */
    269 
    270     if (!lpBits) {
    271         RGBQUAD *pbmiColors;
    272         /* Bicolor, use a palettized DIB */
    273         WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n");
    274         pbmi = (BITMAPINFO *) &bi;
    275         pbmiColors = &(pbmi->bmiColors[0]);
    276 
    277         memset(pbmi, 0, sizeof(BITMAPINFOHEADER));
    278         pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    279         pbmi->bmiHeader.biWidth = pScreenPriv->cursor.sm_cx;
    280         pbmi->bmiHeader.biHeight = -abs(pScreenPriv->cursor.sm_cy);     /* right-side up */
    281         pbmi->bmiHeader.biPlanes = 1;
    282         pbmi->bmiHeader.biBitCount = 8;
    283         pbmi->bmiHeader.biCompression = BI_RGB;
    284         pbmi->bmiHeader.biSizeImage = 0;
    285         pbmi->bmiHeader.biClrUsed = 3;
    286         pbmi->bmiHeader.biClrImportant = 3;
    287 
    288         pbmiColors[0].rgbRed = 0;  /* Empty */
    289         pbmiColors[0].rgbGreen = 0;
    290         pbmiColors[0].rgbBlue = 0;
    291         pbmiColors[0].rgbReserved = 0;
    292         pbmiColors[1].rgbRed = pCursor->backRed >> 8;      /* Background */
    293         pbmiColors[1].rgbGreen = pCursor->backGreen >> 8;
    294         pbmiColors[1].rgbBlue = pCursor->backBlue >> 8;
    295         pbmiColors[1].rgbReserved = 0;
    296         pbmiColors[2].rgbRed = pCursor->foreRed >> 8;      /* Foreground */
    297         pbmiColors[2].rgbGreen = pCursor->foreGreen >> 8;
    298         pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
    299         pbmiColors[2].rgbReserved = 0;
    300 
    301         lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy, 1);
    302 
    303         pCur = (unsigned char *) lpBits;
    304         if (lpBits) {
    305 	    int x, y;
    306             for (y = 0; y < pScreenPriv->cursor.sm_cy; y++) {
    307                 for (x = 0; x < pScreenPriv->cursor.sm_cx; x++) {
    308                     if (x >= nCX || y >= nCY)   /* Outside of X11 icon bounds */
    309                         (*pCur++) = 0;
    310                     else {      /* Within X11 icon bounds */
    311 
    312                         int nWinPix =
    313                             bits_to_bytes(pScreenPriv->cursor.sm_cx) * y +
    314                             (x / 8);
    315 
    316                         bit = pAnd[nWinPix];
    317                         bit = bit & (1 << (7 - (x & 7)));
    318                         if (!bit) {     /* Within the cursor mask? */
    319                             int nXPix =
    320                                 BitmapBytePad(pCursor->bits->width) * y +
    321                                 (x / 8);
    322                             bit =
    323                                 ~reverse(~pCursor->bits->
    324                                          source[nXPix] & pCursor->bits->
    325                                          mask[nXPix]);
    326                             bit = bit & (1 << (7 - (x & 7)));
    327                             if (bit)    /* Draw foreground */
    328                                 (*pCur++) = 2;
    329                             else        /* Draw background */
    330                                 (*pCur++) = 1;
    331                         }
    332                         else    /* Outside the cursor mask */
    333                             (*pCur++) = 0;
    334                     }
    335                 }               /* end for (x) */
    336             }                   /* end for (y) */
    337         }                       /* end if (lpbits) */
    338     }
    339 
    340     /* If one of the previous two methods gave us the bitmap we need, make a cursor */
    341     if (lpBits) {
    342         WIN_DEBUG_MSG("winLoadCursor: Creating bitmap cursor: hotspot %d,%d\n",
    343                       pCursor->bits->xhot, pCursor->bits->yhot);
    344 
    345         hAnd = NULL;
    346         hXor = NULL;
    347 
    348         hAnd =
    349             CreateBitmap(pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy,
    350                          1, 1, pAnd);
    351 
    352         hDC = GetDC(NULL);
    353         if (hDC) {
    354             hXor =
    355                 CreateCompatibleBitmap(hDC, pScreenPriv->cursor.sm_cx,
    356                                        pScreenPriv->cursor.sm_cy);
    357             SetDIBits(hDC, hXor, 0, pScreenPriv->cursor.sm_cy, lpBits,
    358                       (BITMAPINFO *) &bi, DIB_RGB_COLORS);
    359             ReleaseDC(NULL, hDC);
    360         }
    361         free(lpBits);
    362 
    363         if (hAnd && hXor) {
    364             ii.fIcon = FALSE;
    365             ii.xHotspot = pCursor->bits->xhot;
    366             ii.yHotspot = pCursor->bits->yhot;
    367             ii.hbmMask = hAnd;
    368             ii.hbmColor = hXor;
    369             hCursor = (HCURSOR) CreateIconIndirect(&ii);
    370 
    371             if (hCursor == NULL)
    372                 winW32Error(2, "winLoadCursor - CreateIconIndirect failed:");
    373             else {
    374                 if (GetIconInfo(hCursor, &ii)) {
    375                     if (ii.fIcon) {
    376                         WIN_DEBUG_MSG
    377                             ("winLoadCursor: CreateIconIndirect returned  no cursor. Trying again.\n");
    378 
    379                         DestroyCursor(hCursor);
    380 
    381                         ii.fIcon = FALSE;
    382                         ii.xHotspot = pCursor->bits->xhot;
    383                         ii.yHotspot = pCursor->bits->yhot;
    384                         hCursor = (HCURSOR) CreateIconIndirect(&ii);
    385 
    386                         if (hCursor == NULL)
    387                             winW32Error(2,
    388                                         "winLoadCursor - CreateIconIndirect failed:");
    389                     }
    390                     /* GetIconInfo creates new bitmaps. Destroy them again */
    391                     if (ii.hbmMask)
    392                         DeleteObject(ii.hbmMask);
    393                     if (ii.hbmColor)
    394                         DeleteObject(ii.hbmColor);
    395                 }
    396             }
    397         }
    398 
    399         if (hAnd)
    400             DeleteObject(hAnd);
    401         if (hXor)
    402             DeleteObject(hXor);
    403     }
    404 
    405     if (!hCursor) {
    406         /* We couldn't make a color cursor for this screen, use
    407            black and white instead */
    408         hCursor = CreateCursor(g_hInstance,
    409                                pCursor->bits->xhot, pCursor->bits->yhot,
    410                                pScreenPriv->cursor.sm_cx,
    411                                pScreenPriv->cursor.sm_cy, pAnd, pXor);
    412         if (hCursor == NULL)
    413             winW32Error(2, "winLoadCursor - CreateCursor failed:");
    414     }
    415     free(pAnd);
    416     free(pXor);
    417 
    418     return hCursor;
    419 }
    420 
    421 /*
    422 ===========================================================================
    423 
    424  Pointer sprite functions
    425 
    426 ===========================================================================
    427 */
    428 
    429 /*
    430  * winRealizeCursor
    431  *  Convert the X cursor representation to native format if possible.
    432  */
    433 static Bool
    434 winRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
    435 {
    436     if (pCursor == NULL || pCursor->bits == NULL)
    437         return FALSE;
    438 
    439     /* FIXME: cache ARGB8888 representation? */
    440 
    441     return TRUE;
    442 }
    443 
    444 /*
    445  * winUnrealizeCursor
    446  *  Free the storage space associated with a realized cursor.
    447  */
    448 static Bool
    449 winUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
    450 {
    451     return TRUE;
    452 }
    453 
    454 /*
    455  * winSetCursor
    456  *  Set the cursor sprite and position.
    457  */
    458 static void
    459 winSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x,
    460              int y)
    461 {
    462     POINT ptCurPos, ptTemp;
    463     HWND hwnd;
    464     RECT rcClient;
    465     BOOL bInhibit;
    466 
    467     winScreenPriv(pScreen);
    468     WIN_DEBUG_MSG("winSetCursor: cursor=%p\n", pCursor);
    469 
    470     /* Inhibit changing the cursor if the mouse is not in a client area */
    471     bInhibit = FALSE;
    472     if (GetCursorPos(&ptCurPos)) {
    473         hwnd = WindowFromPoint(ptCurPos);
    474         if (hwnd) {
    475             if (GetClientRect(hwnd, &rcClient)) {
    476                 ptTemp.x = rcClient.left;
    477                 ptTemp.y = rcClient.top;
    478                 if (ClientToScreen(hwnd, &ptTemp)) {
    479                     rcClient.left = ptTemp.x;
    480                     rcClient.top = ptTemp.y;
    481                     ptTemp.x = rcClient.right;
    482                     ptTemp.y = rcClient.bottom;
    483                     if (ClientToScreen(hwnd, &ptTemp)) {
    484                         rcClient.right = ptTemp.x;
    485                         rcClient.bottom = ptTemp.y;
    486                         if (!PtInRect(&rcClient, ptCurPos))
    487                             bInhibit = TRUE;
    488                     }
    489                 }
    490             }
    491         }
    492     }
    493 
    494     if (pCursor == NULL) {
    495         if (pScreenPriv->cursor.visible) {
    496             if (!bInhibit && g_fSoftwareCursor)
    497                 ShowCursor(FALSE);
    498             pScreenPriv->cursor.visible = FALSE;
    499         }
    500     }
    501     else {
    502         if (pScreenPriv->cursor.handle) {
    503             if (!bInhibit)
    504                 SetCursor(NULL);
    505             DestroyCursor(pScreenPriv->cursor.handle);
    506             pScreenPriv->cursor.handle = NULL;
    507         }
    508         pScreenPriv->cursor.handle =
    509             winLoadCursor(pScreen, pCursor, pScreen->myNum);
    510         WIN_DEBUG_MSG("winSetCursor: handle=%p\n", pScreenPriv->cursor.handle);
    511 
    512         if (!bInhibit)
    513             SetCursor(pScreenPriv->cursor.handle);
    514 
    515         if (!pScreenPriv->cursor.visible) {
    516             if (!bInhibit && g_fSoftwareCursor)
    517                 ShowCursor(TRUE);
    518             pScreenPriv->cursor.visible = TRUE;
    519         }
    520     }
    521 }
    522 
    523 /*
    524  * winMoveCursor
    525  *  Move the cursor. This is a noop for us.
    526  */
    527 static void
    528 winMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
    529 {
    530 }
    531 
    532 static Bool
    533 winDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr)
    534 {
    535     winScreenPriv(pScr);
    536     return pScreenPriv->cursor.spriteFuncs->DeviceCursorInitialize(pDev, pScr);
    537 }
    538 
    539 static void
    540 winDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr)
    541 {
    542     winScreenPriv(pScr);
    543     pScreenPriv->cursor.spriteFuncs->DeviceCursorCleanup(pDev, pScr);
    544 }
    545 
    546 static miPointerSpriteFuncRec winSpriteFuncsRec = {
    547     winRealizeCursor,
    548     winUnrealizeCursor,
    549     winSetCursor,
    550     winMoveCursor,
    551     winDeviceCursorInitialize,
    552     winDeviceCursorCleanup
    553 };
    554 
    555 /*
    556 ===========================================================================
    557 
    558  Other screen functions
    559 
    560 ===========================================================================
    561 */
    562 
    563 /*
    564  * winCursorQueryBestSize
    565  *  Handle queries for best cursor size
    566  */
    567 static void
    568 winCursorQueryBestSize(int class, unsigned short *width,
    569                        unsigned short *height, ScreenPtr pScreen)
    570 {
    571     winScreenPriv(pScreen);
    572 
    573     if (class == CursorShape) {
    574         *width = pScreenPriv->cursor.sm_cx;
    575         *height = pScreenPriv->cursor.sm_cy;
    576     }
    577     else {
    578         if (pScreenPriv->cursor.QueryBestSize)
    579             (*pScreenPriv->cursor.QueryBestSize) (class, width, height,
    580                                                   pScreen);
    581     }
    582 }
    583 
    584 /*
    585  * winInitCursor
    586  *  Initialize cursor support
    587  */
    588 Bool
    589 winInitCursor(ScreenPtr pScreen)
    590 {
    591     winScreenPriv(pScreen);
    592     miPointerScreenPtr pPointPriv;
    593 
    594     /* override some screen procedures */
    595     pScreenPriv->cursor.QueryBestSize = pScreen->QueryBestSize;
    596     pScreen->QueryBestSize = winCursorQueryBestSize;
    597 
    598     pPointPriv = (miPointerScreenPtr)
    599         dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
    600 
    601     pScreenPriv->cursor.spriteFuncs = pPointPriv->spriteFuncs;
    602     pPointPriv->spriteFuncs = &winSpriteFuncsRec;
    603 
    604     pScreenPriv->cursor.handle = NULL;
    605     pScreenPriv->cursor.visible = FALSE;
    606 
    607     pScreenPriv->cursor.sm_cx = GetSystemMetrics(SM_CXCURSOR);
    608     pScreenPriv->cursor.sm_cy = GetSystemMetrics(SM_CYCURSOR);
    609 
    610     return TRUE;
    611 }