diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt
index 96db4ebcca..48fd1cfa06 100644
--- a/Source/Core/DolphinQt/CMakeLists.txt
+++ b/Source/Core/DolphinQt/CMakeLists.txt
@@ -14,7 +14,7 @@ set(SRCS
SystemInfo.cpp
Utils/Resources.cpp
Utils/Utils.cpp
- VideoInterface/VideoInterface.cpp
+ VideoInterface/RenderWidget.cpp
)
set(UIS
diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj
index 08b4484179..bc5482a1b4 100644
--- a/Source/Core/DolphinQt/DolphinQt.vcxproj
+++ b/Source/Core/DolphinQt/DolphinQt.vcxproj
@@ -48,6 +48,9 @@
$(ExternalsDir)OpenAL\$(PlatformName);%(AdditionalLibraryDirectories)
iphlpapi.lib;winmm.lib;setupapi.lib;vfw32.lib;opengl32.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)
+
+ $(ProjectDir)\VideoInterface;%(AdditionalIncludeDirectories)
+
@@ -62,16 +65,18 @@
+
-
+
+
-
+
@@ -152,6 +157,7 @@
+
diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj.filters b/Source/Core/DolphinQt/DolphinQt.vcxproj.filters
index e81be15e09..e415c300a5 100644
--- a/Source/Core/DolphinQt/DolphinQt.vcxproj.filters
+++ b/Source/Core/DolphinQt/DolphinQt.vcxproj.filters
@@ -5,9 +5,6 @@
-
- VideoInterface
-
Utils
@@ -15,11 +12,27 @@
Utils
+
+ VideoInterface
+
+
+ Generated Files
+
+
+ Generated Files
+
+
+ Generated Files
+
+
+ Generated Files
+
+
@@ -34,6 +47,9 @@
{730f2ae7-a686-4bc8-bb49-b4f8bd240329}
+
+ {c18a1fb3-64ff-4249-b808-d73a56ea3a2d}
+
@@ -42,5 +58,8 @@
Utils
+
+ VideoInterface
+
\ No newline at end of file
diff --git a/Source/Core/DolphinQt/Host.cpp b/Source/Core/DolphinQt/Host.cpp
index ced35df0ab..af10de63c9 100644
--- a/Source/Core/DolphinQt/Host.cpp
+++ b/Source/Core/DolphinQt/Host.cpp
@@ -5,9 +5,14 @@
#include
#include
+#include
+#include
+
#include "Common/MsgHandler.h"
#include "Core/Host.h"
+#include "DolphinQt/MainWindow.h"
+
void Host_SysMessage(const char *fmt, ...)
{
va_list list;
@@ -27,9 +32,48 @@ void Host_Message(int id)
// TODO
}
+void Host_UpdateMainFrame()
+{
+ // TODO
+}
+
+void Host_UpdateTitle(const std::string& title)
+{
+ // TODO
+}
+
void* Host_GetRenderHandle()
{
- return nullptr;
+ return (void*)(g_main_window->GetRenderWidget()->winId());
+}
+
+void Host_GetRenderWindowSize(int& x, int& y, int& w, int& h)
+{
+ // TODO: Make it more clear what this is supposed to return.. i.e. WX always sets x=y=0
+ g_main_window->RenderWidgetSize(x, y, w, h);
+ x = 0;
+ y = 0;
+}
+
+void Host_RequestRenderWindowSize(int w, int h)
+{
+ DRenderWidget* render_widget = g_main_window->GetRenderWidget();
+ qApp->postEvent(render_widget, new QResizeEvent(QSize(w, h), render_widget->size()));
+}
+
+bool Host_RendererHasFocus()
+{
+ return g_main_window->RenderWidgetHasFocus();
+}
+
+bool Host_UIHasFocus()
+{
+ return g_main_window->isActiveWindow();
+}
+
+void Host_RequestFullscreen(bool enable)
+{
+ // TODO
}
void Host_NotifyMapLoaded()
@@ -42,31 +86,6 @@ void Host_UpdateDisasmDialog()
// TODO
}
-void Host_UpdateMainFrame()
-{
- // TODO
-}
-
-void Host_UpdateTitle(const std::string& title)
-{
- // TODO
-}
-
-void Host_GetRenderWindowSize(int& x, int& y, int& width, int& height)
-{
- // TODO
-}
-
-void Host_RequestRenderWindowSize(int width, int height)
-{
- // TODO
-}
-
-void Host_RequestFullscreen(bool enable_fullscreen)
-{
- // TODO
-}
-
void Host_SetStartupDebuggingParameters()
{
// TODO
@@ -77,18 +96,6 @@ void Host_SetWiiMoteConnectionState(int state)
// TODO
}
-bool Host_UIHasFocus()
-{
- // TODO
- return false;
-}
-
-bool Host_RendererHasFocus()
-{
- // TODO
- return false;
-}
-
void Host_ConnectWiimote(int wm_idx, bool connect)
{
// TODO
diff --git a/Source/Core/DolphinQt/Main.cpp b/Source/Core/DolphinQt/Main.cpp
index 93d853ad62..29279e812e 100644
--- a/Source/Core/DolphinQt/Main.cpp
+++ b/Source/Core/DolphinQt/Main.cpp
@@ -54,10 +54,11 @@ int main(int argc, char* argv[])
return 1;
}
- DMainWindow w;
- w.show();
+ g_main_window = new DMainWindow();
+ g_main_window->show();
int retcode = app.exec();
+ delete g_main_window;
UICommon::Shutdown();
return retcode;
}
diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp
index 62382e10c5..0a1d7fa469 100644
--- a/Source/Core/DolphinQt/MainWindow.cpp
+++ b/Source/Core/DolphinQt/MainWindow.cpp
@@ -3,36 +3,247 @@
// Refer to the license.txt file included.
#include
+#include
+#include
#include
#include "ui_MainWindow.h"
#include "Common/StdMakeUnique.h"
+#include "Core/BootManager.h"
+#include "Core/ConfigManager.h"
+
#include "DolphinQt/AboutDialog.h"
#include "DolphinQt/MainWindow.h"
#include "DolphinQt/SystemInfo.h"
#include "DolphinQt/Utils/Resources.h"
#include "DolphinQt/Utils/Utils.h"
+// The "g_main_window" object as defined in MainWindow.h
+DMainWindow* g_main_window = nullptr;
+
DMainWindow::DMainWindow(QWidget* parent_widget)
: QMainWindow(parent_widget)
{
m_ui = std::make_unique();
m_ui->setupUi(this);
-
- Resources::Init();
- m_ui->actOpen->setIcon(Resources::GetIcon(Resources::TOOLBAR_OPEN));
-
#ifdef Q_OS_MACX
m_ui->toolbar->setMovable(false);
#endif
+
+ Resources::Init();
+
+ UpdateIcons();
+ setWindowIcon(Resources::GetIcon(Resources::DOLPHIN_LOGO));
+
+ connect(this, SIGNAL(CoreStateChanged(Core::EState)), this, SLOT(OnCoreStateChanged(Core::EState)));
+ emit CoreStateChanged(Core::CORE_UNINITIALIZED); // update GUI items
}
DMainWindow::~DMainWindow()
{
}
+// Emulation
+
+void DMainWindow::StartGame(const QString filename)
+{
+ m_render_widget = std::make_unique();
+ m_render_widget->setWindowTitle(tr("Dolphin")); // TODO
+ m_render_widget->setWindowIcon(windowIcon());
+
+ // TODO: When rendering to main, this won't resize the parent window..
+ if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
+ {
+ connect(m_render_widget.get(), SIGNAL(Closed()), this, SLOT(on_actStop_triggered()));
+ m_render_widget->move(SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowXPos,
+ SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowYPos);
+ m_render_widget->resize(SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowWidth, // TODO: Make sure these are client sizes!
+ SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowHeight);
+ m_render_widget->show();
+ }
+ else
+ {
+ m_ui->centralWidget->addWidget(m_render_widget.get());
+ m_ui->centralWidget->setCurrentWidget(m_render_widget.get());
+ }
+
+ if (!BootManager::BootCore(filename.toStdString()))
+ {
+ QMessageBox::critical(this, tr("Fatal error"), tr("Failed to init Core"), QMessageBox::Ok);
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
+ m_ui->centralWidget->removeWidget(m_render_widget.get());
+ else
+ m_render_widget->close();
+ m_render_widget.reset();
+ }
+ else
+ {
+ // TODO: Disable screensaver!
+
+ // TODO: Fullscreen
+ //DoFullscreen(SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen);
+
+ m_render_widget->focusWidget();
+ emit CoreStateChanged(Core::CORE_RUN);
+ }
+}
+
+QString DMainWindow::RequestBootFilename()
+{
+ // If a game is already selected, just return the filename
+ // ... TODO
+
+ return ShowFileDialog();
+}
+
+QString DMainWindow::ShowFileDialog()
+{
+ return QFileDialog::getOpenFileName(this, tr("Open File"), QString(),
+ tr("All supported ROMs (%1);;All files (*)")
+ .arg(SL("*.gcm *.iso *.ciso *.gcz *.wbfs *.elf *.dol *.dff *.tmd *.wad")));
+}
+
+void DMainWindow::DoStartPause()
+{
+ if (Core::GetState() == Core::CORE_RUN)
+ {
+ Core::SetState(Core::CORE_PAUSE);
+ emit CoreStateChanged(Core::CORE_PAUSE);
+ }
+ else
+ {
+ Core::SetState(Core::CORE_RUN);
+ emit CoreStateChanged(Core::CORE_RUN);
+ }
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)
+ m_render_widget->setCursor(Qt::BlankCursor);
+}
+
+void DMainWindow::on_actOpen_triggered()
+{
+ StartGame(ShowFileDialog());
+}
+
+void DMainWindow::on_actPlay_triggered()
+{
+ if (Core::GetState() != Core::CORE_UNINITIALIZED)
+ {
+ DoStartPause();
+ }
+ else
+ {
+ // initialize Core and boot the game
+ QString filename = RequestBootFilename();
+ if (!filename.isNull())
+ StartGame(filename);
+ }
+}
+
+void DMainWindow::on_actStop_triggered()
+{
+ if (Core::GetState() != Core::CORE_UNINITIALIZED && !m_isStopping)
+ {
+ m_isStopping = true;
+ // Ask for confirmation in case the user accidentally clicked Stop / Escape
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bConfirmStop)
+ {
+ int ret = QMessageBox::question(m_render_widget.get(), tr("Please confirm..."),
+ tr("Do you want to stop the current emulation?"),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+
+ if (ret == QMessageBox::No)
+ return;
+ }
+
+ // TODO: Movie stuff
+ // TODO: Show the author/description dialog here
+
+ // TODO: Show busy cursor
+ BootManager::Stop();
+ // TODO: Hide busy cursor again
+
+ // TODO: Allow screensaver again
+ // TODO: Restore original window title
+
+ // TODO: Return from fullscreen if necessary (DoFullscreen in the wx code)
+
+ // TODO:
+ // If batch mode was specified on the command-line, exit now.
+ //if (m_bBatchMode)
+ // Close(true);
+
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
+ m_ui->centralWidget->removeWidget(m_render_widget.get());
+ else
+ m_render_widget->close();
+ m_render_widget.reset();
+
+ emit CoreStateChanged(Core::CORE_UNINITIALIZED);
+ }
+ m_isStopping = false;
+}
+
+void DMainWindow::OnCoreStateChanged(Core::EState state)
+{
+ bool is_not_initialized = (state == Core::CORE_UNINITIALIZED);
+ bool is_running = (state == Core::CORE_RUN);
+ bool is_paused = (state == Core::CORE_PAUSE);
+
+ // Update the toolbar
+ m_ui->actPlay->setEnabled(is_not_initialized || is_running || is_paused);
+ if (is_running)
+ {
+ m_ui->actPlay->setIcon(Resources::GetIcon(Resources::TOOLBAR_PAUSE));
+ m_ui->actPlay->setText(tr("Pause"));
+ }
+ else if (is_paused || is_not_initialized)
+ {
+ m_ui->actPlay->setIcon(Resources::GetIcon(Resources::TOOLBAR_PLAY));
+ m_ui->actPlay->setText(tr("Play"));
+ }
+
+ m_ui->actStop->setEnabled(!is_not_initialized);
+ m_ui->actOpen->setEnabled(is_not_initialized);
+}
+
+// DRenderWidget
+void DMainWindow::RenderWidgetSize(int& x_pos, int& y_pos, int& w, int& h)
+{
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
+ {
+ x_pos = x();
+ y_pos = y();
+ }
+ else
+ {
+ x_pos = m_render_widget->x();
+ y_pos = m_render_widget->y();
+ }
+ w = m_render_widget->width();
+ h = m_render_widget->height();
+}
+
+bool DMainWindow::RenderWidgetHasFocus()
+{
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
+ return isActiveWindow();
+ else if (m_render_widget != nullptr)
+ return m_render_widget->isActiveWindow();
+ else
+ return false;
+}
+
+// Update all the icons used in DMainWindow with fresh ones from
+// "Resources". Call this function after changing the icon theme.
+void DMainWindow::UpdateIcons()
+{
+ m_ui->actOpen->setIcon(Resources::GetIcon(Resources::TOOLBAR_OPEN));
+ m_ui->actStop->setIcon(Resources::GetIcon(Resources::TOOLBAR_STOP));
+}
+
+// Help menu
void DMainWindow::on_actWebsite_triggered()
{
QDesktopServices::openUrl(QUrl(SL("https://dolphin-emu.org/")));
diff --git a/Source/Core/DolphinQt/MainWindow.h b/Source/Core/DolphinQt/MainWindow.h
index a1ffa1c6ed..d01279ae6f 100644
--- a/Source/Core/DolphinQt/MainWindow.h
+++ b/Source/Core/DolphinQt/MainWindow.h
@@ -7,6 +7,10 @@
#include
#include
+#include "Core/Core.h"
+
+#include "DolphinQt/VideoInterface/RenderWidget.h"
+
// Predefinitions
namespace Ui
{
@@ -21,7 +25,23 @@ public:
explicit DMainWindow(QWidget* parent_widget = nullptr);
~DMainWindow();
+ // DRenderWidget
+ void RenderWidgetSize(int& x_pos, int& y_pos, int& w, int& h);
+ bool RenderWidgetHasFocus();
+ DRenderWidget* GetRenderWidget() { return m_render_widget.get(); }
+
+signals:
+ void CoreStateChanged(Core::EState state);
+
private slots:
+ // Emulation
+ void StartGame(const QString filename);
+ void OnCoreStateChanged(Core::EState state);
+
+ // Main toolbar
+ void on_actOpen_triggered();
+ void on_actPlay_triggered();
+ void on_actStop_triggered();
// Help menu
void on_actWebsite_triggered();
@@ -30,6 +50,20 @@ private slots:
void on_actSystemInfo_triggered();
void on_actAbout_triggered();
+ // Misc.
+ void UpdateIcons();
+
private:
std::unique_ptr m_ui;
+
+ // Emulation
+ QString RequestBootFilename();
+ QString ShowFileDialog();
+ void DoStartPause();
+
+ std::unique_ptr m_render_widget;
+ bool m_isStopping = false;
};
+
+// Pointer to the only instance of DMainWindow, used by Host_*
+extern DMainWindow* g_main_window;
diff --git a/Source/Core/DolphinQt/MainWindow.ui b/Source/Core/DolphinQt/MainWindow.ui
index c63d5610c0..884dad3714 100644
--- a/Source/Core/DolphinQt/MainWindow.ui
+++ b/Source/Core/DolphinQt/MainWindow.ui
@@ -25,14 +25,14 @@
true
-
+
diff --git a/Source/Core/DolphinQt/VideoInterface/RenderWidget.cpp b/Source/Core/DolphinQt/VideoInterface/RenderWidget.cpp
new file mode 100644
index 0000000000..4fbcd3cd29
--- /dev/null
+++ b/Source/Core/DolphinQt/VideoInterface/RenderWidget.cpp
@@ -0,0 +1,24 @@
+// Copyright 2014 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include
+
+#include "DolphinQt/VideoInterface/RenderWidget.h"
+
+DRenderWidget::DRenderWidget(QWidget* parent_widget)
+ : QWidget(parent_widget)
+{
+ setAttribute(Qt::WA_NativeWindow, true);
+ setAttribute(Qt::WA_OpaquePaintEvent, true);
+ setAttribute(Qt::WA_NoSystemBackground, true);
+}
+
+void DRenderWidget::closeEvent(QCloseEvent* e)
+{
+ // TODO: update render window positions in config
+
+ // TODO: Do this differently...
+ emit Closed();
+ QWidget::closeEvent(e);
+}
diff --git a/Source/Core/DolphinQt/VideoInterface/RenderWidget.h b/Source/Core/DolphinQt/VideoInterface/RenderWidget.h
new file mode 100644
index 0000000000..81ad82374e
--- /dev/null
+++ b/Source/Core/DolphinQt/VideoInterface/RenderWidget.h
@@ -0,0 +1,28 @@
+// Copyright 2014 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+
+class DRenderWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DRenderWidget(QWidget* parent_widget = nullptr);
+
+protected:
+ // Some window managers start window dragging if an "empty" window area was clicked.
+ // Prevent this by intercepting the mouse press event.
+ void mousePressEvent(QMouseEvent*) override {}
+ void paintEvent(QPaintEvent*) override {}
+
+private slots:
+ void closeEvent(QCloseEvent* e) override;
+
+signals:
+ void Closed();
+};
+
diff --git a/Source/Core/DolphinQt/VideoInterface/VideoInterface.cpp b/Source/Core/DolphinQt/VideoInterface/VideoInterface.cpp
deleted file mode 100644
index 4424175f16..0000000000
--- a/Source/Core/DolphinQt/VideoInterface/VideoInterface.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2014 Dolphin Emulator Project
-// Licensed under GPLv2
-// Refer to the license.txt file included.
-
-#include "VideoBackends/OGL/GLInterfaceBase.h"
-
-cInterfaceBase* HostGL_CreateGLInterface()
-{
- // TODO
- return nullptr;
-}