From: Thomas Geymayer Date: Tue, 29 Jul 2014 22:00:03 +0000 (+0200) Subject: Canvas: Keyboard events and input focus. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=49df413444f19f2cc596e3c36850c00ac9c8d2f5;p=flightgear.git Canvas: Keyboard events and input focus. Also allow events on desktop group if no window is receiving events. Currently it is not possible to prevent events handled by the desktop group to further propagate (eg. to normal control input). --- diff --git a/src/Canvas/gui_mgr.cxx b/src/Canvas/gui_mgr.cxx index 1750f5a5b..a4a47ffa7 100644 --- a/src/Canvas/gui_mgr.cxx +++ b/src/Canvas/gui_mgr.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,8 @@ class DesktopGroup: { public: DesktopGroup(); + + void setFocusWindow(const sc::WindowPtr& window); bool handleEvent(const osgGA::GUIEventAdapter& ea); protected: @@ -114,7 +117,9 @@ class DesktopGroup: sc::WindowWeakPtr _last_push, _last_mouse_over, - _resize_window; + _resize_window, + _focus_window; + uint8_t _resize; int _last_cursor; @@ -123,7 +128,10 @@ class DesktopGroup: _last_y; double _last_scroll_time; + uint32_t _last_key_down_no_mod; // Key repeat for non modifier keys + bool handleMouse(const osgGA::GUIEventAdapter& ea); + bool handleKeyboard(const osgGA::GUIEventAdapter& ea); void handleResize(int x, int y, int width, int height); void handleMouseMode(SGPropertyNode* node); @@ -173,7 +181,8 @@ DesktopGroup::DesktopGroup(): _last_cursor(MOUSE_CURSOR_NONE), _last_x(-1), _last_y(-1), - _last_scroll_time(0) + _last_scroll_time(0), + _last_key_down_no_mod(-1) { osg::Camera* camera = flightgear::getGUICamera( flightgear::CameraGroup::getDefault() ); @@ -211,6 +220,9 @@ bool DesktopGroup::handleEvent(const osgGA::GUIEventAdapter& ea) case osgGA::GUIEventAdapter::MOVE: case osgGA::GUIEventAdapter::SCROLL: return handleMouse(ea); + case osgGA::GUIEventAdapter::KEYDOWN: + case osgGA::GUIEventAdapter::KEYUP: + return handleKeyboard(ea); case osgGA::GUIEventAdapter::RESIZE: handleResize( ea.getWindowX(), ea.getWindowY(), @@ -222,6 +234,12 @@ bool DesktopGroup::handleEvent(const osgGA::GUIEventAdapter& ea) } } +//------------------------------------------------------------------------------ +void DesktopGroup::setFocusWindow(const sc::WindowPtr& window) +{ + _focus_window = window; +} + /* RESIZE AREAS ============ @@ -247,7 +265,6 @@ bool DesktopGroup::handleMouse(const osgGA::GUIEventAdapter& ea) if( !_transform->getNumChildren() || !_handle_events ) return false; - namespace sc = simgear::canvas; sc::MouseEventPtr event(new sc::MouseEvent(ea)); event->screen_pos.x() = 0.5 * (ea.getXnormalized() + 1) * _width + 0.5; @@ -450,7 +467,54 @@ bool DesktopGroup::handleMouse(const osgGA::GUIEventAdapter& ea) return target_window->handleEvent(event); } else + { + // TODO somehow return if event has been consumed + sc::Element::handleEvent(event); return false; + } +} + +//------------------------------------------------------------------------------ +bool DesktopGroup::handleKeyboard(const osgGA::GUIEventAdapter& ea) +{ + if( !_transform->getNumChildren() || !_handle_events ) + return false; + + sc::WindowPtr active_window = _focus_window.lock(); + if( !active_window ) + { + int type = (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) + ? sc::Event::KEY_DOWN + : sc::Event::KEY_UP; + + if( !numEventHandler(type) ) + // TODO handle global shortcuts/grabs/etc. + return false; + } + + sc::KeyboardEventPtr event(new sc::KeyboardEvent(ea)); + + // Detect key repeat (of non modifier keys) + if( !event->isModifier() ) + { + if( event->type == sc::Event::KEY_DOWN ) + { + if( event->keyCode() == _last_key_down_no_mod ) + event->setRepeat(true); + _last_key_down_no_mod = event->keyCode(); + } + else + { + if( event->keyCode() == _last_key_down_no_mod ) + _last_key_down_no_mod = -1; + } + } + + if( active_window ) + return active_window->handleEvent(event); + + sc::Element::handleEvent(event); + return false; } //------------------------------------------------------------------------------ @@ -571,6 +635,12 @@ sc::GroupPtr GUIMgr::getDesktop() return _desktop; } +//------------------------------------------------------------------------------ +void GUIMgr::setInputFocus(const simgear::canvas::WindowPtr& window) +{ + static_cast(_desktop.get())->setFocusWindow(window); +} + //------------------------------------------------------------------------------ sc::Placements GUIMgr::addWindowPlacement( SGPropertyNode* placement, diff --git a/src/Canvas/gui_mgr.hxx b/src/Canvas/gui_mgr.hxx index c6764692c..c2cd341cd 100644 --- a/src/Canvas/gui_mgr.hxx +++ b/src/Canvas/gui_mgr.hxx @@ -52,6 +52,11 @@ class GUIMgr: */ simgear::canvas::GroupPtr getDesktop(); + /** + * Set the input (keyboard) focus to the given window. + */ + void setInputFocus(const simgear::canvas::WindowPtr& window); + protected: simgear::canvas::GroupPtr _desktop; diff --git a/src/Scripting/NasalCanvas.cxx b/src/Scripting/NasalCanvas.cxx index deee79324..637734c1c 100644 --- a/src/Scripting/NasalCanvas.cxx +++ b/src/Scripting/NasalCanvas.cxx @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,8 @@ naRef elementGetNode(Element& element, naContext c) typedef nasal::Ghost NasalEvent; typedef nasal::Ghost NasalCustomEvent; +typedef nasal::Ghost NasalDeviceEvent; +typedef nasal::Ghost NasalKeyboardEvent; typedef nasal::Ghost NasalMouseEvent; struct CustomEventDetailWrapper; @@ -177,6 +180,12 @@ naRef f_getDesktop(naContext c, naRef me, int argc, naRef* args) return nasal::to_nasal(c, requireGUIMgr(c).getDesktop()); } +naRef f_setInputFocus(const nasal::CallContext& ctx) +{ + requireGUIMgr(ctx.c).setInputFocus(ctx.requireArg(0)); + return naNil(); +} + static naRef f_groupCreateChild(sc::Group& group, const nasal::CallContext& ctx) { return ctx.to_nasal( group.createChild( ctx.requireArg(0), @@ -272,12 +281,6 @@ static naRef f_propElementData( simgear::PropertyBasedElement& el, return naNil(); } -template -naRef f_eventGetModifier(sc::MouseEvent& event, naContext) -{ - return naNum((event.getModifiers() & Mask) != 0); -} - static naRef f_createCustomEvent(const nasal::CallContext& ctx) { std::string const& type = ctx.requireArg(0); @@ -408,8 +411,24 @@ naRef initNasalCanvas(naRef globals, naContext c) canvas_module.createHash("CustomEvent") .set("new", &f_createCustomEvent); - NasalMouseEvent::init("canvas.MouseEvent") + NasalDeviceEvent::init("canvas.DeviceEvent") .bases() + .member("modifiers", &sc::DeviceEvent::getModifiers) + .member("ctrlKey", &sc::DeviceEvent::ctrlKey) + .member("shiftKey", &sc::DeviceEvent::shiftKey) + .member("altKey", &sc::DeviceEvent::altKey) + .member("metaKey", &sc::DeviceEvent::metaKey); + + NasalKeyboardEvent::init("canvas.KeyboardEvent") + .bases() + .member("key", &sc::KeyboardEvent::key) + .member("location", &sc::KeyboardEvent::location) + .member("repeat", &sc::KeyboardEvent::repeat) + .member("charCode", &sc::KeyboardEvent::charCode) + .member("keyCode", &sc::KeyboardEvent::keyCode); + + NasalMouseEvent::init("canvas.MouseEvent") + .bases() .member("screenX", &sc::MouseEvent::getScreenX) .member("screenY", &sc::MouseEvent::getScreenY) .member("clientX", &sc::MouseEvent::getClientX) @@ -420,11 +439,6 @@ naRef initNasalCanvas(naRef globals, naContext c) .member("deltaY", &sc::MouseEvent::getDeltaY) .member("button", &sc::MouseEvent::getButton) .member("buttons", &sc::MouseEvent::getButtonMask) - .member("modifiers", &sc::MouseEvent::getModifiers) - .member("ctrlKey", &f_eventGetModifier) - .member("shiftKey", &f_eventGetModifier) - .member("altKey", &f_eventGetModifier) - .member("metaKey", &f_eventGetModifier) .member("click_count", &sc::MouseEvent::getCurrentClickCount); //---------------------------------------------------------------------------- @@ -534,6 +548,7 @@ naRef initNasalCanvas(naRef globals, naContext c) canvas_module.set("_newWindowGhost", f_createWindow); canvas_module.set("_getDesktopGhost", f_getDesktop); + canvas_module.set("setInputFocus", f_setInputFocus); return naNil(); }