summaryrefslogtreecommitdiff
path: root/src/protocols
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2023-01-20 19:44:30 +0100
committerGitHub <noreply@github.com>2023-01-20 19:44:30 +0100
commit60b880d9312574c3115d973fd532f2e15d1eafff (patch)
treeb88cad7335c97c876f069f9d378589210332a95f /src/protocols
parentcee7bc6e742aa02675701f772f5e7ebfb56f11ab (diff)
wp-fractional-scaling-v1 impl (#1373)
* Initial fractional scaling impl * apply UV after geom calcs * fix scaling -> scale * meson: add fractional scale proto Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
Diffstat (limited to 'src/protocols')
-rw-r--r--src/protocols/FractionalScale.cpp102
-rw-r--r--src/protocols/FractionalScale.hpp38
-rw-r--r--src/protocols/ToplevelExport.cpp8
3 files changed, 144 insertions, 4 deletions
diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp
new file mode 100644
index 00000000..40d838d1
--- /dev/null
+++ b/src/protocols/FractionalScale.cpp
@@ -0,0 +1,102 @@
+#include "FractionalScale.hpp"
+
+#include "../Compositor.hpp"
+
+#define FRACTIONAL_SCALE_VERSION 1
+
+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) {
+ g_pProtocolManager->m_pFractionalScaleProtocolManager->displayDestroy();
+}
+
+void CFractionalScaleProtocolManager::displayDestroy() {
+ wl_global_destroy(m_pGlobal);
+}
+
+static void handleDestroy(wl_client* client, wl_resource* resource) {
+ wl_resource_destroy(resource);
+}
+
+void handleGetFractionalScale(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* surface) {
+ g_pProtocolManager->m_pFractionalScaleProtocolManager->getFractionalScale(client, resource, id, surface);
+}
+
+CFractionalScaleProtocolManager::CFractionalScaleProtocolManager() {
+ m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &wp_fractional_scale_manager_v1_interface, FRACTIONAL_SCALE_VERSION, this, bindManagerInt);
+
+ if (!m_pGlobal) {
+ Debug::log(ERR, "FractionalScaleManager could not start! Fractional scaling will not work!");
+ return;
+ }
+
+ m_liDisplayDestroy.notify = handleDisplayDestroy;
+ wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy);
+
+ Debug::log(LOG, "FractionalScaleManager started successfully!");
+}
+
+static const struct wp_fractional_scale_manager_v1_interface fractionalScaleManagerImpl = {
+ .destroy = handleDestroy,
+ .get_fractional_scale = handleGetFractionalScale,
+};
+
+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!");
+}
+
+void handleDestroyScaleAddon(wl_client* client, wl_resource* resource);
+//
+
+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);
+}
+
+void handleDestroyScaleAddon(wl_client* client, wl_resource* resource) {
+ g_pProtocolManager->m_pFractionalScaleProtocolManager->removeAddon(addonFromResource(resource)->pSurface);
+ wl_resource_destroy(resource);
+}
+
+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);
+
+ PADDON->pResource = wl_resource_create(client, &wp_fractional_scale_v1_interface, wl_resource_get_version(resource), id);
+
+ wp_fractional_scale_v1_send_preferred_scale(PADDON->pResource, (uint32_t)std::round(PADDON->preferredScale * 120.0));
+}
+
+SFractionalScaleAddon* CFractionalScaleProtocolManager::getAddonForSurface(wlr_surface* surface) {
+ const auto IT = std::find_if(m_vFractionalScaleAddons.begin(), m_vFractionalScaleAddons.end(), [&](const auto& other) { return other->pSurface == surface; });
+
+ 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) {
+ const auto PADDON = getAddonForSurface(surface);
+
+ 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) {
+ std::erase_if(m_vFractionalScaleAddons, [&](const auto& other) { return other->pSurface == surface; });
+} \ No newline at end of file
diff --git a/src/protocols/FractionalScale.hpp b/src/protocols/FractionalScale.hpp
new file mode 100644
index 00000000..71b2c858
--- /dev/null
+++ b/src/protocols/FractionalScale.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "../defines.hpp"
+#include "fractional-scale-v1-protocol.h"
+
+#include <vector>
+#include <algorithm>
+
+struct SFractionalScaleAddon {
+ wlr_surface* pSurface = nullptr;
+ double preferredScale = 1.0;
+ wl_resource* pResource = nullptr;
+};
+
+class CFractionalScaleProtocolManager {
+ public:
+ CFractionalScaleProtocolManager();
+
+ void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id);
+
+ void displayDestroy();
+
+ void setPreferredScaleForSurface(wlr_surface*, double);
+
+ void removeAddon(wlr_surface*);
+
+ // handlers
+
+ void getFractionalScale(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* surface);
+
+ private:
+ SFractionalScaleAddon* getAddonForSurface(wlr_surface*);
+
+ std::vector<std::unique_ptr<SFractionalScaleAddon>> m_vFractionalScaleAddons;
+
+ wl_global* m_pGlobal = nullptr;
+ wl_listener m_liDisplayDestroy;
+}; \ No newline at end of file
diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp
index 309a6856..98afb154 100644
--- a/src/protocols/ToplevelExport.cpp
+++ b/src/protocols/ToplevelExport.cpp
@@ -53,7 +53,7 @@ void handleCaptureToplevelWithWlr(wl_client* client, wl_resource* resource, uint
g_pProtocolManager->m_pToplevelExportProtocolManager->captureToplevel(client, resource, frame, overlay_cursor, g_pCompositor->getWindowFromZWLRHandle(handle));
}
-void handleDestroy(wl_client* client, wl_resource* resource) {
+static void handleDestroy(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource);
}
@@ -74,8 +74,8 @@ static const struct hyprland_toplevel_export_manager_v1_interface toplevelExport
static const struct hyprland_toplevel_export_frame_v1_interface toplevelFrameImpl = {.copy = handleCopyFrame, .destroy = handleDestroyFrame};
SToplevelClient* clientFromResource(wl_resource* resource) {
- ASSERT(wl_resource_instance_of(resource, &hyprland_toplevel_export_manager_v1_interface, &toplevelExportManagerImpl));
- return (SToplevelClient*)wl_resource_get_user_data(resource);
+ ASSERT(wl_resource_instance_of(resource, &hyprland_toplevel_export_manager_v1_interface, &toplevelExportManagerImpl));
+ return (SToplevelClient*)wl_resource_get_user_data(resource);
}
SToplevelFrame* frameFromResource(wl_resource* resource) {
@@ -95,7 +95,7 @@ void CToplevelExportProtocolManager::removeClient(SToplevelClient* client, bool
m_lClients.remove(*client); // TODO: this doesn't get cleaned up after sharing app exits???
}
-void handleManagerResourceDestroy(wl_resource* resource) {
+static void handleManagerResourceDestroy(wl_resource* resource) {
const auto PCLIENT = clientFromResource(resource);
g_pProtocolManager->m_pToplevelExportProtocolManager->removeClient(PCLIENT, true);