| 
									
										
										
										
											2015-11-27 00:33:07 -08:00
										 |  |  | // Copyright 2015 Dolphin Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2+
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-13 20:12:13 +02:00
										 |  |  | #include <QApplication>
 | 
					
						
							|  |  |  | #include <QDesktopWidget>
 | 
					
						
							|  |  |  | #include <QGuiApplication>
 | 
					
						
							| 
									
										
										
										
											2018-05-04 14:04:46 +02:00
										 |  |  | #include <QIcon>
 | 
					
						
							| 
									
										
										
										
											2015-11-27 00:33:07 -08:00
										 |  |  | #include <QKeyEvent>
 | 
					
						
							| 
									
										
										
										
											2018-04-29 13:35:43 +02:00
										 |  |  | #include <QMouseEvent>
 | 
					
						
							| 
									
										
										
										
											2018-03-24 23:50:03 +01:00
										 |  |  | #include <QPalette>
 | 
					
						
							| 
									
										
										
										
											2018-04-13 20:12:13 +02:00
										 |  |  | #include <QScreen>
 | 
					
						
							| 
									
										
										
										
											2017-07-04 10:58:27 -04:00
										 |  |  | #include <QTimer>
 | 
					
						
							| 
									
										
										
										
											2015-11-27 00:33:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 16:40:47 +01:00
										 |  |  | #include "Core/ConfigManager.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-24 23:50:03 +01:00
										 |  |  | #include "Core/Core.h"
 | 
					
						
							| 
									
										
										
										
											2018-04-29 13:35:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-07 00:40:15 +02:00
										 |  |  | #include "DolphinQt/Host.h"
 | 
					
						
							|  |  |  | #include "DolphinQt/RenderWidget.h"
 | 
					
						
							|  |  |  | #include "DolphinQt/Resources.h"
 | 
					
						
							|  |  |  | #include "DolphinQt/Settings.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-27 00:33:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-28 03:48:04 +02:00
										 |  |  | #include "VideoCommon/VertexShaderManager.h"
 | 
					
						
							|  |  |  | #include "VideoCommon/VideoConfig.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | RenderWidget::RenderWidget(QWidget* parent) : QWidget(parent) | 
					
						
							| 
									
										
										
										
											2015-11-27 00:33:07 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-05-04 14:04:46 +02:00
										 |  |  |   setWindowTitle(QStringLiteral("Dolphin")); | 
					
						
							|  |  |  |   setWindowIcon(Resources::GetAppIcon()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 23:50:03 +01:00
										 |  |  |   QPalette p; | 
					
						
							|  |  |  |   p.setColor(QPalette::Background, Qt::black); | 
					
						
							|  |  |  |   setPalette(p); | 
					
						
							| 
									
										
										
										
											2015-11-27 00:33:07 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   connect(Host::GetInstance(), &Host::RequestTitle, this, &RenderWidget::setWindowTitle); | 
					
						
							| 
									
										
										
										
											2018-03-24 16:40:47 +01:00
										 |  |  |   connect(Host::GetInstance(), &Host::RequestRenderSize, this, [this](int w, int h) { | 
					
						
							|  |  |  |     if (!SConfig::GetInstance().bRenderWindowAutoSize || isFullScreen() || isMaximized()) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resize(w, h); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-11-19 17:27:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 23:50:03 +01:00
										 |  |  |   connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) { | 
					
						
							|  |  |  |     SetFillBackground(SConfig::GetInstance().bRenderToMain && state == Core::State::Uninitialized); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-19 17:27:07 +01:00
										 |  |  |   // We have to use Qt::DirectConnection here because we don't want those signals to get queued
 | 
					
						
							|  |  |  |   // (which results in them not getting called)
 | 
					
						
							|  |  |  |   connect(this, &RenderWidget::StateChanged, Host::GetInstance(), &Host::SetRenderFullscreen, | 
					
						
							|  |  |  |           Qt::DirectConnection); | 
					
						
							|  |  |  |   connect(this, &RenderWidget::HandleChanged, Host::GetInstance(), &Host::SetRenderHandle, | 
					
						
							|  |  |  |           Qt::DirectConnection); | 
					
						
							| 
									
										
										
										
											2018-01-26 16:23:24 +10:00
										 |  |  |   connect(this, &RenderWidget::SizeChanged, Host::GetInstance(), &Host::ResizeSurface, | 
					
						
							| 
									
										
										
										
											2018-01-20 21:00:28 +01:00
										 |  |  |           Qt::DirectConnection); | 
					
						
							| 
									
										
										
										
											2018-06-08 20:47:15 +02:00
										 |  |  |   connect(this, &RenderWidget::FocusChanged, Host::GetInstance(), &Host::SetRenderFocus, | 
					
						
							|  |  |  |           Qt::DirectConnection); | 
					
						
							| 
									
										
										
										
											2017-11-19 17:27:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-04 10:58:27 -04:00
										 |  |  |   m_mouse_timer = new QTimer(this); | 
					
						
							|  |  |  |   connect(m_mouse_timer, &QTimer::timeout, this, &RenderWidget::HandleCursorTimer); | 
					
						
							|  |  |  |   m_mouse_timer->setSingleShot(true); | 
					
						
							|  |  |  |   setMouseTracking(true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-31 23:49:21 -07:00
										 |  |  |   connect(&Settings::Instance(), &Settings::HideCursorChanged, this, | 
					
						
							|  |  |  |           &RenderWidget::OnHideCursorChanged); | 
					
						
							|  |  |  |   OnHideCursorChanged(); | 
					
						
							| 
									
										
										
										
											2018-04-22 10:56:15 +02:00
										 |  |  |   connect(&Settings::Instance(), &Settings::KeepWindowOnTopChanged, this, | 
					
						
							|  |  |  |           &RenderWidget::OnKeepOnTopChanged); | 
					
						
							|  |  |  |   OnKeepOnTopChanged(Settings::Instance().IsKeepWindowOnTopEnabled()); | 
					
						
							| 
									
										
										
										
											2017-07-04 10:58:27 -04:00
										 |  |  |   m_mouse_timer->start(MOUSE_HIDE_DELAY); | 
					
						
							| 
									
										
										
										
											2018-03-24 23:50:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 23:03:22 +10:00
										 |  |  |   // We need a native window to render into.
 | 
					
						
							|  |  |  |   setAttribute(Qt::WA_NativeWindow); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 23:50:03 +01:00
										 |  |  |   SetFillBackground(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RenderWidget::SetFillBackground(bool fill) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   setAttribute(Qt::WA_OpaquePaintEvent, !fill); | 
					
						
							|  |  |  |   setAttribute(Qt::WA_NoSystemBackground, !fill); | 
					
						
							|  |  |  |   setAutoFillBackground(fill); | 
					
						
							| 
									
										
										
										
											2017-05-31 23:49:21 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RenderWidget::OnHideCursorChanged() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   setCursor(Settings::Instance().GetHideCursor() ? Qt::BlankCursor : Qt::ArrowCursor); | 
					
						
							| 
									
										
										
										
											2015-11-27 00:33:07 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 10:56:15 +02:00
										 |  |  | void RenderWidget::OnKeepOnTopChanged(bool top) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-04-22 13:01:18 +02:00
										 |  |  |   const bool was_visible = isVisible(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 10:56:15 +02:00
										 |  |  |   setWindowFlags(top ? windowFlags() | Qt::WindowStaysOnTopHint : | 
					
						
							|  |  |  |                        windowFlags() & ~Qt::WindowStaysOnTopHint); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-22 13:01:18 +02:00
										 |  |  |   if (was_visible) | 
					
						
							|  |  |  |     show(); | 
					
						
							| 
									
										
										
										
											2018-04-22 10:56:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-04 10:58:27 -04:00
										 |  |  | void RenderWidget::HandleCursorTimer() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (isActiveWindow()) | 
					
						
							|  |  |  |     setCursor(Qt::BlankCursor); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-21 20:53:37 +01:00
										 |  |  | void RenderWidget::showFullScreen() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   QWidget::showFullScreen(); | 
					
						
							| 
									
										
										
										
											2018-04-13 20:12:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const auto dpr = | 
					
						
							|  |  |  |       QGuiApplication::screens()[QApplication::desktop()->screenNumber(this)]->devicePixelRatio(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   emit SizeChanged(width() * dpr, height() * dpr); | 
					
						
							| 
									
										
										
										
											2018-03-21 20:53:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-27 00:33:07 -08:00
										 |  |  | bool RenderWidget::event(QEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   switch (event->type()) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-04-20 22:11:54 +02:00
										 |  |  |   case QEvent::Paint: | 
					
						
							|  |  |  |     return !autoFillBackground(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   case QEvent::KeyPress: | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     QKeyEvent* ke = static_cast<QKeyEvent*>(event); | 
					
						
							|  |  |  |     if (ke->key() == Qt::Key_Escape) | 
					
						
							|  |  |  |       emit EscapePressed(); | 
					
						
							| 
									
										
										
										
											2018-01-29 18:35:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // The render window might flicker on some platforms because Qt tries to change focus to a new
 | 
					
						
							|  |  |  |     // element when there is none (?) Handling this event before it reaches QWidget fixes the issue.
 | 
					
						
							|  |  |  |     if (ke->key() == Qt::Key_Tab) | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     break; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-07-04 10:58:27 -04:00
										 |  |  |   case QEvent::MouseMove: | 
					
						
							| 
									
										
										
										
											2018-04-29 13:35:43 +02:00
										 |  |  |     if (g_Config.bFreeLook) | 
					
						
							|  |  |  |       OnFreeLookMouseMove(static_cast<QMouseEvent*>(event)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // [[fallthrough]]
 | 
					
						
							| 
									
										
										
										
											2017-07-04 10:58:27 -04:00
										 |  |  |   case QEvent::MouseButtonPress: | 
					
						
							|  |  |  |     if (!Settings::Instance().GetHideCursor() && isActiveWindow()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       setCursor(Qt::ArrowCursor); | 
					
						
							|  |  |  |       m_mouse_timer->start(MOUSE_HIDE_DELAY); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     break; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   case QEvent::WinIdChange: | 
					
						
							| 
									
										
										
										
											2018-10-03 23:03:13 +10:00
										 |  |  |     emit HandleChanged(reinterpret_cast<void*>(winId())); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     break; | 
					
						
							| 
									
										
										
										
											2017-07-13 12:56:33 -07:00
										 |  |  |   case QEvent::WindowActivate: | 
					
						
							| 
									
										
										
										
											2018-04-20 21:46:42 +02:00
										 |  |  |     if (SConfig::GetInstance().m_PauseOnFocusLost && Core::GetState() == Core::State::Paused) | 
					
						
							|  |  |  |       Core::SetState(Core::State::Running); | 
					
						
							| 
									
										
										
										
											2018-06-08 20:47:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     emit FocusChanged(true); | 
					
						
							| 
									
										
										
										
											2017-07-13 12:56:33 -07:00
										 |  |  |     break; | 
					
						
							|  |  |  |   case QEvent::WindowDeactivate: | 
					
						
							| 
									
										
										
										
											2018-04-20 21:46:42 +02:00
										 |  |  |     if (SConfig::GetInstance().m_PauseOnFocusLost && Core::GetState() == Core::State::Running) | 
					
						
							|  |  |  |       Core::SetState(Core::State::Paused); | 
					
						
							| 
									
										
										
										
											2018-06-08 20:47:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     emit FocusChanged(false); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     break; | 
					
						
							| 
									
										
										
										
											2018-01-20 21:00:28 +01:00
										 |  |  |   case QEvent::Resize: | 
					
						
							| 
									
										
										
										
											2018-01-26 16:23:24 +10:00
										 |  |  |   { | 
					
						
							|  |  |  |     const QResizeEvent* se = static_cast<QResizeEvent*>(event); | 
					
						
							|  |  |  |     QSize new_size = se->size(); | 
					
						
							| 
									
										
										
										
											2018-04-13 20:12:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-06 04:42:23 +02:00
										 |  |  |     auto* desktop = QApplication::desktop(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int screen_nr = desktop->screenNumber(this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (screen_nr == -1) | 
					
						
							|  |  |  |       screen_nr = desktop->screenNumber(parentWidget()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto dpr = desktop->screen(screen_nr)->devicePixelRatio(); | 
					
						
							| 
									
										
										
										
											2018-04-13 20:12:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     emit SizeChanged(new_size.width() * dpr, new_size.height() * dpr); | 
					
						
							| 
									
										
										
										
											2018-01-20 21:00:28 +01:00
										 |  |  |     break; | 
					
						
							| 
									
										
										
										
											2018-01-26 16:23:24 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   case QEvent::WindowStateChange: | 
					
						
							|  |  |  |     emit StateChanged(isFullScreen()); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case QEvent::Close: | 
					
						
							|  |  |  |     emit Closed(); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   default: | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return QWidget::event(event); | 
					
						
							| 
									
										
										
										
											2015-11-27 00:33:07 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-04-29 13:35:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void RenderWidget::OnFreeLookMouseMove(QMouseEvent* event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (event->buttons() & Qt::MidButton) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Mouse Move
 | 
					
						
							|  |  |  |     VertexShaderManager::TranslateView((event->x() - m_last_mouse[0]) / 50.0f, | 
					
						
							|  |  |  |                                        (event->y() - m_last_mouse[1]) / 50.0f); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (event->buttons() & Qt::RightButton) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Mouse Look
 | 
					
						
							|  |  |  |     VertexShaderManager::RotateView((event->x() - m_last_mouse[0]) / 200.0f, | 
					
						
							|  |  |  |                                     (event->y() - m_last_mouse[1]) / 200.0f); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   m_last_mouse[0] = event->x(); | 
					
						
							|  |  |  |   m_last_mouse[1] = event->y(); | 
					
						
							|  |  |  | } |