diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 8b581c6d20..1a9700ce4b 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -276,6 +276,15 @@ void checkJoystickStatus() { } } +bool isGuiWindow(sgct::Window* window) { + if (Engine::instance().windows().size() == 1) { + // If we only have one window, assume it's also the GUI window. + // It might not have been given the 'GUI' tag + return true; + } + return window->hasTag("GUI"); +} + // // Init function // @@ -574,7 +583,7 @@ void mainPostDrawFunc() { void mainKeyboardCallback(sgct::Key key, sgct::Modifier modifiers, sgct::Action action, - int) + int, sgct::Window* window) { ZoneScoped LTRACE("main::mainKeyboardCallback(begin)"); @@ -582,7 +591,9 @@ void mainKeyboardCallback(sgct::Key key, sgct::Modifier modifiers, sgct::Action const openspace::Key k = openspace::Key(key); const KeyModifier m = KeyModifier(modifiers); const KeyAction a = KeyAction(action); - global::openSpaceEngine->keyboardCallback(k, m, a); + const IsGuiWindow isGui = IsGuiWindow(isGuiWindow(window)); + + global::openSpaceEngine->keyboardCallback(k, m, a, isGui); LTRACE("main::mainKeyboardCallback(begin)"); } @@ -590,7 +601,7 @@ void mainKeyboardCallback(sgct::Key key, sgct::Modifier modifiers, sgct::Action void mainMouseButtonCallback(sgct::MouseButton key, sgct::Modifier modifiers, - sgct::Action action) + sgct::Action action, sgct::Window* window) { ZoneScoped LTRACE("main::mainMouseButtonCallback(begin)"); @@ -598,36 +609,42 @@ void mainMouseButtonCallback(sgct::MouseButton key, sgct::Modifier modifiers, const openspace::MouseButton k = openspace::MouseButton(key); const openspace::MouseAction a = openspace::MouseAction(action); const openspace::KeyModifier m = openspace::KeyModifier(modifiers); - global::openSpaceEngine->mouseButtonCallback(k, a, m); + const IsGuiWindow isGui = IsGuiWindow(isGuiWindow(window)); + + global::openSpaceEngine->mouseButtonCallback(k, a, m, isGui); LTRACE("main::mainMouseButtonCallback(end)"); } -void mainMousePosCallback(double x, double y) { +void mainMousePosCallback(double x, double y, sgct::Window* window) { ZoneScoped - global::openSpaceEngine->mousePositionCallback(x, y); + const IsGuiWindow isGui = IsGuiWindow(isGuiWindow(window)); + global::openSpaceEngine->mousePositionCallback(x, y, isGui); } -void mainMouseScrollCallback(double posX, double posY) { +void mainMouseScrollCallback(double posX, double posY, sgct::Window* window) { ZoneScoped LTRACE("main::mainMouseScrollCallback(begin"); - global::openSpaceEngine->mouseScrollWheelCallback(posX, posY); + const IsGuiWindow isGui = IsGuiWindow(isGuiWindow(window)); + global::openSpaceEngine->mouseScrollWheelCallback(posX, posY, isGui); LTRACE("main::mainMouseScrollCallback(end)"); } -void mainCharCallback(unsigned int codepoint, int modifiers) { +void mainCharCallback(unsigned int codepoint, int modifiers, sgct::Window* window) { ZoneScoped const KeyModifier m = KeyModifier(modifiers); - global::openSpaceEngine->charCallback(codepoint, m); + const IsGuiWindow isGui = IsGuiWindow(isGuiWindow(window)); + + global::openSpaceEngine->charCallback(codepoint, m, isGui); } diff --git a/include/openspace/engine/globalscallbacks.h b/include/openspace/engine/globalscallbacks.h index fe095749ae..c6363785a8 100644 --- a/include/openspace/engine/globalscallbacks.h +++ b/include/openspace/engine/globalscallbacks.h @@ -28,11 +28,23 @@ #include #include #include +#include #include #include +namespace openspace { + BooleanType(IsGuiWindow); +} // namespace openspace + namespace openspace::global::callback { +using KeyboardCallback = std::function; +using CharacterCallback = std::function; +using MouseButtonCallback = + std::function; +using MousePositionCallback = std::function; +using MouseScrollWheelCallback = std::function; + inline std::vector>* initialize; inline std::vector>* deinitialize; inline std::vector>* initializeGL; @@ -42,12 +54,11 @@ inline std::vector>* postSyncPreDraw; inline std::vector>* render; inline std::vector>* draw2D; inline std::vector>* postDraw; -inline std::vector>* keyboard; -inline std::vector>* character; -inline std::vector>* - mouseButton; -inline std::vector>* mousePosition; -inline std::vector>* mouseScrollWheel; +inline std::vector* keyboard; +inline std::vector* character; +inline std::vector* mouseButton; +inline std::vector* mousePosition; +inline std::vector* mouseScrollWheel; inline std::vector>* touchDetected; inline std::vector>* touchUpdated; inline std::vector>* touchExit; diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 6bd1de4781..7f715b4629 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -25,6 +25,7 @@ #ifndef __OPENSPACE_CORE___OPENSPACEENGINE___H__ #define __OPENSPACE_CORE___OPENSPACEENGINE___H__ +#include #include #include #include @@ -92,11 +93,14 @@ public: void drawOverlays(); void postDraw(); void resetPropertyChangeFlags(); - void keyboardCallback(Key key, KeyModifier mod, KeyAction action); - void charCallback(unsigned int codepoint, KeyModifier modifier); - void mouseButtonCallback(MouseButton button, MouseAction action, KeyModifier mods); - void mousePositionCallback(double x, double y); - void mouseScrollWheelCallback(double posX, double posY); + void keyboardCallback(Key key, KeyModifier mod, KeyAction action, + IsGuiWindow isGuiWindow); + void charCallback(unsigned int codepoint, KeyModifier modifier, + IsGuiWindow isGuiWindow); + void mouseButtonCallback(MouseButton button, MouseAction action, + KeyModifier mods, IsGuiWindow isGuiWindow); + void mousePositionCallback(double x, double y, IsGuiWindow isGuiWindow); + void mouseScrollWheelCallback(double posX, double posY, IsGuiWindow isGuiWindow); void touchDetectionCallback(TouchInput input); void touchUpdateCallback(TouchInput input); void touchExitCallback(TouchInput input); diff --git a/modules/cefwebgui/src/guikeyboardhandler.cpp b/modules/cefwebgui/src/guikeyboardhandler.cpp index 82b7e75d50..7672649fdc 100644 --- a/modules/cefwebgui/src/guikeyboardhandler.cpp +++ b/modules/cefwebgui/src/guikeyboardhandler.cpp @@ -32,10 +32,10 @@ GUIKeyboardHandler::GUIKeyboardHandler() { _keyConsumed = false; global::callback::keyboard->emplace_back( - [&](Key, KeyModifier, KeyAction) -> bool { + [&](Key, KeyModifier, KeyAction, IsGuiWindow isGuiWindow) -> bool { const bool previous = _keyConsumed; _keyConsumed = false; - return previous; + return isGuiWindow ? previous : false; } ); } diff --git a/modules/imgui/imguimodule.cpp b/modules/imgui/imguimodule.cpp index fd94491b86..621154902a 100644 --- a/modules/imgui/imguimodule.cpp +++ b/modules/imgui/imguimodule.cpp @@ -153,31 +153,50 @@ ImGUIModule::ImGUIModule() }); global::callback::keyboard->emplace_back( - [&](Key key, KeyModifier mod, KeyAction action) -> bool { + [&](Key key, KeyModifier mod, KeyAction action, + IsGuiWindow isGuiWindow) -> bool + { ZoneScopedN("ImGUI") - return _isEnabled ? keyCallback(key, mod, action) : false; + if (!isGuiWindow || !_isEnabled) { + return false; + } + return keyCallback(key, mod, action); } ); global::callback::character->emplace_back( - [&](unsigned int codepoint, KeyModifier modifier) -> bool { + [&](unsigned int codepoint, KeyModifier modifier, + IsGuiWindow isGuiWindow) -> bool + { ZoneScopedN("ImGUI") - return _isEnabled ? charCallback(codepoint, modifier) : false; + if (!isGuiWindow || !_isEnabled) { + return false; + } + return charCallback(codepoint, modifier); } ); global::callback::mousePosition->emplace_back( - [&](double x, double y) { + [&](double x, double y, IsGuiWindow isGuiWindow) { + if (!isGuiWindow) { + return; // do nothing + } _mousePosition = glm::vec2(static_cast(x), static_cast(y)); } ); global::callback::mouseButton->emplace_back( - [&](MouseButton button, MouseAction action, KeyModifier) -> bool { + [&](MouseButton button, MouseAction action, KeyModifier, + IsGuiWindow isGuiWindow) -> bool + { ZoneScopedN("ImGUI") + if (!isGuiWindow) { + return false; + } + if (action == MouseAction::Press) { _mouseButtons |= (1 << static_cast(button)); } @@ -190,10 +209,13 @@ ImGUIModule::ImGUIModule() ); global::callback::mouseScrollWheel->emplace_back( - [&](double, double posY) -> bool { + [&](double, double posY, IsGuiWindow isGuiWindow) -> bool { ZoneScopedN("ImGUI") - return _isEnabled ? mouseWheelCallback(posY) : false; + if (!isGuiWindow || !_isEnabled) { + return false; + } + return mouseWheelCallback(posY); } ); @@ -225,7 +247,7 @@ void ImGUIModule::internalInitialize(const ghoul::Dictionary&) { const std::vector& nodes = scene ? scene->allSceneGraphNodes() : std::vector(); - + return std::vector(nodes.begin(), nodes.end()); } ); @@ -412,7 +434,7 @@ void ImGUIModule::internalInitializeGL() { sizeof(ImDrawVert), nullptr ); - + glEnableVertexAttribArray(uvAttrib); glVertexAttribPointer( uvAttrib, @@ -422,7 +444,7 @@ void ImGUIModule::internalInitializeGL() { sizeof(ImDrawVert), reinterpret_cast(offsetof(ImDrawVert, uv)) ); - + glEnableVertexAttribArray(colorAttrib); glVertexAttribPointer( colorAttrib, diff --git a/modules/skybrowser/skybrowsermodule.cpp b/modules/skybrowser/skybrowsermodule.cpp index 7fdb129768..9bac48e218 100644 --- a/modules/skybrowser/skybrowsermodule.cpp +++ b/modules/skybrowser/skybrowsermodule.cpp @@ -166,8 +166,9 @@ SkyBrowserModule::SkyBrowserModule() _wwtImageCollectionUrl.setReadOnly(true); // Set callback functions - global::callback::mouseButton->emplace(global::callback::mouseButton->begin(), - [&](MouseButton, MouseAction action, KeyModifier) -> bool { + global::callback::mouseButton->emplace( + global::callback::mouseButton->begin(), + [&](MouseButton button, MouseAction action, KeyModifier, IsGuiWindow) -> bool { if (action == MouseAction::Press) { _cameraRotation.stop(); } diff --git a/modules/webbrowser/src/eventhandler.cpp b/modules/webbrowser/src/eventhandler.cpp index a1f91d369d..b8f963a939 100644 --- a/modules/webbrowser/src/eventhandler.cpp +++ b/modules/webbrowser/src/eventhandler.cpp @@ -149,33 +149,41 @@ namespace { namespace openspace { void EventHandler::initialize() { - global::callback::character->emplace(global::callback::character->begin(), - [this](unsigned int charCode, KeyModifier mod) -> bool { - if (_browserInstance) { + global::callback::character->emplace( + global::callback::character->begin(), + [this](unsigned int charCode, KeyModifier mod, IsGuiWindow isGuiWindow) -> bool { + if (_browserInstance && isGuiWindow) { return charCallback(charCode, mod); } return false; } ); - global::callback::keyboard->emplace(global::callback::keyboard->begin(), - [this](Key key, KeyModifier mod, KeyAction action) -> bool { - if (_browserInstance) { + global::callback::keyboard->emplace( + global::callback::keyboard->begin(), + [this](Key key, KeyModifier mod, KeyAction action, + IsGuiWindow isGuiWindow) -> bool + { + if (_browserInstance && isGuiWindow) { return keyboardCallback(key, mod, action); } return false; } ); - global::callback::mousePosition->emplace(global::callback::mousePosition->begin(), - [this](double x, double y) -> bool { - if (_browserInstance) { + global::callback::mousePosition->emplace( + global::callback::mousePosition->begin(), + [this](double x, double y, IsGuiWindow isGuiWindow) -> bool { + if (_browserInstance && isGuiWindow) { return mousePositionCallback(x, y); } return false; } ); - [this](MouseButton button, MouseAction action, KeyModifier mods) -> bool { - if (_browserInstance) { - global::callback::mouseButton->emplace(global::callback::mouseButton->begin(), + global::callback::mouseButton->emplace( + global::callback::mouseButton->begin(), + [this](MouseButton button, MouseAction action, + KeyModifier mods, IsGuiWindow isGuiWindow) -> bool + { + if (_browserInstance && isGuiWindow) { return mouseButtonCallback(button, action, mods); } return false; @@ -183,15 +191,16 @@ void EventHandler::initialize() { ); global::callback::mouseScrollWheel->emplace( global::callback::mouseScrollWheel->begin(), - [this](double x, double y) -> bool { - if (_browserInstance) { + [this](double x, double y, IsGuiWindow isGuiWindow) -> bool { + if (_browserInstance && isGuiWindow) { return mouseWheelCallback(glm::ivec2(x, y)); } return false; } ); - global::callback::touchDetected->emplace(global::callback::touchDetected->begin(), + global::callback::touchDetected->emplace( + global::callback::touchDetected->begin(), [&](TouchInput input) -> bool { if (!_browserInstance) { return false; @@ -230,7 +239,8 @@ void EventHandler::initialize() { } ); - global::callback::touchUpdated->emplace(global::callback::touchUpdated->begin(), + global::callback::touchUpdated->emplace( + global::callback::touchUpdated->begin(), [&](TouchInput input) -> bool { if (!_browserInstance || _validTouchStates.empty()) { return false; @@ -268,7 +278,8 @@ void EventHandler::initialize() { } ); - global::callback::touchExit->emplace(global::callback::touchExit->begin(), + global::callback::touchExit->emplace( + global::callback::touchExit->begin(), [&](TouchInput input) { if (!_browserInstance) { return; diff --git a/src/engine/globalscallbacks.cpp b/src/engine/globalscallbacks.cpp index e5cfbb329c..f04aacff05 100644 --- a/src/engine/globalscallbacks.cpp +++ b/src/engine/globalscallbacks.cpp @@ -43,11 +43,11 @@ namespace { sizeof(std::vector>) + sizeof(std::vector>) + sizeof(std::vector>) + - sizeof(std::vector>) + - sizeof(std::vector>) + - sizeof(std::vector>) + - sizeof(std::vector>) + - sizeof(std::vector>) + + sizeof(std::vector) + + sizeof(std::vector) + + sizeof(std::vector) + + sizeof(std::vector) + + sizeof(std::vector) + sizeof(std::vector>) + sizeof(std::vector>) + sizeof(std::vector>); @@ -138,51 +138,44 @@ void create() { #endif // WIN32 #ifdef WIN32 - keyboard = - new (currentPos) std::vector>; + keyboard = new (currentPos) std::vector ghoul_assert(keyboard, "No keyboard"); - currentPos += sizeof(std::vector>); + currentPos += sizeof(std::vector); #else // ^^^ WIN32 / !WIN32 vvv - keyboard = new std::vector>; + keyboard = new std::vector; #endif // WIN32 #ifdef WIN32 - character = - new (currentPos) std::vector>; + character = new (currentPos) std::vector; ghoul_assert(character, "No character"); - currentPos += sizeof(std::vector>); + currentPos += sizeof(std::vector); #else // ^^^ WIN32 / !WIN32 vvv - character = new std::vector>; + character = new std::vector; #endif // WIN32 #ifdef WIN32 - mouseButton = - new (currentPos) std::vector< - std::function - >; + mouseButton = new (currentPos) std::vector; ghoul_assert(mouseButton, "No mouseButton"); - currentPos += sizeof( - std::vector> - ); + currentPos += sizeof(std::vector); #else // ^^^ WIN32 / !WIN32 vvv - mouseButton = - new std::vector>; + mouseButton = new std::vector; #endif // WIN32 #ifdef WIN32 - mousePosition = new (currentPos) std::vector>; + mousePosition = + new (currentPos) std::vector; ghoul_assert(mousePosition, "No mousePosition"); - currentPos += sizeof(std::vector>); + currentPos += sizeof(std::vector); #else // ^^^ WIN32 / !WIN32 vvv - mousePosition = new std::vector>; + mousePosition = new std::vector; #endif // WIN32 #ifdef WIN32 - mouseScrollWheel = new (currentPos) std::vector>; + mouseScrollWheel = new (currentPos) std::vector; ghoul_assert(mouseScrollWheel, "No mouseScrollWheel"); - currentPos += sizeof(std::vector>); + currentPos += sizeof(std::vector); #else // ^^^ WIN32 / !WIN32 vvv - mouseScrollWheel = new std::vector>; + mouseScrollWheel = new std::vector; #endif // WIN32 #ifdef WIN32 diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 0d4e371ef9..8e9308742a 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -1408,7 +1407,9 @@ void OpenSpaceEngine::resetPropertyChangeFlagsOfSubowners(properties::PropertyOw } } -void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction action) { +void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction action, + IsGuiWindow isGuiWindow) +{ ZoneScoped if (_loadingScreen) { @@ -1421,9 +1422,9 @@ void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction actio return; } - using F = std::function; + using F = global::callback::KeyboardCallback; for (const F& func : *global::callback::keyboard) { - const bool isConsumed = func(key, mod, action); + const bool isConsumed = func(key, mod, action, isGuiWindow); if (isConsumed) { return; } @@ -1441,12 +1442,14 @@ void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction actio global::interactionMonitor->markInteraction(); } -void OpenSpaceEngine::charCallback(unsigned int codepoint, KeyModifier modifier) { +void OpenSpaceEngine::charCallback(unsigned int codepoint, KeyModifier modifier, + IsGuiWindow isGuiWindow) +{ ZoneScoped - using F = std::function; + using F = global::callback::CharacterCallback; for (const F& func : *global::callback::character) { - bool isConsumed = func(codepoint, modifier); + bool isConsumed = func(codepoint, modifier, isGuiWindow); if (isConsumed) { return; } @@ -1456,22 +1459,22 @@ void OpenSpaceEngine::charCallback(unsigned int codepoint, KeyModifier modifier) global::interactionMonitor->markInteraction(); } -void OpenSpaceEngine::mouseButtonCallback(MouseButton button, - MouseAction action, - KeyModifier mods) +void OpenSpaceEngine::mouseButtonCallback(MouseButton button, MouseAction action, + KeyModifier mods, IsGuiWindow isGuiWindow) { ZoneScoped - using F = std::function; + using F = global::callback::MouseButtonCallback; for (const F& func : *global::callback::mouseButton) { - bool isConsumed = func(button, action, mods); + bool isConsumed = func(button, action, mods, isGuiWindow); if (isConsumed) { // If the mouse was released, we still want to forward it to the navigation - // handler in order to reliably terminate a rotation or zoom. Accidentally + // handler in order to reliably terminate a rotation or zoom, or to the other + // callbacks to for example release a drag and drop of a UI window. Accidentally // moving the cursor over a UI window is easy to miss and leads to weird // continuing movement if (action == MouseAction::Release) { - break; + continue; } else { return; @@ -1479,8 +1482,9 @@ void OpenSpaceEngine::mouseButtonCallback(MouseButton button, } } - // Check if the user clicked on one of the 'buttons' the RenderEngine is drawing - if (action == MouseAction::Press) { + // Check if the user clicked on one of the 'buttons' the RenderEngine is drawing. + // Only handle the clicks if we are in a GUI window + if (action == MouseAction::Press && isGuiWindow) { bool isConsumed = global::renderEngine->mouseActivationCallback(_mousePosition); if (isConsumed) { return; @@ -1491,12 +1495,14 @@ void OpenSpaceEngine::mouseButtonCallback(MouseButton button, global::interactionMonitor->markInteraction(); } -void OpenSpaceEngine::mousePositionCallback(double x, double y) { +void OpenSpaceEngine::mousePositionCallback(double x, double y, + IsGuiWindow isGuiWindow) +{ ZoneScoped - using F = std::function; + using F = global::callback::MousePositionCallback; for (const F& func : *global::callback::mousePosition) { - func(x, y); + func(x, y, isGuiWindow); } global::navigationHandler->mousePositionCallback(x, y); @@ -1505,12 +1511,14 @@ void OpenSpaceEngine::mousePositionCallback(double x, double y) { _mousePosition = glm::vec2(static_cast(x), static_cast(y)); } -void OpenSpaceEngine::mouseScrollWheelCallback(double posX, double posY) { +void OpenSpaceEngine::mouseScrollWheelCallback(double posX, double posY, + IsGuiWindow isGuiWindow) +{ ZoneScoped - using F = std::function; + using F = global::callback::MouseScrollWheelCallback; for (const F& func : *global::callback::mouseScrollWheel) { - bool isConsumed = func(posX, posY); + bool isConsumed = func(posX, posY, isGuiWindow); if (isConsumed) { return; }