14642e01fSmrg/************************************************************** 24642e01fSmrg * 34642e01fSmrg * Xplugin cursor support 44642e01fSmrg * 54642e01fSmrg * Copyright (c) 2001 Torrey T. Lyons and Greg Parker. 64642e01fSmrg * Copyright (c) 2002 Apple Computer, Inc. 74642e01fSmrg * All Rights Reserved. 84642e01fSmrg * 94642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 104642e01fSmrg * copy of this software and associated documentation files (the "Software"), 114642e01fSmrg * to deal in the Software without restriction, including without limitation 124642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 134642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the 144642e01fSmrg * Software is furnished to do so, subject to the following conditions: 154642e01fSmrg * 164642e01fSmrg * The above copyright notice and this permission notice shall be included in 174642e01fSmrg * all copies or substantial portions of the Software. 184642e01fSmrg * 194642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 204642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 214642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 224642e01fSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 234642e01fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 244642e01fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 254642e01fSmrg * DEALINGS IN THE SOFTWARE. 264642e01fSmrg * 274642e01fSmrg * Except as contained in this notice, the name(s) of the above copyright 284642e01fSmrg * holders shall not be used in advertising or otherwise to promote the sale, 294642e01fSmrg * use or other dealings in this Software without prior written authorization. 304642e01fSmrg */ 314642e01fSmrg 324642e01fSmrg#include "sanitizedCarbon.h" 334642e01fSmrg 344642e01fSmrg#ifdef HAVE_DIX_CONFIG_H 354642e01fSmrg#include <dix-config.h> 364642e01fSmrg#endif 374642e01fSmrg 386747b715Smrg#include "quartz.h" 394642e01fSmrg#include "xpr.h" 404642e01fSmrg#include "darwinEvents.h" 414642e01fSmrg#include <Xplugin.h> 424642e01fSmrg 434642e01fSmrg#include "mi.h" 444642e01fSmrg#include "scrnintstr.h" 454642e01fSmrg#include "cursorstr.h" 464642e01fSmrg#include "mipointrst.h" 474642e01fSmrg#include "windowstr.h" 484642e01fSmrg#include "globals.h" 494642e01fSmrg#include "servermd.h" 504642e01fSmrg#include "dixevents.h" 514642e01fSmrg#include "x-hash.h" 524642e01fSmrg 534642e01fSmrgtypedef struct { 5435c4bbdfSmrg int cursorVisible; 5535c4bbdfSmrg QueryBestSizeProcPtr QueryBestSize; 5635c4bbdfSmrg miPointerSpriteFuncPtr spriteFuncs; 574642e01fSmrg} QuartzCursorScreenRec, *QuartzCursorScreenPtr; 584642e01fSmrg 596747b715Smrgstatic DevPrivateKeyRec darwinCursorScreenKeyRec; 606747b715Smrg#define darwinCursorScreenKey (&darwinCursorScreenKeyRec) 614642e01fSmrg 624642e01fSmrg#define CURSOR_PRIV(pScreen) ((QuartzCursorScreenPtr) \ 6335c4bbdfSmrg dixLookupPrivate(&pScreen->devPrivates, \ 6435c4bbdfSmrg darwinCursorScreenKey)) 654642e01fSmrg 664642e01fSmrgstatic Bool 674642e01fSmrgload_cursor(CursorPtr src, int screen) 684642e01fSmrg{ 694642e01fSmrg uint32_t *data; 706747b715Smrg Bool free_data = FALSE; 714642e01fSmrg uint32_t rowbytes; 724642e01fSmrg int width, height; 734642e01fSmrg int hot_x, hot_y; 744642e01fSmrg 754642e01fSmrg uint32_t fg_color, bg_color; 764642e01fSmrg uint8_t *srow, *sptr; 774642e01fSmrg uint8_t *mrow, *mptr; 784642e01fSmrg uint32_t *drow, *dptr; 794642e01fSmrg unsigned xcount, ycount; 804642e01fSmrg 814642e01fSmrg xp_error err; 824642e01fSmrg 834642e01fSmrg width = src->bits->width; 844642e01fSmrg height = src->bits->height; 854642e01fSmrg hot_x = src->bits->xhot; 864642e01fSmrg hot_y = src->bits->yhot; 874642e01fSmrg 8835c4bbdfSmrg if (src->bits->argb != NULL) { 894642e01fSmrg#if BITMAP_BIT_ORDER == MSBFirst 9035c4bbdfSmrg rowbytes = src->bits->width * sizeof(CARD32); 9135c4bbdfSmrg data = (uint32_t *)src->bits->argb; 924642e01fSmrg#else 9335c4bbdfSmrg const uint32_t *be_data = (uint32_t *)src->bits->argb; 944642e01fSmrg unsigned i; 9535c4bbdfSmrg rowbytes = src->bits->width * sizeof(CARD32); 966747b715Smrg data = malloc(rowbytes * src->bits->height); 976747b715Smrg free_data = TRUE; 9835c4bbdfSmrg if (!data) { 996747b715Smrg FatalError("Failed to allocate memory in %s\n", __func__); 1006747b715Smrg } 10135c4bbdfSmrg for (i = 0; i < (src->bits->width * src->bits->height); i++) 10235c4bbdfSmrg data[i] = ntohl(be_data[i]); 1034642e01fSmrg#endif 1044642e01fSmrg } 1054642e01fSmrg else 1064642e01fSmrg { 1074642e01fSmrg fg_color = 0xFF00 | (src->foreRed >> 8); 1084642e01fSmrg fg_color <<= 16; 1094642e01fSmrg fg_color |= src->foreGreen & 0xFF00; 1104642e01fSmrg fg_color |= src->foreBlue >> 8; 1114642e01fSmrg 1124642e01fSmrg bg_color = 0xFF00 | (src->backRed >> 8); 1134642e01fSmrg bg_color <<= 16; 1144642e01fSmrg bg_color |= src->backGreen & 0xFF00; 1154642e01fSmrg bg_color |= src->backBlue >> 8; 1164642e01fSmrg 1174642e01fSmrg fg_color = htonl(fg_color); 1184642e01fSmrg bg_color = htonl(bg_color); 1194642e01fSmrg 1204642e01fSmrg /* round up to 8 pixel boundary so we can convert whole bytes */ 1214642e01fSmrg rowbytes = ((src->bits->width * 4) + 31) & ~31; 1226747b715Smrg data = malloc(rowbytes * src->bits->height); 1236747b715Smrg free_data = TRUE; 12435c4bbdfSmrg if (!data) { 1256747b715Smrg FatalError("Failed to allocate memory in %s\n", __func__); 1266747b715Smrg } 12735c4bbdfSmrg 12835c4bbdfSmrg if (!src->bits->emptyMask) { 1294642e01fSmrg ycount = src->bits->height; 13035c4bbdfSmrg srow = src->bits->source; 13135c4bbdfSmrg mrow = src->bits->mask; 1324642e01fSmrg drow = data; 1334642e01fSmrg 1344642e01fSmrg while (ycount-- > 0) 1354642e01fSmrg { 1366747b715Smrg xcount = bits_to_bytes(src->bits->width); 13735c4bbdfSmrg sptr = srow; 13835c4bbdfSmrg mptr = mrow; 1394642e01fSmrg dptr = drow; 1404642e01fSmrg 1414642e01fSmrg while (xcount-- > 0) 1424642e01fSmrg { 1434642e01fSmrg uint8_t s, m; 1444642e01fSmrg int i; 1454642e01fSmrg 14635c4bbdfSmrg s = *sptr++; 14735c4bbdfSmrg m = *mptr++; 14835c4bbdfSmrg for (i = 0; i < 8; i++) { 1494642e01fSmrg#if BITMAP_BIT_ORDER == MSBFirst 1504642e01fSmrg if (m & 128) 1514642e01fSmrg *dptr++ = (s & 128) ? fg_color : bg_color; 1524642e01fSmrg else 1534642e01fSmrg *dptr++ = 0; 15435c4bbdfSmrg s <<= 1; 15535c4bbdfSmrg m <<= 1; 1564642e01fSmrg#else 1574642e01fSmrg if (m & 1) 1584642e01fSmrg *dptr++ = (s & 1) ? fg_color : bg_color; 1594642e01fSmrg else 1604642e01fSmrg *dptr++ = 0; 16135c4bbdfSmrg s >>= 1; 16235c4bbdfSmrg m >>= 1; 1634642e01fSmrg#endif 1644642e01fSmrg } 1654642e01fSmrg } 1664642e01fSmrg 1674642e01fSmrg srow += BitmapBytePad(src->bits->width); 1684642e01fSmrg mrow += BitmapBytePad(src->bits->width); 16935c4bbdfSmrg drow = (uint32_t *)((char *)drow + rowbytes); 1704642e01fSmrg } 1714642e01fSmrg } 17235c4bbdfSmrg else { 1734642e01fSmrg memset(data, 0, src->bits->height * rowbytes); 1744642e01fSmrg } 1754642e01fSmrg } 1764642e01fSmrg 1774642e01fSmrg err = xp_set_cursor(width, height, hot_x, hot_y, data, rowbytes); 17835c4bbdfSmrg if (free_data) 1796747b715Smrg free(data); 1804642e01fSmrg return err == Success; 1814642e01fSmrg} 1824642e01fSmrg 1834642e01fSmrg/* 18435c4bbdfSmrg =========================================================================== 1854642e01fSmrg 18635c4bbdfSmrg Pointer sprite functions 1874642e01fSmrg 18835c4bbdfSmrg =========================================================================== 18935c4bbdfSmrg */ 1904642e01fSmrg 1914642e01fSmrg/* 1924642e01fSmrg * QuartzRealizeCursor 1934642e01fSmrg * Convert the X cursor representation to native format if possible. 1944642e01fSmrg */ 1954642e01fSmrgstatic Bool 1964642e01fSmrgQuartzRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 1974642e01fSmrg{ 19835c4bbdfSmrg if (pCursor == NULL || pCursor->bits == NULL) 1994642e01fSmrg return FALSE; 2004642e01fSmrg 2014642e01fSmrg /* FIXME: cache ARGB8888 representation? */ 2024642e01fSmrg 2034642e01fSmrg return TRUE; 2044642e01fSmrg} 2054642e01fSmrg 2064642e01fSmrg/* 2074642e01fSmrg * QuartzUnrealizeCursor 2084642e01fSmrg * Free the storage space associated with a realized cursor. 2094642e01fSmrg */ 2104642e01fSmrgstatic Bool 2114642e01fSmrgQuartzUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 2124642e01fSmrg{ 2134642e01fSmrg return TRUE; 2144642e01fSmrg} 2154642e01fSmrg 2164642e01fSmrg/* 2174642e01fSmrg * QuartzSetCursor 2184642e01fSmrg * Set the cursor sprite and position. 2194642e01fSmrg */ 2204642e01fSmrgstatic void 22135c4bbdfSmrgQuartzSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, 22235c4bbdfSmrg int x, 22335c4bbdfSmrg int y) 2244642e01fSmrg{ 2254642e01fSmrg QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); 2264642e01fSmrg 2276747b715Smrg if (!XQuartzServerVisible) 2284642e01fSmrg return; 2294642e01fSmrg 23035c4bbdfSmrg if (pCursor == NULL) { 23135c4bbdfSmrg if (ScreenPriv->cursorVisible) { 2324642e01fSmrg xp_hide_cursor(); 2334642e01fSmrg ScreenPriv->cursorVisible = FALSE; 2344642e01fSmrg } 2354642e01fSmrg } 23635c4bbdfSmrg else { 2374642e01fSmrg load_cursor(pCursor, pScreen->myNum); 2384642e01fSmrg 23935c4bbdfSmrg if (!ScreenPriv->cursorVisible) { 2404642e01fSmrg xp_show_cursor(); 2414642e01fSmrg ScreenPriv->cursorVisible = TRUE; 2424642e01fSmrg } 2434642e01fSmrg } 2444642e01fSmrg} 2454642e01fSmrg 2464642e01fSmrg/* 2474642e01fSmrg * QuartzMoveCursor 2484642e01fSmrg * Move the cursor. This is a noop for us. 2494642e01fSmrg */ 2504642e01fSmrgstatic void 2514642e01fSmrgQuartzMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 25235c4bbdfSmrg{} 2534642e01fSmrg 2544642e01fSmrg/* 25535c4bbdfSmrg =========================================================================== 2564642e01fSmrg 25735c4bbdfSmrg Pointer screen functions 2584642e01fSmrg 25935c4bbdfSmrg =========================================================================== 26035c4bbdfSmrg */ 2614642e01fSmrg 2624642e01fSmrg/* 2634642e01fSmrg * QuartzCursorOffScreen 2644642e01fSmrg */ 2654642e01fSmrgstatic Bool 2664642e01fSmrgQuartzCursorOffScreen(ScreenPtr *pScreen, int *x, int *y) 2674642e01fSmrg{ 2684642e01fSmrg return FALSE; 2694642e01fSmrg} 2704642e01fSmrg 2714642e01fSmrg/* 2724642e01fSmrg * QuartzCrossScreen 2734642e01fSmrg */ 2744642e01fSmrgstatic void 2754642e01fSmrgQuartzCrossScreen(ScreenPtr pScreen, Bool entering) 2764642e01fSmrg{ 2774642e01fSmrg return; 2784642e01fSmrg} 2794642e01fSmrg 2804642e01fSmrg/* 2814642e01fSmrg * QuartzWarpCursor 2824642e01fSmrg * Change the cursor position without generating an event or motion history. 2834642e01fSmrg * The input coordinates (x,y) are in pScreen-local X11 coordinates. 2844642e01fSmrg * 2854642e01fSmrg */ 2864642e01fSmrgstatic void 2874642e01fSmrgQuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 2884642e01fSmrg{ 28935c4bbdfSmrg if (XQuartzServerVisible) { 2904642e01fSmrg int sx, sy; 2914642e01fSmrg 2926747b715Smrg sx = pScreen->x + darwinMainScreenX; 2936747b715Smrg sy = pScreen->y + darwinMainScreenY; 2944642e01fSmrg 2954642e01fSmrg CGWarpMouseCursorPosition(CGPointMake(sx + x, sy + y)); 2964642e01fSmrg } 2974642e01fSmrg 2984642e01fSmrg miPointerWarpCursor(pDev, pScreen, x, y); 2994642e01fSmrg miPointerUpdateSprite(pDev); 3004642e01fSmrg} 3014642e01fSmrg 3024642e01fSmrgstatic miPointerScreenFuncRec quartzScreenFuncsRec = { 3034642e01fSmrg QuartzCursorOffScreen, 3044642e01fSmrg QuartzCrossScreen, 3054642e01fSmrg QuartzWarpCursor, 3064642e01fSmrg}; 3074642e01fSmrg 3084642e01fSmrg/* 30935c4bbdfSmrg =========================================================================== 3104642e01fSmrg 31135c4bbdfSmrg Other screen functions 3124642e01fSmrg 31335c4bbdfSmrg =========================================================================== 31435c4bbdfSmrg */ 3154642e01fSmrg 3164642e01fSmrg/* 3174642e01fSmrg * QuartzCursorQueryBestSize 3184642e01fSmrg * Handle queries for best cursor size 3194642e01fSmrg */ 3204642e01fSmrgstatic void 3214642e01fSmrgQuartzCursorQueryBestSize(int class, unsigned short *width, 3224642e01fSmrg unsigned short *height, ScreenPtr pScreen) 3234642e01fSmrg{ 3244642e01fSmrg QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); 3254642e01fSmrg 32635c4bbdfSmrg if (class == CursorShape) { 3274642e01fSmrg /* FIXME: query window server? */ 3284642e01fSmrg *width = 32; 3294642e01fSmrg *height = 32; 3304642e01fSmrg } 33135c4bbdfSmrg else { 3324642e01fSmrg (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); 3334642e01fSmrg } 3344642e01fSmrg} 3354642e01fSmrg 3364642e01fSmrg/* 3374642e01fSmrg * QuartzInitCursor 3384642e01fSmrg * Initialize cursor support 3394642e01fSmrg */ 3404642e01fSmrgBool 3414642e01fSmrgQuartzInitCursor(ScreenPtr pScreen) 3424642e01fSmrg{ 3434642e01fSmrg QuartzCursorScreenPtr ScreenPriv; 3444642e01fSmrg miPointerScreenPtr PointPriv; 3454642e01fSmrg 3464642e01fSmrg /* initialize software cursor handling (always needed as backup) */ 3474642e01fSmrg if (!miDCInitialize(pScreen, &quartzScreenFuncsRec)) 3484642e01fSmrg return FALSE; 3494642e01fSmrg 3506747b715Smrg if (!dixRegisterPrivateKey(&darwinCursorScreenKeyRec, PRIVATE_SCREEN, 0)) 35135c4bbdfSmrg return FALSE; 3526747b715Smrg 3536747b715Smrg ScreenPriv = calloc(1, sizeof(QuartzCursorScreenRec)); 3544642e01fSmrg if (ScreenPriv == NULL) 3554642e01fSmrg return FALSE; 3564642e01fSmrg 3574642e01fSmrg /* CURSOR_PRIV(pScreen) = ScreenPriv; */ 3584642e01fSmrg dixSetPrivate(&pScreen->devPrivates, darwinCursorScreenKey, ScreenPriv); 3594642e01fSmrg 3604642e01fSmrg /* override some screen procedures */ 3614642e01fSmrg ScreenPriv->QueryBestSize = pScreen->QueryBestSize; 3624642e01fSmrg pScreen->QueryBestSize = QuartzCursorQueryBestSize; 3634642e01fSmrg 3644642e01fSmrg PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 3654642e01fSmrg 3664642e01fSmrg ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; 3674642e01fSmrg 3684642e01fSmrg PointPriv->spriteFuncs->RealizeCursor = QuartzRealizeCursor; 3694642e01fSmrg PointPriv->spriteFuncs->UnrealizeCursor = QuartzUnrealizeCursor; 3704642e01fSmrg PointPriv->spriteFuncs->SetCursor = QuartzSetCursor; 3714642e01fSmrg PointPriv->spriteFuncs->MoveCursor = QuartzMoveCursor; 37235c4bbdfSmrg 3734642e01fSmrg ScreenPriv->cursorVisible = TRUE; 3744642e01fSmrg return TRUE; 3754642e01fSmrg} 3764642e01fSmrg 3774642e01fSmrg/* 3784642e01fSmrg * QuartzSuspendXCursor 3794642e01fSmrg * X server is hiding. Restore the Aqua cursor. 3804642e01fSmrg */ 3814642e01fSmrgvoid 3824642e01fSmrgQuartzSuspendXCursor(ScreenPtr pScreen) 383a035e2b2Smrg{ 384a035e2b2Smrg xp_show_cursor(); 385a035e2b2Smrg} 3864642e01fSmrg 3874642e01fSmrg/* 3884642e01fSmrg * QuartzResumeXCursor 3894642e01fSmrg * X server is showing. Restore the X cursor. 3904642e01fSmrg */ 3914642e01fSmrgvoid 3926747b715SmrgQuartzResumeXCursor(ScreenPtr pScreen) 3934642e01fSmrg{ 3944642e01fSmrg WindowPtr pWin; 3954642e01fSmrg CursorPtr pCursor; 3964642e01fSmrg 3974642e01fSmrg /* TODO: Tablet? */ 39835c4bbdfSmrg 3994642e01fSmrg pWin = GetSpriteWindow(darwinPointer); 4004642e01fSmrg if (pWin->drawable.pScreen != pScreen) 4014642e01fSmrg return; 4024642e01fSmrg 4034642e01fSmrg pCursor = GetSpriteCursor(darwinPointer); 4044642e01fSmrg if (pCursor == NULL) 4054642e01fSmrg return; 4064642e01fSmrg 4076747b715Smrg QuartzSetCursor(darwinPointer, pScreen, pCursor, /* x */ 0, /* y */ 0); 4084642e01fSmrg} 409