Commit c9cfd840 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii

Check against QRect whether pointer is inside DecorationButton

Summary:
If several buttons share an edge, i.e. spacing between decoration
buttons is set to 0, and the pointer is on that edge, both buttons will
be hovered.

This happens because QRectF::contains returns true for points that are
on "outer" edges, e.g.

    QRectF rect(0, 0, 10, 10);
    rect.contains(QPointF(10, 5)); // returns true

Test Plan: Ran tests.

Reviewers: #kwin, davidedmundson

Reviewed By: #kwin, davidedmundson

Subscribers: davidedmundson, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D15226
parent 42a3bae3
......@@ -60,6 +60,8 @@ private Q_SLOTS:
void testMenuDoubleClick();
void testMenuPressAndHold();
void testApplicationMenu();
void testContains_data();
void testContains();
};
void DecorationButtonTest::testButton()
......@@ -1342,5 +1344,36 @@ void DecorationButtonTest::testApplicationMenu()
QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
}
void DecorationButtonTest::testContains_data()
{
QTest::addColumn<QPointF>("pos");
QTest::addColumn<bool>("contains");
// Button geometry: QRectF(0, 0, 10, 10).
QTest::newRow("on left edge") << QPointF(0, 5) << true;
QTest::newRow("on top edge") << QPointF(5, 0) << true;
QTest::newRow("on right edge") << QPointF(9, 5) << true;
QTest::newRow("on bottom edge") << QPointF(5, 9) << true;
QTest::newRow("inside") << QPointF(5, 5) << true;
QTest::newRow("outside 1") << QPointF(-1, 5) << false;
QTest::newRow("outside 2") << QPointF(5, -1) << false;
QTest::newRow("outside 3") << QPointF(10, 5) << false;
QTest::newRow("outside 4") << QPointF(5, 10) << false;
}
void DecorationButtonTest::testContains()
{
MockBridge bridge;
MockDecoration mockDecoration(&bridge);
MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
button.setGeometry(QRectF(0, 0, 10, 10));
button.setEnabled(true);
button.setVisible(true);
QFETCH(QPointF, pos);
QTEST(button.contains(pos), "contains");
}
QTEST_MAIN(DecorationButtonTest)
#include "decorationbuttontest.moc"
......@@ -330,7 +330,7 @@ void Decoration::hoverMoveEvent(QHoverEvent *event)
continue;
}
const bool hovered = button->isHovered();
const bool contains = button->geometry().contains(event->pos());
const bool contains = button->contains(event->posF());
if (!hovered && contains) {
QHoverEvent e(QEvent::HoverEnter, event->posF(), event->oldPosF(), event->modifiers());
QCoreApplication::instance()->sendEvent(button, &e);
......@@ -383,7 +383,7 @@ void Decoration::mouseReleaseEvent(QMouseEvent *event)
void Decoration::wheelEvent(QWheelEvent *event)
{
for (DecorationButton *button : d->buttons) {
if (button->geometry().contains(event->posF())) {
if (button->contains(event->posF())) {
QCoreApplication::instance()->sendEvent(button, event);
event->setAccepted(true);
}
......
......@@ -445,6 +445,11 @@ DELEGATE(setGeometry, geometry, const QRectF &)
#undef DELEGATE
bool DecorationButton::contains(const QPointF &pos) const
{
return d->geometry.toRect().contains(pos.toPoint());
}
bool DecorationButton::event(QEvent *event)
{
switch (event->type()) {
......@@ -476,7 +481,7 @@ bool DecorationButton::event(QEvent *event)
void DecorationButton::hoverEnterEvent(QHoverEvent *event)
{
if (!d->enabled || !d->visible || !d->geometry.contains(event->posF())) {
if (!d->enabled || !d->visible || !contains(event->posF())) {
return;
}
d->setHovered(true);
......@@ -485,7 +490,7 @@ void DecorationButton::hoverEnterEvent(QHoverEvent *event)
void DecorationButton::hoverLeaveEvent(QHoverEvent *event)
{
if (!d->enabled || !d->visible || !d->hovered || d->geometry.contains(event->posF())) {
if (!d->enabled || !d->visible || !d->hovered || contains(event->posF())) {
return;
}
d->setHovered(false);
......@@ -502,7 +507,7 @@ void DecorationButton::mouseMoveEvent(QMouseEvent *event)
if (!d->enabled || !d->visible || !d->hovered) {
return;
}
if (!d->geometry.contains(event->localPos())) {
if (!contains(event->localPos())) {
d->setHovered(false);
event->setAccepted(true);
}
......@@ -510,7 +515,7 @@ void DecorationButton::mouseMoveEvent(QMouseEvent *event)
void DecorationButton::mousePressEvent(QMouseEvent *event)
{
if (!d->enabled || !d->visible || !d->geometry.contains(event->localPos()) || !d->acceptedButtons.testFlag(event->button())) {
if (!d->enabled || !d->visible || !contains(event->localPos()) || !d->acceptedButtons.testFlag(event->button())) {
return;
}
d->setPressed(event->button(), true);
......@@ -533,7 +538,7 @@ void DecorationButton::mouseReleaseEvent(QMouseEvent *event)
if (!d->enabled || !d->visible || !d->isPressed(event->button())) {
return;
}
if (d->geometry.contains(event->localPos())) {
if (contains(event->localPos())) {
if (!d->pressAndHold || event->button() != Qt::LeftButton) {
emit clicked(event->button());
} else {
......
......@@ -113,6 +113,11 @@ public:
bool isCheckable() const;
DecorationButtonType type() const;
/**
* Returns @c true if @p pos is inside of the button, otherwise returns @c false.
**/
bool contains(const QPointF &pos) const;
Qt::MouseButtons acceptedButtons() const;
void setAcceptedButtons(Qt::MouseButtons buttons);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment