Fixed: #972 Do not reset mouse position to implement FreeLook (IDriver::InterfaceVersion = 0x66)
This commit is contained in:
parent
d74bf9a642
commit
610a04982f
16 changed files with 260 additions and 129 deletions
|
@ -413,6 +413,12 @@ public:
|
|||
//
|
||||
virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable);
|
||||
virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager();
|
||||
|
||||
/**
|
||||
* wrapper for IEventEmitter::emulateMouseRawMode()
|
||||
*/
|
||||
virtual void emulateMouseRawMode(bool enable);
|
||||
|
||||
virtual uint getDoubleClickDelay(bool hardwareMouse);
|
||||
|
||||
/// show cursor if b is true, or hide it if b is false
|
||||
|
|
|
@ -571,6 +571,11 @@ public:
|
|||
*/
|
||||
virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager() = 0;
|
||||
|
||||
/**
|
||||
* wrapper for IEventEmitter::emulateMouseRawMode()
|
||||
*/
|
||||
virtual void emulateMouseRawMode(bool enable) = 0;
|
||||
|
||||
// get delay used for mouse double click
|
||||
virtual uint getDoubleClickDelay(bool hardwareMouse) = 0;
|
||||
|
||||
|
|
|
@ -49,7 +49,19 @@ public:
|
|||
* \param server
|
||||
*/
|
||||
virtual void submitEvents(CEventServer & server, bool allWindows) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Instruct the event emitter to send CGDMouseMove instead of CEventMouseMove.
|
||||
*
|
||||
* On windows, the mouse device can be set into RawMode. Using this mode,
|
||||
* CGDMouseMove events (only containing the raw movement delta) are emitted
|
||||
* instead of the normal CEventMouseMove events (containing the mouse position).
|
||||
*
|
||||
* On Linux and Mac OS X, there is no MouseDevice implementation, all the
|
||||
* events are created by the event emitter. So the event emitter has to
|
||||
* emulate the mouse raw mode.
|
||||
*/
|
||||
virtual void emulateMouseRawMode(bool) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -99,6 +99,9 @@ public:
|
|||
* Return true if the message must be trapped, false if DefWindowProc must be called afterwards
|
||||
*/
|
||||
bool processMessage (HWND hWnd, uint32 msg, WPARAM wParam, LPARAM lParam, CEventServer *server=NULL);
|
||||
|
||||
void emulateMouseRawMode(bool enable);
|
||||
|
||||
private:
|
||||
CWinEventServer _InternalServer;
|
||||
HWND _HWnd;
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace NL3D
|
|||
{
|
||||
|
||||
// ***************************************************************************
|
||||
const uint32 IDriver::InterfaceVersion = 0x65; // Added nlWindow patch.
|
||||
const uint32 IDriver::InterfaceVersion = 0x66; // added IEventEmitter::emulateMouseRawMode(bool)
|
||||
|
||||
// ***************************************************************************
|
||||
IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" )
|
||||
|
|
|
@ -89,6 +89,9 @@ void release();
|
|||
void submitEvents(NLMISC::CEventServer& server,
|
||||
bool allWindows, NLMISC::CCocoaEventEmitter* eventEmitter);
|
||||
|
||||
/// mac specific stuff while calling CCocoaEventEmitter::emulateMouseRawMode()
|
||||
void emulateMouseRawMode(bool enable);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "cocoa_adapter.h"
|
||||
|
||||
#include "nel/misc/events.h"
|
||||
#include "nel/misc/game_device_events.h"
|
||||
#include "nel/3d/driver.h"
|
||||
|
||||
#include "cocoa_event_emitter.h"
|
||||
|
@ -33,11 +34,13 @@
|
|||
|
||||
namespace NL3D { namespace MAC {
|
||||
|
||||
static NSApplication* g_app = nil;
|
||||
static NSAutoreleasePool* g_pool = nil;
|
||||
static CocoaWindow* g_window = nil;
|
||||
static CocoaOpenGLView* g_glview = nil;
|
||||
static NSOpenGLContext* g_glctx = nil;
|
||||
static NSApplication* g_app = nil;
|
||||
static NSAutoreleasePool* g_pool = nil;
|
||||
static CocoaWindow* g_window = nil;
|
||||
static CocoaOpenGLView* g_glview = nil;
|
||||
static NSOpenGLContext* g_glctx = nil;
|
||||
static bool g_emulateRawMode = false;
|
||||
|
||||
|
||||
#define UGLY_BACKBUFFER_SIZE_WORKAROUND
|
||||
|
||||
|
@ -77,13 +80,17 @@ bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable)
|
|||
/*
|
||||
TODO use show and resizable flags
|
||||
*/
|
||||
|
||||
/*
|
||||
TODO add menu, on quit send EventDestroyWindowId
|
||||
*/
|
||||
|
||||
// create a cocoa window with the size provided by the mode parameter
|
||||
g_window = [[CocoaWindow alloc]
|
||||
initWithContentRect:NSMakeRect(0, 0, mode.Width, mode.Height)
|
||||
styleMask:NSTitledWindowMask | NSResizableWindowMask |
|
||||
NSClosableWindowMask | NSMiniaturizableWindowMask
|
||||
backing:NSBackingStoreBuffered
|
||||
styleMask:NSTitledWindowMask | NSResizableWindowMask |
|
||||
NSClosableWindowMask | NSMiniaturizableWindowMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
|
||||
if(!g_window)
|
||||
|
@ -130,7 +137,7 @@ bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable)
|
|||
// enable mouse move events, NeL wants them
|
||||
[g_window setAcceptsMouseMovedEvents:YES];
|
||||
|
||||
// there are no overlapping subview, so we can use the magical optimization!
|
||||
// there are no overlapping subviews, so we can use the magical optimization!
|
||||
[g_window useOptimizedDrawing:YES];
|
||||
|
||||
// create a opengl context for the view
|
||||
|
@ -139,7 +146,7 @@ bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable)
|
|||
if(!g_glctx)
|
||||
nlerror("cannot create context");
|
||||
|
||||
// make the views opengl context the currrent one
|
||||
// make the view's opengl context the currrent one
|
||||
[g_glctx makeCurrentContext];
|
||||
|
||||
// put the window to the front and make it the key window
|
||||
|
@ -178,9 +185,6 @@ bool setMode(const GfxMode& mode)
|
|||
// leave fullscreen mode, enter windowed mode
|
||||
if(mode.Windowed && [g_glview isInFullScreenMode])
|
||||
{
|
||||
// pull the view back from fullscreen restoring window options
|
||||
[g_glview exitFullScreenModeWithOptions:nil];
|
||||
|
||||
// disable manual setting of back buffer size, cocoa handles this
|
||||
// automatically as soon as the view gets resized
|
||||
CGLError error = CGLDisable((CGLContextObj)[g_glctx CGLContextObj],
|
||||
|
@ -189,6 +193,9 @@ bool setMode(const GfxMode& mode)
|
|||
if(error != kCGLNoError)
|
||||
nlerror("cannot disable kCGLCESurfaceBackingSize (%s)",
|
||||
CGLErrorString(error));
|
||||
|
||||
// pull the view back from fullscreen restoring window options
|
||||
[g_glview exitFullScreenModeWithOptions:nil];
|
||||
}
|
||||
|
||||
// enter fullscreen, leave windowed mode
|
||||
|
@ -205,20 +212,21 @@ bool setMode(const GfxMode& mode)
|
|||
// put the view in fullscreen mode, hiding the dock but enabling the menubar
|
||||
// to pop up if the mouse hits the top screen border.
|
||||
// NOTE: withOptions:nil disables <CMD>+<Tab> application switching!
|
||||
/*
|
||||
TODO check if simply using NSView enterFullScreenMode is a good idea.
|
||||
the context can be set to full screen as well, performance differences?
|
||||
*/
|
||||
[g_glview enterFullScreenMode:[NSScreen mainScreen] withOptions:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithInt:
|
||||
NSApplicationPresentationHideDock |
|
||||
NSApplicationPresentationAutoHideMenuBar],
|
||||
NSFullScreenModeApplicationPresentationOptions, nil]];
|
||||
|
||||
/*
|
||||
TODO check if simply using NSView enterFullScreenMode is a good idea.
|
||||
the context can be set to full screen as well, performance differences?
|
||||
*/
|
||||
}
|
||||
|
||||
#ifdef UGLY_BACKBUFFER_SIZE_WORKAROUND
|
||||
// due to the back buffer size reading problem, just store the size
|
||||
// due to a back buffer size reading problem, just store the size
|
||||
g_bufferSize[0] = mode.Width;
|
||||
g_bufferSize[1] = mode.Height;
|
||||
#endif
|
||||
|
@ -240,13 +248,18 @@ void getWindowSize(uint32 &width, uint32 &height)
|
|||
// not the one from the window.
|
||||
|
||||
#ifdef UGLY_BACKBUFFER_SIZE_WORKAROUND
|
||||
// in fullscreen mode
|
||||
if([g_glview isInFullScreenMode])
|
||||
{
|
||||
// use the size stored in setMode()
|
||||
width = g_bufferSize[0];
|
||||
height = g_bufferSize[1];
|
||||
}
|
||||
|
||||
// in windowed mode
|
||||
else
|
||||
{
|
||||
// use the size of the view
|
||||
NSRect rect = [g_glview frame];
|
||||
width = rect.size.width;
|
||||
height = rect.size.height;
|
||||
|
@ -264,7 +277,7 @@ void getWindowSize(uint32 &width, uint32 &height)
|
|||
nlerror("cannot check kCGLCESurfaceBackingSize state (%s)",
|
||||
CGLErrorString(error));
|
||||
|
||||
// if in fullscreen mode
|
||||
// if in fullscreen mode (only in fullscreen back buffer sizing is used)
|
||||
if(surfaceBackingSizeSet)
|
||||
{
|
||||
/*
|
||||
|
@ -341,20 +354,13 @@ void swapBuffers()
|
|||
|
||||
void setCapture(bool b)
|
||||
{
|
||||
/*
|
||||
TODO implement capture cursor, no need to fake using pull back to 0.5 / 0.5
|
||||
set a flag and then act accordingly in event loop?
|
||||
|
||||
// no screen bounds...
|
||||
void CGGetLastMouseDelta(CGMouseDelta* deltaX, CGMouseDelta* deltaY);
|
||||
*/
|
||||
nlwarning("not implemented");
|
||||
// no need to capture
|
||||
}
|
||||
|
||||
void showCursor(bool b)
|
||||
{
|
||||
// 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.
|
||||
// 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.
|
||||
|
@ -379,6 +385,10 @@ void showCursor(bool b)
|
|||
|
||||
void setMousePos(float x, float y)
|
||||
{
|
||||
/*
|
||||
TODO FIXME for windows placed on non primary monitor
|
||||
*/
|
||||
|
||||
// CG wants absolute coordinates related to screen top left
|
||||
CGFloat fromScreenLeft = 0.0;
|
||||
CGFloat fromScreenTop = 0.0;
|
||||
|
@ -571,7 +581,7 @@ NLMISC::TKeyButton modifierFlagsToNelKeyButton(unsigned int modifierFlags)
|
|||
|
||||
bool isTextKeyEvent(NSEvent* event)
|
||||
{
|
||||
// if there are no characters provided with this event, is is not a text event
|
||||
// if there are no characters provided with this event, it is not a text event
|
||||
if([[event characters] length] == 0)
|
||||
return false;
|
||||
|
||||
|
@ -621,6 +631,11 @@ bool isTextKeyEvent(NSEvent* event)
|
|||
return false;
|
||||
}
|
||||
|
||||
void emulateMouseRawMode(bool enable)
|
||||
{
|
||||
g_emulateRawMode = enable;
|
||||
}
|
||||
|
||||
void submitEvents(NLMISC::CEventServer& server,
|
||||
bool allWindows, NLMISC::CCocoaEventEmitter* eventEmitter)
|
||||
{
|
||||
|
@ -641,8 +656,6 @@ void submitEvents(NLMISC::CEventServer& server,
|
|||
if(!event)
|
||||
break;
|
||||
|
||||
// NSLog(@"%@", event);
|
||||
|
||||
// get the views size
|
||||
NSRect rect = [g_glview frame];
|
||||
|
||||
|
@ -651,7 +664,7 @@ void submitEvents(NLMISC::CEventServer& server,
|
|||
float mouseX = event.locationInWindow.x / (float)rect.size.width;
|
||||
float mouseY = event.locationInWindow.y / (float)rect.size.height;
|
||||
|
||||
// if the mouse event was placed on the window's titlebar, ignore it
|
||||
// if the mouse event was placed on the window's titlebar, don't tell NeL :)
|
||||
if(mouseY > 1.0 && event.type != NSKeyDown && event.type != NSKeyUp)
|
||||
{
|
||||
[g_app sendEvent:event];
|
||||
|
@ -662,58 +675,106 @@ void submitEvents(NLMISC::CEventServer& server,
|
|||
switch(event.type)
|
||||
{
|
||||
case NSLeftMouseDown:
|
||||
{
|
||||
/*
|
||||
TODO modifiers with mouse events
|
||||
*/
|
||||
server.postEvent(new NLMISC::CEventMouseDown(
|
||||
mouseX, mouseY, NLMISC::leftButton /* modifiers */, eventEmitter));
|
||||
}
|
||||
break;
|
||||
case NSLeftMouseUp:
|
||||
{
|
||||
/*
|
||||
TODO modifiers with mouse events
|
||||
*/
|
||||
server.postEvent(new NLMISC::CEventMouseUp(
|
||||
mouseX, mouseY, NLMISC::leftButton /* modifiers */, eventEmitter));
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case NSRightMouseDown:
|
||||
{
|
||||
/*
|
||||
TODO modifiers with mouse events
|
||||
*/
|
||||
server.postEvent(new NLMISC::CEventMouseDown(
|
||||
mouseX, mouseY, NLMISC::rightButton /* modifiers */, eventEmitter));
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case NSRightMouseUp:
|
||||
{
|
||||
/*
|
||||
TODO modifiers with mouse events
|
||||
*/
|
||||
server.postEvent(new NLMISC::CEventMouseUp(
|
||||
mouseX, mouseY, NLMISC::rightButton /* modifiers */, eventEmitter));
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case NSMouseMoved:
|
||||
{
|
||||
/*
|
||||
TODO modifiers with mouse events
|
||||
*/
|
||||
server.postEvent(new NLMISC::CEventMouseMove(
|
||||
mouseX, mouseY, (NLMISC::TMouseButton)0 /* modifiers */, eventEmitter));
|
||||
break;
|
||||
case NSLeftMouseDragged:
|
||||
/*
|
||||
TODO modifiers with mouse events
|
||||
*/
|
||||
// nldebug("mouse left drag %f %f", mouseX, mouseY);
|
||||
NLMISC::CEvent* nelEvent;
|
||||
|
||||
// when emulating raw mode, send the delta in a CGDMouseMove event
|
||||
if(g_emulateRawMode)
|
||||
nelEvent = new NLMISC::CGDMouseMove(
|
||||
eventEmitter, NULL /* no mouse device */, event.deltaX, -event.deltaY);
|
||||
|
||||
server.postEvent(new NLMISC::CEventMouseMove(
|
||||
mouseX, mouseY, NLMISC::leftButton /* modifiers */, eventEmitter));
|
||||
break;
|
||||
case NSRightMouseDragged:break;
|
||||
// normally send position in a CEventMouseMove
|
||||
else
|
||||
nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY,
|
||||
(NLMISC::TMouseButton)0 /* modifiers */, eventEmitter);
|
||||
|
||||
|
||||
server.postEvent(nelEvent);
|
||||
break;
|
||||
}
|
||||
case NSLeftMouseDragged:
|
||||
{
|
||||
/*
|
||||
TODO modifiers with mouse events
|
||||
*/
|
||||
server.postEvent(new NLMISC::CEventMouseMove(
|
||||
mouseX, mouseY, NLMISC::rightButton /* modifiers */, eventEmitter));
|
||||
NLMISC::CEvent* nelEvent;
|
||||
|
||||
// when emulating raw mode, send the delta in a CGDMouseMove event
|
||||
if(g_emulateRawMode)
|
||||
nelEvent = new NLMISC::CGDMouseMove(
|
||||
eventEmitter, NULL /* no mouse device */, event.deltaX, -event.deltaY);
|
||||
|
||||
// normally send position in a CEventMouseMove
|
||||
else
|
||||
nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY,
|
||||
NLMISC::leftButton /* modifiers */, eventEmitter);
|
||||
|
||||
server.postEvent(nelEvent);
|
||||
break;
|
||||
}
|
||||
case NSRightMouseDragged:
|
||||
{
|
||||
/*
|
||||
TODO modifiers with mouse events
|
||||
*/
|
||||
NLMISC::CEvent* nelEvent;
|
||||
|
||||
// when emulating raw mode, send the delta in a CGDMouseMove event
|
||||
if(g_emulateRawMode)
|
||||
nelEvent = new NLMISC::CGDMouseMove(
|
||||
eventEmitter, NULL /* no mouse device */, event.deltaX, -event.deltaY);
|
||||
|
||||
// normally send position in a CEventMouseMove
|
||||
else
|
||||
nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY,
|
||||
NLMISC::rightButton /* modifiers */, eventEmitter);
|
||||
|
||||
server.postEvent(nelEvent);
|
||||
break;
|
||||
}
|
||||
case NSMouseEntered:break;
|
||||
case NSMouseExited:break;
|
||||
case NSKeyDown:
|
||||
{
|
||||
// push the key press event to the event server
|
||||
server.postEvent(new NLMISC::CEventKeyDown(
|
||||
virtualKeycodeToNelKey([event keyCode]),
|
||||
|
@ -735,14 +796,17 @@ void submitEvents(NLMISC::CEventServer& server,
|
|||
NLMISC::noKeyButton,
|
||||
eventEmitter));
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case NSKeyUp:
|
||||
{
|
||||
// push the key release event to the event server
|
||||
server.postEvent(new NLMISC::CEventKeyUp(
|
||||
virtualKeycodeToNelKey([event keyCode]),
|
||||
modifierFlagsToNelKeyButton([event modifierFlags]),
|
||||
eventEmitter));
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case NSFlagsChanged:break;
|
||||
case NSAppKitDefined:break;
|
||||
case NSSystemDefined:break;
|
||||
|
@ -762,9 +826,11 @@ void submitEvents(NLMISC::CEventServer& server,
|
|||
case NSEventTypeBeginGesture:break;
|
||||
case NSEventTypeEndGesture:break;
|
||||
default:
|
||||
{
|
||||
nlwarning("Unknown event type. dropping.");
|
||||
// NSLog(@"%@", event);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[g_app sendEvent:event];
|
||||
|
|
|
@ -27,4 +27,10 @@ void CCocoaEventEmitter::submitEvents(CEventServer & server, bool allWindows)
|
|||
NL3D::MAC::submitEvents(server, allWindows, this);
|
||||
}
|
||||
|
||||
void CCocoaEventEmitter::emulateMouseRawMode(bool enable)
|
||||
{
|
||||
// just forwarding to our cocoa adapter
|
||||
NL3D::MAC::emulateMouseRawMode(enable);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ class CCocoaEventEmitter : public IEventEmitter
|
|||
{
|
||||
public:
|
||||
virtual void submitEvents(CEventServer & server, bool allWindows);
|
||||
virtual void emulateMouseRawMode(bool enable);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
namespace NLMISC {
|
||||
|
||||
CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _PreviousKey(KeyNOKEY)
|
||||
CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _PreviousKey(KeyNOKEY), _emulateRawMode(false)
|
||||
{
|
||||
_im = 0;
|
||||
_ic = 0;
|
||||
|
@ -83,6 +83,19 @@ void CUnixEventEmitter::submitEvents(CEventServer & server, bool allWindows)
|
|||
}
|
||||
}
|
||||
|
||||
void CUnixEventEmitter::emulateMouseRawMode(bool enable)
|
||||
{
|
||||
_emulateRawMode = enable;
|
||||
|
||||
if(_emulateRawMode)
|
||||
{
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes(_dpy, _win, &xwa);
|
||||
XWarpPointer(_dpy, None, _win, None, None, None, None,
|
||||
(xwa.width / 2), (xwa.height / 2));
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef AltMask
|
||||
# ifdef NL_OS_MAC
|
||||
# define AltMask (8192)
|
||||
|
@ -120,6 +133,9 @@ TKey getKeyFromKeycode (uint keycode)
|
|||
switch (keycode)
|
||||
{
|
||||
#ifdef NL_OS_MAC
|
||||
/*
|
||||
TODO use key mapping from driver/opengl/mac/cocoa_adapter.mm
|
||||
*/
|
||||
case 0x12: return Key1;
|
||||
case 0x13: return Key2;
|
||||
case 0x14: return Key3;
|
||||
|
@ -316,6 +332,9 @@ TKey getKeyFromKeySym (KeySym keysym)
|
|||
|
||||
void CUnixEventEmitter::processMessage (XEvent &event, CEventServer &server)
|
||||
{
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes (_dpy, _win, &xwa);
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
Case(ReparentNotify)
|
||||
|
@ -325,8 +344,6 @@ void CUnixEventEmitter::processMessage (XEvent &event, CEventServer &server)
|
|||
Case(ButtonPress)
|
||||
{
|
||||
//nlinfo("%d %d %d", event.xbutton.button, event.xbutton.x, event.xbutton.y);
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes (_dpy, _win, &xwa);
|
||||
float fX = (float) event.xbutton.x / (float) xwa.width;
|
||||
float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height;
|
||||
TMouseButton button=getMouseButton(event.xbutton.state);
|
||||
|
@ -353,8 +370,6 @@ void CUnixEventEmitter::processMessage (XEvent &event, CEventServer &server)
|
|||
Case(ButtonRelease)
|
||||
{
|
||||
//nlinfo("%d %d %d", event.xbutton.button, event.xbutton.x, event.xbutton.y);
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes (_dpy, _win, &xwa);
|
||||
float fX = (float) event.xbutton.x / (float) xwa.width;
|
||||
float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height;
|
||||
switch(event.xbutton.button)
|
||||
|
@ -373,13 +388,36 @@ void CUnixEventEmitter::processMessage (XEvent &event, CEventServer &server)
|
|||
}
|
||||
Case(MotionNotify)
|
||||
{
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes (_dpy, _win, &xwa);
|
||||
float fX = (float) event.xbutton.x / (float) xwa.width;
|
||||
float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height;
|
||||
if ((fX == 0.5f) && (fY == 0.5f)) break;
|
||||
TMouseButton button=getMouseButton (event.xbutton.state);
|
||||
server.postEvent (new CEventMouseMove (fX, fY, button, this));
|
||||
|
||||
// if raw mode should be emulated
|
||||
if(_emulateRawMode)
|
||||
{
|
||||
// when we just wrapped back the pointer to 0.5 / 0.5, ignore event
|
||||
if(event.xbutton.x == xwa.width / 2 && event.xbutton.y == xwa.height / 2)
|
||||
break;
|
||||
|
||||
// post a CGDMouseMove with the movement delta to the event server
|
||||
server.postEvent(
|
||||
new CGDMouseMove(this, NULL /* no mouse device */,
|
||||
event.xbutton.x - (xwa.width / 2),
|
||||
(xwa.height / 2) - event.xbutton.y));
|
||||
|
||||
// move the pointer back to the center of the window
|
||||
XWarpPointer(_dpy, None, _win, None, None, None, None,
|
||||
(xwa.width / 2), (xwa.height / 2));
|
||||
}
|
||||
|
||||
// if in normal mouse mode
|
||||
else
|
||||
{
|
||||
// get the relative mouse position
|
||||
float fX = (float) event.xbutton.x / (float) xwa.width;
|
||||
float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height;
|
||||
|
||||
// post a normal mouse move event to the event server
|
||||
server.postEvent (new CEventMouseMove (fX, fY, button, this));
|
||||
}
|
||||
break;
|
||||
}
|
||||
Case(KeyPress)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "nel/misc/types_nl.h"
|
||||
#include "nel/misc/event_emitter.h"
|
||||
#include "nel/misc/events.h"
|
||||
#include "nel/misc/game_device_events.h"
|
||||
|
||||
#ifdef NL_OS_UNIX
|
||||
|
||||
|
@ -54,6 +55,8 @@ public:
|
|||
*/
|
||||
virtual void submitEvents(CEventServer & server, bool allWindows);
|
||||
|
||||
virtual void emulateMouseRawMode(bool);
|
||||
|
||||
public:
|
||||
void processMessage (XEvent &event, CEventServer &server);
|
||||
|
||||
|
@ -65,6 +68,7 @@ private:
|
|||
TKey _PreviousKey;
|
||||
XIM _im;
|
||||
XIC _ic;
|
||||
bool _emulateRawMode;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "nel/3d/water_pool_manager.h"
|
||||
#include "nel/3d/u_camera.h"
|
||||
#include "nel/misc/hierarchical_timer.h"
|
||||
#include "nel/misc/event_emitter.h"
|
||||
|
||||
|
||||
using namespace NLMISC;
|
||||
|
@ -1594,6 +1595,11 @@ NLMISC::IKeyboardDevice *CDriverUser::enableLowLevelKeyboard(bool enable)
|
|||
return _Driver->enableLowLevelKeyboard(enable);
|
||||
}
|
||||
|
||||
void CDriverUser::emulateMouseRawMode(bool enable)
|
||||
{
|
||||
_Driver->getEventEmitter()->emulateMouseRawMode(enable);
|
||||
}
|
||||
|
||||
uint CDriverUser::getDoubleClickDelay(bool hardwareMouse)
|
||||
{
|
||||
NL3D_HAUTO_UI_DRIVER;
|
||||
|
|
|
@ -52,6 +52,13 @@ void CWinEventEmitter::submitEvents(CEventServer & server, bool allWindows)
|
|||
_InternalServer.pump (allWindows);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*\
|
||||
emulateMouseRawMode()
|
||||
\*------------------------------------------------------------------*/
|
||||
void CWinEventEmitter::emulateMouseRawMode(bool enable)
|
||||
{
|
||||
nlerror("no raw mode emulation on windows, the CDIMouse has a real raw mode");
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*\
|
||||
processMessage()
|
||||
|
|
|
@ -145,16 +145,11 @@ void CEventsListener::operator()(const CEvent& event)
|
|||
// Event from the Mouse (ANGLE)
|
||||
if(event == EventGDMouseMove)
|
||||
{
|
||||
#ifdef NL_OS_WINDOWS
|
||||
CGDMouseMove* mouseEvent=(CGDMouseMove*)&event;
|
||||
// Mouse acceleration
|
||||
sint dX = mouseEvent->X;
|
||||
sint dY = ClientCfg.FreeLookInverted ? -mouseEvent->Y : mouseEvent->Y;
|
||||
updateFreeLookPos((float) dX, (float) dY);
|
||||
#else
|
||||
// just to make sure that there is no game device implementation un unix
|
||||
nlerror("not expecting EventGDMouseMove on unix");
|
||||
#endif
|
||||
}
|
||||
// Event from the Mouse (MOVE)
|
||||
else if(event == EventMouseMoveId)
|
||||
|
|
|
@ -198,20 +198,24 @@ void UpdateMouse ()
|
|||
// Raw mode
|
||||
if (MouseDevice)
|
||||
{
|
||||
|
||||
MouseDevice->setMessagesMode(IMouseDevice::RawMode);
|
||||
MouseDevice->setMouseAcceleration(ClientCfg.FreeLookAcceleration);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no mouse device implementation on X11 and Cocoa, emulate raw mode
|
||||
Driver->emulateMouseRawMode(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the driver size
|
||||
uint32 width, height;
|
||||
Driver->getWindowSize(width, height);
|
||||
|
||||
// Set the mouse properties
|
||||
if (MouseDevice)
|
||||
{
|
||||
// Get the driver size
|
||||
uint32 width, height;
|
||||
Driver->getWindowSize(width, height);
|
||||
|
||||
MouseDevice->setMessagesMode(IMouseDevice::NormalMode);
|
||||
MouseDevice->setMouseMode(IMouseDevice::XAxis, IMouseDevice::Clamped);
|
||||
MouseDevice->setMouseMode(IMouseDevice::YAxis, IMouseDevice::Clamped);
|
||||
|
@ -221,6 +225,11 @@ void UpdateMouse ()
|
|||
MouseDevice->setMouseSpeed(MouseCursorSpeed);
|
||||
MouseDevice->setMouseAcceleration(MouseCursorAcceleration);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no mouse device implementation on X11 and Cocoa, emulate raw mode
|
||||
Driver->emulateMouseRawMode(false);
|
||||
}
|
||||
}
|
||||
if (!IsSystemCursorCaptured())
|
||||
{
|
||||
|
@ -249,13 +258,6 @@ void SetMouseFreeLook ()
|
|||
}
|
||||
UpdateMouse ();
|
||||
}
|
||||
|
||||
#ifdef NL_OS_UNIX
|
||||
// on X11 and cocoa the mouse needs to get pulled into the middle each update,
|
||||
// else the cursor would reach the border of the window / desktop
|
||||
// and freelook would hang
|
||||
Driver->setMousePos(0.5f, 0.5f);
|
||||
#endif
|
||||
}
|
||||
|
||||
//*********************************************************************************
|
||||
|
@ -404,6 +406,9 @@ bool IsSystemCursorCaptured()
|
|||
#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
|
||||
}
|
||||
|
|
|
@ -427,72 +427,46 @@ void CUserControls::getMouseAngleMove(float &dx, float &dy)
|
|||
dx = 0.0f;
|
||||
dy = 0.0f;
|
||||
|
||||
|
||||
// The mouse may still "StandardMove" ie through a CEventMouseMove
|
||||
// This can happens cause DirectInputDisabled, or because of the "Rotation Anti-Lag system"
|
||||
// which start to rotate before the mouse is hid and message mode passed to RawMode
|
||||
// This can happens cause DirectInputDisabled, or because of the
|
||||
// "Rotation Anti-Lag system" which start to rotate before the mouse is hid
|
||||
// and message mode passed to RawMode
|
||||
//
|
||||
// If we are not on Windows; on X11 there is always StandardMove/CEventMouseMove.
|
||||
// Currently, there is only a direct input IMouseDevice, not available on X11.
|
||||
// On X11 and Cocoa, there is no MouseDevice, do it without.
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
extern IMouseDevice *MouseDevice;
|
||||
if (MouseDevice)
|
||||
{
|
||||
if( EventsListener.getMousePosX() != _LastFrameMousePosX ||
|
||||
EventsListener.getMousePosY() != _LastFrameMousePosY )
|
||||
{
|
||||
float dmpx= EventsListener.getMousePosX() - _LastFrameMousePosX;
|
||||
float dmpy= EventsListener.getMousePosY() - _LastFrameMousePosY;
|
||||
// simulate mickeys mode
|
||||
MouseDevice->convertStdMouseMoveInMickeys(dmpx, dmpy);
|
||||
if(ClientCfg.FreeLookInverted) dmpy = -dmpy;
|
||||
// update free look
|
||||
EventsListener.updateFreeLookPos(dmpx, dmpy);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// On X11 and Mac, do the thing without IMouseDevice implementation
|
||||
|
||||
// if the mouse position changed
|
||||
if( EventsListener.getMousePosX() != _LastFrameMousePosX ||
|
||||
EventsListener.getMousePosY() != _LastFrameMousePosY )
|
||||
{
|
||||
float dmpx, dmpy;
|
||||
|
||||
// On X11 and Cocoa in free look mode, the mouse is pulled back to (0.5, 0.5)
|
||||
// every update to prevent reaching a border and get stuck.
|
||||
if(IsMouseFreeLook())
|
||||
{
|
||||
/*
|
||||
TODO on X11, use setCapture to not fake it, capture on mac?
|
||||
*/
|
||||
dmpx = EventsListener.getMousePosX() - 0.5;
|
||||
dmpy = EventsListener.getMousePosY() - 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
dmpx = EventsListener.getMousePosX() - _LastFrameMousePosX;
|
||||
dmpy = EventsListener.getMousePosY() - _LastFrameMousePosY;
|
||||
}
|
||||
|
||||
// TODO: read desktop mouse speed value on X11 and Cocoa
|
||||
// implement X11MouseDevice/CocoaMouseDevice?
|
||||
dmpx *= 450.0f;
|
||||
dmpy *= 450.0f;
|
||||
// get the mouse movement delta
|
||||
float dmpx= EventsListener.getMousePosX() - _LastFrameMousePosX;
|
||||
float dmpy= EventsListener.getMousePosY() - _LastFrameMousePosY;
|
||||
|
||||
// simulate mickeys mode if there is a mouse device
|
||||
if (MouseDevice)
|
||||
MouseDevice->convertStdMouseMoveInMickeys(dmpx, dmpy);
|
||||
else
|
||||
{
|
||||
dmpx *= (float)Driver->getWindowWidth();
|
||||
dmpy *= (float)Driver->getWindowHeight();
|
||||
}
|
||||
|
||||
// handle inverted mouse, if enabled
|
||||
if(ClientCfg.FreeLookInverted) dmpy = -dmpy;
|
||||
|
||||
// update free look
|
||||
EventsListener.updateFreeLookPos(dmpx, dmpy);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If the mouse move on the axis X, with a CGDMouseMove
|
||||
if(EventsListener.isMouseAngleX())
|
||||
dx = -EventsListener.getMouseAngleX ();
|
||||
|
||||
// If the mouse move on the axis Y, with a CGDMouseMove
|
||||
if(EventsListener.isMouseAngleY())
|
||||
dy = EventsListener.getMouseAngleY ();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue