mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-05-12 14:50:36 +01:00
protocols: add Hyprland toplevel mapping implementation (#9775)
This commit is contained in:
parent
b06fbdb743
commit
a9549dbca0
9 changed files with 147 additions and 11 deletions
|
@ -316,7 +316,7 @@ endfunction()
|
|||
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads)
|
||||
|
||||
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.2)
|
||||
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.4)
|
||||
if(hyprland_protocols_dep_FOUND)
|
||||
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
|
||||
message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}")
|
||||
|
@ -348,6 +348,7 @@ protocolnew("protocols" "wayland-drm" true)
|
|||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-surface-v1" true)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-lock-notify-v1" true)
|
||||
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-mapping-v1" true)
|
||||
|
||||
protocolnew("staging/tearing-control" "tearing-control-v1" false)
|
||||
protocolnew("staging/fractional-scale" "fractional-scale-v1" false)
|
||||
|
|
|
@ -7,7 +7,7 @@ wayland_protos = dependency(
|
|||
|
||||
hyprland_protos = dependency(
|
||||
'hyprland-protocols',
|
||||
version: '>=0.6.2',
|
||||
version: '>=0.6.4',
|
||||
fallback: 'hyprland-protocols',
|
||||
)
|
||||
|
||||
|
@ -37,6 +37,7 @@ protocols = [
|
|||
'frog-color-management-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-toplevel-mapping-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml',
|
||||
hyprland_protocol_dir / 'protocols/hyprland-surface-v1.xml',
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "../protocols/DRMSyncobj.hpp"
|
||||
#include "../protocols/Screencopy.hpp"
|
||||
#include "../protocols/ToplevelExport.hpp"
|
||||
#include "../protocols/ToplevelMapping.hpp"
|
||||
#include "../protocols/TextInputV1.hpp"
|
||||
#include "../protocols/GlobalShortcuts.hpp"
|
||||
#include "../protocols/XDGDialog.hpp"
|
||||
|
@ -68,6 +69,7 @@
|
|||
|
||||
#include <aquamarine/buffer/Buffer.hpp>
|
||||
#include <aquamarine/backend/Backend.hpp>
|
||||
#include <hyprutils/memory/UniquePtr.hpp>
|
||||
|
||||
// ********************************************************************************************
|
||||
// * IMPORTANT: make sure to .reset() any protocol UP's you create! (put reset in destructor) *
|
||||
|
@ -175,6 +177,7 @@ CProtocolManager::CProtocolManager() {
|
|||
PROTO::xwaylandShell = makeUnique<CXWaylandShellProtocol>(&xwayland_shell_v1_interface, 1, "XWaylandShell");
|
||||
PROTO::screencopy = makeUnique<CScreencopyProtocol>(&zwlr_screencopy_manager_v1_interface, 3, "Screencopy");
|
||||
PROTO::toplevelExport = makeUnique<CToplevelExportProtocol>(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport");
|
||||
PROTO::toplevelMapping = makeUnique<CToplevelMappingProtocol>(&hyprland_toplevel_mapping_manager_v1_interface, 1, "ToplevelMapping");
|
||||
PROTO::globalShortcuts = makeUnique<CGlobalShortcutsProtocol>(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts");
|
||||
PROTO::xdgDialog = makeUnique<CXDGDialogProtocol>(&xdg_wm_dialog_v1_interface, 1, "XDGDialog");
|
||||
PROTO::singlePixel = makeUnique<CSinglePixelProtocol>(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel");
|
||||
|
@ -262,6 +265,7 @@ CProtocolManager::~CProtocolManager() {
|
|||
PROTO::xwaylandShell.reset();
|
||||
PROTO::screencopy.reset();
|
||||
PROTO::toplevelExport.reset();
|
||||
PROTO::toplevelMapping.reset();
|
||||
PROTO::globalShortcuts.reset();
|
||||
PROTO::xdgDialog.reset();
|
||||
PROTO::singlePixel.reset();
|
||||
|
|
|
@ -6,6 +6,8 @@ CForeignToplevelHandle::CForeignToplevelHandle(SP<CExtForeignToplevelHandleV1> r
|
|||
if UNLIKELY (!resource_->resource())
|
||||
return;
|
||||
|
||||
resource->setData(this);
|
||||
|
||||
resource->setOnDestroy([this](CExtForeignToplevelHandleV1* h) { PROTO::foreignToplevel->destroyHandle(this); });
|
||||
resource->setDestroy([this](CExtForeignToplevelHandleV1* h) { PROTO::foreignToplevel->destroyHandle(this); });
|
||||
}
|
||||
|
@ -168,3 +170,8 @@ void CForeignToplevelProtocol::destroyHandle(CForeignToplevelHandle* handle) {
|
|||
bool CForeignToplevelProtocol::windowValidForForeign(PHLWINDOW pWindow) {
|
||||
return validMapped(pWindow) && !pWindow->isX11OverrideRedirect();
|
||||
}
|
||||
|
||||
PHLWINDOW CForeignToplevelProtocol::windowFromHandleResource(wl_resource* res) {
|
||||
auto data = (CForeignToplevelHandle*)(((CExtForeignToplevelHandleV1*)wl_resource_get_user_data(res))->data());
|
||||
return data ? data->window() : nullptr;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "desktop/DesktopTypes.hpp"
|
||||
#include "ext-foreign-toplevel-list-v1.hpp"
|
||||
|
||||
class CForeignToplevelHandle {
|
||||
|
@ -18,6 +19,7 @@ class CForeignToplevelHandle {
|
|||
bool closed = false;
|
||||
|
||||
friend class CForeignToplevelList;
|
||||
friend class CForeignToplevelProtocol;
|
||||
};
|
||||
|
||||
class CForeignToplevelList {
|
||||
|
@ -43,6 +45,7 @@ class CForeignToplevelList {
|
|||
class CForeignToplevelProtocol : public IWaylandProtocol {
|
||||
public:
|
||||
CForeignToplevelProtocol(const wl_interface* iface, const int& ver, const std::string& name);
|
||||
PHLWINDOW windowFromHandleResource(wl_resource* res);
|
||||
|
||||
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP<CZwlrForeignToplevelHand
|
|||
if UNLIKELY (!resource_->resource())
|
||||
return;
|
||||
|
||||
resource->setData(this);
|
||||
|
||||
resource->setOnDestroy([this](CZwlrForeignToplevelHandleV1* h) { PROTO::foreignToplevelWlr->destroyHandle(this); });
|
||||
resource->setDestroy([this](CZwlrForeignToplevelHandleV1* h) { PROTO::foreignToplevelWlr->destroyHandle(this); });
|
||||
|
||||
|
@ -420,14 +422,8 @@ void CForeignToplevelWlrProtocol::destroyHandle(CForeignToplevelHandleWlr* handl
|
|||
}
|
||||
|
||||
PHLWINDOW CForeignToplevelWlrProtocol::windowFromHandleResource(wl_resource* res) {
|
||||
for (auto const& h : m_vHandles) {
|
||||
if (h->res() != res)
|
||||
continue;
|
||||
|
||||
return h->window();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
auto data = (CForeignToplevelHandleWlr*)(((CZwlrForeignToplevelHandleV1*)wl_resource_get_user_data(res))->data());
|
||||
return data ? data->window() : nullptr;
|
||||
}
|
||||
|
||||
bool CForeignToplevelWlrProtocol::windowValidForForeign(PHLWINDOW pWindow) {
|
||||
|
|
78
src/protocols/ToplevelMapping.cpp
Normal file
78
src/protocols/ToplevelMapping.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
#include "ToplevelMapping.hpp"
|
||||
#include "hyprland-toplevel-mapping-v1.hpp"
|
||||
#include "ForeignToplevelWlr.hpp"
|
||||
#include "ForeignToplevel.hpp"
|
||||
|
||||
CToplevelWindowMappingHandle::CToplevelWindowMappingHandle(SP<CHyprlandToplevelWindowMappingHandleV1> resource_) : resource(resource_) {}
|
||||
|
||||
CToplevelMappingManager::CToplevelMappingManager(SP<CHyprlandToplevelMappingManagerV1> resource_) : resource(resource_) {
|
||||
if UNLIKELY (!resource_->resource())
|
||||
return;
|
||||
|
||||
resource->setOnDestroy([this](CHyprlandToplevelMappingManagerV1* h) { PROTO::toplevelMapping->onManagerResourceDestroy(this); });
|
||||
resource->setDestroy([this](CHyprlandToplevelMappingManagerV1* h) { PROTO::toplevelMapping->onManagerResourceDestroy(this); });
|
||||
|
||||
resource->setGetWindowForToplevel([this](CHyprlandToplevelMappingManagerV1* mgr, uint32_t handle, wl_resource* toplevel) {
|
||||
const auto NEWHANDLE = PROTO::toplevelMapping->m_vHandles.emplace_back(
|
||||
makeShared<CToplevelWindowMappingHandle>(makeShared<CHyprlandToplevelWindowMappingHandleV1>(resource->client(), resource->version(), handle)));
|
||||
|
||||
if UNLIKELY (!NEWHANDLE->resource->resource()) {
|
||||
LOGM(ERR, "Couldn't alloc mapping handle! (no memory)");
|
||||
resource->noMemory();
|
||||
return;
|
||||
}
|
||||
|
||||
NEWHANDLE->resource->setOnDestroy([](CHyprlandToplevelWindowMappingHandleV1* h) { PROTO::toplevelMapping->destroyHandle(h); });
|
||||
NEWHANDLE->resource->setDestroy([](CHyprlandToplevelWindowMappingHandleV1* h) { PROTO::toplevelMapping->destroyHandle(h); });
|
||||
|
||||
const auto WINDOW = PROTO::foreignToplevel->windowFromHandleResource(toplevel);
|
||||
if (!WINDOW)
|
||||
NEWHANDLE->resource->sendFailed();
|
||||
else
|
||||
NEWHANDLE->resource->sendWindowAddress((uint64_t)WINDOW.get() >> 32 & 0xFFFFFFFF, (uint64_t)WINDOW.get() & 0xFFFFFFFF);
|
||||
});
|
||||
resource->setGetWindowForToplevelWlr([this](CHyprlandToplevelMappingManagerV1* mgr, uint32_t handle, wl_resource* toplevel) {
|
||||
const auto NEWHANDLE = PROTO::toplevelMapping->m_vHandles.emplace_back(
|
||||
makeShared<CToplevelWindowMappingHandle>(makeShared<CHyprlandToplevelWindowMappingHandleV1>(resource->client(), resource->version(), handle)));
|
||||
|
||||
if UNLIKELY (!NEWHANDLE->resource->resource()) {
|
||||
LOGM(ERR, "Couldn't alloc mapping handle! (no memory)");
|
||||
resource->noMemory();
|
||||
return;
|
||||
}
|
||||
|
||||
NEWHANDLE->resource->setOnDestroy([](CHyprlandToplevelWindowMappingHandleV1* h) { PROTO::toplevelMapping->destroyHandle(h); });
|
||||
NEWHANDLE->resource->setDestroy([](CHyprlandToplevelWindowMappingHandleV1* h) { PROTO::toplevelMapping->destroyHandle(h); });
|
||||
|
||||
const auto WINDOW = PROTO::foreignToplevelWlr->windowFromHandleResource(toplevel);
|
||||
if (!WINDOW)
|
||||
NEWHANDLE->resource->sendFailed();
|
||||
else
|
||||
NEWHANDLE->resource->sendWindowAddress((uint64_t)WINDOW.get() >> 32 & 0xFFFFFFFF, (uint64_t)WINDOW.get() & 0xFFFFFFFF);
|
||||
});
|
||||
}
|
||||
|
||||
bool CToplevelMappingManager::good() const {
|
||||
return resource->resource();
|
||||
}
|
||||
|
||||
CToplevelMappingProtocol::CToplevelMappingProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {}
|
||||
|
||||
void CToplevelMappingProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
const auto RESOURCE = m_vManagers.emplace_back(makeUnique<CToplevelMappingManager>(makeShared<CHyprlandToplevelMappingManagerV1>(client, ver, id))).get();
|
||||
|
||||
if UNLIKELY (!RESOURCE->good()) {
|
||||
LOGM(ERR, "Couldn't create a toplevel mapping manager");
|
||||
wl_client_post_no_memory(client);
|
||||
m_vManagers.pop_back();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CToplevelMappingProtocol::onManagerResourceDestroy(CToplevelMappingManager* mgr) {
|
||||
std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == mgr; });
|
||||
}
|
||||
|
||||
void CToplevelMappingProtocol::destroyHandle(CHyprlandToplevelWindowMappingHandleV1* handle) {
|
||||
std::erase_if(m_vHandles, [&](const auto& other) { return other->resource.get() == handle; });
|
||||
}
|
46
src/protocols/ToplevelMapping.hpp
Normal file
46
src/protocols/ToplevelMapping.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "hyprland-toplevel-mapping-v1.hpp"
|
||||
|
||||
class CToplevelWindowMappingHandle {
|
||||
public:
|
||||
CToplevelWindowMappingHandle(SP<CHyprlandToplevelWindowMappingHandleV1> resource_);
|
||||
|
||||
private:
|
||||
SP<CHyprlandToplevelWindowMappingHandleV1> resource;
|
||||
|
||||
friend class CToplevelMappingManager;
|
||||
friend class CToplevelMappingProtocol;
|
||||
};
|
||||
|
||||
class CToplevelMappingManager {
|
||||
public:
|
||||
CToplevelMappingManager(SP<CHyprlandToplevelMappingManagerV1> resource_);
|
||||
|
||||
bool good() const;
|
||||
|
||||
private:
|
||||
SP<CHyprlandToplevelMappingManagerV1> resource;
|
||||
};
|
||||
|
||||
class CToplevelMappingProtocol : IWaylandProtocol {
|
||||
public:
|
||||
CToplevelMappingProtocol(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(CToplevelMappingManager* mgr);
|
||||
void destroyHandle(CHyprlandToplevelWindowMappingHandleV1* handle);
|
||||
|
||||
std::vector<UP<CToplevelMappingManager>> m_vManagers;
|
||||
std::vector<SP<CToplevelWindowMappingHandle>> m_vHandles;
|
||||
|
||||
friend class CToplevelMappingManager;
|
||||
};
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CToplevelMappingProtocol> toplevelMapping;
|
||||
};
|
|
@ -1 +1 @@
|
|||
Subproject commit 755aef8dab49d0fc4663c715fa4ad221b2aedaed
|
||||
Subproject commit 3a5c2bda1c1a4e55cc1330c782547695a93f05b2
|
Loading…
Reference in a new issue