xf86Cursors.c revision 4202a189
1/* 2 * Copyright © 2007 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_XORG_CONFIG_H 24#include <xorg-config.h> 25#else 26#ifdef HAVE_CONFIG_H 27#include <config.h> 28#endif 29#endif 30 31#include <stddef.h> 32#include <string.h> 33#include <stdio.h> 34 35#include "xf86.h" 36#include "xf86DDC.h" 37#include "xf86Crtc.h" 38#include "xf86Modes.h" 39#include "xf86RandR12.h" 40#include "xf86CursorPriv.h" 41#include "X11/extensions/render.h" 42#include "X11/extensions/dpmsconst.h" 43#include "X11/Xatom.h" 44#include "picturestr.h" 45#include "cursorstr.h" 46#include "inputstr.h" 47 48/* 49 * Given a screen coordinate, rotate back to a cursor source coordinate 50 */ 51static void 52xf86_crtc_rotate_coord (Rotation rotation, 53 int width, 54 int height, 55 int x_dst, 56 int y_dst, 57 int *x_src, 58 int *y_src) 59{ 60 int t; 61 62 switch (rotation & 0xf) { 63 case RR_Rotate_0: 64 break; 65 case RR_Rotate_90: 66 t = x_dst; 67 x_dst = height - y_dst - 1; 68 y_dst = t; 69 break; 70 case RR_Rotate_180: 71 x_dst = width - x_dst - 1; 72 y_dst = height - y_dst - 1; 73 break; 74 case RR_Rotate_270: 75 t = x_dst; 76 x_dst = y_dst; 77 y_dst = width - t - 1; 78 break; 79 } 80 if (rotation & RR_Reflect_X) 81 x_dst = width - x_dst - 1; 82 if (rotation & RR_Reflect_Y) 83 y_dst = height - y_dst - 1; 84 *x_src = x_dst; 85 *y_src = y_dst; 86} 87 88/* 89 * Given a cursor source coordinate, rotate to a screen coordinate 90 */ 91static void 92xf86_crtc_rotate_coord_back (Rotation rotation, 93 int width, 94 int height, 95 int x_dst, 96 int y_dst, 97 int *x_src, 98 int *y_src) 99{ 100 int t; 101 102 if (rotation & RR_Reflect_X) 103 x_dst = width - x_dst - 1; 104 if (rotation & RR_Reflect_Y) 105 y_dst = height - y_dst - 1; 106 107 switch (rotation & 0xf) { 108 case RR_Rotate_0: 109 break; 110 case RR_Rotate_90: 111 t = x_dst; 112 x_dst = y_dst; 113 y_dst = width - t - 1; 114 break; 115 case RR_Rotate_180: 116 x_dst = width - x_dst - 1; 117 y_dst = height - y_dst - 1; 118 break; 119 case RR_Rotate_270: 120 t = x_dst; 121 x_dst = height - y_dst - 1; 122 y_dst = t; 123 break; 124 } 125 *x_src = x_dst; 126 *y_src = y_dst; 127} 128 129/* 130 * Convert an x coordinate to a position within the cursor bitmap 131 */ 132static int 133cursor_bitpos (int flags, int x, Bool mask) 134{ 135 if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) 136 mask = !mask; 137 if (flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) 138 x = (x & ~3) | (3 - (x & 3)); 139 if (((flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) == 0) == 140 (X_BYTE_ORDER == X_BIG_ENDIAN)) 141 x = (x & ~7) | (7 - (x & 7)); 142 if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1) 143 x = (x << 1) + mask; 144 else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8) 145 x = ((x & ~7) << 1) | (mask << 3) | (x & 7); 146 else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16) 147 x = ((x & ~15) << 1) | (mask << 4) | (x & 15); 148 else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32) 149 x = ((x & ~31) << 1) | (mask << 5) | (x & 31); 150 else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64) 151 x = ((x & ~63) << 1) | (mask << 6) | (x & 63); 152 return x; 153} 154 155/* 156 * Fetch one bit from a cursor bitmap 157 */ 158static CARD8 159get_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask) 160{ 161 x = cursor_bitpos (flags, x, mask); 162 image += y * stride; 163 return (image[(x >> 3)] >> (x & 7)) & 1; 164} 165 166/* 167 * Set one bit in a cursor bitmap 168 */ 169static void 170set_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask) 171{ 172 x = cursor_bitpos (flags, x, mask); 173 image += y * stride; 174 image[(x >> 3)] |= 1 << (x & 7); 175} 176 177/* 178 * Load a two color cursor into a driver that supports only ARGB cursors 179 */ 180static void 181xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src) 182{ 183 ScrnInfoPtr scrn = crtc->scrn; 184 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 185 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; 186 CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image; 187 int x, y; 188 int xin, yin; 189 int stride = cursor_info->MaxWidth >> 2; 190 int flags = cursor_info->Flags; 191 CARD32 bits; 192 193#ifdef ARGB_CURSOR 194 crtc->cursor_argb = FALSE; 195#endif 196 197 for (y = 0; y < cursor_info->MaxHeight; y++) 198 for (x = 0; x < cursor_info->MaxWidth; x++) 199 { 200 xf86_crtc_rotate_coord (crtc->rotation, 201 cursor_info->MaxWidth, 202 cursor_info->MaxHeight, 203 x, y, &xin, &yin); 204 if (get_bit (src, stride, flags, xin, yin, TRUE) == 205 ((flags & HARDWARE_CURSOR_INVERT_MASK) == 0)) 206 { 207 if (get_bit (src, stride, flags, xin, yin, FALSE)) 208 bits = xf86_config->cursor_fg; 209 else 210 bits = xf86_config->cursor_bg; 211 } 212 else 213 bits = 0; 214 cursor_image[y * cursor_info->MaxWidth + x] = bits; 215 } 216 crtc->funcs->load_cursor_argb (crtc, cursor_image); 217} 218 219/* 220 * Set the colors for a two-color cursor (ignore for ARGB cursors) 221 */ 222static void 223xf86_set_cursor_colors (ScrnInfoPtr scrn, int bg, int fg) 224{ 225 ScreenPtr screen = scrn->pScreen; 226 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 227 CursorPtr cursor = xf86_config->cursor; 228 int c; 229 CARD8 *bits = cursor ? 230#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) 231 dixLookupPrivate(&cursor->devPrivates, CursorScreenKey(screen)) 232#else 233 cursor->devPriv[screen->myNum] 234#endif 235 : NULL; 236 237 /* Save ARGB versions of these colors */ 238 xf86_config->cursor_fg = (CARD32) fg | 0xff000000; 239 xf86_config->cursor_bg = (CARD32) bg | 0xff000000; 240 241 for (c = 0; c < xf86_config->num_crtc; c++) 242 { 243 xf86CrtcPtr crtc = xf86_config->crtc[c]; 244 245 if (crtc->enabled && !crtc->cursor_argb) 246 { 247 if (crtc->funcs->load_cursor_image) 248 crtc->funcs->set_cursor_colors (crtc, bg, fg); 249 else if (bits) 250 xf86_crtc_convert_cursor_to_argb (crtc, bits); 251 } 252 } 253} 254 255static void 256xf86_crtc_hide_cursor (xf86CrtcPtr crtc) 257{ 258 if (crtc->cursor_shown) 259 { 260 crtc->funcs->hide_cursor (crtc); 261 crtc->cursor_shown = FALSE; 262 } 263} 264 265void 266xf86_hide_cursors (ScrnInfoPtr scrn) 267{ 268 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 269 int c; 270 271 xf86_config->cursor_on = FALSE; 272 for (c = 0; c < xf86_config->num_crtc; c++) 273 { 274 xf86CrtcPtr crtc = xf86_config->crtc[c]; 275 276 if (crtc->enabled) 277 xf86_crtc_hide_cursor (crtc); 278 } 279} 280 281static void 282xf86_crtc_show_cursor (xf86CrtcPtr crtc) 283{ 284 if (!crtc->cursor_shown && crtc->cursor_in_range) 285 { 286 crtc->funcs->show_cursor (crtc); 287 crtc->cursor_shown = TRUE; 288 } 289} 290 291void 292xf86_show_cursors (ScrnInfoPtr scrn) 293{ 294 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 295 int c; 296 297 xf86_config->cursor_on = TRUE; 298 for (c = 0; c < xf86_config->num_crtc; c++) 299 { 300 xf86CrtcPtr crtc = xf86_config->crtc[c]; 301 302 if (crtc->enabled) 303 xf86_crtc_show_cursor (crtc); 304 } 305} 306 307static void 308xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 309{ 310 ScrnInfoPtr scrn = crtc->scrn; 311 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 312 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; 313 DisplayModePtr mode = &crtc->mode; 314 Bool in_range; 315 int dx, dy; 316 317 /* 318 * Transform position of cursor on screen 319 */ 320 if (crtc->transform_in_use) 321 { 322 ScreenPtr screen = scrn->pScreen; 323 xf86CursorScreenPtr ScreenPriv = 324 (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates, 325 xf86CursorScreenKey); 326 struct pict_f_vector v; 327 328 v.v[0] = (x + ScreenPriv->HotX) + 0.5; 329 v.v[1] = (y + ScreenPriv->HotY) + 0.5; 330 v.v[2] = 1; 331 pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v); 332 /* cursor will have 0.5 added to it already so floor is sufficent */ 333 x = floor (v.v[0]); 334 y = floor (v.v[1]); 335 /* 336 * Transform position of cursor upper left corner 337 */ 338 xf86_crtc_rotate_coord_back (crtc->rotation, 339 cursor_info->MaxWidth, 340 cursor_info->MaxHeight, 341 ScreenPriv->HotX, ScreenPriv->HotY, &dx, &dy); 342 x -= dx; 343 y -= dy; 344 } 345 else 346 { 347 x -= crtc->x; 348 y -= crtc->y; 349 } 350 351 /* 352 * Disable the cursor when it is outside the viewport 353 */ 354 in_range = TRUE; 355 if (x >= mode->HDisplay || y >= mode->VDisplay || 356 x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight) 357 { 358 in_range = FALSE; 359 x = 0; 360 y = 0; 361 } 362 363 crtc->cursor_in_range = in_range; 364 365 if (in_range) 366 { 367 crtc->funcs->set_cursor_position (crtc, x, y); 368 xf86_crtc_show_cursor (crtc); 369 } 370 else 371 xf86_crtc_hide_cursor (crtc); 372} 373 374static void 375xf86_set_cursor_position (ScrnInfoPtr scrn, int x, int y) 376{ 377 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 378 int c; 379 380 /* undo what xf86HWCurs did to the coordinates */ 381 x += scrn->frameX0; 382 y += scrn->frameY0; 383 for (c = 0; c < xf86_config->num_crtc; c++) 384 { 385 xf86CrtcPtr crtc = xf86_config->crtc[c]; 386 387 if (crtc->enabled) 388 xf86_crtc_set_cursor_position (crtc, x, y); 389 } 390} 391 392/* 393 * Load a two-color cursor into a crtc, performing rotation as needed 394 */ 395static void 396xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src) 397{ 398 ScrnInfoPtr scrn = crtc->scrn; 399 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 400 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; 401 CARD8 *cursor_image; 402 403#ifdef ARGB_CURSOR 404 crtc->cursor_argb = FALSE; 405#endif 406 407 if (crtc->rotation == RR_Rotate_0) 408 cursor_image = src; 409 else 410 { 411 int x, y; 412 int xin, yin; 413 int stride = cursor_info->MaxWidth >> 2; 414 int flags = cursor_info->Flags; 415 416 cursor_image = xf86_config->cursor_image; 417 memset(cursor_image, 0, cursor_info->MaxHeight * stride); 418 419 for (y = 0; y < cursor_info->MaxHeight; y++) 420 for (x = 0; x < cursor_info->MaxWidth; x++) 421 { 422 xf86_crtc_rotate_coord (crtc->rotation, 423 cursor_info->MaxWidth, 424 cursor_info->MaxHeight, 425 x, y, &xin, &yin); 426 if (get_bit(src, stride, flags, xin, yin, FALSE)) 427 set_bit(cursor_image, stride, flags, x, y, FALSE); 428 if (get_bit(src, stride, flags, xin, yin, TRUE)) 429 set_bit(cursor_image, stride, flags, x, y, TRUE); 430 } 431 } 432 crtc->funcs->load_cursor_image (crtc, cursor_image); 433} 434 435/* 436 * Load a cursor image into all active CRTCs 437 */ 438static void 439xf86_load_cursor_image (ScrnInfoPtr scrn, unsigned char *src) 440{ 441 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 442 int c; 443 444 for (c = 0; c < xf86_config->num_crtc; c++) 445 { 446 xf86CrtcPtr crtc = xf86_config->crtc[c]; 447 448 if (crtc->enabled) 449 { 450 if (crtc->funcs->load_cursor_image) 451 xf86_crtc_load_cursor_image (crtc, src); 452 else if (crtc->funcs->load_cursor_argb) 453 xf86_crtc_convert_cursor_to_argb (crtc, src); 454 } 455 } 456} 457 458static Bool 459xf86_use_hw_cursor (ScreenPtr screen, CursorPtr cursor) 460{ 461 ScrnInfoPtr scrn = xf86Screens[screen->myNum]; 462 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 463 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; 464 465 ++cursor->refcnt; 466 if (xf86_config->cursor) 467 FreeCursor (xf86_config->cursor, None); 468 xf86_config->cursor = cursor; 469 470 if (cursor->bits->width > cursor_info->MaxWidth || 471 cursor->bits->height> cursor_info->MaxHeight) 472 return FALSE; 473 474 return TRUE; 475} 476 477static Bool 478xf86_use_hw_cursor_argb (ScreenPtr screen, CursorPtr cursor) 479{ 480 ScrnInfoPtr scrn = xf86Screens[screen->myNum]; 481 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 482 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; 483 484 ++cursor->refcnt; 485 if (xf86_config->cursor) 486 FreeCursor (xf86_config->cursor, None); 487 xf86_config->cursor = cursor; 488 489 /* Make sure ARGB support is available */ 490 if ((cursor_info->Flags & HARDWARE_CURSOR_ARGB) == 0) 491 return FALSE; 492 493 if (cursor->bits->width > cursor_info->MaxWidth || 494 cursor->bits->height> cursor_info->MaxHeight) 495 return FALSE; 496 497 return TRUE; 498} 499 500static void 501xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc, CursorPtr cursor) 502{ 503 ScrnInfoPtr scrn = crtc->scrn; 504 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 505 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; 506 CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image; 507 CARD32 *cursor_source = (CARD32 *) cursor->bits->argb; 508 int x, y; 509 int xin, yin; 510 CARD32 bits; 511 int source_width = cursor->bits->width; 512 int source_height = cursor->bits->height; 513 int image_width = cursor_info->MaxWidth; 514 int image_height = cursor_info->MaxHeight; 515 516 for (y = 0; y < image_height; y++) 517 for (x = 0; x < image_width; x++) 518 { 519 xf86_crtc_rotate_coord (crtc->rotation, image_width, image_height, 520 x, y, &xin, &yin); 521 if (xin < source_width && yin < source_height) 522 bits = cursor_source[yin * source_width + xin]; 523 else 524 bits = 0; 525 cursor_image[y * image_width + x] = bits; 526 } 527 528 crtc->funcs->load_cursor_argb (crtc, cursor_image); 529} 530 531static void 532xf86_load_cursor_argb (ScrnInfoPtr scrn, CursorPtr cursor) 533{ 534 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 535 int c; 536 537 for (c = 0; c < xf86_config->num_crtc; c++) 538 { 539 xf86CrtcPtr crtc = xf86_config->crtc[c]; 540 541 if (crtc->enabled) 542 xf86_crtc_load_cursor_argb (crtc, cursor); 543 } 544} 545 546Bool 547xf86_cursors_init (ScreenPtr screen, int max_width, int max_height, int flags) 548{ 549 ScrnInfoPtr scrn = xf86Screens[screen->myNum]; 550 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 551 xf86CursorInfoPtr cursor_info; 552 553 cursor_info = xf86CreateCursorInfoRec(); 554 if (!cursor_info) 555 return FALSE; 556 557 xf86_config->cursor_image = malloc(max_width * max_height * 4); 558 559 if (!xf86_config->cursor_image) 560 { 561 xf86DestroyCursorInfoRec (cursor_info); 562 return FALSE; 563 } 564 565 xf86_config->cursor_info = cursor_info; 566 567 cursor_info->MaxWidth = max_width; 568 cursor_info->MaxHeight = max_height; 569 cursor_info->Flags = flags; 570 571 cursor_info->SetCursorColors = xf86_set_cursor_colors; 572 cursor_info->SetCursorPosition = xf86_set_cursor_position; 573 cursor_info->LoadCursorImage = xf86_load_cursor_image; 574 cursor_info->HideCursor = xf86_hide_cursors; 575 cursor_info->ShowCursor = xf86_show_cursors; 576 cursor_info->UseHWCursor = xf86_use_hw_cursor; 577#ifdef ARGB_CURSOR 578 if (flags & HARDWARE_CURSOR_ARGB) 579 { 580 cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb; 581 cursor_info->LoadCursorARGB = xf86_load_cursor_argb; 582 } 583#endif 584 585 xf86_config->cursor = NULL; 586 xf86_hide_cursors (scrn); 587 588 return xf86InitCursor (screen, cursor_info); 589} 590 591/** 592 * Called when anything on the screen is reconfigured. 593 * 594 * Reloads cursor images as needed, then adjusts cursor positions 595 */ 596 597void 598xf86_reload_cursors (ScreenPtr screen) 599{ 600 ScrnInfoPtr scrn; 601 xf86CrtcConfigPtr xf86_config; 602 xf86CursorInfoPtr cursor_info; 603 CursorPtr cursor; 604 int x, y; 605 xf86CursorScreenPtr cursor_screen_priv; 606 607 /* initial mode setting will not have set a screen yet. 608 May be called before the devices are initialised. 609 */ 610 if (!screen || !inputInfo.pointer) 611 return; 612 cursor_screen_priv = dixLookupPrivate(&screen->devPrivates, 613 xf86CursorScreenKey); 614 /* return if HW cursor is inactive, to avoid displaying two cursors */ 615 if (!cursor_screen_priv || !cursor_screen_priv->isUp) 616 return; 617 618 scrn = xf86Screens[screen->myNum]; 619 xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 620 621 /* make sure the cursor code has been initialized */ 622 cursor_info = xf86_config->cursor_info; 623 if (!cursor_info) 624 return; 625 626 cursor = xf86_config->cursor; 627 GetSpritePosition (inputInfo.pointer, &x, &y); 628 if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) 629 (*cursor_info->HideCursor)(scrn); 630 631 if (cursor) 632 { 633#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) 634 void *src = dixLookupPrivate(&cursor->devPrivates, CursorScreenKey(screen)); 635#else 636 void *src = cursor->devPriv[screen->myNum]; 637#endif 638#ifdef ARGB_CURSOR 639 if (cursor->bits->argb && cursor_info->LoadCursorARGB) 640 (*cursor_info->LoadCursorARGB) (scrn, cursor); 641 else if (src) 642#endif 643 (*cursor_info->LoadCursorImage)(scrn, src); 644 645 x += scrn->frameX0 + cursor_screen_priv->HotX; 646 y += scrn->frameY0 + cursor_screen_priv->HotY; 647 (*cursor_info->SetCursorPosition)(scrn, x, y); 648 } 649} 650 651/** 652 * Clean up CRTC-based cursor code 653 */ 654void 655xf86_cursors_fini (ScreenPtr screen) 656{ 657 ScrnInfoPtr scrn = xf86Screens[screen->myNum]; 658 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 659 660 if (xf86_config->cursor_info) 661 { 662 xf86DestroyCursorInfoRec (xf86_config->cursor_info); 663 xf86_config->cursor_info = NULL; 664 } 665 free(xf86_config->cursor_image); 666 xf86_config->cursor_image = NULL; 667 if (xf86_config->cursor) 668 { 669 FreeCursor (xf86_config->cursor, None); 670 xf86_config->cursor = NULL; 671 } 672} 673