2022-03-17 20:22:29 +01:00
|
|
|
#include "Renderer.hpp"
|
|
|
|
#include "../Compositor.hpp"
|
|
|
|
|
|
|
|
void scaleBox(wlr_box* box, float scale) {
|
|
|
|
box->width = std::round((box->x + box->width) * scale) - std::round(box->x * scale);
|
|
|
|
box->height = std::round((box->y + box->height) * scale) - std::round(box->y * scale);
|
|
|
|
box->x = std::round(box->x * scale);
|
|
|
|
box->y = std::round(box->y * scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
|
|
|
const auto TEXTURE = wlr_surface_get_texture(surface);
|
|
|
|
const auto RDATA = (SRenderData*)data;
|
|
|
|
|
|
|
|
if (!TEXTURE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
double outputX = 0, outputY = 0;
|
|
|
|
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->output, &outputX, &outputY);
|
|
|
|
|
|
|
|
wlr_box windowBox = {outputX + RDATA->x + x, outputY + RDATA->y + y, surface->current.width, surface->current.height};
|
|
|
|
scaleBox(&windowBox, RDATA->output->scale);
|
|
|
|
|
|
|
|
const auto TRANSFORM = wlr_output_transform_invert(surface->current.transform);
|
|
|
|
float matrix[9];
|
|
|
|
wlr_matrix_project_box(matrix, &windowBox, TRANSFORM, 0, RDATA->output->transform_matrix);
|
|
|
|
|
|
|
|
wlr_render_texture_with_matrix(g_pCompositor->m_sWLRRenderer, TEXTURE, matrix, 1); // TODO: fadein/out
|
|
|
|
|
|
|
|
wlr_surface_send_frame_done(surface, RDATA->when);
|
|
|
|
|
|
|
|
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(ID);
|
|
|
|
|
|
|
|
if (!PMONITOR)
|
|
|
|
return;
|
|
|
|
|
2022-03-19 13:35:04 +01:00
|
|
|
// Render layer surfaces below windows for monitor
|
|
|
|
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
|
2022-03-19 14:00:24 +01:00
|
|
|
SRenderData renderdata = {PMONITOR->output, time, ls->geometry.x, ls->geometry.y};
|
|
|
|
wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata);
|
2022-03-19 13:35:04 +01:00
|
|
|
}
|
|
|
|
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
|
2022-03-19 14:00:24 +01:00
|
|
|
SRenderData renderdata = {PMONITOR->output, time, ls->geometry.x, ls->geometry.y};
|
|
|
|
wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata);
|
2022-03-19 13:35:04 +01:00
|
|
|
}
|
|
|
|
|
2022-03-18 22:35:51 +01:00
|
|
|
for (auto& w : g_pCompositor->m_lWindows) {
|
2022-03-17 20:22:29 +01:00
|
|
|
|
2022-03-20 15:55:47 +01:00
|
|
|
if (w.m_bIsX11 || w.m_iWorkspaceID != PMONITOR->activeWorkspace)
|
2022-03-18 20:03:39 +01:00
|
|
|
continue;
|
|
|
|
|
2022-03-19 15:59:53 +01:00
|
|
|
wlr_box geometry = { w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y };
|
2022-03-17 20:22:29 +01:00
|
|
|
|
2022-03-18 20:42:49 +01:00
|
|
|
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &geometry))
|
2022-03-17 20:22:29 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// render the bad boy
|
2022-03-19 16:13:19 +01:00
|
|
|
|
|
|
|
// border
|
|
|
|
drawBorderForWindow(&w, PMONITOR);
|
|
|
|
|
2022-03-19 15:59:53 +01:00
|
|
|
SRenderData renderdata = {PMONITOR->output, time, w.m_vRealPosition.x, w.m_vRealPosition.y};
|
2022-03-17 20:22:29 +01:00
|
|
|
|
2022-03-18 20:42:49 +01:00
|
|
|
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(&w), renderSurface, &renderdata);
|
2022-03-17 20:22:29 +01:00
|
|
|
wlr_xdg_surface_for_each_popup_surface(w.m_uSurface.xdg, renderSurface, &renderdata);
|
|
|
|
}
|
2022-03-18 20:03:39 +01:00
|
|
|
|
2022-03-18 22:35:51 +01:00
|
|
|
for (auto& w : g_pCompositor->m_lWindows) {
|
2022-03-18 20:03:39 +01:00
|
|
|
|
2022-03-20 15:55:47 +01:00
|
|
|
if (!w.m_bIsX11 || w.m_iWorkspaceID != PMONITOR->activeWorkspace)
|
2022-03-18 20:03:39 +01:00
|
|
|
continue;
|
|
|
|
|
2022-03-18 23:52:36 +01:00
|
|
|
if (!g_pCompositor->windowValidMapped(&w))
|
|
|
|
continue;
|
|
|
|
|
2022-03-19 15:59:53 +01:00
|
|
|
wlr_box geometry = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
|
2022-03-18 20:03:39 +01:00
|
|
|
|
|
|
|
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &geometry))
|
|
|
|
continue;
|
|
|
|
|
2022-03-18 20:42:49 +01:00
|
|
|
// render the bad boy
|
2022-03-19 16:13:19 +01:00
|
|
|
|
|
|
|
// border
|
|
|
|
drawBorderForWindow(&w, PMONITOR);
|
|
|
|
|
2022-03-19 15:59:53 +01:00
|
|
|
SRenderData renderdata = {PMONITOR->output, time, w.m_vRealPosition.x, w.m_vRealPosition.y};
|
2022-03-18 20:03:39 +01:00
|
|
|
|
2022-03-18 20:20:49 +01:00
|
|
|
if (w.m_uSurface.xwayland->surface)
|
2022-03-18 20:42:49 +01:00
|
|
|
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(&w), renderSurface, &renderdata);
|
2022-03-18 20:03:39 +01:00
|
|
|
}
|
2022-03-19 13:35:04 +01:00
|
|
|
|
|
|
|
// Render surfaces above windows for monitor
|
|
|
|
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
2022-03-19 14:00:24 +01:00
|
|
|
SRenderData renderdata = {PMONITOR->output, time, ls->geometry.x, ls->geometry.y};
|
|
|
|
wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata);
|
2022-03-19 13:35:04 +01:00
|
|
|
}
|
|
|
|
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
2022-03-19 14:00:24 +01:00
|
|
|
SRenderData renderdata = {PMONITOR->output, time, ls->geometry.x, ls->geometry.y};
|
|
|
|
wlr_surface_for_each_surface(ls->layerSurface->surface, renderSurface, &renderdata);
|
2022-03-19 13:35:04 +01:00
|
|
|
}
|
2022-03-17 20:22:29 +01:00
|
|
|
}
|
2022-03-19 14:07:18 +01:00
|
|
|
|
|
|
|
void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool test) {
|
|
|
|
wlr_output_configuration_head_v1* head;
|
|
|
|
bool noError = true;
|
|
|
|
|
|
|
|
wl_list_for_each(head, &config->heads, link) {
|
|
|
|
const auto OUTPUT = head->state.output;
|
|
|
|
|
|
|
|
wlr_output_enable(OUTPUT, head->state.enabled);
|
|
|
|
if (head->state.enabled) {
|
|
|
|
if (head->state.mode)
|
|
|
|
wlr_output_set_mode(OUTPUT, head->state.mode);
|
|
|
|
else
|
|
|
|
wlr_output_set_custom_mode(OUTPUT, head->state.custom_mode.width, head->state.custom_mode.height, head->state.custom_mode.refresh);
|
|
|
|
|
|
|
|
wlr_output_layout_move(g_pCompositor->m_sWLROutputLayout, OUTPUT, head->state.x, head->state.y);
|
|
|
|
wlr_output_set_transform(OUTPUT, head->state.transform);
|
|
|
|
wlr_output_set_scale(OUTPUT, head->state.scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
noError = wlr_output_test(OUTPUT);
|
|
|
|
|
|
|
|
if (!noError)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
wl_list_for_each(head, &config->heads, link) {
|
|
|
|
if (noError && !test)
|
|
|
|
wlr_output_commit(head->state.output);
|
|
|
|
else
|
|
|
|
wlr_output_rollback(head->state.output);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::list<SLayerSurface*>& layerSurfaces) {
|
|
|
|
for (auto& ls : layerSurfaces) {
|
|
|
|
|
|
|
|
const auto STATE = &ls->layerSurface->current;
|
|
|
|
wlr_box layerBox = { .width = STATE->desired_width, .height = STATE->desired_height };
|
|
|
|
|
|
|
|
if (STATE->anchor & (ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT))
|
|
|
|
layerBox.width = pMonitor->vecSize.x;
|
|
|
|
if (STATE->anchor & (ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM))
|
|
|
|
layerBox.height = pMonitor->vecSize.y;
|
|
|
|
|
|
|
|
if (STATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) {
|
2022-03-19 16:48:47 +01:00
|
|
|
pMonitor->vecReservedTopLeft.y = STATE->desired_height;
|
2022-03-19 14:37:40 +01:00
|
|
|
layerBox.x = pMonitor->vecPosition.x + STATE->margin.left;
|
|
|
|
layerBox.y = pMonitor->vecPosition.y + STATE->margin.top;
|
|
|
|
|
|
|
|
layerBox.width -= STATE->margin.left + STATE->margin.right;
|
|
|
|
layerBox.height -= STATE->margin.top + STATE->margin.bottom;
|
|
|
|
}
|
|
|
|
if (STATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) {
|
2022-03-19 16:48:47 +01:00
|
|
|
pMonitor->vecReservedBottomRight.y = STATE->desired_height;
|
2022-03-19 14:37:40 +01:00
|
|
|
layerBox.x = pMonitor->vecPosition.x + STATE->margin.left;
|
|
|
|
layerBox.y = pMonitor->vecPosition.y + pMonitor->vecSize.y - layerBox.height - STATE->margin.bottom;
|
|
|
|
|
|
|
|
layerBox.width -= STATE->margin.left + STATE->margin.right;
|
|
|
|
layerBox.height -= STATE->margin.top + STATE->margin.bottom;
|
|
|
|
}
|
|
|
|
if (STATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) {
|
2022-03-19 16:48:47 +01:00
|
|
|
pMonitor->vecReservedTopLeft.x = STATE->desired_width;
|
2022-03-19 14:37:40 +01:00
|
|
|
layerBox.x = pMonitor->vecPosition.x + STATE->margin.left;
|
|
|
|
layerBox.y = pMonitor->vecPosition.y + STATE->margin.top;
|
|
|
|
|
|
|
|
layerBox.width -= STATE->margin.left + STATE->margin.right;
|
|
|
|
layerBox.height -= STATE->margin.top + STATE->margin.bottom;
|
|
|
|
}
|
|
|
|
if (STATE->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) {
|
2022-03-19 16:48:47 +01:00
|
|
|
pMonitor->vecReservedBottomRight.x = STATE->desired_width;
|
2022-03-19 14:37:40 +01:00
|
|
|
layerBox.x = pMonitor->vecPosition.x + pMonitor->vecSize.x - layerBox.width - STATE->margin.right;
|
|
|
|
layerBox.y = pMonitor->vecPosition.y + STATE->margin.top;
|
|
|
|
|
|
|
|
layerBox.width -= STATE->margin.left + STATE->margin.right;
|
|
|
|
layerBox.height -= STATE->margin.top + STATE->margin.bottom;
|
|
|
|
}
|
|
|
|
|
2022-03-20 14:52:23 +01:00
|
|
|
if (!(STATE->anchor & (ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM))) {
|
|
|
|
// no anchors. center
|
|
|
|
layerBox.x = pMonitor->vecPosition.x + (pMonitor->vecSize.x - layerBox.width) / 2.f;
|
|
|
|
layerBox.y = pMonitor->vecPosition.y + (pMonitor->vecSize.y - layerBox.height) / 2.f;
|
|
|
|
|
|
|
|
// TODO: maybe allow the app to choose for itself its x and y?
|
|
|
|
}
|
|
|
|
|
2022-03-19 14:37:40 +01:00
|
|
|
ls->geometry = layerBox;
|
|
|
|
|
|
|
|
wlr_layer_surface_v1_configure(ls->layerSurface, layerBox.width, layerBox.height);
|
|
|
|
|
|
|
|
Debug::log(LOG, "LayerSurface %x arranged: x: %i y: %i w: %i h: %i", &ls, layerBox.x, layerBox.y, layerBox.width, layerBox.height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) {
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitor);
|
|
|
|
|
|
|
|
if (!PMONITOR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Reset the reserved
|
|
|
|
PMONITOR->vecReservedBottomRight = Vector2D();
|
|
|
|
PMONITOR->vecReservedTopLeft = Vector2D();
|
|
|
|
|
|
|
|
for (auto& la : PMONITOR->m_aLayerSurfaceLists)
|
|
|
|
arrangeLayerArray(PMONITOR, la);
|
2022-03-19 16:13:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprRenderer::drawBorderForWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
|
|
|
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
2022-03-20 14:36:55 +01:00
|
|
|
const auto BORDERCOL = pWindow == g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus) ? g_pConfigManager->getInt("general:col.active_border") : g_pConfigManager->getInt("general:col.inactive_border");
|
2022-03-19 16:13:19 +01:00
|
|
|
|
|
|
|
const float BORDERWLRCOL[4] = {RED(BORDERCOL), GREEN(BORDERCOL), BLUE(BORDERCOL), ALPHA(BORDERCOL)};
|
|
|
|
|
2022-03-19 20:30:21 +01:00
|
|
|
Vector2D correctPos = pWindow->m_vRealPosition - pMonitor->vecPosition;
|
|
|
|
|
2022-03-19 16:13:19 +01:00
|
|
|
// top
|
2022-03-19 20:30:21 +01:00
|
|
|
wlr_box border = {correctPos.x - BORDERSIZE, correctPos.y - BORDERSIZE, pWindow->m_vRealSize.x + 2 * BORDERSIZE, BORDERSIZE };
|
2022-03-19 16:13:19 +01:00
|
|
|
wlr_render_rect(g_pCompositor->m_sWLRRenderer, &border, BORDERWLRCOL, pMonitor->output->transform_matrix);
|
|
|
|
|
|
|
|
// bottom
|
2022-03-19 20:30:21 +01:00
|
|
|
border.y = correctPos.y + pWindow->m_vRealSize.y;
|
2022-03-19 16:13:19 +01:00
|
|
|
wlr_render_rect(g_pCompositor->m_sWLRRenderer, &border, BORDERWLRCOL, pMonitor->output->transform_matrix);
|
|
|
|
|
|
|
|
// left
|
2022-03-19 20:30:21 +01:00
|
|
|
border.y = correctPos.y;
|
2022-03-19 16:13:19 +01:00
|
|
|
border.width = BORDERSIZE;
|
|
|
|
border.height = pWindow->m_vRealSize.y;
|
|
|
|
wlr_render_rect(g_pCompositor->m_sWLRRenderer, &border, BORDERWLRCOL, pMonitor->output->transform_matrix);
|
|
|
|
|
|
|
|
// right
|
2022-03-19 20:30:21 +01:00
|
|
|
border.x = correctPos.x + pWindow->m_vRealSize.x;
|
2022-03-19 16:13:19 +01:00
|
|
|
wlr_render_rect(g_pCompositor->m_sWLRRenderer, &border, BORDERWLRCOL, pMonitor->output->transform_matrix);
|
2022-03-19 14:07:18 +01:00
|
|
|
}
|