Qt: Borderless GBA windows

This commit is contained in:
Bonta 2021-07-24 19:12:17 +02:00
parent ee64e217f4
commit 63ff86adff
2 changed files with 105 additions and 42 deletions

View File

@ -60,22 +60,18 @@ static void QueueEReaderCard(const std::weak_ptr<HW::GBA::Core>& core, std::stri
} }
GBAWidget::GBAWidget(std::weak_ptr<HW::GBA::Core> core, const HW::GBA::CoreInfo& info, GBAWidget::GBAWidget(std::weak_ptr<HW::GBA::Core> core, const HW::GBA::CoreInfo& info,
QWidget* parent, Qt::WindowFlags flags) const std::optional<NetPlay::PadDetails>& netplay_pad)
: QWidget(parent, flags), m_core(std::move(core)), m_core_info(info), : QWidget(nullptr, LoadWindowFlags(netplay_pad ? netplay_pad->local_pad : info.device_number)),
m_local_pad(info.device_number), m_is_local_pad(true), m_volume(0), m_muted(false), m_core(std::move(core)), m_core_info(info), m_local_pad(info.device_number),
m_force_disconnect(false) m_is_local_pad(true), m_volume(0), m_muted(false), m_force_disconnect(false)
{ {
bool visible = true; bool visible = true;
if (NetPlay::IsNetPlayRunning()) if (netplay_pad)
{ {
NetPlay::PadDetails details = NetPlay::GetPadDetails(m_core_info.device_number); m_netplayer_name = netplay_pad->player_name;
if (details.local_pad < 4) m_is_local_pad = netplay_pad->is_local;
{ m_local_pad = netplay_pad->local_pad;
m_netplayer_name = details.player_name; visible = !netplay_pad->hide_gba;
m_is_local_pad = details.is_local;
m_local_pad = details.local_pad;
visible = !details.hide_gba;
}
} }
setWindowIcon(Resources::GetAppIcon()); setWindowIcon(Resources::GetAppIcon());
@ -87,13 +83,13 @@ GBAWidget::GBAWidget(std::weak_ptr<HW::GBA::Core> core, const HW::GBA::CoreInfo&
if (!visible) if (!visible)
ToggleMute(); ToggleMute();
LoadGeometry(); LoadSettings();
UpdateTitle(); UpdateTitle();
} }
GBAWidget::~GBAWidget() GBAWidget::~GBAWidget()
{ {
SaveGeometry(); SaveSettings();
} }
void GBAWidget::GameChanged(const HW::GBA::CoreInfo& info) void GBAWidget::GameChanged(const HW::GBA::CoreInfo& info)
@ -223,6 +219,33 @@ void GBAWidget::Resize(int scale)
resize(m_core_info.width * scale, m_core_info.height * scale); resize(m_core_info.width * scale, m_core_info.height * scale);
} }
bool GBAWidget::IsBorderless() const
{
return windowFlags().testFlag(Qt::FramelessWindowHint) ||
windowState().testFlag(Qt::WindowFullScreen);
}
void GBAWidget::SetBorderless(bool enable)
{
if (windowState().testFlag(Qt::WindowFullScreen))
{
if (!enable)
setWindowState((windowState() ^ Qt::WindowFullScreen) | Qt::WindowMaximized);
}
else if (windowState().testFlag(Qt::WindowMaximized))
{
if (enable)
setWindowState((windowState() ^ Qt::WindowMaximized) | Qt::WindowFullScreen);
}
else if (windowFlags().testFlag(Qt::FramelessWindowHint) != enable)
{
QRect saved_geometry = geometry();
setWindowFlag(Qt::FramelessWindowHint, enable);
setGeometry(saved_geometry);
show();
}
}
void GBAWidget::UpdateTitle() void GBAWidget::UpdateTitle()
{ {
std::string title = fmt::format("GBA{}", m_core_info.device_number + 1); std::string title = fmt::format("GBA{}", m_core_info.device_number + 1);
@ -247,19 +270,27 @@ void GBAWidget::UpdateVolume()
UpdateTitle(); UpdateTitle();
} }
void GBAWidget::LoadGeometry() Qt::WindowFlags GBAWidget::LoadWindowFlags(int device_number)
{ {
const QSettings& settings = Settings::GetQSettings(); const QSettings& settings = Settings::GetQSettings();
const QString key = QStringLiteral("gbawidget/geometry%1").arg(m_local_pad + 1); const QString key = QStringLiteral("gbawidget/flags%1").arg(device_number + 1);
return settings.contains(key) ? Qt::WindowFlags{settings.value(key).toInt()} : Qt::WindowFlags{};
}
void GBAWidget::LoadSettings()
{
const QSettings& settings = Settings::GetQSettings();
QString key = QStringLiteral("gbawidget/geometry%1").arg(m_local_pad + 1);
if (settings.contains(key)) if (settings.contains(key))
restoreGeometry(settings.value(key).toByteArray()); restoreGeometry(settings.value(key).toByteArray());
} }
void GBAWidget::SaveGeometry() void GBAWidget::SaveSettings()
{ {
QSettings& settings = Settings::GetQSettings(); QSettings& settings = Settings::GetQSettings();
const QString key = QStringLiteral("gbawidget/geometry%1").arg(m_local_pad + 1); settings.setValue(QStringLiteral("gbawidget/flags%1").arg(m_local_pad + 1),
settings.setValue(key, saveGeometry()); static_cast<int>(windowFlags()));
settings.setValue(QStringLiteral("gbawidget/geometry%1").arg(m_local_pad + 1), saveGeometry());
} }
bool GBAWidget::CanControlCore() bool GBAWidget::CanControlCore()
@ -305,13 +336,21 @@ void GBAWidget::contextMenuEvent(QContextMenuEvent* event)
reset_action->setEnabled(CanResetCore()); reset_action->setEnabled(CanResetCore());
connect(reset_action, &QAction::triggered, this, &GBAWidget::ResetCore); connect(reset_action, &QAction::triggered, this, &GBAWidget::ResetCore);
auto* state_menu = new QMenu(tr("Save State"), menu);
auto* import_action = new QAction(tr("&Import State"), state_menu);
import_action->setEnabled(CanControlCore());
connect(import_action, &QAction::triggered, this, [this] { DoState(false); });
auto* export_state = new QAction(tr("&Export State"), state_menu);
connect(export_state, &QAction::triggered, this, [this] { DoState(true); });
auto* mute_action = new QAction(tr("&Mute"), menu); auto* mute_action = new QAction(tr("&Mute"), menu);
mute_action->setCheckable(true); mute_action->setCheckable(true);
mute_action->setChecked(m_muted); mute_action->setChecked(m_muted);
connect(mute_action, &QAction::triggered, this, &GBAWidget::ToggleMute); connect(mute_action, &QAction::triggered, this, &GBAWidget::ToggleMute);
auto* size_menu = new QMenu(tr("Window Size"), menu); auto* options_menu = new QMenu(tr("Options"), menu);
auto* size_menu = new QMenu(tr("Window Size"), options_menu);
auto* x1_action = new QAction(tr("&1x"), size_menu); auto* x1_action = new QAction(tr("&1x"), size_menu);
connect(x1_action, &QAction::triggered, this, [this] { Resize(1); }); connect(x1_action, &QAction::triggered, this, [this] { Resize(1); });
auto* x2_action = new QAction(tr("&2x"), size_menu); auto* x2_action = new QAction(tr("&2x"), size_menu);
@ -321,22 +360,10 @@ void GBAWidget::contextMenuEvent(QContextMenuEvent* event)
auto* x4_action = new QAction(tr("&4x"), size_menu); auto* x4_action = new QAction(tr("&4x"), size_menu);
connect(x4_action, &QAction::triggered, this, [this] { Resize(4); }); connect(x4_action, &QAction::triggered, this, [this] { Resize(4); });
size_menu->addAction(x1_action); auto* borderless_action = new QAction(tr("&Borderless Window"), options_menu);
size_menu->addAction(x2_action); borderless_action->setCheckable(true);
size_menu->addAction(x3_action); borderless_action->setChecked(IsBorderless());
size_menu->addAction(x4_action); connect(borderless_action, &QAction::triggered, this, [this] { SetBorderless(!IsBorderless()); });
auto* state_menu = new QMenu(tr("Save State"), menu);
auto* import_action = new QAction(tr("&Import State"), state_menu);
import_action->setEnabled(CanControlCore());
connect(import_action, &QAction::triggered, this, [this] { DoState(false); });
auto* export_state = new QAction(tr("&Export State"), state_menu);
connect(export_state, &QAction::triggered, this, [this] { DoState(true); });
state_menu->addAction(import_action);
state_menu->addAction(export_state);
menu->addAction(disconnect_action); menu->addAction(disconnect_action);
menu->addSeparator(); menu->addSeparator();
@ -349,12 +376,29 @@ void GBAWidget::contextMenuEvent(QContextMenuEvent* event)
menu->addSeparator(); menu->addSeparator();
menu->addAction(mute_action); menu->addAction(mute_action);
menu->addSeparator(); menu->addSeparator();
menu->addMenu(size_menu); menu->addMenu(options_menu);
state_menu->addAction(import_action);
state_menu->addAction(export_state);
options_menu->addMenu(size_menu);
options_menu->addSeparator();
options_menu->addAction(borderless_action);
size_menu->addAction(x1_action);
size_menu->addAction(x2_action);
size_menu->addAction(x3_action);
size_menu->addAction(x4_action);
menu->move(event->globalPos()); menu->move(event->globalPos());
menu->show(); menu->show();
} }
void GBAWidget::mouseDoubleClickEvent(QMouseEvent* event)
{
SetBorderless(!IsBorderless());
}
void GBAWidget::paintEvent(QPaintEvent* event) void GBAWidget::paintEvent(QPaintEvent* event)
{ {
QPainter painter(this); QPainter painter(this);
@ -429,7 +473,14 @@ GBAWidgetController::~GBAWidgetController()
void GBAWidgetController::Create(std::weak_ptr<HW::GBA::Core> core, const HW::GBA::CoreInfo& info) void GBAWidgetController::Create(std::weak_ptr<HW::GBA::Core> core, const HW::GBA::CoreInfo& info)
{ {
m_widget = new GBAWidget(std::move(core), info); std::optional<NetPlay::PadDetails> netplay_pad;
if (NetPlay::IsNetPlayRunning())
{
const NetPlay::PadDetails details = NetPlay::GetPadDetails(info.device_number);
if (details.local_pad < 4)
netplay_pad = details;
}
m_widget = new GBAWidget(std::move(core), info, netplay_pad);
} }
void GBAWidgetController::GameChanged(const HW::GBA::CoreInfo& info) void GBAWidgetController::GameChanged(const HW::GBA::CoreInfo& info)

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <optional>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
@ -17,14 +18,20 @@ class QCloseEvent;
class QContextMenuEvent; class QContextMenuEvent;
class QDragEnterEvent; class QDragEnterEvent;
class QDropEvent; class QDropEvent;
class QMouseEvent;
class QPaintEvent; class QPaintEvent;
namespace NetPlay
{
struct PadDetails;
} // namespace NetPlay
class GBAWidget : public QWidget class GBAWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit GBAWidget(std::weak_ptr<HW::GBA::Core> core, const HW::GBA::CoreInfo& info, explicit GBAWidget(std::weak_ptr<HW::GBA::Core> core, const HW::GBA::CoreInfo& info,
QWidget* parent = nullptr, Qt::WindowFlags flags = {}); const std::optional<NetPlay::PadDetails>& netplay_pad);
~GBAWidget(); ~GBAWidget();
void GameChanged(const HW::GBA::CoreInfo& info); void GameChanged(const HW::GBA::CoreInfo& info);
@ -44,18 +51,23 @@ public:
void DoState(bool export_state); void DoState(bool export_state);
void Resize(int scale); void Resize(int scale);
bool IsBorderless() const;
void SetBorderless(bool enable);
private: private:
void UpdateTitle(); void UpdateTitle();
void UpdateVolume(); void UpdateVolume();
void LoadGeometry(); static Qt::WindowFlags LoadWindowFlags(int device_number);
void SaveGeometry(); void LoadSettings();
void SaveSettings();
bool CanControlCore(); bool CanControlCore();
bool CanResetCore(); bool CanResetCore();
void closeEvent(QCloseEvent* event) override; void closeEvent(QCloseEvent* event) override;
void contextMenuEvent(QContextMenuEvent* event) override; void contextMenuEvent(QContextMenuEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
void paintEvent(QPaintEvent* event) override; void paintEvent(QPaintEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override;