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>
This commit is contained in:
Vaxry 2023-01-20 19:44:30 +01:00 committed by GitHub
parent cee7bc6e74
commit 60b880d931
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 210 additions and 56 deletions

View file

@ -130,4 +130,5 @@ target_link_libraries(Hyprland
${CMAKE_SOURCE_DIR}/ext-workspace-unstable-v1-protocol.o ${CMAKE_SOURCE_DIR}/ext-workspace-unstable-v1-protocol.o
${CMAKE_SOURCE_DIR}/wlr-foreign-toplevel-management-unstable-v1-protocol.o ${CMAKE_SOURCE_DIR}/wlr-foreign-toplevel-management-unstable-v1-protocol.o
${CMAKE_SOURCE_DIR}/hyprland-toplevel-export-v1-protocol.o ${CMAKE_SOURCE_DIR}/hyprland-toplevel-export-v1-protocol.o
${CMAKE_SOURCE_DIR}/fractional-scale-v1-protocol.o
) )

View file

@ -121,6 +121,16 @@ wlr-foreign-toplevel-management-unstable-v1-protocol.c:
wlr-foreign-toplevel-management-unstable-v1-protocol.o: wlr-foreign-toplevel-management-unstable-v1-protocol.h wlr-foreign-toplevel-management-unstable-v1-protocol.o: wlr-foreign-toplevel-management-unstable-v1-protocol.h
fractional-scale-v1-protocol.h:
$(WAYLAND_SCANNER) server-header \
$(WAYLAND_PROTOCOLS)/staging/fractional-scale/fractional-scale-v1.xml $@
fractional-scale-v1-protocol.c:
$(WAYLAND_SCANNER) private-code \
$(WAYLAND_PROTOCOLS)/staging/fractional-scale/fractional-scale-v1.xml $@
fractional-scale-v1-protocol.o: fractional-scale-v1-protocol.h
legacyrenderer: legacyrenderer:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
cmake --build ./build --config Release --target all -j$(shell nproc) cmake --build ./build --config Release --target all -j$(shell nproc)
@ -184,7 +194,7 @@ uninstall:
rm -f ${PREFIX}/share/man/man1/Hyprland.1 rm -f ${PREFIX}/share/man/man1/Hyprland.1
rm -f ${PREFIX}/share/man/man1/hyprctl.1 rm -f ${PREFIX}/share/man/man1/hyprctl.1
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o fractional-scale-v1-protocol.o
fixwlr: fixwlr:
sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build

View file

@ -21,6 +21,7 @@ wayland_scanner = find_program(
protocols = [ protocols = [
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
[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, 'staging/fractional-scale/fractional-scale-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'],
['wlr-output-power-management-unstable-v1.xml'], ['wlr-output-power-management-unstable-v1.xml'],

View file

@ -219,6 +219,9 @@ void CWindow::moveToWorkspace(int workspaceID) {
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); PWORKSPACE) { if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); PWORKSPACE) {
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", this, PWORKSPACE->m_szName.c_str())}); g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", this, PWORKSPACE->m_szName.c_str())});
} }
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(g_pXWaylandManager->getWindowSurface(this), PMONITOR->scale);
} }
} }

View file

@ -564,6 +564,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
// recalc the values for this window // recalc the values for this window
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PMONITOR->scale);
} }
void Events::listener_unmapWindow(void* owner, void* data) { void Events::listener_unmapWindow(void* owner, void* data) {

View file

@ -42,8 +42,10 @@ struct SLayerSurface {
} }
}; };
class CMonitor;
struct SRenderData { struct SRenderData {
wlr_output* output; CMonitor* pMonitor;
timespec* when; timespec* when;
int x, y; int x, y;
@ -51,7 +53,6 @@ struct SRenderData {
void* data = nullptr; void* data = nullptr;
wlr_surface* surface = nullptr; wlr_surface* surface = nullptr;
int w, h; int w, h;
void* pMonitor = nullptr;
// for rounding // for rounding
bool dontRound = true; bool dontRound = true;
@ -223,7 +224,7 @@ struct STablet {
std::string name = ""; std::string name = "";
bool operator==(const STablet& b) { bool operator==(const STablet& b) {
return wlrDevice == b.wlrDevice; return wlrDevice == b.wlrDevice;
} }
}; };

View file

@ -1,5 +1,6 @@
#include "ProtocolManager.hpp" #include "ProtocolManager.hpp"
CProtocolManager::CProtocolManager() { CProtocolManager::CProtocolManager() {
m_pToplevelExportProtocolManager = std::make_unique<CToplevelExportProtocolManager>(); m_pToplevelExportProtocolManager = std::make_unique<CToplevelExportProtocolManager>();
m_pFractionalScaleProtocolManager = std::make_unique<CFractionalScaleProtocolManager>();
} }

View file

@ -2,12 +2,14 @@
#include "../defines.hpp" #include "../defines.hpp"
#include "../protocols/ToplevelExport.hpp" #include "../protocols/ToplevelExport.hpp"
#include "../protocols/FractionalScale.hpp"
class CProtocolManager { class CProtocolManager {
public: public:
CProtocolManager(); CProtocolManager();
std::unique_ptr<CToplevelExportProtocolManager> m_pToplevelExportProtocolManager; std::unique_ptr<CToplevelExportProtocolManager> m_pToplevelExportProtocolManager;
std::unique_ptr<CFractionalScaleProtocolManager> m_pFractionalScaleProtocolManager;
}; };
inline std::unique_ptr<CProtocolManager> g_pProtocolManager; inline std::unique_ptr<CProtocolManager> g_pProtocolManager;

View file

@ -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; });
}

View file

@ -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;
};

View file

@ -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)); 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); 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}; static const struct hyprland_toplevel_export_frame_v1_interface toplevelFrameImpl = {.copy = handleCopyFrame, .destroy = handleDestroyFrame};
SToplevelClient* clientFromResource(wl_resource* resource) { SToplevelClient* clientFromResource(wl_resource* resource) {
ASSERT(wl_resource_instance_of(resource, &hyprland_toplevel_export_manager_v1_interface, &toplevelExportManagerImpl)); ASSERT(wl_resource_instance_of(resource, &hyprland_toplevel_export_manager_v1_interface, &toplevelExportManagerImpl));
return (SToplevelClient*)wl_resource_get_user_data(resource); return (SToplevelClient*)wl_resource_get_user_data(resource);
} }
SToplevelFrame* frameFromResource(wl_resource* 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??? 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); const auto PCLIENT = clientFromResource(resource);
g_pProtocolManager->m_pToplevelExportProtocolManager->removeClient(PCLIENT, true); g_pProtocolManager->m_pToplevelExportProtocolManager->removeClient(PCLIENT, true);

View file

@ -10,7 +10,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
return; return;
double outputX = 0, outputY = 0; double outputX = 0, outputY = 0;
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->output, &outputX, &outputY); wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->pMonitor->output, &outputX, &outputY);
wlr_box windowBox; wlr_box windowBox;
if (RDATA->surface && surface == RDATA->surface) if (RDATA->surface && surface == RDATA->surface)
@ -28,12 +28,12 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
if (RDATA->pWindow) if (RDATA->pWindow)
g_pHyprRenderer->calculateUVForWindowSurface(RDATA->pWindow, surface, RDATA->squishOversized); g_pHyprRenderer->calculateUVForWindowSurface(RDATA->pWindow, surface, RDATA->squishOversized);
scaleBox(&windowBox, RDATA->output->scale); scaleBox(&windowBox, RDATA->pMonitor->scale);
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding; float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
rounding *= RDATA->output->scale; rounding *= RDATA->pMonitor->scale;
rounding -= 1; // to fix a border issue rounding -= 1; // to fix a border issue
@ -52,7 +52,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
wlr_surface_send_frame_done(surface, RDATA->when); wlr_surface_send_frame_done(surface, RDATA->when);
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output); wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->pMonitor->output);
} }
// reset the UV, we might've set it above // reset the UV, we might've set it above
@ -230,7 +230,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
static auto* const PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue; static auto* const PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue;
static auto* const PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue; static auto* const PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue;
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y}; SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y};
if (ignorePosition) { if (ignorePosition) {
renderdata.x = pMonitor->vecPosition.x; renderdata.x = pMonitor->vecPosition.x;
renderdata.y = pMonitor->vecPosition.y; renderdata.y = pMonitor->vecPosition.y;
@ -352,7 +352,7 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times
return; return;
} }
SRenderData renderdata = {pMonitor->output, time, pLayer->geometry.x, pLayer->geometry.y}; SRenderData renderdata = {pMonitor, time, pLayer->geometry.x, pLayer->geometry.y};
renderdata.fadeAlpha = pLayer->alpha.fl(); renderdata.fadeAlpha = pLayer->alpha.fl();
renderdata.blur = pLayer->forceBlur; renderdata.blur = pLayer->forceBlur;
renderdata.surface = pLayer->layerSurface->surface; renderdata.surface = pLayer->layerSurface->surface;
@ -368,7 +368,7 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times
} }
void CHyprRenderer::renderIMEPopup(SIMEPopup* pPopup, CMonitor* pMonitor, timespec* time) { void CHyprRenderer::renderIMEPopup(SIMEPopup* pPopup, CMonitor* pMonitor, timespec* time) {
SRenderData renderdata = {pMonitor->output, time, pPopup->realX, pPopup->realY}; SRenderData renderdata = {pMonitor, time, pPopup->realX, pPopup->realY};
renderdata.blur = false; renderdata.blur = false;
renderdata.surface = pPopup->pSurface->surface; renderdata.surface = pPopup->pSurface->surface;
@ -544,45 +544,23 @@ void CHyprRenderer::calculateUVForWindowSurface(CWindow* pWindow, wlr_surface* p
Vector2D uvTL; Vector2D uvTL;
Vector2D uvBR = Vector2D(1, 1); Vector2D uvBR = Vector2D(1, 1);
wlr_box geom;
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
const auto SUBSURFACE = g_pXWaylandManager->getWindowSurface(pWindow) != pSurface && main;
// wp_viewporter_v1 implementation
if (pSurface->current.viewport.has_src) { if (pSurface->current.viewport.has_src) {
// we stretch it to dest. if no dest, to 1,1
wlr_fbox bufferSource; wlr_fbox bufferSource;
wlr_surface_get_buffer_source_box(pSurface, &bufferSource); wlr_surface_get_buffer_source_box(pSurface, &bufferSource);
Vector2D surfaceSize = Vector2D(pSurface->buffer->texture->width, pSurface->buffer->texture->height); Vector2D bufferSize = Vector2D(pSurface->buffer->texture->width, pSurface->buffer->texture->height);
uvTL = Vector2D(bufferSource.x / surfaceSize.x, bufferSource.y / surfaceSize.y); // calculate UV for the basic src_box. Assume dest == size. TODO: don't.
uvBR = Vector2D((bufferSource.x + bufferSource.width) / surfaceSize.x, (bufferSource.y + bufferSource.height) / surfaceSize.y); uvTL = Vector2D(bufferSource.x / bufferSize.x, bufferSource.y / bufferSize.y);
uvBR = Vector2D((bufferSource.x + bufferSource.width) / bufferSize.x, (bufferSource.y + bufferSource.height) / bufferSize.y);
if (uvBR.x < 0.01f || uvBR.y < 0.01f) { if (uvBR.x < 0.01f || uvBR.y < 0.01f) {
uvTL = Vector2D(); uvTL = Vector2D();
uvBR = Vector2D(1, 1); uvBR = Vector2D(1, 1);
} }
// TODO: (example: chromium) this still has a tiny "bump" at the end.
if (main) {
uvTL = uvTL +
(Vector2D((double)geom.x / ((double)pWindow->m_uSurface.xdg->surface->current.width),
(double)geom.y / ((double)pWindow->m_uSurface.xdg->surface->current.height)) *
(((uvBR.x - uvTL.x) * surfaceSize.x) / surfaceSize.x));
uvBR = uvBR *
Vector2D((double)(geom.width + geom.x) / ((double)pWindow->m_uSurface.xdg->surface->current.width),
(double)(geom.y + geom.height) / ((double)pWindow->m_uSurface.xdg->surface->current.height));
}
} else if (main) {
// oversized windows' UV adjusting
uvTL =
Vector2D((double)geom.x / ((double)pWindow->m_uSurface.xdg->surface->current.width), (double)geom.y / ((double)pWindow->m_uSurface.xdg->surface->current.height));
uvBR = Vector2D((double)(geom.width + geom.x) / ((double)pWindow->m_uSurface.xdg->surface->current.width),
(double)(geom.y + geom.height) / ((double)pWindow->m_uSurface.xdg->surface->current.height));
} }
// set UV
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL; g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL;
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = uvBR; g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = uvBR;
@ -593,20 +571,35 @@ void CHyprRenderer::calculateUVForWindowSurface(CWindow* pWindow, wlr_surface* p
} }
if (!main) if (!main)
return; // ignore the rest return;
// then, if the surface is too big, modify the pos UV wlr_box geom;
if ((geom.width > pWindow->m_vRealSize.vec().x + 1 || geom.height > pWindow->m_vRealSize.vec().y + 1) && !SUBSURFACE) { wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
const auto OFF = Vector2D(pWindow->m_vRealSize.vec().x / (double)geom.width, pWindow->m_vRealSize.vec().y / (double)geom.height);
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D(-1, -1)) // ignore X and Y, adjust uv
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(0, 0); if (geom.x != 0 || geom.y != 0) {
const auto XPERC = (double)geom.x / (double)pSurface->current.width;
const auto YPERC = (double)geom.y / (double)pSurface->current.height;
const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.width;
const auto HPERC = (double)(geom.y + geom.height) / (double)pSurface->current.height;
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y));
Vector2D(g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x * uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y));
(pWindow->m_vRealSize.vec().x / ((double)geom.width / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x)), uvTL = uvTL + TOADDTL;
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y *
(pWindow->m_vRealSize.vec().y / ((double)geom.height / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y))); if (geom.width > pWindow->m_vRealSize.vec().x || geom.height > pWindow->m_vRealSize.vec().y) {
uvBR.x = uvBR.x * (pWindow->m_vRealSize.vec().x / geom.width);
uvBR.y = uvBR.y * (pWindow->m_vRealSize.vec().y / geom.height);
}
}
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL;
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = uvBR;
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
// No special UV mods needed
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
} }
} else { } else {
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
@ -1119,7 +1112,7 @@ void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) {
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface)) if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
return; return;
SRenderData renderdata = {pMonitor->output, time, g_pInputManager->m_sDrag.pos.x, g_pInputManager->m_sDrag.pos.y}; SRenderData renderdata = {pMonitor, time, g_pInputManager->m_sDrag.pos.x, g_pInputManager->m_sDrag.pos.y};
renderdata.surface = g_pInputManager->m_sDrag.dragIcon->surface; renderdata.surface = g_pInputManager->m_sDrag.dragIcon->surface;
renderdata.w = g_pInputManager->m_sDrag.dragIcon->surface->current.width; renderdata.w = g_pInputManager->m_sDrag.dragIcon->surface->current.width;
renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height; renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height;