diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1ea2e559cc..bd126c2d58 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7347,10 +7347,35 @@ bool Application::isThrottleRendering() const { } bool Application::hasFocus() const { - if (_displayPlugin) { - return getActiveDisplayPlugin()->hasFocus(); + bool result = (QApplication::activeWindow() != nullptr); +#if defined(Q_OS_WIN) + // On Windows, QWidget::activateWindow() - as called in setFocus() - makes the application's taskbar icon flash but doesn't + // take user focus away from their current window. So also check whether the application is the user's current foreground + // window. + result = result && (HWND)QApplication::activeWindow()->winId() == GetForegroundWindow(); +#endif + return result; +} + +void Application::setFocus() { + // Note: Windows doesn't allow a user focus to be taken away from another application. Instead, it changes the color of and + // flashes the taskbar icon. + auto window = qApp->getWindow(); + window->activateWindow(); +} + +void Application::raise() { + auto windowState = qApp->getWindow()->windowState(); + if (windowState & Qt::WindowMinimized) { + if (windowState & Qt::WindowMaximized) { + qApp->getWindow()->showMaximized(); + } else if (windowState & Qt::WindowFullScreen) { + qApp->getWindow()->showFullScreen(); + } else { + qApp->getWindow()->showNormal(); + } } - return (QApplication::activeWindow() != nullptr); + qApp->getWindow()->raise(); } void Application::setMaxOctreePacketsPerSecond(int maxOctreePPS) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 95aaa9b6cd..420df1fb3f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -161,6 +161,8 @@ public: QRect getRecommendedHUDRect() const; glm::vec2 getDeviceSize() const; bool hasFocus() const; + void setFocus(); + void raise(); void showCursor(const Cursor::Icon& cursor); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index e0a008b25e..4cedfb5a34 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -74,16 +74,14 @@ QScriptValue WindowScriptingInterface::hasFocus() { void WindowScriptingInterface::setFocus() { // It's forbidden to call focus() from another thread. qApp->postLambdaEvent([] { - auto window = qApp->getWindow(); - window->activateWindow(); - window->setFocus(); + qApp->setFocus(); }); } void WindowScriptingInterface::raiseMainWindow() { // It's forbidden to call raise() from another thread. qApp->postLambdaEvent([] { - qApp->getWindow()->raise(); + qApp->raise(); }); } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 5a30f44856..2a9806a302 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -62,13 +62,14 @@ public slots: QScriptValue hasFocus(); /**jsdoc - * Make the Interface window have focus. + * Make the Interface window have focus. On Windows, if Interface doesn't already have focus, the task bar icon flashes to + * indicate that Interface wants attention but focus isn't taken away from the application that the user is using. * @function Window.setFocus */ void setFocus(); /**jsdoc - * Raise the Interface window if it is minimized, and give it focus. + * Raise the Interface window if it is minimized. If raised, the window gains focus. * @function Window.raiseMainWindow */ void raiseMainWindow(); diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index 6a19a34727..47a213cf71 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -21,10 +21,6 @@ glm::uvec2 NullDisplayPlugin::getRecommendedRenderSize() const { return glm::uvec2(100, 100); } -bool NullDisplayPlugin::hasFocus() const { - return false; -} - void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) { if (frame) { _gpuContext->consumeFrameUpdates(frame); diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index 97b71b5780..11563b3798 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -16,7 +16,6 @@ public: grouping getGrouping() const override { return DEVELOPER; } glm::uvec2 getRecommendedRenderSize() const override; - bool hasFocus() const override; void submitFrame(const gpu::FramePointer& newFrame) override; QImage getScreenshot(float aspectRatio = 0.0f) const override; QImage getSecondaryCameraScreenshot() const override; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index db9b86b9dd..9597be7e53 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -831,11 +831,6 @@ glm::uvec2 OpenGLDisplayPlugin::getSurfaceSize() const { return result; } -bool OpenGLDisplayPlugin::hasFocus() const { - auto window = _container->getPrimaryWidget(); - return window ? window->hasFocus() : false; -} - void OpenGLDisplayPlugin::assertNotPresentThread() const { Q_ASSERT(QThread::currentThread() != _presentThread); } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index bde7984ec0..1cc060161b 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -98,8 +98,6 @@ protected: virtual void compositePointer(); virtual void compositeExtra() {}; - virtual bool hasFocus() const override; - // These functions must only be called on the presentation thread virtual void customizeContext(); virtual void uncustomizeContext(); diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index e95084df52..ff6801109e 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -140,9 +140,6 @@ public: virtual void setContext(const gpu::ContextPointer& context) final { _gpuContext = context; } virtual void submitFrame(const gpu::FramePointer& newFrame) = 0; - // Does the rendering surface have current focus? - virtual bool hasFocus() const = 0; - // The size of the rendering target (may be larger than the device size due to distortion) virtual glm::uvec2 getRecommendedRenderSize() const = 0;