mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-15 20:13:49 -07:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
75dff7205f | ||
|
48817b97f5 | ||
|
664da71d10 | ||
|
a285722bc8 | ||
|
bdee557d15 | ||
|
901271fa8b | ||
|
fa61042288 | ||
|
778508e39e | ||
|
762bbf5857 | ||
|
c68653d7c4 | ||
|
56540f5bd8 | ||
|
017f322532 | ||
|
a7d7df5c4b | ||
|
0d06f287d0 |
@@ -197,6 +197,12 @@ if(NOT HAS_TIMERFD AND epoll_FOUND)
|
||||
target_link_libraries(Hyprland PkgConfig::epoll)
|
||||
endif()
|
||||
|
||||
check_include_file("sys/inotify.h" HAS_INOTIFY)
|
||||
pkg_check_modules(inotify IMPORTED_TARGET libinotify)
|
||||
if(NOT HAS_INOTIFY AND inotify_FOUND)
|
||||
target_link_libraries(Hyprland PkgConfig::inotify)
|
||||
endif()
|
||||
|
||||
if(LEGACY_RENDERER)
|
||||
message(STATUS "Using the legacy GLES2 renderer!")
|
||||
add_compile_definitions(LEGACY_RENDERER)
|
||||
|
@@ -58,6 +58,7 @@ endif
|
||||
|
||||
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
||||
epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs
|
||||
inotify_dep = dependency('libinotify', required: false) # inotify on BSDs
|
||||
|
||||
re2 = dependency('re2', required: true)
|
||||
|
||||
|
@@ -912,12 +912,16 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
|
||||
return RET;
|
||||
}
|
||||
|
||||
void CConfigManager::updateWatcher() {
|
||||
static const auto PDISABLEAUTORELOAD = CConfigValue<Hyprlang::INT>("misc:disable_autoreload");
|
||||
g_pConfigWatcher->setWatchList(*PDISABLEAUTORELOAD ? std::vector<std::string>{} : m_configPaths);
|
||||
}
|
||||
|
||||
void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
||||
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
|
||||
static const auto PDISABLEAUTORELOAD = CConfigValue<Hyprlang::INT>("misc:disable_autoreload");
|
||||
static int prevEnabledExplicit = *PENABLEEXPLICIT;
|
||||
|
||||
g_pConfigWatcher->setWatchList(*PDISABLEAUTORELOAD ? std::vector<std::string>{} : m_configPaths);
|
||||
updateWatcher();
|
||||
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
w->uncacheWindowDecos();
|
||||
@@ -2690,8 +2694,14 @@ std::optional<std::string> CConfigManager::handleSource(const std::string& comma
|
||||
Debug::log(ERR, "source= path garbage");
|
||||
return "source= path " + rawpath + " bogus!";
|
||||
}
|
||||
std::unique_ptr<glob_t, void (*)(glob_t*)> glob_buf{new glob_t, [](glob_t* g) { globfree(g); }};
|
||||
memset(glob_buf.get(), 0, sizeof(glob_t));
|
||||
|
||||
std::unique_ptr<glob_t, void (*)(glob_t*)> glob_buf{static_cast<glob_t*>(calloc(1, sizeof(glob_t))), // allocate and zero-initialize
|
||||
[](glob_t* g) {
|
||||
if (g) {
|
||||
globfree(g); // free internal resources allocated by glob()
|
||||
free(g); // free the memory for the glob_t structure
|
||||
}
|
||||
}};
|
||||
|
||||
if (auto r = glob(absolutePath(rawpath, configCurrentPath).c_str(), GLOB_TILDE, nullptr, glob_buf.get()); r != 0) {
|
||||
std::string err = std::format("source= globbing error: {}", r == GLOB_NOMATCH ? "found no match" : GLOB_ABORTED ? "read error" : "out of memory");
|
||||
|
@@ -190,6 +190,7 @@ class CConfigManager {
|
||||
void ensureVRR(PHLMONITOR pMonitor = nullptr);
|
||||
|
||||
bool shouldUseSoftwareCursors();
|
||||
void updateWatcher();
|
||||
|
||||
std::string parseKeyword(const std::string&, const std::string&);
|
||||
|
||||
|
@@ -1100,6 +1100,9 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in)
|
||||
}
|
||||
}
|
||||
|
||||
if (COMMAND.contains("misc:disable_autoreload"))
|
||||
g_pConfigManager->updateWatcher();
|
||||
|
||||
// decorations will probably need a repaint
|
||||
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source" ||
|
||||
COMMAND.starts_with("windowrule")) {
|
||||
|
@@ -138,10 +138,11 @@ void CPopup::onUnmap() {
|
||||
},
|
||||
nullptr);
|
||||
|
||||
const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == m_pWLSurface->resource() || g_pSeatManager->state.pointerFocus == m_pWLSurface->resource();
|
||||
// TODO: probably refocus, but without a motion event?
|
||||
// const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == m_pWLSurface->resource() || g_pSeatManager->state.pointerFocus == m_pWLSurface->resource();
|
||||
|
||||
if (WASLASTFOCUS)
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
// if (WASLASTFOCUS)
|
||||
// g_pInputManager->simulateMouseMovement();
|
||||
}
|
||||
|
||||
void CPopup::onCommit(bool ignoreSiblings) {
|
||||
|
@@ -143,7 +143,7 @@ void CSubsurface::onNewSubsurface(SP<CWLSubsurfaceResource> pSubsurface) {
|
||||
|
||||
ASSERT(PSUBSURFACE);
|
||||
|
||||
PSUBSURFACE->m_pParent = PSUBSURFACE;
|
||||
PSUBSURFACE->m_pParent = m_pSelf;
|
||||
}
|
||||
|
||||
void CSubsurface::onMap() {
|
||||
|
@@ -44,6 +44,10 @@ void IKeyboard::clearManuallyAllocd() {
|
||||
if (xkbKeymapFD >= 0)
|
||||
close(xkbKeymapFD);
|
||||
|
||||
if (xkbSymState)
|
||||
xkb_state_unref(xkbSymState);
|
||||
|
||||
xkbSymState = nullptr;
|
||||
xkbKeymap = nullptr;
|
||||
xkbState = nullptr;
|
||||
xkbStaticState = nullptr;
|
||||
|
@@ -456,9 +456,9 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
|
||||
|
||||
// sort prioritizing refresh rate 1st and resolution 2nd, then add best 3
|
||||
addBest3Modes([](auto const& a, auto const& b) {
|
||||
if (a->refreshRate > b->refreshRate)
|
||||
if (std::round(a->refreshRate) > std::round(b->refreshRate))
|
||||
return true;
|
||||
else if (DELTALESSTHAN((float)a->refreshRate, (float)b->refreshRate, 1000) && a->pixelSize.x > b->pixelSize.x && a->pixelSize.y > b->pixelSize.y)
|
||||
else if (DELTALESSTHAN((float)a->refreshRate, (float)b->refreshRate, 1.F) && a->pixelSize.x > b->pixelSize.x && a->pixelSize.y > b->pixelSize.y)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
@@ -469,7 +469,8 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
|
||||
addBest3Modes([](auto const& a, auto const& b) {
|
||||
if (a->pixelSize.x > b->pixelSize.x && a->pixelSize.y > b->pixelSize.y)
|
||||
return true;
|
||||
else if (DELTALESSTHAN(a->pixelSize.x, b->pixelSize.x, 1) && DELTALESSTHAN(a->pixelSize.y, b->pixelSize.y, 1) && a->refreshRate > b->refreshRate)
|
||||
else if (DELTALESSTHAN(a->pixelSize.x, b->pixelSize.x, 1) && DELTALESSTHAN(a->pixelSize.y, b->pixelSize.y, 1) &&
|
||||
std::round(a->refreshRate) > std::round(b->refreshRate))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
@@ -33,7 +33,7 @@ struct SMonitorRule {
|
||||
Vector2D resolution = Vector2D(1280, 720);
|
||||
Vector2D offset = Vector2D(0, 0);
|
||||
float scale = 1;
|
||||
float refreshRate = 60;
|
||||
float refreshRate = 60; // Hz
|
||||
bool disabled = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
std::string mirrorOf = "";
|
||||
@@ -92,7 +92,7 @@ class CMonitor {
|
||||
CDamageRing damage;
|
||||
|
||||
SP<Aquamarine::IOutput> output;
|
||||
float refreshRate = 60;
|
||||
float refreshRate = 60; // Hz
|
||||
int forceFullFrames = 0;
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
@@ -82,29 +82,9 @@ CBox CHyprXWaylandManager::getGeometryForWindow(PHLWINDOW pWindow) {
|
||||
|
||||
CBox box;
|
||||
|
||||
if (pWindow->m_bIsX11) {
|
||||
const auto SIZEHINTS = pWindow->m_pXWaylandSurface->sizeHints.get();
|
||||
|
||||
if (SIZEHINTS && !pWindow->isX11OverrideRedirect()) {
|
||||
// WM_SIZE_HINTS' x,y,w,h is deprecated it seems.
|
||||
// Source: https://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#wm_normal_hints_property
|
||||
box.x = pWindow->m_pXWaylandSurface->geometry.x;
|
||||
box.y = pWindow->m_pXWaylandSurface->geometry.y;
|
||||
|
||||
constexpr int ICCCM_USSize = 0x2;
|
||||
constexpr int ICCCM_PSize = 0x8;
|
||||
|
||||
if ((SIZEHINTS->flags & ICCCM_USSize) || (SIZEHINTS->flags & ICCCM_PSize)) {
|
||||
box.w = SIZEHINTS->base_width;
|
||||
box.h = SIZEHINTS->base_height;
|
||||
} else {
|
||||
box.w = pWindow->m_pXWaylandSurface->geometry.w;
|
||||
box.h = pWindow->m_pXWaylandSurface->geometry.h;
|
||||
}
|
||||
} else
|
||||
box = pWindow->m_pXWaylandSurface->geometry;
|
||||
|
||||
} else if (pWindow->m_pXDGSurface)
|
||||
if (pWindow->m_bIsX11)
|
||||
box = pWindow->m_pXWaylandSurface->geometry;
|
||||
else if (pWindow->m_pXDGSurface)
|
||||
box = pWindow->m_pXDGSurface->current.geometry;
|
||||
|
||||
return box;
|
||||
|
@@ -32,6 +32,7 @@ executable(
|
||||
xcb_xfixes_dep,
|
||||
backtrace_dep,
|
||||
epoll_dep,
|
||||
inotify_dep,
|
||||
gio_dep,
|
||||
tracy,
|
||||
|
||||
|
@@ -130,6 +130,11 @@ void CPresentationProtocol::onPresented(PHLMONITOR pMonitor, timespec* when, uin
|
||||
}
|
||||
}
|
||||
|
||||
if (m_vFeedbacks.size() > 10000 /* arbitrary number I chose as fitting */) {
|
||||
LOGM(ERR, "FIXME: presentation has a feedback leak, and has grown to {} pending entries!!! Dropping!!!!!", m_vFeedbacks.size());
|
||||
m_vFeedbacks = {m_vFeedbacks.begin() + 9000, m_vFeedbacks.end()};
|
||||
}
|
||||
|
||||
std::erase_if(m_vFeedbacks, [](const auto& other) { return !other->surface || other->done; });
|
||||
std::erase_if(m_vQueue, [pMonitor](const auto& other) { return !other->surface || other->pMonitor == pMonitor || !other->pMonitor || other->done; });
|
||||
}
|
||||
|
@@ -2147,14 +2147,20 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, const CBox& box, f
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
// stencil done. Render everything.
|
||||
CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
// render our great blurred FB
|
||||
// calculate the uv for it
|
||||
const auto LASTTL = m_RenderData.primarySurfaceUVTopLeft;
|
||||
const auto LASTBR = m_RenderData.primarySurfaceUVBottomRight;
|
||||
|
||||
m_RenderData.primarySurfaceUVTopLeft = box.pos() / MONITORBOX.size();
|
||||
m_RenderData.primarySurfaceUVBottomRight = (box.pos() + box.size()) / MONITORBOX.size();
|
||||
CBox transformedBox = box;
|
||||
transformedBox.transform(wlTransformToHyprutils(invertTransform(m_RenderData.pMonitor->transform)), m_RenderData.pMonitor->vecTransformedSize.x,
|
||||
m_RenderData.pMonitor->vecTransformedSize.y);
|
||||
|
||||
CBox monitorSpaceBox = {transformedBox.pos().x / m_RenderData.pMonitor->vecPixelSize.x * m_RenderData.pMonitor->vecTransformedSize.x,
|
||||
transformedBox.pos().y / m_RenderData.pMonitor->vecPixelSize.y * m_RenderData.pMonitor->vecTransformedSize.y,
|
||||
transformedBox.width / m_RenderData.pMonitor->vecPixelSize.x * m_RenderData.pMonitor->vecTransformedSize.x,
|
||||
transformedBox.height / m_RenderData.pMonitor->vecPixelSize.y * m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
|
||||
m_RenderData.primarySurfaceUVTopLeft = monitorSpaceBox.pos() / m_RenderData.pMonitor->vecTransformedSize;
|
||||
m_RenderData.primarySurfaceUVBottomRight = (monitorSpaceBox.pos() + monitorSpaceBox.size()) / m_RenderData.pMonitor->vecTransformedSize;
|
||||
|
||||
static auto PBLURIGNOREOPACITY = CConfigValue<Hyprlang::INT>("decoration:blur:ignore_opacity");
|
||||
setMonitorTransformEnabled(true);
|
||||
|
@@ -337,7 +337,8 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR
|
||||
|
||||
// then render windows over fullscreen.
|
||||
for (auto const& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || !w->m_bIsFloating || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->isFullscreen())
|
||||
if (w->m_pWorkspace != pWorkspaceWindow->m_pWorkspace || !w->m_bIsFloating || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) ||
|
||||
w->isFullscreen())
|
||||
continue;
|
||||
|
||||
if (w->m_pMonitor == pWorkspace->m_pMonitor && pWorkspace->m_bIsSpecialWorkspace != w->onSpecialWorkspace())
|
||||
|
@@ -13,7 +13,7 @@ class IPassElement {
|
||||
virtual const char* passName() = 0;
|
||||
virtual void discard();
|
||||
virtual bool undiscardable();
|
||||
virtual std::optional<CBox> boundingBox();
|
||||
virtual CRegion opaqueRegion();
|
||||
virtual std::optional<CBox> boundingBox(); // in monitor-local logical coordinates
|
||||
virtual CRegion opaqueRegion(); // in monitor-local logical coordinates
|
||||
virtual bool disableSimplification();
|
||||
};
|
||||
|
@@ -24,7 +24,7 @@ bool CRectPassElement::needsPrecomputeBlur() {
|
||||
}
|
||||
|
||||
std::optional<CBox> CRectPassElement::boundingBox() {
|
||||
return data.box;
|
||||
return data.box.copy().scale(1.F / g_pHyprOpenGL->m_RenderData.pMonitor->scale).round();
|
||||
}
|
||||
|
||||
CRegion CRectPassElement::opaqueRegion() {
|
||||
|
@@ -169,6 +169,22 @@ void CXWaylandSurface::configure(const CBox& box) {
|
||||
uint32_t values[] = {box.x, box.y, box.width, box.height, 0};
|
||||
xcb_configure_window(g_pXWayland->pWM->connection, xID, mask, values);
|
||||
|
||||
if (geometry.width == box.width && geometry.height == box.height) {
|
||||
// ICCCM requires a synthetic event when window size is not changed
|
||||
xcb_configure_notify_event_t e;
|
||||
e.response_type = XCB_CONFIGURE_NOTIFY;
|
||||
e.event = xID;
|
||||
e.window = xID;
|
||||
e.x = box.x;
|
||||
e.y = box.y;
|
||||
e.width = box.width;
|
||||
e.height = box.height;
|
||||
e.border_width = 0;
|
||||
e.above_sibling = XCB_NONE;
|
||||
e.override_redirect = overrideRedirect;
|
||||
xcb_send_event(g_pXWayland->pWM->connection, false, xID, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char*)&e);
|
||||
}
|
||||
|
||||
g_pXWayland->pWM->updateClientList();
|
||||
|
||||
xcb_flush(g_pXWayland->pWM->connection);
|
||||
|
@@ -102,8 +102,8 @@ void CXWM::handleMapRequest(xcb_map_request_event_t* e) {
|
||||
const bool HAS_HINTS = XSURF->sizeHints && Vector2D{XSURF->sizeHints->base_width, XSURF->sizeHints->base_height} > Vector2D{5, 5};
|
||||
const auto DESIREDSIZE = HAS_HINTS ? Vector2D{XSURF->sizeHints->base_width, XSURF->sizeHints->base_height} : Vector2D{800, 800};
|
||||
|
||||
// if it's too small, or its base size is set, configure it.
|
||||
if ((SMALL || HAS_HINTS) && !XSURF->overrideRedirect) // default to 800 x 800
|
||||
// if it's too small, configure it.
|
||||
if (SMALL && !XSURF->overrideRedirect) // default to 800 x 800
|
||||
XSURF->configure({XSURF->geometry.pos(), DESIREDSIZE});
|
||||
|
||||
Debug::log(LOG, "[xwm] Mapping window {} in X (geometry {}x{} at {}x{}))", e->window, XSURF->geometry.width, XSURF->geometry.height, XSURF->geometry.x, XSURF->geometry.y);
|
||||
|
Reference in New Issue
Block a user