Skip to content

Commit

Permalink
libgestures/condition: remove params from constructor, create setters…
Browse files Browse the repository at this point in the history
…, simplify tests
  • Loading branch information
taj-ny committed Oct 16, 2024
1 parent 11a5dc8 commit 3829b7e
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 166 deletions.
14 changes: 7 additions & 7 deletions src/kwin/config/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ std::vector<Condition> Config::readConditions(const KConfigGroup &group, std::sh
{
const auto conditionGroup = group.group(conditionGroupName);

const bool negate = conditionGroup.readEntry("Negate", false);
Condition condition(windowDataProvider);
condition.setNegate(conditionGroup.readEntry("Negate", false));

std::optional<QRegularExpression> windowClassRegex;
const auto windowClassRegexStr = conditionGroup.readEntry("WindowClassRegex", "");
if (windowClassRegexStr != "")
windowClassRegex = QRegularExpression(windowClassRegexStr);
const auto windowClassRegex = conditionGroup.readEntry("WindowClassRegex", "");
if (windowClassRegex != "")
condition.setWindowClassRegex(QRegularExpression(windowClassRegex));

auto windowState = WindowState::Unimportant;
std::optional<WindowState> windowStateOpt;
Expand All @@ -162,9 +162,9 @@ std::vector<Condition> Config::readConditions(const KConfigGroup &group, std::sh
windowState = windowState | WindowState::Maximized;
}
if (windowState)
windowStateOpt = windowState;
condition.setWindowState(windowState);

conditions.emplace_back(windowDataProvider, negate, windowClassRegex, windowStateOpt);
conditions.push_back(condition);
}

return conditions;
Expand Down
56 changes: 39 additions & 17 deletions src/libgestures/condition.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
#include "condition.h"

Condition::Condition(std::shared_ptr<WindowDataProvider> windowDataProvider, bool negate, std::optional<QRegularExpression> windowClassRegex, std::optional<WindowState> windowState)
: m_windowDataProvider(windowDataProvider),
m_negate(negate),
m_windowClassRegex(std::move(windowClassRegex)),
m_windowState(windowState)
Condition::Condition(std::shared_ptr<WindowDataProvider> windowDataProvider)
: m_windowDataProvider(windowDataProvider)
{
}

Expand All @@ -14,19 +11,44 @@ bool Condition::isSatisfied() const
if (!windowData)
return false;

if ((m_windowClassRegex && !m_windowClassRegex.value().pattern().isEmpty())
&& !(m_windowClassRegex.value().match(windowData->resourceClass()).hasMatch()
|| m_windowClassRegex.value().match(windowData->resourceName()).hasMatch()))
return m_negate;
return isWindowClassRegexSubConditionSatisfied(windowData.value())
&& isWindowStateSubConditionSatisfied(windowData.value());
}

void Condition::setNegate(const bool &negate)
{
m_negate = negate;
}

if (m_windowState) {
bool satisfiesFullscreen = (m_windowState.value() & WindowState::Fullscreen) && (windowData->state() & WindowState::Fullscreen);
bool satisfiesMaximized = (m_windowState.value() & WindowState::Maximized) && (windowData->state() & WindowState::Maximized);
void Condition::setWindowClassRegex(const QRegularExpression &windowClassRegex)
{
m_windowClassRegex = windowClassRegex;
}

return m_negate
? (!satisfiesFullscreen && !satisfiesMaximized)
: (satisfiesFullscreen || satisfiesMaximized);
}
void Condition::setWindowState(const WindowState &windowState)
{
m_windowState = windowState;
}

bool Condition::isWindowClassRegexSubConditionSatisfied(const WindowData &data) const
{
if (!m_windowClassRegex || m_windowClassRegex->pattern().isEmpty())
return true;

if (m_windowClassRegex.value().match(data.resourceClass()).hasMatch()
|| m_windowClassRegex.value().match(data.resourceName()).hasMatch())
return !m_negate;

return m_negate;
}

bool Condition::isWindowStateSubConditionSatisfied(const WindowData &data) const
{
if (!m_windowState)
return true;

return !m_negate;
const bool satisfied =
((m_windowState.value() & WindowState::Fullscreen) && (data.state() & WindowState::Fullscreen))
|| ((m_windowState.value() & WindowState::Maximized) && (data.state() & WindowState::Maximized));
return m_negate == !satisfied;
}
18 changes: 13 additions & 5 deletions src/libgestures/condition.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,24 @@
#include <QRegularExpression>
#include "windowdataprovider.h"


class Condition
{
public:
Condition(std::shared_ptr<WindowDataProvider> windowDataProvider, bool negate, std::optional<QRegularExpression> windowClassRegex, std::optional<WindowState> windowState);
explicit Condition(std::shared_ptr<WindowDataProvider> windowDataProvider);

bool isSatisfied() const;

void setNegate(const bool &negate);
void setWindowClassRegex(const QRegularExpression &windowClassRegex);
void setWindowState(const WindowState &windowState);
private:
bool isWindowClassRegexSubConditionSatisfied(const WindowData &data) const;
bool isWindowStateSubConditionSatisfied(const WindowData &data) const;

const std::shared_ptr<WindowDataProvider> m_windowDataProvider;
const bool m_negate;
const std::optional<QRegularExpression> m_windowClassRegex;
const std::optional<WindowState> m_windowState;
bool m_negate = false;
std::optional<QRegularExpression> m_windowClassRegex = std::nullopt;
std::optional<WindowState> m_windowState = std::nullopt;

friend class TestCondition;
};
174 changes: 62 additions & 112 deletions tests/libgestures/test_condition.cpp
Original file line number Diff line number Diff line change
@@ -1,162 +1,112 @@
#include "condition.h"
#include "test_condition.h"

TestCondition::TestCondition()
: m_noActiveWindow(std::make_shared<MockWindowDataProvider>(std::nullopt)),
m_normalWindow(std::make_shared<MockWindowDataProvider>(std::make_optional<WindowData>("Firefox", "firefox", "firefox", WindowState::Unimportant))),
m_maximizedWindow(std::make_shared<MockWindowDataProvider>(std::make_optional<WindowData>("Firefox", "firefox", "firefox", WindowState::Maximized))),
m_fullscreenWindow(std::make_shared<MockWindowDataProvider>(std::make_optional<WindowData>("Firefox", "firefox", "firefox", WindowState::Maximized)))
void TestCondition::init()
{
m_condition = std::make_shared<Condition>(m_normalWindowProvider);
}

void TestCondition::isSatisfied_noActiveWindow_returnsFalse()
{
const auto condition = std::make_shared<Condition>(m_noActiveWindow, false, std::nullopt, std::nullopt);

QVERIFY(!condition->isSatisfied());
}

void TestCondition::isSatisfied_negatedAndNoActiveWindow_returnsFalse()
{
const auto condition = std::make_shared<Condition>(m_noActiveWindow, true, std::nullopt, std::nullopt);

QVERIFY(!condition->isSatisfied());
QVERIFY(!Condition(m_noActiveWindowProvider).isSatisfied());
}

void TestCondition::isSatisfied_noSubConditions_returnsTrue()
{
const auto condition = std::make_shared<Condition>(m_normalWindow, false, std::nullopt, std::nullopt);

QVERIFY(condition->isSatisfied());
}

void TestCondition::isSatisfied_negatedAndNoSubConditions_returnsFalse()
{
const auto condition = std::make_shared<Condition>(m_normalWindow, true, std::nullopt, std::nullopt);

QVERIFY(!condition->isSatisfied());
}

void TestCondition::isSatisfied_windowClassRegexMatchesResourceClass_returnsTrue()
{
const auto window = std::make_shared<MockWindowDataProvider>(std::make_optional<WindowData>("Firefox", "firefox", "", WindowState::Unimportant));
const auto condition = std::make_shared<Condition>(window, false, QRegularExpression("firefox"), std::nullopt);

QVERIFY(condition->isSatisfied());
}

void TestCondition::isSatisfied_windowClassRegexMatchesResourceName_returnsTrue()
{
const auto window = std::make_shared<MockWindowDataProvider>(std::make_optional<WindowData>("Firefox", "", "firefox", WindowState::Unimportant));
const auto condition = std::make_shared<Condition>(window, false, QRegularExpression("firefox"), std::nullopt);

QVERIFY(condition->isSatisfied());
}

void TestCondition::isSatisfied_windowClassRegexDoesntMatch_returnsFalse()
{
const auto condition = std::make_shared<Condition>(m_normalWindow, false, QRegularExpression("firefoxx"), std::nullopt);

QVERIFY(!condition->isSatisfied());
QVERIFY(Condition(m_normalWindowProvider).isSatisfied());
}

void TestCondition::isSatisfied_negatedAndWindowClassRegexMatches_returnsFalse()
void TestCondition::isSatisfied_negatedAndNoSubConditions_returnsTrue()
{
const auto window = std::make_shared<MockWindowDataProvider>(std::make_optional<WindowData>("Firefox", "firefox", "", WindowState::Unimportant));
const auto condition = std::make_shared<Condition>(window, true, QRegularExpression("firefox"), std::nullopt);
m_condition->setNegate(true);

QVERIFY(!condition->isSatisfied());
QVERIFY(m_condition->isSatisfied());
}

void TestCondition::isSatisfied_negatedAndWindowClassRegexDoesntMatch_returnsTrue()
void TestCondition::isWindowClassRegexSubConditionSatisfied_subConditionNotSet_returnsTrue()
{
const auto condition = std::make_shared<Condition>(m_normalWindow, true, QRegularExpression("firefoxx"), std::nullopt);

QVERIFY(condition->isSatisfied());
QVERIFY(m_condition->isWindowClassRegexSubConditionSatisfied(m_normalWindow));
}

void TestCondition::isSatisfied_windowStateDoesntMatch_returnsFalse()
void TestCondition::isWindowClassRegexSubConditionSatisfied_negatedAndSubConditionNotSet_returnsTrue()
{
const auto condition = std::make_shared<Condition>(m_normalWindow, false, std::nullopt, WindowState::Maximized);
m_condition->setNegate(true);

QVERIFY(!condition->isSatisfied());
QVERIFY(m_condition->isWindowClassRegexSubConditionSatisfied(m_normalWindow));
}

void TestCondition::isSatisfied_windowStateMatches_returnsTrue()
void TestCondition::isWindowClassRegexSubConditionSatisfied_data()
{
const auto condition = std::make_shared<Condition>(m_maximizedWindow, false, std::nullopt, WindowState::Maximized);
QTest::addColumn<bool>("negate");
QTest::addColumn<QString>("regex");
QTest::addColumn<QString>("resourceClass");
QTest::addColumn<QString>("resourceName");
QTest::addColumn<bool>("result");

QVERIFY(condition->isSatisfied());
QTest::newRow("resource class only") << false << s_windowClass << s_windowClass << "" << true;
QTest::newRow("resource name only") << false << s_windowClass << "" << s_windowClass << true;
QTest::newRow("no match") << false << s_windowClass << "" << "" << false;
QTest::newRow("negated match") << true << s_windowClass << s_windowClass << s_windowClass << false;
QTest::newRow("negated no match") << true << s_windowClass << "" << "" << true;
}

void TestCondition::isSatisfied_windowStateMatchesEither_returnsTrue()
void TestCondition::isWindowClassRegexSubConditionSatisfied()
{
const auto condition = std::make_shared<Condition>(m_maximizedWindow, false, std::nullopt, WindowState::Fullscreen | WindowState::Maximized);

QVERIFY(condition->isSatisfied());
}
QFETCH(bool, negate);
QFETCH(QString, regex);
QFETCH(QString, resourceClass);
QFETCH(QString, resourceName);
QFETCH(bool, result);
const WindowData windowData(s_windowCaption, resourceClass, resourceName, WindowState::Unimportant);

void TestCondition::isSatisfied_negatedAndWindowStateDoesntMatch_returnsTrue()
{
const auto condition = std::make_shared<Condition>(m_normalWindow, true, std::nullopt, WindowState::Maximized);
m_condition->setNegate(negate);
m_condition->setWindowClassRegex(QRegularExpression(regex));

QVERIFY(condition->isSatisfied());
QCOMPARE(m_condition->isWindowClassRegexSubConditionSatisfied(windowData), result);
}

void TestCondition::isSatisfied_negatedAndWindowStateMatches_returnsFalse()
void TestCondition::isWindowStateSubConditionSatisfied_subConditionNotSet_returnsTrue()
{
const auto condition = std::make_shared<Condition>(m_maximizedWindow, true, std::nullopt, WindowState::Maximized);

QVERIFY(!condition->isSatisfied());
QVERIFY(m_condition->isWindowStateSubConditionSatisfied(m_normalWindow));
}

void TestCondition::isSatisfied_negatedAndWindowStateMatchesEither_returnsFalse()
void TestCondition::isWindowStateSubConditionSatisfied_negatedAndSubConditionNotSet_returnsTrue()
{
const auto condition = std::make_shared<Condition>(m_maximizedWindow, true, std::nullopt, WindowState::Fullscreen | WindowState::Maximized);
m_condition->setNegate(true);

QVERIFY(!condition->isSatisfied());
QVERIFY(m_condition->isWindowStateSubConditionSatisfied(m_normalWindow));
}

void TestCondition::isSatisfied_windowClassMatchesAndStateDoesnt_returnsFalse()
void TestCondition::isWindowStateSubConditionSatisfied_data()
{
const auto condition = std::make_shared<Condition>(m_normalWindow, false, QRegularExpression("firefox"), WindowState::Maximized);
QTest::addColumn<bool>("negate");
QTest::addColumn<int>("conditionWindowState");
QTest::addColumn<int>("windowState");
QTest::addColumn<bool>("result");

QVERIFY(!condition->isSatisfied());
QTest::newRow("matches one") << false << static_cast<int>(WindowState::Maximized)
<< static_cast<int>(WindowState::Maximized) << true;
QTest::newRow("matches all") << false << static_cast<int>(WindowState::Maximized | WindowState::Fullscreen)
<< static_cast<int>(WindowState::Maximized | WindowState::Fullscreen) << true;
QTest::newRow("no match") << false << static_cast<int>(WindowState::Maximized) << static_cast<int>(WindowState::Fullscreen) << false;
QTest::newRow("negated matches one") << true << static_cast<int>(WindowState::Maximized)
<< static_cast<int>(WindowState::Maximized) << false;
QTest::newRow("negated matches all") << true << static_cast<int>(WindowState::Maximized | WindowState::Fullscreen)
<< static_cast<int>(WindowState::Maximized | WindowState::Fullscreen) << false;
QTest::newRow("negated no match") << true << static_cast<int>(WindowState::Maximized) << static_cast<int>(WindowState::Fullscreen) << true;
}

void TestCondition::isSatisfied_windowClassDoesntMatchAndStateDoes_returnsFalse()
void TestCondition::isWindowStateSubConditionSatisfied()
{
const auto condition = std::make_shared<Condition>(m_maximizedWindow, false, QRegularExpression("firefoxx"), WindowState::Maximized);
QFETCH(bool, negate);
QFETCH(int, conditionWindowState);
QFETCH(int, windowState);
QFETCH(bool, result);
const WindowData windowData(s_windowCaption, s_windowClass, s_windowClass, static_cast<WindowState>(windowState));

QVERIFY(!condition->isSatisfied());
}

void TestCondition::isSatisfied_windowClassMatchesAndStateMatches_returnsTrue()
{
const auto condition = std::make_shared<Condition>(m_maximizedWindow, false, QRegularExpression("firefox"), WindowState::Maximized);

QVERIFY(condition->isSatisfied());
}

void TestCondition::isSatisfied_negatedAndWindowClassMatchesAndStateDoesnt_returnsTrue()
{
const auto condition = std::make_shared<Condition>(m_normalWindow, true, QRegularExpression("firefox"), WindowState::Maximized);

QVERIFY(condition->isSatisfied());
}

void TestCondition::isSatisfied_negatedAndWindowClassDoesntMatchAndStateDoes_returnsTrue()
{
const auto condition = std::make_shared<Condition>(m_maximizedWindow, true, QRegularExpression("firefoxx"), WindowState::Maximized);

QVERIFY(condition->isSatisfied());
}

void TestCondition::isSatisfied_negatedAndWindowClassMatchesAndStateMatches_returnsFalse()
{
const auto condition = std::make_shared<Condition>(m_maximizedWindow, true, QRegularExpression("firefox"), WindowState::Maximized);
m_condition->setNegate(negate);
m_condition->setWindowState(static_cast<WindowState>(conditionWindowState));

QVERIFY(!condition->isSatisfied());
QCOMPARE(m_condition->isWindowStateSubConditionSatisfied(windowData), result);
}

QTEST_MAIN(TestCondition)
Expand Down
Loading

0 comments on commit 3829b7e

Please sign in to comment.