mirror of
https://github.com/hyprwm/Hyprland
synced 2026-05-09 07:58:02 +02:00
desktop/rules: fix static rules and content type. (#13725)
Hopefully for the last time in a while. Also a lot easier to add in new static types with the recheck done in window map instead of the rule.
This commit is contained in:
parent
3fd2a95475
commit
94bd4123c6
5 changed files with 66 additions and 44 deletions
|
|
@ -647,31 +647,36 @@ static bool testWindowRuleWorkspaceEmpty() {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void testContentRules() {
|
||||
static bool testContentRules() {
|
||||
NLog::log("{}Testing content window rules", Colors::YELLOW);
|
||||
|
||||
// kill me PLEASE
|
||||
|
||||
OK(getFromSocket("/keyword windowrule match:class kitty_bitch, content game"));
|
||||
OK(getFromSocket("/keyword windowrule match:class kitty_content_string, content game"));
|
||||
OK(getFromSocket("/keyword windowrule match:class kitty_content_numbers, content 3"));
|
||||
OK(getFromSocket("/keyword windowrule match:content game, border_size 10"));
|
||||
OK(getFromSocket("/keyword windowrule match:content 3, opacity 0.5"));
|
||||
|
||||
getFromSocket("/dispatch workspace 420");
|
||||
const auto testProps = []() {
|
||||
EXPECT_CONTAINS(getFromSocket("/getprop active border_size"), "10");
|
||||
EXPECT_CONTAINS(getFromSocket("/getprop active opacity"), "0.5");
|
||||
};
|
||||
if (!spawnKitty("kitty_content_string"))
|
||||
return false;
|
||||
waitForActiveWindow("kitty_content_string");
|
||||
testProps();
|
||||
|
||||
if (!spawnKitty("kitty_bitch")) {
|
||||
NLog::log("{}Error: failed to spawn kitty", Colors::RED);
|
||||
return;
|
||||
}
|
||||
Tests::killAllWindows();
|
||||
EXPECT(Tests::windowCount(), 0);
|
||||
|
||||
{
|
||||
auto res = getFromSocket("/getprop active border_size");
|
||||
EXPECT_CONTAINS(res, "10");
|
||||
}
|
||||
if (!spawnKitty("kitty_content_numbers"))
|
||||
return false;
|
||||
waitForActiveWindow("kitty_content_numbers");
|
||||
testProps();
|
||||
|
||||
{
|
||||
auto res = getFromSocket("/getprop active opacity");
|
||||
EXPECT_CONTAINS(res, "0.5");
|
||||
}
|
||||
Tests::killAllWindows();
|
||||
EXPECT(Tests::windowCount(), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test() {
|
||||
|
|
|
|||
|
|
@ -547,9 +547,10 @@ CWindowRuleApplicator::SRuleResult CWindowRuleApplicator::applyStaticRule(const
|
|||
return SRuleResult{};
|
||||
}
|
||||
|
||||
void CWindowRuleApplicator::readStaticRules(bool preRead) {
|
||||
//
|
||||
bool CWindowRuleApplicator::readStaticRules(bool preRead) {
|
||||
if (!m_window)
|
||||
return;
|
||||
return false;
|
||||
|
||||
static_ = {};
|
||||
|
||||
|
|
@ -575,36 +576,36 @@ void CWindowRuleApplicator::readStaticRules(bool preRead) {
|
|||
tagsWereChanged = tagsWereChanged || RES.tagsChanged;
|
||||
}
|
||||
|
||||
// recheck some props people might wanna use for static rules.
|
||||
std::underlying_type_t<eRuleProperty> propsToRecheck = RULE_PROP_NONE;
|
||||
// set a recheck for some props people might wanna use for static rules.
|
||||
if (tagsWereChanged)
|
||||
propsToRecheck |= RULE_PROP_TAG;
|
||||
if (static_.content != NContentType::CONTENT_TYPE_NONE)
|
||||
propsToRecheck |= RULE_PROP_CONTENT;
|
||||
|
||||
if (propsToRecheck != RULE_PROP_NONE) {
|
||||
for (const auto& r : ruleEngine()->rules()) {
|
||||
if (r->type() != RULE_TYPE_WINDOW)
|
||||
continue;
|
||||
|
||||
if (!(r->getPropertiesMask() & propsToRecheck))
|
||||
continue;
|
||||
|
||||
auto wr = reinterpretPointerCast<CWindowRule>(r);
|
||||
|
||||
if (!wr->matches(m_window.lock(), true))
|
||||
continue;
|
||||
|
||||
applyStaticRule(wr);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& wr : execRules) {
|
||||
applyStaticRule(wr);
|
||||
applyDynamicRule(wr);
|
||||
if (!preRead)
|
||||
ruleEngine()->unregisterRule(wr);
|
||||
}
|
||||
return (propsToRecheck != RULE_PROP_NONE);
|
||||
}
|
||||
|
||||
void CWindowRuleApplicator::recheckStaticRules() {
|
||||
for (const auto& r : ruleEngine()->rules()) {
|
||||
if (r->type() != RULE_TYPE_WINDOW)
|
||||
continue;
|
||||
|
||||
if (!(r->getPropertiesMask() & propsToRecheck))
|
||||
continue;
|
||||
|
||||
auto wr = reinterpretPointerCast<CWindowRule>(r);
|
||||
|
||||
if (!wr->matches(m_window.lock(), true))
|
||||
continue;
|
||||
|
||||
applyStaticRule(wr);
|
||||
}
|
||||
}
|
||||
|
||||
void CWindowRuleApplicator::propertiesChanged(std::underlying_type_t<eRuleProperty> props) {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ namespace Desktop::Rule {
|
|||
void propertiesChanged(std::underlying_type_t<eRuleProperty> props);
|
||||
std::unordered_set<CWindowRuleEffectContainer::storageType> resetProps(std::underlying_type_t<eRuleProperty> props,
|
||||
Types::eOverridePriority prio = Types::PRIORITY_WINDOW_RULE);
|
||||
void readStaticRules(bool preRead = false);
|
||||
bool readStaticRules(bool preRead = false);
|
||||
void recheckStaticRules();
|
||||
|
||||
// static props
|
||||
struct {
|
||||
|
|
@ -138,7 +139,8 @@ namespace Desktop::Rule {
|
|||
#undef DEFINE_PROP
|
||||
|
||||
private:
|
||||
PHLWINDOWREF m_window;
|
||||
PHLWINDOWREF m_window;
|
||||
std::underlying_type_t<eRuleProperty> propsToRecheck = RULE_PROP_NONE;
|
||||
|
||||
struct SRuleResult {
|
||||
bool needsRelayout = false;
|
||||
|
|
|
|||
|
|
@ -1719,8 +1719,7 @@ void CWindow::mapWindow() {
|
|||
requestedClientFSMode = FSMODE_FULLSCREEN;
|
||||
MONITORID requestedFSMonitor = m_wantsInitialFullscreenMonitor;
|
||||
|
||||
m_ruleApplicator->readStaticRules();
|
||||
{
|
||||
auto setStaticProps = [&]() {
|
||||
if (!m_ruleApplicator->static_.monitor.empty()) {
|
||||
const auto& MONITORSTR = m_ruleApplicator->static_.monitor;
|
||||
if (MONITORSTR == "unset")
|
||||
|
|
@ -1771,8 +1770,8 @@ void CWindow::mapWindow() {
|
|||
|
||||
if (m_ruleApplicator->static_.fullscreenStateClient || m_ruleApplicator->static_.fullscreenStateInternal) {
|
||||
requestedFSState = Desktop::View::SFullscreenState{
|
||||
.internal = sc<eFullscreenMode>(m_ruleApplicator->static_.fullscreenStateInternal.value_or(0)),
|
||||
.client = sc<eFullscreenMode>(m_ruleApplicator->static_.fullscreenStateClient.value_or(0)),
|
||||
.internal = sc<eFullscreenMode>(m_ruleApplicator->static_.fullscreenStateInternal.value_or(0)),
|
||||
.client = sc<eFullscreenMode>(m_ruleApplicator->static_.fullscreenStateClient.value_or(0)),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1846,6 +1845,13 @@ void CWindow::mapWindow() {
|
|||
|
||||
if (m_ruleApplicator->static_.noCloseFor)
|
||||
m_closeableSince = Time::steadyNow() + std::chrono::milliseconds(m_ruleApplicator->static_.noCloseFor.value());
|
||||
};
|
||||
|
||||
const bool recheck = m_ruleApplicator->readStaticRules();
|
||||
setStaticProps();
|
||||
if (recheck) {
|
||||
m_ruleApplicator->recheckStaticRules();
|
||||
setStaticProps();
|
||||
}
|
||||
|
||||
// make it uncloseable if it's a Hyprland dialog
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "ContentType.hpp"
|
||||
#include "debug/log/Logger.hpp"
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <drm_mode.h>
|
||||
#include <stdexcept>
|
||||
#include <format>
|
||||
|
||||
namespace NContentType {
|
||||
|
|
@ -8,6 +9,13 @@ namespace NContentType {
|
|||
{"none", CONTENT_TYPE_NONE}, {"photo", CONTENT_TYPE_PHOTO}, {"video", CONTENT_TYPE_VIDEO}, {"game", CONTENT_TYPE_GAME}};
|
||||
|
||||
eContentType fromString(const std::string name) {
|
||||
if (Hyprutils::String::isNumber(name)) {
|
||||
try {
|
||||
auto n = std::stoi(name);
|
||||
if (n >= 0 && n <= 3)
|
||||
return sc<eContentType>(n);
|
||||
} catch (std::exception& e) { Log::logger->log(Log::ERR, "NContentType::fromString: invalid number {}, need to be between 0 and 3", name); }
|
||||
}
|
||||
auto it = table.find(name);
|
||||
if (it != table.end())
|
||||
return it->second;
|
||||
|
|
@ -42,4 +50,4 @@ namespace NContentType {
|
|||
default: return DRM_MODE_CONTENT_TYPE_NO_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue