Changed: #1034 Implement CCustomMouse for Linux
parent
72e4c5208f
commit
a4c64bb753
@ -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)
|
||||
|
@ -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
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
Loading…
Reference in New Issue