diff options
Diffstat (limited to '')
| -rw-r--r-- | src/citra_qt/bootmanager.cpp | 134 |
1 files changed, 66 insertions, 68 deletions
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 6dddde9ba..01cc6b9ca 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp | |||
| @@ -22,13 +22,13 @@ | |||
| 22 | #include "video_core/debug_utils/debug_utils.h" | 22 | #include "video_core/debug_utils/debug_utils.h" |
| 23 | #include "video_core/video_core.h" | 23 | #include "video_core/video_core.h" |
| 24 | 24 | ||
| 25 | #define APP_NAME "citra" | 25 | #define APP_NAME "citra" |
| 26 | #define APP_VERSION "0.1-" VERSION | 26 | #define APP_VERSION "0.1-" VERSION |
| 27 | #define APP_TITLE APP_NAME " " APP_VERSION | 27 | #define APP_TITLE APP_NAME " " APP_VERSION |
| 28 | #define COPYRIGHT "Copyright (C) 2013-2014 Citra Team" | 28 | #define COPYRIGHT "Copyright (C) 2013-2014 Citra Team" |
| 29 | 29 | ||
| 30 | EmuThread::EmuThread(GRenderWindow* render_window) : | 30 | EmuThread::EmuThread(GRenderWindow* render_window) |
| 31 | exec_step(false), running(false), stop_run(false), render_window(render_window) { | 31 | : exec_step(false), running(false), stop_run(false), render_window(render_window) { |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | void EmuThread::run() { | 34 | void EmuThread::run() { |
| @@ -64,7 +64,7 @@ void EmuThread::run() { | |||
| 64 | was_active = false; | 64 | was_active = false; |
| 65 | } else { | 65 | } else { |
| 66 | std::unique_lock<std::mutex> lock(running_mutex); | 66 | std::unique_lock<std::mutex> lock(running_mutex); |
| 67 | running_cv.wait(lock, [this]{ return IsRunning() || exec_step || stop_run; }); | 67 | running_cv.wait(lock, [this] { return IsRunning() || exec_step || stop_run; }); |
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| 70 | 70 | ||
| @@ -78,13 +78,13 @@ void EmuThread::run() { | |||
| 78 | render_window->moveContext(); | 78 | render_window->moveContext(); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | // This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL context. | 81 | // This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL |
| 82 | // context. | ||
| 82 | // The corresponding functionality is handled in EmuThread instead | 83 | // The corresponding functionality is handled in EmuThread instead |
| 83 | class GGLWidgetInternal : public QGLWidget | 84 | class GGLWidgetInternal : public QGLWidget { |
| 84 | { | ||
| 85 | public: | 85 | public: |
| 86 | GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) | 86 | GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) |
| 87 | : QGLWidget(fmt, parent), parent(parent) { | 87 | : QGLWidget(fmt, parent), parent(parent) { |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | void paintEvent(QPaintEvent* ev) override { | 90 | void paintEvent(QPaintEvent* ev) override { |
| @@ -98,37 +98,43 @@ public: | |||
| 98 | parent->OnFramebufferSizeChanged(); | 98 | parent->OnFramebufferSizeChanged(); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void DisablePainting() { do_painting = false; } | 101 | void DisablePainting() { |
| 102 | void EnablePainting() { do_painting = true; } | 102 | do_painting = false; |
| 103 | } | ||
| 104 | void EnablePainting() { | ||
| 105 | do_painting = true; | ||
| 106 | } | ||
| 103 | 107 | ||
| 104 | private: | 108 | private: |
| 105 | GRenderWindow* parent; | 109 | GRenderWindow* parent; |
| 106 | bool do_painting; | 110 | bool do_painting; |
| 107 | }; | 111 | }; |
| 108 | 112 | ||
| 109 | GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) : | 113 | GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) |
| 110 | QWidget(parent), keyboard_id(0), emu_thread(emu_thread), child(nullptr) { | 114 | : QWidget(parent), keyboard_id(0), emu_thread(emu_thread), child(nullptr) { |
| 111 | 115 | ||
| 112 | std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | 116 | std::string window_title = |
| 117 | Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); | ||
| 113 | setWindowTitle(QString::fromStdString(window_title)); | 118 | setWindowTitle(QString::fromStdString(window_title)); |
| 114 | 119 | ||
| 115 | keyboard_id = KeyMap::NewDeviceId(); | 120 | keyboard_id = KeyMap::NewDeviceId(); |
| 116 | ReloadSetKeymaps(); | 121 | ReloadSetKeymaps(); |
| 117 | } | 122 | } |
| 118 | 123 | ||
| 119 | void GRenderWindow::moveContext() | 124 | void GRenderWindow::moveContext() { |
| 120 | { | ||
| 121 | DoneCurrent(); | 125 | DoneCurrent(); |
| 122 | // We need to move GL context to the swapping thread in Qt5 | 126 | // We need to move GL context to the swapping thread in Qt5 |
| 123 | #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) | 127 | #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) |
| 124 | // If the thread started running, move the GL Context to the new thread. Otherwise, move it back. | 128 | // If the thread started running, move the GL Context to the new thread. Otherwise, move it |
| 125 | auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) ? emu_thread : qApp->thread(); | 129 | // back. |
| 130 | auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) | ||
| 131 | ? emu_thread | ||
| 132 | : qApp->thread(); | ||
| 126 | child->context()->moveToThread(thread); | 133 | child->context()->moveToThread(thread); |
| 127 | #endif | 134 | #endif |
| 128 | } | 135 | } |
| 129 | 136 | ||
| 130 | void GRenderWindow::SwapBuffers() | 137 | void GRenderWindow::SwapBuffers() { |
| 131 | { | ||
| 132 | #if !defined(QT_NO_DEBUG) | 138 | #if !defined(QT_NO_DEBUG) |
| 133 | // Qt debug runtime prints a bogus warning on the console if you haven't called makeCurrent | 139 | // Qt debug runtime prints a bogus warning on the console if you haven't called makeCurrent |
| 134 | // since the last time you called swapBuffers. This presumably means something if you're using | 140 | // since the last time you called swapBuffers. This presumably means something if you're using |
| @@ -139,13 +145,11 @@ void GRenderWindow::SwapBuffers() | |||
| 139 | child->swapBuffers(); | 145 | child->swapBuffers(); |
| 140 | } | 146 | } |
| 141 | 147 | ||
| 142 | void GRenderWindow::MakeCurrent() | 148 | void GRenderWindow::MakeCurrent() { |
| 143 | { | ||
| 144 | child->makeCurrent(); | 149 | child->makeCurrent(); |
| 145 | } | 150 | } |
| 146 | 151 | ||
| 147 | void GRenderWindow::DoneCurrent() | 152 | void GRenderWindow::DoneCurrent() { |
| 148 | { | ||
| 149 | child->doneCurrent(); | 153 | child->doneCurrent(); |
| 150 | } | 154 | } |
| 151 | 155 | ||
| @@ -157,36 +161,33 @@ void GRenderWindow::PollEvents() { | |||
| 157 | // Older versions get the window size (density independent pixels), | 161 | // Older versions get the window size (density independent pixels), |
| 158 | // and hence, do not support DPI scaling ("retina" displays). | 162 | // and hence, do not support DPI scaling ("retina" displays). |
| 159 | // The result will be a viewport that is smaller than the extent of the window. | 163 | // The result will be a viewport that is smaller than the extent of the window. |
| 160 | void GRenderWindow::OnFramebufferSizeChanged() | 164 | void GRenderWindow::OnFramebufferSizeChanged() { |
| 161 | { | 165 | // Screen changes potentially incur a change in screen DPI, hence we should update the |
| 162 | // Screen changes potentially incur a change in screen DPI, hence we should update the framebuffer size | 166 | // framebuffer size |
| 163 | qreal pixelRatio = windowPixelRatio(); | 167 | qreal pixelRatio = windowPixelRatio(); |
| 164 | unsigned width = child->QPaintDevice::width() * pixelRatio; | 168 | unsigned width = child->QPaintDevice::width() * pixelRatio; |
| 165 | unsigned height = child->QPaintDevice::height() * pixelRatio; | 169 | unsigned height = child->QPaintDevice::height() * pixelRatio; |
| 166 | 170 | ||
| 167 | NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); | 171 | NotifyFramebufferLayoutChanged( |
| 172 | EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height)); | ||
| 168 | } | 173 | } |
| 169 | 174 | ||
| 170 | void GRenderWindow::BackupGeometry() | 175 | void GRenderWindow::BackupGeometry() { |
| 171 | { | ||
| 172 | geometry = ((QGLWidget*)this)->saveGeometry(); | 176 | geometry = ((QGLWidget*)this)->saveGeometry(); |
| 173 | } | 177 | } |
| 174 | 178 | ||
| 175 | void GRenderWindow::RestoreGeometry() | 179 | void GRenderWindow::RestoreGeometry() { |
| 176 | { | ||
| 177 | // We don't want to back up the geometry here (obviously) | 180 | // We don't want to back up the geometry here (obviously) |
| 178 | QWidget::restoreGeometry(geometry); | 181 | QWidget::restoreGeometry(geometry); |
| 179 | } | 182 | } |
| 180 | 183 | ||
| 181 | void GRenderWindow::restoreGeometry(const QByteArray& geometry) | 184 | void GRenderWindow::restoreGeometry(const QByteArray& geometry) { |
| 182 | { | ||
| 183 | // Make sure users of this class don't need to deal with backing up the geometry themselves | 185 | // Make sure users of this class don't need to deal with backing up the geometry themselves |
| 184 | QWidget::restoreGeometry(geometry); | 186 | QWidget::restoreGeometry(geometry); |
| 185 | BackupGeometry(); | 187 | BackupGeometry(); |
| 186 | } | 188 | } |
| 187 | 189 | ||
| 188 | QByteArray GRenderWindow::saveGeometry() | 190 | QByteArray GRenderWindow::saveGeometry() { |
| 189 | { | ||
| 190 | // If we are a top-level widget, store the current geometry | 191 | // If we are a top-level widget, store the current geometry |
| 191 | // otherwise, store the last backup | 192 | // otherwise, store the last backup |
| 192 | if (parent() == nullptr) | 193 | if (parent() == nullptr) |
| @@ -195,8 +196,7 @@ QByteArray GRenderWindow::saveGeometry() | |||
| 195 | return geometry; | 196 | return geometry; |
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | qreal GRenderWindow::windowPixelRatio() | 199 | qreal GRenderWindow::windowPixelRatio() { |
| 199 | { | ||
| 200 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | 200 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) |
| 201 | // windowHandle() might not be accessible until the window is displayed to screen. | 201 | // windowHandle() might not be accessible until the window is displayed to screen. |
| 202 | return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f; | 202 | return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f; |
| @@ -210,20 +210,16 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { | |||
| 210 | QWidget::closeEvent(event); | 210 | QWidget::closeEvent(event); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | void GRenderWindow::keyPressEvent(QKeyEvent* event) | 213 | void GRenderWindow::keyPressEvent(QKeyEvent* event) { |
| 214 | { | 214 | KeyMap::PressKey(*this, {event->key(), keyboard_id}); |
| 215 | KeyMap::PressKey(*this, { event->key(), keyboard_id }); | ||
| 216 | } | 215 | } |
| 217 | 216 | ||
| 218 | void GRenderWindow::keyReleaseEvent(QKeyEvent* event) | 217 | void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { |
| 219 | { | 218 | KeyMap::ReleaseKey(*this, {event->key(), keyboard_id}); |
| 220 | KeyMap::ReleaseKey(*this, { event->key(), keyboard_id }); | ||
| 221 | } | 219 | } |
| 222 | 220 | ||
| 223 | void GRenderWindow::mousePressEvent(QMouseEvent *event) | 221 | void GRenderWindow::mousePressEvent(QMouseEvent* event) { |
| 224 | { | 222 | if (event->button() == Qt::LeftButton) { |
| 225 | if (event->button() == Qt::LeftButton) | ||
| 226 | { | ||
| 227 | auto pos = event->pos(); | 223 | auto pos = event->pos(); |
| 228 | qreal pixelRatio = windowPixelRatio(); | 224 | qreal pixelRatio = windowPixelRatio(); |
| 229 | this->TouchPressed(static_cast<unsigned>(pos.x() * pixelRatio), | 225 | this->TouchPressed(static_cast<unsigned>(pos.x() * pixelRatio), |
| @@ -231,30 +227,28 @@ void GRenderWindow::mousePressEvent(QMouseEvent *event) | |||
| 231 | } | 227 | } |
| 232 | } | 228 | } |
| 233 | 229 | ||
| 234 | void GRenderWindow::mouseMoveEvent(QMouseEvent *event) | 230 | void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { |
| 235 | { | ||
| 236 | auto pos = event->pos(); | 231 | auto pos = event->pos(); |
| 237 | qreal pixelRatio = windowPixelRatio(); | 232 | qreal pixelRatio = windowPixelRatio(); |
| 238 | this->TouchMoved(std::max(static_cast<unsigned>(pos.x() * pixelRatio), 0u), | 233 | this->TouchMoved(std::max(static_cast<unsigned>(pos.x() * pixelRatio), 0u), |
| 239 | std::max(static_cast<unsigned>(pos.y() * pixelRatio), 0u)); | 234 | std::max(static_cast<unsigned>(pos.y() * pixelRatio), 0u)); |
| 240 | } | 235 | } |
| 241 | 236 | ||
| 242 | void GRenderWindow::mouseReleaseEvent(QMouseEvent *event) | 237 | void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { |
| 243 | { | ||
| 244 | if (event->button() == Qt::LeftButton) | 238 | if (event->button() == Qt::LeftButton) |
| 245 | this->TouchReleased(); | 239 | this->TouchReleased(); |
| 246 | } | 240 | } |
| 247 | 241 | ||
| 248 | void GRenderWindow::ReloadSetKeymaps() | 242 | void GRenderWindow::ReloadSetKeymaps() { |
| 249 | { | ||
| 250 | KeyMap::ClearKeyMapping(keyboard_id); | 243 | KeyMap::ClearKeyMapping(keyboard_id); |
| 251 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | 244 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { |
| 252 | KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, KeyMap::mapping_targets[i]); | 245 | KeyMap::SetKeyMapping( |
| 246 | {Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, | ||
| 247 | KeyMap::mapping_targets[i]); | ||
| 253 | } | 248 | } |
| 254 | } | 249 | } |
| 255 | 250 | ||
| 256 | void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) | 251 | void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) { |
| 257 | { | ||
| 258 | NotifyClientAreaSizeChanged(std::make_pair(width, height)); | 252 | NotifyClientAreaSizeChanged(std::make_pair(width, height)); |
| 259 | } | 253 | } |
| 260 | 254 | ||
| @@ -267,7 +261,8 @@ void GRenderWindow::InitRenderTarget() { | |||
| 267 | delete layout(); | 261 | delete layout(); |
| 268 | } | 262 | } |
| 269 | 263 | ||
| 270 | // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose | 264 | // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, |
| 265 | // WA_DontShowOnScreen, WA_DeleteOnClose | ||
| 271 | QGLFormat fmt; | 266 | QGLFormat fmt; |
| 272 | fmt.setVersion(3, 3); | 267 | fmt.setVersion(3, 3); |
| 273 | fmt.setProfile(QGLFormat::CoreProfile); | 268 | fmt.setProfile(QGLFormat::CoreProfile); |
| @@ -279,7 +274,8 @@ void GRenderWindow::InitRenderTarget() { | |||
| 279 | child = new GGLWidgetInternal(fmt, this); | 274 | child = new GGLWidgetInternal(fmt, this); |
| 280 | QBoxLayout* layout = new QHBoxLayout(this); | 275 | QBoxLayout* layout = new QHBoxLayout(this); |
| 281 | 276 | ||
| 282 | resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); | 277 | resize(VideoCore::kScreenTopWidth, |
| 278 | VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); | ||
| 283 | layout->addWidget(child); | 279 | layout->addWidget(child); |
| 284 | layout->setMargin(0); | 280 | layout->setMargin(0); |
| 285 | setLayout(layout); | 281 | setLayout(layout); |
| @@ -292,7 +288,8 @@ void GRenderWindow::InitRenderTarget() { | |||
| 292 | BackupGeometry(); | 288 | BackupGeometry(); |
| 293 | } | 289 | } |
| 294 | 290 | ||
| 295 | void GRenderWindow::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { | 291 | void GRenderWindow::OnMinimalClientAreaChangeRequest( |
| 292 | const std::pair<unsigned, unsigned>& minimal_size) { | ||
| 296 | setMinimumSize(minimal_size.first, minimal_size.second); | 293 | setMinimumSize(minimal_size.first, minimal_size.second); |
| 297 | } | 294 | } |
| 298 | 295 | ||
| @@ -306,11 +303,12 @@ void GRenderWindow::OnEmulationStopping() { | |||
| 306 | child->EnablePainting(); | 303 | child->EnablePainting(); |
| 307 | } | 304 | } |
| 308 | 305 | ||
| 309 | void GRenderWindow::showEvent(QShowEvent * event) { | 306 | void GRenderWindow::showEvent(QShowEvent* event) { |
| 310 | QWidget::showEvent(event); | 307 | QWidget::showEvent(event); |
| 311 | 308 | ||
| 312 | // windowHandle() is not initialized until the Window is shown, so we connect it here. | 309 | // windowHandle() is not initialized until the Window is shown, so we connect it here. |
| 313 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | 310 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) |
| 314 | connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, SLOT(OnFramebufferSizeChanged()), Qt::UniqueConnection); | 311 | connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, |
| 315 | #endif | 312 | SLOT(OnFramebufferSizeChanged()), Qt::UniqueConnection); |
| 313 | #endif | ||
| 316 | } | 314 | } |