|
|
@ -27,6 +27,9 @@
|
|
|
|
# ifdef HAVE_XRENDER
|
|
|
|
# ifdef HAVE_XRENDER
|
|
|
|
# include <X11/extensions/Xrender.h>
|
|
|
|
# include <X11/extensions/Xrender.h>
|
|
|
|
# endif // HAVE_XRENDER
|
|
|
|
# endif // HAVE_XRENDER
|
|
|
|
|
|
|
|
# ifdef HAVE_XCURSOR
|
|
|
|
|
|
|
|
# include <X11/Xcursor/Xcursor.h>
|
|
|
|
|
|
|
|
# endif // HAVE_XCURSOR
|
|
|
|
#endif // NL_OS_UNIX
|
|
|
|
#endif // NL_OS_UNIX
|
|
|
|
|
|
|
|
|
|
|
|
#include "nel/misc/mouse_device.h"
|
|
|
|
#include "nel/misc/mouse_device.h"
|
|
|
@ -118,7 +121,17 @@ bool CDriverGL::isAlphaBlendedCursorSupported()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#elif defined(NL_OS_MAC)
|
|
|
|
#elif defined(NL_OS_MAC)
|
|
|
|
#elif defined(NL_OS_UNIX)
|
|
|
|
#elif defined(NL_OS_UNIX)
|
|
|
|
_AlphaBlendedCursorSupported = _xrender_version > 0;
|
|
|
|
|
|
|
|
|
|
|
|
_AlphaBlendedCursorSupported = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_XCURSOR
|
|
|
|
|
|
|
|
if (!_AlphaBlendedCursorSupported && XcursorSupportsARGB(_dpy))
|
|
|
|
|
|
|
|
_AlphaBlendedCursorSupported = true;
|
|
|
|
|
|
|
|
#endif // HAVE_XCURSOR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!_AlphaBlendedCursorSupported && _xrender_version > 0)
|
|
|
|
|
|
|
|
_AlphaBlendedCursorSupported = true;
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
_AlphaBlendedCursorSupportRetrieved = true;
|
|
|
|
_AlphaBlendedCursorSupportRetrieved = true;
|
|
|
@ -807,8 +820,12 @@ bool CDriverGL::getBestCursorSize(uint srcWidth, uint srcHeight, uint &dstWidth,
|
|
|
|
#elif defined(NL_OS_MAC)
|
|
|
|
#elif defined(NL_OS_MAC)
|
|
|
|
#elif defined(NL_OS_UNIX)
|
|
|
|
#elif defined(NL_OS_UNIX)
|
|
|
|
|
|
|
|
|
|
|
|
Status res = XQueryBestCursor(_dpy, _win, srcWidth, srcHeight, &dstWidth, &dstHeight);
|
|
|
|
Status status = XQueryBestCursor(_dpy, _win, srcWidth, srcHeight, &dstWidth, &dstHeight);
|
|
|
|
nlwarning("XQueryBestCursor returned %d", (sint)res);
|
|
|
|
|
|
|
|
|
|
|
|
if (!status)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("XQueryBestCursor failed");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
@ -821,7 +838,7 @@ bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &c
|
|
|
|
|
|
|
|
|
|
|
|
return convertBitmapToIcon(bitmap, cursor, iconWidth, iconHeight, iconDepth, col, hotSpotX, hotSpotY, true);
|
|
|
|
return convertBitmapToIcon(bitmap, cursor, iconWidth, iconHeight, iconDepth, col, hotSpotX, hotSpotY, true);
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(NL_OS_UNIX) && defined(HAVE_XRENDER) && !defined(NL_OS_MAC)
|
|
|
|
#elif defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
|
|
|
|
|
|
|
|
|
|
|
|
CBitmap src = bitmap;
|
|
|
|
CBitmap src = bitmap;
|
|
|
|
|
|
|
|
|
|
|
@ -858,93 +875,132 @@ bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &c
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (srcColorPtr != srcColorPtrLast);
|
|
|
|
while (srcColorPtr != srcColorPtrLast);
|
|
|
|
|
|
|
|
|
|
|
|
// use malloc() because X will free() data itself
|
|
|
|
#ifdef HAVE_XCURSOR
|
|
|
|
CRGBA *src32 = (CRGBA*)malloc(colorBm.getSize()*4);
|
|
|
|
|
|
|
|
memcpy(src32, &colorBm.getPixels(0)[0], colorBm.getSize()*4);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint size = iconWidth * iconHeight;
|
|
|
|
if (XcursorSupportsARGB(_dpy))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
XcursorImage *image = XcursorImageCreate(iconWidth, iconHeight);
|
|
|
|
|
|
|
|
|
|
|
|
// Create the icon pixmap
|
|
|
|
if (!image)
|
|
|
|
sint screen = DefaultScreen(_dpy);
|
|
|
|
{
|
|
|
|
Visual *visual = DefaultVisual(_dpy, screen);
|
|
|
|
nlwarning("Failed to create a XcusorImage with size %ux%u", iconWidth, iconHeight);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
image->xhot = (uint)hotSpotX;
|
|
|
|
|
|
|
|
image->yhot = (uint)hotSpotY;
|
|
|
|
|
|
|
|
|
|
|
|
if (!visual)
|
|
|
|
memcpy(image->pixels, &colorBm.getPixels(0)[0], colorBm.getSize()*4);
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("Failed to get a default visual for screen %d", screen);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// create the icon pixmap
|
|
|
|
cursor = XcursorImageLoadCursor(_dpy, image);
|
|
|
|
XImage* image = XCreateImage(_dpy, visual, 32, ZPixmap, 0, (char*)src32, iconWidth, iconHeight, 32, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!image)
|
|
|
|
XcursorImageDestroy(image);
|
|
|
|
{
|
|
|
|
}
|
|
|
|
nlwarning("Failed to set the window's icon");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Pixmap pixmap = XCreatePixmap(_dpy, _win, iconWidth, iconHeight, 32 /* defDepth */);
|
|
|
|
#endif // HAVE_XCURSOR
|
|
|
|
|
|
|
|
|
|
|
|
if (!pixmap)
|
|
|
|
#ifdef HAVE_XRENDER
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (_xrender_version > 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
nlwarning("Failed to create a pixmap %ux%ux%d", iconWidth, iconHeight, 32);
|
|
|
|
// use malloc() because X will free() data itself
|
|
|
|
return false;
|
|
|
|
CRGBA *src32 = (CRGBA*)malloc(colorBm.getSize()*4);
|
|
|
|
}
|
|
|
|
memcpy(src32, &colorBm.getPixels(0)[0], colorBm.getSize()*4);
|
|
|
|
|
|
|
|
|
|
|
|
GC gc = XCreateGC(_dpy, pixmap, 0, NULL);
|
|
|
|
uint size = iconWidth * iconHeight;
|
|
|
|
|
|
|
|
|
|
|
|
if (!gc)
|
|
|
|
sint screen = DefaultScreen(_dpy);
|
|
|
|
{
|
|
|
|
Visual *visual = DefaultVisual(_dpy, screen);
|
|
|
|
nlwarning("Failed to create a GC");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sint res = XPutImage(_dpy, pixmap, gc, image, 0, 0, 0, 0, iconWidth, iconHeight);
|
|
|
|
if (!visual)
|
|
|
|
// should return 0
|
|
|
|
{
|
|
|
|
nlwarning("XPutImage returned %d", res);
|
|
|
|
nlwarning("Failed to get a default visual for screen %d", screen);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
res = XFreeGC(_dpy, gc);
|
|
|
|
// Create the icon image
|
|
|
|
// should return 1
|
|
|
|
XImage* image = XCreateImage(_dpy, visual, 32, ZPixmap, 0, (char*)src32, iconWidth, iconHeight, 32, 0);
|
|
|
|
nlwarning("XFreeGC returned %d", res);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (image->data)
|
|
|
|
if (!image)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
free(image->data);
|
|
|
|
nlwarning("Failed to set the window's icon");
|
|
|
|
image->data = NULL;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
XDestroyImage(image);
|
|
|
|
// Create the icon pixmap
|
|
|
|
|
|
|
|
Pixmap pixmap = XCreatePixmap(_dpy, _win, iconWidth, iconHeight, 32 /* defDepth */);
|
|
|
|
|
|
|
|
|
|
|
|
XRenderPictFormat *format = XRenderFindStandardFormat(_dpy, PictStandardARGB32);
|
|
|
|
if (!pixmap)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("Failed to create a pixmap %ux%ux%d", iconWidth, iconHeight, 32);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!format)
|
|
|
|
// Create the icon graphic contest
|
|
|
|
{
|
|
|
|
GC gc = XCreateGC(_dpy, pixmap, 0, NULL);
|
|
|
|
nlwarning("Failed to find a standard format");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Picture picture = XRenderCreatePicture(_dpy, pixmap, format, 0, 0);
|
|
|
|
if (!gc)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("Failed to create a GC");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!picture)
|
|
|
|
sint res = XPutImage(_dpy, pixmap, gc, image, 0, 0, 0, 0, iconWidth, iconHeight);
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("Failed to create picture");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cursor = XRenderCreateCursor(_dpy, picture, (uint)hotSpotX, (uint)hotSpotY);
|
|
|
|
if (res)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("XPutImage failed with code %d", res);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!cursor)
|
|
|
|
if (!XFreeGC(_dpy, gc))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
nlwarning("Failed to create cursor");
|
|
|
|
nlwarning("XFreeGC failed");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XRenderFreePicture(_dpy, picture);
|
|
|
|
if (image->data)
|
|
|
|
res = XFreePixmap(_dpy, pixmap);
|
|
|
|
{
|
|
|
|
// should return 1
|
|
|
|
free(image->data);
|
|
|
|
nlwarning("XFreePixmap returned %d", res);
|
|
|
|
image->data = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
XDestroyImage(image);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XRenderPictFormat *format = XRenderFindStandardFormat(_dpy, PictStandardARGB32);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!format)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("Failed to find a standard format");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Picture picture = XRenderCreatePicture(_dpy, pixmap, format, 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!picture)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("Failed to create picture");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cursor = XRenderCreateCursor(_dpy, picture, (uint)hotSpotX, (uint)hotSpotY);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!cursor)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("Failed to create cursor");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XRenderFreePicture(_dpy, picture);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!XFreePixmap(_dpy, pixmap))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
nlwarning("XFreePixmap failed");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // HAVE_XRENDER
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
|
|