2022-03-17 20:22:29 +01:00
|
|
|
#include "Renderer.hpp"
|
|
|
|
#include "../Compositor.hpp"
|
2022-11-05 13:50:47 +01:00
|
|
|
#include "linux-dmabuf-unstable-v1-protocol.h"
|
2022-03-17 20:22:29 +01:00
|
|
|
|
|
|
|
void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
|
|
|
const auto TEXTURE = wlr_surface_get_texture(surface);
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto RDATA = (SRenderData*)data;
|
2022-03-17 20:22:29 +01:00
|
|
|
|
|
|
|
if (!TEXTURE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
double outputX = 0, outputY = 0;
|
2023-01-20 19:44:30 +01:00
|
|
|
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->pMonitor->output, &outputX, &outputY);
|
2022-03-17 20:22:29 +01:00
|
|
|
|
2022-03-23 22:01:59 +01:00
|
|
|
wlr_box windowBox;
|
2022-07-04 15:58:12 +02:00
|
|
|
if (RDATA->surface && surface == RDATA->surface)
|
2022-06-29 12:54:53 +02:00
|
|
|
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
|
2022-12-16 18:17:31 +01:00
|
|
|
else // here we clamp to 2, these might be some tiny specks
|
2022-09-26 21:10:24 +02:00
|
|
|
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max(surface->current.width, 2), std::max(surface->current.height, 2)};
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2022-07-11 23:38:10 +02:00
|
|
|
if (RDATA->squishOversized) {
|
|
|
|
if (x + windowBox.width > RDATA->w)
|
|
|
|
windowBox.width = RDATA->w - x;
|
2022-07-15 19:07:06 +02:00
|
|
|
if (y + windowBox.height > RDATA->h)
|
2022-07-11 23:38:10 +02:00
|
|
|
windowBox.height = RDATA->h - y;
|
|
|
|
}
|
2022-08-28 10:14:43 +02:00
|
|
|
|
|
|
|
if (RDATA->pWindow)
|
|
|
|
g_pHyprRenderer->calculateUVForWindowSurface(RDATA->pWindow, surface, RDATA->squishOversized);
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2023-01-20 19:44:30 +01:00
|
|
|
scaleBox(&windowBox, RDATA->pMonitor->scale);
|
2022-03-17 20:22:29 +01:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
2022-06-07 20:41:40 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
|
2023-01-20 19:44:30 +01:00
|
|
|
rounding *= RDATA->pMonitor->scale;
|
2022-05-28 17:48:01 +02:00
|
|
|
|
2022-08-20 22:45:30 +02:00
|
|
|
rounding -= 1; // to fix a border issue
|
|
|
|
|
2022-06-22 15:45:56 +02:00
|
|
|
if (RDATA->surface && surface == RDATA->surface) {
|
2023-01-05 19:25:45 +01:00
|
|
|
if (wlr_surface_is_xwayland_surface(surface) && !wlr_xwayland_surface_from_wlr_surface(surface)->has_alpha && RDATA->fadeAlpha * RDATA->alpha == 1.f) {
|
2022-07-06 22:12:03 +02:00
|
|
|
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true);
|
2022-07-27 13:30:55 +02:00
|
|
|
} else {
|
|
|
|
if (RDATA->blur)
|
2022-12-04 21:57:41 +01:00
|
|
|
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->blockBlurOptimization);
|
2022-07-27 13:30:55 +02:00
|
|
|
else
|
|
|
|
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true);
|
|
|
|
}
|
2022-12-16 18:17:31 +01:00
|
|
|
} else {
|
2022-08-28 10:14:43 +02:00
|
|
|
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true);
|
2022-07-04 15:58:12 +02:00
|
|
|
}
|
2022-03-17 20:22:29 +01:00
|
|
|
|
2022-12-05 20:11:02 +01:00
|
|
|
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
|
|
|
|
wlr_surface_send_frame_done(surface, RDATA->when);
|
2023-01-20 19:44:30 +01:00
|
|
|
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->pMonitor->output);
|
2022-12-05 20:11:02 +01:00
|
|
|
}
|
2022-08-28 10:41:47 +02:00
|
|
|
|
|
|
|
// reset the UV, we might've set it above
|
2022-12-16 18:17:31 +01:00
|
|
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
2022-08-28 10:41:47 +02:00
|
|
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
2022-03-17 20:22:29 +01:00
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor) {
|
2022-05-30 14:55:42 +02:00
|
|
|
wlr_box geometry = pWindow->getFullWindowBoundingBox();
|
2022-03-20 18:49:40 +01:00
|
|
|
|
|
|
|
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
|
|
|
|
return false;
|
|
|
|
|
2022-09-10 13:11:02 +02:00
|
|
|
if (pWindow->m_bPinned)
|
|
|
|
return true;
|
|
|
|
|
2022-03-20 18:49:40 +01:00
|
|
|
// now check if it has the same workspace
|
2022-07-28 16:33:45 +02:00
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
|
|
|
|
2022-07-28 17:56:11 +02:00
|
|
|
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID) {
|
2022-09-12 15:33:20 +02:00
|
|
|
if (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering) {
|
2022-08-18 12:42:21 +02:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
if (!(!PWORKSPACE->m_bHasFullscreenWindow || pWindow->m_bIsFullscreen || (pWindow->m_bIsFloating && pWindow->m_bCreatedOverFullscreen)))
|
|
|
|
return false;
|
|
|
|
}
|
2022-07-28 16:33:45 +02:00
|
|
|
}
|
|
|
|
|
2022-03-20 18:49:40 +01:00
|
|
|
if (pWindow->m_iWorkspaceID == pMonitor->activeWorkspace)
|
|
|
|
return true;
|
|
|
|
|
2022-08-18 12:41:10 +02:00
|
|
|
// if not, check if it maybe is active on a different monitor.
|
2022-10-12 19:37:11 +02:00
|
|
|
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) && pWindow->m_bIsFloating /* tiled windows can't be multi-ws */)
|
2022-08-18 12:41:10 +02:00
|
|
|
return !pWindow->m_bIsFullscreen; // Do not draw fullscreen windows on other monitors
|
2022-03-20 18:49:40 +01:00
|
|
|
|
2022-12-11 17:53:59 +01:00
|
|
|
if (pMonitor->specialWorkspaceID == pWindow->m_iWorkspaceID)
|
2022-05-31 14:01:00 +02:00
|
|
|
return true;
|
|
|
|
|
2022-03-20 18:49:40 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-05-31 22:16:13 +02:00
|
|
|
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
|
|
|
|
|
|
|
|
if (!g_pCompositor->windowValidMapped(pWindow))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
|
|
|
|
2022-09-12 15:33:20 +02:00
|
|
|
if (pWindow->m_bPinned || PWORKSPACE->m_bForceRendering)
|
2022-09-10 13:11:02 +02:00
|
|
|
return true;
|
|
|
|
|
2022-05-31 22:16:13 +02:00
|
|
|
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
|
|
|
return true;
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
|
|
|
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
|
2022-05-31 22:16:13 +02:00
|
|
|
return true;
|
|
|
|
|
2022-11-27 23:42:22 +01:00
|
|
|
if (m->specialWorkspaceID && g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID))
|
2022-05-31 22:16:13 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) {
|
2022-03-30 20:16:23 +02:00
|
|
|
CWindow* pWorkspaceWindow = nullptr;
|
|
|
|
|
2022-09-19 18:26:11 +02:00
|
|
|
// loop over the tiled windows that are fading out
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
|
|
|
if (w->m_iWorkspaceID != pMonitor->activeWorkspace)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (w->m_fAlpha.fl() == 0.f)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (w->m_bIsFullscreen || w->m_bIsFloating)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// and floating ones too
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
|
|
|
if (w->m_iWorkspaceID != pMonitor->activeWorkspace)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (w->m_fAlpha.fl() == 0.f)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (w->m_bIsFullscreen || !w->m_bIsFloating)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
|
|
|
}
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2022-07-28 15:56:55 +02:00
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID);
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen) {
|
2022-09-19 11:23:13 +02:00
|
|
|
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering)))
|
2022-07-28 15:56:55 +02:00
|
|
|
continue;
|
2022-08-17 12:12:16 +02:00
|
|
|
|
|
|
|
if (w->m_iMonitorID != pMonitor->ID)
|
|
|
|
continue;
|
2022-07-28 15:56:55 +02:00
|
|
|
}
|
2022-03-21 19:18:33 +01:00
|
|
|
|
2022-07-28 16:33:45 +02:00
|
|
|
if (w->m_iWorkspaceID == pMonitor->activeWorkspace && !w->m_bIsFullscreen)
|
|
|
|
continue;
|
|
|
|
|
2022-07-12 09:49:56 +02:00
|
|
|
renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL);
|
2022-03-30 20:16:23 +02:00
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
pWorkspaceWindow = w.get();
|
2022-03-30 20:16:23 +02:00
|
|
|
}
|
|
|
|
|
2022-10-11 21:29:37 +02:00
|
|
|
if (!pWorkspaceWindow) {
|
|
|
|
// ?? happens sometimes...
|
|
|
|
pWorkspace->m_bHasFullscreenWindow = false;
|
|
|
|
return; // this will produce one blank frame. Oh well.
|
|
|
|
}
|
|
|
|
|
2022-09-19 18:26:11 +02:00
|
|
|
// then render windows over fullscreen.
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2022-09-10 13:11:02 +02:00
|
|
|
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || !w->m_bIsMapped)
|
2022-03-30 20:16:23 +02:00
|
|
|
continue;
|
|
|
|
|
2022-07-12 09:49:56 +02:00
|
|
|
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
2022-05-31 14:20:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// and then special windows
|
2022-12-16 18:17:31 +01:00
|
|
|
if (pMonitor->specialWorkspaceID)
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
|
|
|
if (!g_pCompositor->windowValidMapped(w.get()) && !w->m_bFadingOut)
|
|
|
|
continue;
|
2022-05-31 14:20:41 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
if (w->m_iWorkspaceID != pMonitor->specialWorkspaceID)
|
|
|
|
continue;
|
2022-05-31 14:20:41 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
if (!shouldRenderWindow(w.get(), pMonitor))
|
|
|
|
continue;
|
2022-05-31 14:20:41 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
// render the bad boy
|
|
|
|
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
|
|
|
}
|
2022-03-31 17:25:23 +02:00
|
|
|
|
2022-04-25 21:49:45 +02:00
|
|
|
// and the overlay layers
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
2022-09-19 11:23:13 +02:00
|
|
|
if (ls->alpha.fl() != 0.f)
|
2022-07-23 15:48:08 +02:00
|
|
|
renderLayer(ls.get(), pMonitor, time);
|
2022-05-29 15:44:30 +02:00
|
|
|
}
|
|
|
|
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
2022-07-23 15:48:08 +02:00
|
|
|
renderLayer(ls.get(), pMonitor, time);
|
2022-04-25 21:49:45 +02:00
|
|
|
}
|
|
|
|
|
2022-03-31 17:25:23 +02:00
|
|
|
renderDragIcon(pMonitor, time);
|
2022-04-08 21:40:41 +02:00
|
|
|
|
|
|
|
// if correct monitor draw hyprerror
|
2022-06-30 15:44:26 +02:00
|
|
|
if (pMonitor == g_pCompositor->m_vMonitors.front().get())
|
2022-04-08 21:40:41 +02:00
|
|
|
g_pHyprError->draw();
|
2022-03-21 19:18:33 +01:00
|
|
|
}
|
|
|
|
|
2022-12-05 18:05:15 +01:00
|
|
|
void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool ignoreAllGeometry) {
|
2022-10-14 21:46:32 +02:00
|
|
|
if (pWindow->isHidden())
|
2022-04-12 16:44:18 +02:00
|
|
|
return;
|
|
|
|
|
2022-04-05 20:49:15 +02:00
|
|
|
if (pWindow->m_bFadingOut) {
|
2022-05-28 18:52:22 +02:00
|
|
|
if (pMonitor->ID == pWindow->m_iMonitorID) // TODO: fix this
|
|
|
|
g_pHyprOpenGL->renderSnapshot(&pWindow);
|
2022-04-05 20:49:15 +02:00
|
|
|
return;
|
|
|
|
}
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
|
|
|
const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec());
|
|
|
|
static auto* const PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue;
|
2022-12-28 15:39:17 +01:00
|
|
|
static auto* const PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue;
|
2022-06-21 22:54:41 +02:00
|
|
|
|
2023-01-20 19:44:30 +01:00
|
|
|
SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y};
|
2022-11-06 18:52:09 +01:00
|
|
|
if (ignorePosition) {
|
2022-11-06 18:58:56 +01:00
|
|
|
renderdata.x = pMonitor->vecPosition.x;
|
|
|
|
renderdata.y = pMonitor->vecPosition.y;
|
2022-11-06 18:52:09 +01:00
|
|
|
}
|
|
|
|
|
2022-12-05 18:05:15 +01:00
|
|
|
if (ignoreAllGeometry)
|
|
|
|
decorate = false;
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
|
|
|
|
renderdata.w = std::max(pWindow->m_vRealSize.vec().x, 5.0); // clamp the size to min 5,
|
|
|
|
renderdata.h = std::max(pWindow->m_vRealSize.vec().y, 5.0); // otherwise we'll have issues later with invalid boxes
|
2022-08-01 12:57:37 +02:00
|
|
|
renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding);
|
2023-01-05 19:25:45 +01:00
|
|
|
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.fl());
|
2022-12-16 18:17:31 +01:00
|
|
|
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
|
|
|
|
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) &&
|
|
|
|
(!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
|
2023-01-24 20:05:34 +01:00
|
|
|
renderdata.rounding = ignoreAllGeometry ? 0 : pWindow->m_sAdditionalConfigData.rounding.toUnderlying();
|
2022-12-16 18:17:31 +01:00
|
|
|
renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later
|
|
|
|
renderdata.pWindow = pWindow;
|
2022-03-21 19:18:33 +01:00
|
|
|
|
2022-12-05 19:00:57 +01:00
|
|
|
if (ignoreAllGeometry) {
|
2022-12-16 18:17:31 +01:00
|
|
|
renderdata.alpha = 1.f;
|
2023-01-05 19:25:45 +01:00
|
|
|
renderdata.fadeAlpha = 1.f;
|
2022-12-05 19:00:57 +01:00
|
|
|
}
|
|
|
|
|
2022-07-28 12:07:41 +02:00
|
|
|
// apply opaque
|
|
|
|
if (pWindow->m_sAdditionalConfigData.forceOpaque)
|
|
|
|
renderdata.alpha = 1.f;
|
|
|
|
|
2022-05-17 13:16:37 +02:00
|
|
|
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
|
2022-03-21 19:18:33 +01:00
|
|
|
|
2022-12-28 19:56:18 +01:00
|
|
|
if (*PDIMAROUND && pWindow->m_sAdditionalConfigData.dimAround && !m_bRenderingSnapshot && mode != RENDER_PASS_POPUP) {
|
2023-01-16 16:12:22 +01:00
|
|
|
wlr_box monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y};
|
2022-12-28 15:39:17 +01:00
|
|
|
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha));
|
|
|
|
}
|
|
|
|
|
2022-10-07 11:35:17 +02:00
|
|
|
// clip box for animated offsets
|
2022-10-07 13:34:54 +02:00
|
|
|
Vector2D offset;
|
2022-12-11 17:58:29 +01:00
|
|
|
if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned) {
|
2022-11-06 19:10:53 +01:00
|
|
|
if (PWORKSPACE->m_vRenderOffset.vec().x != 0) {
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
2022-11-06 19:10:53 +01:00
|
|
|
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.vec().x / PWSMON->vecSize.x;
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto WINBB = pWindow->getFullWindowBoundingBox();
|
2022-11-06 19:10:53 +01:00
|
|
|
|
|
|
|
if (WINBB.x < PWSMON->vecPosition.x) {
|
|
|
|
offset.x = (PWSMON->vecPosition.x - WINBB.x) * PROGRESS;
|
2022-11-16 16:17:01 +01:00
|
|
|
} else if (WINBB.x + WINBB.width > PWSMON->vecPosition.x + PWSMON->vecSize.x) {
|
|
|
|
offset.x = (WINBB.x + WINBB.width - PWSMON->vecPosition.x - PWSMON->vecSize.x) * PROGRESS;
|
2022-11-06 19:10:53 +01:00
|
|
|
}
|
|
|
|
} else if (PWORKSPACE->m_vRenderOffset.vec().y) {
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
2022-11-06 19:10:53 +01:00
|
|
|
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.vec().y / PWSMON->vecSize.y;
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto WINBB = pWindow->getFullWindowBoundingBox();
|
2022-11-06 19:10:53 +01:00
|
|
|
|
|
|
|
if (WINBB.y < PWSMON->vecPosition.y) {
|
|
|
|
offset.y = (PWSMON->vecPosition.y - WINBB.y) * PROGRESS;
|
2022-11-16 16:17:01 +01:00
|
|
|
} else if (WINBB.y + WINBB.height > PWSMON->vecPosition.y + PWSMON->vecSize.y) {
|
|
|
|
offset.y = (WINBB.y + WINBB.width - PWSMON->vecPosition.y - PWSMON->vecSize.y) * PROGRESS;
|
2022-11-06 19:10:53 +01:00
|
|
|
}
|
2022-10-07 13:34:54 +02:00
|
|
|
}
|
|
|
|
|
2022-11-06 19:10:53 +01:00
|
|
|
renderdata.x += offset.x;
|
|
|
|
renderdata.y += offset.y;
|
|
|
|
}
|
2022-12-16 18:17:31 +01:00
|
|
|
|
2022-06-28 15:45:38 +02:00
|
|
|
// render window decorations first, if not fullscreen full
|
2022-07-12 09:49:56 +02:00
|
|
|
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) {
|
2022-12-16 18:17:31 +01:00
|
|
|
if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL)
|
|
|
|
for (auto& wd : pWindow->m_dWindowDecorations)
|
2023-01-05 19:25:45 +01:00
|
|
|
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, offset);
|
2022-06-22 15:45:56 +02:00
|
|
|
|
2022-07-12 09:49:56 +02:00
|
|
|
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
|
|
|
|
|
2022-08-16 16:19:52 +02:00
|
|
|
if (renderdata.decorate && pWindow->m_sSpecialRenderData.border) {
|
2022-12-16 18:17:31 +01:00
|
|
|
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
2022-07-16 20:57:59 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
float rounding = renderdata.dontRound ? 0 : renderdata.rounding == -1 ? *PROUNDING : renderdata.rounding;
|
2022-08-10 18:22:01 +02:00
|
|
|
rounding *= pMonitor->scale;
|
2022-07-16 20:57:59 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
auto grad = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor;
|
2022-11-26 18:56:43 +01:00
|
|
|
const bool ANIMATED = g_pHyprOpenGL->m_pCurrentWindow->m_fBorderAnimationProgress.isBeingAnimated();
|
2023-01-05 19:25:45 +01:00
|
|
|
float a1 = renderdata.fadeAlpha * renderdata.alpha * (ANIMATED ? g_pHyprOpenGL->m_pCurrentWindow->m_fBorderAnimationProgress.fl() : 1.f);
|
2022-07-16 20:57:59 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
wlr_box windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
|
2022-07-16 20:57:59 +02:00
|
|
|
|
2022-07-16 23:29:42 +02:00
|
|
|
scaleBox(&windowBox, pMonitor->scale);
|
|
|
|
|
2022-11-26 18:56:43 +01:00
|
|
|
g_pHyprOpenGL->renderBorder(&windowBox, grad, rounding, a1);
|
|
|
|
|
|
|
|
if (ANIMATED) {
|
2023-01-05 19:25:45 +01:00
|
|
|
float a2 = renderdata.fadeAlpha * renderdata.alpha * (1.f - g_pHyprOpenGL->m_pCurrentWindow->m_fBorderAnimationProgress.fl());
|
2022-11-26 18:56:43 +01:00
|
|
|
g_pHyprOpenGL->renderBorder(&windowBox, g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColorPrevious, rounding, a2);
|
|
|
|
}
|
2022-07-16 20:57:59 +02:00
|
|
|
}
|
2022-06-22 15:45:56 +02:00
|
|
|
}
|
|
|
|
|
2022-07-12 09:49:56 +02:00
|
|
|
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) {
|
|
|
|
if (!pWindow->m_bIsX11) {
|
2022-08-28 10:14:43 +02:00
|
|
|
wlr_box geom;
|
|
|
|
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
|
|
|
|
|
|
|
renderdata.x -= geom.x;
|
|
|
|
renderdata.y -= geom.y;
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
renderdata.dontRound = true; // don't round popups
|
|
|
|
renderdata.pMonitor = pMonitor;
|
2022-07-15 19:07:06 +02:00
|
|
|
renderdata.squishOversized = false; // don't squish popups
|
2022-07-12 09:49:56 +02:00
|
|
|
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
|
|
|
|
}
|
2022-05-17 13:16:37 +02:00
|
|
|
}
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
g_pHyprOpenGL->m_pCurrentWindow = nullptr;
|
|
|
|
g_pHyprOpenGL->m_RenderData.clipBox = {0, 0, 0, 0};
|
2022-03-21 19:18:33 +01:00
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, timespec* time) {
|
2022-05-14 17:23:46 +02:00
|
|
|
if (pLayer->fadingOut) {
|
|
|
|
g_pHyprOpenGL->renderSnapshot(&pLayer);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-20 19:44:30 +01:00
|
|
|
SRenderData renderdata = {pMonitor, time, pLayer->geometry.x, pLayer->geometry.y};
|
2022-12-16 18:17:31 +01:00
|
|
|
renderdata.fadeAlpha = pLayer->alpha.fl();
|
|
|
|
renderdata.blur = pLayer->forceBlur;
|
|
|
|
renderdata.surface = pLayer->layerSurface->surface;
|
|
|
|
renderdata.decorate = false;
|
|
|
|
renderdata.w = pLayer->layerSurface->surface->current.width;
|
|
|
|
renderdata.h = pLayer->layerSurface->surface->current.height;
|
2022-12-04 21:57:41 +01:00
|
|
|
renderdata.blockBlurOptimization = pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM || pLayer->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND;
|
2022-05-14 17:23:46 +02:00
|
|
|
wlr_surface_for_each_surface(pLayer->layerSurface->surface, renderSurface, &renderdata);
|
2022-07-27 18:02:20 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
renderdata.squishOversized = false; // don't squish popups
|
|
|
|
renderdata.dontRound = true;
|
2022-07-27 18:02:20 +02:00
|
|
|
wlr_layer_surface_v1_for_each_popup_surface(pLayer->layerSurface, renderSurface, &renderdata);
|
2022-05-14 17:23:46 +02:00
|
|
|
}
|
|
|
|
|
2022-08-05 17:07:01 +02:00
|
|
|
void CHyprRenderer::renderIMEPopup(SIMEPopup* pPopup, CMonitor* pMonitor, timespec* time) {
|
2023-01-20 19:44:30 +01:00
|
|
|
SRenderData renderdata = {pMonitor, time, pPopup->realX, pPopup->realY};
|
2022-08-05 17:07:01 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
renderdata.blur = false;
|
|
|
|
renderdata.surface = pPopup->pSurface->surface;
|
2022-08-05 17:07:01 +02:00
|
|
|
renderdata.decorate = false;
|
2022-12-16 18:17:31 +01:00
|
|
|
renderdata.w = pPopup->pSurface->surface->current.width;
|
|
|
|
renderdata.h = pPopup->pSurface->surface->current.height;
|
2022-08-05 17:07:01 +02:00
|
|
|
|
|
|
|
wlr_surface_for_each_surface(pPopup->pSurface->surface, renderSurface, &renderdata);
|
|
|
|
}
|
|
|
|
|
2022-03-17 20:22:29 +01:00
|
|
|
void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
2022-12-28 15:18:23 +01:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(ID);
|
|
|
|
static auto* const PDIMSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:dim_special")->floatValue;
|
2022-03-17 20:22:29 +01:00
|
|
|
|
|
|
|
if (!PMONITOR)
|
|
|
|
return;
|
|
|
|
|
2022-03-19 13:35:04 +01:00
|
|
|
// Render layer surfaces below windows for monitor
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
|
2022-07-23 15:48:08 +02:00
|
|
|
renderLayer(ls.get(), PMONITOR, time);
|
2022-03-19 13:35:04 +01:00
|
|
|
}
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
|
2022-07-23 15:48:08 +02:00
|
|
|
renderLayer(ls.get(), PMONITOR, time);
|
2022-03-19 13:35:04 +01:00
|
|
|
}
|
|
|
|
|
2022-08-01 12:23:09 +02:00
|
|
|
// pre window pass
|
|
|
|
g_pHyprOpenGL->preWindowPass();
|
|
|
|
|
2022-03-21 19:18:33 +01:00
|
|
|
// if there is a fullscreen window, render it and then do not render anymore.
|
|
|
|
// fullscreen window will hide other windows and top layers
|
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
2022-03-18 20:03:39 +01:00
|
|
|
|
2022-04-11 19:51:37 +02:00
|
|
|
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
2022-03-21 19:18:33 +01:00
|
|
|
renderWorkspaceWithFullscreenWindow(PMONITOR, PWORKSPACE, time);
|
|
|
|
return;
|
2022-03-17 20:22:29 +01:00
|
|
|
}
|
2022-03-18 20:03:39 +01:00
|
|
|
|
2022-11-20 19:50:01 +01:00
|
|
|
CWindow* lastWindow = nullptr;
|
|
|
|
|
2022-07-12 09:49:56 +02:00
|
|
|
// Non-floating main
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2022-10-14 21:46:32 +02:00
|
|
|
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
|
2022-07-12 09:49:56 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (w->m_bIsFloating)
|
2022-12-16 18:17:31 +01:00
|
|
|
continue; // floating are in the second pass
|
2022-07-12 09:49:56 +02:00
|
|
|
|
2022-11-27 23:42:22 +01:00
|
|
|
if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
2022-12-16 18:17:31 +01:00
|
|
|
continue; // special are in the third pass
|
2022-07-12 09:49:56 +02:00
|
|
|
|
|
|
|
if (!shouldRenderWindow(w.get(), PMONITOR))
|
|
|
|
continue;
|
2022-12-16 18:17:31 +01:00
|
|
|
|
2022-11-20 19:50:01 +01:00
|
|
|
// render active window after all others of this pass
|
|
|
|
if (w.get() == g_pCompositor->m_pLastWindow) {
|
|
|
|
lastWindow = w.get();
|
|
|
|
continue;
|
|
|
|
}
|
2022-07-12 09:49:56 +02:00
|
|
|
|
|
|
|
// render the bad boy
|
|
|
|
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_MAIN);
|
|
|
|
}
|
|
|
|
|
2022-11-20 19:50:01 +01:00
|
|
|
if (lastWindow)
|
|
|
|
renderWindow(lastWindow, PMONITOR, time, true, RENDER_PASS_MAIN);
|
|
|
|
|
2022-07-12 09:49:56 +02:00
|
|
|
// Non-floating popup
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2022-10-14 21:46:32 +02:00
|
|
|
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
|
2022-03-18 23:52:36 +01:00
|
|
|
continue;
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
if (w->m_bIsFloating)
|
2022-12-16 18:17:31 +01:00
|
|
|
continue; // floating are in the second pass
|
2022-05-31 14:01:00 +02:00
|
|
|
|
2022-11-27 23:42:22 +01:00
|
|
|
if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
2022-05-31 14:01:00 +02:00
|
|
|
continue; // special are in the third pass
|
2022-03-22 17:14:07 +01:00
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
if (!shouldRenderWindow(w.get(), PMONITOR))
|
2022-03-22 17:14:07 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// render the bad boy
|
2022-07-12 09:49:56 +02:00
|
|
|
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_POPUP);
|
2022-03-22 17:14:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// floating on top
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2022-10-14 21:46:32 +02:00
|
|
|
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
|
2022-03-22 17:14:07 +01:00
|
|
|
continue;
|
|
|
|
|
2022-12-21 00:07:17 +01:00
|
|
|
if (!w->m_bIsFloating || w->m_bPinned)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!shouldRenderWindow(w.get(), PMONITOR))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// render the bad boy
|
|
|
|
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// pinned always above
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
|
|
|
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!w->m_bPinned || !w->m_bIsFloating)
|
2022-03-22 17:14:07 +01:00
|
|
|
continue;
|
|
|
|
|
2022-11-27 23:42:22 +01:00
|
|
|
if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
2022-05-31 14:01:00 +02:00
|
|
|
continue;
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
if (!shouldRenderWindow(w.get(), PMONITOR))
|
2022-05-31 14:01:00 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// render the bad boy
|
2022-07-12 09:49:56 +02:00
|
|
|
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
|
2022-05-31 14:01:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// and then special
|
2022-12-28 15:18:23 +01:00
|
|
|
bool renderedSpecialBG = false;
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2022-10-14 21:46:32 +02:00
|
|
|
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
|
2022-05-31 14:01:00 +02:00
|
|
|
continue;
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2022-11-27 23:42:22 +01:00
|
|
|
if (!g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
2022-05-31 14:01:00 +02:00
|
|
|
continue;
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
if (!shouldRenderWindow(w.get(), PMONITOR))
|
2022-03-18 20:03:39 +01:00
|
|
|
continue;
|
|
|
|
|
2022-12-28 15:18:23 +01:00
|
|
|
if (!renderedSpecialBG) {
|
|
|
|
if (*PDIMSPECIAL != 0.f) {
|
|
|
|
const auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID);
|
|
|
|
|
|
|
|
const auto SPECIALANIMPROGRS =
|
2022-12-29 12:30:43 +01:00
|
|
|
PSPECIALWORKSPACE->m_vRenderOffset.isBeingAnimated() ? PSPECIALWORKSPACE->m_vRenderOffset.getCurveValue() : PSPECIALWORKSPACE->m_fAlpha.getCurveValue();
|
2022-12-28 15:18:23 +01:00
|
|
|
|
|
|
|
const bool ANIMOUT = !PMONITOR->specialWorkspaceID;
|
|
|
|
|
2023-01-16 16:12:22 +01:00
|
|
|
wlr_box monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
2023-01-05 19:25:45 +01:00
|
|
|
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)));
|
2022-12-28 15:18:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
renderedSpecialBG = true;
|
|
|
|
}
|
|
|
|
|
2022-03-18 20:42:49 +01:00
|
|
|
// render the bad boy
|
2022-07-12 09:49:56 +02:00
|
|
|
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
|
2022-03-18 20:03:39 +01:00
|
|
|
}
|
2022-03-19 13:35:04 +01:00
|
|
|
|
|
|
|
// Render surfaces above windows for monitor
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
2022-07-23 15:48:08 +02:00
|
|
|
renderLayer(ls.get(), PMONITOR, time);
|
2022-03-19 13:35:04 +01:00
|
|
|
}
|
2022-08-05 17:07:01 +02:00
|
|
|
|
|
|
|
// Render IME popups
|
|
|
|
for (auto& imep : g_pInputManager->m_sIMERelay.m_lIMEPopups) {
|
|
|
|
renderIMEPopup(&imep, PMONITOR, time);
|
|
|
|
}
|
|
|
|
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto ls = PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].rbegin(); ls != PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].rend();
|
2022-12-27 15:25:51 +01:00
|
|
|
ls++) {
|
|
|
|
renderLayer(ls->get(), PMONITOR, time);
|
2022-03-19 13:35:04 +01:00
|
|
|
}
|
2022-03-31 17:25:23 +02:00
|
|
|
|
|
|
|
renderDragIcon(PMONITOR, time);
|
2022-03-17 20:22:29 +01:00
|
|
|
}
|
2022-03-19 14:07:18 +01:00
|
|
|
|
2022-08-28 10:14:43 +02:00
|
|
|
void CHyprRenderer::calculateUVForWindowSurface(CWindow* pWindow, wlr_surface* pSurface, bool main) {
|
|
|
|
if (!pWindow->m_bIsX11) {
|
|
|
|
Vector2D uvTL;
|
|
|
|
Vector2D uvBR = Vector2D(1, 1);
|
|
|
|
|
|
|
|
if (pSurface->current.viewport.has_src) {
|
2023-01-20 19:44:30 +01:00
|
|
|
// we stretch it to dest. if no dest, to 1,1
|
2022-08-28 10:14:43 +02:00
|
|
|
wlr_fbox bufferSource;
|
|
|
|
wlr_surface_get_buffer_source_box(pSurface, &bufferSource);
|
|
|
|
|
2023-01-20 19:44:30 +01:00
|
|
|
Vector2D bufferSize = Vector2D(pSurface->buffer->texture->width, pSurface->buffer->texture->height);
|
2022-08-28 10:14:43 +02:00
|
|
|
|
2023-01-20 19:44:30 +01:00
|
|
|
// 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);
|
2022-08-28 10:14:43 +02:00
|
|
|
|
2022-08-28 14:32:06 +02:00
|
|
|
if (uvBR.x < 0.01f || uvBR.y < 0.01f) {
|
|
|
|
uvTL = Vector2D();
|
2022-12-16 18:17:31 +01:00
|
|
|
uvBR = Vector2D(1, 1);
|
2022-08-28 14:32:06 +02:00
|
|
|
}
|
2022-08-28 10:14:43 +02:00
|
|
|
}
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL;
|
2022-08-28 10:14:43 +02:00
|
|
|
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
|
2022-12-16 18:17:31 +01:00
|
|
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
2022-08-28 10:14:43 +02:00
|
|
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!main)
|
2023-01-20 19:44:30 +01:00
|
|
|
return;
|
2022-08-28 10:14:43 +02:00
|
|
|
|
2023-01-20 19:44:30 +01:00
|
|
|
wlr_box geom;
|
|
|
|
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
|
|
|
|
|
|
|
// ignore X and Y, adjust uv
|
2023-01-22 16:58:10 +01:00
|
|
|
if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.goalv().x || geom.height > pWindow->m_vRealSize.goalv().y) {
|
2023-01-20 19:44:30 +01:00
|
|
|
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;
|
2022-08-28 10:14:43 +02:00
|
|
|
|
2023-01-20 19:44:30 +01:00
|
|
|
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;
|
2022-08-28 10:14:43 +02:00
|
|
|
|
2023-01-22 16:58:10 +01:00
|
|
|
if (geom.width > pWindow->m_vRealSize.goalv().x || geom.height > pWindow->m_vRealSize.goalv().y) {
|
|
|
|
uvBR.x = uvBR.x * (pWindow->m_vRealSize.goalv().x / geom.width);
|
|
|
|
uvBR.y = uvBR.y * (pWindow->m_vRealSize.goalv().y / geom.height);
|
2023-01-20 19:44:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2022-08-28 10:14:43 +02:00
|
|
|
}
|
|
|
|
} else {
|
2022-12-16 18:17:31 +01:00
|
|
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
2022-08-28 10:14:43 +02:00
|
|
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-05 13:50:47 +01:00
|
|
|
void countSubsurfacesIter(wlr_surface* pSurface, int x, int y, void* data) {
|
|
|
|
*(int*)data += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
|
2022-11-09 11:56:36 +01:00
|
|
|
if (!pMonitor->mirrors.empty())
|
|
|
|
return false; // do not DS if this monitor is being mirrored. Will break the functionality.
|
|
|
|
|
2022-11-05 13:50:47 +01:00
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace);
|
|
|
|
|
2022-11-27 23:42:22 +01:00
|
|
|
if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || g_pCompositor->m_sSeat.exclusiveClient || pMonitor->specialWorkspaceID)
|
2022-11-05 13:50:47 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
|
|
|
|
|
|
|
if (!PCANDIDATE)
|
|
|
|
return false; // ????
|
|
|
|
|
2023-01-05 19:25:45 +01:00
|
|
|
if (PCANDIDATE->m_fAlpha.fl() != 1.f || PCANDIDATE->m_fActiveInactiveAlpha.fl() != 1.f || PWORKSPACE->m_fAlpha.fl() != 1.f)
|
2022-11-05 13:50:47 +01:00
|
|
|
return false;
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
if (PCANDIDATE->m_vRealSize.vec() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.vec() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() ||
|
|
|
|
PCANDIDATE->m_vRealSize.isBeingAnimated())
|
2022-11-05 13:50:47 +01:00
|
|
|
return false;
|
|
|
|
|
2023-01-22 17:03:25 +01:00
|
|
|
if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty())
|
2022-11-05 13:50:47 +01:00
|
|
|
return false;
|
|
|
|
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
2022-11-05 13:50:47 +01:00
|
|
|
if (topls->alpha.fl() != 0.f)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if it did not open any subsurfaces or shit
|
|
|
|
int surfaceCount = 0;
|
|
|
|
if (PCANDIDATE->m_bIsX11) {
|
|
|
|
surfaceCount = 1;
|
|
|
|
|
|
|
|
// check opaque
|
|
|
|
if (PCANDIDATE->m_uSurface.xwayland->has_alpha)
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
wlr_xdg_surface_for_each_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount);
|
|
|
|
wlr_xdg_surface_for_each_popup_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount);
|
|
|
|
|
|
|
|
if (!PCANDIDATE->m_uSurface.xdg->surface->opaque)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (surfaceCount != 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE);
|
|
|
|
|
|
|
|
if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// finally, we should be GTG.
|
|
|
|
wlr_output_attach_buffer(pMonitor->output, &PSURFACE->buffer->base);
|
|
|
|
|
|
|
|
if (!wlr_output_test(pMonitor->output)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-11-06 15:20:03 +01:00
|
|
|
timespec now;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
|
|
wlr_surface_send_frame_done(PSURFACE, &now);
|
2022-11-05 13:50:47 +01:00
|
|
|
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, PSURFACE, pMonitor->output);
|
|
|
|
|
|
|
|
if (wlr_output_commit(pMonitor->output)) {
|
|
|
|
if (!m_pLastScanout) {
|
|
|
|
m_pLastScanout = PCANDIDATE;
|
|
|
|
Debug::log(LOG, "Entered a direct scanout to %x: \"%s\"", PCANDIDATE, PCANDIDATE->m_szTitle.c_str());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_pLastScanout = nullptr;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprRenderer::setWindowScanoutMode(CWindow* pWindow) {
|
|
|
|
if (!g_pCompositor->m_sWLRLinuxDMABuf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!pWindow->m_bIsFullscreen) {
|
|
|
|
wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, g_pXWaylandManager->getWindowSurface(pWindow), nullptr);
|
|
|
|
Debug::log(LOG, "Scanout mode OFF set for %x", pWindow);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto RENDERERDRMFD = wlr_renderer_get_drm_fd(g_pCompositor->m_sWLRRenderer);
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto BACKENDDRMFD = wlr_backend_get_drm_fd(g_pCompositor->m_sWLRBackend);
|
2022-11-05 13:50:47 +01:00
|
|
|
|
|
|
|
if (RENDERERDRMFD < 0 || BACKENDDRMFD < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto deviceIDFromFD = [](int fd, unsigned long* deviceID) -> bool {
|
|
|
|
struct stat stat;
|
|
|
|
if (fstat(fd, &stat) != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*deviceID = stat.st_rdev;
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
unsigned long rendererDevice, scanoutDevice;
|
|
|
|
if (!deviceIDFromFD(RENDERERDRMFD, &rendererDevice) || !deviceIDFromFD(BACKENDDRMFD, &scanoutDevice))
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
|
|
|
|
|
|
|
const auto POUTPUTFORMATS = wlr_output_get_primary_formats(PMONITOR->output, WLR_BUFFER_CAP_DMABUF);
|
|
|
|
if (!POUTPUTFORMATS)
|
|
|
|
return;
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto PRENDERERFORMATS = wlr_renderer_get_dmabuf_texture_formats(g_pCompositor->m_sWLRRenderer);
|
|
|
|
wlr_drm_format_set scanoutFormats = {0};
|
2022-11-05 13:50:47 +01:00
|
|
|
|
|
|
|
if (!wlr_drm_format_set_intersect(&scanoutFormats, POUTPUTFORMATS, PRENDERERFORMATS))
|
|
|
|
return;
|
|
|
|
|
|
|
|
const wlr_linux_dmabuf_feedback_v1_tranche TRANCHES[] = {
|
2022-12-16 18:17:31 +01:00
|
|
|
{.target_device = scanoutDevice, .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, .formats = &scanoutFormats},
|
|
|
|
{.target_device = rendererDevice, .formats = PRENDERERFORMATS}};
|
2022-11-05 13:50:47 +01:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
const wlr_linux_dmabuf_feedback_v1 FEEDBACK = {.main_device = rendererDevice, .tranches_len = sizeof(TRANCHES) / sizeof(TRANCHES[0]), .tranches = TRANCHES};
|
2022-11-05 13:50:47 +01:00
|
|
|
|
|
|
|
if (!wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, g_pXWaylandManager->getWindowSurface(pWindow), &FEEDBACK)) {
|
|
|
|
Debug::log(ERR, "Error in scanout mode setting: wlr_linux_dmabuf_v1_set_surface_feedback returned false.");
|
|
|
|
}
|
|
|
|
|
|
|
|
wlr_drm_format_set_finish(&scanoutFormats);
|
|
|
|
|
|
|
|
Debug::log(LOG, "Scanout mode ON set for %x", pWindow);
|
|
|
|
}
|
|
|
|
|
2022-03-19 14:07:18 +01:00
|
|
|
void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool test) {
|
|
|
|
wlr_output_configuration_head_v1* head;
|
2022-12-16 18:17:31 +01:00
|
|
|
bool noError = true;
|
2022-03-19 14:07:18 +01:00
|
|
|
|
|
|
|
wl_list_for_each(head, &config->heads, link) {
|
2022-05-06 17:18:24 +02:00
|
|
|
|
|
|
|
std::string commandForCfg = "";
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto OUTPUT = head->state.output;
|
2022-03-19 14:07:18 +01:00
|
|
|
|
2022-05-06 17:18:24 +02:00
|
|
|
commandForCfg += std::string(OUTPUT->name) + ",";
|
|
|
|
|
|
|
|
if (!head->state.enabled) {
|
|
|
|
commandForCfg += "disabled";
|
|
|
|
if (!test)
|
|
|
|
g_pConfigManager->parseKeyword("monitor", commandForCfg, true);
|
|
|
|
continue;
|
2022-03-19 14:07:18 +01:00
|
|
|
}
|
|
|
|
|
2022-05-06 17:18:24 +02:00
|
|
|
wlr_output_enable(OUTPUT, head->state.enabled);
|
|
|
|
|
|
|
|
if (head->state.mode)
|
2022-12-16 18:17:31 +01:00
|
|
|
commandForCfg +=
|
|
|
|
std::to_string(head->state.mode->width) + "x" + std::to_string(head->state.mode->height) + "@" + std::to_string(head->state.mode->refresh / 1000.f) + ",";
|
2022-05-06 17:18:24 +02:00
|
|
|
else
|
2022-12-16 18:17:31 +01:00
|
|
|
commandForCfg += std::to_string(head->state.custom_mode.width) + "x" + std::to_string(head->state.custom_mode.height) + "@" +
|
|
|
|
std::to_string(head->state.custom_mode.refresh / 1000.f) + ",";
|
2022-05-06 17:18:24 +02:00
|
|
|
|
|
|
|
commandForCfg += std::to_string(head->state.x) + "x" + std::to_string(head->state.y) + "," + std::to_string(head->state.scale);
|
|
|
|
|
2022-11-03 10:06:44 +01:00
|
|
|
if (!test) {
|
2022-05-06 17:18:24 +02:00
|
|
|
g_pConfigManager->parseKeyword("monitor", commandForCfg, true);
|
2022-11-03 10:06:44 +01:00
|
|
|
|
|
|
|
std::string transformStr = std::string(OUTPUT->name) + ",transform," + std::to_string((int)OUTPUT->transform);
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromName(OUTPUT->name);
|
2022-11-03 10:06:44 +01:00
|
|
|
|
|
|
|
if (!PMONITOR || OUTPUT->transform != PMONITOR->transform)
|
|
|
|
g_pConfigManager->parseKeyword("monitor", transformStr);
|
|
|
|
}
|
2022-05-06 17:18:24 +02:00
|
|
|
|
2022-03-19 14:07:18 +01:00
|
|
|
noError = wlr_output_test(OUTPUT);
|
|
|
|
|
|
|
|
if (!noError)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-05-06 17:18:24 +02:00
|
|
|
if (!test)
|
2022-12-16 18:17:31 +01:00
|
|
|
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
|
2022-03-19 14:07:18 +01:00
|
|
|
|
|
|
|
if (noError)
|
|
|
|
wlr_output_configuration_v1_send_succeeded(config);
|
|
|
|
else
|
|
|
|
wlr_output_configuration_v1_send_failed(config);
|
|
|
|
wlr_output_configuration_v1_destroy(config);
|
|
|
|
|
|
|
|
Debug::log(LOG, "OutputMgr Applied/Tested.");
|
2022-03-19 14:37:40 +01:00
|
|
|
}
|
|
|
|
|
2022-03-21 17:00:17 +01:00
|
|
|
// taken from Sway.
|
|
|
|
// this is just too much of a spaghetti for me to understand
|
|
|
|
void apply_exclusive(struct wlr_box* usable_area, uint32_t anchor, int32_t exclusive, int32_t margin_top, int32_t margin_right, int32_t margin_bottom, int32_t margin_left) {
|
|
|
|
if (exclusive <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
struct {
|
|
|
|
uint32_t singular_anchor;
|
|
|
|
uint32_t anchor_triplet;
|
2022-12-16 18:17:31 +01:00
|
|
|
int* positive_axis;
|
|
|
|
int* negative_axis;
|
|
|
|
int margin;
|
2022-03-21 17:00:17 +01:00
|
|
|
} edges[] = {
|
|
|
|
// Top
|
|
|
|
{
|
|
|
|
.singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
|
2022-12-16 18:17:31 +01:00
|
|
|
.anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
|
|
|
|
.positive_axis = &usable_area->y,
|
|
|
|
.negative_axis = &usable_area->height,
|
|
|
|
.margin = margin_top,
|
2022-03-21 17:00:17 +01:00
|
|
|
},
|
|
|
|
// Bottom
|
|
|
|
{
|
|
|
|
.singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
|
2022-12-16 18:17:31 +01:00
|
|
|
.anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
|
|
|
|
.positive_axis = NULL,
|
|
|
|
.negative_axis = &usable_area->height,
|
|
|
|
.margin = margin_bottom,
|
2022-03-21 17:00:17 +01:00
|
|
|
},
|
|
|
|
// Left
|
|
|
|
{
|
|
|
|
.singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT,
|
2022-12-16 18:17:31 +01:00
|
|
|
.anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
|
|
|
|
.positive_axis = &usable_area->x,
|
|
|
|
.negative_axis = &usable_area->width,
|
|
|
|
.margin = margin_left,
|
2022-03-21 17:00:17 +01:00
|
|
|
},
|
|
|
|
// Right
|
|
|
|
{
|
|
|
|
.singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
|
2022-12-16 18:17:31 +01:00
|
|
|
.anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
|
|
|
|
.positive_axis = NULL,
|
|
|
|
.negative_axis = &usable_area->width,
|
|
|
|
.margin = margin_right,
|
2022-03-21 17:00:17 +01:00
|
|
|
},
|
|
|
|
};
|
|
|
|
for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) {
|
|
|
|
if ((anchor == edges[i].singular_anchor || anchor == edges[i].anchor_triplet) && exclusive + edges[i].margin > 0) {
|
|
|
|
if (edges[i].positive_axis) {
|
|
|
|
*edges[i].positive_axis += exclusive + edges[i].margin;
|
|
|
|
}
|
|
|
|
if (edges[i].negative_axis) {
|
|
|
|
*edges[i].negative_axis -= exclusive + edges[i].margin;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-03-19 14:37:40 +01:00
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector<std::unique_ptr<SLayerSurface>>& layerSurfaces, bool exclusiveZone, wlr_box* usableArea) {
|
2022-03-21 17:00:17 +01:00
|
|
|
wlr_box full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
|
2022-03-19 14:37:40 +01:00
|
|
|
|
2022-03-21 17:00:17 +01:00
|
|
|
for (auto& ls : layerSurfaces) {
|
2022-07-18 21:16:01 +02:00
|
|
|
if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess)
|
2022-05-14 17:23:46 +02:00
|
|
|
continue;
|
|
|
|
|
2022-03-21 17:00:17 +01:00
|
|
|
const auto PLAYER = ls->layerSurface;
|
|
|
|
const auto PSTATE = &PLAYER->current;
|
|
|
|
if (exclusiveZone != (PSTATE->exclusive_zone > 0)) {
|
|
|
|
continue;
|
2022-03-19 14:37:40 +01:00
|
|
|
}
|
|
|
|
|
2022-03-21 17:00:17 +01:00
|
|
|
wlr_box bounds;
|
|
|
|
if (PSTATE->exclusive_zone == -1) {
|
|
|
|
bounds = full_area;
|
|
|
|
} else {
|
|
|
|
bounds = *usableArea;
|
2022-03-19 14:37:40 +01:00
|
|
|
}
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
wlr_box box = {.width = PSTATE->desired_width, .height = PSTATE->desired_height};
|
2022-03-21 17:00:17 +01:00
|
|
|
// Horizontal axis
|
|
|
|
const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
|
|
|
if (box.width == 0) {
|
|
|
|
box.x = bounds.x;
|
|
|
|
} else if ((PSTATE->anchor & both_horiz) == both_horiz) {
|
|
|
|
box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
|
|
|
|
} else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
|
|
|
|
box.x = bounds.x;
|
|
|
|
} else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
|
|
|
|
box.x = bounds.x + (bounds.width - box.width);
|
|
|
|
} else {
|
|
|
|
box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
|
2022-03-19 14:37:40 +01:00
|
|
|
}
|
2022-03-21 17:00:17 +01:00
|
|
|
// Vertical axis
|
|
|
|
const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
|
|
|
if (box.height == 0) {
|
|
|
|
box.y = bounds.y;
|
|
|
|
} else if ((PSTATE->anchor & both_vert) == both_vert) {
|
|
|
|
box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
|
|
|
|
} else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
|
|
|
|
box.y = bounds.y;
|
|
|
|
} else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
|
|
|
|
box.y = bounds.y + (bounds.height - box.height);
|
|
|
|
} else {
|
|
|
|
box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
|
2022-03-19 14:37:40 +01:00
|
|
|
}
|
2022-03-21 17:00:17 +01:00
|
|
|
// Margin
|
|
|
|
if (box.width == 0) {
|
|
|
|
box.x += PSTATE->margin.left;
|
2022-12-16 18:17:31 +01:00
|
|
|
box.width = bounds.width - (PSTATE->margin.left + PSTATE->margin.right);
|
2022-03-21 17:00:17 +01:00
|
|
|
} else if ((PSTATE->anchor & both_horiz) == both_horiz) {
|
|
|
|
// don't apply margins
|
|
|
|
} else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
|
|
|
|
box.x += PSTATE->margin.left;
|
|
|
|
} else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
|
|
|
|
box.x -= PSTATE->margin.right;
|
|
|
|
}
|
|
|
|
if (box.height == 0) {
|
|
|
|
box.y += PSTATE->margin.top;
|
2022-12-16 18:17:31 +01:00
|
|
|
box.height = bounds.height - (PSTATE->margin.top + PSTATE->margin.bottom);
|
2022-03-21 17:00:17 +01:00
|
|
|
} else if ((PSTATE->anchor & both_vert) == both_vert) {
|
|
|
|
// don't apply margins
|
|
|
|
} else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
|
|
|
|
box.y += PSTATE->margin.top;
|
|
|
|
} else if ((PSTATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
|
|
|
|
box.y -= PSTATE->margin.bottom;
|
|
|
|
}
|
|
|
|
if (box.width <= 0 || box.height <= 0) {
|
2022-07-23 15:48:08 +02:00
|
|
|
Debug::log(ERR, "LayerSurface %x has a negative/zero w/h???", ls.get());
|
2022-03-21 17:00:17 +01:00
|
|
|
continue;
|
2022-03-20 14:52:23 +01:00
|
|
|
}
|
2022-03-21 17:00:17 +01:00
|
|
|
// Apply
|
|
|
|
ls->geometry = box;
|
2022-03-20 14:52:23 +01:00
|
|
|
|
2022-03-21 17:00:17 +01:00
|
|
|
apply_exclusive(usableArea, PSTATE->anchor, PSTATE->exclusive_zone, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left);
|
2022-03-19 14:37:40 +01:00
|
|
|
|
2022-03-21 17:00:17 +01:00
|
|
|
wlr_layer_surface_v1_configure(ls->layerSurface, box.width, box.height);
|
2022-03-19 14:37:40 +01:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "LayerSurface %x arranged: x: %i y: %i w: %i h: %i with margins: t: %i l: %i r: %i b: %i", &ls, box.x, box.y, box.width, box.height, PSTATE->margin.top,
|
|
|
|
PSTATE->margin.left, PSTATE->margin.right, PSTATE->margin.bottom);
|
2022-03-19 14:37:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) {
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitor);
|
|
|
|
|
|
|
|
if (!PMONITOR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Reset the reserved
|
2022-12-16 18:17:31 +01:00
|
|
|
PMONITOR->vecReservedBottomRight = Vector2D();
|
|
|
|
PMONITOR->vecReservedTopLeft = Vector2D();
|
2022-03-19 14:37:40 +01:00
|
|
|
|
2022-03-21 17:00:17 +01:00
|
|
|
wlr_box usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
|
|
|
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& la : PMONITOR->m_aLayerSurfaceLayers)
|
2022-03-21 17:00:17 +01:00
|
|
|
arrangeLayerArray(PMONITOR, la, true, &usableArea);
|
|
|
|
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& la : PMONITOR->m_aLayerSurfaceLayers)
|
2022-03-21 17:00:17 +01:00
|
|
|
arrangeLayerArray(PMONITOR, la, false, &usableArea);
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
PMONITOR->vecReservedTopLeft = Vector2D(usableArea.x, usableArea.y) - PMONITOR->vecPosition;
|
2022-03-21 17:00:17 +01:00
|
|
|
PMONITOR->vecReservedBottomRight = PMONITOR->vecSize - Vector2D(usableArea.width, usableArea.height) - PMONITOR->vecReservedTopLeft;
|
|
|
|
|
2022-10-18 00:23:01 +02:00
|
|
|
auto ADDITIONALRESERVED = g_pConfigManager->m_mAdditionalReservedAreas.find(PMONITOR->szName);
|
|
|
|
if (ADDITIONALRESERVED == g_pConfigManager->m_mAdditionalReservedAreas.end()) {
|
2022-12-16 18:17:31 +01:00
|
|
|
ADDITIONALRESERVED = g_pConfigManager->m_mAdditionalReservedAreas.find(""); // glob wildcard
|
2022-10-18 00:23:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ADDITIONALRESERVED != g_pConfigManager->m_mAdditionalReservedAreas.end()) {
|
2022-12-16 18:17:31 +01:00
|
|
|
PMONITOR->vecReservedTopLeft = PMONITOR->vecReservedTopLeft + Vector2D(ADDITIONALRESERVED->second.left, ADDITIONALRESERVED->second.top);
|
2022-10-18 00:23:01 +02:00
|
|
|
PMONITOR->vecReservedBottomRight = PMONITOR->vecReservedBottomRight + Vector2D(ADDITIONALRESERVED->second.right, ADDITIONALRESERVED->second.bottom);
|
|
|
|
}
|
2022-04-27 17:46:07 +02:00
|
|
|
|
2022-05-04 15:23:30 +02:00
|
|
|
// damage the monitor if can
|
|
|
|
if (PMONITOR->damage)
|
|
|
|
damageMonitor(PMONITOR);
|
|
|
|
|
2022-09-08 14:11:32 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitor);
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Monitor %s layers arranged: reserved: %f %f %f %f", PMONITOR->szName.c_str(), PMONITOR->vecReservedTopLeft.x, PMONITOR->vecReservedTopLeft.y,
|
|
|
|
PMONITOR->vecReservedBottomRight.x, PMONITOR->vecReservedBottomRight.y);
|
2022-03-19 16:13:19 +01:00
|
|
|
}
|
|
|
|
|
2022-04-14 16:43:29 +02:00
|
|
|
void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
|
|
|
|
if (!pSurface)
|
|
|
|
return; // wut?
|
2022-03-21 16:13:43 +01:00
|
|
|
|
2022-08-10 23:14:53 +02:00
|
|
|
if (g_pCompositor->m_bUnsafeState)
|
|
|
|
return;
|
|
|
|
|
2022-04-14 16:43:29 +02:00
|
|
|
pixman_region32_t damageBox;
|
|
|
|
pixman_region32_init(&damageBox);
|
|
|
|
wlr_surface_get_effective_damage(pSurface, &damageBox);
|
2022-03-21 16:13:43 +01:00
|
|
|
|
2022-07-04 17:55:33 +02:00
|
|
|
// schedule frame events
|
|
|
|
if (!wl_list_empty(&pSurface->current.frame_callback_list)) {
|
2022-07-13 18:18:23 +02:00
|
|
|
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)));
|
2022-07-04 17:55:33 +02:00
|
|
|
}
|
|
|
|
|
2022-06-28 15:30:46 +02:00
|
|
|
if (!pixman_region32_not_empty(&damageBox)) {
|
|
|
|
pixman_region32_fini(&damageBox);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-28 22:15:56 +02:00
|
|
|
pixman_region32_t damageBoxForEach;
|
|
|
|
pixman_region32_init(&damageBoxForEach);
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
2022-04-14 16:43:29 +02:00
|
|
|
double lx = 0, ly = 0;
|
2022-06-30 15:44:26 +02:00
|
|
|
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m->output, &lx, &ly);
|
2022-07-28 22:15:56 +02:00
|
|
|
|
2022-07-28 23:21:35 +02:00
|
|
|
pixman_region32_copy(&damageBoxForEach, &damageBox);
|
2022-07-29 11:52:56 +02:00
|
|
|
pixman_region32_translate(&damageBoxForEach, x - m->vecPosition.x, y - m->vecPosition.y);
|
2022-07-28 23:21:35 +02:00
|
|
|
wlr_region_scale(&damageBoxForEach, &damageBoxForEach, m->scale);
|
2022-07-29 11:52:56 +02:00
|
|
|
pixman_region32_translate(&damageBoxForEach, lx + m->vecPosition.x, ly + m->vecPosition.y);
|
2022-07-28 22:15:56 +02:00
|
|
|
|
2022-08-23 16:07:47 +02:00
|
|
|
m->addDamage(&damageBoxForEach);
|
2022-03-21 16:13:43 +01:00
|
|
|
}
|
|
|
|
|
2022-07-28 22:15:56 +02:00
|
|
|
pixman_region32_fini(&damageBoxForEach);
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
2022-06-07 20:41:40 +02:00
|
|
|
|
|
|
|
if (*PLOGDAMAGE)
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1,
|
|
|
|
damageBox.extents.y2 - damageBox.extents.y1);
|
2022-07-20 12:06:14 +02:00
|
|
|
|
|
|
|
pixman_region32_fini(&damageBox);
|
2022-04-14 16:43:29 +02:00
|
|
|
}
|
2022-03-21 16:13:43 +01:00
|
|
|
|
2022-04-14 16:43:29 +02:00
|
|
|
void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
2022-08-10 23:14:53 +02:00
|
|
|
if (g_pCompositor->m_bUnsafeState)
|
|
|
|
return;
|
|
|
|
|
2022-06-29 11:21:42 +02:00
|
|
|
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
|
|
|
wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
|
|
|
|
scaleBox(&fixedDamageBox, m->scale);
|
2022-08-23 16:07:47 +02:00
|
|
|
m->addDamage(&fixedDamageBox);
|
2022-06-29 11:21:42 +02:00
|
|
|
}
|
2022-05-05 15:09:26 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
2022-06-07 20:41:40 +02:00
|
|
|
|
2022-06-29 11:21:42 +02:00
|
|
|
if (*PLOGDAMAGE)
|
|
|
|
Debug::log(LOG, "Damage: Window (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
|
2022-03-21 16:13:43 +01:00
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
2022-09-13 15:25:42 +02:00
|
|
|
if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror())
|
2022-08-10 23:14:53 +02:00
|
|
|
return;
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
wlr_box damageBox = {0, 0, INT16_MAX, INT16_MAX};
|
2022-08-23 16:07:47 +02:00
|
|
|
pMonitor->addDamage(&damageBox);
|
2022-05-05 15:09:26 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
2022-06-07 20:41:40 +02:00
|
|
|
|
|
|
|
if (*PLOGDAMAGE)
|
2022-05-05 15:09:26 +02:00
|
|
|
Debug::log(LOG, "Damage: Monitor %s", pMonitor->szName.c_str());
|
2022-04-14 16:43:29 +02:00
|
|
|
}
|
2022-03-21 16:13:43 +01:00
|
|
|
|
2022-04-14 16:43:29 +02:00
|
|
|
void CHyprRenderer::damageBox(wlr_box* pBox) {
|
2022-08-10 23:14:53 +02:00
|
|
|
if (g_pCompositor->m_bUnsafeState)
|
|
|
|
return;
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
2022-09-13 15:25:42 +02:00
|
|
|
if (m->isMirror())
|
|
|
|
continue; // don't damage mirrors traditionally
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
|
|
|
scaleBox(&damageBox, m->scale);
|
2022-08-23 16:07:47 +02:00
|
|
|
m->addDamage(&damageBox);
|
2022-04-17 18:47:10 +02:00
|
|
|
}
|
2022-05-05 15:09:26 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
2022-06-07 20:41:40 +02:00
|
|
|
|
|
|
|
if (*PLOGDAMAGE)
|
2022-05-05 15:09:26 +02:00
|
|
|
Debug::log(LOG, "Damage: Box: xy: %d, %d wh: %d, %d", pBox->x, pBox->y, pBox->width, pBox->height);
|
2022-03-31 17:25:23 +02:00
|
|
|
}
|
|
|
|
|
2022-05-05 14:02:30 +02:00
|
|
|
void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const int& h) {
|
|
|
|
wlr_box box = {x, y, w, h};
|
|
|
|
damageBox(&box);
|
|
|
|
}
|
|
|
|
|
2022-07-16 12:44:45 +02:00
|
|
|
void CHyprRenderer::damageRegion(pixman_region32_t* rg) {
|
|
|
|
PIXMAN_DAMAGE_FOREACH(rg) {
|
|
|
|
const auto RECT = RECTSARR[i];
|
|
|
|
damageBox(RECT.x1, RECT.y1, RECT.x2 - RECT.x1, RECT.y2 - RECT.y1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-13 15:25:42 +02:00
|
|
|
void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, pixman_region32_t* pRegion) {
|
|
|
|
for (auto& mirror : pMonitor->mirrors) {
|
2022-12-16 18:17:31 +01:00
|
|
|
Vector2D scale = {mirror->vecSize.x / pMonitor->vecSize.x, mirror->vecSize.y / pMonitor->vecSize.y};
|
2022-09-13 15:25:42 +02:00
|
|
|
|
|
|
|
pixman_region32_t rg;
|
|
|
|
pixman_region32_init(&rg);
|
|
|
|
pixman_region32_copy(&rg, pRegion);
|
|
|
|
wlr_region_scale_xy(&rg, &rg, scale.x, scale.y);
|
|
|
|
pMonitor->addDamage(&rg);
|
|
|
|
pixman_region32_fini(&rg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) {
|
2022-03-31 17:25:23 +02:00
|
|
|
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
|
|
|
|
return;
|
|
|
|
|
2023-01-20 19:44:30 +01:00
|
|
|
SRenderData renderdata = {pMonitor, time, g_pInputManager->m_sDrag.pos.x, g_pInputManager->m_sDrag.pos.y};
|
2022-12-16 18:17:31 +01:00
|
|
|
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;
|
2022-03-31 17:25:23 +02:00
|
|
|
|
|
|
|
wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata);
|
2022-06-29 14:15:08 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
wlr_box box = {g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4,
|
|
|
|
g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4};
|
2022-06-29 14:15:08 +02:00
|
|
|
g_pHyprRenderer->damageBox(&box);
|
2022-04-14 16:43:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& mode) {
|
|
|
|
if (mode == "full")
|
|
|
|
return DAMAGE_TRACKING_FULL;
|
|
|
|
if (mode == "monitor")
|
|
|
|
return DAMAGE_TRACKING_MONITOR;
|
|
|
|
if (mode == "none")
|
|
|
|
return DAMAGE_TRACKING_NONE;
|
|
|
|
|
|
|
|
return DAMAGE_TRACKING_INVALID;
|
2022-04-19 19:01:23 +02:00
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) {
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-04-21 18:11:28 +02:00
|
|
|
Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str());
|
|
|
|
|
2022-06-30 23:50:57 +02:00
|
|
|
// if it's disabled, disable and ignore
|
|
|
|
if (pMonitorRule->disabled) {
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
if (pMonitor->m_bEnabled)
|
|
|
|
pMonitor->onDisconnect();
|
|
|
|
|
2022-08-03 17:32:12 +02:00
|
|
|
return true;
|
2022-06-30 23:50:57 +02:00
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
if (!pMonitor->m_bEnabled) {
|
|
|
|
pMonitor->onConnect(true); // enable it.
|
|
|
|
force = true;
|
|
|
|
}
|
|
|
|
|
2022-04-19 19:01:23 +02:00
|
|
|
// Check if the rule isn't already applied
|
2022-12-16 18:17:31 +01:00
|
|
|
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) &&
|
|
|
|
DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale &&
|
|
|
|
((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) ||
|
|
|
|
pMonitorRule->offset == Vector2D(-1, -1)) &&
|
|
|
|
pMonitor->transform == pMonitorRule->transform && pMonitorRule->enable10bit == pMonitor->enabled10bit) {
|
2022-08-04 11:10:26 +02:00
|
|
|
|
2022-04-19 19:01:23 +02:00
|
|
|
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
|
2022-06-30 23:55:28 +02:00
|
|
|
return true;
|
2022-04-19 19:01:23 +02:00
|
|
|
}
|
|
|
|
|
2023-01-20 16:03:52 +01:00
|
|
|
if (pMonitorRule->scale > 0.1) {
|
2022-12-14 18:57:18 +01:00
|
|
|
wlr_output_set_scale(pMonitor->output, pMonitorRule->scale);
|
|
|
|
pMonitor->scale = pMonitorRule->scale;
|
|
|
|
} else {
|
|
|
|
const auto DEFAULTSCALE = pMonitor->getDefaultScale();
|
|
|
|
wlr_output_set_scale(pMonitor->output, DEFAULTSCALE);
|
|
|
|
pMonitor->scale = DEFAULTSCALE;
|
|
|
|
}
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-11-18 15:15:19 +01:00
|
|
|
wlr_output_set_transform(pMonitor->output, pMonitorRule->transform);
|
|
|
|
pMonitor->transform = pMonitorRule->transform;
|
|
|
|
|
2022-04-19 19:01:23 +02:00
|
|
|
// loop over modes and choose an appropriate one.
|
2022-12-16 18:17:31 +01:00
|
|
|
if (pMonitorRule->resolution != Vector2D() && pMonitorRule->resolution != Vector2D(-1, -1) && pMonitorRule->resolution != Vector2D(-1, -2)) {
|
2022-07-30 22:54:29 +02:00
|
|
|
if (!wl_list_empty(&pMonitor->output->modes)) {
|
|
|
|
wlr_output_mode* mode;
|
2022-12-16 18:17:31 +01:00
|
|
|
bool found = false;
|
2022-07-30 22:54:29 +02:00
|
|
|
|
|
|
|
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
|
|
|
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
|
2022-12-16 18:17:31 +01:00
|
|
|
if (DELTALESSTHAN(mode->width, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(mode->height, pMonitorRule->resolution.y, 1) &&
|
|
|
|
DELTALESSTHAN(mode->refresh / 1000.f, pMonitorRule->refreshRate, 1)) {
|
2022-07-30 22:54:29 +02:00
|
|
|
wlr_output_set_mode(pMonitor->output, mode);
|
|
|
|
|
|
|
|
if (!wlr_output_test(pMonitor->output)) {
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Monitor %s: REJECTED available mode: %ix%i@%2f!", pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y,
|
|
|
|
(float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh / 1000.f);
|
2022-07-30 22:54:29 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Monitor %s: requested %ix%i@%2f, found available mode: %ix%i@%imHz, applying.", pMonitor->output->name, (int)pMonitorRule->resolution.x,
|
|
|
|
(int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh);
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-07-30 22:54:29 +02:00
|
|
|
found = true;
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-07-30 22:54:29 +02:00
|
|
|
pMonitor->refreshRate = mode->refresh / 1000.f;
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = Vector2D(mode->width, mode->height);
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-07-30 22:54:29 +02:00
|
|
|
break;
|
|
|
|
}
|
2022-04-19 19:01:23 +02:00
|
|
|
}
|
|
|
|
|
2022-07-30 22:54:29 +02:00
|
|
|
if (!found) {
|
|
|
|
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = pMonitorRule->resolution;
|
2022-09-24 14:10:11 +02:00
|
|
|
pMonitor->refreshRate = pMonitorRule->refreshRate;
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-07-30 22:54:29 +02:00
|
|
|
if (!wlr_output_test(pMonitor->output)) {
|
|
|
|
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
2022-06-28 11:12:01 +02:00
|
|
|
|
2022-07-30 22:54:29 +02:00
|
|
|
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
2022-06-28 11:12:01 +02:00
|
|
|
|
2022-07-30 22:54:29 +02:00
|
|
|
if (!PREFERREDMODE) {
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f", (int)pMonitorRule->resolution.x,
|
|
|
|
(int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
|
2022-07-30 22:54:29 +02:00
|
|
|
return true;
|
|
|
|
}
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-07-30 22:54:29 +02:00
|
|
|
// Preferred is valid
|
|
|
|
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f", pMonitor->output->name,
|
|
|
|
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height,
|
|
|
|
PREFERREDMODE->refresh / 1000.f);
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-07-30 22:54:29 +02:00
|
|
|
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
2022-07-30 22:54:29 +02:00
|
|
|
} else {
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Set a custom mode %ix%i@%2f (mode not found in monitor modes)", (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y,
|
|
|
|
(float)pMonitorRule->refreshRate);
|
2022-07-30 22:54:29 +02:00
|
|
|
}
|
2022-06-28 11:12:01 +02:00
|
|
|
}
|
2022-09-24 14:10:11 +02:00
|
|
|
} else {
|
|
|
|
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = pMonitorRule->resolution;
|
2022-09-24 14:10:11 +02:00
|
|
|
pMonitor->refreshRate = pMonitorRule->refreshRate;
|
|
|
|
|
|
|
|
if (!wlr_output_test(pMonitor->output)) {
|
|
|
|
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
|
|
|
|
|
|
|
|
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
|
|
|
|
|
|
|
if (!PREFERREDMODE) {
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f", (int)pMonitorRule->resolution.x,
|
|
|
|
(int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
|
2022-09-24 14:10:11 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Preferred is valid
|
|
|
|
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f", pMonitor->output->name,
|
|
|
|
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height,
|
|
|
|
PREFERREDMODE->refresh / 1000.f);
|
2022-09-24 14:10:11 +02:00
|
|
|
|
|
|
|
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
2022-09-24 14:10:11 +02:00
|
|
|
} else {
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Set a custom mode %ix%i@%2f (mode not found in monitor modes)", (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y,
|
|
|
|
(float)pMonitorRule->refreshRate);
|
2022-09-24 14:10:11 +02:00
|
|
|
}
|
2022-09-22 00:45:56 +02:00
|
|
|
}
|
2022-09-24 12:30:41 +02:00
|
|
|
} else if (pMonitorRule->resolution != Vector2D()) {
|
2022-09-22 00:45:56 +02:00
|
|
|
if (!wl_list_empty(&pMonitor->output->modes)) {
|
|
|
|
wlr_output_mode* mode;
|
2022-12-16 18:17:31 +01:00
|
|
|
float currentWidth = 0;
|
|
|
|
float currentHeight = 0;
|
|
|
|
float currentRefresh = 0;
|
|
|
|
bool success = false;
|
2022-09-22 00:45:56 +02:00
|
|
|
|
2022-09-25 20:07:48 +02:00
|
|
|
//(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution
|
2022-12-16 18:17:31 +01:00
|
|
|
if (pMonitorRule->resolution == Vector2D(-1, -1)) {
|
2022-09-22 00:45:56 +02:00
|
|
|
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
2022-12-16 18:17:31 +01:00
|
|
|
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || mode->refresh > (currentRefresh + 3000.f)) {
|
|
|
|
wlr_output_set_mode(pMonitor->output, mode);
|
|
|
|
if (wlr_output_test(pMonitor->output)) {
|
|
|
|
currentWidth = mode->width;
|
|
|
|
currentHeight = mode->height;
|
|
|
|
currentRefresh = mode->refresh;
|
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
}
|
2022-09-22 00:45:56 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
2022-12-16 18:17:31 +01:00
|
|
|
if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) ||
|
|
|
|
(mode->width > currentWidth && mode->height > currentHeight)) {
|
|
|
|
wlr_output_set_mode(pMonitor->output, mode);
|
|
|
|
if (wlr_output_test(pMonitor->output)) {
|
|
|
|
currentWidth = mode->width;
|
|
|
|
currentHeight = mode->height;
|
|
|
|
currentRefresh = mode->refresh;
|
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
}
|
2022-09-21 22:29:52 +02:00
|
|
|
}
|
2022-09-22 00:45:56 +02:00
|
|
|
}
|
2022-08-07 19:28:31 +02:00
|
|
|
|
2022-09-22 00:45:56 +02:00
|
|
|
if (!success) {
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Monitor %s: REJECTED mode: %ix%i@%2f! Falling back to preferred.", pMonitor->output->name, (int)pMonitorRule->resolution.x,
|
|
|
|
(int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh / 1000.f);
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2022-09-22 00:45:56 +02:00
|
|
|
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
2022-09-21 22:29:52 +02:00
|
|
|
|
2022-09-22 00:45:56 +02:00
|
|
|
if (!PREFERREDMODE) {
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f", (int)pMonitorRule->resolution.x,
|
|
|
|
(int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
|
2022-09-22 00:45:56 +02:00
|
|
|
return true;
|
|
|
|
}
|
2022-09-21 22:29:52 +02:00
|
|
|
|
2022-09-22 00:45:56 +02:00
|
|
|
// Preferred is valid
|
|
|
|
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
2022-09-21 22:29:52 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f", pMonitor->output->name,
|
|
|
|
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height,
|
|
|
|
PREFERREDMODE->refresh / 1000.f);
|
2022-09-21 22:29:52 +02:00
|
|
|
|
2022-09-22 00:45:56 +02:00
|
|
|
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
2022-09-22 00:45:56 +02:00
|
|
|
} else {
|
2022-09-21 22:29:52 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Monitor %s: Applying highest mode %ix%i@%2f.", pMonitor->output->name, (int)currentWidth, (int)currentHeight, (int)currentRefresh / 1000.f,
|
2022-09-22 00:45:56 +02:00
|
|
|
mode->width, mode->height, mode->refresh / 1000.f);
|
2022-09-21 22:29:52 +02:00
|
|
|
|
2022-09-22 00:45:56 +02:00
|
|
|
pMonitor->refreshRate = currentRefresh / 1000.f;
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = Vector2D(currentWidth, currentHeight);
|
2022-09-21 22:29:52 +02:00
|
|
|
}
|
2022-09-22 00:45:56 +02:00
|
|
|
}
|
|
|
|
} else {
|
2022-07-30 22:54:29 +02:00
|
|
|
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
|
|
|
|
|
|
|
|
if (!PREFERREDMODE) {
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE", (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
|
2022-07-30 22:54:29 +02:00
|
|
|
|
2022-08-02 22:20:45 +02:00
|
|
|
if (!wl_list_empty(&pMonitor->output->modes)) {
|
|
|
|
wlr_output_mode* mode;
|
|
|
|
|
|
|
|
wl_list_for_each(mode, &pMonitor->output->modes, link) {
|
|
|
|
wlr_output_set_mode(pMonitor->output, mode);
|
|
|
|
|
|
|
|
if (!wlr_output_test(pMonitor->output)) {
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Monitor %s: REJECTED available mode: %ix%i@%2f!", pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y,
|
|
|
|
(float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh / 1000.f);
|
2022-08-02 22:20:45 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
Debug::log(LOG, "Monitor %s: requested %ix%i@%2f, found available mode: %ix%i@%imHz, applying.", pMonitor->output->name, (int)pMonitorRule->resolution.x,
|
|
|
|
(int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate, mode->width, mode->height, mode->refresh);
|
2022-08-02 22:20:45 +02:00
|
|
|
|
|
|
|
pMonitor->refreshRate = mode->refresh / 1000.f;
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = Vector2D(mode->width, mode->height);
|
2022-08-02 22:20:45 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Preferred is valid
|
|
|
|
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
|
2022-08-02 22:20:45 +02:00
|
|
|
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
|
2022-08-07 19:28:31 +02:00
|
|
|
|
|
|
|
Debug::log(LOG, "Setting preferred mode for %s", pMonitor->output->name);
|
2022-08-02 22:20:45 +02:00
|
|
|
}
|
2022-04-19 19:01:23 +02:00
|
|
|
}
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vrrActive = pMonitor->output->pending.adaptive_sync_enabled; // disabled here, will be tested in CConfigManager::ensureVRR()
|
2022-04-19 19:01:23 +02:00
|
|
|
|
2022-05-18 20:33:54 +02:00
|
|
|
pMonitor->vecPixelSize = pMonitor->vecSize;
|
|
|
|
|
2022-10-27 14:26:47 +02:00
|
|
|
if (pMonitorRule->enable10bit) {
|
|
|
|
// try 10b RGB
|
|
|
|
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XRGB2101010);
|
|
|
|
pMonitor->enabled10bit = true;
|
|
|
|
|
|
|
|
if (!wlr_output_test(pMonitor->output)) {
|
|
|
|
Debug::log(ERR, "Output %s -> 10 bit enabled, but failed format DRM_FORMAT_XRGB2101010. Trying BGR.", pMonitor->output->name);
|
|
|
|
|
|
|
|
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XBGR2101010);
|
|
|
|
|
|
|
|
if (!wlr_output_test(pMonitor->output)) {
|
|
|
|
Debug::log(ERR, "Output %s -> 10 bit enabled, but failed format DRM_FORMAT_XBGR2101010. Falling back to 8 bit.", pMonitor->output->name);
|
|
|
|
|
|
|
|
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XRGB8888);
|
|
|
|
} else {
|
|
|
|
Debug::log(LOG, "10bit format DRM_FORMAT_XBGR2101010 succeeded for output %s", pMonitor->output->name);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Debug::log(LOG, "10bit format DRM_FORMAT_XRGB2101010 succeeded for output %s", pMonitor->output->name);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XRGB8888);
|
|
|
|
pMonitor->enabled10bit = false;
|
|
|
|
}
|
|
|
|
|
2022-04-19 19:01:23 +02:00
|
|
|
if (!wlr_output_commit(pMonitor->output)) {
|
|
|
|
Debug::log(ERR, "Couldn't commit output named %s", pMonitor->output->name);
|
|
|
|
}
|
2022-04-21 18:11:28 +02:00
|
|
|
|
2022-05-29 12:27:45 +02:00
|
|
|
int x, y;
|
|
|
|
wlr_output_transformed_resolution(pMonitor->output, &x, &y);
|
2022-12-16 18:17:31 +01:00
|
|
|
pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).floor();
|
|
|
|
pMonitor->vecTransformedSize = Vector2D(x, y);
|
2022-05-29 12:27:45 +02:00
|
|
|
|
2022-11-05 19:04:44 +01:00
|
|
|
if (pMonitor->createdByUser) {
|
2022-12-16 18:17:31 +01:00
|
|
|
wlr_box transformedBox = {0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y};
|
|
|
|
wlr_box_transform(&transformedBox, &transformedBox, wlr_output_transform_invert(pMonitor->output->transform), (int)pMonitor->vecTransformedSize.x,
|
|
|
|
(int)pMonitor->vecTransformedSize.y);
|
2022-11-05 19:04:44 +01:00
|
|
|
|
|
|
|
pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height);
|
|
|
|
}
|
|
|
|
|
2022-10-12 16:16:31 +02:00
|
|
|
if (pMonitorRule->offset == Vector2D(-1, -1) && pMonitor->vecPosition == Vector2D(-1, -1)) {
|
2022-08-04 11:10:26 +02:00
|
|
|
// let's find manually a sensible position for it, to the right.
|
|
|
|
Vector2D finalPos;
|
|
|
|
|
|
|
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
|
|
|
if (m->ID == pMonitor->ID)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (m->vecPosition.x + std::ceil(m->vecSize.x) > finalPos.x) {
|
|
|
|
finalPos.x = m->vecPosition.x + std::ceil(m->vecSize.x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pMonitor->vecPosition = finalPos;
|
2022-10-12 16:16:31 +02:00
|
|
|
} else if (pMonitorRule->offset != Vector2D(-1, -1)) {
|
|
|
|
pMonitor->vecPosition = pMonitorRule->offset;
|
2022-08-04 11:10:26 +02:00
|
|
|
}
|
2022-04-21 18:11:28 +02:00
|
|
|
|
2022-12-15 18:17:15 +01:00
|
|
|
wlr_output_enable(pMonitor->output, 1);
|
|
|
|
|
2022-10-07 23:19:23 +02:00
|
|
|
// update renderer (here because it will call rollback, so we cannot do this before committing)
|
|
|
|
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
|
|
|
|
|
2022-04-21 18:11:28 +02:00
|
|
|
// updato wlroots
|
2022-10-29 18:32:03 +02:00
|
|
|
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
|
2022-04-21 18:11:28 +02:00
|
|
|
|
|
|
|
// updato us
|
|
|
|
arrangeLayersForMonitor(pMonitor->ID);
|
|
|
|
|
|
|
|
// frame skip
|
2022-06-06 13:48:17 +02:00
|
|
|
pMonitor->framesToSkip = 1;
|
2022-06-30 23:55:28 +02:00
|
|
|
|
2022-09-13 15:25:42 +02:00
|
|
|
// reload to fix mirrors
|
|
|
|
g_pConfigManager->m_bWantsMonitorReload = true;
|
|
|
|
|
2023-01-18 16:12:15 +01:00
|
|
|
Debug::log(LOG, "Monitor %s data dump: res %ix%i@%.2fHz, scale %.2f, transform %i, pos %ix%i, 10b %i", pMonitor->szName.c_str(), (int)pMonitor->vecPixelSize.x,
|
|
|
|
(int)pMonitor->vecPixelSize.y, pMonitor->refreshRate, pMonitor->scale, (int)pMonitor->transform, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y,
|
|
|
|
(int)pMonitor->enabled10bit);
|
2023-01-17 11:57:36 +01:00
|
|
|
|
2022-06-30 23:55:28 +02:00
|
|
|
return true;
|
2022-04-21 18:11:28 +02:00
|
|
|
}
|
2022-06-24 23:27:02 +02:00
|
|
|
|
|
|
|
void CHyprRenderer::ensureCursorRenderingMode() {
|
2022-12-16 18:17:31 +01:00
|
|
|
static auto* const PCURSORTIMEOUT = &g_pConfigManager->getConfigValuePtr("general:cursor_inactive_timeout")->intValue;
|
2023-01-17 11:47:39 +01:00
|
|
|
static auto* const PHIDEONTOUCH = &g_pConfigManager->getConfigValuePtr("misc:hide_cursor_on_touch")->intValue;
|
2022-06-24 23:27:02 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto PASSEDCURSORSECONDS = g_pInputManager->m_tmrLastCursorMovement.getSeconds();
|
2022-06-24 23:27:02 +02:00
|
|
|
|
2023-01-17 11:47:39 +01:00
|
|
|
if (*PCURSORTIMEOUT > 0 || *PHIDEONTOUCH) {
|
|
|
|
const bool HIDE = (*PCURSORTIMEOUT > 0 && *PCURSORTIMEOUT < PASSEDCURSORSECONDS) || (g_pInputManager->m_bLastInputTouch && *PHIDEONTOUCH);
|
|
|
|
|
|
|
|
if (HIDE && m_bHasARenderedCursor) {
|
2022-06-24 23:27:02 +02:00
|
|
|
m_bHasARenderedCursor = false;
|
|
|
|
|
|
|
|
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, nullptr, 0, 0); // hide
|
|
|
|
|
|
|
|
Debug::log(LOG, "Hiding the cursor (timeout)");
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : g_pCompositor->m_vMonitors)
|
2022-12-16 18:17:31 +01:00
|
|
|
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
|
2023-01-17 11:47:39 +01:00
|
|
|
} else if (!HIDE && !m_bHasARenderedCursor) {
|
2022-06-24 23:27:02 +02:00
|
|
|
m_bHasARenderedCursor = true;
|
|
|
|
|
2022-06-26 13:43:32 +02:00
|
|
|
if (!m_bWindowRequestedCursorHide)
|
|
|
|
wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor);
|
2022-06-24 23:27:02 +02:00
|
|
|
|
|
|
|
Debug::log(LOG, "Showing the cursor (timeout)");
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : g_pCompositor->m_vMonitors)
|
2022-12-16 18:17:31 +01:00
|
|
|
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
|
2022-06-24 23:27:02 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_bHasARenderedCursor = true;
|
|
|
|
}
|
2022-06-26 13:43:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CHyprRenderer::shouldRenderCursor() {
|
|
|
|
return m_bHasARenderedCursor;
|
2022-07-11 23:38:10 +02:00
|
|
|
}
|