From a4c64bb753eb4a5b63eaf16e65580c3a6974b95b Mon Sep 17 00:00:00 2001 From: kervala Date: Tue, 2 Nov 2010 19:45:05 +0100 Subject: [PATCH] Changed: #1034 Implement CCustomMouse for Linux --- code/CMakeModules/FindXRandR.cmake | 46 - code/nel/include/nel/3d/driver.h | 9 + code/nel/include/nel/3d/driver_user.h | 10 + code/nel/include/nel/3d/u_driver.h | 10 + code/nel/include/nel/misc/bitmap.h | 4 - code/nel/include/nel/misc/common.h | 2 - code/nel/include/nel/misc/system_utils.h | 3 - code/nel/src/3d/driver.cpp | 2 +- .../3d/driver/direct3d/driver_direct3d.cpp | 103 ++- .../src/3d/driver/direct3d/driver_direct3d.h | 95 ++ .../direct3d/driver_direct3d_inputs.cpp | 526 ++++++++++-- .../src/3d/driver/opengl/driver_opengl.cpp | 15 +- code/nel/src/3d/driver/opengl/driver_opengl.h | 103 ++- .../3d/driver/opengl/driver_opengl_inputs.cpp | 808 ++++++++++++++++++ .../3d/driver/opengl/driver_opengl_window.cpp | 647 +++++++------- code/nel/src/3d/driver_user.cpp | 20 + code/nel/src/misc/bitmap.cpp | 82 -- code/nel/src/misc/system_utils.cpp | 52 -- code/ryzom/client/src/init.cpp | 12 - code/ryzom/client/src/input.cpp | 149 +--- code/ryzom/client/src/input.h | 13 - .../client/src/interface_v3/custom_mouse.cpp | 458 ---------- .../client/src/interface_v3/custom_mouse.h | 116 --- .../interface_v3/input_handler_manager.cpp | 16 +- .../client/src/interface_v3/view_pointer.cpp | 7 +- .../client/src/interface_v3/view_renderer.cpp | 28 +- code/ryzom/client/src/release.cpp | 5 - 27 files changed, 1969 insertions(+), 1372 deletions(-) delete mode 100644 code/CMakeModules/FindXRandR.cmake create mode 100644 code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp delete mode 100644 code/ryzom/client/src/interface_v3/custom_mouse.cpp delete mode 100644 code/ryzom/client/src/interface_v3/custom_mouse.h diff --git a/code/CMakeModules/FindXRandR.cmake b/code/CMakeModules/FindXRandR.cmake deleted file mode 100644 index 5867e65eb..000000000 --- a/code/CMakeModules/FindXRandR.cmake +++ /dev/null @@ -1,46 +0,0 @@ -# - Locate XRandR library -# This module defines -# XRandR_LIBRARY, the library to link against -# XRandR_FOUND, if false, do not try to link to XRandR -# XRandR_INCLUDE_DIR, where to find headers. - -IF(XRandR_LIBRARY AND XRandR_INCLUDE_DIR) - # in cache already - SET(XRandR_FIND_QUIETLY TRUE) -ENDIF(XRandR_LIBRARY AND XRandR_INCLUDE_DIR) - - -FIND_PATH(XRandR_INCLUDE_DIR - Xrandr.h - PATHS - $ENV{XRandR_DIR}/include - /usr/include/X11/ - /usr/X11R6/include/ - PATH_SUFFIXES extensions -) - -FIND_LIBRARY(XRandR_LIBRARY - Xrandr - PATHS - $ENV{XRandR_DIR}/lib - /usr/X11R6/lib - /usr/lib - /sw/lib - /opt/local/lib - /opt/csw/lib - /opt/lib - /usr/freeware/lib64 -) - -IF(XRandR_LIBRARY AND XRandR_INCLUDE_DIR) - SET(XRandR_FOUND "YES") - SET(XRandR_DEFINITIONS -DXRANDR) - IF(NOT XRandR_FIND_QUIETLY) - MESSAGE(STATUS "Found XRandR: ${XRandR_LIBRARY}") - ENDIF(NOT XRandR_FIND_QUIETLY) -ELSE(XRandR_LIBRARY AND XRandR_INCLUDE_DIR) - IF(NOT XRandR_FIND_QUIETLY) - MESSAGE(STATUS "Warning: Unable to find XRandR!") - ENDIF(NOT XRandR_FIND_QUIETLY) -ENDIF(XRandR_LIBRARY AND XRandR_INCLUDE_DIR) - diff --git a/code/nel/include/nel/3d/driver.h b/code/nel/include/nel/3d/driver.h index 329dd19d2..51ea013c3 100644 --- a/code/nel/include/nel/3d/driver.h +++ b/code/nel/include/nel/3d/driver.h @@ -746,6 +746,15 @@ public: */ virtual void setCapture (bool b) = 0; + // see if system cursor is currently captured + virtual bool isSystemCursorCaptured() = 0; + + // Add a new cursor (name is case unsensitive) + virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap) = 0; + + // Display a cursor from its name (case unsensitive) + virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false) = 0; + /** Check whether there is a low level device manager available, and get its interface. Return NULL if not available * From this interface you can deal with mouse and keyboard as above, but you can also manage game device (joysticks, joypads ...) */ diff --git a/code/nel/include/nel/3d/driver_user.h b/code/nel/include/nel/3d/driver_user.h index 1d079a2b7..bb21b01a6 100644 --- a/code/nel/include/nel/3d/driver_user.h +++ b/code/nel/include/nel/3d/driver_user.h @@ -430,6 +430,16 @@ public: virtual void setMousePos (float x, float y); /// If true, capture the mouse to force it to stay under the window. virtual void setCapture (bool b); + + // see if system cursor is currently captured + virtual bool isSystemCursorCaptured(); + + // Add a new cursor (name is case unsensitive) + virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap); + + // Display a cursor from its name (case unsensitive) + virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false); + // @} diff --git a/code/nel/include/nel/3d/u_driver.h b/code/nel/include/nel/3d/u_driver.h index 9fe5c86d0..173ac4b9e 100644 --- a/code/nel/include/nel/3d/u_driver.h +++ b/code/nel/include/nel/3d/u_driver.h @@ -594,6 +594,16 @@ public: * NB : If a low level mouse is used, it does nothing */ virtual void setCapture (bool b) = 0; + + // see if system cursor is currently captured + virtual bool isSystemCursorCaptured() = 0; + + // Add a new cursor (name is case unsensitive) + virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap) = 0; + + // Display a cursor from its name (case unsensitive) + virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false) = 0; + // @} /// \name Misc. diff --git a/code/nel/include/nel/misc/bitmap.h b/code/nel/include/nel/misc/bitmap.h index 2a2361b55..99fa5527f 100644 --- a/code/nel/include/nel/misc/bitmap.h +++ b/code/nel/include/nel/misc/bitmap.h @@ -621,10 +621,6 @@ public: void getDibData(uint8*& extractData); -#ifdef NL_OS_WINDOWS - HICON getHICON(sint iconWidth, sint iconHeight, sint iconDepth, const NLMISC::CRGBA &col = NLMISC::CRGBA::White, sint hotSpotX = 0, sint hotSpotY = 0, bool cursor = false) const; -#endif - CBitmap& operator= (const CBitmap& from) { if (&from == this) diff --git a/code/nel/include/nel/misc/common.h b/code/nel/include/nel/misc/common.h index d5460b362..42bf56d3b 100644 --- a/code/nel/include/nel/misc/common.h +++ b/code/nel/include/nel/misc/common.h @@ -41,8 +41,6 @@ #include "string_common.h" #ifdef NL_OS_WINDOWS - struct nameHICON__; - typedef struct HICON__ *HICON; struct nameHWND__; typedef struct HWND__ *HWND; typedef HWND nlWindow; diff --git a/code/nel/include/nel/misc/system_utils.h b/code/nel/include/nel/misc/system_utils.h index 4cd13a7ac..14c68f2de 100644 --- a/code/nel/include/nel/misc/system_utils.h +++ b/code/nel/include/nel/misc/system_utils.h @@ -77,9 +77,6 @@ public: /// Get desktop current color depth without using UDriver. static uint getCurrentColorDepth(); - - /// Check if mouse cursor is in client area. - static bool isSystemCursorInClientArea(); }; } // NLMISC diff --git a/code/nel/src/3d/driver.cpp b/code/nel/src/3d/driver.cpp index 0caf4a508..d5d12c885 100644 --- a/code/nel/src/3d/driver.cpp +++ b/code/nel/src/3d/driver.cpp @@ -33,7 +33,7 @@ namespace NL3D { // *************************************************************************** -const uint32 IDriver::InterfaceVersion = 0x69; // added clipboard methods +const uint32 IDriver::InterfaceVersion = 0x6a; // added cursors methods // *************************************************************************** IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" ) diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp index 0890a9084..febc34286 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp @@ -162,6 +162,19 @@ CDriverD3D::CDriverD3D() _WindowX = 0; _WindowY = 0; _FullScreen = false; + + _ColorDepth = ColorDepth32; + + _DefaultCursor = EmptyCursor; + + _AlphaBlendedCursorSupported = false; + _AlphaBlendedCursorSupportRetrieved = false; + _CurrCol = CRGBA::White; + _CurrRot = 0; + _CurrHotSpotX = 0; + _CurrHotSpotY = 0; + _CursorScale = 0.85f; + _UserViewMtx.identity(); _UserModelMtx.identity(); _PZBCameraPos = CVector::Null; @@ -1214,6 +1227,8 @@ bool CDriverD3D::init (uint windowIcon, emptyProc exitFunc) ExitFunc = exitFunc; + createCursors(); + // Register a window class WNDCLASSW wc; @@ -1224,7 +1239,7 @@ bool CDriverD3D::init (uint windowIcon, emptyProc exitFunc) wc.cbWndExtra = 0; wc.hInstance = GetModuleHandleW(NULL); wc.hIcon = (HICON)windowIcon; - wc.hCursor = LoadCursorW(NULL,(LPCWSTR)IDC_ARROW); + wc.hCursor = _DefaultCursor; wc.hbrBackground = WHITE_BRUSH; _WindowClass = "NLD3D" + toString(windowIcon); ucstring us = _WindowClass; @@ -1712,6 +1727,8 @@ bool CDriverD3D::release() if (_HWnd) { + releaseCursors(); + // make sure window icons are deleted std::vector bitmaps; setWindowIcon(bitmaps); @@ -2231,10 +2248,10 @@ void CDriverD3D::setWindowIcon(const std::vector &bitmaps) } if (smallIndex > -1) - winIconSmall = bitmaps[smallIndex].getHICON(smallWidth, smallHeight, 32); + convertBitmapToIcon(bitmaps[smallIndex], winIconSmall, smallWidth, smallHeight, 32); if (bigIndex > -1) - winIconBig = bitmaps[bigIndex].getHICON(bigWidth, bigHeight, 32); + convertBitmapToIcon(bitmaps[bigIndex], winIconBig, bigWidth, bigHeight, 32); if (winIconBig) { @@ -3840,4 +3857,84 @@ bool CDriverD3D::pasteTextFromClipboard(ucstring &text) { return _EventEmitter.pasteTextFromClipboard(text); } + +bool CDriverD3D::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY, bool cursor) +{ + 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]); + static volatile uint8 alphaThreshold = 127; + do + { + destColorPtr->modulateFromColor(*srcColorPtr, col); + std::swap(destColorPtr->R, destColorPtr->B); + ++ srcColorPtr; + ++ destColorPtr; + } + while (srcColorPtr != srcColorPtrLast); + // + HBITMAP colorHbm = NULL; + HBITMAP maskHbm = NULL; + // + if (iconDepth == 16) + { + std::vector colorBm16(iconWidth * iconHeight); + const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0]; + + for (uint k = 0; k < colorBm16.size(); ++k) + { + colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8); + } + + colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 16, &colorBm16[0]); + std::vector bitMask((iconWidth * iconHeight + 7) / 8, 0); + + for (uint k = 0;k < colorBm16.size(); ++k) + { + if (src32[k].A <= 120) + { + bitMask[k / 8] |= (0x80 >> (k & 7)); + } + } + + maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 1, &bitMask[0]); + } + else + { + colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]); + maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]); + } + + ICONINFO iconInfo; + iconInfo.fIcon = cursor ? FALSE:TRUE; + iconInfo.xHotspot = (DWORD) hotSpotX; + iconInfo.yHotspot = (DWORD) hotSpotY; + iconInfo.hbmMask = maskHbm; + iconInfo.hbmColor = colorHbm; + + if (colorHbm && maskHbm) + { + icon = CreateIconIndirect(&iconInfo); + } + + // + if (colorHbm) DeleteObject(colorHbm); + if (maskHbm) DeleteObject(maskHbm); + + 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 2870c55b2..83e85dc1d 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.h +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.h @@ -46,6 +46,9 @@ // #include +typedef HCURSOR nlCursor; +#define EmptyCursor NULL + // *** DEBUG MACRO @@ -916,6 +919,18 @@ public: virtual void showCursor (bool b); virtual void setMousePos(float x, float y); virtual void setCapture (bool b); + + // see if system cursor is currently captured + virtual bool isSystemCursorCaptured(); + + virtual void setHardwareCursorScale(float scale) { _CursorScale = scale; } + + // Add a new cursor (name is case unsensitive) + virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap); + + // Display a cursor from its name (case unsensitive) + virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false); + virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive); virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable); virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager(); @@ -2075,6 +2090,58 @@ private: uint _Interval; bool _FullScreen; + // cursors + enum TColorDepth { ColorDepth16 = 0, ColorDepth32, ColorDepthCount }; + + TColorDepth _ColorDepth; + std::string _CurrName; + NLMISC::CRGBA _CurrCol; + uint8 _CurrRot; + uint _CurrHotSpotX; + uint _CurrHotSpotY; + float _CursorScale; + + nlCursor _DefaultCursor; + + bool _AlphaBlendedCursorSupported; + bool _AlphaBlendedCursorSupportRetrieved; + + class CCursor + { + public: + NLMISC::CBitmap Src; + TColorDepth ColorDepth; + uint OrigHeight; + float HotspotScale; + uint HotspotOffsetX; + uint HotspotOffsetY; + sint HotSpotX; + sint HotSpotY; + nlCursor Cursor; + NLMISC::CRGBA Col; + uint8 Rot; +#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC) + Display *Dpy; +#endif + public: + CCursor(); + ~CCursor(); + CCursor& operator= (const CCursor& from); + + void reset(); + }; + + struct CStrCaseUnsensitiveCmp + { + bool operator()(const std::string &lhs, const std::string &rhs) const + { + return NLMISC::nlstricmp(lhs, rhs) < 0; + } + }; + + typedef std::map TCursorMap; + + TCursorMap _Cursors; // Directx uint32 _Adapter; @@ -2393,6 +2460,34 @@ public: // Build 16 bit index buffer for quad bool buildQuadIndexBuffer(); + // Test if cursor is in the client area. always true when software cursor is used and window visible + // (displayed in software when DirectInput is used) + bool isSystemCursorInClientArea(); + + // Check if RGBA cursors are supported + bool isAlphaBlendedCursorSupported(); + + // Update cursor appearance + void updateCursor(bool forceRebuild = false); + + // Create default cursors + void createCursors(); + + // Release all cursors + void releaseCursors(); + + // 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); + + // 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); + + // reset the cursor shape to the system arrow + void setSystemArrow(); + + bool convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col = NLMISC::CRGBA::White, sint hotSpotX = 0, sint hotSpotY = 0, bool cursor = false); + virtual bool copyTextToClipboard(const ucstring &text); virtual bool pasteTextFromClipboard(ucstring &text); 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 f38e15dd2..c2c456fcc 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp @@ -26,131 +26,529 @@ using namespace NLMISC; namespace NL3D { -// *************************************************************************** +// ************************************************************************************* +CDriverD3D::CCursor::CCursor() : ColorDepth(CDriverD3D::ColorDepth32), + OrigHeight(32), + HotspotScale(1.f), + HotspotOffsetX(0), + HotspotOffsetY(0), + HotSpotX(0), + HotSpotY(0), + Cursor(EmptyCursor), + Col(CRGBA::White), + Rot(0) +{ +} -void CDriverD3D::showCursor (bool b) +// ************************************************************************************* +CDriverD3D::CCursor::~CCursor() +{ + reset(); +} + +// ************************************************************************************* +void CDriverD3D::CCursor::reset() +{ + if (Cursor != EmptyCursor) + { + DestroyIcon(Cursor); + } +} + +// ************************************************************************************* +CDriverD3D::CCursor& CDriverD3D::CCursor::operator= (const CDriverD3D::CCursor& from) +{ + if (&from == this) + return *this; + Src = from.Src; // requires more than a surface copy + OrigHeight = from.OrigHeight; + HotspotScale = from.HotspotScale; + HotspotOffsetX = from.HotspotOffsetX; + HotspotOffsetY = from.HotspotOffsetY; + HotSpotX = from.HotSpotX; + HotSpotY = from.HotSpotY; + Cursor = from.Cursor; + Col = from.Col; + Rot = from.Rot; + return *this; +} + +// ************************************************************************************* +bool CDriverD3D::isAlphaBlendedCursorSupported() +{ + if (!_AlphaBlendedCursorSupportRetrieved) + { + // Support starts with windows 2000 (not only from XP as seen in most docs) + // NB : Additionnaly, could query D3D caps to know if + // color hardware cursor is supported, not only emulated, + // but can't be sure that using the win32 api 'SetCursor' uses the same resources + // So far, seems to be supported on any modern card used by the game anyway ... + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (GetVersionEx(&osvi)) + { + _AlphaBlendedCursorSupported = (osvi.dwMajorVersion >= 5); + } + + _AlphaBlendedCursorSupportRetrieved = true; + } + + return _AlphaBlendedCursorSupported; +} + +// ************************************************************************************* +void CDriverD3D::addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap) +{ + if (!isAlphaBlendedCursorSupported()) return; + + nlassert(cursorBitmap.getWidth() != 0); + nlassert(cursorBitmap.getHeight() != 0); + + // find used part base on alpha, to avoid too much shrinking + const CRGBA *pixels = (const CRGBA *) &cursorBitmap.getPixels()[0]; + uint minX, maxX, minY, maxY; + uint width = cursorBitmap.getWidth(); + uint height = cursorBitmap.getHeight(); + // + minX = 0; + for (uint x = 0; x < width; ++x) + { + bool stop = false; + minX = x; + for (uint y = 0; y < height; ++y) + { + if(pixels[x + y * width].A != 0) + { + stop = true; + break; + } + } + if (stop) break; + } + // + maxX = width - 1; + for (sint x = width - 1; x >= 0; --x) + { + bool stop = false; + maxX = (uint) x; + for (uint y = 0; y < height; ++y) + { + if(pixels[x + y * width].A != 0) + { + stop = true; + break; + } + } + if (stop) break; + } + // + minY = 0; + for (uint y = 0; y < height; ++y) + { + bool stop = false; + minY = y; + for (uint x = 0; x < width; ++x) + { + if(pixels[x + y * width].A != 0) + { + stop = true; + break; + } + } + if (stop) break; + } + // + maxY = height - 1; + for (sint y = height - 1; y >= 0; --y) + { + bool stop = false; + maxY = (uint) y; + for (uint x = 0; x < width; ++x) + { + if(pixels[x + y * width].A != 0) + { + stop = true; + break; + } + } + if (stop) break; + } + // + CCursor &curs = _Cursors[name]; + curs = CCursor(); // erase possible previous cursor + + uint destWidth; + uint destHeight; + + destWidth = GetSystemMetrics(SM_CXCURSOR); + destHeight = GetSystemMetrics(SM_CYCURSOR); + + // build a square bitmap + uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1); + curs.Src.resize(tmpSize, tmpSize); + // blit at top left corner + curs.Src.blit(cursorBitmap, minX, minY, maxX - minX + 1, maxY - minY + 1, 0, 0); + + curs.OrigHeight = cursorBitmap.getHeight(); + curs.HotspotOffsetX = minX; + curs.HotspotOffsetY = minY; + // + curs.HotspotScale = _CursorScale; + clamp(curs.HotspotScale, 0.f, 1.f); + // first resampling, same for all cursors + tmpSize = (uint) (tmpSize * curs.HotspotScale); + if (tmpSize == 0) tmpSize = 1; +/* + curs.Src.resample(tmpSize, tmpSize); +*/ + // shrink if necessary + if (tmpSize > destWidth || tmpSize > destHeight) // need to shrink ? + { + // constraint proportions + curs.HotspotScale *= std::min(float(destWidth) / tmpSize, float(destHeight) / tmpSize); + curs.Src.resample(destWidth, destHeight); + } + else + { + CBitmap final; + final.resize(destWidth, destHeight); + final.blit(&curs.Src, 0, 0); + curs.Src.swap(final); + } + + if (name == _CurrName) + { + updateCursor(); + } +} + +// ************************************************************************************* +void CDriverD3D::createCursors() +{ + _DefaultCursor = LoadCursor(NULL, IDC_ARROW); +} + +// ************************************************************************************* +void CDriverD3D::releaseCursors() +{ + SetClassLongPtr(_HWnd, GCLP_HCURSOR, 0); + + _Cursors.clear(); +} + +// ************************************************************************************* +void CDriverD3D::updateCursor(bool forceRebuild) +{ + setCursor(_CurrName, _CurrCol, _CurrRot, _CurrHotSpotX, _CurrHotSpotY, forceRebuild); +} + +// ************************************************************************************* +void CDriverD3D::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild) +{ + // don't update cursor if it's hidden or if custom cursors are not suppported + if (!isAlphaBlendedCursorSupported() || _CurrName == "none") return; + + _CurrName = name; + _CurrCol = col; + _CurrRot = rot; + _CurrHotSpotX = hotSpotX; + _CurrHotSpotY = hotSpotY; + + // cursor has to be changed next time + if (_CurrName.empty()) return; + + if (rot > 3) rot = 3; // same than 'CViewRenderer::drawRotFlipBitmapTiled + + TCursorMap::iterator it = _Cursors.find(name); + + nlCursor cursorHandle = _DefaultCursor; + + if (it != _Cursors.end()) + { + // Update cursor if modified or not already built + CCursor &curs = it->second; + hotSpotX = (sint) (curs.HotspotScale * (hotSpotX - curs.HotspotOffsetX)); + hotSpotY = (sint) (curs.HotspotScale * ((curs.OrigHeight - hotSpotY) - curs.HotspotOffsetY)); + if (curs.Cursor == EmptyCursor || + curs.HotSpotX != hotSpotX || + curs.HotSpotY != hotSpotY || + curs.Col != col || + curs.Rot != rot || + curs.ColorDepth != _ColorDepth || + forceRebuild + ) + { + curs.reset(); + curs.Cursor = buildCursor(curs.Src, col, rot, hotSpotX, hotSpotY); + curs.Col = col; + curs.Rot = rot; + curs.HotSpotX = hotSpotX; + curs.HotSpotY = hotSpotY; + curs.ColorDepth = _ColorDepth; + } + cursorHandle = curs.Cursor ? curs.Cursor : _DefaultCursor; + } + + if (isSystemCursorInClientArea() || isSystemCursorCaptured() || forceRebuild) + { +// if (CInputHandlerManager::getInstance()->hasFocus()) + { + ::SetCursor(cursorHandle); + SetClassLongPtr(_HWnd, GCLP_HCURSOR, (LONG_PTR) cursorHandle); // set default mouse icon to the last one + } + } + +} + +// ************************************************************************************* +nlCursor CDriverD3D::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY) +{ + nlassert(isAlphaBlendedCursorSupported()); + + uint mouseW; + uint mouseH; + + // use cursor size from system + mouseW = GetSystemMetrics(SM_CXCURSOR); + mouseH = GetSystemMetrics(SM_CYCURSOR); + + CBitmap rotSrc = src; + if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...) + switch(rot) + { + case 0: break; + case 1: rotSrc.rot90CW(); break; + case 2: rotSrc.rot90CW(); rotSrc.rot90CW(); break; + case 3: rotSrc.rot90CCW(); break; + } + + // create a cursor from bitmap + nlCursor result = NULL; + convertBitmapToCursor(rotSrc, result, mouseW, mouseH, _ColorDepth == ColorDepth16 ? 16:32, col, hotSpotX, hotSpotY); + return result; +} + + +// ************************************************************************************* +void CDriverD3D::setSystemArrow() +{ + H_AUTO_D3D(CDriverD3D_setSystemArrow); + + if (isSystemCursorInClientArea() || isSystemCursorCaptured()) + { + SetCursor(_DefaultCursor); + } + + // set default mouse icon to the default one + SetClassLongPtr(_HWnd, GCLP_HCURSOR, (LONG_PTR) _DefaultCursor); +} + +// *************************************************************************** +void CDriverD3D::showCursor(bool b) { H_AUTO_D3D(CDriverD3D_showCursor); + + if (_HWnd == EmptyWindow) + return; + if (b) { - while (ShowCursor(b) < 0) {} + // update current hardware icon to avoid to have the plain arrow + updateCursor(true); + + while (ShowCursor(b) < 0) + ; } else { - while (ShowCursor(b) >= 0) {} + while (ShowCursor(b) >= 0) + ; } -}; +} // *************************************************************************** - void CDriverD3D::setMousePos(float x, float y) { - H_AUTO_D3D(CDriver3D_setMousePos); - if (_HWnd) - { - // NeL window coordinate to MSWindows coordinates - POINT pt; - pt.x = (int)((float)(_CurrentMode.Width)*x); - pt.y = (int)((float)(_CurrentMode.Height)*(1.0f-y)); - ClientToScreen (_HWnd, &pt); - SetCursorPos(pt.x, pt.y); - } + H_AUTO_D3D(CDriverD3D_setMousePos); + + if (_HWnd == EmptyWindow) + return; + + sint x1 = (sint)((float)_CurrentMode.Width*x); + sint y1 = (sint)((float)_CurrentMode.Height*(1.0f-y)); + + // NeL window coordinate to MSWindows coordinates + POINT pt; + pt.x = x1; + pt.y = y1; + ClientToScreen (_HWnd, &pt); + SetCursorPos(pt.x, pt.y); } // *************************************************************************** +bool CDriverD3D::isSystemCursorInClientArea() +{ + if (_FullScreen /* || !IsMouseCursorHardware() */) + { + return IsWindowVisible(_HWnd) != FALSE; + } + else + { + POINT cursPos; + // the mouse should be in the client area of the window + if (!GetCursorPos(&cursPos)) + { + return false; + } + HWND wnd = WindowFromPoint(cursPos); + if (wnd != _HWnd) + { + return false; // not the same window + } + // want that the mouse be in the client area + RECT clientRect; + if (!GetClientRect(_HWnd, &clientRect)) + { + return false; + } + POINT tl, br; + tl.x = clientRect.left; + tl.y = clientRect.top; + br.x = clientRect.right; + br.y = clientRect.bottom; + if (!ClientToScreen(_HWnd, &tl)) + { + return false; + } + if (!ClientToScreen(_HWnd, &br)) + { + return false; + } + if ((cursPos.x < tl.x) || (cursPos.x >= br.x) || (cursPos.y < tl.y) || (cursPos.y >= br.y)) + { + return false; + } + } + return true; +} + +// *************************************************************************** void CDriverD3D::setCapture (bool b) { - if (b) + H_AUTO_D3D(CDriverD3D_setCapture); + + if (b && isSystemCursorInClientArea() && !isSystemCursorCaptured()) { - RECT client; - GetClientRect (_HWnd, &client); - POINT pt1,pt2; - pt1.x = client.left; - pt1.y = client.top; - ClientToScreen (_HWnd, &pt1); - pt2.x = client.right; - pt2.y = client.bottom; - ClientToScreen (_HWnd, &pt2); - client.bottom = pt2.y; - client.top = pt1.y; - client.left = pt1.x; - client.right = pt2.x; - ClipCursor (&client); + 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(); } - else - ClipCursor (NULL); } // *************************************************************************** +bool CDriverD3D::isSystemCursorCaptured() +{ + H_AUTO_D3D(CDriverD3D_isSystemCursorCaptured); -NLMISC::IMouseDevice *CDriverD3D::enableLowLevelMouse(bool enable, bool exclusive) + return GetCapture() == _HWnd; +} + +// *************************************************************************** +NLMISC::IMouseDevice* CDriverD3D::enableLowLevelMouse(bool enable, bool exclusive) { H_AUTO_D3D(CDriverD3D_enableLowLevelMouse); - if (_EventEmitter.getNumEmitters() < 2) - return NULL; - NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); + + NLMISC::IMouseDevice *res = NULL; + + NLMISC::CDIEventEmitter *diee = NULL; + + if (_EventEmitter.getNumEmitters() > 1) + diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); + if (enable) { try { - NLMISC::IMouseDevice *md = diee->getMouseDevice(exclusive); - return md; + if (diee) + res = diee->getMouseDevice(exclusive); } catch (EDirectInput &) { - return NULL; } } else { - diee->releaseMouse(); - return NULL; + if (diee) + diee->releaseMouse(); } + + return res; } // *************************************************************************** - -NLMISC::IKeyboardDevice *CDriverD3D::enableLowLevelKeyboard(bool enable) +NLMISC::IKeyboardDevice* CDriverD3D::enableLowLevelKeyboard(bool enable) { H_AUTO_D3D(CDriverD3D_enableLowLevelKeyboard); - if (_EventEmitter.getNumEmitters() < 2) return NULL; - NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); + + NLMISC::IKeyboardDevice *res = NULL; + + NLMISC::CDIEventEmitter *diee = NULL; + + if (_EventEmitter.getNumEmitters() > 1) + diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); + if (enable) { try { - NLMISC::IKeyboardDevice *md = diee->getKeyboardDevice(); - return md; + if (diee) + res = diee->getKeyboardDevice(); } catch (EDirectInput &) { - return NULL; } } else { - diee->releaseKeyboard(); - return NULL; + if (diee) + diee->releaseKeyboard(); } + + return res; } // *************************************************************************** - -NLMISC::IInputDeviceManager *CDriverD3D::getLowLevelInputDeviceManager() +NLMISC::IInputDeviceManager* CDriverD3D::getLowLevelInputDeviceManager() { H_AUTO_D3D(CDriverD3D_getLowLevelInputDeviceManager); - if (_EventEmitter.getNumEmitters() < 2) return NULL; - NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - return diee; + + NLMISC::IInputDeviceManager *res = NULL; + + if (_EventEmitter.getNumEmitters() > 1) + res = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); + + return res; } // *************************************************************************** - uint CDriverD3D::getDoubleClickDelay(bool hardwareMouse) { H_AUTO_D3D(CDriverD3D_getDoubleClickDelay); + + uint res = 250; + NLMISC::IMouseDevice *md = NULL; + if (_EventEmitter.getNumEmitters() >= 2) { NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); @@ -166,14 +564,18 @@ uint CDriverD3D::getDoubleClickDelay(bool hardwareMouse) } } } + if (md) { - return md->getDoubleClickDelay(); + res = md->getDoubleClickDelay(); } - // try to read the good value from windows - return ::GetDoubleClickTime(); + else + { + // try to read the good value from windows + res = ::GetDoubleClickTime(); + } + + return res; } -// *************************************************************************** - } // NL3D diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.cpp b/code/nel/src/3d/driver/opengl/driver_opengl.cpp index 3b7a2a1d3..c592f24cf 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp @@ -202,7 +202,6 @@ CDriverGL::CDriverGL() #elif defined (NL_OS_UNIX) - _cursor = None; _dpy = 0; _visual_info = NULL; @@ -213,6 +212,20 @@ CDriverGL::CDriverGL() #endif // NL_OS_UNIX + _ColorDepth = ColorDepth32; + + _DefaultCursor = EmptyCursor; + _BlankCursor = EmptyCursor; + + _AlphaBlendedCursorSupported = false; + _AlphaBlendedCursorSupportRetrieved = false; + _CurrCol = CRGBA::White; + _CurrRot = 0; + _CurrHotSpotX = 0; + _CurrHotSpotY = 0; + _CursorScale = 0.85f; + _MouseCaptured = false; + _NeedToRestaureGammaRamp = false; _Interval = 1; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.h b/code/nel/src/3d/driver/opengl/driver_opengl.h index 1dbf9cc23..8ab0b3f6a 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl.h @@ -116,14 +116,20 @@ class COcclusionQueryGL; #ifdef NL_OS_WINDOWS bool GlWndProc(CDriverGL *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +typedef HCURSOR nlCursor; +#define EmptyCursor NULL #elif defined (NL_OS_MAC) bool GlWndProc(CDriverGL *driver, const void* e); +typedef void* nlCursor; +#define EmptyCursor NULL #elif defined (NL_OS_UNIX) bool GlWndProc(CDriverGL *driver, XEvent &e); +typedef Cursor nlCursor; +#define EmptyCursor None #endif @@ -514,6 +520,17 @@ public: virtual void setCapture (bool b); + // see if system cursor is currently captured + virtual bool isSystemCursorCaptured(); + + virtual void setHardwareCursorScale(float scale) { _CursorScale = scale; } + + // Add a new cursor (name is case unsensitive) + virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap); + + // Display a cursor from its name (case unsensitive) + virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false); + virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive); virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable); @@ -692,8 +709,65 @@ private: sint32 _DecorationWidth; sint32 _DecorationHeight; + // cursors + enum TColorDepth { ColorDepth16 = 0, ColorDepth32, ColorDepthCount }; + + TColorDepth _ColorDepth; + std::string _CurrName; + NLMISC::CRGBA _CurrCol; + uint8 _CurrRot; + uint _CurrHotSpotX; + uint _CurrHotSpotY; + float _CursorScale; + bool _MouseCaptured; + + nlCursor _DefaultCursor; + nlCursor _BlankCursor; + + bool _AlphaBlendedCursorSupported; + bool _AlphaBlendedCursorSupportRetrieved; + + class CCursor + { + public: + NLMISC::CBitmap Src; + TColorDepth ColorDepth; + uint OrigHeight; + float HotspotScale; + uint HotspotOffsetX; + uint HotspotOffsetY; + sint HotSpotX; + sint HotSpotY; + nlCursor Cursor; + NLMISC::CRGBA Col; + uint8 Rot; +#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC) + Display *Dpy; +#endif + public: + CCursor(); + ~CCursor(); + CCursor& operator= (const CCursor& from); + + void reset(); + }; + + struct CStrCaseUnsensitiveCmp + { + bool operator()(const std::string &lhs, const std::string &rhs) const + { + return NLMISC::nlstricmp(lhs, rhs) < 0; + } + }; + + typedef std::map TCursorMap; + + TCursorMap _Cursors; + #ifdef NL_OS_WINDOWS + bool convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col = NLMISC::CRGBA::White, sint hotSpotX = 0, sint hotSpotY = 0, bool cursor = false); + friend bool GlWndProc(CDriverGL *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); HDC _hDC; @@ -724,11 +798,12 @@ private: #elif defined (NL_OS_UNIX) + bool convertBitmapToIcon(const NLMISC::CBitmap &bitmap, std::vector &icon); + friend bool GlWndProc(CDriverGL *driver, XEvent &e); Display* _dpy; GLXContext _ctx; - Cursor _cursor; NLMISC::CUnixEventEmitter _EventEmitter; XVisualInfo* _visual_info; uint32 _xrandr_version; @@ -908,6 +983,32 @@ private: bool saveScreenMode(); bool setScreenMode(const GfxMode &mode); + // Test if cursor is in the client area. always true when software cursor is used and window visible + // (displayed in software when DirectInput is used) + bool isSystemCursorInClientArea(); + + // Check if RGBA cursors are supported + bool isAlphaBlendedCursorSupported(); + + // Update cursor appearance + void updateCursor(bool forceRebuild = false); + + // Create default cursors + void createCursors(); + + // Release all cursors + void releaseCursors(); + + // 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); + + // 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); + + // reset the cursor shape to the system arrow + void setSystemArrow(); + // Get the proj matrix setupped in GL void refreshProjMatrixFromGL(); diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp new file mode 100644 index 000000000..9f3f050d6 --- /dev/null +++ b/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp @@ -0,0 +1,808 @@ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdopengl.h" +#include "driver_opengl.h" + +#ifdef NL_OS_WINDOWS +# include +#elif defined(NL_OS_MAC) +#elif defined (NL_OS_UNIX) +# include +# include +# include +#endif // NL_OS_UNIX + +#include "nel/misc/mouse_device.h" +#include "nel/misc/di_event_emitter.h" +#include "nel/3d/u_driver.h" +#include "nel/misc/file.h" + +using namespace std; +using namespace NLMISC; + +namespace NL3D +{ + +// ************************************************************************************* +CDriverGL::CCursor::CCursor() : ColorDepth(CDriverGL::ColorDepth32), + OrigHeight(32), + HotspotScale(1.f), + HotspotOffsetX(0), + HotspotOffsetY(0), + HotSpotX(0), + HotSpotY(0), + Cursor(EmptyCursor), + Col(CRGBA::White), + Rot(0) +{ +#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC) + Dpy = NULL; +#endif +} + +// ************************************************************************************* +CDriverGL::CCursor::~CCursor() +{ + reset(); +} + +// ************************************************************************************* +void CDriverGL::CCursor::reset() +{ + if (Cursor != EmptyCursor) + { +#ifdef NL_OS_WINDOWS + DestroyIcon(Cursor); +#elif defined(NL_OS_MAC) +#elif defined(NL_OS_UNIX) + XFreeCursor(Dpy, Cursor); + XSync(Dpy, False); +#endif + } +} + +// ************************************************************************************* +CDriverGL::CCursor& CDriverGL::CCursor::operator= (const CDriverGL::CCursor& from) +{ + if (&from == this) + return *this; + Src = from.Src; // requires more than a surface copy + OrigHeight = from.OrigHeight; + HotspotScale = from.HotspotScale; + HotspotOffsetX = from.HotspotOffsetX; + HotspotOffsetY = from.HotspotOffsetY; + HotSpotX = from.HotSpotX; + HotSpotY = from.HotSpotY; + Cursor = from.Cursor; + Col = from.Col; + Rot = from.Rot; +#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC) + Dpy = from.Dpy; +#endif + return *this; +} + +// ************************************************************************************* +bool CDriverGL::isAlphaBlendedCursorSupported() +{ + if (!_AlphaBlendedCursorSupportRetrieved) + { +#ifdef NL_OS_WINDOWS + // Support starts with windows 2000 (not only from XP as seen in most docs) + // NB : Additionnaly, could query D3D caps to know if + // color hardware cursor is supported, not only emulated, + // but can't be sure that using the win32 api 'SetCursor' uses the same resources + // So far, seems to be supported on any modern card used by the game anyway ... + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (GetVersionEx(&osvi)) + { + _AlphaBlendedCursorSupported = (osvi.dwMajorVersion >= 5); + } +#elif defined(NL_OS_MAC) +#elif defined(NL_OS_UNIX) + _AlphaBlendedCursorSupported = _xrender_version > 0; +#endif + + _AlphaBlendedCursorSupportRetrieved = true; + } + + return _AlphaBlendedCursorSupported; +} + +// ************************************************************************************* +void CDriverGL::addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap) +{ + if (!isAlphaBlendedCursorSupported()) return; + + nlassert(cursorBitmap.getWidth() != 0); + nlassert(cursorBitmap.getHeight() != 0); + + // find used part base on alpha, to avoid too much shrinking + const CRGBA *pixels = (const CRGBA *) &cursorBitmap.getPixels()[0]; + uint minX, maxX, minY, maxY; + uint width = cursorBitmap.getWidth(); + uint height = cursorBitmap.getHeight(); + // + minX = 0; + for (uint x = 0; x < width; ++x) + { + bool stop = false; + minX = x; + for (uint y = 0; y < height; ++y) + { + if(pixels[x + y * width].A != 0) + { + stop = true; + break; + } + } + if (stop) break; + } + // + maxX = width - 1; + for (sint x = width - 1; x >= 0; --x) + { + bool stop = false; + maxX = (uint) x; + for (uint y = 0; y < height; ++y) + { + if(pixels[x + y * width].A != 0) + { + stop = true; + break; + } + } + if (stop) break; + } + // + minY = 0; + for (uint y = 0; y < height; ++y) + { + bool stop = false; + minY = y; + for (uint x = 0; x < width; ++x) + { + if(pixels[x + y * width].A != 0) + { + stop = true; + break; + } + } + if (stop) break; + } + // + maxY = height - 1; + for (sint y = height - 1; y >= 0; --y) + { + bool stop = false; + maxY = (uint) y; + for (uint x = 0; x < width; ++x) + { + if(pixels[x + y * width].A != 0) + { + stop = true; + break; + } + } + if (stop) break; + } + // + 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 + + // build a square bitmap + uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1); + curs.Src.resize(tmpSize, tmpSize); + // blit at top left corner + curs.Src.blit(cursorBitmap, minX, minY, maxX - minX + 1, maxY - minY + 1, 0, 0); + + curs.OrigHeight = cursorBitmap.getHeight(); + curs.HotspotOffsetX = minX; + curs.HotspotOffsetY = minY; + // + curs.HotspotScale = _CursorScale; + clamp(curs.HotspotScale, 0.f, 1.f); + // first resampling, same for all cursors + tmpSize = (uint) (tmpSize * curs.HotspotScale); + if (tmpSize == 0) tmpSize = 1; +/* + curs.Src.resample(tmpSize, tmpSize); +*/ + // shrink if necessary + if (tmpSize > destWidth || tmpSize > destHeight) // need to shrink ? + { + // constraint proportions + curs.HotspotScale *= std::min(float(destWidth) / tmpSize, float(destHeight) / tmpSize); + curs.Src.resample(destWidth, destHeight); + } + else + { + CBitmap final; + final.resize(destWidth, destHeight); + final.blit(&curs.Src, 0, 0); + curs.Src.swap(final); + } + + if (name == _CurrName) + { + updateCursor(); + } +} + +// ************************************************************************************* +void CDriverGL::createCursors() +{ +#ifdef NL_OS_WINDOWS + _DefaultCursor = LoadCursor(NULL, IDC_ARROW); + _BlankCursor = NULL; +#elif defined(NL_OS_MAC) +#elif defined(NL_OS_UNIX) + _DefaultCursor = None; + + // create blank cursor + char bm_no_data[] = { 0,0,0,0,0,0,0,0 }; + Pixmap pixmap_no_data = XCreateBitmapFromData (_dpy, _win, bm_no_data, 8, 8); + XColor black; + memset(&black, 0, sizeof (XColor)); + black.flags = DoRed | DoGreen | DoBlue; + _BlankCursor = XCreatePixmapCursor (_dpy, pixmap_no_data, pixmap_no_data, &black, &black, 0, 0); + XFreePixmap(_dpy, pixmap_no_data); +#endif +} + +// ************************************************************************************* +void CDriverGL::releaseCursors() +{ +#ifdef NL_OS_WINDOWS + SetClassLongPtr(_win, GCLP_HCURSOR, 0); +#elif defined(NL_OS_MAC) +#elif defined(NL_OS_UNIX) + XUndefineCursor(_dpy, _win); + XFreeCursor(_dpy, _BlankCursor); +#endif + + _Cursors.clear(); +} + +// ************************************************************************************* +void CDriverGL::updateCursor(bool forceRebuild) +{ + setCursor(_CurrName, _CurrCol, _CurrRot, _CurrHotSpotX, _CurrHotSpotY, forceRebuild); +} + +// ************************************************************************************* +void CDriverGL::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild) +{ + // don't update cursor if it's hidden or if custom cursors are not suppported + if (!isAlphaBlendedCursorSupported() || _CurrName == "none") return; + + _CurrName = name; + _CurrCol = col; + _CurrRot = rot; + _CurrHotSpotX = hotSpotX; + _CurrHotSpotY = hotSpotY; + + // cursor has to be changed next time + if (_CurrName.empty()) return; + + if (rot > 3) rot = 3; // same than 'CViewRenderer::drawRotFlipBitmapTiled + + TCursorMap::iterator it = _Cursors.find(name); + + nlCursor cursorHandle = _DefaultCursor; + + if (it != _Cursors.end()) + { + // Update cursor if modified or not already built + CCursor &curs = it->second; + hotSpotX = (sint) (curs.HotspotScale * (hotSpotX - curs.HotspotOffsetX)); + hotSpotY = (sint) (curs.HotspotScale * ((curs.OrigHeight - hotSpotY) - curs.HotspotOffsetY)); + if (curs.Cursor == EmptyCursor || + curs.HotSpotX != hotSpotX || + curs.HotSpotY != hotSpotY || + curs.Col != col || + curs.Rot != rot || + curs.ColorDepth != _ColorDepth || + forceRebuild + ) + { + curs.reset(); + curs.Cursor = buildCursor(curs.Src, col, rot, hotSpotX, hotSpotY); + curs.Col = col; + curs.Rot = rot; + curs.HotSpotX = hotSpotX; + curs.HotSpotY = hotSpotY; + curs.ColorDepth = _ColorDepth; +#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC) + curs.Dpy = _dpy; +#endif + } + cursorHandle = curs.Cursor ? curs.Cursor : _DefaultCursor; + } + + if (isSystemCursorInClientArea() || isSystemCursorCaptured() || forceRebuild) + { +// if (CInputHandlerManager::getInstance()->hasFocus()) +#ifdef NL_OS_WINDOWS + { + ::SetCursor(cursorHandle); + SetClassLongPtr(_win, GCLP_HCURSOR, (LONG_PTR) cursorHandle); // set default mouse icon to the last one + } +#elif defined(NL_OS_MAC) +#elif defined(NL_OS_UNIX) + if (cursorHandle == _DefaultCursor) + { + XUndefineCursor(_dpy, _win); + } + else + { + XDefineCursor(_dpy, _win, cursorHandle); + } +#endif + } + +} + +// ************************************************************************************* +nlCursor CDriverGL::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY) +{ + 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 + + CBitmap rotSrc = src; + if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...) + switch(rot) + { + case 0: break; + case 1: rotSrc.rot90CW(); break; + case 2: rotSrc.rot90CW(); rotSrc.rot90CW(); break; + case 3: rotSrc.rot90CCW(); break; + } + + // create a cursor from bitmap + nlCursor result = NULL; + convertBitmapToCursor(rotSrc, result, mouseW, mouseH, _ColorDepth == ColorDepth16 ? 16:32, col, hotSpotX, hotSpotY); + return result; +} + + +// ************************************************************************************* +void CDriverGL::setSystemArrow() +{ + H_AUTO_OGL(CDriverGL_setSystemArrow); + +#ifdef NL_OS_WINDOWS + if (isSystemCursorInClientArea() || isSystemCursorCaptured()) + { + SetCursor(_DefaultCursor); + } + + // set default mouse icon to the default one + SetClassLongPtr(_win, GCLP_HCURSOR, (LONG_PTR) _DefaultCursor); +#elif defined(NL_OS_MAC) +#elif defined(NL_OS_UNIX) + XUndefineCursor(_dpy, _win); +#endif +} + +// -------------------------------------------------- +void CDriverGL::showCursor(bool b) +{ + H_AUTO_OGL(CDriverGL_showCursor); + + if (_win == EmptyWindow) + return; + +#ifdef NL_OS_WINDOWS + + if (b) + { + // update current hardware icon to avoid to have the plain arrow + updateCursor(true); + + while (ShowCursor(b) < 0) + ; + } + else + { + while (ShowCursor(b) >= 0) + ; + } + +#elif defined(NL_OS_MAC) + + // Mac OS manages a show/hide counter for the cursor, so hiding the cursor + // twice requires two calls to "show" to make the cursor visible again. + // Since other platforms seem to not do this, the functionality is masked here + // by only calling hide if the cursor is visible and only calling show if + // the cursor was hidden. + + CGDisplayErr error = kCGErrorSuccess; + static bool visible = true; + + if(b && !visible) + { + error = CGDisplayShowCursor(kCGDirectMainDisplay); + visible = true; + } + else if(!b && visible) + { + error = CGDisplayHideCursor(kCGDirectMainDisplay); + visible = false; + } + + if(error != kCGErrorSuccess) + nlerror("cannot show / hide cursor"); + +#elif defined (NL_OS_UNIX) + + if (!b) + { + XDefineCursor(_dpy, _win, _BlankCursor); + _CurrName = "none"; + } + else + { + _CurrName = ""; + } + + // update current hardware icon to avoid to have the plain arrow + updateCursor(true); + +#endif // NL_OS_UNIX +} + +// -------------------------------------------------- +void CDriverGL::setMousePos(float x, float y) +{ + H_AUTO_OGL(CDriverGL_setMousePos) + + if (_win == EmptyWindow) + return; + + sint x1 = (sint)((float)_CurrentMode.Width*x); + sint y1 = (sint)((float)_CurrentMode.Height*(1.0f-y)); + +#ifdef NL_OS_WINDOWS + + // NeL window coordinate to MSWindows coordinates + POINT pt; + pt.x = x1; + pt.y = y1; + ClientToScreen (_win, &pt); + SetCursorPos(pt.x, pt.y); + +#elif defined(NL_OS_MAC) + + // CG wants absolute coordinates related to first screen's top left + + // get the first screen's (conaints menubar) rect (this is not mainScreen) + NSRect firstScreenRect = [[[NSScreen screens] objectAtIndex:0] frame]; + + // get the rect (position, size) of the window + NSRect windowRect; + if([containerView() isInFullScreenMode]) + windowRect = [[[containerView() window] screen] frame]; + else + windowRect = [[containerView() window] frame]; + + // get the view's rect for height and width + NSRect viewRect = [containerView() frame]; + + // set the cursor position + CGDisplayErr error = CGDisplayMoveCursorToPoint( + kCGDirectMainDisplay, CGPointMake( + windowRect.origin.x + (viewRect.size.width * x), + firstScreenRect.size.height - windowRect.origin.y - + viewRect.size.height + ((1.0 - y) * viewRect.size.height))); + + if(error != kCGErrorSuccess) + nlerror("cannot set mouse position"); + +#elif defined (NL_OS_UNIX) + + XWarpPointer (_dpy, None, _win, None, None, None, None, x1, y1); + +#endif // NL_OS_UNIX +} + +void CDriverGL::setCapture (bool b) +{ + H_AUTO_OGL(CDriverGL_setCapture ) + +#ifdef NL_OS_WINDOWS + + if (b && isSystemCursorInClientArea() && !isSystemCursorCaptured()) + { + SetCapture(_win); + } + 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(); + } + +#elif defined(NL_OS_MAC) + + // no need to capture + _MouseCaptured = b; + +#elif defined (NL_OS_UNIX) + + if(b /* && isSystemCursorInClientArea() && !isSystemCursorCaptured()*/) // capture the cursor. + { + // capture the cursor + XGrabPointer(_dpy, _win, True, 0, GrabModeAsync, GrabModeAsync, _win, None, CurrentTime); + _MouseCaptured = true; + } + else if (!b/* && isSystemCursorCaptured()*/) + { + // release the cursor + XUngrabPointer(_dpy, CurrentTime); + _MouseCaptured = false; + } + +#endif // NL_OS_UNIX +} + +bool CDriverGL::isSystemCursorInClientArea() +{ + if (_FullScreen /* || !IsMouseCursorHardware() */) + { +#ifdef NL_OS_WINDOWS + return IsWindowVisible(_win) != FALSE; +#endif + } + else + { +#ifdef NL_OS_WINDOWS + POINT cursPos; + // the mouse should be in the client area of the window + if (!GetCursorPos(&cursPos)) + { + return false; + } + HWND wnd = WindowFromPoint(cursPos); + if (wnd != _win) + { + return false; // not the same window + } + // want that the mouse be in the client area + RECT clientRect; + if (!GetClientRect(_win, &clientRect)) + { + return false; + } + POINT tl, br; + tl.x = clientRect.left; + tl.y = clientRect.top; + br.x = clientRect.right; + br.y = clientRect.bottom; + if (!ClientToScreen(_win, &tl)) + { + return false; + } + if (!ClientToScreen(_win, &br)) + { + return false; + } + if ((cursPos.x < tl.x) || (cursPos.x >= br.x) || (cursPos.y < tl.y) || (cursPos.y >= br.y)) + { + return false; + } +#endif + } + + return true; +} + +// *************************************************************************** +bool CDriverGL::isSystemCursorCaptured() +{ + H_AUTO_OGL(CDriverGL_isSystemCursorCaptured); + +#ifdef NL_OS_WINDOWS + return GetCapture() == _win; +#else + return _MouseCaptured; +#endif +} + +// *************************************************************************** +NLMISC::IMouseDevice* CDriverGL::enableLowLevelMouse(bool enable, bool exclusive) +{ + H_AUTO_OGL(CDriverGL_enableLowLevelMouse); + + NLMISC::IMouseDevice *res = NULL; + +#ifdef NL_OS_WINDOWS + + NLMISC::CDIEventEmitter *diee = NULL; + + if (_EventEmitter.getNumEmitters() > 1) + diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); + + if (enable) + { + try + { + if (diee) + res = diee->getMouseDevice(exclusive); + } + catch (EDirectInput &) + { + } + } + else + { + if (diee) + diee->releaseMouse(); + } + +#elif defined(NL_OS_MAC) +#elif defined (NL_OS_UNIX) +#endif + + return res; +} + +// *************************************************************************** +NLMISC::IKeyboardDevice* CDriverGL::enableLowLevelKeyboard(bool enable) +{ + H_AUTO_OGL(CDriverGL_enableLowLevelKeyboard); + + NLMISC::IKeyboardDevice *res = NULL; + +#ifdef NL_OS_WINDOWS + + NLMISC::CDIEventEmitter *diee = NULL; + + if (_EventEmitter.getNumEmitters() > 1) + diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); + + if (enable) + { + try + { + if (diee) + res = diee->getKeyboardDevice(); + } + catch (EDirectInput &) + { + } + } + else + { + if (diee) + diee->releaseKeyboard(); + } + +#elif defined(NL_OS_MAC) +#elif defined (NL_OS_UNIX) +#endif + + return res; +} + +// *************************************************************************** +NLMISC::IInputDeviceManager* CDriverGL::getLowLevelInputDeviceManager() +{ + H_AUTO_OGL(CDriverGL_getLowLevelInputDeviceManager); + + NLMISC::IInputDeviceManager *res = NULL; + +#ifdef NL_OS_WINDOWS + + if (_EventEmitter.getNumEmitters() > 1) + res = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); + +#elif defined(NL_OS_MAC) +#elif defined (NL_OS_UNIX) +#endif + + return res; +} + +// *************************************************************************** +uint CDriverGL::getDoubleClickDelay(bool hardwareMouse) +{ + H_AUTO_OGL(CDriverGL_getDoubleClickDelay); + + uint res = 250; + +#ifdef NL_OS_WINDOWS + + NLMISC::IMouseDevice *md = NULL; + + if (_EventEmitter.getNumEmitters() >= 2) + { + NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); + if (diee->isMouseCreated()) + { + try + { + md = diee->getMouseDevice(hardwareMouse); + } + catch (EDirectInput &) + { + // could not get device .. + } + } + } + + if (md) + { + res = md->getDoubleClickDelay(); + } + else + { + // try to read the good value from windows + res = ::GetDoubleClickTime(); + } + +#elif defined(NL_OS_MAC) +# warning "OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay" + nlwarning("OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay"); + +#elif defined (NL_OS_UNIX) + + // TODO for Linux + +#endif + + return res; +} + +} // 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 da1f919bf..3d23721be 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -272,6 +272,8 @@ bool CDriverGL::init (uint windowIcon, emptyProc exitFunc) ExitFunc = exitFunc; + createCursors(); + #ifdef NL_OS_WINDOWS WNDCLASSW wc; @@ -284,7 +286,7 @@ bool CDriverGL::init (uint windowIcon, emptyProc exitFunc) wc.cbWndExtra = 0; wc.hInstance = GetModuleHandle(NULL); wc.hIcon = (HICON)windowIcon; - wc.hCursor = LoadCursorA(NULL, IDC_ARROW); + wc.hCursor = _DefaultCursor; wc.hbrBackground = WHITE_BRUSH; wc.lpszClassName = L"NLClass"; wc.lpszMenuName = NULL; @@ -478,10 +480,10 @@ void CDriverGL::setWindowIcon(const std::vector &bitmaps) } if (smallIndex > -1) - winIconSmall = bitmaps[smallIndex].getHICON(smallWidth, smallHeight, 32); + convertBitmapToIcon(bitmaps[smallIndex], winIconSmall, smallWidth, smallHeight, 32); if (bigIndex > -1) - winIconBig = bitmaps[bigIndex].getHICON(bigWidth, bigHeight, 32); + convertBitmapToIcon(bitmaps[bigIndex], winIconBig, bigWidth, bigHeight, 32); if (winIconBig) { @@ -507,24 +509,7 @@ void CDriverGL::setWindowIcon(const std::vector &bitmaps) // process each bitmap for(uint i = 0; i < bitmaps.size(); ++i) { - // get bitmap width and height - uint width = bitmaps[i].getWidth(); - uint height = bitmaps[i].getHeight(); - - // icon_data position for bitmap - uint pos = (uint)icon_data.size(); - - // extend icon_data size for bitmap - icon_data.resize(pos + 2 + width*height); - - // set bitmap width and height - icon_data[pos++] = width; - icon_data[pos++] = height; - - // convert RGBA to ARGB - CObjectVector pixels = bitmaps[i].getPixels(); - for(uint j = 0; j < pixels.size(); j+=4) - icon_data[pos++] = pixels[j] << 16 | pixels[j+1] << 8 | pixels[j+2] | pixels[j+3] << 24; + convertBitmapToIcon(bitmaps[i], icon_data); } } @@ -1502,6 +1487,8 @@ bool CDriverGL::createWindow(const GfxMode &mode) setWindowTitle(ucstring("NeL window")); + createCursors(); + return true; } @@ -1511,6 +1498,8 @@ bool CDriverGL::destroyWindow() { H_AUTO_OGL(CDriverGL_destroyWindow) + releaseCursors(); + // make sure window icons are deleted std::vector bitmaps; setWindowIcon(bitmaps); @@ -1770,6 +1759,16 @@ bool CDriverGL::setMode(const GfxMode& mode) setWindowSize(mode.Width, mode.Height); setWindowPos(_WindowX, _WindowY); + switch (_Depth) + { + case 16: _ColorDepth = ColorDepth16; break; + case 24: + case 32: _ColorDepth = ColorDepth32; break; + } + + // set color depth for custom cursor + updateCursor(true); + return true; } @@ -2322,135 +2321,6 @@ IDriver::TMessageBoxId CDriverGL::systemMessageBox (const char* message, const c return okId; } -// -------------------------------------------------- -void CDriverGL::showCursor(bool b) -{ - H_AUTO_OGL(CDriverGL_showCursor) - - if (_win == EmptyWindow) - return; - -#ifdef NL_OS_WINDOWS - - if (b) - { - while (ShowCursor(b) < 0) - ; - } - else - { - while (ShowCursor(b) >= 0) - ; - } - -#elif defined(NL_OS_MAC) - - // Mac OS manages a show/hide counter for the cursor, so hiding the cursor - // twice requires two calls to "show" to make the cursor visible again. - // Since other platforms seem to not do this, the functionality is masked here - // by only calling hide if the cursor is visible and only calling show if - // the cursor was hidden. - - CGDisplayErr error = kCGErrorSuccess; - static bool visible = true; - - if(b && !visible) - { - error = CGDisplayShowCursor(kCGDirectMainDisplay); - visible = true; - } - else if(!b && visible) - { - error = CGDisplayHideCursor(kCGDirectMainDisplay); - visible = false; - } - - if(error != kCGErrorSuccess) - nlerror("cannot show / hide cursor"); - -#elif defined (NL_OS_UNIX) - - if (b) - { - if (_cursor != None) - { - XFreeCursor(_dpy, _cursor); - _cursor = None; - } - XUndefineCursor(_dpy, _win); - } - else - { - if (_cursor == None) - { - char bm_no_data[] = { 0,0,0,0, 0,0,0,0 }; - Pixmap pixmap_no_data = XCreateBitmapFromData (_dpy, _win, bm_no_data, 8, 8); - XColor black; - memset(&black, 0, sizeof (XColor)); - black.flags = DoRed | DoGreen | DoBlue; - _cursor = XCreatePixmapCursor (_dpy, pixmap_no_data, pixmap_no_data, &black, &black, 0, 0); - XFreePixmap(_dpy, pixmap_no_data); - } - XDefineCursor(_dpy, _win, _cursor); - } - -#endif // NL_OS_UNIX -} - -// -------------------------------------------------- -void CDriverGL::setMousePos(float x, float y) -{ - H_AUTO_OGL(CDriverGL_setMousePos) - - if (_win == EmptyWindow) - return; - - sint x1 = (sint)((float)_WindowWidth*x); - sint y1 = (sint)((float)_WindowHeight*(1.0f-y)); - -#ifdef NL_OS_WINDOWS - - // NeL window coordinate to MSWindows coordinates - POINT pt; - pt.x = x1; - pt.y = y1; - ClientToScreen (_win, &pt); - SetCursorPos(pt.x, pt.y); - -#elif defined(NL_OS_MAC) - - // CG wants absolute coordinates related to first screen's top left - - // get the first screen's (conaints menubar) rect (this is not mainScreen) - NSRect firstScreenRect = [[[NSScreen screens] objectAtIndex:0] frame]; - - // get the rect (position, size) of the window - NSRect windowRect; - if([containerView() isInFullScreenMode]) - windowRect = [[[containerView() window] screen] frame]; - else - windowRect = [[containerView() window] frame]; - - // get the view's rect for height and width - NSRect viewRect = [containerView() frame]; - - // set the cursor position - CGDisplayErr error = CGDisplayMoveCursorToPoint( - kCGDirectMainDisplay, CGPointMake( - windowRect.origin.x + (viewRect.size.width * x), - firstScreenRect.size.height - windowRect.origin.y - - viewRect.size.height + ((1.0 - y) * viewRect.size.height))); - - if(error != kCGErrorSuccess) - nlerror("cannot set mouse position"); - -#elif defined (NL_OS_UNIX) - - XWarpPointer (_dpy, None, _win, None, None, None, None, x1, y1); - -#endif // NL_OS_UNIX -} - void CDriverGL::getWindowSize(uint32 &width, uint32 &height) { H_AUTO_OGL(CDriverGL_getWindowSize) @@ -2622,206 +2492,6 @@ bool CDriverGL::isActive() return res; } -void CDriverGL::setCapture (bool b) -{ - H_AUTO_OGL(CDriverGL_setCapture ) - -#ifdef NL_OS_WINDOWS - - if (b) - { - RECT client; - GetClientRect (_win, &client); - POINT pt1,pt2; - pt1.x = client.left; - pt1.y = client.top; - ClientToScreen (_win, &pt1); - pt2.x = client.right; - pt2.y = client.bottom; - ClientToScreen (_win, &pt2); - client.bottom = pt2.y; - client.top = pt1.y; - client.left = pt1.x; - client.right = pt2.x; - ClipCursor (&client); - } - else - ClipCursor (NULL); - - /* - if (b) - SetCapture (_hWnd); - else - ReleaseCapture (); - */ - -#elif defined(NL_OS_MAC) - - // no need to capture - -#elif defined (NL_OS_UNIX) - - /* - TODO x11 funtion: setCapture - */ - - if(b) // capture the cursor. - { - XGrabPointer(_dpy, _win, True, 0, GrabModeAsync, GrabModeAsync, _win, None, CurrentTime); - } - else // release the cursor. - { - XUngrabPointer(_dpy, CurrentTime); - } - -#endif // NL_OS_UNIX -} - -// *************************************************************************** -NLMISC::IMouseDevice* CDriverGL::enableLowLevelMouse(bool enable, bool exclusive) -{ - H_AUTO_OGL(CDriverGL_enableLowLevelMouse) - - NLMISC::IMouseDevice *res = NULL; - -#ifdef NL_OS_WINDOWS - - NLMISC::CDIEventEmitter *diee = NULL; - - if (_EventEmitter.getNumEmitters() > 1) - diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - - if (enable) - { - try - { - if (diee) - res = diee->getMouseDevice(exclusive); - } - catch (EDirectInput &) - { - } - } - else - { - if (diee) - diee->releaseMouse(); - } - -#elif defined(NL_OS_MAC) -#elif defined (NL_OS_UNIX) -#endif - - return res; -} - -// *************************************************************************** -NLMISC::IKeyboardDevice* CDriverGL::enableLowLevelKeyboard(bool enable) -{ - H_AUTO_OGL(CDriverGL_enableLowLevelKeyboard) - - NLMISC::IKeyboardDevice *res = NULL; - -#ifdef NL_OS_WINDOWS - - NLMISC::CDIEventEmitter *diee = NULL; - - if (_EventEmitter.getNumEmitters() > 1) - diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - - if (enable) - { - try - { - if (diee) - res = diee->getKeyboardDevice(); - } - catch (EDirectInput &) - { - } - } - else - { - if (diee) - diee->releaseKeyboard(); - } - -#elif defined(NL_OS_MAC) -#elif defined (NL_OS_UNIX) -#endif - - return res; -} - -// *************************************************************************** -NLMISC::IInputDeviceManager* CDriverGL::getLowLevelInputDeviceManager() -{ - H_AUTO_OGL(CDriverGL_getLowLevelInputDeviceManager) - - NLMISC::IInputDeviceManager *res = NULL; - -#ifdef NL_OS_WINDOWS - - if (_EventEmitter.getNumEmitters() > 1) - res = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - -#elif defined(NL_OS_MAC) -#elif defined (NL_OS_UNIX) -#endif - - return res; -} - -// *************************************************************************** -uint CDriverGL::getDoubleClickDelay(bool hardwareMouse) -{ - H_AUTO_OGL(CDriverGL_getDoubleClickDelay) - - uint res = 250; - -#ifdef NL_OS_WINDOWS - - NLMISC::IMouseDevice *md = NULL; - - if (_EventEmitter.getNumEmitters() >= 2) - { - NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - if (diee->isMouseCreated()) - { - try - { - md = diee->getMouseDevice(hardwareMouse); - } - catch (EDirectInput &) - { - // could not get device .. - } - } - } - - if (md) - { - res = md->getDoubleClickDelay(); - } - else - { - // try to read the good value from windows - res = ::GetDoubleClickTime(); - } - -#elif defined(NL_OS_MAC) -# warning "OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay" - nlwarning("OpenGL Driver: Missing Mac Implementation for getDoubleClickDelay"); - -#elif defined (NL_OS_UNIX) - - // TODO for Linux - -#endif - - return res; -} - // *************************************************************************** bool CDriverGL::setMonitorColorProperties (const CMonitorColorProperties &properties) { @@ -2955,4 +2625,281 @@ bool CDriverGL::pasteTextFromClipboard(ucstring &text) return _EventEmitter.pasteTextFromClipboard(text); } +#ifdef NL_OS_WINDOWS + +bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY, bool cursor) +{ + 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]); + static volatile uint8 alphaThreshold = 127; + do + { + destColorPtr->modulateFromColor(*srcColorPtr, col); + std::swap(destColorPtr->R, destColorPtr->B); + ++ srcColorPtr; + ++ destColorPtr; + } + while (srcColorPtr != srcColorPtrLast); + // + HBITMAP colorHbm = NULL; + HBITMAP maskHbm = NULL; + // + if (iconDepth == 16) + { + std::vector colorBm16(iconWidth * iconHeight); + const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0]; + + for (uint k = 0; k < colorBm16.size(); ++k) + { + colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8); + } + + colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 16, &colorBm16[0]); + std::vector bitMask((iconWidth * iconHeight + 7) / 8, 0); + + for (uint k = 0;k < colorBm16.size(); ++k) + { + if (src32[k].A <= 120) + { + bitMask[k / 8] |= (0x80 >> (k & 7)); + } + } + + maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 1, &bitMask[0]); + } + else + { + colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]); + maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]); + } + + ICONINFO iconInfo; + iconInfo.fIcon = cursor ? FALSE:TRUE; + iconInfo.xHotspot = (DWORD) hotSpotX; + iconInfo.yHotspot = (DWORD) hotSpotY; + iconInfo.hbmMask = maskHbm; + iconInfo.hbmColor = colorHbm; + + if (colorHbm && maskHbm) + { + icon = CreateIconIndirect(&iconInfo); + } + + // + if (colorHbm) DeleteObject(colorHbm); + if (maskHbm) DeleteObject(maskHbm); + + 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_UNIX) + +bool CDriverGL::convertBitmapToIcon(const NLMISC::CBitmap &bitmap, std::vector &icon) +{ + // get bitmap width and height + uint width = bitmap.getWidth(); + uint height = bitmap.getHeight(); + + // icon position for bitmap + uint pos = (uint)icon.size(); + + // extend icon_data size for bitmap + icon.resize(pos + 2 + width*height); + + // set bitmap width and height + icon[pos++] = width; + icon[pos++] = height; + + // convert RGBA to ARGB + CObjectVector pixels = bitmap.getPixels(); + for(uint j = 0; j < pixels.size(); j+=4) + icon[pos++] = pixels[j] << 16 | pixels[j+1] << 8 | pixels[j+2] | pixels[j+3] << 24; + + return true; +} + +bool CDriverGL::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, Cursor &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* defVisual = DefaultVisual(_dpy, screen); + XImage* image = NULL; + + // create the icon pixmap + if (iconDepth == 16) + { + std::vector colorBm16(iconWidth * iconHeight); + + for (uint k = 0; k < colorBm16.size(); ++k) + { + colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8); + } + + image = XCreateImage(_dpy, defVisual, 16, ZPixmap, 0, (char*)colorBm16[0], iconWidth, iconHeight, 16, 0); + } + else + { + image = XCreateImage(_dpy, defVisual, 32, ZPixmap, 0, (char*)src32, iconWidth, iconHeight, 32, 0); + } + + if (!image) + { + nlwarning("Failed to set the window's icon"); + return false; + } + + Pixmap iconPixmap = XCreatePixmap(_dpy, _win, iconWidth, iconHeight, 32 /* defDepth */); + GC gc = XCreateGC(_dpy, iconPixmap, 0, NULL); + XPutImage(_dpy, iconPixmap, gc, image, 0, 0, 0, 0, iconWidth, iconHeight); + XFreeGC(_dpy, gc); + + if (image->data) + { + free(image->data); + image->data = NULL; + } + + XDestroyImage(image); + +/* + // Send our new icon to the window through the WMHints + XWMHints* Hints = XAllocWMHints(); + Hints->flags = IconPixmapHint | IconMaskHint; + Hints->icon_pixmap = iconPixmap; + Hints->icon_mask = maskPixmap; + XSetWMHints(ourDisplay, myWindow, Hints); + XFree(Hints); +*/ + + XRenderPictFormat *format = XRenderFindStandardFormat (_dpy, PictStandardARGB32); + Picture picture = XRenderCreatePicture (_dpy, iconPixmap, format, 0, 0); + + cursor = XRenderCreateCursor(_dpy, picture, (uint)hotSpotX, (uint)hotSpotY); + + XRenderFreePicture(_dpy, picture); + XFreePixmap(_dpy, iconPixmap); + + return true; + +#else + + return false; + +#endif +} + +/* +XRenderPictFormat* format = None; + + { + XRenderPictFormat alpha_format; + unsigned long mask = PictFormatType|PictFormatDepth|PictFormatAlpha|PictFormatAlphaMask; + alpha_format.type = PictTypeDirect; + alpha_format.depth = 8; + alpha_format.direct.alpha = 0; + alpha_format.direct.alphaMask = 0xff; + + format = XRenderFindFormat(dpy, mask, &alpha_format, 0); + } + + if (!format) { + printf("%s", "error, couldnt find valid format for alpha.\n"); + XFreePixmap(dpy, dst_pm); + XFreePixmap(dpy, src_pm); + return 0; + } + + { /* fill the alpha-picture */ + Pixmap alpha_pm = None; + + XRenderColor alpha_color; + XRenderPictureAttributes alpha_attr; + + alpha_color.alpha = 0xffff * (shade)/100; + + alpha_attr.repeat = True; + + alpha_pm = XCreatePixmap(dpy, src_pm, 1, 1, 8); + alpha_pic = XRenderCreatePicture(dpy, alpha_pm, format, CPRepeat, &alpha_attr); + XRenderFillRectangle(dpy, PictOpSrc, alpha_pic, &alpha_color, 0, 0, 1, 1); + XFreePixmap(dpy, alpha_pm); + } + + { /* blend all together */ + Picture src_pic; + Picture dst_pic; + + format = XRenderFindVisualFormat(dpy, vis); + + src_pic = XRenderCreatePicture(dpy, src_pm, format, 0, 0); + dst_pic = XRenderCreatePicture(dpy, dst_pm, format, 0, 0); + + XRenderComposite(dpy, PictOpOver, + src_pic, alpha_pic, dst_pic, + src_x, src_y, 0, 0, dst_x, dst_y, width, height); + XRenderFreePicture(dpy, src_pic); + XRenderFreePicture(dpy, dst_pic); + } +*/ + +#endif + } // NL3D diff --git a/code/nel/src/3d/driver_user.cpp b/code/nel/src/3d/driver_user.cpp index d6fccb362..b26a4b951 100644 --- a/code/nel/src/3d/driver_user.cpp +++ b/code/nel/src/3d/driver_user.cpp @@ -1643,6 +1643,26 @@ void CDriverUser::setCapture (bool b) _Driver->setCapture (b); } +bool CDriverUser::isSystemCursorCaptured() +{ + NL3D_HAUTO_UI_DRIVER; + + return _Driver->isSystemCursorCaptured(); +} + +void CDriverUser::addCursor(const std::string &name, const NLMISC::CBitmap &bitmap) +{ + NL3D_HAUTO_UI_DRIVER; + + _Driver->addCursor(name, bitmap); +} + +void CDriverUser::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild) +{ + NL3D_HAUTO_UI_DRIVER; + + _Driver->setCursor(name, col, rot, hotSpotX, hotSpotY, forceRebuild); +} // *************************************************************************** // *************************************************************************** diff --git a/code/nel/src/misc/bitmap.cpp b/code/nel/src/misc/bitmap.cpp index 4a97a004d..90afc460c 100644 --- a/code/nel/src/misc/bitmap.cpp +++ b/code/nel/src/misc/bitmap.cpp @@ -1614,9 +1614,6 @@ void CBitmap::releaseMipMaps() } } -bool TempMaxVerboseResample = false; -#define logResample if (TempMaxVerboseResample) nldebug - /*-------------------------------------------------------------------*\ resample \*-------------------------------------------------------------------*/ @@ -4107,84 +4104,5 @@ void CBitmap::getDibData(uint8*& extractData) } -#ifdef NL_OS_WINDOWS - -HICON CBitmap::getHICON(sint iconWidth, sint iconHeight, sint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY, bool cursor) const -{ - HICON result = NULL; - CBitmap src = *this; - // resample bitmap if necessary - if (_Width != iconWidth || _Height != 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]); - static volatile uint8 alphaThreshold = 127; - do - { - destColorPtr->modulateFromColor(*srcColorPtr, col); - std::swap(destColorPtr->R, destColorPtr->B); - ++ srcColorPtr; - ++ destColorPtr; - } - while (srcColorPtr != srcColorPtrLast); - // - HBITMAP colorHbm = NULL; - HBITMAP maskHbm = NULL; - // - if (iconDepth == 16) - { - std::vector colorBm16(iconWidth * iconHeight); - const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0]; - - for (uint k = 0; k < colorBm16.size(); ++k) - { - colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8); - } - - colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 16, &colorBm16[0]); - std::vector bitMask((iconWidth * iconHeight + 7) / 8, 0); - - for (uint k = 0;k < colorBm16.size(); ++k) - { - if (src32[k].A <= 120) - { - bitMask[k / 8] |= (0x80 >> (k & 7)); - } - } - - maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 1, &bitMask[0]); - } - else - { - colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]); - maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]); - } - - ICONINFO iconInfo; - iconInfo.fIcon = cursor ? FALSE:TRUE; - iconInfo.xHotspot = (DWORD) hotSpotX; - iconInfo.yHotspot = (DWORD) hotSpotY; - iconInfo.hbmMask = maskHbm; - iconInfo.hbmColor = colorHbm; - - if (colorHbm && maskHbm) - { - result = CreateIconIndirect(&iconInfo); - } - - // - if (colorHbm) DeleteObject(colorHbm); - if (maskHbm) DeleteObject(maskHbm); - - return result; -} - -#endif - } // NLMISC diff --git a/code/nel/src/misc/system_utils.cpp b/code/nel/src/misc/system_utils.cpp index 544adb7c4..238000426 100644 --- a/code/nel/src/misc/system_utils.cpp +++ b/code/nel/src/misc/system_utils.cpp @@ -352,56 +352,4 @@ uint CSystemUtils::getCurrentColorDepth() return depth; } -bool CSystemUtils::isSystemCursorInClientArea() -{ -#ifdef NL_OS_WINDOWS - if (s_window == NULL) - { - nlwarning("No window has be set with CSystemUtils::setWindow()"); - return false; - } - - POINT cursPos; - // the mouse should be in the client area of the window - if (!GetCursorPos(&cursPos)) - { - return false; - } - HWND wnd = WindowFromPoint(cursPos); - if (wnd != s_window) - { - return false; // not the same window - } - // want that the mouse be in the client area - RECT clientRect; - if (!GetClientRect(s_window, &clientRect)) - { - return false; - } - POINT tl, br; - tl.x = clientRect.left; - tl.y = clientRect.top; - br.x = clientRect.right; - br.y = clientRect.bottom; - if (!ClientToScreen(s_window, &tl)) - { - return false; - } - if (!ClientToScreen(s_window, &br)) - { - return false; - } - if (cursPos.x < tl.x || - cursPos.x >= br.x || - cursPos.y < tl.y || - cursPos.y >= br.y) - { - return false; - } -#else - // TODO for Linux and Mac OS -#endif - return true; -} - } // NLMISC diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index ff581b12b..5bdac0321 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -90,8 +90,6 @@ #include "login_progress_post_thread.h" -#include "interface_v3/custom_mouse.h" - #include "browse_faq.h" @@ -789,16 +787,6 @@ void prelogInit() FPU_CHECKER_ONCE - switch (getCurrentColorDepth()) - { - case 16: CustomMouse.setColorDepth(CCustomMouse::ColorDepth16); break; - case 24: - case 32: CustomMouse.setColorDepth(CCustomMouse::ColorDepth32); break; - default: - ExitClientError(CI18N::get("uiUnsupportedColorDepth").toUtf8().c_str()); - break; - } - // Check driver version checkDriverVersion(); diff --git a/code/ryzom/client/src/input.cpp b/code/ryzom/client/src/input.cpp index 668b1f15b..0d0e2c4ca 100644 --- a/code/ryzom/client/src/input.cpp +++ b/code/ryzom/client/src/input.cpp @@ -27,7 +27,6 @@ #include "interface_v3/input_handler_manager.h" #include "client_cfg.h" #include "time_client.h" -#include "interface_v3/custom_mouse.h" // 3D #include "nel/3d/u_driver.h" // Misc @@ -66,11 +65,6 @@ bool SetMousePosFirstTime = true; // mask for mouse buttons that are known to be down uint DownMouseButtons = 0; -#ifdef NL_OS_UNIX -// on X11 and cocoa, store whether the mouse was captured or not -bool MouseCapture = false; -#endif - ////////////// // FUNCTION // ////////////// @@ -128,12 +122,14 @@ bool InitMouseWithCursor (bool hardware) // Get the current mouse position if (hardware) { - if (CInterfaceManager::getInstance()->getPointer()) + Driver->showCursor(true); + + CViewPointer *pointer = CInterfaceManager::getInstance()->getPointer(); + if (pointer) { - float x = (float)CInterfaceManager::getInstance()->getPointer()->getX()/(float)Driver->getWindowWidth(); - float y = (float)CInterfaceManager::getInstance()->getPointer()->getY()/(float)Driver->getWindowHeight(); - CustomMouse.updateCursor(); // update current hardware icon to avoid to have the plain arrow - Driver->showCursor(true); + float x = (float)pointer->getX()/(float)Driver->getWindowWidth(); + float y = (float)pointer->getY()/(float)Driver->getWindowHeight(); + if (SetMousePosFirstTime) { SetMousePosFirstTime = false; @@ -141,12 +137,9 @@ bool InitMouseWithCursor (bool hardware) else { Driver->setMousePos(x, y); + nlwarning("mouse pos %f,%f", x, y); } - } - else - { - CustomMouse.updateCursor(); // update current hardware icon to avoid to have the plain arrow - Driver->showCursor(true); + } } else @@ -232,7 +225,7 @@ void UpdateMouse () Driver->emulateMouseRawMode(false); } } - if (!IsSystemCursorCaptured()) + if (!Driver->isSystemCursorCaptured()) { DownMouseButtons = 0; } @@ -246,7 +239,9 @@ void SetMouseFreeLook () { MouseFreeLook = true; if (MouseHardware) + { Driver->showCursor(false); + } else { CInterfaceManager *im = CInterfaceManager::getInstance(); @@ -306,9 +301,13 @@ void SetMouseCursor (bool updatePos) if (updatePos) { if (MouseDevice) + { MouseDevice->setMousePos((float)ix, (float)iy); + } else + { Driver->setMousePos(x, y); + } if (MouseHardware) { @@ -367,53 +366,6 @@ void SetMouseAcceleration (uint accel) UpdateMouse (); } -// ********************************************************************************* -void CaptureSystemCursor() -{ - if (IsSystemCursorCaptured()) return; -#ifdef NL_OS_WINDOWS - HWND drvWnd = Driver->getDisplay(); - if (!drvWnd) return; - SetCapture(drvWnd); -#else - // on X11 and cocoa, set driver mouse capture on and store it locally as well - Driver->setCapture(MouseCapture = true); -#endif -} - -// ********************************************************************************* -void ReleaseSystemCursor() -{ - if (!IsSystemCursorCaptured()) return; -#ifdef NL_OS_WINDOWS - // if hardware mouse and not in client area, then force to update its aspect by updating its pos - if (!IsSystemCursorInClientArea()) - { - // force update - ShowCursor(FALSE); - ShowCursor(TRUE); - } - ReleaseCapture(); -#else - // on X11 and cocoa, set driver mouse capture off and store it locally as well - Driver->setCapture(MouseCapture = false); -#endif -} - -// ********************************************************************************* -bool IsSystemCursorCaptured() -{ - if (!Driver) return false; -#ifdef NL_OS_WINDOWS - return GetCapture() == Driver->getDisplay(); -#else - /* - TODO there should be a way to ask the driver if capturing is on or off - */ - return MouseCapture; -#endif -} - // ********************************************************************************* void HandleSystemCursorCapture(const CEvent &event) { @@ -421,10 +373,7 @@ void HandleSystemCursorCapture(const CEvent &event) { CEventMouseDown &em = (CEventMouseDown &) event; DownMouseButtons |= em.Button & (leftButton | middleButton | rightButton); - if (IsSystemCursorInClientArea()) - { - CaptureSystemCursor(); - } + Driver->setCapture(true); } if (event == EventMouseUpId) @@ -434,7 +383,7 @@ void HandleSystemCursorCapture(const CEvent &event) DownMouseButtons &= ~(em.Button & (leftButton | middleButton | rightButton)); if (DownMouseButtons == 0) { - ReleaseSystemCursor(); + Driver->setCapture(false); } } @@ -445,66 +394,6 @@ void HandleSystemCursorCapture(const CEvent &event) } } -// ********************************************************************************* -bool IsSystemCursorInClientArea() -{ - if (!Driver) return false; -#ifdef NL_OS_WINDOWS - HWND drvWnd = Driver->getDisplay(); - if (!drvWnd) return false; - UDriver::CMode videoMode; - Driver->getCurrentScreenMode(videoMode); - if (!videoMode.Windowed || !IsMouseCursorHardware()) - { - // just test visibility - return IsWindowVisible(drvWnd) != FALSE; - } - else - { - POINT cursPos; - // the mouse should be in the client area of the window - if (!GetCursorPos(&cursPos)) - { - return false; - } - HWND wnd = WindowFromPoint(cursPos); - if (wnd != drvWnd) - { - return false; // not the same window - } - // want that the mouse be in the client area - RECT clientRect; - if (!GetClientRect(drvWnd, &clientRect)) - { - return false; - } - POINT tl, br; - tl.x = clientRect.left; - tl.y = clientRect.top; - br.x = clientRect.right; - br.y = clientRect.bottom; - if (!ClientToScreen(drvWnd, &tl)) - { - return false; - } - if (!ClientToScreen(drvWnd, &br)) - { - return false; - } - if (cursPos.x < tl.x || - cursPos.x >= br.x || - cursPos.y < tl.y || - cursPos.y >= br.y) - { - return false; - } - } -#else - // TODO for Linux and Mac OS -#endif - return true; -} - sint CNiceInputAuto::_Count = 0; @@ -516,7 +405,7 @@ CNiceInputAuto::CNiceInputAuto() Driver->enableLowLevelMouse(false, false); // but ignore direct input (win 32 msg only) - CustomMouse.setCursor("curs_default.tga", CRGBA::White, 0, 0x15, 0x18); + Driver->setCursor("curs_default.tga", CRGBA::White, 0, 0x15, 0x18); Driver->showCursor(true); // keep cursor visible in windowed mode MouseDevice = NULL; Driver->enableLowLevelKeyboard (false); diff --git a/code/ryzom/client/src/input.h b/code/ryzom/client/src/input.h index de189eae4..80185e04a 100644 --- a/code/ryzom/client/src/input.h +++ b/code/ryzom/client/src/input.h @@ -62,22 +62,9 @@ void SetMouseSpeed (float speed); // Use this method to set the cursor acceleration void SetMouseAcceleration (uint accel); -// capture the system cursor -void CaptureSystemCursor(); - -// release the system cursor -void ReleaseSystemCursor(); - -// see if system cursor is currently captured -bool IsSystemCursorCaptured(); - // handle capturing of mouse on button up / button down void HandleSystemCursorCapture(const NLMISC::CEvent &event); -// Test if cursor is in the client area. always true when software cursor is used and window visible -// (displayed in software when DirectInput is used) -bool IsSystemCursorInClientArea(); - // get state of mouse button, as a bitfield formatted like NLMISC::TMouseButton (modifier keys are not included) uint GetMouseButtonsState(); diff --git a/code/ryzom/client/src/interface_v3/custom_mouse.cpp b/code/ryzom/client/src/interface_v3/custom_mouse.cpp deleted file mode 100644 index c7d127803..000000000 --- a/code/ryzom/client/src/interface_v3/custom_mouse.cpp +++ /dev/null @@ -1,458 +0,0 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdpch.h" -#include "custom_mouse.h" -// -#include "../global.h" -#include "../input.h" -#include "input_handler_manager.h" - - -CCustomMouse CustomMouse; - -using namespace NLMISC; -using namespace NL3D; - -#ifdef NL_OS_WINDOWS - -// ************************************************************************************* -CCustomMouse::CCursor::CCursor() : ColorDepth(CCustomMouse::ColorDepth32), - OrigHeight(32), - HotspotScale(1.f), - HotspotOffsetX(0), - HotspotOffsetY(0), - HotSpotX(0), - HotSpotY(0), - Icon(0), - Col(CRGBA::White), - Rot(0) -{ -} - -// ************************************************************************************* -CCustomMouse::CCursor::~CCursor() -{ - if (Icon) - { - DestroyIcon(Icon); - } -} - -// ************************************************************************************* -CCustomMouse::CCustomMouse() -{ - _ColorDepth = CCustomMouse::ColorDepth32; - _DefaultCursor = LoadCursor(NULL, IDC_ARROW); - _AlphaBlendedCursorSupported = false; - _AlphaBlendedCursorSupportRetrieved = false; - _CurrCol = CRGBA::White; - _CurrRot = 0; - _CurrHotSpotX = 0; - _CurrHotSpotY = 0; -} - - - -// ************************************************************************************* -bool CCustomMouse::isAlphaBlendedCursorSupported() -{ - if (!_AlphaBlendedCursorSupportRetrieved) - { - // Support starts with windows 2000 (not only from XP as seen in most docs) - // NB : Additionnaly, could query D3D caps to know if - // color hardware cursor is supported, not only emulated, - // but can't be sure that using the win32 api 'SetCursor' uses the same resources - // So far, seems to be supported on any modern card used by the game anyway ... - OSVERSIONINFO osvi; - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (GetVersionEx(&osvi)) - { - _AlphaBlendedCursorSupported = (osvi.dwMajorVersion >= 5); - } - _AlphaBlendedCursorSupportRetrieved = true; - } - return _AlphaBlendedCursorSupported; -} - -bool VerboseCursorRT12516 = true; - -namespace NLMISC -{ - extern bool TempMaxVerboseResample; -} - -// ************************************************************************************* -void CCustomMouse::addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap) -{ - if (!isAlphaBlendedCursorSupported()) return; - nlassert(cursorBitmap.getWidth() != 0); - nlassert(cursorBitmap.getHeight() != 0); - // find used part base on alpha, to avoid too much shrinking - const CRGBA *pixels = (const CRGBA *) &cursorBitmap.getPixels()[0]; - uint minX, maxX, minY, maxY; - uint width = cursorBitmap.getWidth(); - uint height = cursorBitmap.getHeight(); - // - minX = 0; - for (uint x = 0; x < width; ++x) - { - bool stop = false; - minX = x; - for (uint y = 0; y < height; ++y) - { - if(pixels[x + y * width].A != 0) - { - stop = true; - break; - } - } - if (stop) break; - } - // - maxX = width - 1; - for (sint x = width - 1; x >= 0; --x) - { - bool stop = false; - maxX = (uint) x; - for (uint y = 0; y < height; ++y) - { - if(pixels[x + y * width].A != 0) - { - stop = true; - break; - } - } - if (stop) break; - } - // - minY = 0; - for (uint y = 0; y < height; ++y) - { - bool stop = false; - minY = y; - for (uint x = 0; x < width; ++x) - { - if(pixels[x + y * width].A != 0) - { - stop = true; - break; - } - } - if (stop) break; - } - // - maxY = height - 1; - for (sint y = height - 1; y >= 0; --y) - { - bool stop = false; - maxY = (uint) y; - for (uint x = 0; x < width; ++x) - { - if(pixels[x + y * width].A != 0) - { - stop = true; - break; - } - } - if (stop) break; - } - // - CCursor &curs = _Cursors[name]; - curs = CCursor(); // erase possible previous cursor - - uint destWidth = GetSystemMetrics(SM_CXCURSOR); - uint destHeight = GetSystemMetrics(SM_CYCURSOR); - // build a square bitmap - uint tmpSize = std::max(maxX - minX + 1, maxY - minY + 1); - curs.Src.resize(tmpSize, tmpSize), - // blit at top left corner - curs.Src.blit(cursorBitmap, minX, minY, maxX - minX + 1, maxY - minY + 1, 0, 0); - - curs.OrigHeight = cursorBitmap.getHeight(); - curs.HotspotOffsetX = minX; - curs.HotspotOffsetY = minY; - // - curs.HotspotScale = ClientCfg.HardwareCursorScale; - clamp(curs.HotspotScale, 0.f, 1.f); - // first resampling, same for all cursors - tmpSize = (uint) (tmpSize * curs.HotspotScale); - if (tmpSize == 0) tmpSize = 1; - - if (VerboseCursorRT12516 && ((name == "curs_stop.tga") || (name == "curs_pick_dup.tga"))) - TempMaxVerboseResample = true; - - if (TempMaxVerboseResample) - { - try - { - //nldebug("RT12516: BEFORE FIRST RESAMPLE"); - //nldebug("RT12516: %s: curs=%p curs.Src=%p curs.Src.PixelPtr=%p", name.c_str(), &curs, &(curs.Src), &curs.Src.getPixels(0)[0]); - //nldebug("RT12516: %s: curs.Src.PixelSize=%u", name.c_str(), curs.Src.getPixels(0).size()); - } - catch (...) - { - //nldebug("RT12516: An exception occurred!"); - } - } - - // TMP for RT 12406 -/* nlwarning("Resampling mouse %s cursor : initial size = %d x %d, new size = %d x %d", - name.c_str(), - curs.Src.getWidth(), - curs.Src.getHeight(), - tmpSize, - tmpSize - );*/ - curs.Src.resample(tmpSize, tmpSize); - - if (TempMaxVerboseResample) - { - try - { - //nldebug("RT12516: AFTER FIRST RESAMPLE"); - //nldebug("RT12516: %s: curs=%p curs.Src=%p curs.Src.PixelPtr=%p", name.c_str(), &curs, &(curs.Src), &curs.Src.getPixels(0)[0]); - //nldebug("RT12516: %s: curs.Src.PixelSize=%u", name.c_str(), curs.Src.getPixels(0).size()); - } - catch (...) - { - //nldebug("RT12516: An exception occurred!"); - } - } - - // shrink if necessary - if (tmpSize > destWidth || tmpSize > destHeight) // need to shrink ? - { - // constraint proportions - curs.HotspotScale *= std::min(float(destWidth) / tmpSize, float(destHeight) / tmpSize); - // TMP for RT 12406 -/* nlwarning("Resampling mouse %s cursor : initial size = %d x %d, new size = %d x %d", - name.c_str(), - curs.Src.getWidth(), - curs.Src.getHeight(), - destWidth, - destHeight - );*/ - curs.Src.resample(destWidth, destHeight); - } - else - { - CBitmap final; - final.resize(destWidth, destHeight); - final.blit(&curs.Src, 0, 0); - curs.Src.swap(final); - } - - if (TempMaxVerboseResample) - { - try - { - //nldebug("RT12516: AFTER SECOND RESAMPLE"); - //nldebug("RT12516: %s: curs=%p curs.Src=%p curs.Src.PixelPtr=%p", name.c_str(), &curs, &(curs.Src), &curs.Src.getPixels(0)[0]); - //nldebug("RT12516: %s: curs.Src.PixelSize=%u", name.c_str(), curs.Src.getPixels(0).size()); - } - catch (...) - { - //nldebug("RT12516: An exception occurred!"); - } - } - - if (name == _CurrName) - { - updateCursor(); - } - TempMaxVerboseResample = false; -} - - -// ************************************************************************************* -void CCustomMouse::release() -{ - if (!isAlphaBlendedCursorSupported()) return; - nlassert(Driver); - HWND drvWnd = Driver->getDisplay(); - if (drvWnd) - { - SetClassLongPtr(drvWnd, GCLP_HCURSOR, 0); - } - _Cursors.clear(); -} - -// ************************************************************************************* -void CCustomMouse::setColorDepth(TColorDepth colorDepth) -{ - if (colorDepth == _ColorDepth) return; - _ColorDepth = colorDepth; - updateCursor(true); -} - -// ************************************************************************************* -void CCustomMouse::updateCursor(bool forceRebuild) -{ - if (!Driver) return; - setCursor(_CurrName, _CurrCol, _CurrRot, _CurrHotSpotX, _CurrHotSpotY, forceRebuild); -} - -// ************************************************************************************* -void CCustomMouse::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild) -{ - if (!isAlphaBlendedCursorSupported()) return; - _CurrName = name; - _CurrCol = col; - _CurrRot = rot; - _CurrHotSpotX = hotSpotX; - _CurrHotSpotY = hotSpotY; - // - if (rot > 3) rot = 3; // same than 'CViewRenderer::drawRotFlipBitmapTiled - TIconMap::iterator it = _Cursors.find(name); - HCURSOR cursorHandle = _DefaultCursor; - if (it != _Cursors.end()) - { - // Update cursor if modified or not already built - CCursor &curs = it->second; - hotSpotX = (sint) (curs.HotspotScale * (hotSpotX - curs.HotspotOffsetX)); - hotSpotY = (sint) (curs.HotspotScale * ((curs.OrigHeight - hotSpotY) - curs.HotspotOffsetY)); - if (curs.Icon == 0 || - curs.HotSpotX != hotSpotX || - curs.HotSpotY != hotSpotY || - curs.Col != col || - curs.Rot != rot || - curs.ColorDepth != _ColorDepth || - forceRebuild - ) - { - if (curs.Icon != 0) - { - DestroyIcon(curs.Icon); - } - curs.Icon = buildCursor(curs.Src, col, rot, hotSpotX, hotSpotY); - curs.Col = col; - curs.Rot = rot; - curs.HotSpotX = hotSpotX; - curs.HotSpotY = hotSpotY; - curs.ColorDepth = _ColorDepth; - } - cursorHandle = curs.Icon ? (HCURSOR) curs.Icon : _DefaultCursor; - } - if (IsSystemCursorInClientArea() || IsSystemCursorCaptured() || forceRebuild) - { - if (CInputHandlerManager::getInstance()->hasFocus()) - { - ::SetCursor(cursorHandle); - HWND drvWnd = Driver->getDisplay(); - if (drvWnd) - { - SetClassLongPtr(drvWnd, GCLP_HCURSOR, (LONG_PTR) cursorHandle); // set default mouse icon to the last one - } - } - } - -} - -// ************************************************************************************* -HICON CCustomMouse::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY) -{ - nlassert(isAlphaBlendedCursorSupported()); - uint mouseW = GetSystemMetrics(SM_CXCURSOR); - uint mouseH = GetSystemMetrics(SM_CYCURSOR); - nlassert(src.getWidth() == mouseW); - nlassert(src.getHeight() == mouseH); - CBitmap rotSrc = src; - if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...) - switch(rot) - { - case 0: break; - case 1: rotSrc.rot90CW(); break; - case 2: rotSrc.rot90CW(); rotSrc.rot90CW(); break; - case 3: rotSrc.rot90CCW(); break; - } - return rotSrc.getHICON(mouseW, mouseH, _ColorDepth == ColorDepth16 ? 16:32, col, hotSpotX, hotSpotY, true); -} - - -// ************************************************************************************* -void CCustomMouse::setSystemArrow() -{ - extern HINSTANCE HInstance; - HCURSOR arrow = LoadCursor(NULL, IDC_ARROW); - if (IsSystemCursorInClientArea() || IsSystemCursorCaptured()) - { - ::SetCursor(arrow); - } - HWND drvWnd = Driver->getDisplay(); - if (drvWnd) - { - SetClassLongPtr(drvWnd, GCLP_HCURSOR, (LONG_PTR) arrow); // set default mouse icon to the last one - } -} - -#else - -// not implemented yet for other OS - -// ************************************************************************************* -CCustomMouse::CCustomMouse() -{ - // NOT IMPLEMENTED -} - -// ************************************************************************************* -void CCustomMouse::setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild) -{ - // NOT IMPLEMENTED -} - -// ************************************************************************************* -void CCustomMouse::release() -{ - // NOT IMPLEMENTED -} - -// ************************************************************************************* -bool CCustomMouse::isAlphaBlendedCursorSupported() -{ - return false; -} - -// ************************************************************************************* -void CCustomMouse::setSystemArrow() -{ - // -} - -void CCustomMouse::addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap) -{ - // TODO for Linux -} - -// ************************************************************************************* -void CCustomMouse::setColorDepth(TColorDepth colorDepth) -{ - // TODO for Linux -} - -// ************************************************************************************* -void CCustomMouse::updateCursor(bool forceRebuild) -{ - // TODO for Linux -} - -#endif // NL_OS_WINDOWS - - - - - diff --git a/code/ryzom/client/src/interface_v3/custom_mouse.h b/code/ryzom/client/src/interface_v3/custom_mouse.h deleted file mode 100644 index 258d0febb..000000000 --- a/code/ryzom/client/src/interface_v3/custom_mouse.h +++ /dev/null @@ -1,116 +0,0 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef RY_CUSTOM_MOUSE_H -#define RY_CUSTOM_MOUSE_H - -#ifdef NL_OS_WINDOWS - #include -#endif - -#include "nel/misc/rgba.h" -#include "nel/misc/bitmap.h" -#include "nel/misc/common.h" - -namespace NL3D -{ - class UTexture; -} - -// TMP Nico : made a separate class to avoid a lot of compilation until it works -class CCustomMouse -{ -public: - enum TColorDepth { ColorDepth16 = 0, ColorDepth32, ColorDepthCount }; - CCustomMouse(); - /** Signal a change of color depth (of desktop if windowed, or video mode if fullscreen) - * This is necessary to have the cursor built with good format - */ - void setColorDepth(TColorDepth colorDepth); - // Add a new cursor (name is case unsensitive) - void addCursor(const std::string &name, const NLMISC::CBitmap &cursorBitmap); - // Display a cursor from its name (case unsensitive) - void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false); - void updateCursor(bool forceRebuild = false); - void release(); - bool isAlphaBlendedCursorSupported(); - // reset the cursor shape to the system arrow - void setSystemArrow(); -private: -#ifdef NL_OS_WINDOWS - TColorDepth _ColorDepth; - std::string _CurrName; - NLMISC::CRGBA _CurrCol; - uint8 _CurrRot; - uint _CurrHotSpotX; - uint _CurrHotSpotY; - // - class CCursor - { - public: - NLMISC::CBitmap Src; - TColorDepth ColorDepth; - uint OrigHeight; - float HotspotScale; - uint HotspotOffsetX; - uint HotspotOffsetY; - sint HotSpotX; - sint HotSpotY; - HICON Icon; - NLMISC::CRGBA Col; - uint8 Rot; - public: - CCursor(); - ~CCursor(); - CCursor& operator= (const CCursor& from) - { - if (&from == this) - return *this; - Src = from.Src; // requires more than a surface copy - OrigHeight = from.OrigHeight; - HotspotScale = from.HotspotScale; - HotspotOffsetX = from.HotspotOffsetX; - HotspotOffsetY = from.HotspotOffsetY; - HotSpotX = from.HotSpotX; - HotSpotY = from.HotSpotY; - Icon = from.Icon; - Col = from.Col; - Rot = from.Rot; - return *this; - } - }; - struct CStrCaseUnsensitiveCmp - { - bool operator()(const std::string &lhs, const std::string &rhs) const - { - return NLMISC::nlstricmp(lhs, rhs) < 0; - } - }; - typedef std::map TIconMap; - TIconMap _Cursors; - HCURSOR _DefaultCursor; - bool _AlphaBlendedCursorSupported; - bool _AlphaBlendedCursorSupportRetrieved; -private: - // build a cursor from src, src should have the same size that the hardware cursor - // or a assertion is thrown - HICON buildCursor(const NLMISC::CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY); -#endif // NL_OS_WINDOWS -}; - -extern CCustomMouse CustomMouse; - -#endif 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 46f0cd9e7..cfbaf009d 100644 --- a/code/ryzom/client/src/interface_v3/input_handler_manager.cpp +++ b/code/ryzom/client/src/interface_v3/input_handler_manager.cpp @@ -29,7 +29,6 @@ #include "../actions.h" #include "../input.h" #include "../client_cfg.h" -#include "custom_mouse.h" #include "../motion/user_controls.h" #include "../init.h" #include "../release.h" @@ -65,6 +64,7 @@ CInputHandlerManager::CInputHandlerManager() _MouseButtonsState = noButton; _MouseX = _MouseY = _MouseLastX = _MouseLastY = 0; _Focus = true; + // Driver->setFocus(true); _MouseWheel = 0; _SkipInterfaceManager=false; _RecoverFocusLost = false; @@ -143,16 +143,6 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) if (event == EventDisplayChangeId) { - switch (getCurrentColorDepth()) - { - case 16: CustomMouse.setColorDepth(CCustomMouse::ColorDepth16); break; - case 24: - case 32: CustomMouse.setColorDepth(CCustomMouse::ColorDepth32); break; - default: - release(); - ExitClientError(CI18N::get("uiUnsupportedNewColorDepth").toUtf8().c_str()); - break; - } } // Process message to InterfaceManager @@ -168,6 +158,7 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) _MouseButtonsReleased = noButton; _MouseButtonsState = noButton; _Focus = false; + // Driver->setFocus(false); if (!_SkipInterfaceManager) { @@ -186,13 +177,14 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) } // be nice with other app : let the mouse reappear (useful in direct 3D mode with no hardware cursor) Driver->showCursor(true); - CustomMouse.setSystemArrow(); +// Driver->setSystemArrow(); } else { _RecoverFocusLost = true; // force to update mouse pos on next click or move Driver->showCursor(IsMouseCursorHardware()); _Focus = true; + // Driver->setFocus(true); } if(!_SkipInterfaceManager) diff --git a/code/ryzom/client/src/interface_v3/view_pointer.cpp b/code/ryzom/client/src/interface_v3/view_pointer.cpp index 849aba1b2..2f70d382b 100644 --- a/code/ryzom/client/src/interface_v3/view_pointer.cpp +++ b/code/ryzom/client/src/interface_v3/view_pointer.cpp @@ -19,7 +19,6 @@ #include "stdpch.h" #include "../input.h" -#include "custom_mouse.h" // #include "view_pointer.h" #include "interface_manager.h" @@ -692,17 +691,17 @@ void CViewPointer::drawCursor(sint32 texId, NLMISC::CRGBA col, uint8 rot) { CInterfaceManager *pIM = CInterfaceManager::getInstance(); CViewRenderer &rVR = pIM->getViewRenderer(); + sint32 xPos = _XReal + _OffsetX; + sint32 yPos = _YReal + _OffsetY; if (!IsMouseCursorHardware()) { - sint32 xPos = _XReal + _OffsetX; - sint32 yPos = _YReal + _OffsetY; rVR.draw11RotFlipBitmap (_RenderLayer, xPos, yPos, rot, false, texId, col); } else { // set new cursor for the hardware mouse std::string name = rVR.getTextureNameFromId(texId); - CustomMouse.setCursor(name, col, rot, (uint32) std::max(getX() - (_XReal + _OffsetX), (sint32) 0), (uint32) std::max(getY() - (_YReal + _OffsetY), (sint32) 0)); + Driver->setCursor(name, col, rot, (uint32) std::max(getX() - xPos, (sint32) 0), (uint32) std::max(getY() - yPos, (sint32) 0)); } } diff --git a/code/ryzom/client/src/interface_v3/view_renderer.cpp b/code/ryzom/client/src/interface_v3/view_renderer.cpp index 42e105a45..35443d14c 100644 --- a/code/ryzom/client/src/interface_v3/view_renderer.cpp +++ b/code/ryzom/client/src/interface_v3/view_renderer.cpp @@ -24,7 +24,6 @@ #include "nel/misc/uv.h" #include "nel/misc/hierarchical_timer.h" #include "interface_manager.h" -#include "custom_mouse.h" #include "../client_cfg.h" using namespace NLMISC; @@ -730,6 +729,8 @@ void CViewRenderer::loadTextures (const std::string &textureFileName, const std: _GlobalTextures.push_back (gt); +// Driver->setHardwareCursorScale(ClientCfg.HardwareCursorScale); + char bufTmp[256], tgaName[256]; string sTGAname; float uvMinU, uvMinV, uvMaxU, uvMaxV; @@ -767,23 +768,20 @@ void CViewRenderer::loadTextures (const std::string &textureFileName, const std: } // if this is a cursor texture, extract it now (supported for rgba only now, because of the blit) - if (CustomMouse.isAlphaBlendedCursorSupported()) + if (texDatas && texDatas->getPixelFormat() == CBitmap::RGBA) { - if (texDatas && texDatas->getPixelFormat() == CBitmap::RGBA) + if (ClientCfg.HardwareCursors.count(image.Name)) { - if (ClientCfg.HardwareCursors.count(image.Name)) + uint x0 = (uint) (image.UVMin.U * gt.Width); + uint y0 = (uint) (image.UVMin.V * gt.Height); + uint x1 = (uint) (image.UVMax.U * gt.Width); + uint y1 = (uint) (image.UVMax.V * gt.Height); + if (x1 != x0 && y1 != y0) { - uint x0 = (uint) (image.UVMin.U * gt.Width); - uint y0 = (uint) (image.UVMin.V * gt.Height); - uint x1 = (uint) (image.UVMax.U * gt.Width); - uint y1 = (uint) (image.UVMax.V * gt.Height); - if (x1 != x0 && y1 != y0) - { - CBitmap curs; - curs.resize(x1 - x0, y1 - y0); - curs.blit(*texDatas, x0, y0, (x1 - x0), (y1 - y0), 0, 0); - CustomMouse.addCursor(image.Name, curs); - } + CBitmap curs; + curs.resize(x1 - x0, y1 - y0); + curs.blit(*texDatas, x0, y0, (x1 - x0), (y1 - y0), 0, 0); + Driver->addCursor(image.Name, curs); } } } diff --git a/code/ryzom/client/src/release.cpp b/code/ryzom/client/src/release.cpp index 39705abb7..26edece3c 100644 --- a/code/ryzom/client/src/release.cpp +++ b/code/ryzom/client/src/release.cpp @@ -71,7 +71,6 @@ #include "interface_v3/music_player.h" #include "http_client.h" #include "actions_client.h" -#include "interface_v3/custom_mouse.h" #include "login_progress_post_thread.h" // #include "r2/editor.h" @@ -502,8 +501,6 @@ void releaseOutGame() // Remove the Actions listener from the Events Server. EventsListener.removeFromServer(CInputHandlerManager::getInstance()->FilteredEventServer); - CustomMouse.release(); - // Release Bloom CBloomEffect::releaseInstance(); @@ -574,8 +571,6 @@ void release() Driver->deleteTextContext(TextContext); TextContext = NULL; - CustomMouse.release(); - // Release Bloom CBloomEffect::releaseInstance();