diff --git a/code/nel/include/nel/gui/input_event_listener.h b/code/nel/include/nel/gui/input_event_listener.h new file mode 100644 index 000000000..753b4f337 --- /dev/null +++ b/code/nel/include/nel/gui/input_event_listener.h @@ -0,0 +1,36 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef INPUTEVENTLISTENER_H +#define INPUTEVENTLISTENER_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/event_descriptor.h" + +namespace NLGUI +{ + /** + @brief Interface for accepting GUI input events. + */ + class IInputEventListener + { + public: + virtual ~IInputEventListener(){} + virtual bool handleEvent( const CEventDescriptor &eventDesc ) = 0; + }; +} + +#endif diff --git a/code/nel/include/nel/gui/input_handler.h b/code/nel/include/nel/gui/input_handler.h new file mode 100644 index 000000000..3ac66ac98 --- /dev/null +++ b/code/nel/include/nel/gui/input_handler.h @@ -0,0 +1,57 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef INPUT_HANDLER_H +#define INPUT_HANDLER_H + +#include "nel/misc/events.h" +#include "nel/gui/event_descriptor.h" +#include "nel/gui/input_event_listener.h" + +namespace NLGUI{ + + /** + @brief The input event entry point of the GUI library. + + Translates the NEL input events and forwards them. + */ + class CInputHandler + { + public: + CInputHandler(); + ~CInputHandler(); + + bool handleEvent( const NLMISC::CEvent &evnt ); + bool handleSetFocusEvent( const NLMISC::CEvent &evnt ); + bool handleKeyboardEvent( const NLMISC::CEvent &evnt ); + bool handleMouseEvent( const NLMISC::CEvent &evnt ); + bool handleMouseMoveEvent( const NLMISC::CEvent &evnt ); + bool handleMouseButtonDownEvent( const NLMISC::CEvent &evnt ); + bool handleMouseButtonUpEvent( const NLMISC::CEvent &evnt ); + bool handleMouseDblClickEvent( const NLMISC::CEvent &evnt ); + bool handleMouseWheelEvent( const NLMISC::CEvent &evnt ); + + void setListener( IInputEventListener* listener ); + + private: + IInputEventListener *listener; + }; + +} + +#endif + diff --git a/code/nel/src/gui/input_handler.cpp b/code/nel/src/gui/input_handler.cpp new file mode 100644 index 000000000..594773a3e --- /dev/null +++ b/code/nel/src/gui/input_handler.cpp @@ -0,0 +1,212 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/gui/input_handler.h" + +namespace NLGUI +{ + CInputHandler::CInputHandler() + { + listener = NULL; + } + + CInputHandler::~CInputHandler() + { + listener = NULL; + } + + + bool CInputHandler::handleEvent( const NLMISC::CEvent &evnt ) + { + if( evnt == NLMISC::EventSetFocusId ) + return handleSetFocusEvent( evnt ); + else + if( evnt == NLMISC::EventKeyDownId || + evnt == NLMISC::EventKeyUpId || + evnt == NLMISC::EventCharId || + evnt == NLMISC::EventStringId ) + return handleKeyboardEvent( evnt ); + else + if( evnt == NLMISC::EventMouseMoveId || + evnt == NLMISC::EventMouseDownId || + evnt == NLMISC::EventMouseUpId || + evnt == NLMISC::EventMouseWheelId || + evnt == NLMISC::EventMouseDblClkId ) + return handleMouseEvent( evnt ); + + + return false; + } + + bool CInputHandler::handleSetFocusEvent( const NLMISC::CEvent &evnt ) + { + nlassert( evnt == NLMISC::EventSetFocusId ); + const NLMISC::CEventSetFocus *e = reinterpret_cast< const NLMISC::CEventSetFocus* >( &evnt ); + + return listener->handleEvent( CEventDescriptorSetFocus( e->Get ) ); + } + + bool CInputHandler::handleKeyboardEvent( const NLMISC::CEvent &evnt ) + { + bool ok = false; + if( evnt == NLMISC::EventKeyDownId || + evnt == NLMISC::EventKeyUpId || + evnt == NLMISC::EventCharId || + evnt == NLMISC::EventStringId ) + ok = true; + + nlassert( ok ); + + return listener->handleEvent( NLGUI::CEventDescriptorKey( reinterpret_cast< const NLMISC::CEventKey& >( evnt ) ) ); + } + + bool CInputHandler::handleMouseEvent( const NLMISC::CEvent &evnt ) + { + if( evnt == NLMISC::EventMouseMoveId ) + return handleMouseMoveEvent( evnt ); + else + if( evnt == NLMISC::EventMouseDownId ) + return handleMouseButtonDownEvent( evnt ); + else + if( evnt == NLMISC::EventMouseUpId ) + return handleMouseButtonUpEvent( evnt ); + else + if( evnt == NLMISC::EventMouseDblClkId ) + return handleMouseDblClickEvent( evnt ); + else + if( evnt == NLMISC::EventMouseWheelId ) + return handleMouseWheelEvent( evnt ); + + return false; + } + + bool CInputHandler::handleMouseMoveEvent( const NLMISC::CEvent &evnt ) + { + const NLMISC::CEventMouseMove &mouseMoveEvent = static_cast< const NLMISC::CEventMouseMove& >( evnt ); + + CEventDescriptorMouse eventDesc; + float x = mouseMoveEvent.X; + float y = mouseMoveEvent.Y; + + // These bloody hacks here are used so that we can send the x, and y float coordinates + // from the NEL mouse move event, to the GUI event listener, without having to change + // CEventDescriptorMouse or without having to couple with the consumer class + eventDesc.setX( *reinterpret_cast< sint32* >( &x ) ); + eventDesc.setY( *reinterpret_cast< sint32* >( &y ) ); + + eventDesc.setEventTypeExtended( CEventDescriptorMouse::mousemove ); + + return listener->handleEvent( eventDesc ); + } + + bool CInputHandler::handleMouseButtonDownEvent( const NLMISC::CEvent &evnt ) + { + nlassert( evnt == NLMISC::EventMouseDownId ); + + CEventDescriptorMouse eventDesc; + + const NLMISC::CEventMouseDown *mouseDownEvent = static_cast< const NLMISC::CEventMouseDown* >( &evnt ); + + if( mouseDownEvent->Button & NLMISC::leftButton ) + { + eventDesc.setEventTypeExtended( CEventDescriptorMouse::mouseleftdown ); + return listener->handleEvent( eventDesc ); + } + + if(mouseDownEvent->Button & NLMISC::rightButton) + { + eventDesc.setEventTypeExtended( CEventDescriptorMouse::mouserightdown ); + return listener->handleEvent( eventDesc ); + } + + return false; + } + + bool CInputHandler::handleMouseButtonUpEvent( const NLMISC::CEvent &evnt ) + { + nlassert( evnt == NLMISC::EventMouseUpId ); + + CEventDescriptorMouse eventDesc; + + const NLMISC::CEventMouseUp *mouseUpEvent = static_cast< const NLMISC::CEventMouseUp* >( &evnt ); + + if( mouseUpEvent->Button & NLMISC::leftButton ) + { + eventDesc.setEventTypeExtended( CEventDescriptorMouse::mouseleftup ); + return listener->handleEvent( eventDesc ); + } + + if( mouseUpEvent->Button & NLMISC::rightButton ) + { + eventDesc.setEventTypeExtended( CEventDescriptorMouse::mouserightup ); + return listener->handleEvent( eventDesc ); + } + + return false; + } + + bool CInputHandler::handleMouseDblClickEvent( const NLMISC::CEvent &evnt ) + { + nlassert( evnt == NLMISC::EventMouseDblClkId ); + + CEventDescriptorMouse eventDesc; + + const NLMISC::CEventMouseDblClk *dblClickEvent = static_cast< const NLMISC::CEventMouseDblClk* >( &evnt ); + + if( dblClickEvent->Button & NLMISC::leftButton ) + { + eventDesc.setEventTypeExtended( CEventDescriptorMouse::mouseleftdblclk ); + return listener->handleEvent (eventDesc); + } + + if( dblClickEvent->Button & NLMISC::rightButton ) + { + eventDesc.setEventTypeExtended(NLGUI::CEventDescriptorMouse::mouserightdblclk); + return listener->handleEvent (eventDesc); + } + + return false; + } + + bool CInputHandler::handleMouseWheelEvent( const NLMISC::CEvent &evnt ) + { + nlassert( evnt == NLMISC::EventMouseWheelId ); + + CEventDescriptorMouse eventDesc; + sint32 mouseWheel = 0; + + const NLMISC::CEventMouseWheel *wheelEvent = static_cast< const NLMISC::CEventMouseWheel* >( &evnt ); + + if( wheelEvent->Direction ) + mouseWheel = 1; + else + mouseWheel = -1; + + if( mouseWheel != 0 ) + { + eventDesc.setEventTypeExtended( CEventDescriptorMouse::mousewheel ); + eventDesc.setWheel( mouseWheel ); + return listener->handleEvent( eventDesc ); + } + + return false; + } + + void CInputHandler::setListener( IInputEventListener *listener ) + { + this->listener = listener; + } +} diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index e9d60774e..e64c0df94 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -1067,6 +1067,13 @@ void prelogInit() if(GenericMat.empty()) nlerror("init: Cannot Create the generic material."); + + // Create a text context. We need to put the full path because we not already add search path +// resetTextContext ("bremenb.ttf", false); + resetTextContext ("ryzom.ttf", false); + + CInterfaceManager::create( Driver, TextContext ); + // Yoyo: initialize NOW the InputHandler for Event filtering. CInputHandlerManager *InputHandlerManager = CInputHandlerManager::getInstance(); InputHandlerManager->addToServer (&Driver->EventServer); @@ -1075,12 +1082,6 @@ void prelogInit() if( !filename.empty() ) InputHandlerManager->readInputConfigFile( filename ); - // Create a text context. We need to put the full path because we not already add search path -// resetTextContext ("bremenb.ttf", false); - resetTextContext ("ryzom.ttf", false); - - CInterfaceManager::create( Driver, TextContext ); - ProgressBar.setFontFactor(0.85f); nmsg = "Loading background..."; diff --git a/code/ryzom/client/src/interface_v3/input_handler_manager.cpp b/code/ryzom/client/src/interface_v3/input_handler_manager.cpp index 87a20d35a..18420ef82 100644 --- a/code/ryzom/client/src/interface_v3/input_handler_manager.cpp +++ b/code/ryzom/client/src/interface_v3/input_handler_manager.cpp @@ -59,14 +59,14 @@ CInputHandlerManager* CInputHandlerManager::_Instance = NULL; CInputHandlerManager::CInputHandlerManager() { _EventServer= NULL; - _MouseButtonsReleased = noButton; - _MouseButtonsDown = noButton; _MouseButtonsState = noButton; _MouseX = _MouseY = _MouseLastX = _MouseLastY = 0; _Focus = true; _MouseWheel = 0; _SkipInterfaceManager=false; _RecoverFocusLost = false; + + inputHandler.setListener( CInterfaceManager::getInstance() ); } // *************************************************************************** @@ -153,24 +153,13 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) if (!pEvent->Get) { // Deactivate all keys - _MouseButtonsDown = noButton; - _MouseButtonsReleased = noButton; _MouseButtonsState = noButton; _Focus = false; if (!_SkipInterfaceManager) { // if there was some control capturing the mouse, warn them that they lost the focus - if (pIM->getCapturePointerLeft()) - { - pIM->getCapturePointerLeft()->handleEvent(NLGUI::CEventDescriptorSetFocus(pEvent->Get)); - } - pIM->setCapturePointerLeft(NULL); - if (pIM->getCapturePointerRight()) - { - pIM->getCapturePointerRight()->handleEvent(NLGUI::CEventDescriptorSetFocus(pEvent->Get)); - } - pIM->setCapturePointerRight(NULL); + inputHandler.handleSetFocusEvent( event ); UserControls.stopFreeLook(); } // be nice with other app : let the mouse reappear (useful in direct 3D mode with no hardware cursor) @@ -214,7 +203,6 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) return; } - // **** Event Focus // **** Event Keyboard @@ -224,7 +212,7 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) event == EventStringId) { // if not handled, post to Action Manager - if( !pIM->handleEvent( NLGUI::CEventDescriptorKey((const CEventKey &) event) ) ) + if( !inputHandler.handleKeyboardEvent( event ) ) { // See if handled by editor bool handled = false; @@ -283,6 +271,7 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) CViewPointer &rIP = *pIM->getPointer(); NLGUI::CEventDescriptorMouse eventDesc; + sint32 x,y; rIP.getPointerDispPos (x, y); eventDesc.setX (x); @@ -313,71 +302,18 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) handled |= R2::getEditor().handleEvent(eventDesc); } } - - CEventMouseDown *pEvent=(CEventMouseDown*)&event; - - // update states - _MouseButtonsDown = (TMouseButton) (_MouseButtonsDown | pEvent->Button); - _MouseButtonsReleased =(TMouseButton) (_MouseButtonsReleased & ~(pEvent->Button)); - _MouseButtonsState = (TMouseButton) (_MouseButtonsState | pEvent->Button); - - rIP.setButtonState(_MouseButtonsState); - - // handle Event - if(pEvent->Button & leftButton) - { - eventDesc.setEventTypeExtended(NLGUI::CEventDescriptorMouse::mouseleftdown); - handled|= pIM->handleEvent (eventDesc); - } - if(pEvent->Button & rightButton) - { - eventDesc.setEventTypeExtended(NLGUI::CEventDescriptorMouse::mouserightdown); - handled|= pIM->handleEvent (eventDesc); - } + handled |= inputHandler.handleMouseButtonDownEvent( event ); } // button up ? else if (event==EventMouseUpId) { - CEventMouseUp *pEvent=(CEventMouseUp*)&event; - - // update states - _MouseButtonsReleased = (TMouseButton) (_MouseButtonsReleased | pEvent->Button); - _MouseButtonsDown =(TMouseButton) (_MouseButtonsDown & ~(pEvent->Button)); - _MouseButtonsState = (TMouseButton) (_MouseButtonsState & ~(pEvent->Button)); - - rIP.setButtonState(_MouseButtonsState); - - // handle Event - if(pEvent->Button & leftButton) - { - eventDesc.setEventTypeExtended(NLGUI::CEventDescriptorMouse::mouseleftup); - handled|= pIM->handleEvent (eventDesc); - } - if(pEvent->Button & rightButton) - { - eventDesc.setEventTypeExtended(NLGUI::CEventDescriptorMouse::mouserightup); - handled|= pIM->handleEvent (eventDesc); - } + handled |= inputHandler.handleMouseButtonUpEvent( event ); } // db click ? else if (event == EventMouseDblClkId ) { // TODO: yoyo make it work if needed (for now, seems preferable to manage in each ActionHandler) - - CEventMouseDblClk* pEvent=(CEventMouseDblClk*)&event; - - // handle Event - if(pEvent->Button & leftButton) - { - eventDesc.setEventTypeExtended(NLGUI::CEventDescriptorMouse::mouseleftdblclk); - handled|= pIM->handleEvent (eventDesc); - } - if(pEvent->Button & rightButton) - { - eventDesc.setEventTypeExtended(NLGUI::CEventDescriptorMouse::mouserightdblclk); - handled|= pIM->handleEvent (eventDesc); - } - + handled |= inputHandler.handleMouseDblClickEvent( event ); } // mouse move? else if(event == EventMouseMoveId) @@ -386,20 +322,7 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) } else if (event == EventMouseWheelId) { - CEventMouseWheel *pEvent=(CEventMouseWheel*)&event; - if (pEvent->Direction) - _MouseWheel += 1; - else - _MouseWheel -= 1; - - // handle Event now. - if (_MouseWheel != 0) - { - eventDesc.setEventTypeExtended(NLGUI::CEventDescriptorMouse::mousewheel); - eventDesc.setWheel(_MouseWheel); - handled|= pIM->handleEvent (eventDesc); - _MouseWheel = 0; - } + handled |= inputHandler.handleMouseWheelEvent( event ); } } @@ -432,39 +355,8 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) bool CInputHandlerManager::updateMousePos(NLMISC::CEventMouse &event, NLGUI::CEventDescriptorMouse &eventDesc) { if (!IsMouseFreeLook()) - { - CEventMouseMove* mouseEvent=(CEventMouseMove*)&event; - uint32 w, h; - CInterfaceManager::getInstance()->getViewRenderer().getScreenSize(w, h); + return inputHandler.handleMouseMoveEvent( event ); - // compute new coords - _MouseLastX = _MouseX; - _MouseLastY = _MouseY; - _MouseX = (sint32)(mouseEvent->X*w + 0.5f); - _MouseY = (sint32)(mouseEvent->Y*h + 0.5f); - - // Process Move message only if not Null move - if(_MouseX!=_MouseLastX || _MouseY!=_MouseLastY) - { - // Move the pointer - //pIM->movePointer (_MouseX-_MouseLastX, _MouseY-_MouseLastY); - - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - - pIM->movePointerAbs(_MouseX, _MouseY); - - CViewPointer &rIP = *pIM->getPointer(); - // get new pointer pos. - sint32 x,y; - rIP.getPointerDispPos (x, y); - eventDesc.setX (x); - eventDesc.setY (y); - - // handle Event now. - eventDesc.setEventTypeExtended(NLGUI::CEventDescriptorMouse::mousemove); - return pIM->handleEvent (eventDesc); - } - } return false; } diff --git a/code/ryzom/client/src/interface_v3/input_handler_manager.h b/code/ryzom/client/src/interface_v3/input_handler_manager.h index 9f152c87c..085806122 100644 --- a/code/ryzom/client/src/interface_v3/input_handler_manager.h +++ b/code/ryzom/client/src/interface_v3/input_handler_manager.h @@ -25,6 +25,7 @@ #include #include #include "nel/gui/event_descriptor.h" +#include "nel/gui/input_handler.h" /** @@ -38,9 +39,6 @@ * \date 2002 */ -class CInputHandlerBase; -class CViewText; - class CInputHandlerManager : public NLMISC::IEventListener { @@ -133,8 +131,6 @@ private: NLMISC::CEventServer* _EventServer; // Mouse Infos - NLMISC::TMouseButton _MouseButtonsReleased; - NLMISC::TMouseButton _MouseButtonsDown; NLMISC::TMouseButton _MouseButtonsState; sint32 _MouseX, _MouseY; @@ -180,6 +176,8 @@ private: // return true if handled bool updateMousePos(NLMISC::CEventMouse &event, NLGUI::CEventDescriptorMouse &eventDesc); + NLGUI::CInputHandler inputHandler; + }; #endif // NL_INPUT_HANDLER_MANAGER_H diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 41d736448..135d6812a 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -2675,6 +2675,25 @@ bool CInterfaceManager::handleEvent (const NLGUI::CEventDescriptor& event) { bool handled= false; + if( event.getType() == NLGUI::CEventDescriptor::system ) + { + const NLGUI::CEventDescriptorSystem &eventDesc = reinterpret_cast< const NLGUI::CEventDescriptorSystem& >( event ); + if( eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorSystem::setfocus ) + { + if( _CapturePointerLeft != NULL ) + { + _CapturePointerLeft->handleEvent( event ); + setCapturePointerLeft( NULL ); + } + + if( _CapturePointerRight != NULL ) + { + _CapturePointerRight->handleEvent( event ); + setCapturePointerRight( NULL ); + } + } + } + // Check if we can receive events (no anims!) for (uint i = 0; i < _ActiveAnims.size(); ++i) if (_ActiveAnims[i]->isDisableButtons()) @@ -2802,260 +2821,280 @@ bool CInterfaceManager::handleEvent (const NLGUI::CEventDescriptor& event) return result; } } - else if (event.getType() == NLGUI::CEventDescriptor::mouse && _MouseHandlingEnabled ) + else if (event.getType() == NLGUI::CEventDescriptor::mouse ) { NLGUI::CEventDescriptorMouse &eventDesc = (NLGUI::CEventDescriptorMouse&)event; - // First thing to do : Capture handling - if (_CapturePointerLeft != NULL) - handled|= _CapturePointerLeft->handleEvent(event); + if( eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown ) + _Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() | NLMISC::leftButton ) ); + else + if( eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown ) + _Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() | NLMISC::rightButton ) ); + else + if( eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup ) + _Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() & ~NLMISC::leftButton ) ); + if( eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup ) + _Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() & ~NLMISC::rightButton ) ); - if (_CapturePointerRight != NULL && _CapturePointerRight!=_CapturePointerLeft) - handled|= _CapturePointerRight->handleEvent(event); + if( eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousemove ) + handleMouseMoveEvent( eventDesc ); - CInterfaceGroup *ptr = getWindowUnder (eventDesc.getX(), eventDesc.getY()); - _WindowUnder = ptr?ptr->getId():""; + eventDesc.setX( _Pointer->getX() ); + eventDesc.setY( _Pointer->getY() ); - // Any Mouse event but move disable the ContextHelp - if(eventDesc.getEventTypeExtended() != NLGUI::CEventDescriptorMouse::mousemove) + if( _MouseHandlingEnabled ) { - disableContextHelp(); - } + // First thing to do : Capture handling + if (_CapturePointerLeft != NULL) + handled|= _CapturePointerLeft->handleEvent(event); - // get the group under the mouse - CInterfaceGroup *pNewCurrentWnd = _WindowUnder; - _MouseOverWindow= pNewCurrentWnd!=NULL; + if (_CapturePointerRight != NULL && _CapturePointerRight!=_CapturePointerLeft) + handled|= _CapturePointerRight->handleEvent(event); + CInterfaceGroup *ptr = getWindowUnder (eventDesc.getX(), eventDesc.getY()); + _WindowUnder = ptr?ptr->getId():""; - NLMISC::CRefPtr clickedOutModalWindow; - - // modal special features - if (!_ModalStack.empty()) - { - CModalWndInfo mwi = _ModalStack.back(); - if(mwi.ModalWindow) + // Any Mouse event but move disable the ContextHelp + if(eventDesc.getEventTypeExtended() != NLGUI::CEventDescriptorMouse::mousemove) { - // If we are not in "click out" mode so we dont handle controls other than those of the modal - if (pNewCurrentWnd != mwi.ModalWindow && !mwi.ModalExitClickOut) - { - pNewCurrentWnd = NULL; - } - else - { - // If there is a handler on click out launch it - if (pNewCurrentWnd != mwi.ModalWindow) - if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown || - (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown)) - if (!mwi.ModalHandlerClickOut.empty()) - runActionHandler(mwi.ModalHandlerClickOut,NULL,mwi.ModalClickOutParams); + disableContextHelp(); + } - // If the current window is not the modal and if must quit on click out - if(pNewCurrentWnd != mwi.ModalWindow && mwi.ModalExitClickOut) + // get the group under the mouse + CInterfaceGroup *pNewCurrentWnd = _WindowUnder; + _MouseOverWindow= pNewCurrentWnd!=NULL; + + + NLMISC::CRefPtr clickedOutModalWindow; + + // modal special features + if (!_ModalStack.empty()) + { + CModalWndInfo mwi = _ModalStack.back(); + if(mwi.ModalWindow) + { + // If we are not in "click out" mode so we dont handle controls other than those of the modal + if (pNewCurrentWnd != mwi.ModalWindow && !mwi.ModalExitClickOut) { - // NB: don't force handle==true because to quit a modal does not avoid other actions + pNewCurrentWnd = NULL; + } + else + { + // If there is a handler on click out launch it + if (pNewCurrentWnd != mwi.ModalWindow) + if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown || + (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown)) + if (!mwi.ModalHandlerClickOut.empty()) + runActionHandler(mwi.ModalHandlerClickOut,NULL,mwi.ModalClickOutParams); - // quit if click outside - if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown || - (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown)) + // If the current window is not the modal and if must quit on click out + if(pNewCurrentWnd != mwi.ModalWindow && mwi.ModalExitClickOut) { - clickedOutModalWindow = dynamic_cast((CInterfaceGroup*)mwi.ModalWindow); - // disable the modal - popModalWindow(); - if (!_ModalStack.empty()) + // NB: don't force handle==true because to quit a modal does not avoid other actions + + // quit if click outside + if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown || + (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown)) { - // don't handle event unless it is a previous modal window - uint k = 0; - for(k = 0; k < _ModalStack.size(); ++k) + clickedOutModalWindow = dynamic_cast((CInterfaceGroup*)mwi.ModalWindow); + // disable the modal + popModalWindow(); + if (!_ModalStack.empty()) { - if (_ModalStack[k].ModalWindow == pNewCurrentWnd) + // don't handle event unless it is a previous modal window + uint k = 0; + for(k = 0; k < _ModalStack.size(); ++k) { - break; + if (_ModalStack[k].ModalWindow == pNewCurrentWnd) + { + break; + } + } + if (k == _ModalStack.size()) + { + pNewCurrentWnd = NULL; // can't handle event before we have left all modal windows } } - if (k == _ModalStack.size()) - { - pNewCurrentWnd = NULL; // can't handle event before we have left all modal windows - } + movePointer (0,0); // Reget controls under pointer } - movePointer (0,0); // Reget controls under pointer } } } } - } - // Manage LeftClick. - if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown) - { - if ((pNewCurrentWnd != NULL) && (_ModalStack.empty()) && (pNewCurrentWnd->getOverlappable())) + // Manage LeftClick. + if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown) { - CGroupContainer *pGC = dynamic_cast(pNewCurrentWnd); - if (pGC != NULL) + if ((pNewCurrentWnd != NULL) && (_ModalStack.empty()) && (pNewCurrentWnd->getOverlappable())) { - if (!pGC->isGrayed()) setTopWindow(pNewCurrentWnd); + CGroupContainer *pGC = dynamic_cast(pNewCurrentWnd); + if (pGC != NULL) + { + if (!pGC->isGrayed()) setTopWindow(pNewCurrentWnd); + } + else + { + setTopWindow(pNewCurrentWnd); + } } - else + + // must not capture a new element if a sheet is currentlty being dragged. + // This may happen when alt-tab has been used => the sheet is dragged but the left button is up + if (!CDBCtrlSheet::getDraggedSheet()) { - setTopWindow(pNewCurrentWnd); + // Take the top most control. + uint nMaxDepth = 0; + for (sint32 i = (sint32)_CtrlsUnderPointer.size()-1; i >= 0; i--) + { + CCtrlBase *ctrl= _CtrlsUnderPointer[i]; + if (ctrl && ctrl->isCapturable() && isControlInWindow(ctrl, pNewCurrentWnd)) + { + uint d = getDepth(ctrl, pNewCurrentWnd); + if (d > nMaxDepth) + { + nMaxDepth = d; + _CapturePointerLeft = ctrl; + } + } + } + notifyElementCaptured(_CapturePointerLeft); + if (clickedOutModalWindow && !clickedOutModalWindow->OnPostClickOut.empty()) + { + runActionHandler(clickedOutModalWindow->OnPostClickOut, _CapturePointerLeft, clickedOutModalWindow->OnPostClickOutParams); + } + } + //if found + if (_CapturePointerLeft != NULL) + { + // consider clicking on a control implies handling of the event. + handled= true; + + // handle the capture + _CapturePointerLeft->handleEvent(event); } } - // must not capture a new element if a sheet is currentlty being dragged. - // This may happen when alt-tab has been used => the sheet is dragged but the left button is up - if (!CDBCtrlSheet::getDraggedSheet()) + // Manage RightClick + if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown) { + if ((pNewCurrentWnd != NULL) && (_ModalStack.empty()) && (pNewCurrentWnd->getOverlappable())) + { + CGroupContainer *pGC = dynamic_cast(pNewCurrentWnd); + if (pGC != NULL) + { + if (!pGC->isGrayed()) setTopWindow(pNewCurrentWnd); + } + else + { + setTopWindow(pNewCurrentWnd); + } + } + // Take the top most control. - uint nMaxDepth = 0; - for (sint32 i = (sint32)_CtrlsUnderPointer.size()-1; i >= 0; i--) { - CCtrlBase *ctrl= _CtrlsUnderPointer[i]; - if (ctrl && ctrl->isCapturable() && isControlInWindow(ctrl, pNewCurrentWnd)) + uint nMaxDepth = 0; + for (sint32 i = (sint32)_CtrlsUnderPointer.size()-1; i >= 0; i--) { - uint d = getDepth(ctrl, pNewCurrentWnd); - if (d > nMaxDepth) + CCtrlBase *ctrl= _CtrlsUnderPointer[i]; + if (ctrl && ctrl->isCapturable() && isControlInWindow(ctrl, pNewCurrentWnd)) { - nMaxDepth = d; - _CapturePointerLeft = ctrl; + uint d = getDepth(ctrl , pNewCurrentWnd); + if (d > nMaxDepth) + { + nMaxDepth = d; + _CapturePointerRight = ctrl; + } } } - } - notifyElementCaptured(_CapturePointerLeft); - if (clickedOutModalWindow && !clickedOutModalWindow->OnPostClickOut.empty()) - { - runActionHandler(clickedOutModalWindow->OnPostClickOut, _CapturePointerLeft, clickedOutModalWindow->OnPostClickOutParams); - } - } - //if found - if (_CapturePointerLeft != NULL) - { - // consider clicking on a control implies handling of the event. - handled= true; - - // handle the capture - _CapturePointerLeft->handleEvent(event); - } - } - - // Manage RightClick - if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown) - { - if ((pNewCurrentWnd != NULL) && (_ModalStack.empty()) && (pNewCurrentWnd->getOverlappable())) - { - CGroupContainer *pGC = dynamic_cast(pNewCurrentWnd); - if (pGC != NULL) - { - if (!pGC->isGrayed()) setTopWindow(pNewCurrentWnd); - } - else - { - setTopWindow(pNewCurrentWnd); - } - } - - // Take the top most control. - { - uint nMaxDepth = 0; - for (sint32 i = (sint32)_CtrlsUnderPointer.size()-1; i >= 0; i--) - { - CCtrlBase *ctrl= _CtrlsUnderPointer[i]; - if (ctrl && ctrl->isCapturable() && isControlInWindow(ctrl, pNewCurrentWnd)) + notifyElementCaptured(_CapturePointerRight); + if (clickedOutModalWindow && !clickedOutModalWindow->OnPostClickOut.empty()) { - uint d = getDepth(ctrl , pNewCurrentWnd); - if (d > nMaxDepth) - { - nMaxDepth = d; - _CapturePointerRight = ctrl; - } + runActionHandler(clickedOutModalWindow->OnPostClickOut, _CapturePointerRight, clickedOutModalWindow->OnPostClickOutParams); } } - notifyElementCaptured(_CapturePointerRight); - if (clickedOutModalWindow && !clickedOutModalWindow->OnPostClickOut.empty()) + //if found + if (_CapturePointerRight != NULL) { - runActionHandler(clickedOutModalWindow->OnPostClickOut, _CapturePointerRight, clickedOutModalWindow->OnPostClickOutParams); + // handle the capture + handled |= _CapturePointerRight->handleEvent(event); } } - //if found - if (_CapturePointerRight != NULL) - { - // handle the capture - handled |= _CapturePointerRight->handleEvent(event); + if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup) + { + if (!handled) + if (pNewCurrentWnd != NULL) + pNewCurrentWnd->handleEvent(event); + if (_CapturePointerRight != NULL) + { + EventsListener.addUIHandledButtonMask(rightButton); // prevent 'click in scene' as mouse was previously captured + // (more a patch that anything, but 'UserControls' test for 'mouse up' + // directly later in the main loop (not through message queue), so it has no way of knowing that the event was handled... + setCapturePointerRight(NULL); + handled= true; + } } - } - if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup) - { + + // window handling. if not handled by a control if (!handled) - if (pNewCurrentWnd != NULL) - pNewCurrentWnd->handleEvent(event); - if (_CapturePointerRight != NULL) { - EventsListener.addUIHandledButtonMask(rightButton); // prevent 'click in scene' as mouse was previously captured - // (more a patch that anything, but 'UserControls' test for 'mouse up' - // directly later in the main loop (not through message queue), so it has no way of knowing that the event was handled... - setCapturePointerRight(NULL); - handled= true; - } - } - - // window handling. if not handled by a control - if (!handled) - { - if (((pNewCurrentWnd != NULL) && _ModalStack.empty()) || ((!_ModalStack.empty() && _ModalStack.back().ModalWindow == pNewCurrentWnd))) - { - NLGUI::CEventDescriptorMouse ev2 = eventDesc; - sint32 x= eventDesc.getX(), y = eventDesc.getY(); - if (pNewCurrentWnd) + if (((pNewCurrentWnd != NULL) && _ModalStack.empty()) || ((!_ModalStack.empty() && _ModalStack.back().ModalWindow == pNewCurrentWnd))) { - pNewCurrentWnd->absoluteToRelative (x, y); - ev2.setX (x); ev2.setY (y); - handled|= pNewCurrentWnd->handleEvent (ev2); + NLGUI::CEventDescriptorMouse ev2 = eventDesc; + sint32 x= eventDesc.getX(), y = eventDesc.getY(); + if (pNewCurrentWnd) + { + pNewCurrentWnd->absoluteToRelative (x, y); + ev2.setX (x); ev2.setY (y); + handled|= pNewCurrentWnd->handleEvent (ev2); + } + + // After handle event of a left click, may set window Top if movable (infos etc...) + //if( (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown) && pNewCurrentWnd->isMovable() ) + // setTopWindow(pNewCurrentWnd); + } + } + + // Put here to let a chance to the window to handle if the capture dont + if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup) + { + if (_CapturePointerLeft != NULL) + { + EventsListener.addUIHandledButtonMask (leftButton); // prevent 'click in scene' as mouse was previously captured + // (more a patch that anything, but 'UserControls' test for 'mouse up' + // directly later in the main loop (not through message queue), so it has no way of knowing that the event was handled... + setCapturePointerLeft(NULL); + //handled= true; + } + } + + + // If the current window is the modal, may Modal quit. Do it after standard event handle + if(!_ModalStack.empty() && pNewCurrentWnd == _ModalStack.back().ModalWindow) + { + // NB: don't force handle==true because to quit a modal does not avoid other actions + CModalWndInfo mwi = _ModalStack.back(); + // and if must quit on click right + if(mwi.ModalExitClickR) + { + // quit if click right + if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup) + // disable the modal + disableModalWindow(); } - // After handle event of a left click, may set window Top if movable (infos etc...) - //if( (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown) && pNewCurrentWnd->isMovable() ) - // setTopWindow(pNewCurrentWnd); + // and if must quit on click left + if(mwi.ModalExitClickL) + { + // quit if click right + if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup) + // disable the modal + disableModalWindow(); + } } + + // If the mouse is over a window, always consider the event is taken (avoid click behind) + handled|= _MouseOverWindow; } - - // Put here to let a chance to the window to handle if the capture dont - if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup) - { - if (_CapturePointerLeft != NULL) - { - EventsListener.addUIHandledButtonMask (leftButton); // prevent 'click in scene' as mouse was previously captured - // (more a patch that anything, but 'UserControls' test for 'mouse up' - // directly later in the main loop (not through message queue), so it has no way of knowing that the event was handled... - setCapturePointerLeft(NULL); - //handled= true; - } - } - - - // If the current window is the modal, may Modal quit. Do it after standard event handle - if(!_ModalStack.empty() && pNewCurrentWnd == _ModalStack.back().ModalWindow) - { - // NB: don't force handle==true because to quit a modal does not avoid other actions - CModalWndInfo mwi = _ModalStack.back(); - // and if must quit on click right - if(mwi.ModalExitClickR) - { - // quit if click right - if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup) - // disable the modal - disableModalWindow(); - } - - // and if must quit on click left - if(mwi.ModalExitClickL) - { - // quit if click right - if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup) - // disable the modal - disableModalWindow(); - } - } - - // If the mouse is over a window, always consider the event is taken (avoid click behind) - handled|= _MouseOverWindow; } IngameDbMngr.flushObserverCalls(); @@ -3064,6 +3103,36 @@ bool CInterfaceManager::handleEvent (const NLGUI::CEventDescriptor& event) return handled; } +bool CInterfaceManager::handleMouseMoveEvent( const NLGUI::CEventDescriptor &eventDesc ) +{ + nlassert( eventDesc.getType() == NLGUI::CEventDescriptor::mouse ); + const NLGUI::CEventDescriptorMouse &e = static_cast< const NLGUI::CEventDescriptorMouse& >( eventDesc ); + nlassert( e.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousemove ); + + uint32 screenW, screenH; + _ViewRenderer.getScreenSize( screenW, screenH ); + sint32 oldX = _Pointer->getX(); + sint32 oldY = _Pointer->getY(); + + sint32 x = e.getX(); + sint32 y = e.getY(); + + // These are floats packed in the sint32 from the NEL events that provide them as float + // see comment in CInputHandler::handleMouseMoveEvent + sint32 newX = static_cast< sint32 >( std::floor( *reinterpret_cast< float* >( &x ) * screenW + 0.5f ) ); + sint32 newY = static_cast< sint32 >( std::floor( *reinterpret_cast< float* >( &y ) * screenH + 0.5f ) ); + + if( ( oldX != newX ) || ( oldY != newY ) ) + { + movePointerAbs( newX, newY ); + NLGUI::CEventDescriptorMouse &ve = const_cast< NLGUI::CEventDescriptorMouse& >( e ); + ve.setX( _Pointer->getX() ); + ve.setY( _Pointer->getY() ); + } + + return true; +} + // ------------------------------------------------------------------------------------------------ void CInterfaceManager::movePointer (sint32 dx, sint32 dy) { diff --git a/code/ryzom/client/src/interface_v3/interface_manager.h b/code/ryzom/client/src/interface_v3/interface_manager.h index 7fe26fc3e..3a5bccbb0 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.h +++ b/code/ryzom/client/src/interface_v3/interface_manager.h @@ -42,6 +42,8 @@ #include "interface_pointer.h" #include "flying_text_manager.h" +#include "nel/gui/input_event_listener.h" + // CLIENT #include "../string_manager_client.h" #include "yubo_chat.h" @@ -75,7 +77,7 @@ class CGroupMenu; * \author Nevrax France * \date 2002 */ -class CInterfaceManager : public CInterfaceParser, public NLMISC::CCDBManager +class CInterfaceManager : public CInterfaceParser, public NLMISC::CCDBManager, public NLGUI::IInputEventListener { public: @@ -339,6 +341,7 @@ public: /// Handle The Event. return true if the interfaceManager catch it and if must not send to the Game Action Manager bool handleEvent (const NLGUI::CEventDescriptor &eventDesc); + bool handleMouseMoveEvent( const NLGUI::CEventDescriptor &eventDesc ); void runActionHandler (const std::string &AHName, CCtrlBase *pCaller, const std::string &Params=std::string("")); void runActionHandler (IActionHandler *ah, CCtrlBase *pCaller,