fix for bug 5486 Patch makes it possible to load and display 32bit rgba cursor. I have made tested the code with Football Manager 2006. The ealier version of patch was confimed loading 32bit cursors from Guild Wars.
I would like to hear comments how to improve the code. Is there chance that this could be included to wine? (without huge modifications) The code is a hack and not perfect solution. But hack is better than invisible cursor.
Index: dlls/winex11.drv/mouse.c =================================================================== RCS file: /home/wine/wine/dlls/winex11.drv/mouse.c,v retrieving revision 1.1 diff -u -p -t -r1.1 mouse.c --- dlls/winex11.drv/mouse.c 16 Jun 2006 13:19:17 -0000 1.1 +++ dlls/winex11.drv/mouse.c 24 Jun 2006 22:25:07 -0000 @@ -422,16 +422,19 @@ static Cursor create_cursor( Display *di } else { - int rbits, gbits, bbits, red, green, blue; + int rbits, gbits, bbits,abits, red, green, blue, alpha; int rfg, gfg, bfg, rbg, gbg, bbg; int rscale, gscale, bscale; int x, y, xmax, ymax, bitIndex, byteIndex, xorIndex; unsigned char *theMask, *theImage, theChar; int threshold, fgBits, bgBits, bitShifted; - BYTE pXorBits[128]; /* Up to 32x32 icons */ + BYTE pXorBits[128], pAndBits[128]; /* Up to 32x32 icons; could use same array but ... */ + int failure = 0; switch (ptr->bBitsPerPixel) { + case 32: + abits = 8; case 24: rbits = 8; gbits = 8; @@ -473,13 +476,16 @@ static Cursor create_cursor( Display *di ymax = (ptr->nHeight > 32) ? 32 : ptr->nHeight; memset(pXorBits, 0, 128); + memset(pAndBits, 0, 128); for (y=0; y<ymax; y++) { for (x=0; x<xmax; x++) { red = green = blue = 0; + alpha = 255; // This is vissible? switch (ptr->bBitsPerPixel) { + case 32: case 24: theChar = theImage[byteIndex++]; blue = theChar; @@ -487,6 +493,11 @@ static Cursor create_cursor( Display *di green = theChar; theChar = theImage[byteIndex++]; red = theChar; + if (ptr->bBitsPerPixel == 32) + { + theChar = theImage[byteIndex++]; + alpha = theChar; + } break; case 16: theChar = theImage[byteIndex++]; @@ -498,8 +509,19 @@ static Cursor create_cursor( Display *di break; } - if (red+green+blue > threshold) + + //bg or fg? + // If there is alpha for fg color then we should calculate avarange + // alpha and use that to create transperancy for cursor (at least my gnome + // has transperancy with xorg 7) + if (alpha < threshold>>3) + { + // Transperant + pAndBits[xorIndex] |= bitShifted; + } + else if (red+green+blue > threshold) { + // Foreground rfg += red; gfg += green; bfg += blue; @@ -508,10 +530,18 @@ static Cursor create_cursor( Display *di } else { + // Background rbg += red; gbg += green; bbg += blue; } +/* // What is going on? + TRACE("Cursor file pixel, red=%d green=%d blue=%d alpha=%d Xor=%d\n", + red, + green, + blue, + alpha, + pXorBits[xorIndex]&bitShifted);*/ if (x%8 == 7) { bitShifted = 0x01; @@ -540,7 +570,19 @@ static Cursor create_cursor( Display *di } else bg.red = bg.green = bg.blue = 0; pixmapBits = XCreateBitmapFromData( display, root_window, (char *)pXorBits, xmax, ymax ); - if (!pixmapBits) + if (ptr->bBitsPerPixel == 32) + { + pixmapMask = XCreateBitmapFromData( display, root_window, (char *)pAndBits, xmax, ymax ); + + if (!pixmapMask) + { + XFreePixmap( display, pixmapAll ); + failure = 1; + } + + } + if (!pixmapBits + && failure) { XFreePixmap( display, pixmapAll ); XFreeGC( display, gc ); @@ -556,6 +598,12 @@ static Cursor create_cursor( Display *di /* Put the image */ XCopyArea( display, pixmapBits, pixmapAll, gc, 0, 0, xmax, ymax, 0, ptr->nHeight ); + if (ptr->bBitsPerPixel == 32) + { + XCopyArea( display, pixmapMask, pixmapAll, gc, + 0, 0, xmax, ymax, 0, 0); + XFreePixmap( display, pixmapMask ); + } XFreePixmap( display, pixmapBits ); } image->data = NULL;