Fractional-scale: move to new impl

This commit is contained in:
Vaxry 2024-04-20 14:14:54 +01:00
parent ea95449402
commit ea47e8c92a
9 changed files with 126 additions and 118 deletions

View file

@ -273,10 +273,10 @@ 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/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false) protocol("unstable/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false)
protocol("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-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)
protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false) protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false)
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)
# tools # tools
add_subdirectory(hyprctl) add_subdirectory(hyprctl)

View file

@ -28,7 +28,6 @@ protocols = [
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'], [wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'], [wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'],
['wlr-foreign-toplevel-management-unstable-v1.xml'], ['wlr-foreign-toplevel-management-unstable-v1.xml'],
['wlr-layer-shell-unstable-v1.xml'], ['wlr-layer-shell-unstable-v1.xml'],
@ -43,6 +42,7 @@ protocols = [
new_protocols = [ new_protocols = [
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'], [wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
] ]
wl_protos_src = [] wl_protos_src = []

View file

@ -12,6 +12,7 @@
#endif #endif
#include <ranges> #include <ranges>
#include "helpers/VarList.hpp" #include "helpers/VarList.hpp"
#include "protocols/FractionalScale.hpp"
int handleCritSignal(int signo, void* data) { int handleCritSignal(int signo, void* data) {
Debug::log(LOG, "Hyprland received signal {}", signo); Debug::log(LOG, "Hyprland received signal {}", signo);
@ -2849,7 +2850,7 @@ void CCompositor::leaveUnsafeState() {
} }
void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) { void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) {
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale); PROTO::fractional->sendScale(pSurface, scale);
wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(std::ceil(scale))); wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(std::ceil(scale)));
const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface); const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface);

View file

@ -1,17 +1,19 @@
#include "ProtocolManager.hpp" #include "ProtocolManager.hpp"
#include "../protocols/TearingControl.hpp" #include "../protocols/TearingControl.hpp"
#include "../protocols/FractionalScale.hpp"
#include "xdg-output-unstable-v1-protocol.h" #include "xdg-output-unstable-v1-protocol.h"
#include "tearing-control-v1.hpp" #include "tearing-control-v1.hpp"
#include "fractional-scale-v1.hpp"
CProtocolManager::CProtocolManager() { CProtocolManager::CProtocolManager() {
m_pToplevelExportProtocolManager = std::make_unique<CToplevelExportProtocolManager>(); m_pToplevelExportProtocolManager = std::make_unique<CToplevelExportProtocolManager>();
m_pFractionalScaleProtocolManager = std::make_unique<CFractionalScaleProtocolManager>();
m_pTextInputV1ProtocolManager = std::make_unique<CTextInputV1ProtocolManager>(); m_pTextInputV1ProtocolManager = std::make_unique<CTextInputV1ProtocolManager>();
m_pGlobalShortcutsProtocolManager = std::make_unique<CGlobalShortcutsProtocolManager>(); m_pGlobalShortcutsProtocolManager = std::make_unique<CGlobalShortcutsProtocolManager>();
m_pScreencopyProtocolManager = std::make_unique<CScreencopyProtocolManager>(); m_pScreencopyProtocolManager = std::make_unique<CScreencopyProtocolManager>();
m_pXDGOutputProtocol = std::make_unique<CXDGOutputProtocol>(&zxdg_output_manager_v1_interface, 3, "XDGOutput"); m_pXDGOutputProtocol = std::make_unique<CXDGOutputProtocol>(&zxdg_output_manager_v1_interface, 3, "XDGOutput");
PROTO::tearing = std::make_unique<CTearingControlProtocol>(&wp_tearing_control_manager_v1_interface, 1, "TearingControl"); PROTO::tearing = std::make_unique<CTearingControlProtocol>(&wp_tearing_control_manager_v1_interface, 1, "TearingControl");
PROTO::fractional = std::make_unique<CFractionalScaleProtocol>(&wp_fractional_scale_manager_v1_interface, 1, "FractionalScale");
} }

View file

@ -2,7 +2,6 @@
#include "../defines.hpp" #include "../defines.hpp"
#include "../protocols/ToplevelExport.hpp" #include "../protocols/ToplevelExport.hpp"
#include "../protocols/FractionalScale.hpp"
#include "../protocols/TextInputV1.hpp" #include "../protocols/TextInputV1.hpp"
#include "../protocols/GlobalShortcuts.hpp" #include "../protocols/GlobalShortcuts.hpp"
#include "../protocols/Screencopy.hpp" #include "../protocols/Screencopy.hpp"
@ -14,7 +13,6 @@ class CProtocolManager {
// TODO: rewrite to use the new protocol framework // TODO: rewrite to use the new protocol framework
std::unique_ptr<CToplevelExportProtocolManager> m_pToplevelExportProtocolManager; std::unique_ptr<CToplevelExportProtocolManager> m_pToplevelExportProtocolManager;
std::unique_ptr<CFractionalScaleProtocolManager> m_pFractionalScaleProtocolManager;
std::unique_ptr<CTextInputV1ProtocolManager> m_pTextInputV1ProtocolManager; std::unique_ptr<CTextInputV1ProtocolManager> m_pTextInputV1ProtocolManager;
std::unique_ptr<CGlobalShortcutsProtocolManager> m_pGlobalShortcutsProtocolManager; std::unique_ptr<CGlobalShortcutsProtocolManager> m_pGlobalShortcutsProtocolManager;
std::unique_ptr<CScreencopyProtocolManager> m_pScreencopyProtocolManager; std::unique_ptr<CScreencopyProtocolManager> m_pScreencopyProtocolManager;

View file

@ -1,6 +1,7 @@
#include "SessionLockManager.hpp" #include "SessionLockManager.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../protocols/FractionalScale.hpp"
static void handleSurfaceMap(void* owner, void* data) { static void handleSurfaceMap(void* owner, void* data) {
const auto PSURFACE = (SSessionLockSurface*)owner; const auto PSURFACE = (SSessionLockSurface*)owner;
@ -74,7 +75,7 @@ void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) {
PSURFACE->pWlrLockSurface = PWLRSURFACE; PSURFACE->pWlrLockSurface = PWLRSURFACE;
PSURFACE->iMonitorID = PMONITOR->ID; PSURFACE->iMonitorID = PMONITOR->ID;
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PSURFACE->pWlrLockSurface->surface, PMONITOR->scale); PROTO::fractional->sendScale(PSURFACE->pWlrLockSurface->surface, PMONITOR->scale);
wlr_session_lock_surface_v1_configure(PWLRSURFACE, PMONITOR->vecSize.x, PMONITOR->vecSize.y); wlr_session_lock_surface_v1_configure(PWLRSURFACE, PMONITOR->vecSize.x, PMONITOR->vecSize.y);

View file

@ -1,6 +1,7 @@
#include "InputMethodPopup.hpp" #include "InputMethodPopup.hpp"
#include "InputManager.hpp" #include "InputManager.hpp"
#include "../../Compositor.hpp" #include "../../Compositor.hpp"
#include "../../protocols/FractionalScale.hpp"
CInputPopup::CInputPopup(wlr_input_popup_surface_v2* surf) : pWlr(surf) { CInputPopup::CInputPopup(wlr_input_popup_surface_v2* surf) : pWlr(surf) {
surface.assign(surf->surface); surface.assign(surf->surface);
@ -63,7 +64,7 @@ void CInputPopup::onMap() {
if (!PMONITOR) if (!PMONITOR)
return; return;
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(surface.wlr(), PMONITOR->scale); PROTO::fractional->sendScale(surface.wlr(), PMONITOR->scale);
} }
void CInputPopup::onUnmap() { void CInputPopup::onUnmap() {

View file

@ -1,118 +1,93 @@
#include "FractionalScale.hpp" #include "FractionalScale.hpp"
#include "../Compositor.hpp" static void onWlrSurfaceDestroy(void* owner, void* data) {
const auto SURF = (wlr_surface*)owner;
#define FRACTIONAL_SCALE_VERSION 1 PROTO::fractional->onSurfaceDestroy(SURF);
static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) {
g_pProtocolManager->m_pFractionalScaleProtocolManager->bindManager(client, data, version, id);
} }
static void handleDisplayDestroy(struct wl_listener* listener, void* data) { CFractionalScaleProtocol::CFractionalScaleProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
g_pProtocolManager->m_pFractionalScaleProtocolManager->displayDestroy(); ;
} }
void CFractionalScaleProtocolManager::displayDestroy() { void CFractionalScaleProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
wl_global_destroy(m_pGlobal); const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CWpFractionalScaleManagerV1>(client, ver, id)).get();
RESOURCE->setOnDestroy([this](CWpFractionalScaleManagerV1* p) { this->onManagerResourceDestroy(p->resource()); });
RESOURCE->setDestroy([this](CWpFractionalScaleManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); });
RESOURCE->setGetFractionalScale(
[this](CWpFractionalScaleManagerV1* pMgr, uint32_t id, wl_resource* surface) { this->onGetFractionalScale(pMgr, id, wlr_surface_from_resource(surface)); });
} }
static void handleDestroy(wl_client* client, wl_resource* resource) { void CFractionalScaleProtocol::removeAddon(CFractionalScaleAddon* addon) {
wl_resource_destroy(resource); m_mAddons.erase(addon->surf());
} }
void handleGetFractionalScale(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* surface) { void CFractionalScaleProtocol::onManagerResourceDestroy(wl_resource* res) {
g_pProtocolManager->m_pFractionalScaleProtocolManager->getFractionalScale(client, resource, id, surface); std::erase_if(m_vManagers, [res](const auto& other) { return other->resource() == res; });
} }
CFractionalScaleProtocolManager::CFractionalScaleProtocolManager() { void CFractionalScaleProtocol::onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, wlr_surface* surface) {
m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &wp_fractional_scale_manager_v1_interface, FRACTIONAL_SCALE_VERSION, this, bindManagerInt); const auto PADDON = m_mAddons
.emplace(surface,
std::make_unique<CFractionalScaleAddon>(
std::make_shared<CWpFractionalScaleV1>(wl_resource_get_client(pMgr->resource()), wl_resource_get_version(pMgr->resource()), id), surface))
.first->second.get();
if (!m_pGlobal) { if (!PADDON->good()) {
Debug::log(ERR, "FractionalScaleManager could not start! Fractional scaling will not work!"); m_mAddons.erase(surface);
wl_resource_post_no_memory(pMgr->resource());
return; return;
} }
m_liDisplayDestroy.notify = handleDisplayDestroy; PADDON->resource->setOnDestroy([this, PADDON](CWpFractionalScaleV1* self) { this->removeAddon(PADDON); });
wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy); PADDON->resource->setDestroy([this, PADDON](CWpFractionalScaleV1* self) { this->removeAddon(PADDON); });
Debug::log(LOG, "FractionalScaleManager started successfully!"); if (!m_mSurfaceScales.contains(surface))
m_mSurfaceScales[surface] = 1.F;
PADDON->setScale(m_mSurfaceScales[surface]);
registerSurface(surface);
} }
static const struct wp_fractional_scale_manager_v1_interface fractionalScaleManagerImpl = { void CFractionalScaleProtocol::sendScale(wlr_surface* surf, const float& scale) {
.destroy = handleDestroy, m_mSurfaceScales[surf] = scale;
.get_fractional_scale = handleGetFractionalScale, if (m_mAddons.contains(surf))
}; m_mAddons[surf]->setScale(scale);
registerSurface(surf);
void CFractionalScaleProtocolManager::bindManager(wl_client* client, void* data, uint32_t version, uint32_t id) {
const auto RESOURCE = wl_resource_create(client, &wp_fractional_scale_manager_v1_interface, version, id);
wl_resource_set_implementation(RESOURCE, &fractionalScaleManagerImpl, this, nullptr);
Debug::log(LOG, "FractionalScaleManager bound successfully!");
} }
static void handleDestroyScaleAddon(wl_client* client, wl_resource* resource); void CFractionalScaleProtocol::registerSurface(wlr_surface* surf) {
// if (m_mSurfaceDestroyListeners.contains(surf))
static const struct wp_fractional_scale_v1_interface fractionalScaleAddonImpl {
.destroy = handleDestroyScaleAddon
};
//
SFractionalScaleAddon* addonFromResource(wl_resource* resource) {
ASSERT(wl_resource_instance_of(resource, &wp_fractional_scale_v1_interface, &fractionalScaleAddonImpl));
return (SFractionalScaleAddon*)wl_resource_get_user_data(resource);
}
static void handleDestroyScaleAddon(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource);
}
static void handleAddonDestroy(wl_resource* resource) {
const auto PADDON = addonFromResource(resource);
if (PADDON->pResource) {
wl_resource_set_user_data(PADDON->pResource, nullptr);
}
g_pProtocolManager->m_pFractionalScaleProtocolManager->removeAddon(PADDON->pSurface);
}
void CFractionalScaleProtocolManager::getFractionalScale(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* surface) {
const auto PSURFACE = wlr_surface_from_resource(surface);
const auto PADDON = getAddonForSurface(PSURFACE);
if (PADDON->pResource) {
wl_resource_post_error(resource, WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS, "Fractional scale exists.");
return; return;
m_mSurfaceDestroyListeners[surf].hyprListener_surfaceDestroy.initCallback(&surf->events.destroy, ::onWlrSurfaceDestroy, surf, "FractionalScale");
} }
PADDON->pResource = wl_resource_create(client, &wp_fractional_scale_v1_interface, wl_resource_get_version(resource), id); void CFractionalScaleProtocol::onSurfaceDestroy(wlr_surface* surf) {
wl_resource_set_implementation(PADDON->pResource, &fractionalScaleAddonImpl, PADDON, handleAddonDestroy); m_mSurfaceDestroyListeners.erase(surf);
m_mSurfaceScales.erase(surf);
wp_fractional_scale_v1_send_preferred_scale(PADDON->pResource, (uint32_t)std::round(PADDON->preferredScale * 120.0)); if (m_mAddons.contains(surf))
m_mAddons[surf]->onSurfaceDestroy();
} }
SFractionalScaleAddon* CFractionalScaleProtocolManager::getAddonForSurface(wlr_surface* surface) { CFractionalScaleAddon::CFractionalScaleAddon(SP<CWpFractionalScaleV1> resource_, wlr_surface* surf_) : resource(resource_), surface(surf_) {
const auto IT = std::find_if(m_vFractionalScaleAddons.begin(), m_vFractionalScaleAddons.end(), [&](const auto& other) { return other->pSurface == surface; }); resource->setDestroy([this](CWpFractionalScaleV1* self) { PROTO::fractional->removeAddon(this); });
resource->setOnDestroy([this](CWpFractionalScaleV1* self) { PROTO::fractional->removeAddon(this); });
if (IT != m_vFractionalScaleAddons.end())
return IT->get();
m_vFractionalScaleAddons.emplace_back(std::make_unique<SFractionalScaleAddon>());
m_vFractionalScaleAddons.back()->pSurface = surface;
return m_vFractionalScaleAddons.back().get();
} }
void CFractionalScaleProtocolManager::setPreferredScaleForSurface(wlr_surface* surface, double scale) { void CFractionalScaleAddon::onSurfaceDestroy() {
const auto PADDON = getAddonForSurface(surface); surfaceGone = true;
PADDON->preferredScale = scale;
if (PADDON->pResource)
wp_fractional_scale_v1_send_preferred_scale(PADDON->pResource, (uint32_t)std::round(scale * 120.0));
} }
void CFractionalScaleProtocolManager::removeAddon(wlr_surface* surface) { void CFractionalScaleAddon::setScale(const float& scale) {
std::erase_if(m_vFractionalScaleAddons, [&](const auto& other) { return other->pSurface == surface; }); resource->sendPreferredScale(std::round(scale * 120.0));
}
bool CFractionalScaleAddon::good() {
return resource->resource();
}
wlr_surface* CFractionalScaleAddon::surf() {
return surface;
} }

View file

@ -1,38 +1,68 @@
#pragma once #pragma once
#include "../defines.hpp" #include <memory>
#include "fractional-scale-v1-protocol.h" #include <unordered_map>
#include "WaylandProtocol.hpp"
#include "fractional-scale-v1.hpp"
#include <vector> class CFractionalScaleProtocol;
#include <algorithm>
struct SFractionalScaleAddon { class CFractionalScaleAddon {
wlr_surface* pSurface = nullptr;
double preferredScale = 1.0;
wl_resource* pResource = nullptr;
};
class CFractionalScaleProtocolManager {
public: public:
CFractionalScaleProtocolManager(); CFractionalScaleAddon(SP<CWpFractionalScaleV1> resource_, wlr_surface* surf_);
void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); void setScale(const float& scale);
void onSurfaceDestroy();
void displayDestroy(); bool good();
void setPreferredScaleForSurface(wlr_surface*, double); wlr_surface* surf();
void removeAddon(wlr_surface*); bool operator==(const wl_resource* other) const {
return other == resource->resource();
}
// handlers bool operator==(const CFractionalScaleAddon* other) const {
return other->resource == resource;
void getFractionalScale(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* surface); }
private: private:
SFractionalScaleAddon* getAddonForSurface(wlr_surface*); SP<CWpFractionalScaleV1> resource;
float scale = 1.F;
wlr_surface* surface = nullptr;
bool surfaceGone = false;
std::vector<std::unique_ptr<SFractionalScaleAddon>> m_vFractionalScaleAddons; friend class CFractionalScaleProtocol;
};
wl_global* m_pGlobal = nullptr;
wl_listener m_liDisplayDestroy; struct SSurfaceListener {
DYNLISTENER(surfaceDestroy);
};
class CFractionalScaleProtocol : public IWaylandProtocol {
public:
CFractionalScaleProtocol(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);
void onManagerResourceDestroy(wl_resource* res);
void onGetFractionalScale(CWpFractionalScaleManagerV1* pMgr, uint32_t id, wlr_surface* surface);
void sendScale(wlr_surface* surf, const float& scale);
void onSurfaceDestroy(wlr_surface* surf);
void removeAddon(CFractionalScaleAddon*);
private:
void registerSurface(wlr_surface*);
std::unordered_map<wlr_surface*, SSurfaceListener> m_mSurfaceDestroyListeners;
std::unordered_map<wlr_surface*, float> m_mSurfaceScales;
std::unordered_map<wlr_surface*, UP<CFractionalScaleAddon>> m_mAddons;
std::vector<UP<CWpFractionalScaleManagerV1>> m_vManagers;
};
namespace PROTO {
inline UP<CFractionalScaleProtocol> fractional;
}; };