Skip to content

Commit

Permalink
Host: Add GetTopLevelWindowInfo()
Browse files Browse the repository at this point in the history
And use it for screensaver inhibiting on Linux.
  • Loading branch information
stenzek committed Nov 18, 2022
1 parent 3d4d233 commit 8d7aea5
Show file tree
Hide file tree
Showing 25 changed files with 133 additions and 126 deletions.
4 changes: 2 additions & 2 deletions src/duckstation-nogui/nogui_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -964,9 +964,9 @@ void Host::SetFullscreen(bool enabled)
g_nogui_window->SetFullscreen(enabled);
}

void* Host::GetTopLevelWindowHandle()
std::optional<WindowInfo> Host::GetTopLevelWindowInfo()
{
return g_nogui_window->GetPlatformWindowHandle();
return g_nogui_window->GetPlatformWindowInfo();
}

void Host::RequestExit(bool save_state_if_running)
Expand Down
1 change: 0 additions & 1 deletion src/duckstation-nogui/nogui_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class NoGUIPlatform

virtual std::optional<WindowInfo> GetPlatformWindowInfo() = 0;
virtual void SetPlatformWindowTitle(std::string title) = 0;
virtual void* GetPlatformWindowHandle() = 0;

virtual std::optional<u32> ConvertHostKeyboardStringToCode(const std::string_view& str) = 0;
virtual std::optional<std::string> ConvertHostKeyboardCodeToString(u32 code) = 0;
Expand Down
5 changes: 0 additions & 5 deletions src/duckstation-nogui/vty_nogui_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,6 @@ void VTYNoGUIPlatform::SetPlatformWindowTitle(std::string title)
Log_InfoPrintf("Window Title: %s", title.c_str());
}

void* VTYNoGUIPlatform::GetPlatformWindowHandle()
{
return nullptr;
}

void VTYNoGUIPlatform::RunMessageLoop()
{
while (m_message_loop_running.load(std::memory_order_acquire))
Expand Down
1 change: 0 additions & 1 deletion src/duckstation-nogui/vty_nogui_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class VTYNoGUIPlatform : public NoGUIPlatform
void DestroyPlatformWindow() override;
std::optional<WindowInfo> GetPlatformWindowInfo() override;
void SetPlatformWindowTitle(std::string title) override;
void* GetPlatformWindowHandle() override;

std::optional<u32> ConvertHostKeyboardStringToCode(const std::string_view& str) override;
std::optional<std::string> ConvertHostKeyboardCodeToString(u32 code) override;
Expand Down
5 changes: 0 additions & 5 deletions src/duckstation-nogui/wayland_nogui_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,6 @@ void WaylandNoGUIPlatform::SetPlatformWindowTitle(std::string title)
xdg_toplevel_set_title(m_xdg_toplevel, title.c_str());
}

void* WaylandNoGUIPlatform::GetPlatformWindowHandle()
{
return m_surface;
}

std::optional<u32> WaylandNoGUIPlatform::ConvertHostKeyboardStringToCode(const std::string_view& str)
{
std::unique_lock lock(m_key_map_mutex);
Expand Down
1 change: 0 additions & 1 deletion src/duckstation-nogui/wayland_nogui_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ class WaylandNoGUIPlatform : public NoGUIPlatform
void DestroyPlatformWindow() override;
std::optional<WindowInfo> GetPlatformWindowInfo() override;
void SetPlatformWindowTitle(std::string title) override;
void* GetPlatformWindowHandle() override;

std::optional<u32> ConvertHostKeyboardStringToCode(const std::string_view& str) override;
std::optional<std::string> ConvertHostKeyboardCodeToString(u32 code) override;
Expand Down
5 changes: 0 additions & 5 deletions src/duckstation-nogui/win32_nogui_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,6 @@ void Win32NoGUIPlatform::SetPlatformWindowTitle(std::string title)
SetWindowTextW(m_hwnd, StringUtil::UTF8StringToWideString(title).c_str());
}

void* Win32NoGUIPlatform::GetPlatformWindowHandle()
{
return m_hwnd;
}

std::optional<u32> Win32NoGUIPlatform::ConvertHostKeyboardStringToCode(const std::string_view& str)
{
std::optional<DWORD> converted(Win32KeyNames::GetKeyCodeForName(str));
Expand Down
1 change: 0 additions & 1 deletion src/duckstation-nogui/win32_nogui_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class Win32NoGUIPlatform : public NoGUIPlatform
void DestroyPlatformWindow() override;
std::optional<WindowInfo> GetPlatformWindowInfo() override;
void SetPlatformWindowTitle(std::string title) override;
void* GetPlatformWindowHandle() override;

std::optional<u32> ConvertHostKeyboardStringToCode(const std::string_view& str) override;
std::optional<std::string> ConvertHostKeyboardCodeToString(u32 code) override;
Expand Down
5 changes: 0 additions & 5 deletions src/duckstation-nogui/x11_nogui_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,6 @@ void X11NoGUIPlatform::SetPlatformWindowTitle(std::string title)
});
}

void* X11NoGUIPlatform::GetPlatformWindowHandle()
{
return reinterpret_cast<void*>(m_window);
}

void X11NoGUIPlatform::InitializeKeyMap()
{
int min_keycode = 0, max_keycode = -1;
Expand Down
1 change: 0 additions & 1 deletion src/duckstation-nogui/x11_nogui_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ class X11NoGUIPlatform : public NoGUIPlatform
void DestroyPlatformWindow() override;
std::optional<WindowInfo> GetPlatformWindowInfo() override;
void SetPlatformWindowTitle(std::string title) override;
void* GetPlatformWindowHandle() override;

std::optional<u32> ConvertHostKeyboardStringToCode(const std::string_view& str) override;
std::optional<std::string> ConvertHostKeyboardCodeToString(u32 code) override;
Expand Down
58 changes: 12 additions & 46 deletions src/duckstation-qt/displaywidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,62 +44,28 @@ 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 enabled)
Expand Down Expand Up @@ -270,7 +236,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);
Expand Down Expand Up @@ -341,7 +307,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 =
Expand Down
1 change: 0 additions & 1 deletion src/duckstation-qt/displaywidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class DisplayWidget final : public QWidget

int scaledWindowWidth() const;
int scaledWindowHeight() const;
qreal devicePixelRatioFromScreen() const;

std::optional<WindowInfo> getWindowInfo();

Expand Down
7 changes: 7 additions & 0 deletions src/duckstation-qt/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2520,6 +2520,13 @@ void MainWindow::checkForSettingChanges()
updateWindowState();
}

void MainWindow::getWindowInfo(WindowInfo* wi)
{
std::optional<WindowInfo> opt_wi(QtUtils::GetWindowInfoForWidget(this));
if (opt_wi.has_value())
*wi = opt_wi.value();
}

void MainWindow::onCheckForUpdatesActionTriggered()
{
// Wipe out the last version, that way it displays the update if we've previously skipped it.
Expand Down
3 changes: 3 additions & 0 deletions src/duckstation-qt/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QStackedWidget>
#include <memory>
#include <optional>

#include "controllersettingsdialog.h"
#include "common/window_info.h"
#include "core/types.h"
#include "displaywidget.h"
#include "settingsdialog.h"
Expand Down Expand Up @@ -97,6 +99,7 @@ public Q_SLOTS:
bool requestShutdown(bool allow_confirm = true, bool allow_save_to_state = true, bool save_state = true, bool block_until_done = false);
void requestExit(bool allow_save_to_state = true);
void checkForSettingChanges();
void getWindowInfo(WindowInfo* wi);

void checkForUpdates(bool display_message);

Expand Down
10 changes: 7 additions & 3 deletions src/duckstation-qt/qthost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "common/log.h"
#include "common/path.h"
#include "common/string_util.h"
#include "common/window_info.h"
#include "core/cheats.h"
#include "core/controller.h"
#include "core/game_database.h"
Expand Down Expand Up @@ -1757,10 +1758,13 @@ void Host::RequestExit(bool save_state_if_running)
QMetaObject::invokeMethod(g_main_window, "requestExit", Qt::QueuedConnection, Q_ARG(bool, save_state_if_running));
}

void* Host::GetTopLevelWindowHandle()
std::optional<WindowInfo> Host::GetTopLevelWindowInfo()
{
void* ret = nullptr;
QMetaObject::invokeMethod(g_main_window, &MainWindow::getNativeWindowId, Qt::BlockingQueuedConnection, &ret);
// Normally we'd just feed the std::optional all the way through here. But that won't work because of some bug
// in Qt 6.1, and we can't upgrade that because of raging/abusive Win7 users... to anyone still using that dead
// OS, this is a passive-aggressive "screw you".
WindowInfo ret;
QMetaObject::invokeMethod(g_main_window, "getWindowInfo", Qt::BlockingQueuedConnection, Q_ARG(WindowInfo*, &ret));
return ret;
}

Expand Down
58 changes: 58 additions & 0 deletions src/duckstation-qt/qtutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QMetaObject>
#include <QtGui/QDesktopServices>
#include <QtGui/QGuiApplication>
#include <QtGui/QKeyEvent>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialog>
Expand All @@ -22,6 +23,14 @@
#include <array>
#include <map>

#if !defined(_WIN32) && !defined(APPLE)
#include <qpa/qplatformnativeinterface.h>
#endif

#ifdef _WIN32
#include "common/windows_headers.h"
#endif

namespace QtUtils {

QFrame* CreateHorizontalLine(QWidget* parent)
Expand Down Expand Up @@ -862,4 +871,53 @@ QIcon GetIconForCompatibility(GameDatabase::CompatibilityRating rating)
return QIcon(QStringLiteral(":/icons/star-%1.png").arg(static_cast<u32>(rating)));
}

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
7 changes: 7 additions & 0 deletions src/duckstation-qt/qtutils.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "common/window_info.h"
#include "common/types.h"
#include <QtCore/QByteArray>
#include <QtCore/QMetaType>
Expand Down Expand Up @@ -91,4 +92,10 @@ QIcon GetIconForRegion(DiscRegion region);
QIcon GetIconForEntryType(GameList::EntryType type);
QIcon GetIconForCompatibility(GameDatabase::CompatibilityRating rating);

/// 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
6 changes: 3 additions & 3 deletions src/frontend-common/common_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ void CommonHost::OnSystemStarted()
FullscreenUI::OnSystemStarted();

if (g_settings.inhibit_screensaver)
FrontendCommon::SuspendScreensaver(g_host_display->GetWindowInfo());
FrontendCommon::SuspendScreensaver();
}

void CommonHost::OnSystemPaused()
Expand All @@ -261,7 +261,7 @@ void CommonHost::OnSystemResumed()
FullscreenUI::OnSystemResumed();

if (g_settings.inhibit_screensaver)
FrontendCommon::SuspendScreensaver(g_host_display->GetWindowInfo());
FrontendCommon::SuspendScreensaver();
}

void CommonHost::OnSystemDestroyed()
Expand Down Expand Up @@ -361,7 +361,7 @@ void CommonHost::CheckForSettingsChanges(const Settings& old_settings)
if (g_settings.inhibit_screensaver != old_settings.inhibit_screensaver)
{
if (g_settings.inhibit_screensaver)
FrontendCommon::SuspendScreensaver(g_host_display->GetWindowInfo());
FrontendCommon::SuspendScreensaver();
else
FrontendCommon::ResumeScreensaver();
}
Expand Down
5 changes: 0 additions & 5 deletions src/frontend-common/common_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,3 @@ std::unique_ptr<AudioStream> CreateXAudio2Stream(u32 sample_rate, u32 channels,
namespace ImGuiManager {
void RenderDebugWindows();
}

namespace Host {
/// Return the current window handle. Needed for DInput.
void* GetTopLevelWindowHandle();
} // namespace Host
Loading

0 comments on commit 8d7aea5

Please sign in to comment.