diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d4660c3..88f60038 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,4 +130,5 @@ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/ext-workspace-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}/fractional-scale-v1-protocol.o ) diff --git a/Makefile b/Makefile index 89cb200c..47a27d00 100644 --- a/Makefile +++ b/Makefile @@ -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 +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: 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) @@ -184,7 +194,7 @@ uninstall: rm -f ${PREFIX}/share/man/man1/Hyprland.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: sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build diff --git a/protocols/meson.build b/protocols/meson.build index 394ca1b8..9d47e0a6 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -21,6 +21,7 @@ wayland_scanner = find_program( protocols = [ [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.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-layer-shell-unstable-v1.xml'], ['wlr-output-power-management-unstable-v1.xml'], diff --git a/src/Window.cpp b/src/Window.cpp index cb0565bf..e64835be 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -219,6 +219,9 @@ void CWindow::moveToWorkspace(int workspaceID) { if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); PWORKSPACE) { 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); } } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 68ce4664..46ea5abf 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -564,6 +564,8 @@ void Events::listener_mapWindow(void* owner, void* data) { // recalc the values for this window g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); + + g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PMONITOR->scale); } void Events::listener_unmapWindow(void* owner, void* data) { diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 1c10a5e9..af070c78 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -42,8 +42,10 @@ struct SLayerSurface { } }; +class CMonitor; + struct SRenderData { - wlr_output* output; + CMonitor* pMonitor; timespec* when; int x, y; @@ -51,7 +53,6 @@ struct SRenderData { void* data = nullptr; wlr_surface* surface = nullptr; int w, h; - void* pMonitor = nullptr; // for rounding bool dontRound = true; @@ -223,7 +224,7 @@ struct STablet { std::string name = ""; bool operator==(const STablet& b) { - return wlrDevice == b.wlrDevice; + return wlrDevice == b.wlrDevice; } }; diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 34a6e679..4dd9ed79 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -1,5 +1,6 @@ #include "ProtocolManager.hpp" CProtocolManager::CProtocolManager() { - m_pToplevelExportProtocolManager = std::make_unique(); + m_pToplevelExportProtocolManager = std::make_unique(); + m_pFractionalScaleProtocolManager = std::make_unique(); } \ No newline at end of file diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 4e583a02..66d8ef20 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -2,12 +2,14 @@ #include "../defines.hpp" #include "../protocols/ToplevelExport.hpp" +#include "../protocols/FractionalScale.hpp" class CProtocolManager { public: CProtocolManager(); - std::unique_ptr m_pToplevelExportProtocolManager; + std::unique_ptr m_pToplevelExportProtocolManager; + std::unique_ptr m_pFractionalScaleProtocolManager; }; inline std::unique_ptr g_pProtocolManager; 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()); + + 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 +#include + +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> 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); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 43351eda..87896e64 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -10,7 +10,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { return; 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; 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) 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; 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 @@ -52,7 +52,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { 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 @@ -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 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) { renderdata.x = pMonitor->vecPosition.x; renderdata.y = pMonitor->vecPosition.y; @@ -352,7 +352,7 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times 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.blur = pLayer->forceBlur; 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) { - SRenderData renderdata = {pMonitor->output, time, pPopup->realX, pPopup->realY}; + SRenderData renderdata = {pMonitor, time, pPopup->realX, pPopup->realY}; renderdata.blur = false; renderdata.surface = pPopup->pSurface->surface; @@ -544,45 +544,23 @@ void CHyprRenderer::calculateUVForWindowSurface(CWindow* pWindow, wlr_surface* p Vector2D uvTL; 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) { + // we stretch it to dest. if no dest, to 1,1 wlr_fbox 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); - uvBR = Vector2D((bufferSource.x + bufferSource.width) / surfaceSize.x, (bufferSource.y + bufferSource.height) / surfaceSize.y); + // calculate UV for the basic src_box. Assume dest == size. TODO: don't. + 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) { uvTL = Vector2D(); 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.primarySurfaceUVBottomRight = uvBR; @@ -593,20 +571,35 @@ void CHyprRenderer::calculateUVForWindowSurface(CWindow* pWindow, wlr_surface* p } if (!main) - return; // ignore the rest + return; - // then, if the surface is too big, modify the pos UV - if ((geom.width > pWindow->m_vRealSize.vec().x + 1 || geom.height > pWindow->m_vRealSize.vec().y + 1) && !SUBSURFACE) { - const auto OFF = Vector2D(pWindow->m_vRealSize.vec().x / (double)geom.width, pWindow->m_vRealSize.vec().y / (double)geom.height); + wlr_box geom; + wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom); - if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D(-1, -1)) - g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(0, 0); + // ignore X and Y, adjust uv + 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 = - Vector2D(g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x * - (pWindow->m_vRealSize.vec().x / ((double)geom.width / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x)), - g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y * - (pWindow->m_vRealSize.vec().y / ((double)geom.height / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y))); + const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y)); + uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y)); + uvTL = uvTL + TOADDTL; + + 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 { 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)) 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.w = g_pInputManager->m_sDrag.dragIcon->surface->current.width; renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height;