xdg-activation: move to new impl

This commit is contained in:
Vaxry 2024-04-29 16:43:24 +01:00
parent 39595aaca3
commit 86133983a9
11 changed files with 158 additions and 25 deletions

View File

@ -275,6 +275,7 @@ protocolNew("unstable/pointer-gestures/pointer-gestures-unstable-v1.xml" "pointe
protocolNew("unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml" "keyboard-shortcuts-inhibit-unstable-v1" false)
protocolNew("unstable/text-input/text-input-unstable-v3.xml" "text-input-unstable-v3" false)
protocolNew("unstable/pointer-constraints/pointer-constraints-unstable-v1.xml" "pointer-constraints-unstable-v1" false)
protocolNew("staging/xdg-activation/xdg-activation-v1.xml" "xdg-activation-v1" false)
# tools
add_subdirectory(hyprctl)

View File

@ -52,6 +52,7 @@ new_protocols = [
[wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'],
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
[wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'],
]
wl_protos_src = []

View File

@ -265,8 +265,6 @@ void CCompositor::initServer() {
m_sWLRIMEMgr = wlr_input_method_manager_v2_create(m_sWLDisplay);
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLEventLoop);
m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay);
@ -318,7 +316,6 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRVKeyboardMgr->events.new_virtual_keyboard, &Events::listen_newVirtualKeyboard, m_sWLRVKeyboardMgr, "VKeyboardMgr");
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
addWLSignal(&m_sWLRIMEMgr->events.input_method, &Events::listen_newIME, m_sWLRIMEMgr, "IMEMgr");
addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1");
addWLSignal(&m_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr");
if (m_sWRLDRMLeaseMgr)
@ -363,7 +360,6 @@ void CCompositor::removeAllSignals() {
removeWLSignal(&Events::listen_newVirtualKeyboard);
removeWLSignal(&Events::listen_RendererDestroy);
removeWLSignal(&Events::listen_newIME);
removeWLSignal(&Events::listen_activateXDG);
removeWLSignal(&Events::listen_newSessionLock);
if (m_sWRLDRMLeaseMgr)

View File

@ -51,7 +51,6 @@ class CCompositor {
wlr_data_device_manager* m_sWLRDataDevMgr;
wlr_drm* m_sWRLDRM;
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
wlr_xdg_activation_v1* m_sWLRXDGActivation;
wlr_output_layout* m_sWLROutputLayout;
wlr_idle_notifier_v1* m_sWLRIdleNotifier;
wlr_layer_shell_v1* m_sWLRLayerShell;
@ -67,7 +66,6 @@ class CCompositor {
wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
wlr_input_method_manager_v2* m_sWLRIMEMgr;
wlr_xdg_activation_v1* m_sWLRActivation;
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
wlr_backend* m_sWLRHeadlessBackend;
wlr_session_lock_manager_v1* m_sWLRSessionLockMgr;

View File

@ -1272,7 +1272,7 @@ void CWindow::activate() {
m_bIsUrgent = true;
if (!*PFOCUSONACTIVATE || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY))
if (!*PFOCUSONACTIVATE || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE))
return;
if (m_bIsFloating)

View File

@ -24,7 +24,6 @@ namespace Events {
// Surface XDG (window)
LISTENER(newXDGToplevel);
LISTENER(activateXDG);
// Window events
DYNLISTENFUNC(commitWindow);

View File

@ -1015,22 +1015,6 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
Debug::log(LOG, "{} fullscreen to {}", PWINDOW, PWINDOW->m_bIsFullscreen);
}
void Events::listener_activateXDG(wl_listener* listener, void* data) {
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
Debug::log(LOG, "Activate request for surface at {:x}", (uintptr_t)E->surface);
if (!wlr_xdg_surface_try_from_wlr_surface(E->surface))
return;
const auto PWINDOW = g_pCompositor->getWindowFromSurface(E->surface);
if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow.lock() || (PWINDOW->m_eSuppressedEvents & SUPPRESS_ACTIVATE))
return;
PWINDOW->activate();
}
void Events::listener_activateX11(void* owner, void* data) {
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();

View File

@ -63,7 +63,6 @@ extern "C" {
#include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_xdg_activation_v1.h>
#include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/types/wlr_subcompositor.h>

View File

@ -16,6 +16,7 @@
#include "../protocols/TextInputV3.hpp"
#include "../protocols/PointerConstraints.hpp"
#include "../protocols/OutputPower.hpp"
#include "../protocols/XDGActivation.hpp"
#include "tearing-control-v1.hpp"
#include "fractional-scale-v1.hpp"
@ -33,6 +34,7 @@
#include "text-input-unstable-v3.hpp"
#include "pointer-constraints-unstable-v1.hpp"
#include "wlr-output-power-management-unstable-v1.hpp"
#include "xdg-activation-v1.hpp"
CProtocolManager::CProtocolManager() {
@ -52,6 +54,7 @@ CProtocolManager::CProtocolManager() {
PROTO::textInputV3 = std::make_unique<CTextInputV3Protocol>(&zwp_text_input_manager_v3_interface, 1, "TextInputV3");
PROTO::constraints = std::make_unique<CPointerConstraintsProtocol>(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints");
PROTO::outputPower = std::make_unique<COutputPowerProtocol>(&zwlr_output_power_manager_v1_interface, 1, "OutputPower");
PROTO::activation = std::make_unique<CXDGActivationProtocol>(&xdg_activation_v1_interface, 1, "XDGActivation");
// Old protocol implementations.
// TODO: rewrite them to use hyprwayland-scanner.

View File

@ -0,0 +1,103 @@
#include "XDGActivation.hpp"
#include "../managers/TokenManager.hpp"
#include "../Compositor.hpp"
#include <algorithm>
#define LOGM PROTO::activation->protoLog
CXDGActivationToken::CXDGActivationToken(SP<CXdgActivationTokenV1> resource_) : resource(resource_) {
if (!resource_->resource())
return;
resource->setDestroy([this](CXdgActivationTokenV1* r) { PROTO::activation->destroyToken(this); });
resource->setOnDestroy([this](CXdgActivationTokenV1* r) { PROTO::activation->destroyToken(this); });
resource->setSetSerial([this](CXdgActivationTokenV1* r, uint32_t serial_, wl_resource* seat) { serial = serial_; });
resource->setSetAppId([this](CXdgActivationTokenV1* r, const char* appid) { appID = appid; });
resource->setCommit([this](CXdgActivationTokenV1* r) {
// TODO: should we send a protocol error of already_used here
// if it was used? the protocol spec doesn't say _when_ it should be sent...
if (committed) {
LOGM(WARN, "possible protocol error, two commits from one token. Ignoring.");
return;
}
committed = true;
// send done with a new token
token = g_pTokenManager->registerNewToken({}, std::chrono::months{12});
LOGM(LOG, "assigned new xdg-activation token {}", token);
resource->sendDone(token.c_str());
});
}
CXDGActivationToken::~CXDGActivationToken() {
if (committed)
g_pTokenManager->removeToken(g_pTokenManager->getToken(token));
}
bool CXDGActivationToken::good() {
return resource->resource();
}
CXDGActivationProtocol::CXDGActivationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
;
}
void CXDGActivationProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CXdgActivationV1>(client, ver, id)).get();
RESOURCE->setOnDestroy([this](CXdgActivationV1* p) { this->onManagerResourceDestroy(p->resource()); });
RESOURCE->setDestroy([this](CXdgActivationV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); });
RESOURCE->setGetActivationToken([this](CXdgActivationV1* pMgr, uint32_t id) { this->onGetToken(pMgr, id); });
RESOURCE->setActivate([this](CXdgActivationV1* pMgr, const char* token, wl_resource* surface) {
const auto TOKEN = std::find_if(m_vTokens.begin(), m_vTokens.end(), [token](const auto& t) { return t->committed && t->token == token; });
if (TOKEN == m_vTokens.end()) {
LOGM(WARN, "activate event for non-existent token {}??", token);
return;
}
auto xdgToken = TOKEN->get();
if (xdgToken->used) {
LOGM(WARN, "activate event for already used token {}, ignoring", token);
return;
}
xdgToken->used = true;
wlr_surface* surf = wlr_surface_from_resource(surface);
const auto PWINDOW = g_pCompositor->getWindowFromSurface(surf);
if (!PWINDOW) {
LOGM(WARN, "activate event for non-window or gone surface with token {}, ignoring", token);
return;
}
PWINDOW->activate();
});
}
void CXDGActivationProtocol::onManagerResourceDestroy(wl_resource* res) {
std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; });
}
void CXDGActivationProtocol::destroyToken(CXDGActivationToken* token) {
std::erase_if(m_vTokens, [&](const auto& other) { return other.get() == token; });
}
void CXDGActivationProtocol::onGetToken(CXdgActivationV1* pMgr, uint32_t id) {
const auto CLIENT = wl_resource_get_client(pMgr->resource());
const auto RESOURCE =
m_vTokens.emplace_back(std::make_unique<CXDGActivationToken>(std::make_shared<CXdgActivationTokenV1>(CLIENT, wl_resource_get_version(pMgr->resource()), id))).get();
if (!RESOURCE->good()) {
wl_resource_post_no_memory(pMgr->resource());
m_vTokens.pop_back();
return;
}
}

View File

@ -0,0 +1,49 @@
#pragma once
#include <memory>
#include <vector>
#include <cstdint>
#include "WaylandProtocol.hpp"
#include "xdg-activation-v1.hpp"
class CXDGActivationToken {
public:
CXDGActivationToken(SP<CXdgActivationTokenV1> resource_);
~CXDGActivationToken();
bool good();
private:
SP<CXdgActivationTokenV1> resource;
uint32_t serial = 0;
std::string appID = "";
bool committed = false;
bool used = false;
std::string token = "";
friend class CXDGActivationProtocol;
};
class CXDGActivationProtocol : public IWaylandProtocol {
public:
CXDGActivationProtocol(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(wl_resource* res);
void destroyToken(CXDGActivationToken* pointer);
void onGetToken(CXdgActivationV1* pMgr, uint32_t id);
//
std::vector<UP<CXdgActivationV1>> m_vManagers;
std::vector<UP<CXDGActivationToken>> m_vTokens;
friend class CXDGActivationToken;
};
namespace PROTO {
inline UP<CXDGActivationProtocol> activation;
};