wayland/core: move to new impl (#6268)
* wayland/core/dmabuf: move to new impl it's the final countdown
This commit is contained in:
parent
c31d9ef417
commit
6967a31450
147 changed files with 5388 additions and 2226 deletions
271
src/helpers/Format.cpp
Normal file
271
src/helpers/Format.cpp
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
#include "Format.hpp"
|
||||
#include <vector>
|
||||
#include "../includes.hpp"
|
||||
|
||||
/*
|
||||
DRM formats are LE, while OGL is BE. The two primary formats
|
||||
will be flipped, so we will set flipRB which will later use swizzle
|
||||
to flip the red and blue channels.
|
||||
This will not work on GLES2, but I want to drop support for it one day anyways.
|
||||
*/
|
||||
inline const std::vector<SPixelFormat> GLES3_FORMATS = {
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ARGB8888,
|
||||
.flipRB = true,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = true,
|
||||
.alphaStripped = DRM_FORMAT_XRGB8888,
|
||||
.bytesPerBlock = 4,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XRGB8888,
|
||||
.flipRB = true,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_XRGB8888,
|
||||
.bytesPerBlock = 4,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR8888,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_XBGR8888,
|
||||
.bytesPerBlock = 4,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR8888,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = true,
|
||||
.alphaStripped = DRM_FORMAT_XBGR8888,
|
||||
.bytesPerBlock = 4,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_BGR888,
|
||||
.glFormat = GL_RGB,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_BGR888,
|
||||
.bytesPerBlock = 3,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBX4444,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_RGBX4444,
|
||||
.bytesPerBlock = 2,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBA4444,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
.withAlpha = true,
|
||||
.alphaStripped = DRM_FORMAT_RGBX4444,
|
||||
.bytesPerBlock = 2,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBX5551,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_RGBX5551,
|
||||
.bytesPerBlock = 2,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBA5551,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
.withAlpha = true,
|
||||
.alphaStripped = DRM_FORMAT_RGBX5551,
|
||||
.bytesPerBlock = 2,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGB565,
|
||||
.glFormat = GL_RGB,
|
||||
.glType = GL_UNSIGNED_SHORT_5_6_5,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_RGB565,
|
||||
.bytesPerBlock = 2,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR2101010,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_XBGR2101010,
|
||||
.bytesPerBlock = 4,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR2101010,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||
.withAlpha = true,
|
||||
.alphaStripped = DRM_FORMAT_XBGR2101010,
|
||||
.bytesPerBlock = 4,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XRGB2101010,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_XRGB2101010,
|
||||
.bytesPerBlock = 4,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ARGB2101010,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||
.withAlpha = true,
|
||||
.alphaStripped = DRM_FORMAT_XRGB2101010,
|
||||
.bytesPerBlock = 4,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR16161616F,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_HALF_FLOAT,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_XBGR16161616F,
|
||||
.bytesPerBlock = 8,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR16161616F,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_HALF_FLOAT,
|
||||
.withAlpha = true,
|
||||
.alphaStripped = DRM_FORMAT_XBGR16161616F,
|
||||
.bytesPerBlock = 8,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR16161616,
|
||||
.glInternalFormat = GL_RGBA16UI,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT,
|
||||
.withAlpha = false,
|
||||
.alphaStripped = DRM_FORMAT_XBGR16161616,
|
||||
.bytesPerBlock = 8,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR16161616,
|
||||
.glInternalFormat = GL_RGBA16UI,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT,
|
||||
.withAlpha = true,
|
||||
.alphaStripped = DRM_FORMAT_XBGR16161616,
|
||||
.bytesPerBlock = 8,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_YVYU,
|
||||
.bytesPerBlock = 4,
|
||||
.blockSize = {2, 1},
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_VYUY,
|
||||
.bytesPerBlock = 4,
|
||||
.blockSize = {2, 1},
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_R8,
|
||||
.bytesPerBlock = 1,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_GR88,
|
||||
.bytesPerBlock = 2,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGB888,
|
||||
.bytesPerBlock = 3,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_BGR888,
|
||||
.bytesPerBlock = 3,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBX4444,
|
||||
.bytesPerBlock = 2,
|
||||
},
|
||||
};
|
||||
|
||||
SHMFormat FormatUtils::drmToShm(DRMFormat drm) {
|
||||
switch (drm) {
|
||||
case DRM_FORMAT_XRGB8888: return WL_SHM_FORMAT_XRGB8888;
|
||||
case DRM_FORMAT_ARGB8888: return WL_SHM_FORMAT_ARGB8888;
|
||||
default: return drm;
|
||||
}
|
||||
|
||||
return drm;
|
||||
}
|
||||
|
||||
DRMFormat FormatUtils::shmToDRM(SHMFormat shm) {
|
||||
switch (shm) {
|
||||
case WL_SHM_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888;
|
||||
case WL_SHM_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888;
|
||||
default: return shm;
|
||||
}
|
||||
|
||||
return shm;
|
||||
}
|
||||
|
||||
const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) {
|
||||
for (auto& fmt : GLES3_FORMATS) {
|
||||
if (fmt.drmFormat == drm)
|
||||
return &fmt;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SPixelFormat* FormatUtils::getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha) {
|
||||
for (auto& fmt : GLES3_FORMATS) {
|
||||
if (fmt.glFormat == (int)glFormat && fmt.glType == (int)glType && fmt.withAlpha == alpha)
|
||||
return &fmt;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool FormatUtils::isFormatOpaque(DRMFormat drm) {
|
||||
const auto FMT = FormatUtils::getPixelFormatFromDRM(drm);
|
||||
if (!FMT)
|
||||
return false;
|
||||
|
||||
return !FMT->withAlpha;
|
||||
}
|
||||
|
||||
int FormatUtils::pixelsPerBlock(const SPixelFormat* const fmt) {
|
||||
return fmt->blockSize.x * fmt->blockSize.y > 0 ? fmt->blockSize.x * fmt->blockSize.y : 1;
|
||||
}
|
||||
|
||||
int FormatUtils::minStride(const SPixelFormat* const fmt, int32_t width) {
|
||||
return std::ceil((width * fmt->bytesPerBlock) / pixelsPerBlock(fmt));
|
||||
}
|
||||
|
||||
uint32_t FormatUtils::drmFormatToGL(DRMFormat drm) {
|
||||
switch (drm) {
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case.
|
||||
case DRM_FORMAT_XRGB2101010:
|
||||
case DRM_FORMAT_XBGR2101010:
|
||||
#ifdef GLES2
|
||||
return GL_RGB10_A2_EXT;
|
||||
#else
|
||||
return GL_RGB10_A2;
|
||||
#endif
|
||||
default: return GL_RGBA;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return GL_RGBA;
|
||||
}
|
||||
|
||||
uint32_t FormatUtils::glFormatToType(uint32_t gl) {
|
||||
return gl != GL_RGBA ?
|
||||
#ifdef GLES2
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV_EXT :
|
||||
#else
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV :
|
||||
#endif
|
||||
GL_UNSIGNED_BYTE;
|
||||
}
|
||||
37
src/helpers/Format.hpp
Normal file
37
src/helpers/Format.hpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "Vector2D.hpp"
|
||||
|
||||
typedef uint32_t DRMFormat;
|
||||
typedef uint32_t SHMFormat;
|
||||
|
||||
struct SPixelFormat {
|
||||
DRMFormat drmFormat = 0; /* DRM_FORMAT_INVALID */
|
||||
bool flipRB = false;
|
||||
int glInternalFormat = 0;
|
||||
int glFormat = 0;
|
||||
int glType = 0;
|
||||
bool withAlpha = true;
|
||||
DRMFormat alphaStripped = 0; /* DRM_FORMAT_INVALID */
|
||||
uint32_t bytesPerBlock = 0;
|
||||
Vector2D blockSize;
|
||||
};
|
||||
|
||||
struct SDRMFormat {
|
||||
uint32_t format = 0;
|
||||
std::vector<uint64_t> mods;
|
||||
};
|
||||
|
||||
namespace FormatUtils {
|
||||
SHMFormat drmToShm(DRMFormat drm);
|
||||
DRMFormat shmToDRM(SHMFormat shm);
|
||||
|
||||
const SPixelFormat* getPixelFormatFromDRM(DRMFormat drm);
|
||||
const SPixelFormat* getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha);
|
||||
bool isFormatOpaque(DRMFormat drm);
|
||||
int pixelsPerBlock(const SPixelFormat* const fmt);
|
||||
int minStride(const SPixelFormat* const fmt, int32_t width);
|
||||
uint32_t drmFormatToGL(DRMFormat drm);
|
||||
uint32_t glFormatToType(uint32_t gl);
|
||||
};
|
||||
|
|
@ -857,33 +857,6 @@ void throwError(const std::string& err) {
|
|||
throw std::runtime_error(err);
|
||||
}
|
||||
|
||||
uint32_t drmFormatToGL(uint32_t drm) {
|
||||
switch (drm) {
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case.
|
||||
case DRM_FORMAT_XRGB2101010:
|
||||
case DRM_FORMAT_XBGR2101010:
|
||||
#ifdef GLES2
|
||||
return GL_RGB10_A2_EXT;
|
||||
#else
|
||||
return GL_RGB10_A2;
|
||||
#endif
|
||||
default: return GL_RGBA;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return GL_RGBA;
|
||||
}
|
||||
|
||||
uint32_t glFormatToType(uint32_t gl) {
|
||||
return gl != GL_RGBA ?
|
||||
#ifdef GLES2
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV_EXT :
|
||||
#else
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV :
|
||||
#endif
|
||||
GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
bool envEnabled(const std::string& env) {
|
||||
const auto ENV = getenv(env.c_str());
|
||||
if (!ENV)
|
||||
|
|
@ -922,3 +895,42 @@ int allocateSHMFile(size_t len) {
|
|||
|
||||
return fd;
|
||||
}
|
||||
|
||||
bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr) {
|
||||
auto [fd, name] = openExclusiveShm();
|
||||
if (fd < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// CLOEXEC is guaranteed to be set by shm_open
|
||||
int ro_fd = shm_open(name.c_str(), O_RDONLY, 0);
|
||||
if (ro_fd < 0) {
|
||||
shm_unlink(name.c_str());
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
shm_unlink(name.c_str());
|
||||
|
||||
// Make sure the file cannot be re-opened in read-write mode (e.g. via
|
||||
// "/proc/self/fd/" on Linux)
|
||||
if (fchmod(fd, 0) != 0) {
|
||||
close(fd);
|
||||
close(ro_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
int ret;
|
||||
do {
|
||||
ret = ftruncate(fd, size);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
close(ro_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
*rw_fd_ptr = fd;
|
||||
*ro_fd_ptr = ro_fd;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,9 @@ double normalizeAngleRad(double ang);
|
|||
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace);
|
||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||
void throwError(const std::string& err);
|
||||
uint32_t drmFormatToGL(uint32_t drm);
|
||||
uint32_t glFormatToType(uint32_t gl);
|
||||
bool envEnabled(const std::string& env);
|
||||
int allocateSHMFile(size_t len);
|
||||
bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr);
|
||||
|
||||
template <typename... Args>
|
||||
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {
|
||||
|
|
|
|||
|
|
@ -216,7 +216,6 @@ void CMonitor::onConnect(bool noRule) {
|
|||
PROTO::gamma->applyGammaToState(this);
|
||||
|
||||
events.connect.emit();
|
||||
updateGlobal();
|
||||
}
|
||||
|
||||
void CMonitor::onDisconnect(bool destroy) {
|
||||
|
|
@ -284,8 +283,6 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
m_bEnabled = false;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
updateGlobal();
|
||||
|
||||
if (BACKUPMON) {
|
||||
// snap cursor
|
||||
g_pCompositor->warpCursorTo(BACKUPMON->vecPosition + BACKUPMON->vecTransformedSize / 2.F, true);
|
||||
|
|
@ -304,7 +301,7 @@ void CMonitor::onDisconnect(bool destroy) {
|
|||
w->startAnim(true, true, true);
|
||||
}
|
||||
} else {
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
g_pCompositor->m_pLastFocus.reset();
|
||||
g_pCompositor->m_pLastWindow.reset();
|
||||
g_pCompositor->m_pLastMonitor.reset();
|
||||
}
|
||||
|
|
@ -750,13 +747,6 @@ CBox CMonitor::logicalBox() {
|
|||
return {vecPosition, vecSize};
|
||||
}
|
||||
|
||||
void CMonitor::updateGlobal() {
|
||||
if (output->width > 0 && output->height > 0 && m_bEnabled)
|
||||
wlr_output_create_global(output, g_pCompositor->m_sWLDisplay);
|
||||
else
|
||||
wlr_output_destroy_global(output);
|
||||
}
|
||||
|
||||
CMonitorState::CMonitorState(CMonitor* owner) {
|
||||
m_pOwner = owner;
|
||||
wlr_output_state_init(&m_state);
|
||||
|
|
|
|||
|
|
@ -172,7 +172,6 @@ class CMonitor {
|
|||
int64_t activeWorkspaceID();
|
||||
int64_t activeSpecialWorkspaceID();
|
||||
CBox logicalBox();
|
||||
void updateGlobal();
|
||||
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ extern "C" {
|
|||
#include <wlr/util/region.h>
|
||||
}
|
||||
|
||||
constexpr const int64_t MAX_REGION_SIDE = 10000000;
|
||||
|
||||
CRegion::CRegion() {
|
||||
pixman_region32_init(&m_rRegion);
|
||||
}
|
||||
|
|
@ -103,6 +105,11 @@ CRegion& CRegion::transform(const wl_output_transform t, double w, double h) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::rationalize() {
|
||||
intersect(CBox{-MAX_REGION_SIDE, -MAX_REGION_SIDE, MAX_REGION_SIDE * 2, MAX_REGION_SIDE * 2});
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion CRegion::copy() const {
|
||||
return CRegion(*this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class CRegion {
|
|||
CRegion& invert(const CBox& box);
|
||||
CRegion& scale(float scale);
|
||||
CRegion& scale(const Vector2D& scale);
|
||||
CRegion& rationalize();
|
||||
CBox getExtents();
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
class CMonitor;
|
||||
class IPointer;
|
||||
class IKeyboard;
|
||||
class CWLSurfaceResource;
|
||||
|
||||
struct SRenderData {
|
||||
CMonitor* pMonitor;
|
||||
|
|
@ -20,9 +21,9 @@ struct SRenderData {
|
|||
double x, y;
|
||||
|
||||
// for iters
|
||||
void* data = nullptr;
|
||||
wlr_surface* surface = nullptr;
|
||||
double w, h;
|
||||
void* data = nullptr;
|
||||
SP<CWLSurfaceResource> surface = nullptr;
|
||||
double w, h;
|
||||
|
||||
// for rounding
|
||||
bool dontRound = true;
|
||||
|
|
@ -52,12 +53,6 @@ struct SRenderData {
|
|||
bool popup = false;
|
||||
};
|
||||
|
||||
struct SExtensionFindingData {
|
||||
Vector2D origin;
|
||||
Vector2D vec;
|
||||
wlr_surface** found;
|
||||
};
|
||||
|
||||
struct SSwipeGesture {
|
||||
PHLWORKSPACE pWorkspaceBegin = nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ namespace CSharedPointer_ {
|
|||
bool _destroying = false;
|
||||
|
||||
void _destroy() {
|
||||
if (!_data)
|
||||
if (!_data || _destroying)
|
||||
return;
|
||||
|
||||
// first, we destroy the data, but keep the pointer.
|
||||
|
|
@ -297,6 +297,6 @@ static CSharedPointer<U> makeShared(Args&&... args) {
|
|||
template <typename T>
|
||||
struct std::hash<CSharedPointer<T>> {
|
||||
std::size_t operator()(const CSharedPointer<T>& p) const noexcept {
|
||||
return std::hash<void*>{}(p->impl_);
|
||||
return std::hash<void*>{}(p.impl_);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -185,6 +185,6 @@ class CWeakPointer {
|
|||
template <typename T>
|
||||
struct std::hash<CWeakPointer<T>> {
|
||||
std::size_t operator()(const CWeakPointer<T>& p) const noexcept {
|
||||
return std::hash<void*>{}(p->impl_);
|
||||
return std::hash<void*>{}(p.impl_);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,19 +2,40 @@
|
|||
#include <algorithm>
|
||||
|
||||
void CSignal::emit(std::any data) {
|
||||
bool dirty = false;
|
||||
bool dirty = false;
|
||||
|
||||
std::vector<SP<CSignalListener>> listeners;
|
||||
for (auto& l : m_vListeners) {
|
||||
if (const CHyprSignalListener L = l.lock())
|
||||
L->emit(data);
|
||||
else
|
||||
if (l.expired()) {
|
||||
dirty = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
listeners.emplace_back(l.lock());
|
||||
}
|
||||
|
||||
std::vector<CStaticSignalListener*> statics;
|
||||
for (auto& l : m_vStaticListeners) {
|
||||
statics.emplace_back(l.get());
|
||||
}
|
||||
|
||||
for (auto& l : listeners) {
|
||||
// if there is only one lock, it means the event is only held by the listeners
|
||||
// vector and was removed during our iteration
|
||||
if (l.strongRef() == 1) {
|
||||
dirty = true;
|
||||
continue;
|
||||
}
|
||||
l->emit(data);
|
||||
}
|
||||
|
||||
for (auto& l : statics) {
|
||||
l->emit(data);
|
||||
}
|
||||
|
||||
// release SPs
|
||||
listeners.clear();
|
||||
|
||||
if (dirty)
|
||||
std::erase_if(m_vListeners, [](const auto& other) { return other.expired(); });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue