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<NLMISC::CBitmap> bitmaps;
 		setWindowIcon(bitmaps);
@@ -2231,10 +2248,10 @@ void CDriverD3D::setWindowIcon(const std::vector<NLMISC::CBitmap> &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<uint16> 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<uint8> 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 <algorithm>
 
+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<std::string, CCursor, CStrCaseUnsensitiveCmp> 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<CDIEventEmitter *>(_EventEmitter.getEmitter(1));
+
+	NLMISC::IMouseDevice *res = NULL;
+
+	NLMISC::CDIEventEmitter *diee = NULL;
+
+	if (_EventEmitter.getNumEmitters() > 1)
+		diee = NLMISC::safe_cast<CDIEventEmitter *>(_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<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
+
+	NLMISC::IKeyboardDevice *res = NULL;
+
+	NLMISC::CDIEventEmitter *diee = NULL;
+
+	if (_EventEmitter.getNumEmitters() > 1)
+		diee = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_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<NLMISC::CDIEventEmitter *>(_EventEmitter.getEmitter(1));
-	return diee;
+
+	NLMISC::IInputDeviceManager *res = NULL;
+
+	if (_EventEmitter.getNumEmitters() > 1)
+		res = NLMISC::safe_cast<NLMISC::CDIEventEmitter *>(_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<CDIEventEmitter *>(_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<std::string, CCursor, CStrCaseUnsensitiveCmp> 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<long> &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 <http://dev.ryzom.com/projects/nel/>
+// 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 <http://www.gnu.org/licenses/>.
+
+#include "stdopengl.h"
+#include "driver_opengl.h"
+
+#ifdef NL_OS_WINDOWS
+# include <windowsx.h>
+#elif defined(NL_OS_MAC)
+#elif defined (NL_OS_UNIX)
+# include <GL/gl.h>
+# include <GL/glx.h>
+# include <X11/Xatom.h>
+#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<CDIEventEmitter *>(_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<NLMISC::CDIEventEmitter *>(_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<NLMISC::CDIEventEmitter *>(_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<CDIEventEmitter *>(_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<NLMISC::CBitmap> &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<NLMISC::CBitmap> &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<uint8> 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<NLMISC::CBitmap> 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<CDIEventEmitter *>(_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<NLMISC::CDIEventEmitter *>(_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<NLMISC::CDIEventEmitter *>(_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<CDIEventEmitter *>(_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<uint16> 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<uint8> 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<long> &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<uint8> 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<uint16> 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<uint16> 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<uint8> 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 <http://dev.ryzom.com/projects/ryzom/>
-// 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 <http://www.gnu.org/licenses/>.
-
-#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 <http://dev.ryzom.com/projects/ryzom/>
-// 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 <http://www.gnu.org/licenses/>.
-
-#ifndef	RY_CUSTOM_MOUSE_H
-#define RY_CUSTOM_MOUSE_H
-
-#ifdef NL_OS_WINDOWS
-	#include <windows.h>
-#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<std::string, CCursor, CStrCaseUnsensitiveCmp> 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();