Return correct hit-test values for title bar buttons on Windows (#4994)

Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
nerix
2023-12-03 14:41:33 +01:00
committed by GitHub
parent 584a7c86fc
commit 812186dc4c
8 changed files with 381 additions and 38 deletions
+35
View File
@@ -124,4 +124,39 @@ void TitleBarButton::paintEvent(QPaintEvent *event)
this->paintButton(painter);
}
void TitleBarButton::ncEnter()
{
this->enterEvent(nullptr);
this->update();
}
void TitleBarButton::ncLeave()
{
this->leaveEvent(nullptr);
this->update();
}
void TitleBarButton::ncMove(QPoint at)
{
QMouseEvent evt(QMouseEvent::MouseMove, at, Qt::NoButton, Qt::NoButton,
Qt::NoModifier);
this->mouseMoveEvent(&evt);
}
void TitleBarButton::ncMousePress(QPoint at)
{
QMouseEvent evt(QMouseEvent::MouseButtonPress, at, Qt::LeftButton,
Qt::NoButton, Qt::NoModifier);
this->mousePressEvent(&evt);
this->update();
}
void TitleBarButton::ncMouseRelease(QPoint at)
{
QMouseEvent evt(QMouseEvent::MouseButtonRelease, at, Qt::LeftButton,
Qt::NoButton, Qt::NoModifier);
this->mouseReleaseEvent(&evt);
this->update();
}
} // namespace chatterino
+18
View File
@@ -23,6 +23,24 @@ public:
TitleBarButtonStyle getButtonStyle() const;
void setButtonStyle(TitleBarButtonStyle style_);
/// Simulate a `mouseEnter` event.
void ncEnter();
/// Simulate a `mouseLeave` event.
void ncLeave();
/// Simulate a `mouseMove` event.
/// @param at a local position relative to this widget
void ncMove(QPoint at);
/// Simulate a `mousePress` event with the left mouse button.
/// @param at a local position relative to this widget
void ncMousePress(QPoint at);
/// Simulate a `mouseRelease` event with the left mouse button.
/// @param at a local position relative to this widget
void ncMouseRelease(QPoint at);
protected:
void paintEvent(QPaintEvent *) override;
+116
View File
@@ -0,0 +1,116 @@
#include "widgets/helper/TitlebarButtons.hpp"
#ifdef USEWINSDK
# include "widgets/helper/TitlebarButton.hpp"
# include <Windows.h>
# include <cassert>
namespace chatterino {
TitleBarButtons::TitleBarButtons(QWidget *window, TitleBarButton *minButton,
TitleBarButton *maxButton,
TitleBarButton *closeButton)
: QObject(window)
, window_(window)
, minButton_(minButton)
, maxButton_(maxButton)
, closeButton_(closeButton)
{
}
void TitleBarButtons::hover(size_t ht, QPoint at)
{
TitleBarButton *hovered{};
TitleBarButton *other1{};
TitleBarButton *other2{};
switch (ht)
{
case HTMAXBUTTON:
hovered = this->maxButton_;
other1 = this->minButton_;
other2 = this->closeButton_;
break;
case HTMINBUTTON:
hovered = this->minButton_;
other1 = this->maxButton_;
other2 = this->closeButton_;
break;
case HTCLOSE:
hovered = this->closeButton_;
other1 = this->minButton_;
other2 = this->maxButton_;
break;
default:
assert(false && "TitleBarButtons::hover precondition violated");
return;
}
hovered->ncEnter();
hovered->ncMove(hovered->mapFromGlobal(at));
other1->ncLeave();
other2->ncLeave();
}
void TitleBarButtons::leave()
{
this->minButton_->ncLeave();
this->maxButton_->ncLeave();
this->closeButton_->ncLeave();
}
void TitleBarButtons::mousePress(size_t ht, QPoint at)
{
auto *button = this->buttonForHt(ht);
button->ncMousePress(button->mapFromGlobal(at));
}
void TitleBarButtons::mouseRelease(size_t ht, QPoint at)
{
auto *button = this->buttonForHt(ht);
button->ncMouseRelease(button->mapFromGlobal(at));
}
void TitleBarButtons::updateMaxButton()
{
this->maxButton_->setButtonStyle(
this->window_->windowState().testFlag(Qt::WindowMaximized)
? TitleBarButtonStyle::Unmaximize
: TitleBarButtonStyle::Maximize);
}
void TitleBarButtons::setSmallSize()
{
this->minButton_->setScaleIndependantSize(30, 30);
this->maxButton_->setScaleIndependantSize(30, 30);
this->closeButton_->setScaleIndependantSize(30, 30);
}
void TitleBarButtons::setRegularSize()
{
this->minButton_->setScaleIndependantSize(46, 30);
this->maxButton_->setScaleIndependantSize(46, 30);
this->closeButton_->setScaleIndependantSize(46, 30);
}
TitleBarButton *TitleBarButtons::buttonForHt(size_t ht) const
{
switch (ht)
{
case HTMAXBUTTON:
return this->maxButton_;
case HTMINBUTTON:
return this->minButton_;
case HTCLOSE:
return this->closeButton_;
default:
assert(false &&
"TitleBarButtons::buttonForHt precondition violated");
return nullptr;
}
}
} // namespace chatterino
#endif
+69
View File
@@ -0,0 +1,69 @@
#pragma once
class QPoint;
class QWidget;
#include <QtGlobal>
namespace chatterino {
#ifdef USEWINSDK
class TitleBarButton;
class TitleBarButtons : QObject
{
public:
/// The parent of this object is set to `window`.
///
/// All parameters must have a parent;
/// they're not deleted in the destructor.
TitleBarButtons(QWidget *window, TitleBarButton *minButton,
TitleBarButton *maxButton, TitleBarButton *closeButton);
/// Hover over the button `ht` at the global position `at`.
///
/// @pre `ht` must be one of { HTMAXBUTTON, HTMINBUTTON, HTCLOSE }.
/// @param ht The hovered button
/// @param at The global position of the event
void hover(size_t ht, QPoint at);
/// Leave all buttons - simulate `leaveEvent` for all buttons.
void leave();
/// Press the left mouse over the button `ht` at the global position `at`.
///
/// @pre `ht` must be one of { HTMAXBUTTON, HTMINBUTTON, HTCLOSE }.
/// @param ht The clicked button
/// @param at The global position of the event
void mousePress(size_t ht, QPoint at);
/// Release the left mouse button over the button `ht` at the
/// global position `at`.
///
/// @pre `ht` must be one of { HTMAXBUTTON, HTMINBUTTON, HTCLOSE }.
/// @param ht The clicked button
/// @param at The global position of the event
void mouseRelease(size_t ht, QPoint at);
/// Update the maximize/restore button to show the correct image
/// according to the current window state.
void updateMaxButton();
/// Set buttons to be narrow.
void setSmallSize();
/// Set buttons to be regular size.
void setRegularSize();
private:
/// @pre ht must be one of { HTMAXBUTTON, HTMINBUTTON, HTCLOSE }.
TitleBarButton *buttonForHt(size_t ht) const;
QWidget *window_ = nullptr;
TitleBarButton *minButton_ = nullptr;
TitleBarButton *maxButton_ = nullptr;
TitleBarButton *closeButton_ = nullptr;
};
#endif
} // namespace chatterino