#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasPlacement.hxx>
#include <simgear/canvas/CanvasWindow.hxx>
+#include <simgear/canvas/events/KeyboardEvent.hxx>
#include <simgear/scene/util/OsgMath.hxx>
#include <osg/BlendFunc>
{
public:
DesktopGroup();
+
+ void setFocusWindow(const sc::WindowPtr& window);
bool handleEvent(const osgGA::GUIEventAdapter& ea);
protected:
sc::WindowWeakPtr _last_push,
_last_mouse_over,
- _resize_window;
+ _resize_window,
+ _focus_window;
+
uint8_t _resize;
int _last_cursor;
_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);
_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() );
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(),
}
}
+//------------------------------------------------------------------------------
+void DesktopGroup::setFocusWindow(const sc::WindowPtr& window)
+{
+ _focus_window = window;
+}
+
/*
RESIZE AREAS
============
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;
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;
}
//------------------------------------------------------------------------------
return _desktop;
}
+//------------------------------------------------------------------------------
+void GUIMgr::setInputFocus(const simgear::canvas::WindowPtr& window)
+{
+ static_cast<DesktopGroup*>(_desktop.get())->setFocusWindow(window);
+}
+
//------------------------------------------------------------------------------
sc::Placements
GUIMgr::addWindowPlacement( SGPropertyNode* placement,
#include <simgear/canvas/layout/BoxLayout.hxx>
#include <simgear/canvas/layout/NasalWidget.hxx>
#include <simgear/canvas/events/CustomEvent.hxx>
+#include <simgear/canvas/events/KeyboardEvent.hxx>
#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/nasal/cppbind/from_nasal.hxx>
typedef nasal::Ghost<sc::EventPtr> NasalEvent;
typedef nasal::Ghost<sc::CustomEventPtr> NasalCustomEvent;
+typedef nasal::Ghost<sc::DeviceEventPtr> NasalDeviceEvent;
+typedef nasal::Ghost<sc::KeyboardEventPtr> NasalKeyboardEvent;
typedef nasal::Ghost<sc::MouseEventPtr> NasalMouseEvent;
struct CustomEventDetailWrapper;
return nasal::to_nasal(c, requireGUIMgr(c).getDesktop());
}
+naRef f_setInputFocus(const nasal::CallContext& ctx)
+{
+ requireGUIMgr(ctx.c).setInputFocus(ctx.requireArg<sc::WindowPtr>(0));
+ return naNil();
+}
+
static naRef f_groupCreateChild(sc::Group& group, const nasal::CallContext& ctx)
{
return ctx.to_nasal( group.createChild( ctx.requireArg<std::string>(0),
return naNil();
}
-template<int Mask>
-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<std::string>(0);
canvas_module.createHash("CustomEvent")
.set("new", &f_createCustomEvent);
- NasalMouseEvent::init("canvas.MouseEvent")
+ NasalDeviceEvent::init("canvas.DeviceEvent")
.bases<NasalEvent>()
+ .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<NasalDeviceEvent>()
+ .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<NasalDeviceEvent>()
.member("screenX", &sc::MouseEvent::getScreenX)
.member("screenY", &sc::MouseEvent::getScreenY)
.member("clientX", &sc::MouseEvent::getClientX)
.member("deltaY", &sc::MouseEvent::getDeltaY)
.member("button", &sc::MouseEvent::getButton)
.member("buttons", &sc::MouseEvent::getButtonMask)
- .member("modifiers", &sc::MouseEvent::getModifiers)
- .member("ctrlKey", &f_eventGetModifier<GUIEventAdapter::MODKEY_CTRL>)
- .member("shiftKey", &f_eventGetModifier<GUIEventAdapter::MODKEY_SHIFT>)
- .member("altKey", &f_eventGetModifier<GUIEventAdapter::MODKEY_ALT>)
- .member("metaKey", &f_eventGetModifier<GUIEventAdapter::MODKEY_META>)
.member("click_count", &sc::MouseEvent::getCurrentClickCount);
//----------------------------------------------------------------------------
canvas_module.set("_newWindowGhost", f_createWindow);
canvas_module.set("_getDesktopGhost", f_getDesktop);
+ canvas_module.set("setInputFocus", f_setInputFocus);
return naNil();
}