xprCursor.c (11016B)
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 "darwinEvents.h" 41 #include <Xplugin.h> 42 43 #include "mi.h" 44 #include "scrnintstr.h" 45 #include "cursorstr.h" 46 #include "mipointrst.h" 47 #include "windowstr.h" 48 #include "globals.h" 49 #include "servermd.h" 50 #include "dixevents.h" 51 #include "x-hash.h" 52 53 typedef struct { 54 int cursorVisible; 55 QueryBestSizeProcPtr QueryBestSize; 56 miPointerSpriteFuncPtr spriteFuncs; 57 } QuartzCursorScreenRec, *QuartzCursorScreenPtr; 58 59 static DevPrivateKeyRec darwinCursorScreenKeyRec; 60 #define darwinCursorScreenKey (&darwinCursorScreenKeyRec) 61 62 #define CURSOR_PRIV(pScreen) ((QuartzCursorScreenPtr) \ 63 dixLookupPrivate(&pScreen->devPrivates, \ 64 darwinCursorScreenKey)) 65 66 static Bool 67 load_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 if (src->bits->argb != NULL) { 89 #if BITMAP_BIT_ORDER == MSBFirst 90 rowbytes = src->bits->width * sizeof(CARD32); 91 data = (uint32_t *)src->bits->argb; 92 #else 93 const uint32_t *be_data = (uint32_t *)src->bits->argb; 94 unsigned i; 95 rowbytes = src->bits->width * sizeof(CARD32); 96 data = malloc(rowbytes * src->bits->height); 97 free_data = TRUE; 98 if (!data) { 99 FatalError("Failed to allocate memory in %s\n", __func__); 100 } 101 for (i = 0; i < (src->bits->width * src->bits->height); i++) 102 data[i] = ntohl(be_data[i]); 103 #endif 104 } 105 else 106 { 107 fg_color = 0xFF00 | (src->foreRed >> 8); 108 fg_color <<= 16; 109 fg_color |= src->foreGreen & 0xFF00; 110 fg_color |= src->foreBlue >> 8; 111 112 bg_color = 0xFF00 | (src->backRed >> 8); 113 bg_color <<= 16; 114 bg_color |= src->backGreen & 0xFF00; 115 bg_color |= src->backBlue >> 8; 116 117 fg_color = htonl(fg_color); 118 bg_color = htonl(bg_color); 119 120 /* round up to 8 pixel boundary so we can convert whole bytes */ 121 rowbytes = ((src->bits->width * 4) + 31) & ~31; 122 data = malloc(rowbytes * src->bits->height); 123 free_data = TRUE; 124 if (!data) { 125 FatalError("Failed to allocate memory in %s\n", __func__); 126 } 127 128 if (!src->bits->emptyMask) { 129 ycount = src->bits->height; 130 srow = src->bits->source; 131 mrow = src->bits->mask; 132 drow = data; 133 134 while (ycount-- > 0) 135 { 136 xcount = bits_to_bytes(src->bits->width); 137 sptr = srow; 138 mptr = mrow; 139 dptr = drow; 140 141 while (xcount-- > 0) 142 { 143 uint8_t s, m; 144 int i; 145 146 s = *sptr++; 147 m = *mptr++; 148 for (i = 0; i < 8; i++) { 149 #if BITMAP_BIT_ORDER == MSBFirst 150 if (m & 128) 151 *dptr++ = (s & 128) ? fg_color : bg_color; 152 else 153 *dptr++ = 0; 154 s <<= 1; 155 m <<= 1; 156 #else 157 if (m & 1) 158 *dptr++ = (s & 1) ? fg_color : bg_color; 159 else 160 *dptr++ = 0; 161 s >>= 1; 162 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 memset(data, 0, src->bits->height * rowbytes); 174 } 175 } 176 177 err = xp_set_cursor(width, height, hot_x, hot_y, data, rowbytes); 178 if (free_data) 179 free(data); 180 return err == Success; 181 } 182 183 /* 184 =========================================================================== 185 186 Pointer sprite functions 187 188 =========================================================================== 189 */ 190 191 /* 192 * QuartzRealizeCursor 193 * Convert the X cursor representation to native format if possible. 194 */ 195 static Bool 196 QuartzRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 197 { 198 if (pCursor == NULL || pCursor->bits == NULL) 199 return FALSE; 200 201 /* FIXME: cache ARGB8888 representation? */ 202 203 return TRUE; 204 } 205 206 /* 207 * QuartzUnrealizeCursor 208 * Free the storage space associated with a realized cursor. 209 */ 210 static Bool 211 QuartzUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 212 { 213 return TRUE; 214 } 215 216 /* 217 * QuartzSetCursor 218 * Set the cursor sprite and position. 219 */ 220 static void 221 QuartzSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, 222 int x, 223 int y) 224 { 225 QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); 226 227 if (!XQuartzServerVisible) 228 return; 229 230 if (pCursor == NULL) { 231 if (ScreenPriv->cursorVisible) { 232 xp_hide_cursor(); 233 ScreenPriv->cursorVisible = FALSE; 234 } 235 } 236 else { 237 load_cursor(pCursor, pScreen->myNum); 238 239 if (!ScreenPriv->cursorVisible) { 240 xp_show_cursor(); 241 ScreenPriv->cursorVisible = TRUE; 242 } 243 } 244 } 245 246 /* 247 * QuartzMoveCursor 248 * Move the cursor. This is a noop for us. 249 */ 250 static void 251 QuartzMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 252 {} 253 254 /* 255 =========================================================================== 256 257 Pointer screen functions 258 259 =========================================================================== 260 */ 261 262 /* 263 * QuartzCursorOffScreen 264 */ 265 static Bool 266 QuartzCursorOffScreen(ScreenPtr *pScreen, int *x, int *y) 267 { 268 return FALSE; 269 } 270 271 /* 272 * QuartzCrossScreen 273 */ 274 static void 275 QuartzCrossScreen(ScreenPtr pScreen, Bool entering) 276 { 277 return; 278 } 279 280 /* 281 * QuartzWarpCursor 282 * Change the cursor position without generating an event or motion history. 283 * The input coordinates (x,y) are in pScreen-local X11 coordinates. 284 * 285 */ 286 static void 287 QuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 288 { 289 if (XQuartzServerVisible) { 290 int sx, sy; 291 292 sx = pScreen->x + darwinMainScreenX; 293 sy = pScreen->y + darwinMainScreenY; 294 295 CGWarpMouseCursorPosition(CGPointMake(sx + x, sy + y)); 296 } 297 298 miPointerWarpCursor(pDev, pScreen, x, y); 299 miPointerUpdateSprite(pDev); 300 } 301 302 static miPointerScreenFuncRec quartzScreenFuncsRec = { 303 QuartzCursorOffScreen, 304 QuartzCrossScreen, 305 QuartzWarpCursor, 306 }; 307 308 /* 309 =========================================================================== 310 311 Other screen functions 312 313 =========================================================================== 314 */ 315 316 /* 317 * QuartzCursorQueryBestSize 318 * Handle queries for best cursor size 319 */ 320 static void 321 QuartzCursorQueryBestSize(int class, unsigned short *width, 322 unsigned short *height, ScreenPtr pScreen) 323 { 324 QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); 325 326 if (class == CursorShape) { 327 /* FIXME: query window server? */ 328 *width = 32; 329 *height = 32; 330 } 331 else { 332 (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); 333 } 334 } 335 336 /* 337 * QuartzInitCursor 338 * Initialize cursor support 339 */ 340 Bool 341 QuartzInitCursor(ScreenPtr pScreen) 342 { 343 QuartzCursorScreenPtr ScreenPriv; 344 miPointerScreenPtr PointPriv; 345 346 /* initialize software cursor handling (always needed as backup) */ 347 if (!miDCInitialize(pScreen, &quartzScreenFuncsRec)) 348 return FALSE; 349 350 if (!dixRegisterPrivateKey(&darwinCursorScreenKeyRec, PRIVATE_SCREEN, 0)) 351 return FALSE; 352 353 ScreenPriv = calloc(1, sizeof(QuartzCursorScreenRec)); 354 if (ScreenPriv == NULL) 355 return FALSE; 356 357 /* CURSOR_PRIV(pScreen) = ScreenPriv; */ 358 dixSetPrivate(&pScreen->devPrivates, darwinCursorScreenKey, ScreenPriv); 359 360 /* override some screen procedures */ 361 ScreenPriv->QueryBestSize = pScreen->QueryBestSize; 362 pScreen->QueryBestSize = QuartzCursorQueryBestSize; 363 364 PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 365 366 ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; 367 368 PointPriv->spriteFuncs->RealizeCursor = QuartzRealizeCursor; 369 PointPriv->spriteFuncs->UnrealizeCursor = QuartzUnrealizeCursor; 370 PointPriv->spriteFuncs->SetCursor = QuartzSetCursor; 371 PointPriv->spriteFuncs->MoveCursor = QuartzMoveCursor; 372 373 ScreenPriv->cursorVisible = TRUE; 374 return TRUE; 375 } 376 377 /* 378 * QuartzSuspendXCursor 379 * X server is hiding. Restore the Aqua cursor. 380 */ 381 void 382 QuartzSuspendXCursor(ScreenPtr pScreen) 383 { 384 xp_show_cursor(); 385 } 386 387 /* 388 * QuartzResumeXCursor 389 * X server is showing. Restore the X cursor. 390 */ 391 void 392 QuartzResumeXCursor(ScreenPtr pScreen) 393 { 394 WindowPtr pWin; 395 CursorPtr pCursor; 396 397 /* TODO: Tablet? */ 398 399 pWin = GetSpriteWindow(darwinPointer); 400 if (pWin->drawable.pScreen != pScreen) 401 return; 402 403 pCursor = GetSpriteCursor(darwinPointer); 404 if (pCursor == NULL) 405 return; 406 407 QuartzSetCursor(darwinPointer, pScreen, pCursor, /* x */ 0, /* y */ 0); 408 }