mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-05-19 08:30:22 -07:00
protocols: add xdg_toplevel_tag_v1 support
Adds a new windowrule to target windows by xdgTag, xdgtag:
This commit is contained in:
parent
55e953b383
commit
a4f7d7c594
@ -132,7 +132,7 @@ pkg_check_modules(
|
||||
xkbcommon
|
||||
uuid
|
||||
wayland-server>=1.22.90
|
||||
wayland-protocols>=1.41
|
||||
wayland-protocols>=1.43
|
||||
cairo
|
||||
pango
|
||||
pangocairo
|
||||
@ -382,6 +382,7 @@ protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false)
|
||||
protocolnew("staging/security-context" "security-context-v1" false)
|
||||
protocolnew("staging/content-type" "content-type-v1" false)
|
||||
protocolnew("staging/color-management" "color-management-v1" false)
|
||||
protocolnew("staging/xdg-toplevel-tag" "xdg-toplevel-tag-v1" false)
|
||||
|
||||
protocolwayland()
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
wayland_protos = dependency(
|
||||
'wayland-protocols',
|
||||
version: '>=1.41',
|
||||
version: '>=1.43',
|
||||
fallback: 'wayland-protocols',
|
||||
default_options: ['tests=false'],
|
||||
)
|
||||
@ -72,6 +72,7 @@ protocols = [
|
||||
wayland_protocol_dir / 'staging/security-context/security-context-v1.xml',
|
||||
wayland_protocol_dir / 'staging/content-type/content-type-v1.xml',
|
||||
wayland_protocol_dir / 'staging/color-management/color-management-v1.xml',
|
||||
wayland_protocol_dir / 'staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml',
|
||||
]
|
||||
|
||||
wl_protocols = []
|
||||
|
@ -1415,6 +1415,11 @@ std::vector<SP<CWindowRule>> CConfigManager::getMatchingRules(PHLWINDOW pWindow,
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"content:{}\" failed with: {}", rule->szContentType, e.what()); }
|
||||
}
|
||||
|
||||
if (!rule->szXdgTag.empty()) {
|
||||
if (pWindow->xdgTag().value_or("") != rule->szXdgTag)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!rule->szWorkspace.empty()) {
|
||||
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
||||
|
||||
@ -2407,6 +2412,7 @@ std::optional<std::string> CConfigManager::handleWindowRule(const std::string& c
|
||||
const auto FULLSCREENSTATEPOS = VALUE.find("fullscreenstate:");
|
||||
const auto ONWORKSPACEPOS = VALUE.find("onworkspace:");
|
||||
const auto CONTENTTYPEPOS = VALUE.find("content:");
|
||||
const auto XDGTAGPOS = VALUE.find("xdgTag:");
|
||||
|
||||
// find workspacepos that isn't onworkspacepos
|
||||
size_t WORKSPACEPOS = std::string::npos;
|
||||
@ -2419,8 +2425,8 @@ std::optional<std::string> CConfigManager::handleWindowRule(const std::string& c
|
||||
currentPos = VALUE.find("workspace:", currentPos + 1);
|
||||
}
|
||||
|
||||
const auto checkPos = std::unordered_set{TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS,
|
||||
FULLSCREENPOS, PINNEDPOS, FULLSCREENSTATEPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS, CONTENTTYPEPOS};
|
||||
const auto checkPos = std::unordered_set{TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS, FULLSCREENPOS,
|
||||
PINNEDPOS, FULLSCREENSTATEPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS, CONTENTTYPEPOS, XDGTAGPOS};
|
||||
if (checkPos.size() == 1 && checkPos.contains(std::string::npos)) {
|
||||
Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE);
|
||||
return "Invalid rulev2 syntax: " + VALUE;
|
||||
@ -2459,6 +2465,8 @@ std::optional<std::string> CConfigManager::handleWindowRule(const std::string& c
|
||||
min = FOCUSPOS;
|
||||
if (CONTENTTYPEPOS > pos && CONTENTTYPEPOS < min)
|
||||
min = CONTENTTYPEPOS;
|
||||
if (XDGTAGPOS > pos && XDGTAGPOS < min)
|
||||
min = XDGTAGPOS;
|
||||
|
||||
result = result.substr(0, min - pos);
|
||||
|
||||
@ -2520,6 +2528,9 @@ std::optional<std::string> CConfigManager::handleWindowRule(const std::string& c
|
||||
if (CONTENTTYPEPOS != std::string::npos)
|
||||
rule->szContentType = extract(CONTENTTYPEPOS + 8);
|
||||
|
||||
if (XDGTAGPOS != std::string::npos)
|
||||
rule->szXdgTag = extract(XDGTAGPOS + 8);
|
||||
|
||||
if (RULE == "unset") {
|
||||
std::erase_if(m_windowRules, [&](const auto& other) {
|
||||
if (!other->v2)
|
||||
|
@ -258,7 +258,9 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
||||
"tags": [{}],
|
||||
"swallowing": "0x{:x}",
|
||||
"focusHistoryID": {},
|
||||
"inhibitingIdle": {}
|
||||
"inhibitingIdle": {},
|
||||
"xdgTag": "{}",
|
||||
"xdgDescription": "{}"
|
||||
}},)#",
|
||||
(uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition->goal().x, (int)w->m_vRealPosition->goal().y,
|
||||
(int)w->m_vRealSize->goal().x, (int)w->m_vRealSize->goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
|
||||
@ -266,19 +268,21 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
||||
(int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass),
|
||||
escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"),
|
||||
(uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.get(),
|
||||
getFocusHistoryID(w), (g_pInputManager->isWindowInhibiting(w, false) ? "true" : "false"));
|
||||
getFocusHistoryID(w), (g_pInputManager->isWindowInhibiting(w, false) ? "true" : "false"), escapeJSONStrings(w->xdgTag().value_or("")),
|
||||
escapeJSONStrings(w->xdgDescription().value_or("")));
|
||||
} else {
|
||||
return std::format(
|
||||
"Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tpseudo: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: "
|
||||
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
||||
"{}\n\txwayland: {}\n\tpinned: "
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\tinhibitingIdle: {}\n\n",
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\tinhibitingIdle: {}\n\txdgTag: "
|
||||
"{}\n\txdgDescription: {}\n\n",
|
||||
(uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition->goal().x, (int)w->m_vRealPosition->goal().y,
|
||||
(int)w->m_vRealSize->goal().x, (int)w->m_vRealSize->goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
|
||||
(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle,
|
||||
w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal,
|
||||
(uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.get(), getFocusHistoryID(w),
|
||||
(int)g_pInputManager->isWindowInhibiting(w, false));
|
||||
(int)g_pInputManager->isWindowInhibiting(w, false), w->xdgTag().value_or(""), w->xdgDescription().value_or(""));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1808,3 +1808,17 @@ void CWindow::deactivateGroupMembers() {
|
||||
bool CWindow::isNotResponding() {
|
||||
return g_pANRManager->isNotResponding(m_pSelf.lock());
|
||||
}
|
||||
|
||||
std::optional<std::string> CWindow::xdgTag() {
|
||||
if (!m_pXDGSurface || !m_pXDGSurface->toplevel)
|
||||
return std::nullopt;
|
||||
|
||||
return m_pXDGSurface->toplevel->m_toplevelTag;
|
||||
}
|
||||
|
||||
std::optional<std::string> CWindow::xdgDescription() {
|
||||
if (!m_pXDGSurface || !m_pXDGSurface->toplevel)
|
||||
return std::nullopt;
|
||||
|
||||
return m_pXDGSurface->toplevel->m_toplevelDescription;
|
||||
}
|
||||
|
@ -407,6 +407,8 @@ class CWindow {
|
||||
void setContentType(NContentType::eContentType contentType);
|
||||
void deactivateGroupMembers();
|
||||
bool isNotResponding();
|
||||
std::optional<std::string> xdgTag();
|
||||
std::optional<std::string> xdgDescription();
|
||||
|
||||
CBox getWindowMainSurfaceBox() const {
|
||||
return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y};
|
||||
|
@ -37,7 +37,7 @@ class CWindowRule {
|
||||
RULE_WORKSPACE,
|
||||
RULE_PROP,
|
||||
RULE_CONTENT,
|
||||
RULE_PERSISTENTSIZE,
|
||||
RULE_PERSISTENTSIZE
|
||||
};
|
||||
|
||||
eRuleType ruleType = RULE_INVALID;
|
||||
@ -61,6 +61,7 @@ class CWindowRule {
|
||||
std::string szOnWorkspace = ""; // empty means any
|
||||
std::string szWorkspace = ""; // empty means any
|
||||
std::string szContentType = ""; // empty means any
|
||||
std::string szXdgTag = ""; // empty means any
|
||||
|
||||
// precompiled regexes
|
||||
CRuleRegexContainer rTitle;
|
||||
|
@ -49,7 +49,6 @@
|
||||
#include "../protocols/SecurityContext.hpp"
|
||||
#include "../protocols/CTMControl.hpp"
|
||||
#include "../protocols/HyprlandSurface.hpp"
|
||||
|
||||
#include "../protocols/core/Seat.hpp"
|
||||
#include "../protocols/core/DataDevice.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
@ -60,6 +59,7 @@
|
||||
#include "../protocols/XXColorManagement.hpp"
|
||||
#include "../protocols/FrogColorManagement.hpp"
|
||||
#include "../protocols/ContentType.hpp"
|
||||
#include "../protocols/XDGTag.hpp"
|
||||
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../render/Renderer.hpp"
|
||||
@ -182,6 +182,7 @@ CProtocolManager::CProtocolManager() {
|
||||
PROTO::ctm = makeUnique<CHyprlandCTMControlProtocol>(&hyprland_ctm_control_manager_v1_interface, 2, "CTMControl");
|
||||
PROTO::hyprlandSurface = makeUnique<CHyprlandSurfaceProtocol>(&hyprland_surface_manager_v1_interface, 2, "HyprlandSurface");
|
||||
PROTO::contentType = makeUnique<CContentTypeProtocol>(&wp_content_type_manager_v1_interface, 1, "ContentType");
|
||||
PROTO::xdgTag = makeUnique<CXDGToplevelTagProtocol>(&xdg_toplevel_tag_manager_v1_interface, 1, "XDGTag");
|
||||
|
||||
if (*PENABLECM)
|
||||
PROTO::colorManagement = makeUnique<CColorManagementProtocol>(&wp_color_manager_v1_interface, 1, "ColorManagement", *PDEBUGCM);
|
||||
@ -271,6 +272,7 @@ CProtocolManager::~CProtocolManager() {
|
||||
PROTO::colorManagement.reset();
|
||||
PROTO::xxColorManagement.reset();
|
||||
PROTO::frogColorManagement.reset();
|
||||
PROTO::xdgTag.reset();
|
||||
|
||||
PROTO::lease.reset();
|
||||
PROTO::sync.reset();
|
||||
@ -322,6 +324,7 @@ bool CProtocolManager::isGlobalPrivileged(const wl_global* global) {
|
||||
PROTO::singlePixel->getGlobal(),
|
||||
PROTO::primarySelection->getGlobal(),
|
||||
PROTO::hyprlandSurface->getGlobal(),
|
||||
PROTO::xdgTag->getGlobal(),
|
||||
PROTO::sync ? PROTO::sync->getGlobal() : nullptr,
|
||||
PROTO::mesaDRM ? PROTO::mesaDRM->getGlobal() : nullptr,
|
||||
PROTO::linuxDma ? PROTO::linuxDma->getGlobal() : nullptr,
|
||||
|
@ -141,6 +141,8 @@ class CXDGToplevelResource {
|
||||
WP<CXDGToplevelResource> parent;
|
||||
WP<CXDGDialogV1Resource> dialog;
|
||||
|
||||
std::optional<std::string> m_toplevelTag, m_toplevelDescription;
|
||||
|
||||
bool anyChildModal();
|
||||
|
||||
std::vector<WP<CXDGToplevelResource>> children;
|
||||
|
54
src/protocols/XDGTag.cpp
Normal file
54
src/protocols/XDGTag.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "XDGTag.hpp"
|
||||
#include "XDGShell.hpp"
|
||||
|
||||
CXDGToplevelTagManagerResource::CXDGToplevelTagManagerResource(UP<CXdgToplevelTagManagerV1>&& resource) : m_resource(std::move(resource)) {
|
||||
if UNLIKELY (!good())
|
||||
return;
|
||||
|
||||
m_resource->setDestroy([this](CXdgToplevelTagManagerV1* r) { PROTO::xdgTag->destroyResource(this); });
|
||||
m_resource->setOnDestroy([this](CXdgToplevelTagManagerV1* r) { PROTO::xdgTag->destroyResource(this); });
|
||||
|
||||
resource->setSetToplevelTag([](CXdgToplevelTagManagerV1* r, wl_resource* toplevel, const char* tag) {
|
||||
auto TOPLEVEL = CXDGToplevelResource::fromResource(toplevel);
|
||||
|
||||
if (!TOPLEVEL) {
|
||||
r->error(-1, "Invalid toplevel handle");
|
||||
return;
|
||||
}
|
||||
|
||||
TOPLEVEL->m_toplevelTag = tag;
|
||||
});
|
||||
|
||||
resource->setSetToplevelDescription([](CXdgToplevelTagManagerV1* r, wl_resource* toplevel, const char* description) {
|
||||
auto TOPLEVEL = CXDGToplevelResource::fromResource(toplevel);
|
||||
|
||||
if (!TOPLEVEL) {
|
||||
r->error(-1, "Invalid toplevel handle");
|
||||
return;
|
||||
}
|
||||
|
||||
TOPLEVEL->m_toplevelDescription = description;
|
||||
});
|
||||
}
|
||||
|
||||
bool CXDGToplevelTagManagerResource::good() {
|
||||
return m_resource->resource();
|
||||
}
|
||||
|
||||
CXDGToplevelTagProtocol::CXDGToplevelTagProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
;
|
||||
}
|
||||
|
||||
void CXDGToplevelTagProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
const auto RESOURCE =
|
||||
WP<CXDGToplevelTagManagerResource>{m_vManagers.emplace_back(makeUnique<CXDGToplevelTagManagerResource>(makeUnique<CXdgToplevelTagManagerV1>(client, ver, id)))};
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CXDGToplevelTagProtocol::destroyResource(CXDGToplevelTagManagerResource* res) {
|
||||
std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; });
|
||||
}
|
36
src/protocols/XDGTag.hpp
Normal file
36
src/protocols/XDGTag.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "xdg-toplevel-tag-v1.hpp"
|
||||
|
||||
class CXDGToplevelResource;
|
||||
|
||||
class CXDGToplevelTagManagerResource {
|
||||
public:
|
||||
CXDGToplevelTagManagerResource(UP<CXdgToplevelTagManagerV1>&& resource);
|
||||
|
||||
bool good();
|
||||
|
||||
private:
|
||||
UP<CXdgToplevelTagManagerV1> m_resource;
|
||||
};
|
||||
|
||||
class CXDGToplevelTagProtocol : public IWaylandProtocol {
|
||||
public:
|
||||
CXDGToplevelTagProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||
|
||||
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||
|
||||
private:
|
||||
void destroyResource(CXDGToplevelTagManagerResource* res);
|
||||
|
||||
//
|
||||
std::vector<UP<CXDGToplevelTagManagerResource>> m_vManagers;
|
||||
|
||||
friend class CXDGToplevelTagManagerResource;
|
||||
};
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CXDGToplevelTagProtocol> xdgTag;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user