ksuprynowiczFix UI input on Vulkan3c0a8391 year agoHistory
308 lines · 10.3 KB · C++
RawDownload
////  HMDToolsDialog.cpp//  interface/src/ui////  Created by Brad Hefta-Gaub on 7/19/13.//  Copyright 2013 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include "HMDToolsDialog.h" #include <QDesktopWidget>#include <QDialogButtonBox>#include <QFormLayout>#include <QGuiApplication>#include <QLabel>#include <QPushButton>#include <QString>#include <QScreen>#include <QWindow> #include <plugins/PluginManager.h>#include <display-plugins/DisplayPlugin.h> #include "Application.h"#include "MainWindow.h"#include "Menu.h"#include "DialogsManager.h"#include "LodToolsDialog.h"#include "OctreeStatsDialog.h" static const int WIDTH = 350;static const int HEIGHT = 100;  HMDToolsDialog::HMDToolsDialog(QWidget* parent) :    QDialog(parent, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowStaysOnTopHint){    // FIXME do we want to support more than one connected HMD?  It seems like a pretty corner case    for (const auto &displayPlugin : PluginManager::getInstance()->getDisplayPlugins()) {        // The first plugin is always the standard 2D display, by convention        if (_defaultPluginName.isEmpty()) {            _defaultPluginName = displayPlugin->getName();            continue;        }         if (displayPlugin->isHmd()) {            // Not all HMD's have corresponding screens            if (displayPlugin->getHmdScreen() >= 0) {                _hmdScreenNumber = displayPlugin->getHmdScreen();            }            _hmdPluginName = displayPlugin->getName();            break;        }    }     setWindowTitle("HMD Tools");     // Create layouter    {        QFormLayout* form = new QFormLayout();        // Add a button to enter        _switchModeButton = new QPushButton("Toggle HMD Mode");        if (_hmdPluginName.isEmpty()) {            _switchModeButton->setEnabled(false);        }        // Add a button to enter        _switchModeButton->setFixedWidth(WIDTH);        form->addRow("", _switchModeButton);        // Create a label with debug details...        _debugDetails = new QLabel();        _debugDetails->setFixedSize(WIDTH, HEIGHT);        form->addRow("", _debugDetails);        setLayout(form);    } #ifdef USE_GL    qApp->getWindow()->activateWindow(); //VKTODO#endif     // watch for our dialog window moving screens. If it does we want to enforce our rules about    // what screens we're allowed on    watchWindow(windowHandle());    auto dialogsManager = DependencyManager::get<DialogsManager>();    if (dialogsManager->getOctreeStatsDialog()) {        watchWindow(dialogsManager->getOctreeStatsDialog()->windowHandle());    }    if (dialogsManager->getLodToolsDialog()) {        watchWindow(dialogsManager->getLodToolsDialog()->windowHandle());    }     connect(_switchModeButton, &QPushButton::clicked, [this]{        toggleHMDMode();    });     // when the application is about to quit, leave HDM mode    connect(qApp, &Application::beforeAboutToQuit, [this]{        // FIXME this is ineffective because it doesn't trigger the menu to        // save the fact that VR Mode is not checked.        leaveHMDMode();    });     connect(qApp, &Application::activeDisplayPluginChanged, [this]{        updateUi();    });     // watch for our application window moving screens. If it does we want to update our screen details    QWindow* mainWindow = qApp->getWindow()->windowHandle();    connect(mainWindow, &QWindow::screenChanged, [this]{        updateUi();    });      // keep track of changes to the number of screens    connect(qApp, &QGuiApplication::screenAdded, this, &HMDToolsDialog::screenCountChanged);    connect(qApp, &QGuiApplication::screenRemoved, this, &HMDToolsDialog::screenCountChanged);     updateUi();} HMDToolsDialog::~HMDToolsDialog() {    foreach(HMDWindowWatcher* watcher, _windowWatchers) {        delete watcher;    }    _windowWatchers.clear();} QString HMDToolsDialog::getDebugDetails() const {    QString results;     if (_hmdScreenNumber >= 0) {        results += "HMD Screen: " + QGuiApplication::screens()[_hmdScreenNumber]->name() + "\n";    } else {        results += "HMD Screen Name: N/A\n";    }     QScreen* desktopPrimaryScreen = QGuiApplication::primaryScreen();    results += "Desktop's Primary Screen: " + desktopPrimaryScreen->name() + "\n";     results += "Application Primary Screen: " + QGuiApplication::primaryScreen()->name() + "\n";    QScreen* mainWindowScreen = qApp->getWindow()->windowHandle()->screen();    results += "Application Main Window Screen: " + mainWindowScreen->name() + "\n";    results += "Total Screens: " + QString::number(QGuiApplication::screens().count()) + "\n";     return results;} void HMDToolsDialog::toggleHMDMode() {    if (!qApp->isHMDMode()) {        enterHMDMode();    } else {        leaveHMDMode();    }} void HMDToolsDialog::enterHMDMode() {    if (!qApp->isHMDMode()) {        qApp->setActiveDisplayPlugin(_hmdPluginName);#ifdef USE_GL        qApp->getWindow()->activateWindow(); //VKTODO#endif    }} void HMDToolsDialog::leaveHMDMode() {    if (qApp->isHMDMode()) {        qApp->setActiveDisplayPlugin(_defaultPluginName);#ifdef USE_GL        qApp->getWindow()->activateWindow(); //VKTODO#endif    }} void HMDToolsDialog::reject() {    // We don't want this window to be closable from a close icon, just from our "Leave HMD Mode" button} void HMDToolsDialog::closeEvent(QCloseEvent* event) {    // We don't want this window to be closable from a close icon, just from our "Leave HMD Mode" button    event->ignore();} void HMDToolsDialog::centerCursorOnWidget(QWidget* widget) {    QWindow* window = widget->windowHandle();    QScreen* screen = window->screen();    QPoint windowCenter = window->geometry().center();    QCursor::setPos(screen, windowCenter);} void HMDToolsDialog::updateUi() {    _switchModeButton->setText(qApp->isHMDMode() ? "Leave HMD Mode" : "Enter HMD Mode");    _debugDetails->setText(getDebugDetails());} void HMDToolsDialog::showEvent(QShowEvent* event) {    // center the cursor on the hmd tools dialog    centerCursorOnWidget(this);    updateUi();} void HMDToolsDialog::hideEvent(QHideEvent* event) {    // center the cursor on the main application window    centerCursorOnWidget(qApp->getWindow());} void HMDToolsDialog::screenCountChanged() {    int hmdScreenNumber = -1;    const auto& displayPlugins = PluginManager::getInstance()->getDisplayPlugins();    for(const auto& dp : displayPlugins) {        if (dp->isHmd()) {            if (dp->getHmdScreen() >= 0) {                hmdScreenNumber = dp->getHmdScreen();            }            break;        }    }     if (qApp->isHMDMode() && _hmdScreenNumber != hmdScreenNumber) {        qDebug() << "HMD Display changed WHILE IN HMD MODE";        leaveHMDMode();         // if there is a new best HDM screen then go back into HDM mode after done leaving        if (hmdScreenNumber >= 0) {            qDebug() << "Trying to go back into HMD Mode";            const int SLIGHT_DELAY = 2000;            QTimer::singleShot(SLIGHT_DELAY, [this]{                enterHMDMode();            });        }    }} void HMDToolsDialog::watchWindow(QWindow* window) {    qDebug() << "HMDToolsDialog::watchWindow() window:" << window;    if (window && !_windowWatchers.contains(window)) {        HMDWindowWatcher* watcher = new HMDWindowWatcher(window, this);        _windowWatchers[window] = watcher;    }}  HMDWindowWatcher::HMDWindowWatcher(QWindow* window, HMDToolsDialog* hmdTools) :    _window(window),    _hmdTools(hmdTools),    _previousScreen(NULL){    connect(window, &QWindow::screenChanged, this, &HMDWindowWatcher::windowScreenChanged);    connect(window, &QWindow::xChanged, this, &HMDWindowWatcher::windowGeometryChanged);    connect(window, &QWindow::yChanged, this, &HMDWindowWatcher::windowGeometryChanged);    connect(window, &QWindow::widthChanged, this, &HMDWindowWatcher::windowGeometryChanged);    connect(window, &QWindow::heightChanged, this, &HMDWindowWatcher::windowGeometryChanged);} HMDWindowWatcher::~HMDWindowWatcher() {}  void HMDWindowWatcher::windowGeometryChanged(int arg) {    _previousRect = _window->geometry();    _previousScreen = _window->screen();} void HMDWindowWatcher::windowScreenChanged(QScreen* screen) {    // if we have more than one screen, and a known hmdScreen then try to    // keep our dialog off of the hmdScreen    if (QGuiApplication::screens().count() > 1) {        int hmdScreenNumber = _hmdTools->_hmdScreenNumber;        // we want to use a local variable here because we are not necesarily in HMD mode        if (hmdScreenNumber >= 0) {            QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber];            if (screen == hmdScreen) {                qDebug() << "HMD Tools: Whoa! What are you doing? You don't want to move me to the HMD Screen!";                 // try to pick a better screen                QScreen* betterScreen = NULL;                 QScreen* lastApplicationScreen = _hmdTools->getLastApplicationScreen();                QWindow* appWindow = qApp->getWindow()->windowHandle();                QScreen* appScreen = appWindow->screen();                 if (_previousScreen && _previousScreen != hmdScreen) {                    // first, if the previous dialog screen is not the HMD screen, then move it there.                    betterScreen = _previousScreen;                } else if (appScreen != hmdScreen) {                    // second, if the application screen is not the HMD screen, then move it there.                    betterScreen = appScreen;                } else if (lastApplicationScreen && lastApplicationScreen != hmdScreen) {                    // third, if the application screen is the HMD screen, we want to move it to                    // the previous screen                    betterScreen = lastApplicationScreen;                } else {                    // last, if we can't use the previous screen the use the primary desktop screen                    QScreen* desktopPrimaryScreen = QGuiApplication::primaryScreen();                    betterScreen = desktopPrimaryScreen;                }                 if (betterScreen) {                    _window->setScreen(betterScreen);                    _window->setGeometry(_previousRect);                }            }        }    }}