diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 60b6171fa7..621210cc4e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -673,8 +673,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::DomainConnectionDenied, this, "handleDomainConnectionDeniedPacket"); + // If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it auto entityScriptingInterface = DependencyManager::get(); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, [this, entityScriptingInterface](const EntityItemID& entityItemID, const MouseEvent& event) { + connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, + [this, entityScriptingInterface](const EntityItemID& entityItemID, const MouseEvent& event) { if (_keyboardFocusedItem != entityItemID) { _keyboardFocusedItem = UNKNOWN_ENTITY_ID; auto properties = entityScriptingInterface->getEntityProperties(entityItemID); @@ -684,15 +686,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : if (webEntity) { webEntity->setProxyWindow(_window->windowHandle()); _keyboardFocusedItem = entityItemID; + _lastAcceptedKeyPress = usecTimestampNow(); } } } }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const MouseEvent& event) { - if (_keyboardFocusedItem == entityItemID) { - _keyboardFocusedItem = UNKNOWN_ENTITY_ID; - } + // If the user clicks somewhere where there is NO entity at all, we will release focus + connect(getEntities(), &EntityTreeRenderer::mousePressOffEntity, + [=](const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId) { + _keyboardFocusedItem = UNKNOWN_ENTITY_ID; }); } @@ -1270,6 +1273,7 @@ bool Application::event(QEvent* event) { event->setAccepted(false); QCoreApplication::sendEvent(webEntity->getEventHandler(), event); if (event->isAccepted()) { + _lastAcceptedKeyPress = usecTimestampNow(); return true; } } @@ -1986,6 +1990,15 @@ void Application::idle() { return; // bail early, nothing to do here. } + // Drop focus from _keyboardFocusedItem if no keyboard messages for 30 seconds + if (!_keyboardFocusedItem.isInvalidID()) { + const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus + quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress; + if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) { + _keyboardFocusedItem = UNKNOWN_ENTITY_ID; + } + } + // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing // details normally. diff --git a/interface/src/Application.h b/interface/src/Application.h index cec1325baf..e0d4fa559d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -680,6 +680,7 @@ private: DialogsManagerScriptingInterface* _dialogsManagerScriptingInterface = new DialogsManagerScriptingInterface(); EntityItemID _keyboardFocusedItem; + quint64 _lastAcceptedKeyPress = 0; }; #endif // hifi_Application_h diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 50f79e2ff3..72400dcefb 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -861,6 +861,8 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device if (entityScript.property("clickDownOnEntity").isValid()) { entityScript.property("clickDownOnEntity").call(entityScript, entityScriptArgs); } + } else { + emit mousePressOffEntity(rayPickResult, event, deviceID); } _lastMouseEvent = MouseEvent(*event, deviceID); _lastMouseEventValid = true; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 39f088f06d..25eb87b422 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -95,6 +95,7 @@ public: signals: void mousePressOnEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId); + void mousePressOffEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId); void mouseMoveOnEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId); void mouseReleaseOnEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 73aa6f2718..84707aca3b 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -56,6 +56,16 @@ RenderableWebEntityItem::~RenderableWebEntityItem() { } void RenderableWebEntityItem::render(RenderArgs* args) { + + #ifdef WANT_EXTRA_DEBUGGING + { + gpu::Batch& batch = *args->_batch; + batch.setModelTransform(getTransformToCenter()); // we want to include the scale as well + glm::vec4 cubeColor{ 1.0f, 0.0f, 0.0f, 1.0f}; + DependencyManager::get()->renderWireCube(batch, 1.0f, cubeColor); + } + #endif + QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); if (!_webSurface) {