Restoring HMD tools dialog, phase 1

This commit is contained in:
Brad Davis 2015-07-30 11:35:55 -07:00
parent 382ef057b0
commit 5878a4661c
11 changed files with 474 additions and 10 deletions

View file

@ -4734,6 +4734,7 @@ void Application::updateDisplayMode() {
oldDisplayPlugin->deactivate(this);
_offscreenContext->makeCurrent();
}
resetSensors();
}
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
}
@ -4877,9 +4878,21 @@ void Application::unsetFullscreen() {
void Application::showDisplayPluginsTools() {
DependencyManager::get<DialogsManager>()->hmdTools(true);
}
QGLWidget* Application::getPrimarySurface() {
return _glWidget;
}
void Application::setActiveDisplayPlugin(const QString& pluginName) {
auto menu = Menu::getInstance();
foreach(DisplayPluginPointer displayPlugin, getDisplayPlugins()) {
QString name = displayPlugin->getName();
QAction* action = menu->getActionForOption(name);
if (pluginName == name) {
action->setChecked(true);
}
}
updateDisplayMode();
}

View file

@ -289,8 +289,9 @@ public:
virtual void setFullscreen(const QScreen* target) override;
virtual void unsetFullscreen() override;
virtual void showDisplayPluginsTools() override;
virtual QGLWidget* Application::getPrimarySurface() override;
virtual QGLWidget* getPrimarySurface() override;
void setActiveDisplayPlugin(const QString& pluginName);
private:
DisplayPlugin * getActiveDisplayPlugin();
const DisplayPlugin * getActiveDisplayPlugin() const;

View file

@ -290,6 +290,15 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView,
0, false, qApp, SLOT(rotationModeChanged()));
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools,
#ifdef Q_OS_MAC
Qt::META | Qt::Key_H,
#else
Qt::CTRL | Qt::Key_H,
#endif
false,
dialogsManager.data(),
SLOT(hmdTools(bool)));
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::TurnWithHead, 0, false);

View file

@ -196,6 +196,7 @@ namespace MenuOption {
const QString FullscreenMirror = "Fullscreen Mirror";
const QString GlowWhenSpeaking = "Glow When Speaking";
const QString HandMouseInput = "Enable Hand Mouse Input";
const QString HMDTools = "HMD Tools";
const QString IncreaseAvatarSize = "Increase Avatar Size";
const QString IndependentMode = "Independent Mode";
const QString InputMenu = "Avatar>Input Devices";

View file

@ -25,6 +25,7 @@
#include "CachesSizeDialog.h"
#include "DiskCacheEditor.h"
#include "DomainConnectionDialog.h"
#include "HMDToolsDialog.h"
#include "LodToolsDialog.h"
#include "LoginDialog.h"
#include "OctreeStatsDialog.h"
@ -57,6 +58,10 @@ void DialogsManager::showUpdateDialog() {
void DialogsManager::octreeStatsDetails() {
if (!_octreeStatsDialog) {
_octreeStatsDialog = new OctreeStatsDialog(qApp->getWindow(), qApp->getOcteeSceneStats());
if (_hmdToolsDialog) {
_hmdToolsDialog->watchWindow(_octreeStatsDialog->windowHandle());
}
connect(_octreeStatsDialog, SIGNAL(closed()), _octreeStatsDialog, SLOT(deleteLater()));
_octreeStatsDialog->show();
}
@ -114,6 +119,10 @@ void DialogsManager::audioStatsDetails() {
_audioStatsDialog = new AudioStatsDialog(qApp->getWindow());
connect(_audioStatsDialog, SIGNAL(closed()), _audioStatsDialog, SLOT(deleteLater()));
if (_hmdToolsDialog) {
_hmdToolsDialog->watchWindow(_audioStatsDialog->windowHandle());
}
_audioStatsDialog->show();
}
_audioStatsDialog->raise();
@ -123,6 +132,11 @@ void DialogsManager::bandwidthDetails() {
if (! _bandwidthDialog) {
_bandwidthDialog = new BandwidthDialog(qApp->getWindow());
connect(_bandwidthDialog, SIGNAL(closed()), _bandwidthDialog, SLOT(deleteLater()));
if (_hmdToolsDialog) {
_hmdToolsDialog->watchWindow(_bandwidthDialog->windowHandle());
}
_bandwidthDialog->show();
}
_bandwidthDialog->raise();
@ -143,6 +157,25 @@ void DialogsManager::toggleToolWindow() {
toolWindow->setVisible(!toolWindow->isVisible());
}
void DialogsManager::hmdTools(bool showTools) {
if (showTools) {
if (!_hmdToolsDialog) {
maybeCreateDialog(_hmdToolsDialog);
connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed()));
}
_hmdToolsDialog->show();
_hmdToolsDialog->raise();
} else {
hmdToolsClosed();
}
qApp->getWindow()->activateWindow();
}
void DialogsManager::hmdToolsClosed() {
Menu::getInstance()->getActionForOption(MenuOption::HMDTools)->setChecked(false);
_hmdToolsDialog->hide();
}
void DialogsManager::showScriptEditor() {
maybeCreateDialog(_scriptEditor);
_scriptEditor->show();

View file

@ -17,6 +17,8 @@
#include <Application.h>
#include <DependencyManager.h>
#include "HMDToolsDialog.h"
class QAction;
class AddressBarDialog;
@ -43,6 +45,7 @@ class DialogsManager : public QObject, public Dependency {
public:
QPointer<AudioStatsDialog> getAudioStatsDialog() const { return _audioStatsDialog; }
QPointer<BandwidthDialog> getBandwidthDialog() const { return _bandwidthDialog; }
QPointer<HMDToolsDialog> getHMDToolsDialog() const { return _hmdToolsDialog; }
QPointer<LodToolsDialog> getLodToolsDialog() const { return _lodToolsDialog; }
QPointer<OctreeStatsDialog> getOctreeStatsDialog() const { return _octreeStatsDialog; }
QPointer<PreferencesDialog> getPreferencesDialog() const { return _preferencesDialog; }
@ -60,6 +63,7 @@ public slots:
void audioStatsDetails();
void bandwidthDetails();
void lodTools();
void hmdTools(bool showTools);
void showScriptEditor();
void showIRCLink();
void changeAvatarAppearance();
@ -70,6 +74,7 @@ public slots:
private slots:
void toggleToolWindow();
void hmdToolsClosed();
private:
DialogsManager() {}
@ -81,6 +86,10 @@ private:
Q_CHECK_PTR(parent);
member = new T(parent);
Q_CHECK_PTR(member);
if (_hmdToolsDialog && member->windowHandle()) {
_hmdToolsDialog->watchWindow(member->windowHandle());
}
}
}
@ -92,6 +101,7 @@ private:
QPointer<CachesSizeDialog> _cachesSizeDialog;
QPointer<DiskCacheEditor> _diskCacheEditor;
QPointer<QMessageBox> _ircInfoBox;
QPointer<HMDToolsDialog> _hmdToolsDialog;
QPointer<LodToolsDialog> _lodToolsDialog;
QPointer<LoginDialog> _loginDialog;
QPointer<OctreeStatsDialog> _octreeStatsDialog;

View file

@ -0,0 +1,317 @@
//
// 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 <display-plugins/DisplayPlugin.h>
#include "MainWindow.h"
#include "Menu.h"
#include "ui/DialogsManager.h"
#include "ui/HMDToolsDialog.h"
#include "DisplayPlugins.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);
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);
// FIXME do we want to support more than one connected HMD? It seems like a pretty corner case
foreach(auto dp, getDisplayPlugins()) {
// The first plugin is always the standard 2D display, by convention
if (_defaultPluginName.isEmpty()) {
_defaultPluginName = dp->getName();
continue;
}
if (dp->isHmd()) {
// Not all HMD's have corresponding screens
if (dp->getHmdScreen() >= 0) {
_hmdScreenNumber = dp->getHmdScreen();
}
_hmdPluginName = dp->getName();
break;
}
}
}
HMDToolsDialog::~HMDToolsDialog() {
foreach(HMDWindowWatcher* watcher, _windowWatchers) {
delete watcher;
}
_windowWatchers.clear();
}
void HMDToolsDialog::applicationWindowScreenChanged(QScreen* screen) {
_debugDetails->setText(getDebugDetails());
}
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";
}
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());
// 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()->setActiveDisplayPlugin(_hmdPluginName);
_inHDMMode = true;
}
}
void HMDToolsDialog::leaveHDMMode() {
if (_inHDMMode) {
_switchModeButton->setText("Enter HMD Mode");
_debugDetails->setText(getDebugDetails());
Application::getInstance()->setActiveDisplayPlugin(_defaultPluginName);
Application::getInstance()->getWindow()->activateWindow();
_inHDMMode = false;
}
}
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) {
// FIXME this is ineffective because it doesn't trigger the menu to
// save the fact that VR Mode is not checked.
leaveHDMMode();
}
}
void HMDToolsDialog::screenCountChanged(int newCount) {
int hmdScreenNumber = -1;
foreach(auto dp, getDisplayPlugins()) {
if (dp->isHmd()) {
if (dp->getHmdScreen() >= 0) {
hmdScreenNumber = dp->getHmdScreen();
}
break;
}
}
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) {
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 = 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);
}
}
}
}
}

View file

@ -0,0 +1,87 @@
//
// HMDToolsDialog.h
// 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
//
#ifndef hifi_HMDToolsDialog_h
#define hifi_HMDToolsDialog_h
#include <QDialog>
class HMDWindowWatcher;
class HMDToolsDialog : public QDialog {
Q_OBJECT
public:
// Sets up the UI
HMDToolsDialog(QWidget* parent);
~HMDToolsDialog();
QString getDebugDetails() const;
QScreen* getHMDScreen() const { return _hmdScreen; }
QScreen* getLastApplicationScreen() const { return _previousScreen; }
bool hasHMDScreen() const { return _hmdScreenNumber >= -1; }
void watchWindow(QWindow* window);
signals:
void closed();
public slots:
void reject();
void switchModeClicked(bool checked);
void applicationWindowScreenChanged(QScreen* screen);
void aboutToQuit();
void screenCountChanged(int newCount);
protected:
virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed.
virtual void showEvent(QShowEvent* event);
virtual void hideEvent(QHideEvent* event);
private:
void centerCursorOnWidget(QWidget* widget);
void enterHDMMode();
void leaveHDMMode();
QScreen* _previousScreen;
QScreen* _hmdScreen;
int _hmdScreenNumber;
QPushButton* _switchModeButton;
QLabel* _debugDetails;
QRect _previousDialogRect;
QScreen* _previousDialogScreen;
bool _inHDMMode;
QString _hmdPluginName;
QString _defaultPluginName;
QHash<QWindow*, HMDWindowWatcher*> _windowWatchers;
friend class HMDWindowWatcher;
};
class HMDWindowWatcher : public QObject {
Q_OBJECT
public:
// Sets up the UI
HMDWindowWatcher(QWindow* window, HMDToolsDialog* hmdTools);
~HMDWindowWatcher();
public slots:
void windowScreenChanged(QScreen* screen);
void windowGeometryChanged(int arg);
private:
QWindow* _window;
HMDToolsDialog* _hmdTools;
QRect _previousRect;
QScreen* _previousScreen;
};
#endif // hifi_HMDToolsDialog_h

View file

@ -126,7 +126,6 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) {
return imageTempFile;
}
return nullptr;
}

View file

@ -50,6 +50,7 @@ class DisplayPlugin : public Plugin {
Q_OBJECT
public:
virtual bool isHmd() const { return false; }
virtual int getHmdScreen() const { return -1; }
/// By default, all HMDs are stereo
virtual bool isStereo() const { return isHmd(); }
virtual bool isThrottled() const { return false; }

View file

@ -13,13 +13,6 @@
#include <QTimer>
class OffscreenGlCanvas;
struct SwapFramebufferWrapper;
struct MirrorFramebufferWrapper;
using SwapFboPtr = QSharedPointer<SwapFramebufferWrapper>;
using MirrorFboPtr = QSharedPointer<MirrorFramebufferWrapper>;
class Oculus_0_5_DisplayPlugin : public OculusBaseDisplayPlugin {
public:
virtual bool isSupported() const override;