~ubuntu-branches/ubuntu/saucy/wine1.2/saucy

« back to all changes in this revision

Viewing changes to dlls/winex11.drv/mouse.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Ritchie
  • Date: 2010-12-06 00:21:37 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20101206002137-ywazcomhqf97iw3c
Tags: 1.2.2-0ubuntu1
* New upstream release (LP: #685474)
  - Support for animated cursors. 
  - Translation updates.
  - Various bug fixes. (LP: #665270)
* Add Japanese font aliases to workaround lack of fontconfig substitution
* Recommend requisite umefont as a default (same as Crossover)
* Conflict with "wine" << 1.2.1 to prevent upgrade failures from very old
  ppa packages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
MAKE_FUNCPTR(XcursorImageCreate);
33
33
MAKE_FUNCPTR(XcursorImageDestroy);
34
34
MAKE_FUNCPTR(XcursorImageLoadCursor);
 
35
MAKE_FUNCPTR(XcursorImagesCreate);
 
36
MAKE_FUNCPTR(XcursorImagesDestroy);
 
37
MAKE_FUNCPTR(XcursorImagesLoadCursor);
35
38
# undef MAKE_FUNCPTR
36
39
#endif /* SONAME_LIBXCURSOR */
37
40
 
114
117
    LOAD_FUNCPTR(XcursorImageCreate);
115
118
    LOAD_FUNCPTR(XcursorImageDestroy);
116
119
    LOAD_FUNCPTR(XcursorImageLoadCursor);
 
120
    LOAD_FUNCPTR(XcursorImagesCreate);
 
121
    LOAD_FUNCPTR(XcursorImagesDestroy);
 
122
    LOAD_FUNCPTR(XcursorImagesLoadCursor);
117
123
#undef LOAD_FUNCPTR
118
124
#endif /* SONAME_LIBXCURSOR */
119
125
}
468
474
#ifdef SONAME_LIBXCURSOR
469
475
 
470
476
/***********************************************************************
471
 
 *              create_xcursor_cursor
 
477
 *              create_xcursor_frame
472
478
 *
473
 
 * Use Xcursor to create an X cursor from a Windows one.
 
479
 * Use Xcursor to create a frame of an X cursor from a Windows one.
474
480
 */
475
 
static Cursor create_xcursor_cursor( HDC hdc, ICONINFO *icon, int width, int height )
 
481
static XcursorImage *create_xcursor_frame( HDC hdc, ICONINFO *iinfo, HANDLE icon,
 
482
                                           HBITMAP hbmColor, unsigned char *color_bits, int color_size,
 
483
                                           HBITMAP hbmMask, unsigned char *mask_bits, int mask_size,
 
484
                                           int width, int height, int istep )
476
485
{
 
486
    XcursorImage *image, *ret = NULL;
477
487
    int x, y, i, has_alpha;
478
 
    BITMAPINFO *info;
479
 
    Cursor cursor;
480
 
    XcursorImage *image;
481
488
    XcursorPixel *ptr;
482
489
 
483
 
    if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) return 0;
484
 
 
485
490
    wine_tsx11_lock();
486
491
    image = pXcursorImageCreate( width, height );
487
492
    wine_tsx11_unlock();
488
493
    if (!image)
489
494
    {
490
 
        HeapFree( GetProcessHeap(), 0, info );
491
 
        return 0;
492
 
    }
493
 
 
494
 
    image->xhot = icon->xHotspot;
495
 
    image->yhot = icon->yHotspot;
496
 
    image->delay = 0;
497
 
 
498
 
    info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
499
 
    info->bmiHeader.biWidth = width;
500
 
    info->bmiHeader.biHeight = -height;
501
 
    info->bmiHeader.biPlanes = 1;
502
 
    info->bmiHeader.biBitCount = 32;
503
 
    info->bmiHeader.biCompression = BI_RGB;
504
 
    info->bmiHeader.biSizeImage = width * height * 4;
505
 
    info->bmiHeader.biXPelsPerMeter = 0;
506
 
    info->bmiHeader.biYPelsPerMeter = 0;
507
 
    info->bmiHeader.biClrUsed = 0;
508
 
    info->bmiHeader.biClrImportant = 0;
509
 
    GetDIBits( hdc, icon->hbmColor, 0, height, image->pixels, info, DIB_RGB_COLORS );
510
 
 
 
495
        ERR("X11 failed to produce a cursor frame!\n");
 
496
        goto cleanup;
 
497
    }
 
498
 
 
499
    image->xhot = iinfo->xHotspot;
 
500
    image->yhot = iinfo->yHotspot;
 
501
    image->delay = 100; /* TODO: find a way to get the proper delay */
 
502
 
 
503
    /* draw the cursor frame to a temporary buffer then copy it into the XcursorImage */
 
504
    memset( color_bits, 0x00, color_size );
 
505
    SelectObject( hdc, hbmColor );
 
506
    if (!DrawIconEx( hdc, 0, 0, icon, width, height, istep, NULL, DI_NORMAL ))
 
507
    {
 
508
        TRACE("Could not draw frame %d (walk past end of frames).\n", istep);
 
509
        goto cleanup;
 
510
    }
 
511
    memcpy( image->pixels, color_bits, color_size );
 
512
 
 
513
    /* check if the cursor frame was drawn with an alpha channel */
511
514
    for (i = 0, ptr = image->pixels; i < width * height; i++, ptr++)
512
515
        if ((has_alpha = (*ptr & 0xff000000) != 0)) break;
513
516
 
 
517
    /* if no alpha channel was drawn then generate it from the mask */
514
518
    if (!has_alpha)
515
519
    {
516
 
        unsigned char *mask_bits;
517
520
        unsigned int width_bytes = (width + 31) / 32 * 4;
518
521
 
519
 
        /* generate alpha channel from the mask */
520
 
        info->bmiHeader.biBitCount = 1;
521
 
        info->bmiHeader.biSizeImage = width_bytes * height;
522
 
        if ((mask_bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
 
522
        /* draw the cursor mask to a temporary buffer */
 
523
        memset( mask_bits, 0xFF, mask_size );
 
524
        SelectObject( hdc, hbmMask );
 
525
        if (!DrawIconEx( hdc, 0, 0, icon, width, height, istep, NULL, DI_MASK ))
523
526
        {
524
 
            GetDIBits( hdc, icon->hbmMask, 0, height, mask_bits, info, DIB_RGB_COLORS );
525
 
            for (y = 0, ptr = image->pixels; y < height; y++)
526
 
                for (x = 0; x < width; x++, ptr++)
527
 
                    if (!((mask_bits[y * width_bytes + x / 8] << (x % 8)) & 0x80))
528
 
                        *ptr |= 0xff000000;
529
 
            HeapFree( GetProcessHeap(), 0, mask_bits );
 
527
            ERR("Failed to draw frame mask %d.\n", istep);
 
528
            goto cleanup;
530
529
        }
531
 
    }
532
 
    HeapFree( GetProcessHeap(), 0, info );
533
 
 
 
530
        /* use the buffer to directly modify the XcursorImage alpha channel */
 
531
        for (y = 0, ptr = image->pixels; y < height; y++)
 
532
            for (x = 0; x < width; x++, ptr++)
 
533
                if (!((mask_bits[y * width_bytes + x / 8] << (x % 8)) & 0x80))
 
534
                    *ptr |= 0xff000000;
 
535
    }
 
536
    ret = image;
 
537
 
 
538
cleanup:
 
539
    if (ret == NULL) pXcursorImageDestroy( image );
 
540
    return ret;
 
541
}
 
542
 
 
543
/***********************************************************************
 
544
 *              create_xcursor_cursor
 
545
 *
 
546
 * Use Xcursor to create an X cursor from a Windows one.
 
547
 */
 
548
static Cursor create_xcursor_cursor( HDC hdc, ICONINFO *iinfo, HANDLE icon, int width, int height )
 
549
{
 
550
    unsigned char *color_bits, *mask_bits;
 
551
    HBITMAP hbmColor = 0, hbmMask = 0;
 
552
    XcursorImage **imgs, *image;
 
553
    int color_size, mask_size;
 
554
    BITMAPINFO *info = NULL;
 
555
    XcursorImages *images;
 
556
    Cursor cursor = 0;
 
557
    int nFrames = 0;
 
558
 
 
559
    if (!(imgs = HeapAlloc( GetProcessHeap(), 0, sizeof(XcursorImage*) ))) return 0;
 
560
 
 
561
    /* Allocate all of the resources necessary to obtain a cursor frame */
 
562
    if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto cleanup;
 
563
    info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 
564
    info->bmiHeader.biWidth = width;
 
565
    info->bmiHeader.biHeight = -height;
 
566
    info->bmiHeader.biPlanes = 1;
 
567
    info->bmiHeader.biCompression = BI_RGB;
 
568
    info->bmiHeader.biXPelsPerMeter = 0;
 
569
    info->bmiHeader.biYPelsPerMeter = 0;
 
570
    info->bmiHeader.biClrUsed = 0;
 
571
    info->bmiHeader.biClrImportant = 0;
 
572
    info->bmiHeader.biBitCount = 32;
 
573
    color_size = width * height * 4;
 
574
    info->bmiHeader.biSizeImage = color_size;
 
575
    hbmColor = CreateDIBSection( hdc, info, DIB_RGB_COLORS, (VOID **) &color_bits, NULL, 0);
 
576
    if (!hbmColor)
 
577
    {
 
578
        ERR("Failed to create DIB section for cursor color data!\n");
 
579
        goto cleanup;
 
580
    }
 
581
    info->bmiHeader.biBitCount = 1;
 
582
    mask_size = ((width + 31) / 32 * 4) * height; /* width_bytes * height */
 
583
    info->bmiHeader.biSizeImage = mask_size;
 
584
    hbmMask = CreateDIBSection( hdc, info, DIB_RGB_COLORS, (VOID **) &mask_bits, NULL, 0);
 
585
    if (!hbmMask)
 
586
    {
 
587
        ERR("Failed to create DIB section for cursor mask data!\n");
 
588
        goto cleanup;
 
589
    }
 
590
 
 
591
    /* Create an XcursorImage for each frame of the cursor */
 
592
    while (1)
 
593
    {
 
594
        XcursorImage **imgstmp;
 
595
 
 
596
        image = create_xcursor_frame( hdc, iinfo, icon,
 
597
                                      hbmColor, color_bits, color_size,
 
598
                                      hbmMask, mask_bits, mask_size,
 
599
                                      width, height, nFrames );
 
600
        if (!image) break; /* no more drawable frames */
 
601
 
 
602
        imgs[nFrames++] = image;
 
603
        if (!(imgstmp = HeapReAlloc( GetProcessHeap(), 0, imgs, (nFrames+1)*sizeof(XcursorImage*) ))) goto cleanup;
 
604
        imgs = imgstmp;
 
605
    }
 
606
 
 
607
    /* Build an X cursor out of all of the frames */
 
608
    if (!(images = pXcursorImagesCreate( nFrames ))) goto cleanup;
 
609
    for (images->nimage = 0; images->nimage < nFrames; images->nimage++)
 
610
        images->images[images->nimage] = imgs[images->nimage];
534
611
    wine_tsx11_lock();
535
 
    cursor = pXcursorImageLoadCursor( gdi_display, image );
536
 
    pXcursorImageDestroy( image );
 
612
    cursor = pXcursorImagesLoadCursor( gdi_display, images );
537
613
    wine_tsx11_unlock();
 
614
    pXcursorImagesDestroy( images ); /* Note: this frees each individual frame (calls XcursorImageDestroy) */
 
615
    HeapFree( GetProcessHeap(), 0, imgs );
 
616
    imgs = NULL;
 
617
 
 
618
cleanup:
 
619
    if (imgs)
 
620
    {
 
621
        /* Failed to produce a cursor, free previously allocated frames */
 
622
        for (nFrames--; nFrames >= 0; nFrames--)
 
623
            pXcursorImageDestroy( imgs[nFrames] );
 
624
        HeapFree( GetProcessHeap(), 0, imgs );
 
625
    }
 
626
    /* Cleanup all of the resources used to obtain the frame data */
 
627
    if (hbmColor) DeleteObject( hbmColor );
 
628
    if (hbmMask) DeleteObject( hbmMask );
 
629
    HeapFree( GetProcessHeap(), 0, info );
538
630
    return cursor;
539
631
}
540
632
 
772
864
    if (info.hbmColor)
773
865
    {
774
866
#ifdef SONAME_LIBXCURSOR
775
 
        if (pXcursorImageLoadCursor) cursor = create_xcursor_cursor( hdc, &info, bm.bmWidth, bm.bmHeight );
 
867
        if (pXcursorImagesLoadCursor) cursor = create_xcursor_cursor( hdc, &info, handle, bm.bmWidth, bm.bmHeight );
776
868
#endif
777
869
        if (!cursor) cursor = create_xlib_cursor( hdc, &info, bm.bmWidth, bm.bmHeight );
778
870
        DeleteObject( info.hbmColor );