mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-16 14:46:17 +02:00
346 lines
13 KiB
C++
346 lines
13 KiB
C++
//
|
|
// 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 <QFormLayout>
|
|
#include <QGuiApplication>
|
|
#include <QDialogButtonBox>
|
|
|
|
#include <QDesktopWidget>
|
|
#include <QPushButton>
|
|
#include <QString>
|
|
#include <QScreen>
|
|
#include <QWindow>
|
|
|
|
#include "MainWindow.h"
|
|
#include "Menu.h"
|
|
#include "ui/DialogsManager.h"
|
|
#include "ui/HMDToolsDialog.h"
|
|
#include "devices/OculusManager.h"
|
|
|
|
HMDToolsDialog::HMDToolsDialog(QWidget* parent) :
|
|
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) ,
|
|
_previousScreen(NULL),
|
|
_hmdScreen(NULL),
|
|
_hmdScreenNumber(-1),
|
|
_switchModeButton(NULL),
|
|
_debugDetails(NULL),
|
|
_previousDialogScreen(NULL),
|
|
_inHDMMode(false)
|
|
{
|
|
this->setWindowTitle("HMD Tools");
|
|
|
|
// Create layouter
|
|
QFormLayout* form = new QFormLayout();
|
|
const int WIDTH = 350;
|
|
|
|
// Add a button to enter
|
|
_switchModeButton = new QPushButton("Enter HMD Mode");
|
|
_switchModeButton->setFixedWidth(WIDTH);
|
|
form->addRow("", _switchModeButton);
|
|
connect(_switchModeButton,SIGNAL(clicked(bool)),this,SLOT(switchModeClicked(bool)));
|
|
|
|
// Create a label with debug details...
|
|
_debugDetails = new QLabel();
|
|
_debugDetails->setText(getDebugDetails());
|
|
const int HEIGHT = 100;
|
|
_debugDetails->setFixedSize(WIDTH, HEIGHT);
|
|
form->addRow("", _debugDetails);
|
|
|
|
this->QDialog::setLayout(form);
|
|
|
|
_wasMoved = false;
|
|
_previousRect = Application::getInstance()->getWindow()->rect();
|
|
Application::getInstance()->getWindow()->activateWindow();
|
|
|
|
// watch for our application window moving screens. If it does we want to update our screen details
|
|
QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle();
|
|
connect(mainWindow, &QWindow::screenChanged, this, &HMDToolsDialog::applicationWindowScreenChanged);
|
|
|
|
// 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 (Application::getInstance()->getRunningScriptsWidget()) {
|
|
watchWindow(Application::getInstance()->getRunningScriptsWidget()->windowHandle());
|
|
}
|
|
if (Application::getInstance()->getToolWindow()) {
|
|
watchWindow(Application::getInstance()->getToolWindow()->windowHandle());
|
|
}
|
|
if (dialogsManager->getBandwidthDialog()) {
|
|
watchWindow(dialogsManager->getBandwidthDialog()->windowHandle());
|
|
}
|
|
if (dialogsManager->getOctreeStatsDialog()) {
|
|
watchWindow(dialogsManager->getOctreeStatsDialog()->windowHandle());
|
|
}
|
|
if (dialogsManager->getLodToolsDialog()) {
|
|
watchWindow(dialogsManager->getLodToolsDialog()->windowHandle());
|
|
}
|
|
|
|
// when the application is about to quit, leave HDM mode
|
|
connect(Application::getInstance(), SIGNAL(beforeAboutToQuit()), this, SLOT(aboutToQuit()));
|
|
|
|
// keep track of changes to the number of screens
|
|
connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &HMDToolsDialog::screenCountChanged);
|
|
}
|
|
|
|
HMDToolsDialog::~HMDToolsDialog() {
|
|
foreach(HMDWindowWatcher* watcher, _windowWatchers) {
|
|
delete watcher;
|
|
}
|
|
_windowWatchers.clear();
|
|
}
|
|
|
|
void HMDToolsDialog::applicationWindowScreenChanged(QScreen* screen) {
|
|
_debugDetails->setText(getDebugDetails());
|
|
}
|
|
|
|
QString HMDToolsDialog::getDebugDetails() const {
|
|
QString results;
|
|
|
|
int hmdScreenNumber = OculusManager::getHMDScreen();
|
|
if (hmdScreenNumber >= 0) {
|
|
results += "HMD Screen: " + QGuiApplication::screens()[hmdScreenNumber]->name() + "\n";
|
|
} else {
|
|
results += "HMD Screen Name: Unknown\n";
|
|
}
|
|
|
|
int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen();
|
|
QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber];
|
|
results += "Desktop's Primary Screen: " + desktopPrimaryScreen->name() + "\n";
|
|
|
|
results += "Application Primary Screen: " + QGuiApplication::primaryScreen()->name() + "\n";
|
|
QScreen* mainWindowScreen = Application::getInstance()->getWindow()->windowHandle()->screen();
|
|
results += "Application Main Window Screen: " + mainWindowScreen->name() + "\n";
|
|
results += "Total Screens: " + QString::number(QApplication::desktop()->screenCount()) + "\n";
|
|
|
|
return results;
|
|
}
|
|
|
|
void HMDToolsDialog::switchModeClicked(bool checked) {
|
|
if (!_inHDMMode) {
|
|
enterHDMMode();
|
|
} else {
|
|
leaveHDMMode();
|
|
}
|
|
}
|
|
|
|
void HMDToolsDialog::enterHDMMode() {
|
|
if (!_inHDMMode) {
|
|
_switchModeButton->setText("Leave HMD Mode");
|
|
_debugDetails->setText(getDebugDetails());
|
|
|
|
_hmdScreenNumber = OculusManager::getHMDScreen();
|
|
|
|
if (_hmdScreenNumber >= 0) {
|
|
QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle();
|
|
_hmdScreen = QGuiApplication::screens()[_hmdScreenNumber];
|
|
|
|
_previousRect = Application::getInstance()->getWindow()->rect();
|
|
_previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()),
|
|
mainWindow->mapToGlobal(_previousRect.bottomRight()));
|
|
_previousScreen = mainWindow->screen();
|
|
QRect rect = QApplication::desktop()->screenGeometry(_hmdScreenNumber);
|
|
mainWindow->setScreen(_hmdScreen);
|
|
mainWindow->setGeometry(rect);
|
|
|
|
_wasMoved = true;
|
|
}
|
|
|
|
|
|
// if we're on a single screen setup, then hide our tools window when entering HMD mode
|
|
if (QApplication::desktop()->screenCount() == 1) {
|
|
close();
|
|
}
|
|
|
|
Application::getInstance()->setEnableVRMode(true);
|
|
|
|
const int SLIGHT_DELAY = 500;
|
|
// If we go to fullscreen immediately, it ends up on the primary monitor,
|
|
// even though we've already moved the window. By adding this delay, the
|
|
// fullscreen target screen ends up correct.
|
|
QTimer::singleShot(SLIGHT_DELAY, this, [&]{
|
|
Application::getInstance()->setFullscreen(true);
|
|
activateWindowAfterEnterMode();
|
|
});
|
|
|
|
_inHDMMode = true;
|
|
}
|
|
}
|
|
|
|
void HMDToolsDialog::activateWindowAfterEnterMode() {
|
|
Application::getInstance()->getWindow()->activateWindow();
|
|
|
|
// center the cursor on the main application window
|
|
centerCursorOnWidget(Application::getInstance()->getWindow());
|
|
}
|
|
|
|
void HMDToolsDialog::leaveHDMMode() {
|
|
if (_inHDMMode) {
|
|
_switchModeButton->setText("Enter HMD Mode");
|
|
_debugDetails->setText(getDebugDetails());
|
|
|
|
Application::getInstance()->setEnableVRMode(false);
|
|
Application::getInstance()->setFullscreen(false);
|
|
Application::getInstance()->getWindow()->activateWindow();
|
|
|
|
if (_wasMoved) {
|
|
QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle();
|
|
mainWindow->setScreen(_previousScreen);
|
|
mainWindow->setGeometry(_previousRect);
|
|
|
|
const int SLIGHT_DELAY = 1500;
|
|
QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode()));
|
|
}
|
|
_wasMoved = false;
|
|
_inHDMMode = false;
|
|
}
|
|
}
|
|
|
|
void HMDToolsDialog::moveWindowAfterLeaveMode() {
|
|
QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle();
|
|
mainWindow->setScreen(_previousScreen);
|
|
mainWindow->setGeometry(_previousRect);
|
|
Application::getInstance()->getWindow()->activateWindow();
|
|
Application::getInstance()->resetSensors();
|
|
}
|
|
|
|
|
|
void HMDToolsDialog::reject() {
|
|
// Just regularly close upon ESC
|
|
close();
|
|
}
|
|
|
|
void HMDToolsDialog::closeEvent(QCloseEvent* event) {
|
|
// TODO: consider if we want to prevent closing of this window with event->ignore();
|
|
this->QDialog::closeEvent(event);
|
|
emit closed();
|
|
}
|
|
|
|
void HMDToolsDialog::centerCursorOnWidget(QWidget* widget) {
|
|
QWindow* window = widget->windowHandle();
|
|
QScreen* screen = window->screen();
|
|
QPoint windowCenter = window->geometry().center();
|
|
QCursor::setPos(screen, windowCenter);
|
|
}
|
|
|
|
void HMDToolsDialog::showEvent(QShowEvent* event) {
|
|
// center the cursor on the hmd tools dialog
|
|
centerCursorOnWidget(this);
|
|
}
|
|
|
|
void HMDToolsDialog::hideEvent(QHideEvent* event) {
|
|
// center the cursor on the main application window
|
|
centerCursorOnWidget(Application::getInstance()->getWindow());
|
|
}
|
|
|
|
|
|
void HMDToolsDialog::aboutToQuit() {
|
|
if (_inHDMMode) {
|
|
leaveHDMMode();
|
|
}
|
|
}
|
|
|
|
void HMDToolsDialog::screenCountChanged(int newCount) {
|
|
if (!OculusManager::isConnected()) {
|
|
OculusManager::connect();
|
|
}
|
|
int hmdScreenNumber = OculusManager::getHMDScreen();
|
|
|
|
if (_inHDMMode && _hmdScreenNumber != hmdScreenNumber) {
|
|
qDebug() << "HMD Display changed WHILE IN HMD MODE";
|
|
leaveHDMMode();
|
|
|
|
// 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 HDM Mode";
|
|
const int SLIGHT_DELAY = 2000;
|
|
QTimer::singleShot(SLIGHT_DELAY, this, SLOT(enterHDMMode()));
|
|
}
|
|
}
|
|
_debugDetails->setText(getDebugDetails());
|
|
}
|
|
|
|
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 (QApplication::desktop()->screenCount() > 1) {
|
|
|
|
// we want to use a local variable here because we are not necesarily in HMD mode
|
|
int hmdScreenNumber = OculusManager::getHMDScreen();
|
|
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 = Application::getInstance()->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
|
|
int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen();
|
|
QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber];
|
|
betterScreen = desktopPrimaryScreen;
|
|
}
|
|
|
|
if (betterScreen) {
|
|
_window->setScreen(betterScreen);
|
|
_window->setGeometry(_previousRect);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|