mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-26 21:45:59 +01:00
surface/wayland: conform to small surface requirements
do not stretch small surfaces, instead center them if they fit.
This commit is contained in:
parent
bab2f6a664
commit
7f35f33b4c
7 changed files with 74 additions and 12 deletions
|
@ -424,6 +424,7 @@ void CWindow::onUnmap() {
|
||||||
void CWindow::onMap() {
|
void CWindow::onMap() {
|
||||||
|
|
||||||
m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this));
|
m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this));
|
||||||
|
m_pWLSurface.m_pOwner = this;
|
||||||
|
|
||||||
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
|
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
|
||||||
m_vRealPosition.resetAllCallbacks();
|
m_vRealPosition.resetAllCallbacks();
|
||||||
|
@ -453,6 +454,8 @@ void CWindow::onMap() {
|
||||||
|
|
||||||
hyprListener_unmapWindow.initCallback(m_bIsX11 ? &m_uSurface.xwayland->surface->events.unmap : &m_uSurface.xdg->surface->events.unmap, &Events::listener_unmapWindow, this,
|
hyprListener_unmapWindow.initCallback(m_bIsX11 ? &m_uSurface.xwayland->surface->events.unmap : &m_uSurface.xdg->surface->events.unmap, &Events::listener_unmapWindow, this,
|
||||||
"CWindow");
|
"CWindow");
|
||||||
|
|
||||||
|
m_vReportedSize = m_vPendingReportedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
||||||
|
@ -882,6 +885,9 @@ bool CWindow::opaque() {
|
||||||
|
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||||
|
|
||||||
|
if (m_pWLSurface.small() && !m_pWLSurface.m_bFillIgnoreSmall)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (PWORKSPACE->m_fAlpha.fl() != 1.f)
|
if (PWORKSPACE->m_fAlpha.fl() != 1.f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,7 @@ class CWindow {
|
||||||
// for not spamming the protocols
|
// for not spamming the protocols
|
||||||
Vector2D m_vReportedPosition;
|
Vector2D m_vReportedPosition;
|
||||||
Vector2D m_vReportedSize;
|
Vector2D m_vReportedSize;
|
||||||
|
Vector2D m_vPendingReportedSize;
|
||||||
|
|
||||||
// for restoring floating statuses
|
// for restoring floating statuses
|
||||||
Vector2D m_vLastFloatingSize;
|
Vector2D m_vLastFloatingSize;
|
||||||
|
|
|
@ -789,6 +789,8 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
|
if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged.
|
||||||
|
|
||||||
PWINDOW->updateSurfaceOutputs();
|
PWINDOW->updateSurfaceOutputs();
|
||||||
|
|
||||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
||||||
|
|
|
@ -27,12 +27,29 @@ wlr_surface* CWLSurface::wlr() const {
|
||||||
return m_pWLRSurface;
|
return m_pWLRSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CWLSurface::small() const {
|
||||||
|
if (!m_pOwner || !exists())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_pOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width || m_pOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CWLSurface::correctSmallVec() const {
|
||||||
|
if (!m_pOwner || !exists() || !small() || m_bFillIgnoreSmall)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return Vector2D{(m_pOwner->m_vReportedSize.x - m_pWLRSurface->current.buffer_width) / 2, (m_pOwner->m_vReportedSize.y - m_pWLRSurface->current.buffer_height) / 2}.clamp(
|
||||||
|
{}, {INFINITY, INFINITY}) *
|
||||||
|
(m_pOwner->m_vRealSize.vec() / m_pOwner->m_vReportedSize);
|
||||||
|
}
|
||||||
|
|
||||||
void CWLSurface::destroy() {
|
void CWLSurface::destroy() {
|
||||||
if (!m_pWLRSurface)
|
if (!m_pWLRSurface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hyprListener_destroy.removeCallback();
|
hyprListener_destroy.removeCallback();
|
||||||
m_pWLRSurface->data = nullptr;
|
m_pWLRSurface->data = nullptr;
|
||||||
|
m_pOwner = nullptr;
|
||||||
|
|
||||||
if (g_pCompositor->m_pLastFocus == m_pWLRSurface)
|
if (g_pCompositor->m_pLastFocus == m_pWLRSurface)
|
||||||
g_pCompositor->m_pLastFocus = nullptr;
|
g_pCompositor->m_pLastFocus = nullptr;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
|
||||||
|
class CWindow;
|
||||||
|
|
||||||
class CWLSurface {
|
class CWLSurface {
|
||||||
public:
|
public:
|
||||||
CWLSurface() = default;
|
CWLSurface() = default;
|
||||||
|
@ -17,6 +20,14 @@ class CWLSurface {
|
||||||
|
|
||||||
wlr_surface* wlr() const;
|
wlr_surface* wlr() const;
|
||||||
bool exists() const;
|
bool exists() const;
|
||||||
|
bool small() const; // means surface is smaller than the requested size
|
||||||
|
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
||||||
|
|
||||||
|
// allow stretching. Useful for plugins.
|
||||||
|
bool m_bFillIgnoreSmall = false;
|
||||||
|
|
||||||
|
// if present, means this is a base surface of a window. Cleaned on unassign()
|
||||||
|
CWindow* m_pOwner = nullptr;
|
||||||
|
|
||||||
CWLSurface& operator=(wlr_surface* pSurface) {
|
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||||
destroy();
|
destroy();
|
||||||
|
@ -38,6 +49,10 @@ class CWLSurface {
|
||||||
return exists();
|
return exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) {
|
||||||
|
return (CWLSurface*)pSurface->data;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wlr_surface* m_pWLRSurface = nullptr;
|
wlr_surface* m_pWLRSurface = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pWindow->m_vReportedPosition = windowPos;
|
pWindow->m_vReportedPosition = windowPos;
|
||||||
pWindow->m_vReportedSize = size;
|
pWindow->m_vPendingReportedSize = size;
|
||||||
|
|
||||||
pWindow->m_fX11SurfaceScaledBy = 1.f;
|
pWindow->m_fX11SurfaceScaledBy = 1.f;
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,23 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||||
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->pMonitor->output, &outputX, &outputY);
|
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->pMonitor->output, &outputX, &outputY);
|
||||||
|
|
||||||
wlr_box windowBox;
|
wlr_box windowBox;
|
||||||
if (RDATA->surface && surface == RDATA->surface)
|
if (RDATA->surface && surface == RDATA->surface) {
|
||||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
|
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
|
||||||
else { // here we clamp to 2, these might be some tiny specks
|
|
||||||
|
// however, if surface buffer w / h < box, we need to adjust them
|
||||||
|
auto* const PSURFACE = CWLSurface::surfaceFromWlr(surface);
|
||||||
|
|
||||||
|
if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees m_pOwner */) {
|
||||||
|
const auto CORRECT = PSURFACE->correctSmallVec();
|
||||||
|
|
||||||
|
windowBox.x += CORRECT.x;
|
||||||
|
windowBox.y += CORRECT.y;
|
||||||
|
|
||||||
|
windowBox.width = (double)surface->current.buffer_width * (PSURFACE->m_pOwner->m_vRealSize.vec().x / PSURFACE->m_pOwner->m_vReportedSize.x);
|
||||||
|
windowBox.height = (double)surface->current.buffer_height * (PSURFACE->m_pOwner->m_vRealSize.vec().y / PSURFACE->m_pOwner->m_vReportedSize.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // here we clamp to 2, these might be some tiny specks
|
||||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max(surface->current.width, 2), std::max(surface->current.height, 2)};
|
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max(surface->current.width, 2), std::max(surface->current.height, 2)};
|
||||||
if (RDATA->pWindow && RDATA->pWindow->m_vRealSize.isBeingAnimated() && RDATA->surface && RDATA->surface != surface && RDATA->squishOversized /* subsurface */) {
|
if (RDATA->pWindow && RDATA->pWindow->m_vRealSize.isBeingAnimated() && RDATA->surface && RDATA->surface != surface && RDATA->squishOversized /* subsurface */) {
|
||||||
// adjust subsurfaces to the window
|
// adjust subsurfaces to the window
|
||||||
|
@ -1392,6 +1406,13 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou
|
||||||
if (g_pCompositor->m_bUnsafeState)
|
if (g_pCompositor->m_bUnsafeState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto* const PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
||||||
|
if (PSURFACE && PSURFACE->m_pOwner && PSURFACE->small()) {
|
||||||
|
const auto CORRECTION = PSURFACE->correctSmallVec();
|
||||||
|
x += CORRECTION.x;
|
||||||
|
y += CORRECTION.y;
|
||||||
|
}
|
||||||
|
|
||||||
CRegion damageBox;
|
CRegion damageBox;
|
||||||
wlr_surface_get_effective_damage(pSurface, damageBox.pixman());
|
wlr_surface_get_effective_damage(pSurface, damageBox.pixman());
|
||||||
if (scale != 1.0)
|
if (scale != 1.0)
|
||||||
|
|
Loading…
Reference in a new issue