Qt: Add Host::GetTopLevelWindowInfo()

This commit is contained in:
Connor McLaughlin 2022-10-15 19:03:52 +10:00 committed by refractionpcsx2
parent 48926a7ec4
commit bcd19dd0f5
8 changed files with 100 additions and 51 deletions

View File

@ -62,62 +62,26 @@ DisplayWidget::~DisplayWidget()
#endif
}
qreal DisplayWidget::devicePixelRatioFromScreen() const
{
const QScreen* screen_for_ratio = screen();
if (!screen_for_ratio)
screen_for_ratio = QGuiApplication::primaryScreen();
return screen_for_ratio ? screen_for_ratio->devicePixelRatio() : static_cast<qreal>(1);
}
int DisplayWidget::scaledWindowWidth() const
{
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * devicePixelRatioFromScreen())), 1);
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * QtUtils::GetDevicePixelRatioForWidget(this))), 1);
}
int DisplayWidget::scaledWindowHeight() const
{
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * devicePixelRatioFromScreen())), 1);
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * QtUtils::GetDevicePixelRatioForWidget(this))), 1);
}
std::optional<WindowInfo> DisplayWidget::getWindowInfo()
{
WindowInfo wi;
// Windows and Apple are easy here since there's no display connection.
#if defined(_WIN32)
wi.type = WindowInfo::Type::Win32;
wi.window_handle = reinterpret_cast<void*>(winId());
#elif defined(__APPLE__)
wi.type = WindowInfo::Type::MacOS;
wi.window_handle = reinterpret_cast<void*>(winId());
#else
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
const QString platform_name = QGuiApplication::platformName();
if (platform_name == QStringLiteral("xcb"))
std::optional<WindowInfo> ret(QtUtils::GetWindowInfoForWidget(this));
if (ret.has_value())
{
wi.type = WindowInfo::Type::X11;
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle());
wi.window_handle = reinterpret_cast<void*>(winId());
m_last_window_width = ret->surface_width;
m_last_window_height = ret->surface_height;
m_last_window_scale = ret->surface_scale;
}
else if (platform_name == QStringLiteral("wayland"))
{
wi.type = WindowInfo::Type::Wayland;
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle());
wi.window_handle = pni->nativeResourceForWindow("surface", windowHandle());
}
else
{
qCritical() << "Unknown PNI platform " << platform_name;
return std::nullopt;
}
#endif
m_last_window_width = wi.surface_width = static_cast<u32>(scaledWindowWidth());
m_last_window_height = wi.surface_height = static_cast<u32>(scaledWindowHeight());
m_last_window_scale = wi.surface_scale = static_cast<float>(devicePixelRatioFromScreen());
return wi;
return ret;
}
void DisplayWidget::updateRelativeMode(bool master_enable)
@ -295,7 +259,7 @@ bool DisplayWidget::event(QEvent* event)
if (!m_relative_mouse_enabled)
{
const qreal dpr = devicePixelRatioFromScreen();
const qreal dpr = QtUtils::GetDevicePixelRatioForWidget(this);
const QPoint mouse_pos = mouse_event->pos();
const float scaled_x = static_cast<float>(static_cast<qreal>(mouse_pos.x()) * dpr);
@ -380,7 +344,7 @@ bool DisplayWidget::event(QEvent* event)
{
QWidget::event(event);
const float dpr = devicePixelRatioFromScreen();
const float dpr = QtUtils::GetDevicePixelRatioForWidget(this);
const u32 scaled_width = static_cast<u32>(std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * dpr)), 1));
const u32 scaled_height = static_cast<u32>(std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * dpr)), 1));

View File

@ -36,7 +36,6 @@ public:
int scaledWindowWidth() const;
int scaledWindowHeight() const;
qreal devicePixelRatioFromScreen() const;
std::optional<WindowInfo> getWindowInfo();

View File

@ -1181,6 +1181,11 @@ void MainWindow::checkForSettingChanges()
updateWindowState();
}
std::optional<WindowInfo> MainWindow::getWindowInfo()
{
return QtUtils::GetWindowInfoForWidget(this);
}
void Host::InvalidateSaveStateCache()
{
QMetaObject::invokeMethod(g_main_window, &MainWindow::invalidateSaveStateCache, Qt::QueuedConnection);

View File

@ -15,6 +15,8 @@
#pragma once
#include "common/WindowInfo.h"
#include <QtWidgets/QLabel>
#include <QtWidgets/QMainWindow>
#include <functional>
@ -108,6 +110,7 @@ public Q_SLOTS:
bool requestShutdown(bool allow_confirm = true, bool allow_save_to_state = true, bool default_save_to_state = true, bool block_until_done = false);
void requestExit();
void checkForSettingChanges();
std::optional<WindowInfo> getWindowInfo();
private Q_SLOTS:
void onUpdateCheckComplete();

View File

@ -1482,6 +1482,13 @@ void Host::EndTextInput()
QMetaObject::invokeMethod(method, "hide", Qt::QueuedConnection);
}
std::optional<WindowInfo> Host::GetTopLevelWindowInfo()
{
std::optional<WindowInfo> ret;
QMetaObject::invokeMethod(g_main_window, &MainWindow::getWindowInfo, Qt::BlockingQueuedConnection, &ret);
return ret;
}
void Host::OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name)
{
emit g_emu_thread->onInputDeviceConnected(
@ -1754,6 +1761,7 @@ static bool PerformEarlyHardwareChecks()
static void RegisterTypes()
{
qRegisterMetaType<std::optional<bool>>();
qRegisterMetaType<std::optional<WindowInfo>>("std::optional<WindowInfo>()");
qRegisterMetaType<std::function<void()>>("std::function<void()>");
qRegisterMetaType<std::shared_ptr<VMBootParameters>>();
qRegisterMetaType<GSRendererType>();

View File

@ -15,13 +15,15 @@
#include "PrecompiledHeader.h"
#include "QtUtils.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QMetaObject>
#include <QtGui/QAction>
#include <QtGui/QGuiApplication>
#include <QtGui/QDesktopServices>
#include <QtGui/QKeyEvent>
#include <QtGui/QAction>
#include <QtGui/QScreen>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialog>
#include <QtWidgets/QHeaderView>
@ -33,11 +35,16 @@
#include <QtWidgets/QStyle>
#include <QtWidgets/QTableView>
#include <QtWidgets/QTreeView>
#include <algorithm>
#include <array>
#include <map>
#include "QtUtils.h"
#if defined(_WIN32)
#include "common/RedtapeWindows.h"
#elif !defined(APPLE)
#include <qpa/qplatformnativeinterface.h>
#endif
namespace QtUtils
{
@ -203,4 +210,54 @@ namespace QtUtils
widget->resize(width, height);
}
qreal GetDevicePixelRatioForWidget(const QWidget* widget)
{
const QScreen* screen_for_ratio = widget->screen();
if (!screen_for_ratio)
screen_for_ratio = QGuiApplication::primaryScreen();
return screen_for_ratio ? screen_for_ratio->devicePixelRatio() : static_cast<qreal>(1);
}
std::optional<WindowInfo> GetWindowInfoForWidget(QWidget* widget)
{
WindowInfo wi;
// Windows and Apple are easy here since there's no display connection.
#if defined(_WIN32)
wi.type = WindowInfo::Type::Win32;
wi.window_handle = reinterpret_cast<void*>(widget->winId());
#elif defined(__APPLE__)
wi.type = WindowInfo::Type::MacOS;
wi.window_handle = reinterpret_cast<void*>(widget->winId());
#else
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
const QString platform_name = QGuiApplication::platformName();
if (platform_name == QStringLiteral("xcb"))
{
wi.type = WindowInfo::Type::X11;
wi.display_connection = pni->nativeResourceForWindow("display", widget->windowHandle());
wi.window_handle = reinterpret_cast<void*>(widget->winId());
}
else if (platform_name == QStringLiteral("wayland"))
{
wi.type = WindowInfo::Type::Wayland;
wi.display_connection = pni->nativeResourceForWindow("display", widget->windowHandle());
wi.window_handle = pni->nativeResourceForWindow("surface", widget->windowHandle());
}
else
{
qCritical() << "Unknown PNI platform " << platform_name;
return std::nullopt;
}
#endif
const qreal dpr = GetDevicePixelRatioForWidget(widget);
wi.surface_width = static_cast<u32>(static_cast<qreal>(widget->width()) * dpr);
wi.surface_height = static_cast<u32>(static_cast<qreal>(widget->height()) * dpr);
wi.surface_scale = static_cast<float>(dpr);
return wi;
}
} // namespace QtUtils

View File

@ -14,6 +14,9 @@
*/
#pragma once
#include "common/WindowInfo.h"
#include <QtCore/QByteArray>
#include <QtCore/QMetaType>
#include <QtCore/QString>
@ -77,4 +80,10 @@ namespace QtUtils
/// Adjusts the fixed size for a window if it's not resizeable.
void ResizePotentiallyFixedSizeWindow(QWidget* widget, int width, int height);
/// Returns the pixel ratio/scaling factor for a widget.
qreal GetDevicePixelRatioForWidget(const QWidget* widget);
/// Returns the common window info structure for a Qt widget.
std::optional<WindowInfo> GetWindowInfoForWidget(QWidget* widget);
} // namespace QtUtils

View File

@ -24,6 +24,7 @@
#include "common/Pcsx2Types.h"
#include "common/SettingsInterface.h"
#include "common/WindowInfo.h"
/// Class, or source of an input event.
enum class InputSourceType : u32
@ -303,6 +304,9 @@ namespace InputManager
namespace Host
{
/// Return the current window handle. Needed for DInput.
std::optional<WindowInfo> GetTopLevelWindowInfo();
/// Called when a new input device is connected.
void OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name);