From: Thomas Geymayer Date: Tue, 29 Jul 2014 20:20:24 +0000 (+0200) Subject: Canvas: basic Keyboard event support (with input focus). X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=c5d649aa0b36939773b41acc88ed782976012c60;p=simgear.git Canvas: basic Keyboard event support (with input focus). --- diff --git a/simgear/canvas/Canvas.cxx b/simgear/canvas/Canvas.cxx index 5ca1eb95..0a6b2b48 100644 --- a/simgear/canvas/Canvas.cxx +++ b/simgear/canvas/Canvas.cxx @@ -20,6 +20,7 @@ #include "CanvasEventManager.hxx" #include "CanvasEventVisitor.hxx" #include "CanvasPlacement.hxx" +#include #include #include #include @@ -198,6 +199,19 @@ namespace canvas _layout->setCanvas(this); } + //---------------------------------------------------------------------------- + void Canvas::setFocusElement(const ElementPtr& el) + { + if( el && el->getCanvas().lock() != this ) + { + SG_LOG(SG_GUI, SG_WARN, "setFocusElement: element not from this canvas"); + return; + } + + // TODO focus out/in events + _focus_element = el; + } + //---------------------------------------------------------------------------- void Canvas::enableRendering(bool force) { @@ -448,6 +462,18 @@ namespace canvas return _event_manager->handleEvent(event, visitor.getPropagationPath()); } + //---------------------------------------------------------------------------- + bool Canvas::handleKeyboardEvent(const KeyboardEventPtr& event) + { + ElementPtr target = _focus_element.lock(); + if( !target ) + target = _root_group; + if( !target ) + return false; + + return target->dispatchEvent(event); + } + //---------------------------------------------------------------------------- bool Canvas::propagateEvent( EventPtr const& event, EventPropagationPath const& path ) diff --git a/simgear/canvas/Canvas.hxx b/simgear/canvas/Canvas.hxx index cf9ae2a5..8501b504 100644 --- a/simgear/canvas/Canvas.hxx +++ b/simgear/canvas/Canvas.hxx @@ -132,6 +132,15 @@ namespace canvas */ void setLayout(const LayoutRef& layout); + /** + * Set the focus to the given element. + * + * The focus element will receive all keyboard events propagated to this + * canvas. If there is no valid focus element the root group will receive + * the events instead. + */ + void setFocusElement(const ElementPtr& el); + /** * Enable rendering for the next frame * @@ -159,6 +168,8 @@ namespace canvas SGRect getViewport() const; bool handleMouseEvent(const MouseEventPtr& event); + bool handleKeyboardEvent(const KeyboardEventPtr& event); + bool propagateEvent( EventPtr const& event, EventPropagationPath const& path ); @@ -210,6 +221,8 @@ namespace canvas GroupPtr _root_group; LayoutRef _layout; + ElementWeakPtr _focus_element; + CullCallbackPtr _cull_callback; bool _render_always; //createChild("content"); _image_content->setSrcCanvas(content); + // Forward keyboard events to content + _image_content->setFocus(); + // Draw content on top of decoration _image_content->set("z-index", 1); } diff --git a/simgear/canvas/canvas_fwd.hxx b/simgear/canvas/canvas_fwd.hxx index b14d2886..3b1b4646 100644 --- a/simgear/canvas/canvas_fwd.hxx +++ b/simgear/canvas/canvas_fwd.hxx @@ -53,6 +53,8 @@ namespace canvas SG_FWD_DECL(Event) SG_FWD_DECL(CustomEvent) + SG_FWD_DECL(DeviceEvent) + SG_FWD_DECL(KeyboardEvent) SG_FWD_DECL(MouseEvent) #undef SG_FWD_DECL diff --git a/simgear/canvas/elements/CanvasElement.cxx b/simgear/canvas/elements/CanvasElement.cxx index 56219734..478cfb8b 100644 --- a/simgear/canvas/elements/CanvasElement.cxx +++ b/simgear/canvas/elements/CanvasElement.cxx @@ -303,6 +303,14 @@ namespace canvas _listener.clear(); } + //---------------------------------------------------------------------------- + void Element::setFocus() + { + CanvasPtr canvas = _canvas.lock(); + if( canvas ) + canvas->setFocusElement(this); + } + //---------------------------------------------------------------------------- bool Element::accept(EventVisitor& visitor) { @@ -326,6 +334,15 @@ namespace canvas return true; } + //---------------------------------------------------------------------------- + size_t Element::numEventHandler(int type) const + { + ListenerMap::const_iterator listeners = _listener.find(type); + if( listeners != _listener.end() ) + return listeners->second.size(); + return 0; + } + //---------------------------------------------------------------------------- bool Element::handleEvent(const EventPtr& event) { diff --git a/simgear/canvas/elements/CanvasElement.hxx b/simgear/canvas/elements/CanvasElement.hxx index 70f676f0..242c2202 100644 --- a/simgear/canvas/elements/CanvasElement.hxx +++ b/simgear/canvas/elements/CanvasElement.hxx @@ -108,10 +108,16 @@ namespace canvas bool addEventListener(const std::string& type, const EventListener& cb); virtual void clearEventListener(); + /// Get (keyboard) input focus. + void setFocus(); + virtual bool accept(EventVisitor& visitor); virtual bool ascend(EventVisitor& visitor); virtual bool traverse(EventVisitor& visitor); + /// Get the number of event handlers for the given type + size_t numEventHandler(int type) const; + virtual bool handleEvent(const EventPtr& event); bool dispatchEvent(const EventPtr& event); diff --git a/simgear/canvas/elements/CanvasImage.cxx b/simgear/canvas/elements/CanvasImage.cxx index c7ca43d0..4f4ffc7b 100644 --- a/simgear/canvas/elements/CanvasImage.cxx +++ b/simgear/canvas/elements/CanvasImage.cxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -525,8 +526,7 @@ namespace canvas if( !src_canvas ) return handled; - MouseEventPtr mouse_event = dynamic_cast(event.get()); - if( mouse_event ) + if( MouseEventPtr mouse_event = dynamic_cast(event.get()) ) { mouse_event.reset( new MouseEvent(*mouse_event) ); @@ -551,6 +551,11 @@ namespace canvas handled |= src_canvas->handleMouseEvent(mouse_event); } + else if( KeyboardEventPtr keyboard_event = + dynamic_cast(event.get()) ) + { + handled |= src_canvas->handleKeyboardEvent(keyboard_event); + } return handled; } diff --git a/simgear/canvas/events/CMakeLists.txt b/simgear/canvas/events/CMakeLists.txt index cfac3f69..8168ea5c 100644 --- a/simgear/canvas/events/CMakeLists.txt +++ b/simgear/canvas/events/CMakeLists.txt @@ -2,11 +2,15 @@ include (SimGearComponent) set(HEADERS CustomEvent.hxx + DeviceEvent.hxx + KeyboardEvent.hxx MouseEvent.hxx ) set(SOURCES CustomEvent.cxx + DeviceEvent.cxx + KeyboardEvent.cxx MouseEvent.cxx ) diff --git a/simgear/canvas/events/DeviceEvent.cxx b/simgear/canvas/events/DeviceEvent.cxx new file mode 100644 index 00000000..14751720 --- /dev/null +++ b/simgear/canvas/events/DeviceEvent.cxx @@ -0,0 +1,66 @@ +// Input device event +// +// Copyright (C) 2014 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#include "DeviceEvent.hxx" +#include + +namespace simgear +{ +namespace canvas +{ + + //---------------------------------------------------------------------------- + DeviceEvent::DeviceEvent(): + modifiers(0) + { + + } + + //---------------------------------------------------------------------------- + DeviceEvent::DeviceEvent(const osgGA::GUIEventAdapter& ea): + modifiers(ea.getModKeyMask()) + { + time = ea.getTime(); + } + + //---------------------------------------------------------------------------- + bool DeviceEvent::ctrlKey() const + { + return (modifiers & osgGA::GUIEventAdapter::MODKEY_CTRL) != 0; + } + + //---------------------------------------------------------------------------- + bool DeviceEvent::shiftKey() const + { + return (modifiers & osgGA::GUIEventAdapter::MODKEY_SHIFT) != 0; + } + + //---------------------------------------------------------------------------- + bool DeviceEvent::altKey() const + { + return (modifiers & osgGA::GUIEventAdapter::MODKEY_ALT) != 0; + } + + //---------------------------------------------------------------------------- + bool DeviceEvent::metaKey() const + { + return (modifiers & osgGA::GUIEventAdapter::MODKEY_META) != 0; + } + +} // namespace canvas +} // namespace simgear diff --git a/simgear/canvas/events/DeviceEvent.hxx b/simgear/canvas/events/DeviceEvent.hxx new file mode 100644 index 00000000..8fc366a3 --- /dev/null +++ b/simgear/canvas/events/DeviceEvent.hxx @@ -0,0 +1,55 @@ +///@file Input device event (keyboard/mouse) +// +// Copyright (C) 2014 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef CANVAS_DEVICE_EVENT_HXX_ +#define CANVAS_DEVICE_EVENT_HXX_ + +#include + +namespace osgGA { class GUIEventAdapter; } + +namespace simgear +{ +namespace canvas +{ + + /** + * Common interface for input device events. + */ + class DeviceEvent: + public Event + { + public: + DeviceEvent(); + DeviceEvent(const osgGA::GUIEventAdapter& ea); + + int getModifiers() const { return modifiers; } + + bool ctrlKey() const; + bool shiftKey() const; + bool altKey() const; + bool metaKey() const; + + protected: + int modifiers; //!< Keyboard modifier state + }; + +} // namespace canvas +} // namespace simgear + +#endif /* CANVAS_DEVICE_EVENT_HXX_ */ diff --git a/simgear/canvas/events/KeyboardEvent.cxx b/simgear/canvas/events/KeyboardEvent.cxx new file mode 100644 index 00000000..978894ad --- /dev/null +++ b/simgear/canvas/events/KeyboardEvent.cxx @@ -0,0 +1,282 @@ +// Keyboard event +// +// Copyright (C) 2014 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#include "KeyboardEvent.hxx" + +#include + +#include +#include +#include + +namespace simgear +{ +namespace canvas +{ + typedef osgGA::GUIEventAdapter EA; + + // TODO check Win/Mac keycode for altgr/ISO Level3 Shift + const uint32_t KEY_AltGraph = 0xfe03; + + //---------------------------------------------------------------------------- + KeyboardEvent::KeyboardEvent(): + _key(0), + _unmodified_key(0), + _repeat(false), + _location(DOM_KEY_LOCATION_STANDARD) + { + + } + + //---------------------------------------------------------------------------- + KeyboardEvent::KeyboardEvent(const osgGA::GUIEventAdapter& ea): + DeviceEvent(ea), + _key(ea.getKey()), + _unmodified_key(ea.getUnmodifiedKey()), + _repeat(false), + _location(DOM_KEY_LOCATION_STANDARD) + { + if( ea.getEventType() == EA::KEYDOWN ) + type = KEY_DOWN; + else if( ea.getEventType() == EA::KEYUP ) + type = KEY_UP; +// else +// // TODO what to do with wrong event type? + } + + //---------------------------------------------------------------------------- + void KeyboardEvent::setKey(uint32_t key) + { + _name.clear(); + _key = key; + } + + //---------------------------------------------------------------------------- + void KeyboardEvent::setUnmodifiedKey(uint32_t key) + { + _name.clear(); + _unmodified_key = key; + } + + //---------------------------------------------------------------------------- + void KeyboardEvent::setRepeat(bool repeat) + { + _repeat = repeat; + } + + //---------------------------------------------------------------------------- + std::string KeyboardEvent::key() const + { + if( !_name.empty() ) + return _name; + + // We need to make sure only valid const char* pointers are passed. The best + // way is just to use string constants. + // Use an empty string ("") to just use the value reported by the operating + // system. + typedef std::pair InternalKeyInfo; + typedef boost::container::flat_map InternalKeyMap; + typedef boost::container::flat_set KeyList; + + static InternalKeyMap key_map; + static KeyList num_pad_keys; + + if( key_map.empty() ) + { + const uint8_t S = DOM_KEY_LOCATION_STANDARD, + L = DOM_KEY_LOCATION_LEFT, + R = DOM_KEY_LOCATION_RIGHT, + N = DOM_KEY_LOCATION_NUMPAD; + + key_map[ EA::KEY_BackSpace ] = std::make_pair("Backspace", S); + key_map[ EA::KEY_Tab ] = std::make_pair("Tab", S); + key_map[ EA::KEY_Linefeed ] = std::make_pair("Linefeed", S); + key_map[ EA::KEY_Clear ] = std::make_pair("Clear", S); + key_map[ EA::KEY_Return ] = std::make_pair("Enter", S); + key_map[ EA::KEY_Pause ] = std::make_pair("Pause", S); + key_map[ EA::KEY_Scroll_Lock ] = std::make_pair("ScrollLock", S); + key_map[ EA::KEY_Sys_Req ] = std::make_pair("SystemRequest", S); + key_map[ EA::KEY_Escape ] = std::make_pair("Escape", S); + key_map[ EA::KEY_Delete ] = std::make_pair("Delete", S); + + key_map[ EA::KEY_Home ] = std::make_pair("Home", S); + key_map[ EA::KEY_Left ] = std::make_pair("Left", S); + key_map[ EA::KEY_Up ] = std::make_pair("Up", S); + key_map[ EA::KEY_Right ] = std::make_pair("Right", S); + key_map[ EA::KEY_Down ] = std::make_pair("Down", S); + key_map[ EA::KEY_Page_Up ] = std::make_pair("PageUp", S); + key_map[ EA::KEY_Page_Down ] = std::make_pair("PageDown", S); + key_map[ EA::KEY_End ] = std::make_pair("End", S); + key_map[ EA::KEY_Begin ] = std::make_pair("Begin", S); + + key_map[ EA::KEY_Select ] = std::make_pair("Select", S); + key_map[ EA::KEY_Print ] = std::make_pair("PrintScreen", S); + key_map[ EA::KEY_Execute ] = std::make_pair("Execute", S); + key_map[ EA::KEY_Insert ] = std::make_pair("Insert", S); + key_map[ EA::KEY_Undo ] = std::make_pair("Undo", S); + key_map[ EA::KEY_Redo ] = std::make_pair("Redo", S); + key_map[ EA::KEY_Menu ] = std::make_pair("ContextMenu", S); + key_map[ EA::KEY_Find ] = std::make_pair("Find", S); + key_map[ EA::KEY_Cancel ] = std::make_pair("Cancel", S); + key_map[ EA::KEY_Help ] = std::make_pair("Help", S); + key_map[ EA::KEY_Break ] = std::make_pair("Break", S); + key_map[ EA::KEY_Mode_switch ] = std::make_pair("ModeChange", S); + key_map[ EA::KEY_Num_Lock ] = std::make_pair("NumLock", S); + + key_map[ EA::KEY_KP_Space ] = std::make_pair(" ", N); + key_map[ EA::KEY_KP_Tab ] = std::make_pair("Tab", N); + key_map[ EA::KEY_KP_Enter ] = std::make_pair("Enter", N); + key_map[ EA::KEY_KP_F1 ] = std::make_pair("F1", N); + key_map[ EA::KEY_KP_F2 ] = std::make_pair("F2", N); + key_map[ EA::KEY_KP_F3 ] = std::make_pair("F3", N); + key_map[ EA::KEY_KP_F4 ] = std::make_pair("F4", N); + key_map[ EA::KEY_KP_Home ] = std::make_pair("Home", N); + key_map[ EA::KEY_KP_Left ] = std::make_pair("Left", N); + key_map[ EA::KEY_KP_Up ] = std::make_pair("Up", N); + key_map[ EA::KEY_KP_Right ] = std::make_pair("Right", N); + key_map[ EA::KEY_KP_Down ] = std::make_pair("Down", N); + key_map[ EA::KEY_KP_Page_Up ] = std::make_pair("PageUp", N); + key_map[ EA::KEY_KP_Page_Down ] = std::make_pair("PageDown", N); + key_map[ EA::KEY_KP_End ] = std::make_pair("End", N); + key_map[ EA::KEY_KP_Begin ] = std::make_pair("Begin", N); + key_map[ EA::KEY_KP_Insert ] = std::make_pair("Insert", N); + key_map[ EA::KEY_KP_Delete ] = std::make_pair("Delete", N); + key_map[ EA::KEY_KP_Equal ] = std::make_pair("=", N); + key_map[ EA::KEY_KP_Multiply ] = std::make_pair("*", N); + key_map[ EA::KEY_KP_Add ] = std::make_pair("+", N); + key_map[ EA::KEY_KP_Separator ] = std::make_pair("", N); + key_map[ EA::KEY_KP_Subtract ] = std::make_pair("-", N); + key_map[ EA::KEY_KP_Decimal ] = std::make_pair("", N); + key_map[ EA::KEY_KP_Divide ] = std::make_pair("/", N); + + key_map[ EA::KEY_KP_0 ] = std::make_pair("0", N); + key_map[ EA::KEY_KP_1 ] = std::make_pair("1", N); + key_map[ EA::KEY_KP_2 ] = std::make_pair("2", N); + key_map[ EA::KEY_KP_3 ] = std::make_pair("3", N); + key_map[ EA::KEY_KP_4 ] = std::make_pair("4", N); + key_map[ EA::KEY_KP_5 ] = std::make_pair("5", N); + key_map[ EA::KEY_KP_6 ] = std::make_pair("6", N); + key_map[ EA::KEY_KP_7 ] = std::make_pair("7", N); + key_map[ EA::KEY_KP_8 ] = std::make_pair("8", N); + key_map[ EA::KEY_KP_9 ] = std::make_pair("9", N); + + key_map[ EA::KEY_F1 ] = std::make_pair("F1", S); + key_map[ EA::KEY_F2 ] = std::make_pair("F2", S); + key_map[ EA::KEY_F3 ] = std::make_pair("F3", S); + key_map[ EA::KEY_F4 ] = std::make_pair("F4", S); + key_map[ EA::KEY_F5 ] = std::make_pair("F5", S); + key_map[ EA::KEY_F6 ] = std::make_pair("F6", S); + key_map[ EA::KEY_F7 ] = std::make_pair("F7", S); + key_map[ EA::KEY_F8 ] = std::make_pair("F8", S); + key_map[ EA::KEY_F9 ] = std::make_pair("F9", S); + key_map[ EA::KEY_F10 ] = std::make_pair("F10", S); + key_map[ EA::KEY_F11 ] = std::make_pair("F11", S); + key_map[ EA::KEY_F12 ] = std::make_pair("F12", S); + key_map[ EA::KEY_F13 ] = std::make_pair("F13", S); + key_map[ EA::KEY_F14 ] = std::make_pair("F14", S); + key_map[ EA::KEY_F15 ] = std::make_pair("F15", S); + key_map[ EA::KEY_F16 ] = std::make_pair("F16", S); + key_map[ EA::KEY_F17 ] = std::make_pair("F17", S); + key_map[ EA::KEY_F18 ] = std::make_pair("F18", S); + key_map[ EA::KEY_F19 ] = std::make_pair("F19", S); + key_map[ EA::KEY_F20 ] = std::make_pair("F20", S); + key_map[ EA::KEY_F21 ] = std::make_pair("F21", S); + key_map[ EA::KEY_F22 ] = std::make_pair("F22", S); + key_map[ EA::KEY_F23 ] = std::make_pair("F23", S); + key_map[ EA::KEY_F24 ] = std::make_pair("F24", S); + key_map[ EA::KEY_F25 ] = std::make_pair("F25", S); + key_map[ EA::KEY_F26 ] = std::make_pair("F26", S); + key_map[ EA::KEY_F27 ] = std::make_pair("F27", S); + key_map[ EA::KEY_F28 ] = std::make_pair("F28", S); + key_map[ EA::KEY_F29 ] = std::make_pair("F29", S); + key_map[ EA::KEY_F30 ] = std::make_pair("F30", S); + key_map[ EA::KEY_F31 ] = std::make_pair("F31", S); + key_map[ EA::KEY_F32 ] = std::make_pair("F32", S); + key_map[ EA::KEY_F33 ] = std::make_pair("F33", S); + key_map[ EA::KEY_F34 ] = std::make_pair("F34", S); + key_map[ EA::KEY_F35 ] = std::make_pair("F35", S); + + key_map[ KEY_AltGraph ] = std::make_pair("AltGraph", S); + key_map[ EA::KEY_Shift_L ] = std::make_pair("Shift", L); + key_map[ EA::KEY_Shift_R ] = std::make_pair("Shift", R); + key_map[ EA::KEY_Control_L ] = std::make_pair("Control", L); + key_map[ EA::KEY_Control_R ] = std::make_pair("Control", R); + key_map[ EA::KEY_Caps_Lock ] = std::make_pair("CapsLock", S); + key_map[ EA::KEY_Shift_Lock ] = std::make_pair("ShiftLock", S); + key_map[ EA::KEY_Meta_L ] = std::make_pair("Meta", L); + key_map[ EA::KEY_Meta_R ] = std::make_pair("Meta", R); + key_map[ EA::KEY_Alt_L ] = std::make_pair("Alt", L); + key_map[ EA::KEY_Alt_R ] = std::make_pair("Alt", R); + key_map[ EA::KEY_Super_L ] = std::make_pair("Super", L); + key_map[ EA::KEY_Super_R ] = std::make_pair("Super", R); + key_map[ EA::KEY_Hyper_L ] = std::make_pair("Hyper", L); + key_map[ EA::KEY_Hyper_R ] = std::make_pair("Hyper", R); + + num_pad_keys.insert(EA::KEY_KP_Home ); + num_pad_keys.insert(EA::KEY_KP_Left ); + num_pad_keys.insert(EA::KEY_KP_Up ); + num_pad_keys.insert(EA::KEY_KP_Right ); + num_pad_keys.insert(EA::KEY_KP_Down ); + num_pad_keys.insert(EA::KEY_KP_Page_Up ); + num_pad_keys.insert(EA::KEY_KP_Page_Down); + num_pad_keys.insert(EA::KEY_KP_End ); + num_pad_keys.insert(EA::KEY_KP_Begin ); + num_pad_keys.insert(EA::KEY_KP_Insert ); + num_pad_keys.insert(EA::KEY_KP_Delete ); + } + + _location = DOM_KEY_LOCATION_STANDARD; + + InternalKeyMap::const_iterator it = key_map.find(_key); + if( it != key_map.end()) + { + _name = it->second.first; + _location = it->second.second; + } + + // Empty or no mapping -> convert UTF-32 key value to UTF-8 + if( _name.empty() ) + _name = boost::locale::conv::utf_to_utf(&_key, &_key + 1); + + // Keys on the numpad with NumLock enabled are reported just like their + // equivalent keys in the standard key block. Using the unmodified key value + // we can detect such keys and set the location accordingly. + if( num_pad_keys.find(_unmodified_key) != num_pad_keys.end() ) + _location = DOM_KEY_LOCATION_NUMPAD; + + return _name; + } + + //---------------------------------------------------------------------------- + KeyboardEvent::DOMKeyLocation KeyboardEvent::location() const + { + key(); // ensure location is up-to-date + return static_cast(_location); + } + + //---------------------------------------------------------------------------- + bool KeyboardEvent::isModifier() const + { + return ( _key >= EA::KEY_Shift_L + && _key <= EA::KEY_Hyper_R + ) + || _key == KEY_AltGraph; + } + +} // namespace canvas +} // namespace simgear diff --git a/simgear/canvas/events/KeyboardEvent.hxx b/simgear/canvas/events/KeyboardEvent.hxx new file mode 100644 index 00000000..d90a9246 --- /dev/null +++ b/simgear/canvas/events/KeyboardEvent.hxx @@ -0,0 +1,74 @@ +///@file Keyboard event +// +// Copyright (C) 2014 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef CANVAS_KEYBOARD_EVENT_HXX_ +#define CANVAS_KEYBOARD_EVENT_HXX_ + +#include "DeviceEvent.hxx" + +namespace simgear +{ +namespace canvas +{ + + class KeyboardEvent: + public DeviceEvent + { + public: + + enum DOMKeyLocation + { + DOM_KEY_LOCATION_STANDARD = 0, + DOM_KEY_LOCATION_LEFT, + DOM_KEY_LOCATION_RIGHT, + DOM_KEY_LOCATION_NUMPAD + }; + + KeyboardEvent(); + KeyboardEvent(const osgGA::GUIEventAdapter& ea); + + void setKey(uint32_t key); + void setUnmodifiedKey(uint32_t key); + void setRepeat(bool repeat); + + std::string key() const; + DOMKeyLocation location() const; + bool repeat() const { return _repeat; } + + uint32_t charCode() const { return _key; } + uint32_t keyCode() const { return _unmodified_key; } + + /// Whether the key which has triggered this event is a modifier + bool isModifier() const; + + protected: + uint32_t _key, // namespace simgear { @@ -27,7 +28,6 @@ namespace canvas MouseEvent::MouseEvent(): button(0), buttons(0), - modifiers(0), click_count(0) { @@ -35,13 +35,11 @@ namespace canvas //---------------------------------------------------------------------------- MouseEvent::MouseEvent(const osgGA::GUIEventAdapter& ea): + DeviceEvent(ea), button(0), buttons(ea.getButtonMask()), - modifiers(ea.getModKeyMask()), click_count(0) { - time = ea.getTime(); - // Convert button mask to index int button_mask = ea.getButton(); while( (button_mask >>= 1) > 0 ) diff --git a/simgear/canvas/events/MouseEvent.hxx b/simgear/canvas/events/MouseEvent.hxx index d50b5238..d3223f59 100644 --- a/simgear/canvas/events/MouseEvent.hxx +++ b/simgear/canvas/events/MouseEvent.hxx @@ -19,8 +19,7 @@ #ifndef CANVAS_MOUSE_EVENT_HXX_ #define CANVAS_MOUSE_EVENT_HXX_ -#include -#include +#include "DeviceEvent.hxx" namespace simgear { @@ -28,7 +27,7 @@ namespace canvas { class MouseEvent: - public Event + public DeviceEvent { public: MouseEvent(); @@ -55,7 +54,6 @@ namespace canvas int getButton() const { return button; } int getButtonMask() const { return buttons; } - int getModifiers() const { return modifiers; } int getCurrentClickCount() const { return click_count; } @@ -65,7 +63,6 @@ namespace canvas delta; int button, //