Changed: #1034 Implement CCustomMouse for Linux
This commit is contained in:
parent
16a086697d
commit
6f0fef6808
7 changed files with 214 additions and 229 deletions
|
@ -3932,9 +3932,4 @@ bool CDriverD3D::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDriverD3D::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
|
|
||||||
{
|
|
||||||
return convertBitmapToIcon(bitmap, cursor, iconWidth, iconHeight, iconDepth, col, hotSpotX, hotSpotY, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // NL3D
|
} // NL3D
|
||||||
|
|
|
@ -177,11 +177,8 @@ void CDriverD3D::addCursor(const std::string &name, const NLMISC::CBitmap &curso
|
||||||
CCursor &curs = _Cursors[name];
|
CCursor &curs = _Cursors[name];
|
||||||
curs = CCursor(); // erase possible previous cursor
|
curs = CCursor(); // erase possible previous cursor
|
||||||
|
|
||||||
uint destWidth;
|
uint destWidth = GetSystemMetrics(SM_CXCURSOR);
|
||||||
uint destHeight;
|
uint destHeight = GetSystemMetrics(SM_CYCURSOR);
|
||||||
|
|
||||||
destWidth = GetSystemMetrics(SM_CXCURSOR);
|
|
||||||
destHeight = GetSystemMetrics(SM_CYCURSOR);
|
|
||||||
|
|
||||||
// build a square bitmap
|
// build a square bitmap
|
||||||
uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1);
|
uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1);
|
||||||
|
@ -198,9 +195,12 @@ void CDriverD3D::addCursor(const std::string &name, const NLMISC::CBitmap &curso
|
||||||
// first resampling, same for all cursors
|
// first resampling, same for all cursors
|
||||||
tmpSize = (uint) (tmpSize * curs.HotspotScale);
|
tmpSize = (uint) (tmpSize * curs.HotspotScale);
|
||||||
if (tmpSize == 0) tmpSize = 1;
|
if (tmpSize == 0) tmpSize = 1;
|
||||||
/*
|
|
||||||
|
if (curs.HotspotScale < 1.f)
|
||||||
|
{
|
||||||
curs.Src.resample(tmpSize, tmpSize);
|
curs.Src.resample(tmpSize, tmpSize);
|
||||||
*/
|
}
|
||||||
|
|
||||||
// shrink if necessary
|
// shrink if necessary
|
||||||
if (tmpSize > destWidth || tmpSize > destHeight) // need to shrink ?
|
if (tmpSize > destWidth || tmpSize > destHeight) // need to shrink ?
|
||||||
{
|
{
|
||||||
|
@ -305,12 +305,8 @@ nlCursor CDriverD3D::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 ro
|
||||||
{
|
{
|
||||||
nlassert(isAlphaBlendedCursorSupported());
|
nlassert(isAlphaBlendedCursorSupported());
|
||||||
|
|
||||||
uint mouseW;
|
uint mouseW = GetSystemMetrics(SM_CXCURSOR);
|
||||||
uint mouseH;
|
uint mouseH = GetSystemMetrics(SM_CYCURSOR);
|
||||||
|
|
||||||
// use cursor size from system
|
|
||||||
mouseW = GetSystemMetrics(SM_CXCURSOR);
|
|
||||||
mouseH = GetSystemMetrics(SM_CYCURSOR);
|
|
||||||
|
|
||||||
CBitmap rotSrc = src;
|
CBitmap rotSrc = src;
|
||||||
if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...)
|
if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...)
|
||||||
|
@ -374,6 +370,7 @@ void CDriverD3D::setMousePos(float x, float y)
|
||||||
if (_HWnd == EmptyWindow)
|
if (_HWnd == EmptyWindow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// convert position size from float to pixels
|
||||||
sint x1 = (sint)((float)_CurrentMode.Width*x);
|
sint x1 = (sint)((float)_CurrentMode.Width*x);
|
||||||
sint y1 = (sint)((float)_CurrentMode.Height*(1.0f-y));
|
sint y1 = (sint)((float)_CurrentMode.Height*(1.0f-y));
|
||||||
|
|
||||||
|
@ -385,6 +382,28 @@ void CDriverD3D::setMousePos(float x, float y)
|
||||||
SetCursorPos(pt.x, pt.y);
|
SetCursorPos(pt.x, pt.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CDriverD3D::setCapture (bool b)
|
||||||
|
{
|
||||||
|
H_AUTO_D3D(CDriverD3D_setCapture);
|
||||||
|
|
||||||
|
if (b && isSystemCursorInClientArea() && !isSystemCursorCaptured())
|
||||||
|
{
|
||||||
|
SetCapture(_HWnd);
|
||||||
|
}
|
||||||
|
else if (!b && isSystemCursorCaptured())
|
||||||
|
{
|
||||||
|
// if hardware mouse and not in client area, then force to update its aspect by updating its pos
|
||||||
|
if (!isSystemCursorInClientArea())
|
||||||
|
{
|
||||||
|
// force update
|
||||||
|
showCursor(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseCapture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
bool CDriverD3D::isSystemCursorInClientArea()
|
bool CDriverD3D::isSystemCursorInClientArea()
|
||||||
{
|
{
|
||||||
|
@ -433,28 +452,6 @@ bool CDriverD3D::isSystemCursorInClientArea()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
|
||||||
void CDriverD3D::setCapture (bool b)
|
|
||||||
{
|
|
||||||
H_AUTO_D3D(CDriverD3D_setCapture);
|
|
||||||
|
|
||||||
if (b && isSystemCursorInClientArea() && !isSystemCursorCaptured())
|
|
||||||
{
|
|
||||||
SetCapture(_HWnd);
|
|
||||||
}
|
|
||||||
else if (!b && isSystemCursorCaptured())
|
|
||||||
{
|
|
||||||
// if hardware mouse and not in client area, then force to update its aspect by updating its pos
|
|
||||||
if (!isSystemCursorInClientArea())
|
|
||||||
{
|
|
||||||
// force update
|
|
||||||
showCursor(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseCapture();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
bool CDriverD3D::isSystemCursorCaptured()
|
bool CDriverD3D::isSystemCursorCaptured()
|
||||||
{
|
{
|
||||||
|
@ -578,4 +575,9 @@ uint CDriverD3D::getDoubleClickDelay(bool hardwareMouse)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CDriverD3D::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
|
||||||
|
{
|
||||||
|
return convertBitmapToIcon(bitmap, cursor, iconWidth, iconHeight, iconDepth, col, hotSpotX, hotSpotY, true);
|
||||||
|
}
|
||||||
|
|
||||||
} // NL3D
|
} // NL3D
|
||||||
|
|
|
@ -1002,6 +1002,9 @@ private:
|
||||||
// Convert a NLMISC::CBitmap to nlCursor
|
// Convert a NLMISC::CBitmap to nlCursor
|
||||||
bool convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY);
|
bool convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY);
|
||||||
|
|
||||||
|
// Return the best cursor size depending on specified width and height
|
||||||
|
bool getBestCursorSize(uint srcWidth, uint srcHeight, uint &dstWidth, uint &dstHeight);
|
||||||
|
|
||||||
// build a cursor from src, src should have the same size that the hardware cursor
|
// build a cursor from src, src should have the same size that the hardware cursor
|
||||||
// or a assertion is thrown
|
// or a assertion is thrown
|
||||||
nlCursor buildCursor(const NLMISC::CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY);
|
nlCursor buildCursor(const NLMISC::CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY);
|
||||||
|
|
|
@ -205,20 +205,8 @@ void CDriverGL::addCursor(const std::string &name, const NLMISC::CBitmap &cursor
|
||||||
CCursor &curs = _Cursors[name];
|
CCursor &curs = _Cursors[name];
|
||||||
curs = CCursor(); // erase possible previous cursor
|
curs = CCursor(); // erase possible previous cursor
|
||||||
|
|
||||||
uint destWidth;
|
uint destWidth = 32, destHeight = 32;
|
||||||
uint destHeight;
|
getBestCursorSize(width, height, destWidth, destHeight);
|
||||||
|
|
||||||
#ifdef NL_OS_WINDOWS
|
|
||||||
|
|
||||||
destWidth = GetSystemMetrics(SM_CXCURSOR);
|
|
||||||
destHeight = GetSystemMetrics(SM_CYCURSOR);
|
|
||||||
|
|
||||||
#elif defined(NL_OS_MAC)
|
|
||||||
#elif defined(NL_OS_UNIX)
|
|
||||||
|
|
||||||
Status res = XQueryBestCursor(_dpy, _win, width, height, &destWidth, &destHeight);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// build a square bitmap
|
// build a square bitmap
|
||||||
uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1);
|
uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1);
|
||||||
|
@ -384,22 +372,8 @@ nlCursor CDriverGL::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot
|
||||||
{
|
{
|
||||||
nlassert(isAlphaBlendedCursorSupported());
|
nlassert(isAlphaBlendedCursorSupported());
|
||||||
|
|
||||||
uint mouseW;
|
uint mouseW = 32, mouseH = 32;
|
||||||
uint mouseH;
|
getBestCursorSize(src.getWidth(), src.getHeight(), mouseW, mouseH);
|
||||||
|
|
||||||
#ifdef NL_OS_WINDOWS
|
|
||||||
|
|
||||||
// use cursor size from system
|
|
||||||
mouseW = GetSystemMetrics(SM_CXCURSOR);
|
|
||||||
mouseH = GetSystemMetrics(SM_CYCURSOR);
|
|
||||||
|
|
||||||
#elif defined(NL_OS_MAC)
|
|
||||||
#elif defined(NL_OS_UNIX)
|
|
||||||
|
|
||||||
// use best cursor size for bitmap
|
|
||||||
Status res = XQueryBestCursor(_dpy, _win, src.getWidth(), src.getHeight(), &mouseW, &mouseH);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CBitmap rotSrc = src;
|
CBitmap rotSrc = src;
|
||||||
if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...)
|
if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...)
|
||||||
|
@ -811,4 +785,161 @@ uint CDriverGL::getDoubleClickDelay(bool hardwareMouse)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CDriverGL::getBestCursorSize(uint srcWidth, uint srcHeight, uint &dstWidth, uint &dstHeight)
|
||||||
|
{
|
||||||
|
#ifdef NL_OS_WINDOWS
|
||||||
|
|
||||||
|
// Windows provides default size for cursors
|
||||||
|
dstWidth = (uint)GetSystemMetrics(SM_CXCURSOR);
|
||||||
|
dstHeight = (uint)GetSystemMetrics(SM_CYCURSOR);
|
||||||
|
|
||||||
|
#elif defined(NL_OS_MAC)
|
||||||
|
#elif defined(NL_OS_UNIX)
|
||||||
|
|
||||||
|
Status res = XQueryBestCursor(_dpy, _win, srcWidth, srcHeight, &dstWidth, &dstHeight);
|
||||||
|
nlwarning("XQueryBestCursor returned %d", (sint)res);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
|
||||||
|
{
|
||||||
|
#if defined(NL_OS_WINDOWS)
|
||||||
|
|
||||||
|
return convertBitmapToIcon(bitmap, cursor, iconWidth, iconHeight, iconDepth, col, hotSpotX, hotSpotY, true);
|
||||||
|
|
||||||
|
#elif defined(NL_OS_UNIX) && defined(HAVE_XRENDER) && !defined(NL_OS_MAC)
|
||||||
|
|
||||||
|
CBitmap src = bitmap;
|
||||||
|
|
||||||
|
// resample bitmap if necessary
|
||||||
|
if (src.getWidth() != iconWidth || src.getHeight() != iconHeight)
|
||||||
|
{
|
||||||
|
src.resample(iconWidth, iconHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBitmap colorBm;
|
||||||
|
colorBm.resize(iconWidth, iconHeight, CBitmap::RGBA);
|
||||||
|
const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]);
|
||||||
|
const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight);
|
||||||
|
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// colorize icon
|
||||||
|
destColorPtr->modulateFromColor(*srcColorPtr, col);
|
||||||
|
|
||||||
|
// X11 wants BGRA pixels : swap red and blue channels
|
||||||
|
std::swap(destColorPtr->R, destColorPtr->B);
|
||||||
|
|
||||||
|
// premultiplied alpha
|
||||||
|
if (destColorPtr->A < 255)
|
||||||
|
{
|
||||||
|
destColorPtr->R = (destColorPtr->R * destColorPtr->A) / 255;
|
||||||
|
destColorPtr->G = (destColorPtr->G * destColorPtr->A) / 255;
|
||||||
|
destColorPtr->B = (destColorPtr->B * destColorPtr->A) / 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
++ srcColorPtr;
|
||||||
|
++ destColorPtr;
|
||||||
|
}
|
||||||
|
while (srcColorPtr != srcColorPtrLast);
|
||||||
|
|
||||||
|
// use malloc() because X will free() data itself
|
||||||
|
CRGBA *src32 = (CRGBA*)malloc(colorBm.getSize()*4);
|
||||||
|
memcpy(src32, &colorBm.getPixels(0)[0], colorBm.getSize()*4);
|
||||||
|
|
||||||
|
uint size = iconWidth * iconHeight;
|
||||||
|
|
||||||
|
// Create the icon pixmap
|
||||||
|
sint screen = DefaultScreen(_dpy);
|
||||||
|
Visual *visual = DefaultVisual(_dpy, screen);
|
||||||
|
|
||||||
|
if (!visual)
|
||||||
|
{
|
||||||
|
nlwarning("Failed to get a default visual for screen %d", screen);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the icon pixmap
|
||||||
|
XImage* image = XCreateImage(_dpy, visual, 32, ZPixmap, 0, (char*)src32, iconWidth, iconHeight, 32, 0);
|
||||||
|
|
||||||
|
if (!image)
|
||||||
|
{
|
||||||
|
nlwarning("Failed to set the window's icon");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pixmap pixmap = XCreatePixmap(_dpy, _win, iconWidth, iconHeight, 32 /* defDepth */);
|
||||||
|
|
||||||
|
if (!pixmap)
|
||||||
|
{
|
||||||
|
nlwarning("Failed to create a pixmap %ux%ux%d", iconWidth, iconHeight, 32);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GC gc = XCreateGC(_dpy, pixmap, 0, NULL);
|
||||||
|
|
||||||
|
if (!gc)
|
||||||
|
{
|
||||||
|
nlwarning("Failed to create a GC");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sint res = XPutImage(_dpy, pixmap, gc, image, 0, 0, 0, 0, iconWidth, iconHeight);
|
||||||
|
// should return 0
|
||||||
|
nlwarning("XPutImage returned %d", res);
|
||||||
|
|
||||||
|
res = XFreeGC(_dpy, gc);
|
||||||
|
// should return 1
|
||||||
|
nlwarning("XFreeGC returned %d", res);
|
||||||
|
|
||||||
|
if (image->data)
|
||||||
|
{
|
||||||
|
free(image->data);
|
||||||
|
image->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
res = XFreePixmap(_dpy, pixmap);
|
||||||
|
// should return 1
|
||||||
|
nlwarning("XFreePixmap returned %d", res);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // NL3D
|
} // NL3D
|
||||||
|
|
|
@ -2646,7 +2646,7 @@ bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon,
|
||||||
const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]);
|
const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]);
|
||||||
const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight);
|
const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight);
|
||||||
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
|
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
|
||||||
static volatile uint8 alphaThreshold = 127;
|
static uint8 alphaThreshold = 127;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
destColorPtr->modulateFromColor(*srcColorPtr, col);
|
destColorPtr->modulateFromColor(*srcColorPtr, col);
|
||||||
|
@ -2674,7 +2674,7 @@ bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon,
|
||||||
|
|
||||||
for (uint k = 0;k < colorBm16.size(); ++k)
|
for (uint k = 0;k < colorBm16.size(); ++k)
|
||||||
{
|
{
|
||||||
if (src32[k].A <= 120)
|
if (src32[k].A <= alphaThreshold)
|
||||||
{
|
{
|
||||||
bitMask[k / 8] |= (0x80 >> (k & 7));
|
bitMask[k / 8] |= (0x80 >> (k & 7));
|
||||||
}
|
}
|
||||||
|
@ -2707,18 +2707,8 @@ bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
|
|
||||||
{
|
|
||||||
return convertBitmapToIcon(bitmap, cursor, iconWidth, iconHeight, iconDepth, col, hotSpotX, hotSpotY, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(NL_OS_MAC)
|
#elif defined(NL_OS_MAC)
|
||||||
|
|
||||||
bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(NL_OS_UNIX)
|
#elif defined(NL_OS_UNIX)
|
||||||
|
|
||||||
bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, std::vector<long> &icon)
|
bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, std::vector<long> &icon)
|
||||||
|
@ -2745,140 +2735,6 @@ bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, std::vector<l
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_XRENDER
|
|
||||||
|
|
||||||
CBitmap src = bitmap;
|
|
||||||
|
|
||||||
// resample bitmap if necessary
|
|
||||||
if (src.getWidth() != iconWidth || src.getHeight() != iconHeight)
|
|
||||||
{
|
|
||||||
src.resample(iconWidth, iconHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
CBitmap colorBm;
|
|
||||||
colorBm.resize(iconWidth, iconHeight, CBitmap::RGBA);
|
|
||||||
const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]);
|
|
||||||
const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight);
|
|
||||||
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// colorize icon
|
|
||||||
destColorPtr->modulateFromColor(*srcColorPtr, col);
|
|
||||||
|
|
||||||
// X11 wants BGRA pixels : swap red and blue channels
|
|
||||||
std::swap(destColorPtr->R, destColorPtr->B);
|
|
||||||
|
|
||||||
// premultiplied alpha
|
|
||||||
if (destColorPtr->A < 255)
|
|
||||||
{
|
|
||||||
destColorPtr->R = (destColorPtr->R * destColorPtr->A) / 255;
|
|
||||||
destColorPtr->G = (destColorPtr->G * destColorPtr->A) / 255;
|
|
||||||
destColorPtr->B = (destColorPtr->B * destColorPtr->A) / 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
++ srcColorPtr;
|
|
||||||
++ destColorPtr;
|
|
||||||
}
|
|
||||||
while (srcColorPtr != srcColorPtrLast);
|
|
||||||
|
|
||||||
// use malloc() because X will free() data itself
|
|
||||||
CRGBA *src32 = (CRGBA*)malloc(colorBm.getSize()*4);
|
|
||||||
memcpy(src32, &colorBm.getPixels(0)[0], colorBm.getSize()*4);
|
|
||||||
|
|
||||||
uint size = iconWidth * iconHeight;
|
|
||||||
|
|
||||||
// Create the icon pixmap
|
|
||||||
sint screen = DefaultScreen(_dpy);
|
|
||||||
Visual *visual = DefaultVisual(_dpy, screen);
|
|
||||||
|
|
||||||
if (!visual)
|
|
||||||
{
|
|
||||||
nlwarning("Failed to get a default visual for screen %d", screen);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the icon pixmap
|
|
||||||
XImage* image = XCreateImage(_dpy, visual, 32, ZPixmap, 0, (char*)src32, iconWidth, iconHeight, 32, 0);
|
|
||||||
|
|
||||||
if (!image)
|
|
||||||
{
|
|
||||||
nlwarning("Failed to set the window's icon");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pixmap pixmap = XCreatePixmap(_dpy, _win, iconWidth, iconHeight, 32 /* defDepth */);
|
|
||||||
|
|
||||||
if (!pixmap)
|
|
||||||
{
|
|
||||||
nlwarning("Failed to create a pixmap %ux%ux%d", iconWidth, iconHeight, 32);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GC gc = XCreateGC(_dpy, pixmap, 0, NULL);
|
|
||||||
|
|
||||||
if (!gc)
|
|
||||||
{
|
|
||||||
nlwarning("Failed to create a GC");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint res = XPutImage(_dpy, pixmap, gc, image, 0, 0, 0, 0, iconWidth, iconHeight);
|
|
||||||
// should return 0
|
|
||||||
nlwarning("XPutImage returned %d", res);
|
|
||||||
|
|
||||||
res = XFreeGC(_dpy, gc);
|
|
||||||
// should return 1
|
|
||||||
nlwarning("XFreeGC returned %d", res);
|
|
||||||
|
|
||||||
if (image->data)
|
|
||||||
{
|
|
||||||
free(image->data);
|
|
||||||
image->data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
res = XFreePixmap(_dpy, pixmap);
|
|
||||||
// should return 1
|
|
||||||
nlwarning("XFreePixmap returned %d", res);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // NL3D
|
} // NL3D
|
||||||
|
|
|
@ -64,7 +64,6 @@ CInputHandlerManager::CInputHandlerManager()
|
||||||
_MouseButtonsState = noButton;
|
_MouseButtonsState = noButton;
|
||||||
_MouseX = _MouseY = _MouseLastX = _MouseLastY = 0;
|
_MouseX = _MouseY = _MouseLastX = _MouseLastY = 0;
|
||||||
_Focus = true;
|
_Focus = true;
|
||||||
// Driver->setFocus(true);
|
|
||||||
_MouseWheel = 0;
|
_MouseWheel = 0;
|
||||||
_SkipInterfaceManager=false;
|
_SkipInterfaceManager=false;
|
||||||
_RecoverFocusLost = false;
|
_RecoverFocusLost = false;
|
||||||
|
@ -184,7 +183,6 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event)
|
||||||
_RecoverFocusLost = true; // force to update mouse pos on next click or move
|
_RecoverFocusLost = true; // force to update mouse pos on next click or move
|
||||||
Driver->showCursor(IsMouseCursorHardware());
|
Driver->showCursor(IsMouseCursorHardware());
|
||||||
_Focus = true;
|
_Focus = true;
|
||||||
// Driver->setFocus(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_SkipInterfaceManager)
|
if(!_SkipInterfaceManager)
|
||||||
|
|
Loading…
Reference in a new issue