1/************************************************************** 2 * 3 * Xplugin cursor support 4 * 5 * Copyright (c) 2001 Torrey T. Lyons and Greg Parker. 6 * Copyright (c) 2002 Apple Computer, Inc. 7 * All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 * 27 * Except as contained in this notice, the name(s) of the above copyright 28 * holders shall not be used in advertising or otherwise to promote the sale, 29 * use or other dealings in this Software without prior written authorization. 30 */ 31 32#include "sanitizedCarbon.h" 33 34#ifdef HAVE_DIX_CONFIG_H 35#include <dix-config.h> 36#endif 37 38#include "quartz.h" 39#include "xpr.h" 40#include "darwin.h" 41#include "darwinEvents.h" 42#include <Xplugin.h> 43 44#include "mi.h" 45#include "scrnintstr.h" 46#include "cursorstr.h" 47#include "mipointrst.h" 48#include "windowstr.h" 49#include "globals.h" 50#include "servermd.h" 51#include "dixevents.h" 52#include "x-hash.h" 53 54typedef struct { 55 int cursorVisible; 56 QueryBestSizeProcPtr QueryBestSize; 57 miPointerSpriteFuncPtr spriteFuncs; 58} QuartzCursorScreenRec, *QuartzCursorScreenPtr; 59 60static DevPrivateKeyRec darwinCursorScreenKeyRec; 61#define darwinCursorScreenKey (&darwinCursorScreenKeyRec) 62 63#define CURSOR_PRIV(pScreen) ((QuartzCursorScreenPtr) \ 64 dixLookupPrivate(&pScreen->devPrivates, darwinCursorScreenKey)) 65 66static Bool 67load_cursor(CursorPtr src, int screen) 68{ 69 uint32_t *data; 70 Bool free_data = FALSE; 71 uint32_t rowbytes; 72 int width, height; 73 int hot_x, hot_y; 74 75 uint32_t fg_color, bg_color; 76 uint8_t *srow, *sptr; 77 uint8_t *mrow, *mptr; 78 uint32_t *drow, *dptr; 79 unsigned xcount, ycount; 80 81 xp_error err; 82 83 width = src->bits->width; 84 height = src->bits->height; 85 hot_x = src->bits->xhot; 86 hot_y = src->bits->yhot; 87 88#ifdef ARGB_CURSOR 89 if (src->bits->argb != NULL) 90 { 91#if BITMAP_BIT_ORDER == MSBFirst 92 rowbytes = src->bits->width * sizeof (CARD32); 93 data = (uint32_t *) src->bits->argb; 94#else 95 const uint32_t *be_data=(uint32_t *) src->bits->argb; 96 unsigned i; 97 rowbytes = src->bits->width * sizeof (CARD32); 98 data = malloc(rowbytes * src->bits->height); 99 free_data = TRUE; 100 if(!data) { 101 FatalError("Failed to allocate memory in %s\n", __func__); 102 } 103 for(i=0;i<(src->bits->width*src->bits->height);i++) 104 data[i]=ntohl(be_data[i]); 105#endif 106 } 107 else 108#endif 109 { 110 fg_color = 0xFF00 | (src->foreRed >> 8); 111 fg_color <<= 16; 112 fg_color |= src->foreGreen & 0xFF00; 113 fg_color |= src->foreBlue >> 8; 114 115 bg_color = 0xFF00 | (src->backRed >> 8); 116 bg_color <<= 16; 117 bg_color |= src->backGreen & 0xFF00; 118 bg_color |= src->backBlue >> 8; 119 120 fg_color = htonl(fg_color); 121 bg_color = htonl(bg_color); 122 123 /* round up to 8 pixel boundary so we can convert whole bytes */ 124 rowbytes = ((src->bits->width * 4) + 31) & ~31; 125 data = malloc(rowbytes * src->bits->height); 126 free_data = TRUE; 127 if(!data) { 128 FatalError("Failed to allocate memory in %s\n", __func__); 129 } 130 131 if (!src->bits->emptyMask) 132 { 133 ycount = src->bits->height; 134 srow = src->bits->source; mrow = src->bits->mask; 135 drow = data; 136 137 while (ycount-- > 0) 138 { 139 xcount = bits_to_bytes(src->bits->width); 140 sptr = srow; mptr = mrow; 141 dptr = drow; 142 143 while (xcount-- > 0) 144 { 145 uint8_t s, m; 146 int i; 147 148 s = *sptr++; m = *mptr++; 149 for (i = 0; i < 8; i++) 150 { 151#if BITMAP_BIT_ORDER == MSBFirst 152 if (m & 128) 153 *dptr++ = (s & 128) ? fg_color : bg_color; 154 else 155 *dptr++ = 0; 156 s <<= 1; m <<= 1; 157#else 158 if (m & 1) 159 *dptr++ = (s & 1) ? fg_color : bg_color; 160 else 161 *dptr++ = 0; 162 s >>= 1; m >>= 1; 163#endif 164 } 165 } 166 167 srow += BitmapBytePad(src->bits->width); 168 mrow += BitmapBytePad(src->bits->width); 169 drow = (uint32_t *) ((char *) drow + rowbytes); 170 } 171 } 172 else 173 { 174 memset(data, 0, src->bits->height * rowbytes); 175 } 176 } 177 178 err = xp_set_cursor(width, height, hot_x, hot_y, data, rowbytes); 179 if(free_data) 180 free(data); 181 return err == Success; 182} 183 184 185/* 186=========================================================================== 187 188 Pointer sprite functions 189 190=========================================================================== 191*/ 192 193/* 194 * QuartzRealizeCursor 195 * Convert the X cursor representation to native format if possible. 196 */ 197static Bool 198QuartzRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 199{ 200 if(pCursor == NULL || pCursor->bits == NULL) 201 return FALSE; 202 203 /* FIXME: cache ARGB8888 representation? */ 204 205 return TRUE; 206} 207 208 209/* 210 * QuartzUnrealizeCursor 211 * Free the storage space associated with a realized cursor. 212 */ 213static Bool 214QuartzUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 215{ 216 return TRUE; 217} 218 219 220/* 221 * QuartzSetCursor 222 * Set the cursor sprite and position. 223 */ 224static void 225QuartzSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) 226{ 227 QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); 228 229 if (!XQuartzServerVisible) 230 return; 231 232 if (pCursor == NULL) 233 { 234 if (ScreenPriv->cursorVisible) 235 { 236 xp_hide_cursor(); 237 ScreenPriv->cursorVisible = FALSE; 238 } 239 } 240 else 241 { 242 load_cursor(pCursor, pScreen->myNum); 243 244 if (!ScreenPriv->cursorVisible) 245 { 246 xp_show_cursor(); 247 ScreenPriv->cursorVisible = TRUE; 248 } 249 } 250} 251 252/* 253 * QuartzMoveCursor 254 * Move the cursor. This is a noop for us. 255 */ 256static void 257QuartzMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 258{ 259} 260 261/* 262=========================================================================== 263 264 Pointer screen functions 265 266=========================================================================== 267*/ 268 269/* 270 * QuartzCursorOffScreen 271 */ 272static Bool 273QuartzCursorOffScreen(ScreenPtr *pScreen, int *x, int *y) 274{ 275 return FALSE; 276} 277 278 279/* 280 * QuartzCrossScreen 281 */ 282static void 283QuartzCrossScreen(ScreenPtr pScreen, Bool entering) 284{ 285 return; 286} 287 288 289/* 290 * QuartzWarpCursor 291 * Change the cursor position without generating an event or motion history. 292 * The input coordinates (x,y) are in pScreen-local X11 coordinates. 293 * 294 */ 295static void 296QuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 297{ 298 if (XQuartzServerVisible) 299 { 300 int sx, sy; 301 302 sx = pScreen->x + darwinMainScreenX; 303 sy = pScreen->y + darwinMainScreenY; 304 305 CGWarpMouseCursorPosition(CGPointMake(sx + x, sy + y)); 306 } 307 308 miPointerWarpCursor(pDev, pScreen, x, y); 309 miPointerUpdateSprite(pDev); 310} 311 312 313static miPointerScreenFuncRec quartzScreenFuncsRec = { 314 QuartzCursorOffScreen, 315 QuartzCrossScreen, 316 QuartzWarpCursor, 317 NULL, 318 NULL 319}; 320 321 322/* 323=========================================================================== 324 325 Other screen functions 326 327=========================================================================== 328*/ 329 330/* 331 * QuartzCursorQueryBestSize 332 * Handle queries for best cursor size 333 */ 334static void 335QuartzCursorQueryBestSize(int class, unsigned short *width, 336 unsigned short *height, ScreenPtr pScreen) 337{ 338 QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); 339 340 if (class == CursorShape) 341 { 342 /* FIXME: query window server? */ 343 *width = 32; 344 *height = 32; 345 } 346 else 347 { 348 (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); 349 } 350} 351 352/* 353 * QuartzInitCursor 354 * Initialize cursor support 355 */ 356Bool 357QuartzInitCursor(ScreenPtr pScreen) 358{ 359 QuartzCursorScreenPtr ScreenPriv; 360 miPointerScreenPtr PointPriv; 361 362 /* initialize software cursor handling (always needed as backup) */ 363 if (!miDCInitialize(pScreen, &quartzScreenFuncsRec)) 364 return FALSE; 365 366 if (!dixRegisterPrivateKey(&darwinCursorScreenKeyRec, PRIVATE_SCREEN, 0)) 367 return FALSE; 368 369 ScreenPriv = calloc(1, sizeof(QuartzCursorScreenRec)); 370 if (ScreenPriv == NULL) 371 return FALSE; 372 373 /* CURSOR_PRIV(pScreen) = ScreenPriv; */ 374 dixSetPrivate(&pScreen->devPrivates, darwinCursorScreenKey, ScreenPriv); 375 376 /* override some screen procedures */ 377 ScreenPriv->QueryBestSize = pScreen->QueryBestSize; 378 pScreen->QueryBestSize = QuartzCursorQueryBestSize; 379 380 PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 381 382 ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; 383 384 PointPriv->spriteFuncs->RealizeCursor = QuartzRealizeCursor; 385 PointPriv->spriteFuncs->UnrealizeCursor = QuartzUnrealizeCursor; 386 PointPriv->spriteFuncs->SetCursor = QuartzSetCursor; 387 PointPriv->spriteFuncs->MoveCursor = QuartzMoveCursor; 388 389 ScreenPriv->cursorVisible = TRUE; 390 return TRUE; 391} 392 393/* 394 * QuartzSuspendXCursor 395 * X server is hiding. Restore the Aqua cursor. 396 */ 397void 398QuartzSuspendXCursor(ScreenPtr pScreen) 399{ 400} 401 402 403/* 404 * QuartzResumeXCursor 405 * X server is showing. Restore the X cursor. 406 */ 407void 408QuartzResumeXCursor(ScreenPtr pScreen) 409{ 410 WindowPtr pWin; 411 CursorPtr pCursor; 412 413 /* TODO: Tablet? */ 414 415 pWin = GetSpriteWindow(darwinPointer); 416 if (pWin->drawable.pScreen != pScreen) 417 return; 418 419 pCursor = GetSpriteCursor(darwinPointer); 420 if (pCursor == NULL) 421 return; 422 423 QuartzSetCursor(darwinPointer, pScreen, pCursor, /* x */ 0, /* y */ 0); 424} 425