From 6f0fef6808ecb60ec79a84fdf74b5109bcf5fa24 Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 4 Nov 2010 19:35:44 +0100 Subject: [PATCH] Changed: #1034 Implement CCustomMouse for Linux --- .../3d/driver/direct3d/driver_direct3d.cpp | 5 - .../src/3d/driver/direct3d/driver_direct3d.h | 20 +- .../direct3d/driver_direct3d_inputs.cpp | 74 +++---- code/nel/src/3d/driver/opengl/driver_opengl.h | 3 + .../3d/driver/opengl/driver_opengl_inputs.cpp | 191 +++++++++++++++--- .../3d/driver/opengl/driver_opengl_window.cpp | 148 +------------- .../interface_v3/input_handler_manager.cpp | 2 - 7 files changed, 214 insertions(+), 229 deletions(-) diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp index febc34286..50c2f5c15 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp @@ -3932,9 +3932,4 @@ bool CDriverD3D::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, 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 diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.h b/code/nel/src/3d/driver/direct3d/driver_direct3d.h index 83e85dc1d..fae4d6dee 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.h +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.h @@ -2093,18 +2093,18 @@ private: // cursors enum TColorDepth { ColorDepth16 = 0, ColorDepth32, ColorDepthCount }; - TColorDepth _ColorDepth; - std::string _CurrName; - NLMISC::CRGBA _CurrCol; - uint8 _CurrRot; - uint _CurrHotSpotX; - uint _CurrHotSpotY; - float _CursorScale; + TColorDepth _ColorDepth; + std::string _CurrName; + NLMISC::CRGBA _CurrCol; + uint8 _CurrRot; + uint _CurrHotSpotX; + uint _CurrHotSpotY; + float _CursorScale; - nlCursor _DefaultCursor; + nlCursor _DefaultCursor; - bool _AlphaBlendedCursorSupported; - bool _AlphaBlendedCursorSupportRetrieved; + bool _AlphaBlendedCursorSupported; + bool _AlphaBlendedCursorSupportRetrieved; class CCursor { diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp index c2c456fcc..038ae5ea7 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp @@ -177,11 +177,8 @@ void CDriverD3D::addCursor(const std::string &name, const NLMISC::CBitmap &curso CCursor &curs = _Cursors[name]; curs = CCursor(); // erase possible previous cursor - uint destWidth; - uint destHeight; - - destWidth = GetSystemMetrics(SM_CXCURSOR); - destHeight = GetSystemMetrics(SM_CYCURSOR); + uint destWidth = GetSystemMetrics(SM_CXCURSOR); + uint destHeight = GetSystemMetrics(SM_CYCURSOR); // build a square bitmap 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 tmpSize = (uint) (tmpSize * curs.HotspotScale); if (tmpSize == 0) tmpSize = 1; -/* - curs.Src.resample(tmpSize, tmpSize); -*/ + + if (curs.HotspotScale < 1.f) + { + curs.Src.resample(tmpSize, tmpSize); + } + // shrink if necessary 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()); - uint mouseW; - uint mouseH; - - // use cursor size from system - mouseW = GetSystemMetrics(SM_CXCURSOR); - mouseH = GetSystemMetrics(SM_CYCURSOR); + uint mouseW = GetSystemMetrics(SM_CXCURSOR); + uint mouseH = GetSystemMetrics(SM_CYCURSOR); CBitmap rotSrc = src; 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) return; + // convert position size from float to pixels sint x1 = (sint)((float)_CurrentMode.Width*x); 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); } +// *************************************************************************** +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() { @@ -433,28 +452,6 @@ bool CDriverD3D::isSystemCursorInClientArea() 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() { @@ -578,4 +575,9 @@ uint CDriverD3D::getDoubleClickDelay(bool hardwareMouse) 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 diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.h b/code/nel/src/3d/driver/opengl/driver_opengl.h index 8ab0b3f6a..9b4dcfb9e 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl.h @@ -1002,6 +1002,9 @@ private: // 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); + // 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 // or a assertion is thrown nlCursor buildCursor(const NLMISC::CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY); diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp index 70c2ce9d6..5af8a057a 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp @@ -205,20 +205,8 @@ void CDriverGL::addCursor(const std::string &name, const NLMISC::CBitmap &cursor CCursor &curs = _Cursors[name]; curs = CCursor(); // erase possible previous cursor - uint destWidth; - uint 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 + uint destWidth = 32, destHeight = 32; + getBestCursorSize(width, height, destWidth, destHeight); // build a square bitmap 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()); - uint mouseW; - uint 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 + uint mouseW = 32, mouseH = 32; + getBestCursorSize(src.getWidth(), src.getHeight(), mouseW, mouseH); CBitmap rotSrc = src; 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; } +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 diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp index e340520ca..68cd0a5b5 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -2646,7 +2646,7 @@ bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]); const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight); CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]); - static volatile uint8 alphaThreshold = 127; + static uint8 alphaThreshold = 127; do { 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) { - if (src32[k].A <= 120) + if (src32[k].A <= alphaThreshold) { bitMask[k / 8] |= (0x80 >> (k & 7)); } @@ -2707,18 +2707,8 @@ bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, 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) -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) bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, std::vector &icon) @@ -2745,140 +2735,6 @@ bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, std::vectormodulateFromColor(*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 } // NL3D diff --git a/code/ryzom/client/src/interface_v3/input_handler_manager.cpp b/code/ryzom/client/src/interface_v3/input_handler_manager.cpp index 12efeed5a..90adc44a3 100644 --- a/code/ryzom/client/src/interface_v3/input_handler_manager.cpp +++ b/code/ryzom/client/src/interface_v3/input_handler_manager.cpp @@ -64,7 +64,6 @@ CInputHandlerManager::CInputHandlerManager() _MouseButtonsState = noButton; _MouseX = _MouseY = _MouseLastX = _MouseLastY = 0; _Focus = true; - // Driver->setFocus(true); _MouseWheel = 0; _SkipInterfaceManager=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 Driver->showCursor(IsMouseCursorHardware()); _Focus = true; - // Driver->setFocus(true); } if(!_SkipInterfaceManager)