FlightGear next
FGEventHandler.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4#include <osg/Camera>
5#include <osg/GraphicsContext>
6#include <osg/Math>
7#include <osg/Viewport>
8#include <osgViewer/Viewer>
9
10#include <Main/fg_props.hxx>
11#include "CameraGroup.hxx"
12#include "FGEventHandler.hxx"
14#include "WindowBuilder.hxx"
15#include "renderer.hxx"
16#include "sview.hxx"
17
18/*
19 WARNING: These have to be the same as PW_KEY_whatever and also
20 the same as (GLUT_KEY_whatever+256)
21*/
22#define PU_KEY_GLUT_SPECIAL_OFFSET 256
23
24#define PU_KEY_F1 (1 + PU_KEY_GLUT_SPECIAL_OFFSET)
25#define PU_KEY_F2 (2 + PU_KEY_GLUT_SPECIAL_OFFSET)
26#define PU_KEY_F3 (3 + PU_KEY_GLUT_SPECIAL_OFFSET)
27#define PU_KEY_F4 (4 + PU_KEY_GLUT_SPECIAL_OFFSET)
28#define PU_KEY_F5 (5 + PU_KEY_GLUT_SPECIAL_OFFSET)
29#define PU_KEY_F6 (6 + PU_KEY_GLUT_SPECIAL_OFFSET)
30#define PU_KEY_F7 (7 + PU_KEY_GLUT_SPECIAL_OFFSET)
31#define PU_KEY_F8 (8 + PU_KEY_GLUT_SPECIAL_OFFSET)
32#define PU_KEY_F9 (9 + PU_KEY_GLUT_SPECIAL_OFFSET)
33#define PU_KEY_F10 (10 + PU_KEY_GLUT_SPECIAL_OFFSET)
34#define PU_KEY_F11 (11 + PU_KEY_GLUT_SPECIAL_OFFSET)
35#define PU_KEY_F12 (12 + PU_KEY_GLUT_SPECIAL_OFFSET)
36#define PU_KEY_LEFT (100 + PU_KEY_GLUT_SPECIAL_OFFSET)
37#define PU_KEY_UP (101 + PU_KEY_GLUT_SPECIAL_OFFSET)
38#define PU_KEY_RIGHT (102 + PU_KEY_GLUT_SPECIAL_OFFSET)
39#define PU_KEY_DOWN (103 + PU_KEY_GLUT_SPECIAL_OFFSET)
40#define PU_KEY_PAGE_UP (104 + PU_KEY_GLUT_SPECIAL_OFFSET)
41#define PU_KEY_PAGE_DOWN (105 + PU_KEY_GLUT_SPECIAL_OFFSET)
42#define PU_KEY_HOME (106 + PU_KEY_GLUT_SPECIAL_OFFSET)
43#define PU_KEY_END (107 + PU_KEY_GLUT_SPECIAL_OFFSET)
44#define PU_KEY_INSERT (108 + PU_KEY_GLUT_SPECIAL_OFFSET)
45
46namespace flightgear
47{
48const int displayStatsKey = 1;
49const int printStatsKey = 2;
50
51// The manipulator is responsible for updating a Viewer's camera. Its
52// event handling method is also a convenient place to run the FG idle
53// and draw handlers.
54
56 idleHandler(0),
57 keyHandler(0),
61 statsEvent(new osgGA::GUIEventAdapter),
62 statsType(osgViewer::StatsHandler::NO_STATS),
64 resizable(true),
65 mouseWarped(false),
68{
69 using namespace osgGA;
70 statsHandler->setKeyEventTogglesOnScreenStats(displayStatsKey);
71 statsHandler->setKeyEventPrintsOutStats(printStatsKey);
72 statsEvent->setEventType(GUIEventAdapter::KEYDOWN);
73
74 for (int i = 0; i < 128; i++)
75 release_keys[i] = i;
76
77 _display = fgGetNode("/sim/rendering/on-screen-statistics", true);
78 _print = fgGetNode("/sim/rendering/print-statistics", true);
79}
80
82{
83 _display.clear();
84 _print.clear();
85}
86
88{
89 _display = fgGetNode("/sim/rendering/on-screen-statistics", true);
90 _print = fgGetNode("/sim/rendering/print-statistics", true);
91 statsHandler->reset();
92}
93
94#if 0
95void FGEventHandler::init(const osgGA::GUIEventAdapter& ea,
96 osgGA::GUIActionAdapter& us)
97{
98 currentModifiers = osgToFGModifiers(ea.getModKeyMask());
99 (void)handle(ea, us);
100}
101#endif
102
103// Calculate event coordinates in the viewport of the GUI camera, if
104// possible. Otherwise sets (x, y) to (-1, -1).
105FGEventHandler::WindowType
106FGEventHandler::eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
107 int& x, int& y)
108{
109 WindowType ret = WindowType_NONE;
110
112 flightgear::GraphicsWindow* main_window = wsa->getGUIWindow();
113 if (!main_window) {
114 // GUI window is still not available, skip the event
115 return WindowType_NONE;
116 }
117
118 x = -1;
119 y = -1;
120
121 const osg::GraphicsContext* eventGC = ea.getGraphicsContext();
122 if( !eventGC )
123 return WindowType_NONE; // TODO how can this happen?
124 const osg::GraphicsContext::Traits* traits = eventGC->getTraits();
125
126 osg::Viewport* vport;
127
128 if (eventGC != main_window->gc.get()) {
129 // This is not the main window.
130 simgear::compositor::Compositor* compositor = SviewGetEventViewport(ea);
131 if (!compositor) {
132 SG_LOG(SG_GENERAL, SG_DEBUG, "SviewGetEventViewport() returned nullptr");
133 return WindowType_NONE;
134 }
135 vport = compositor->getViewport();
136 if (!vport) {
137 SG_LOG(SG_GENERAL, SG_ALERT, "compositor->getViewport() is nullptr");
138 return WindowType_NONE;
139 }
140 ret = WindowType_SVIEW;
141 }
142 else {
143 osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
144 if (!guiCamera)
145 return WindowType_NONE;
146 vport = guiCamera->getViewport();
147 if (!vport)
148 return WindowType_NONE;
149 ret = WindowType_MAIN;
150 }
151
152 // Scale x, y to the dimensions of the window
153 double wx = (((ea.getX() - ea.getXmin()) / (ea.getXmax() - ea.getXmin()))
154 * (float)traits->width);
155 double wy = (((ea.getY() - ea.getYmin()) / (ea.getYmax() - ea.getYmin()))
156 * (float)traits->height);
157 if (vport->x() <= wx && wx <= vport->x() + vport->width()
158 && vport->y() <= wy && wy <= vport->y() + vport->height()) {
159 // Finally, into viewport coordinates. Change y to "increasing
160 // downwards".
161 x = wx - vport->x();
162 y = vport->height() - (wy - vport->y());
163 }
164 return ret;
165}
166
167/* A hack for when we are linked with OSG-3.4 and CompositeViewer is
168enabled. It seems that OSG-3.4 incorrectly calls our event handler for
169extra view windows (e.g. resize/close events), so we try to detect
170this. Unfortunately OSG also messes up <ea>'s graphics context pointer so this
171does't alwys work. */
172bool FGEventHandler::isMainWindow(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
173{
174 int x;
175 int y;
176 return eventToViewport(ea, us, x, y) == WindowType_MAIN;
177}
178
179void FGEventHandler::setWindowRectangleInteriorWithCorrection(osgViewer::GraphicsWindow* window, int x, int y, int width, int height)
180{
181 // Store (x y) in our state so that our handle() event handler can
182 // compare the requested position with the actual position and update
183 // (m_setWindowRectangle_delta_x m_setWindowRectangle_delta_y) accordingly.
184 //
185 SG_LOG(SG_VIEW, SG_DEBUG, "FGEventHandler::setWindowRectangle(): pos=(" << x << " " << y << ")"
186 << " delta=(" << m_setWindowRectangle_delta_x << " " << m_setWindowRectangle_delta_y << ")"
187 );
188 m_setWindowRectangle_called = true;
189 m_setWindowRectangle_called_x = x;
190 m_setWindowRectangle_called_y = y;
191 window->setWindowRectangle(
192 x - m_setWindowRectangle_delta_x,
193 y - m_setWindowRectangle_delta_y,
194 width,
195 height
196 );
197}
198
199bool FGEventHandler::handle(const osgGA::GUIEventAdapter& ea,
200 osgGA::GUIActionAdapter& us)
201{
202 // Event handlers seem to be called even if the according event has already
203 // been handled. Already handled events shouldn't be handled multiple times
204 // so we need to exit here manually.
205 if (ea.getHandled()
206 // Let mouse move events pass to correctly handle mouse cursor hide
207 // timeout while moving just on the canvas gui.
208 // TODO We should clean up the whole mouse input and make hide
209 // timeout independent of the event handler which consumed the
210 // event.
211
212 // if we see a release, still process for active pick callbacks
213 // https://sourceforge.net/p/flightgear/codetickets/2347/
214
215 && ea.getEventType() != osgGA::GUIEventAdapter::MOVE && ea.getEventType() != osgGA::GUIEventAdapter::DRAG && ea.getEventType() != osgGA::GUIEventAdapter::RELEASE) {
216 return false;
217 }
218
219 int x = 0;
220 int y = 0;
221
222 switch (ea.getEventType()) {
223 case osgGA::GUIEventAdapter::FRAME:
224 mouseWarped = false;
225 handleStats(us);
226 return true;
227 case osgGA::GUIEventAdapter::KEYDOWN:
228 case osgGA::GUIEventAdapter::KEYUP:
229 {
230 int key, modmask;
231 handleKey(ea, key, modmask);
232 eventToViewport(ea, us, x, y);
233 if (keyHandler)
234 (*keyHandler)(key, modmask, x, y);
235 return true;
236 }
237 case osgGA::GUIEventAdapter::PUSH:
238 case osgGA::GUIEventAdapter::RELEASE:
239 {
240 WindowType window_type = eventToViewport(ea, us, x, y);
241 bool mainWindow = (window_type == WindowType_MAIN);
242 int button = 0;
243 switch (ea.getButton()) {
244 case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
245 button = 0;
246 break;
247 case osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON:
248 button = 1;
249 break;
250 case osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON:
251 button = 2;
252 break;
253 }
255 (*mouseClickHandler)(button,
256 (ea.getEventType()
257 == osgGA::GUIEventAdapter::RELEASE), x, y, mainWindow, &ea);
258 return true;
259 }
260 case osgGA::GUIEventAdapter::SCROLL:
261 {
262 WindowType window_type = eventToViewport(ea, us, x, y);
263 bool mainWindow = (window_type == WindowType_MAIN);
264
265 int button;
266 if (ea.getScrollingMotion() == osgGA::GUIEventAdapter::SCROLL_2D) {
267 if (ea.getScrollingDeltaY() > 0)
268 button = 3;
269 else if (ea.getScrollingDeltaY() < 0)
270 button = 4;
271 else
272 button = -1;
273
274#if defined(SG_MAC)
275 // bug https://code.google.com/p/flightgear-bugs/issues/detail?id=1286
276 // Mac (Cocoa) interprets shuft+wheel as horizontal scroll
277 if (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT) {
278 if (ea.getScrollingDeltaX() > 0)
279 button = 3;
280 else if (ea.getScrollingDeltaX() < 0)
281 button = 4;
282 }
283#endif
284
285 } else if (ea.getScrollingMotion() == osgGA::GUIEventAdapter::SCROLL_UP)
286 button = 3;
287 else
288 button = 4;
289 if (mouseClickHandler && button != -1) {
290 (*mouseClickHandler)(button, 0, x, y, mainWindow, &ea);
291 (*mouseClickHandler)(button, 1, x, y, mainWindow, &ea);
292 }
293 return true;
294 }
295 case osgGA::GUIEventAdapter::MOVE:
296 case osgGA::GUIEventAdapter::DRAG:
297 // If we warped the mouse, then disregard all pointer motion
298 // events for this frame. We really want to flush the event
299 // queue of mouse events, but don't have the ability to do
300 // that with osgViewer.
301 if (mouseWarped)
302 return true;
303 if (eventToViewport(ea, us, x, y) != WindowType_NONE && mouseMotionHandler)
304 (*mouseMotionHandler)(x, y, &ea);
305 return true;
306 case osgGA::GUIEventAdapter::RESIZE:
307 SG_LOG(SG_VIEW, SG_DEBUG, "FGEventHandler::handle: RESIZE event " << ea.getWindowHeight() << " x " << ea.getWindowWidth() << ", resizable: " << resizable);
308 if (!isMainWindow(ea, us)) {
309 return true;
310 }
312 if (resizable) {
313 if (m_setWindowRectangle_called) {
314 // Update m_setWindowRectangle_delta_x and
315 // m_setWindowRectangle_delta_y so that our
316 // setWindowRectangle() compensates for the window furniture
317 // differences in future calls.
318 //
319 m_setWindowRectangle_called = false;
320 int error_x = ea.getWindowX() - m_setWindowRectangle_called_x;
321 int error_y = ea.getWindowY() - m_setWindowRectangle_called_y;
322 SG_LOG(SG_VIEW, SG_BULK, "m_setWindowRectangle_called is set:"
323 << " m_setWindowRectangle_delta=("
324 << m_setWindowRectangle_delta_x << " " << m_setWindowRectangle_delta_y << ")"
325 << " m_setWindowRectangle_called_=("
326 << m_setWindowRectangle_called_x << " " << m_setWindowRectangle_called_y << ")"
327 << " ea.getWindow=(" << ea.getWindowX() << " " << ea.getWindowY() << ")"
328 << " error=(" << error_x << " " << error_y << ")"
329 );
330 m_setWindowRectangle_delta_x += error_x;
331 m_setWindowRectangle_delta_y += error_y;
332 }
333 globals->get_renderer()->resize(ea.getWindowWidth(), ea.getWindowHeight(), ea.getWindowX(), ea.getWindowY());
334 }
335 statsHandler->handle(ea, us);
336 return true;
337 case osgGA::GUIEventAdapter::CLOSE_WINDOW:
338 if (!isMainWindow(ea, us)) {
339 return true;
340 }
341 // Fall through.
342 case osgGA::GUIEventAdapter::QUIT_APPLICATION:
343 fgOSExit(0);
344 return true;
345 default:
346 return false;
347 }
348}
349
350int FGEventHandler::translateKey(const osgGA::GUIEventAdapter& ea)
351{
352 using namespace osgGA;
353
354 static std::map<int, int> numlockKeyMap;
355 static std::map<int, int> noNumlockKeyMap;
356
357 if (numlockKeyMap.empty()) {
358 // init these first time around
359
360 // OSG reports NumPad keycodes independent of the NumLock modifier.
361 // Both KP-4 and KP-Left are reported as KEY_KP_Left (0xff96), so we
362 // have to generate the locked keys ourselves.
363 numlockKeyMap[GUIEventAdapter::KEY_KP_Insert] = '0';
364 numlockKeyMap[GUIEventAdapter::KEY_KP_End] = '1';
365 numlockKeyMap[GUIEventAdapter::KEY_KP_Down] = '2';
366 numlockKeyMap[GUIEventAdapter::KEY_KP_Page_Down] = '3';
367 numlockKeyMap[GUIEventAdapter::KEY_KP_Left] = '4';
368 numlockKeyMap[GUIEventAdapter::KEY_KP_Begin] = '5';
369 numlockKeyMap[GUIEventAdapter::KEY_KP_Right] = '6';
370 numlockKeyMap[GUIEventAdapter::KEY_KP_Home] = '7';
371 numlockKeyMap[GUIEventAdapter::KEY_KP_Up] = '8';
372 numlockKeyMap[GUIEventAdapter::KEY_KP_Page_Up] = '9';
373 numlockKeyMap[GUIEventAdapter::KEY_KP_Delete] = '.';
374
375 // The comment above is incorrect on Mac osgViewer, at least. So we
376 // need to map the 'num-locked' key codes to real values.
377 numlockKeyMap[GUIEventAdapter::KEY_KP_0] = '0';
378 numlockKeyMap[GUIEventAdapter::KEY_KP_1] = '1';
379 numlockKeyMap[GUIEventAdapter::KEY_KP_2] = '2';
380 numlockKeyMap[GUIEventAdapter::KEY_KP_3] = '3';
381 numlockKeyMap[GUIEventAdapter::KEY_KP_4] = '4';
382 numlockKeyMap[GUIEventAdapter::KEY_KP_5] = '5';
383 numlockKeyMap[GUIEventAdapter::KEY_KP_6] = '6';
384 numlockKeyMap[GUIEventAdapter::KEY_KP_7] = '7';
385 numlockKeyMap[GUIEventAdapter::KEY_KP_8] = '8';
386 numlockKeyMap[GUIEventAdapter::KEY_KP_9] = '9';
387 numlockKeyMap[GUIEventAdapter::KEY_KP_Decimal] = '.';
388
389 // mapping when NumLock is off
390 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Insert] = PU_KEY_INSERT;
391 noNumlockKeyMap[GUIEventAdapter::KEY_KP_End] = PU_KEY_END;
392 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Down] = PU_KEY_DOWN;
393 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Page_Down] = PU_KEY_PAGE_DOWN;
394 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Left] = PU_KEY_LEFT;
395 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Begin] = '5';
396 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Right] = PU_KEY_RIGHT;
397 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Home] = PU_KEY_HOME;
398 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Up] = PU_KEY_UP;
399 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Page_Up] = PU_KEY_PAGE_UP;
400 noNumlockKeyMap[GUIEventAdapter::KEY_KP_Delete] = 127;
401 }
402
403 int key = ea.getKey();
404 // XXX Probably other translations are needed too.
405 switch (key) {
406 case GUIEventAdapter::KEY_Escape: key = 0x1b; break;
407 case GUIEventAdapter::KEY_Return: key = '\n'; break;
408 case GUIEventAdapter::KEY_BackSpace: key = '\b'; break;
409 case GUIEventAdapter::KEY_Delete: key = 0x7f; break;
410 case GUIEventAdapter::KEY_Tab: key = '\t'; break;
411 case GUIEventAdapter::KEY_Left: key = PU_KEY_LEFT; break;
412 case GUIEventAdapter::KEY_Up: key = PU_KEY_UP; break;
413 case GUIEventAdapter::KEY_Right: key = PU_KEY_RIGHT; break;
414 case GUIEventAdapter::KEY_Down: key = PU_KEY_DOWN; break;
415 case GUIEventAdapter::KEY_Page_Up: key = PU_KEY_PAGE_UP; break;
416 case GUIEventAdapter::KEY_Page_Down: key = PU_KEY_PAGE_DOWN; break;
417 case GUIEventAdapter::KEY_Home: key = PU_KEY_HOME; break;
418 case GUIEventAdapter::KEY_End: key = PU_KEY_END; break;
419 case GUIEventAdapter::KEY_Insert: key = PU_KEY_INSERT; break;
420 case GUIEventAdapter::KEY_F1: key = PU_KEY_F1; break;
421 case GUIEventAdapter::KEY_F2: key = PU_KEY_F2; break;
422 case GUIEventAdapter::KEY_F3: key = PU_KEY_F3; break;
423 case GUIEventAdapter::KEY_F4: key = PU_KEY_F4; break;
424 case GUIEventAdapter::KEY_F5: key = PU_KEY_F5; break;
425 case GUIEventAdapter::KEY_F6: key = PU_KEY_F6; break;
426 case GUIEventAdapter::KEY_F7: key = PU_KEY_F7; break;
427 case GUIEventAdapter::KEY_F8: key = PU_KEY_F8; break;
428 case GUIEventAdapter::KEY_F9: key = PU_KEY_F9; break;
429 case GUIEventAdapter::KEY_F10: key = PU_KEY_F10; break;
430 case GUIEventAdapter::KEY_F11: key = PU_KEY_F11; break;
431 case GUIEventAdapter::KEY_F12: key = PU_KEY_F12; break;
432 case GUIEventAdapter::KEY_KP_Enter: key = '\r'; break;
433 case GUIEventAdapter::KEY_KP_Add: key = '+'; break;
434 case GUIEventAdapter::KEY_KP_Divide: key = '/'; break;
435 case GUIEventAdapter::KEY_KP_Multiply: key = '*'; break;
436 case GUIEventAdapter::KEY_KP_Subtract: key = '-'; break;
437 }
438
439#ifdef __APPLE__
440 // Num Lock is always true on Mac
441 auto numPadIter = numlockKeyMap.find(key);
442 if (numPadIter != numlockKeyMap.end()) {
443 key = numPadIter->second;
444 }
445#else
446 if (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_NUM_LOCK) {
447 // NumLock on: map to numeric keys
448 auto numPadIter = numlockKeyMap.find(key);
449 if (numPadIter != numlockKeyMap.end()) {
450 key = numPadIter->second;
451 }
452 } else {
453 // NumLock off: map to PU arrow keys
454 auto numPadIter = noNumlockKeyMap.find(key);
455 if (numPadIter != noNumlockKeyMap.end()) {
456 key = numPadIter->second;
457 }
458 }
459#endif
460 return key;
461}
462
463int FGEventHandler::translateModifiers(const osgGA::GUIEventAdapter& ea)
464{
465 int result = 0;
466 const auto modifiers = ea.getModKeyMask();
467 if (modifiers & osgGA::GUIEventAdapter::MODKEY_SHIFT)
468 result |= KEYMOD_SHIFT;
469
470 if (modifiers & osgGA::GUIEventAdapter::MODKEY_CTRL)
471 result |= KEYMOD_CTRL;
472
473 if (modifiers & osgGA::GUIEventAdapter::MODKEY_ALT)
474 result |= KEYMOD_ALT;
475
476 if (modifiers & osgGA::GUIEventAdapter::MODKEY_META)
477 result |= KEYMOD_META;
478
479 if (modifiers & osgGA::GUIEventAdapter::MODKEY_SUPER)
480 result |= KEYMOD_SUPER;
481
482 if (modifiers & osgGA::GUIEventAdapter::MODKEY_HYPER)
483 result |= KEYMOD_HYPER;
484 return result;
485}
486
487void FGEventHandler::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
488 int& modifiers)
489{
490 key = translateKey(ea);
491 modifiers = translateModifiers(ea);
492 currentModifiers = modifiers;
493 const auto eventType = ea.getEventType();
494 if (eventType == osgGA::GUIEventAdapter::KEYUP)
495 modifiers |= KEYMOD_RELEASED;
496
497 // Release the letter key, for which the key press was reported. This
498 // is to deal with Ctrl-press -> a-press -> Ctrl-release -> a-release
499 // correctly.
500 if (key >= 0 && key < 128) {
501 if (modifiers & KEYMOD_RELEASED) {
502 key = release_keys[key];
503 } else {
504 release_keys[key] = key;
505 if (key >= 1 && key <= 26) {
506 release_keys[key + '@'] = key;
507 release_keys[key + '`'] = key;
508 } else if (key >= 'A' && key <= 'Z') {
509 release_keys[key - '@'] = key;
510 release_keys[tolower(key)] = key;
511 } else if (key >= 'a' && key <= 'z') {
512 release_keys[key - '`'] = key;
513 release_keys[toupper(key)] = key;
514 }
515 }
516 }
517}
518
519void FGEventHandler::handleStats(osgGA::GUIActionAdapter& us)
520{
521 int type = _display->getIntValue() % osgViewer::StatsHandler::LAST;
522 if (type != statsType) {
524 do {
525 statsType = (statsType + 1) % osgViewer::StatsHandler::LAST;
526 statsHandler->handle(*statsEvent, us);
528 statsHandler->getCamera()->setRenderOrder(osg::Camera::POST_RENDER, 99999);
530 }
531 } while (statsType != type);
532
533 _display->setIntValue(statsType);
534 }
535
536 if (_print->getBoolValue()) {
537 statsEvent->setKey(printStatsKey);
538 statsHandler->handle(*statsEvent, us);
539 _print->setBoolValue(false);
540 }
541}
542
543bool eventToWindowCoords(const osgGA::GUIEventAdapter* ea,
544 double& x, double& y)
545{
546 using namespace osg;
547 const GraphicsContext* gc = ea->getGraphicsContext();
548 if (!gc || !gc->getTraits()) {
549 return false;
550 }
551
552 const GraphicsContext::Traits* traits = gc->getTraits() ;
553 // Scale x, y to the dimensions of the window
554 x = (((ea->getX() - ea->getXmin()) / (ea->getXmax() - ea->getXmin()))
555 * (double)traits->width);
556 y = (((ea->getY() - ea->getYmin()) / (ea->getYmax() - ea->getYmin()))
557 * (double)traits->height);
558 if (ea->getMouseYOrientation() == osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS)
559 y = (double)traits->height - y;
560
561 return true;
562}
563
564}
#define PU_KEY_PAGE_DOWN
#define PU_KEY_INSERT
#define PU_KEY_F8
#define PU_KEY_DOWN
#define PU_KEY_UP
#define PU_KEY_RIGHT
#define PU_KEY_PAGE_UP
#define PU_KEY_END
#define PU_KEY_F7
#define PU_KEY_F4
#define PU_KEY_F2
#define PU_KEY_F3
#define PU_KEY_F10
#define PU_KEY_F5
#define PU_KEY_F1
#define PU_KEY_HOME
#define PU_KEY_F12
#define PU_KEY_F11
#define PU_KEY_F6
#define PU_KEY_LEFT
#define PU_KEY_F9
#define i(x)
static CameraGroup * getDefault()
Get the default CameraGroup.
void resized()
Update camera properties after a resize event.
static int translateModifiers(const osgGA::GUIEventAdapter &ea)
osg::ref_ptr< osgGA::GUIEventAdapter > statsEvent
void handleStats(osgGA::GUIActionAdapter &us)
void setWindowRectangleInteriorWithCorrection(osgViewer::GraphicsWindow *window, int x, int y, int width, int height)
fgMouseClickHandler mouseClickHandler
static int translateKey(const osgGA::GUIEventAdapter &ea)
osg::ref_ptr< FGStatsHandler > statsHandler
void handleKey(const osgGA::GUIEventAdapter &ea, int &key, int &modifiers)
bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us) override
fgMouseMotionHandler mouseMotionHandler
A window with a graphics context and an integer ID.
osg::ref_ptr< osg::GraphicsContext > gc
The OSG graphics context for this window.
Adapter from windows system / graphics context management API to functions used by flightgear.
GraphicsWindow * getGUIWindow() const
Get the first window marked as GUI (there should only be one).
static WindowSystemAdapter * getWSA()
Get the global WindowSystemAdapter.
void fgOSExit(int code)
@ KEYMOD_SUPER
Definition fg_os.hxx:30
@ KEYMOD_CTRL
Definition fg_os.hxx:27
@ KEYMOD_HYPER
Definition fg_os.hxx:31
@ KEYMOD_ALT
Definition fg_os.hxx:28
@ KEYMOD_META
Definition fg_os.hxx:29
@ KEYMOD_RELEASED
Definition fg_os.hxx:25
@ KEYMOD_SHIFT
Definition fg_os.hxx:26
FGGlobals * globals
Definition globals.cxx:142
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
Definition Addon.cxx:53
const int printStatsKey
bool eventToWindowCoords(const osgGA::GUIEventAdapter *ea, double &x, double &y)
osg::Camera * getGUICamera(CameraGroup *cgroup)
Get the osg::Camera that draws the GUI, if any, from a camera group.
const int displayStatsKey
Definition AIBase.hxx:25
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
Definition proptest.cpp:27
simgear::compositor::Compositor * SviewGetEventViewport(const osgGA::GUIEventAdapter &ea)
Definition sview.cxx:1829