From 610a04982f828ef3bdf5262036f8d96242f52e88 Mon Sep 17 00:00:00 2001 From: rti Date: Fri, 11 Jun 2010 15:04:10 +0200 Subject: [PATCH] Fixed: #972 Do not reset mouse position to implement FreeLook (IDriver::InterfaceVersion = 0x66) --- code/nel/include/nel/3d/driver_user.h | 6 + code/nel/include/nel/3d/u_driver.h | 5 + code/nel/include/nel/misc/event_emitter.h | 14 +- code/nel/include/nel/misc/win_event_emitter.h | 3 + code/nel/src/3d/driver.cpp | 2 +- .../src/3d/driver/opengl/mac/cocoa_adapter.h | 3 + .../src/3d/driver/opengl/mac/cocoa_adapter.mm | 170 ++++++++++++------ .../driver/opengl/mac/cocoa_event_emitter.cpp | 6 + .../driver/opengl/mac/cocoa_event_emitter.h | 1 + .../3d/driver/opengl/unix_event_emitter.cpp | 60 +++++-- .../src/3d/driver/opengl/unix_event_emitter.h | 4 + code/nel/src/3d/driver_user.cpp | 6 + code/nel/src/misc/win_event_emitter.cpp | 7 + code/ryzom/client/src/events_listener.cpp | 5 - code/ryzom/client/src/input.cpp | 29 +-- .../ryzom/client/src/motion/user_controls.cpp | 68 +++---- 16 files changed, 260 insertions(+), 129 deletions(-) diff --git a/code/nel/include/nel/3d/driver_user.h b/code/nel/include/nel/3d/driver_user.h index e5a662d9a..1d2c2aaed 100644 --- a/code/nel/include/nel/3d/driver_user.h +++ b/code/nel/include/nel/3d/driver_user.h @@ -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 diff --git a/code/nel/include/nel/3d/u_driver.h b/code/nel/include/nel/3d/u_driver.h index 4e3126c4b..8201288c6 100644 --- a/code/nel/include/nel/3d/u_driver.h +++ b/code/nel/include/nel/3d/u_driver.h @@ -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; diff --git a/code/nel/include/nel/misc/event_emitter.h b/code/nel/include/nel/misc/event_emitter.h index 62ea5cb0c..e678c2674 100644 --- a/code/nel/include/nel/misc/event_emitter.h +++ b/code/nel/include/nel/misc/event_emitter.h @@ -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; }; diff --git a/code/nel/include/nel/misc/win_event_emitter.h b/code/nel/include/nel/misc/win_event_emitter.h index 9a0dd8768..0c0a611d5 100644 --- a/code/nel/include/nel/misc/win_event_emitter.h +++ b/code/nel/include/nel/misc/win_event_emitter.h @@ -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; diff --git a/code/nel/src/3d/driver.cpp b/code/nel/src/3d/driver.cpp index 063823433..b00c44388 100644 --- a/code/nel/src/3d/driver.cpp +++ b/code/nel/src/3d/driver.cpp @@ -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" ) diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.h b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.h index 334fa1664..4f89f97eb 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.h +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.h @@ -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 diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm index ded8c746b..f2dfdd517 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm @@ -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 + 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]; diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp index 4cef1c3a4..81225ab9a 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp @@ -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); +} + } diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h index 5763d53df..b31272b8f 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h @@ -26,6 +26,7 @@ class CCocoaEventEmitter : public IEventEmitter { public: virtual void submitEvents(CEventServer & server, bool allWindows); + virtual void emulateMouseRawMode(bool enable); }; } diff --git a/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp b/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp index 0f131fcab..69916cc5e 100644 --- a/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp +++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp @@ -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) diff --git a/code/nel/src/3d/driver/opengl/unix_event_emitter.h b/code/nel/src/3d/driver/opengl/unix_event_emitter.h index ea0dde021..45c5e868a 100644 --- a/code/nel/src/3d/driver/opengl/unix_event_emitter.h +++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.h @@ -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; }; diff --git a/code/nel/src/3d/driver_user.cpp b/code/nel/src/3d/driver_user.cpp index 89a1d0197..255d3e4ed 100644 --- a/code/nel/src/3d/driver_user.cpp +++ b/code/nel/src/3d/driver_user.cpp @@ -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; diff --git a/code/nel/src/misc/win_event_emitter.cpp b/code/nel/src/misc/win_event_emitter.cpp index 0c9a6ad3c..57924c06c 100644 --- a/code/nel/src/misc/win_event_emitter.cpp +++ b/code/nel/src/misc/win_event_emitter.cpp @@ -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() diff --git a/code/ryzom/client/src/events_listener.cpp b/code/ryzom/client/src/events_listener.cpp index 91379c8ca..82b01271d 100644 --- a/code/ryzom/client/src/events_listener.cpp +++ b/code/ryzom/client/src/events_listener.cpp @@ -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) diff --git a/code/ryzom/client/src/input.cpp b/code/ryzom/client/src/input.cpp index b4bd5359d..483abdd0c 100644 --- a/code/ryzom/client/src/input.cpp +++ b/code/ryzom/client/src/input.cpp @@ -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 } diff --git a/code/ryzom/client/src/motion/user_controls.cpp b/code/ryzom/client/src/motion/user_controls.cpp index 69e2efeea..e5a3a58be 100644 --- a/code/ryzom/client/src/motion/user_controls.cpp +++ b/code/ryzom/client/src/motion/user_controls.cpp @@ -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 (); - - }