mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-26 13:05:58 +01:00
ext-foreign-toplevel: add implementation
This commit is contained in:
parent
34413d1f36
commit
0d1bb65c75
5 changed files with 219 additions and 1 deletions
|
@ -262,6 +262,8 @@ protocol("subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.x
|
||||||
protocol("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false)
|
protocol("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false)
|
||||||
protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false)
|
protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false)
|
||||||
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
|
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
|
||||||
|
|
||||||
|
protocolNew("protocols/wlr-gamma-control-unstable-v1.xml" "wlr-gamma-control-unstable-v1" true)
|
||||||
protocolNew("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false)
|
protocolNew("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false)
|
||||||
protocolNew("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false)
|
protocolNew("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false)
|
||||||
protocolNew("unstable/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false)
|
protocolNew("unstable/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false)
|
||||||
|
@ -270,7 +272,7 @@ protocolNew("unstable/idle-inhibit/idle-inhibit-unstable-v1.xml" "idle-inhibit-u
|
||||||
protocolNew("unstable/relative-pointer/relative-pointer-unstable-v1.xml" "relative-pointer-unstable-v1" false)
|
protocolNew("unstable/relative-pointer/relative-pointer-unstable-v1.xml" "relative-pointer-unstable-v1" false)
|
||||||
protocolNew("unstable/xdg-decoration/xdg-decoration-unstable-v1.xml" "xdg-decoration-unstable-v1" false)
|
protocolNew("unstable/xdg-decoration/xdg-decoration-unstable-v1.xml" "xdg-decoration-unstable-v1" false)
|
||||||
protocolNew("staging/alpha-modifier/alpha-modifier-v1.xml" "alpha-modifier-v1" false)
|
protocolNew("staging/alpha-modifier/alpha-modifier-v1.xml" "alpha-modifier-v1" false)
|
||||||
protocolNew("protocols/wlr-gamma-control-unstable-v1.xml" "wlr-gamma-control-unstable-v1" true)
|
protocolNew("staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml" "ext-foreign-toplevel-list-v1" false)
|
||||||
|
|
||||||
# tools
|
# tools
|
||||||
add_subdirectory(hyprctl)
|
add_subdirectory(hyprctl)
|
||||||
|
|
|
@ -48,6 +48,7 @@ new_protocols = [
|
||||||
[wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'],
|
[wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'],
|
||||||
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
|
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
|
||||||
[wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'],
|
[wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'],
|
||||||
|
[wl_protocol_dir, 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml'],
|
||||||
]
|
]
|
||||||
|
|
||||||
wl_protos_src = []
|
wl_protos_src = []
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "../protocols/XDGDecoration.hpp"
|
#include "../protocols/XDGDecoration.hpp"
|
||||||
#include "../protocols/AlphaModifier.hpp"
|
#include "../protocols/AlphaModifier.hpp"
|
||||||
#include "../protocols/GammaControl.hpp"
|
#include "../protocols/GammaControl.hpp"
|
||||||
|
#include "../protocols/ForeignToplevel.hpp"
|
||||||
|
|
||||||
#include "tearing-control-v1.hpp"
|
#include "tearing-control-v1.hpp"
|
||||||
#include "fractional-scale-v1.hpp"
|
#include "fractional-scale-v1.hpp"
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
#include "xdg-decoration-unstable-v1.hpp"
|
#include "xdg-decoration-unstable-v1.hpp"
|
||||||
#include "alpha-modifier-v1.hpp"
|
#include "alpha-modifier-v1.hpp"
|
||||||
#include "wlr-gamma-control-unstable-v1.hpp"
|
#include "wlr-gamma-control-unstable-v1.hpp"
|
||||||
|
#include "ext-foreign-toplevel-list-v1.hpp"
|
||||||
|
|
||||||
CProtocolManager::CProtocolManager() {
|
CProtocolManager::CProtocolManager() {
|
||||||
|
|
||||||
|
@ -31,6 +33,7 @@ CProtocolManager::CProtocolManager() {
|
||||||
PROTO::xdgDecoration = std::make_unique<CXDGDecorationProtocol>(&zxdg_decoration_manager_v1_interface, 1, "XDGDecoration");
|
PROTO::xdgDecoration = std::make_unique<CXDGDecorationProtocol>(&zxdg_decoration_manager_v1_interface, 1, "XDGDecoration");
|
||||||
PROTO::alphaModifier = std::make_unique<CAlphaModifierProtocol>(&wp_alpha_modifier_v1_interface, 1, "AlphaModifier");
|
PROTO::alphaModifier = std::make_unique<CAlphaModifierProtocol>(&wp_alpha_modifier_v1_interface, 1, "AlphaModifier");
|
||||||
PROTO::gamma = std::make_unique<CGammaControlProtocol>(&zwlr_gamma_control_manager_v1_interface, 1, "GammaControl");
|
PROTO::gamma = std::make_unique<CGammaControlProtocol>(&zwlr_gamma_control_manager_v1_interface, 1, "GammaControl");
|
||||||
|
PROTO::foreignToplevel = std::make_unique<CForeignToplevelProtocol>(&ext_foreign_toplevel_list_v1_interface, 1, "ForeignToplevel");
|
||||||
|
|
||||||
// Old protocol implementations.
|
// Old protocol implementations.
|
||||||
// TODO: rewrite them to use hyprwayland-scanner.
|
// TODO: rewrite them to use hyprwayland-scanner.
|
||||||
|
|
148
src/protocols/ForeignToplevel.cpp
Normal file
148
src/protocols/ForeignToplevel.cpp
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
#include "ForeignToplevel.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
#define LOGM PROTO::foreignToplevel->protoLog
|
||||||
|
|
||||||
|
CForeignToplevelHandle::CForeignToplevelHandle(SP<CExtForeignToplevelHandleV1> resource_, CWindow* pWindow_) : resource(resource_), pWindow(pWindow_) {
|
||||||
|
if (!resource_->resource())
|
||||||
|
return;
|
||||||
|
|
||||||
|
resource->setOnDestroy([this](CExtForeignToplevelHandleV1* h) { PROTO::foreignToplevel->destroyHandle(this); });
|
||||||
|
resource->setDestroy([this](CExtForeignToplevelHandleV1* h) { PROTO::foreignToplevel->destroyHandle(this); });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CForeignToplevelHandle::good() {
|
||||||
|
return resource->resource();
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindow* CForeignToplevelHandle::window() {
|
||||||
|
return pWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
CForeignToplevelList::CForeignToplevelList(SP<CExtForeignToplevelListV1> resource_) : resource(resource_) {
|
||||||
|
if (!resource_->resource())
|
||||||
|
return;
|
||||||
|
|
||||||
|
resource->setOnDestroy([this](CExtForeignToplevelListV1* h) { PROTO::foreignToplevel->onManagerResourceDestroy(this); });
|
||||||
|
resource->setDestroy([this](CExtForeignToplevelListV1* h) { PROTO::foreignToplevel->onManagerResourceDestroy(this); });
|
||||||
|
|
||||||
|
resource->setStop([this](CExtForeignToplevelListV1* h) {
|
||||||
|
resource->sendFinished();
|
||||||
|
finished = true;
|
||||||
|
LOGM(LOG, "CForeignToplevelList: finished");
|
||||||
|
});
|
||||||
|
|
||||||
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
|
if (!w->m_bIsMapped || w->m_bFadingOut)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
onMap(w.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CForeignToplevelList::onMap(CWindow* pWindow) {
|
||||||
|
if (finished)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto NEWHANDLE = PROTO::foreignToplevel->m_vHandles.emplace_back(std::make_shared<CForeignToplevelHandle>(
|
||||||
|
std::make_shared<CExtForeignToplevelHandleV1>(wl_resource_get_client(resource->resource()), wl_resource_get_version(resource->resource()), 0), pWindow));
|
||||||
|
|
||||||
|
if (!NEWHANDLE->good()) {
|
||||||
|
LOGM(ERR, "Couldn't create a foreign handle");
|
||||||
|
wl_resource_post_no_memory(resource->resource());
|
||||||
|
PROTO::foreignToplevel->m_vHandles.pop_back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto IDENTIFIER = std::format("{:08x}->{:016x}", static_cast<uint32_t>((uintptr_t)this & 0xFFFFFFFF), (uintptr_t)pWindow);
|
||||||
|
|
||||||
|
LOGM(LOG, "Newly mapped window gets an identifier of {}", IDENTIFIER);
|
||||||
|
resource->sendToplevel(NEWHANDLE->resource.get());
|
||||||
|
NEWHANDLE->resource->sendIdentifier(IDENTIFIER.c_str());
|
||||||
|
NEWHANDLE->resource->sendAppId(pWindow->m_szInitialClass.c_str());
|
||||||
|
NEWHANDLE->resource->sendTitle(pWindow->m_szInitialTitle.c_str());
|
||||||
|
NEWHANDLE->resource->sendDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<CForeignToplevelHandle> CForeignToplevelList::handleForWindow(CWindow* pWindow) {
|
||||||
|
std::erase_if(handles, [](const auto& wp) { return !wp.lock(); });
|
||||||
|
const auto IT = std::find_if(handles.begin(), handles.end(), [pWindow](const auto& h) { return h.lock()->window() == pWindow; });
|
||||||
|
return IT == handles.end() ? SP<CForeignToplevelHandle>{} : IT->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CForeignToplevelList::onTitle(CWindow* pWindow) {
|
||||||
|
if (finished)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto H = handleForWindow(pWindow);
|
||||||
|
if (!H || H->closed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
H->resource->sendTitle(pWindow->m_szTitle.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CForeignToplevelList::onClass(CWindow* pWindow) {
|
||||||
|
if (finished)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto H = handleForWindow(pWindow);
|
||||||
|
if (!H || H->closed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
H->resource->sendAppId(g_pXWaylandManager->getAppIDClass(pWindow).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CForeignToplevelList::onUnmap(CWindow* pWindow) {
|
||||||
|
if (finished)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto H = handleForWindow(pWindow);
|
||||||
|
if (!H)
|
||||||
|
return;
|
||||||
|
|
||||||
|
H->resource->sendClosed();
|
||||||
|
H->closed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CForeignToplevelList::good() {
|
||||||
|
return resource->resource();
|
||||||
|
}
|
||||||
|
|
||||||
|
CForeignToplevelProtocol::CForeignToplevelProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||||
|
static auto P = g_pHookSystem->hookDynamic("openWindow", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||||
|
for (auto& m : m_vManagers) {
|
||||||
|
m->onMap(std::any_cast<CWindow*>(data));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static auto P1 = g_pHookSystem->hookDynamic("closeWindow", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||||
|
for (auto& m : m_vManagers) {
|
||||||
|
m->onUnmap(std::any_cast<CWindow*>(data));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static auto P2 = g_pHookSystem->hookDynamic("windowTitle", [this](void* self, SCallbackInfo& info, std::any data) {
|
||||||
|
for (auto& m : m_vManagers) {
|
||||||
|
m->onTitle(std::any_cast<CWindow*>(data));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CForeignToplevelProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||||
|
const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CForeignToplevelList>(std::make_shared<CExtForeignToplevelListV1>(client, ver, id))).get();
|
||||||
|
|
||||||
|
if (!RESOURCE->good()) {
|
||||||
|
LOGM(ERR, "Couldn't create a foreign list");
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
m_vManagers.pop_back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CForeignToplevelProtocol::onManagerResourceDestroy(CForeignToplevelList* mgr) {
|
||||||
|
std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == mgr; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CForeignToplevelProtocol::destroyHandle(CForeignToplevelHandle* handle) {
|
||||||
|
std::erase_if(m_vHandles, [&](const auto& other) { return other.get() == handle; });
|
||||||
|
}
|
64
src/protocols/ForeignToplevel.hpp
Normal file
64
src/protocols/ForeignToplevel.hpp
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "WaylandProtocol.hpp"
|
||||||
|
#include "ext-foreign-toplevel-list-v1.hpp"
|
||||||
|
|
||||||
|
class CForeignToplevelHandle {
|
||||||
|
public:
|
||||||
|
CForeignToplevelHandle(SP<CExtForeignToplevelHandleV1> resource_, CWindow* pWindow);
|
||||||
|
|
||||||
|
bool good();
|
||||||
|
CWindow* window();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SP<CExtForeignToplevelHandleV1> resource;
|
||||||
|
CWindow* pWindow = nullptr;
|
||||||
|
bool closed = false;
|
||||||
|
|
||||||
|
friend class CForeignToplevelList;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CForeignToplevelList {
|
||||||
|
public:
|
||||||
|
CForeignToplevelList(SP<CExtForeignToplevelListV1> resource_);
|
||||||
|
|
||||||
|
void onMap(CWindow* pWindow);
|
||||||
|
void onTitle(CWindow* pWindow);
|
||||||
|
void onClass(CWindow* pWindow);
|
||||||
|
void onUnmap(CWindow* pWindow);
|
||||||
|
|
||||||
|
bool good();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SP<CExtForeignToplevelListV1> resource;
|
||||||
|
bool finished = false;
|
||||||
|
|
||||||
|
SP<CForeignToplevelHandle> handleForWindow(CWindow* pWindow);
|
||||||
|
|
||||||
|
std::vector<WP<CForeignToplevelHandle>> handles;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CForeignToplevelProtocol : public IWaylandProtocol {
|
||||||
|
public:
|
||||||
|
CForeignToplevelProtocol(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 onManagerResourceDestroy(CForeignToplevelList* mgr);
|
||||||
|
void destroyHandle(CForeignToplevelHandle* handle);
|
||||||
|
|
||||||
|
//
|
||||||
|
std::vector<UP<CForeignToplevelList>> m_vManagers;
|
||||||
|
std::vector<SP<CForeignToplevelHandle>> m_vHandles;
|
||||||
|
|
||||||
|
friend class CForeignToplevelList;
|
||||||
|
friend class CForeignToplevelHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace PROTO {
|
||||||
|
inline UP<CForeignToplevelProtocol> foreignToplevel;
|
||||||
|
};
|
Loading…
Reference in a new issue