Allow to use a window without titlebar

This might look better than a popup on Windows 11 because we'd still get
the round window corners.
This commit is contained in:
Martchus 2023-02-18 21:27:09 +01:00
parent 5bf8a4e25a
commit 1b72e61c86
7 changed files with 68 additions and 22 deletions

View File

@ -19,7 +19,7 @@ namespace QtGui {
TrayMenu::TrayMenu(TrayIcon *trayIcon, QWidget *parent)
: QMenu(parent)
, m_trayIcon(trayIcon)
, m_windowed(false)
, m_windowType(WindowType::Popup)
{
setObjectName(QStringLiteral("QtGui::TrayMenu"));
auto *const menuLayout = new QHBoxLayout;
@ -68,23 +68,50 @@ void TrayMenu::showUsingPositioningSettings()
activateWindow();
}
void TrayMenu::setWindowed(bool windowed)
void TrayMenu::setWindowType(int windowType)
{
if (m_windowed != windowed) {
setWindowFlags((m_windowed = windowed) ? Qt::Window : Qt::FramelessWindowHint | Qt::Popup);
if (windowType >= 0 && windowType <= 2) {
setWindowType(static_cast<WindowType>(windowType));
}
}
void TrayMenu::setWindowType(WindowType windowType)
{
if (m_windowType == windowType) {
return;
}
auto flags = Qt::WindowFlags();
switch (m_windowType = windowType) {
case WindowType::Popup:
flags = Qt::FramelessWindowHint | Qt::Popup;
break;
case WindowType::NormalWindow:
flags = Qt::Window;
break;
case WindowType::CustomWindow:
flags = Qt::Dialog | Qt::CustomizeWindowHint;
break;
}
setWindowFlags(flags);
}
void TrayMenu::mousePressEvent(QMouseEvent *event)
{
if (!m_windowed) {
if (m_windowType != TrayMenu::WindowType::NormalWindow) {
QMenu::mousePressEvent(event);
}
}
void TrayMenu::mouseReleaseEvent(QMouseEvent *event)
{
if (m_windowType != TrayMenu::WindowType::NormalWindow) {
QMenu::mouseReleaseEvent(event);
}
}
void TrayMenu::paintEvent(QPaintEvent *event)
{
if (!m_windowed) {
if (m_windowType == WindowType::Popup) {
QMenu::paintEvent(event);
} else {
QPainter(this).fillRect(event->rect(), palette().window());
@ -92,10 +119,13 @@ void TrayMenu::paintEvent(QPaintEvent *event)
}
}
void TrayMenu::mouseReleaseEvent(QMouseEvent *event)
void TrayMenu::focusOutEvent(QFocusEvent *)
{
if (!m_windowed) {
QMenu::mouseReleaseEvent(event);
if (m_windowType == WindowType::CustomWindow) {
if (const auto *fw = focusWidget(); fw->hasFocus()) {
return;
}
close();
}
}

View File

@ -10,30 +10,37 @@ class TrayWidget;
class TrayMenu : public QMenu {
Q_OBJECT
Q_PROPERTY(bool windowed READ isWindowed WRITE setWindowed)
public:
enum class WindowType {
Popup,
NormalWindow,
CustomWindow,
};
explicit TrayMenu(TrayIcon *trayIcon = nullptr, QWidget *parent = nullptr);
QSize sizeHint() const override;
TrayWidget &widget();
const TrayWidget &widget() const;
TrayIcon *icon();
bool isWindowed() const;
WindowType windowType() const;
void setWindowType(int windowType);
void setWindowType(WindowType windowType);
public Q_SLOTS:
void showUsingPositioningSettings();
void setWindowed(bool windowed);
protected:
void mouseReleaseEvent(QMouseEvent *) override;
void mousePressEvent(QMouseEvent *) override;
void paintEvent(QPaintEvent *) override;
void focusOutEvent(QFocusEvent *) override;
private:
TrayWidget *m_trayWidget;
TrayIcon *m_trayIcon;
bool m_windowed = false;
WindowType m_windowType;
};
inline TrayWidget &TrayMenu::widget()
@ -51,9 +58,9 @@ inline TrayIcon *TrayMenu::icon()
return m_trayIcon;
}
inline bool TrayMenu::isWindowed() const
inline TrayMenu::WindowType TrayMenu::windowType() const
{
return m_windowed;
return m_windowType;
}
} // namespace QtGui

View File

@ -596,7 +596,7 @@ void TrayWidget::applySettings(const QString &connectionConfig)
}
}
if (m_menu) {
m_menu->setWindowed(settings.appearance.windowed);
m_menu->setWindowType(settings.appearance.windowType);
}
// update status icon and text of tray icon because reconnect interval might have changed
@ -934,7 +934,7 @@ void TrayWidget::concludeWizard(const QString &errorMessage)
void TrayWidget::showDialog(QWidget *dlg, bool maximized)
{
if (m_menu && !m_menu->isWindowed()) {
if (m_menu && m_menu->windowType() != TrayMenu::WindowType::NormalWindow) {
m_menu->close();
}
if (maximized) {

View File

@ -383,6 +383,11 @@
<string>Normal window</string>
</property>
</item>
<item>
<property name="text">
<string>Window without titlebar</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">

View File

@ -347,7 +347,11 @@ bool restore()
auto &appearance = v.appearance;
appearance.showTraffic = settings.value(QStringLiteral("showTraffic"), appearance.showTraffic).toBool();
appearance.showTabTexts = settings.value(QStringLiteral("showTabTexts"), appearance.showTabTexts).toBool();
appearance.windowed = settings.value(QStringLiteral("windowed"), appearance.windowed).toBool();
if (auto windowType = settings.value(QStringLiteral("windowType")); windowType.isValid()) {
appearance.windowType = windowType.toInt();
} else if (auto windowed = settings.value(QStringLiteral("windowed")); windowed.isValid()) {
appearance.windowType = !windowed.toBool() ? 0 : 1;
}
appearance.trayMenuSize = settings.value(QStringLiteral("trayMenuSize"), appearance.trayMenuSize).toSize();
appearance.frameStyle = settings.value(QStringLiteral("frameStyle"), appearance.frameStyle).toInt();
appearance.tabPosition = settings.value(QStringLiteral("tabPos"), appearance.tabPosition).toInt();
@ -471,7 +475,7 @@ bool save()
const auto &appearance = v.appearance;
settings.setValue(QStringLiteral("showTraffic"), appearance.showTraffic);
settings.setValue(QStringLiteral("showTabTexts"), appearance.showTabTexts);
settings.setValue(QStringLiteral("windowed"), appearance.windowed);
settings.setValue(QStringLiteral("windowType"), appearance.windowType);
settings.setValue(QStringLiteral("trayMenuSize"), appearance.trayMenuSize);
settings.setValue(QStringLiteral("frameStyle"), appearance.frameStyle);
settings.setValue(QStringLiteral("tabPos"), appearance.tabPosition);

View File

@ -64,7 +64,7 @@ struct SYNCTHINGWIDGETS_EXPORT NotifyOn {
struct SYNCTHINGWIDGETS_EXPORT Appearance {
bool showTraffic = true;
bool showTabTexts = true;
bool windowed = false;
int windowType = 0; // corresponds to TrayMenu::WindowType
QSize trayMenuSize = QSize(575, 475);
int frameStyle = static_cast<int>(QFrame::NoFrame) | static_cast<int>(QFrame::Plain);
int tabPosition = QTabWidget::South;

View File

@ -465,7 +465,7 @@ bool AppearanceOptionPage::apply()
{
auto &v = values();
auto &settings = v.appearance;
settings.windowed = ui()->windowTypeComboBox->currentIndex() == 1;
settings.windowType = ui()->windowTypeComboBox->currentIndex();
settings.trayMenuSize.setWidth(ui()->widthSpinBox->value());
settings.trayMenuSize.setHeight(ui()->heightSpinBox->value());
settings.showTraffic = ui()->showTrafficCheckBox->isChecked();
@ -508,7 +508,7 @@ void AppearanceOptionPage::reset()
{
const auto &v = values();
const auto &settings = v.appearance;
ui()->windowTypeComboBox->setCurrentIndex(settings.windowed ? 1 : 0);
ui()->windowTypeComboBox->setCurrentIndex(settings.windowType);
ui()->widthSpinBox->setValue(settings.trayMenuSize.width());
ui()->heightSpinBox->setValue(settings.trayMenuSize.height());
ui()->showTrafficCheckBox->setChecked(settings.showTraffic);