mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-15 12:03:48 -07:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
29e2e59fdb | ||
|
1fdb5ba09e | ||
|
aa421c2e95 | ||
|
3c36e083f1 | ||
|
3fc0abcb56 | ||
|
273f43bda6 | ||
|
0a3948107a | ||
|
189e18394e | ||
|
3eb859bb4e | ||
|
eaa9663057 | ||
|
5da8281d68 | ||
|
d2031ba3e0 | ||
|
c22f46768c | ||
|
66470020a7 | ||
|
ed2f50d5ad |
@@ -2627,7 +2627,13 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO
|
||||
|
||||
const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2;
|
||||
|
||||
const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, getMonitorFromID(monID), NAME, SPECIAL, isEmpty));
|
||||
const auto PMONITOR = getMonitorFromID(monID);
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "BUG THIS: No pMonitor for new workspace in createNewWorkspace");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, PMONITOR, NAME, SPECIAL, isEmpty));
|
||||
|
||||
PWORKSPACE->m_fAlpha->setValueAndWarp(0);
|
||||
|
||||
@@ -3061,6 +3067,8 @@ bool CCompositor::shouldChangePreferredImageDescription() {
|
||||
}
|
||||
|
||||
void CCompositor::ensurePersistentWorkspacesPresent(const std::vector<SWorkspaceRule>& rules, PHLWORKSPACE pWorkspace) {
|
||||
if (!m_pLastMonitor)
|
||||
return;
|
||||
|
||||
for (const auto& rule : rules) {
|
||||
if (!rule.isPersistent)
|
||||
@@ -3076,6 +3084,9 @@ void CCompositor::ensurePersistentWorkspacesPresent(const std::vector<SWorkspace
|
||||
|
||||
const auto PMONITOR = getMonitorFromString(rule.monitor);
|
||||
|
||||
if (!rule.monitor.empty() && !PMONITOR)
|
||||
continue; // don't do anything yet, as the monitor is not yet present.
|
||||
|
||||
if (!PWORKSPACE) {
|
||||
WORKSPACEID id = rule.workspaceId;
|
||||
std::string wsname = rule.workspaceName;
|
||||
@@ -3092,7 +3103,7 @@ void CCompositor::ensurePersistentWorkspacesPresent(const std::vector<SWorkspace
|
||||
}
|
||||
PWORKSPACE = getWorkspaceByID(id);
|
||||
if (!PWORKSPACE)
|
||||
createNewWorkspace(id, PMONITOR ? PMONITOR : m_pLastMonitor.lock(), wsname, false);
|
||||
createNewWorkspace(id, PMONITOR ? PMONITOR->ID : m_pLastMonitor->ID, wsname, false);
|
||||
}
|
||||
|
||||
if (PWORKSPACE)
|
||||
|
@@ -621,14 +621,10 @@ void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, timespec* no
|
||||
box.y = std::round(box.y);
|
||||
|
||||
CTexPassElement::SRenderData data;
|
||||
data.tex = texture;
|
||||
data.box = box.round();
|
||||
data.syncTimeline = currentCursorImage.waitTimeline;
|
||||
data.syncPoint = currentCursorImage.waitPoint;
|
||||
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||
data.tex = texture;
|
||||
data.box = box.round();
|
||||
|
||||
currentCursorImage.waitTimeline.reset();
|
||||
currentCursorImage.waitPoint = 0;
|
||||
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||
|
||||
if (currentCursorImage.surface)
|
||||
currentCursorImage.surface->resource()->frame(now);
|
||||
|
@@ -148,8 +148,6 @@ class CPointerManager {
|
||||
|
||||
CHyprSignalListener destroySurface;
|
||||
CHyprSignalListener commitSurface;
|
||||
SP<CSyncTimeline> waitTimeline = nullptr;
|
||||
uint64_t waitPoint = 0;
|
||||
} currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors
|
||||
|
||||
Vector2D pointerPos = {0, 0};
|
||||
|
@@ -75,20 +75,22 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(UP<CWpLinuxDrmSyncobjSurf
|
||||
});
|
||||
|
||||
listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) {
|
||||
if (!surface->pending.buffer && surface->pending.newBuffer && !surface->pending.texture) {
|
||||
const bool PENDING_HAS_NEW_BUFFER = surface->pending.updated & SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_BUFFER;
|
||||
|
||||
if (!surface->pending.buffer && PENDING_HAS_NEW_BUFFER && !surface->pending.texture) {
|
||||
removeAllWaiters();
|
||||
surface->commitPendingState(surface->pending);
|
||||
return; // null buffer attached.
|
||||
}
|
||||
|
||||
if (!surface->pending.buffer && !surface->pending.newBuffer && surface->current.buffer) {
|
||||
if (!surface->pending.buffer && !PENDING_HAS_NEW_BUFFER && surface->current.buffer) {
|
||||
surface->current.bufferDamage.clear();
|
||||
surface->current.damage.clear();
|
||||
surface->commitPendingState(surface->current);
|
||||
return; // no new buffer, but we still have current around and a commit happend, commit current again.
|
||||
}
|
||||
|
||||
if (!surface->pending.buffer && !surface->pending.newBuffer && !surface->current.buffer) {
|
||||
if (!surface->pending.buffer && !PENDING_HAS_NEW_BUFFER && !surface->current.buffer) {
|
||||
surface->commitPendingState(surface->pending); // no pending buffer, no current buffer. probably first commit
|
||||
return;
|
||||
}
|
||||
@@ -109,7 +111,8 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(UP<CWpLinuxDrmSyncobjSurf
|
||||
const auto& state = pendingStates.emplace_back(makeShared<SSurfaceState>(surface->pending));
|
||||
surface->pending.damage.clear();
|
||||
surface->pending.bufferDamage.clear();
|
||||
surface->pending.newBuffer = false;
|
||||
surface->pending.updated &= ~SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_BUFFER;
|
||||
surface->pending.updated &= ~SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
|
||||
surface->pending.buffer.reset();
|
||||
|
||||
state->buffer->buffer->syncReleaser = state->buffer->release->createSyncRelease();
|
||||
|
@@ -319,8 +319,11 @@ uint32_t CXDGToplevelResource::setSuspeneded(bool sus) {
|
||||
void CXDGToplevelResource::applyState() {
|
||||
wl_array arr;
|
||||
wl_array_init(&arr);
|
||||
wl_array_add(&arr, pendingApply.states.size() * sizeof(int));
|
||||
memcpy(arr.data, pendingApply.states.data(), pendingApply.states.size() * sizeof(int));
|
||||
|
||||
if (!pendingApply.states.empty()) {
|
||||
wl_array_add(&arr, pendingApply.states.size() * sizeof(int));
|
||||
memcpy(arr.data, pendingApply.states.data(), pendingApply.states.size() * sizeof(int));
|
||||
}
|
||||
|
||||
resource->sendConfigure(pendingApply.size.x, pendingApply.size.y, &arr);
|
||||
|
||||
|
@@ -71,12 +71,13 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
|
||||
resource->setOnDestroy([this](CWlSurface* r) { destroy(); });
|
||||
|
||||
resource->setAttach([this](CWlSurface* r, wl_resource* buffer, int32_t x, int32_t y) {
|
||||
pending.offset = {x, y};
|
||||
pending.newBuffer = true;
|
||||
pending.offset = {x, y};
|
||||
pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_BUFFER | SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_OFFSET;
|
||||
|
||||
if (!buffer) {
|
||||
pending.buffer.reset();
|
||||
pending.texture.reset();
|
||||
pending.bufferSize = Vector2D{};
|
||||
} else {
|
||||
auto res = CWLBufferResource::fromResource(buffer);
|
||||
pending.buffer = res && res->buffer ? makeShared<CHLBufferReference>(res->buffer.lock(), self.lock()) : nullptr;
|
||||
@@ -85,10 +86,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
|
||||
pending.bufferSize = res && res->buffer ? res->buffer->size : Vector2D{};
|
||||
}
|
||||
|
||||
Vector2D oldBufSize = current.buffer ? current.bufferSize : Vector2D{};
|
||||
Vector2D newBufSize = pending.buffer ? pending.bufferSize : Vector2D{};
|
||||
|
||||
if (oldBufSize != newBufSize || current.buffer != pending.buffer)
|
||||
if (pending.bufferSize != current.bufferSize)
|
||||
pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
|
||||
});
|
||||
|
||||
@@ -119,11 +117,29 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
|
||||
commitPendingState(pending);
|
||||
});
|
||||
|
||||
resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.damage.add(CBox{x, y, w, h}); });
|
||||
resource->setDamageBuffer([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.bufferDamage.add(CBox{x, y, w, h}); });
|
||||
resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) {
|
||||
pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
|
||||
pending.damage.add(CBox{x, y, w, h});
|
||||
});
|
||||
resource->setDamageBuffer([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) {
|
||||
pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
|
||||
pending.bufferDamage.add(CBox{x, y, w, h});
|
||||
});
|
||||
|
||||
resource->setSetBufferScale([this](CWlSurface* r, int32_t scale) { pending.scale = scale; });
|
||||
resource->setSetBufferTransform([this](CWlSurface* r, uint32_t tr) { pending.transform = (wl_output_transform)tr; });
|
||||
resource->setSetBufferScale([this](CWlSurface* r, int32_t scale) {
|
||||
if (scale == pending.scale)
|
||||
return;
|
||||
pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_SCALE | SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
|
||||
pending.scale = scale;
|
||||
pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
|
||||
});
|
||||
resource->setSetBufferTransform([this](CWlSurface* r, uint32_t tr) {
|
||||
if (tr == pending.transform)
|
||||
return;
|
||||
pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_TRANSFORM | SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_DAMAGE;
|
||||
pending.transform = (wl_output_transform)tr;
|
||||
pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}};
|
||||
});
|
||||
|
||||
resource->setSetInputRegion([this](CWlSurface* r, wl_resource* region) {
|
||||
if (!region) {
|
||||
@@ -131,6 +147,8 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
|
||||
return;
|
||||
}
|
||||
|
||||
pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_INPUT;
|
||||
|
||||
auto RG = CWLRegionResource::fromResource(region);
|
||||
pending.input = RG->region;
|
||||
});
|
||||
@@ -141,13 +159,18 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
|
||||
return;
|
||||
}
|
||||
|
||||
pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_OPAQUE;
|
||||
|
||||
auto RG = CWLRegionResource::fromResource(region);
|
||||
pending.opaque = RG->region;
|
||||
});
|
||||
|
||||
resource->setFrame([this](CWlSurface* r, uint32_t id) { callbacks.emplace_back(makeShared<CWLCallbackResource>(makeShared<CWlCallback>(pClient, 1, id))); });
|
||||
|
||||
resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) { pending.offset = {x, y}; });
|
||||
resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) {
|
||||
pending.updated |= SSurfaceState::eUpdatedProperties::SURFACE_UPDATED_OFFSET;
|
||||
pending.offset = {x, y};
|
||||
});
|
||||
}
|
||||
|
||||
CWLSurfaceResource::~CWLSurfaceResource() {
|
||||
@@ -403,13 +426,8 @@ CBox CWLSurfaceResource::extends() {
|
||||
|
||||
void CWLSurfaceResource::commitPendingState(SSurfaceState& state) {
|
||||
auto lastTexture = current.texture;
|
||||
if (state.newBuffer) {
|
||||
state.newBuffer = false;
|
||||
current = state;
|
||||
state.damage.clear();
|
||||
state.bufferDamage.clear();
|
||||
state.buffer.reset();
|
||||
}
|
||||
current.updateFrom(state);
|
||||
state.updated = 0;
|
||||
|
||||
if (current.buffer) {
|
||||
if (current.buffer->buffer->isSynchronous())
|
||||
|
@@ -22,7 +22,7 @@ bool CWLTouchResource::good() {
|
||||
}
|
||||
|
||||
void CWLTouchResource::sendDown(SP<CWLSurfaceResource> surface, uint32_t timeMs, int32_t id, const Vector2D& local) {
|
||||
if (!owner)
|
||||
if (!owner || !surface || !surface->getResource()->resource())
|
||||
return;
|
||||
|
||||
if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_TOUCH))
|
||||
@@ -145,7 +145,7 @@ bool CWLPointerResource::good() {
|
||||
}
|
||||
|
||||
void CWLPointerResource::sendEnter(SP<CWLSurfaceResource> surface, const Vector2D& local) {
|
||||
if (!owner || currentSurface == surface)
|
||||
if (!owner || currentSurface == surface || !surface->getResource()->resource())
|
||||
return;
|
||||
|
||||
if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER))
|
||||
@@ -165,7 +165,7 @@ void CWLPointerResource::sendEnter(SP<CWLSurfaceResource> surface, const Vector2
|
||||
}
|
||||
|
||||
void CWLPointerResource::sendLeave() {
|
||||
if (!owner || !currentSurface)
|
||||
if (!owner || !currentSurface || !currentSurface->getResource()->resource())
|
||||
return;
|
||||
|
||||
if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_POINTER))
|
||||
@@ -336,7 +336,7 @@ void CWLKeyboardResource::sendKeymap(SP<IKeyboard> keyboard) {
|
||||
}
|
||||
|
||||
void CWLKeyboardResource::sendEnter(SP<CWLSurfaceResource> surface) {
|
||||
if (!owner || currentSurface == surface)
|
||||
if (!owner || currentSurface == surface || !surface->getResource()->resource())
|
||||
return;
|
||||
|
||||
if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD))
|
||||
@@ -361,7 +361,7 @@ void CWLKeyboardResource::sendEnter(SP<CWLSurfaceResource> surface) {
|
||||
}
|
||||
|
||||
void CWLKeyboardResource::sendLeave() {
|
||||
if (!owner || !currentSurface)
|
||||
if (!owner || !currentSurface || !currentSurface->getResource()->resource())
|
||||
return;
|
||||
|
||||
if (!(PROTO::seat->currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD))
|
||||
|
@@ -56,3 +56,38 @@ void SSurfaceState::reset() {
|
||||
offset = {};
|
||||
size = {};
|
||||
}
|
||||
|
||||
void SSurfaceState::updateFrom(SSurfaceState& ref) {
|
||||
updated = ref.updated;
|
||||
|
||||
if (ref.updated & SURFACE_UPDATED_BUFFER) {
|
||||
ref.updated &= ~SURFACE_UPDATED_BUFFER;
|
||||
*this = ref;
|
||||
ref.damage.clear();
|
||||
ref.bufferDamage.clear();
|
||||
ref.buffer.reset();
|
||||
} else {
|
||||
if (ref.updated & SURFACE_UPDATED_DAMAGE) {
|
||||
damage = ref.damage;
|
||||
bufferDamage = ref.bufferDamage;
|
||||
}
|
||||
|
||||
if (ref.updated & SURFACE_UPDATED_INPUT)
|
||||
input = ref.input;
|
||||
|
||||
if (ref.updated & SURFACE_UPDATED_OPAQUE)
|
||||
opaque = ref.opaque;
|
||||
|
||||
if (ref.updated & SURFACE_UPDATED_OFFSET)
|
||||
offset = ref.offset;
|
||||
|
||||
if (ref.updated & SURFACE_UPDATED_SCALE)
|
||||
scale = ref.scale;
|
||||
|
||||
if (ref.updated & SURFACE_UPDATED_VIEWPORT)
|
||||
viewport = ref.viewport;
|
||||
|
||||
if (ref.updated & SURFACE_UPDATED_TRANSFORM)
|
||||
transform = ref.transform;
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,17 @@ class CHLBufferReference;
|
||||
class CTexture;
|
||||
|
||||
struct SSurfaceState {
|
||||
enum eUpdatedProperties : uint8_t {
|
||||
SURFACE_UPDATED_OPAQUE = 1 << 0,
|
||||
SURFACE_UPDATED_INPUT = 1 << 1,
|
||||
SURFACE_UPDATED_DAMAGE = 1 << 2,
|
||||
SURFACE_UPDATED_SCALE = 1 << 3,
|
||||
SURFACE_UPDATED_BUFFER = 1 << 4,
|
||||
SURFACE_UPDATED_OFFSET = 1 << 5,
|
||||
SURFACE_UPDATED_VIEWPORT = 1 << 6,
|
||||
SURFACE_UPDATED_TRANSFORM = 1 << 7,
|
||||
};
|
||||
|
||||
CRegion opaque, input = CBox{{}, {INT32_MAX, INT32_MAX}}, damage, bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}} /* initial damage */;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
int scale = 1;
|
||||
@@ -20,12 +31,15 @@ struct SSurfaceState {
|
||||
Vector2D destination;
|
||||
CBox source;
|
||||
} viewport;
|
||||
bool rejected = false;
|
||||
bool newBuffer = false;
|
||||
bool rejected = false;
|
||||
uint8_t updated = 0; // eUpdatedProperties. Stores what the last update changed
|
||||
|
||||
Vector2D sourceSize();
|
||||
// Translates damage into bufferDamage, clearing damage and returning the updated bufferDamage
|
||||
CRegion accumulateBufferDamage();
|
||||
void updateSynchronousTexture(SP<CTexture> lastTexture);
|
||||
void reset();
|
||||
// updates this state from a reference state. Mutates the reference state. If a new buffer is committed,
|
||||
// reference state gets its damage and buffer cleared.
|
||||
void updateFrom(SSurfaceState& ref);
|
||||
};
|
||||
|
@@ -158,6 +158,7 @@ void CHyprOpenGLImpl::initEGL(bool gbm) {
|
||||
#else
|
||||
attrs.push_back(EGL_CONTEXT_CLIENT_VERSION);
|
||||
attrs.push_back(2);
|
||||
m_eglContextVersion = EGL_CONTEXT_GLES_2_0;
|
||||
#endif
|
||||
|
||||
attrs.push_back(EGL_NONE);
|
||||
@@ -176,7 +177,8 @@ void CHyprOpenGLImpl::initEGL(bool gbm) {
|
||||
attrs.push_back(0);
|
||||
attrs.push_back(EGL_NONE);
|
||||
|
||||
m_pEglContext = eglCreateContext(m_pEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data());
|
||||
m_pEglContext = eglCreateContext(m_pEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data());
|
||||
m_eglContextVersion = EGL_CONTEXT_GLES_3_0;
|
||||
|
||||
if (m_pEglContext == EGL_NO_CONTEXT)
|
||||
RASSERT(false, "EGL: failed to create a context with either GLES3.2 or 3.0");
|
||||
@@ -564,7 +566,7 @@ EGLImageKHR CHyprOpenGLImpl::createEGLImage(const Aquamarine::SDMABUFAttrs& attr
|
||||
return image;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program) {
|
||||
void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program, bool silent) {
|
||||
GLint maxLength = 0;
|
||||
if (program)
|
||||
glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
|
||||
@@ -582,18 +584,19 @@ void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program) {
|
||||
|
||||
Debug::log(ERR, "Failed to link shader: {}", FULLERROR);
|
||||
|
||||
g_pConfigManager->addParseError(FULLERROR);
|
||||
if (!silent)
|
||||
g_pConfigManager->addParseError(FULLERROR);
|
||||
}
|
||||
|
||||
GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag, bool dynamic) {
|
||||
auto vertCompiled = compileShader(GL_VERTEX_SHADER, vert, dynamic);
|
||||
GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string& frag, bool dynamic, bool silent) {
|
||||
auto vertCompiled = compileShader(GL_VERTEX_SHADER, vert, dynamic, silent);
|
||||
if (dynamic) {
|
||||
if (vertCompiled == 0)
|
||||
return 0;
|
||||
} else
|
||||
RASSERT(vertCompiled, "Compiling shader failed. VERTEX nullptr! Shader source:\n\n{}", vert);
|
||||
|
||||
auto fragCompiled = compileShader(GL_FRAGMENT_SHADER, frag, dynamic);
|
||||
auto fragCompiled = compileShader(GL_FRAGMENT_SHADER, frag, dynamic, silent);
|
||||
if (dynamic) {
|
||||
if (fragCompiled == 0)
|
||||
return 0;
|
||||
@@ -614,7 +617,7 @@ GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &ok);
|
||||
if (dynamic) {
|
||||
if (ok == GL_FALSE) {
|
||||
logShaderError(prog, true);
|
||||
logShaderError(prog, true, silent);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@@ -626,7 +629,7 @@ GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string
|
||||
return prog;
|
||||
}
|
||||
|
||||
GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool dynamic) {
|
||||
GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool dynamic, bool silent) {
|
||||
auto shader = glCreateShader(type);
|
||||
|
||||
auto shaderSource = src.c_str();
|
||||
@@ -639,7 +642,7 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool
|
||||
|
||||
if (dynamic) {
|
||||
if (ok == GL_FALSE) {
|
||||
logShaderError(shader, false);
|
||||
logShaderError(shader, false, silent);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@@ -868,41 +871,43 @@ void CHyprOpenGLImpl::initShaders() {
|
||||
m_RenderData.pCurrentMonData->m_shQUAD.roundingPower = glGetUniformLocation(prog, "roundingPower");
|
||||
|
||||
#ifndef GLES2
|
||||
prog = createProgram(TEXVERTSRC320, TEXFRAGSRCCM, true);
|
||||
m_bCMSupported = prog > 0;
|
||||
if (m_bCMSupported) {
|
||||
m_RenderData.pCurrentMonData->m_shCM.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shCM.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shCM.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shCM.texType = glGetUniformLocation(prog, "texType");
|
||||
m_RenderData.pCurrentMonData->m_shCM.sourceTF = glGetUniformLocation(prog, "sourceTF");
|
||||
m_RenderData.pCurrentMonData->m_shCM.targetTF = glGetUniformLocation(prog, "targetTF");
|
||||
m_RenderData.pCurrentMonData->m_shCM.sourcePrimaries = glGetUniformLocation(prog, "sourcePrimaries");
|
||||
m_RenderData.pCurrentMonData->m_shCM.targetPrimaries = glGetUniformLocation(prog, "targetPrimaries");
|
||||
m_RenderData.pCurrentMonData->m_shCM.maxLuminance = glGetUniformLocation(prog, "maxLuminance");
|
||||
m_RenderData.pCurrentMonData->m_shCM.dstMaxLuminance = glGetUniformLocation(prog, "dstMaxLuminance");
|
||||
m_RenderData.pCurrentMonData->m_shCM.dstRefLuminance = glGetUniformLocation(prog, "dstRefLuminance");
|
||||
m_RenderData.pCurrentMonData->m_shCM.sdrSaturation = glGetUniformLocation(prog, "sdrSaturation");
|
||||
m_RenderData.pCurrentMonData->m_shCM.sdrBrightness = glGetUniformLocation(prog, "sdrBrightnessMultiplier");
|
||||
m_RenderData.pCurrentMonData->m_shCM.alphaMatte = glGetUniformLocation(prog, "texMatte");
|
||||
m_RenderData.pCurrentMonData->m_shCM.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shCM.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shCM.matteTexAttrib = glGetAttribLocation(prog, "texcoordMatte");
|
||||
m_RenderData.pCurrentMonData->m_shCM.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shCM.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
m_RenderData.pCurrentMonData->m_shCM.discardAlpha = glGetUniformLocation(prog, "discardAlpha");
|
||||
m_RenderData.pCurrentMonData->m_shCM.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue");
|
||||
m_RenderData.pCurrentMonData->m_shCM.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shCM.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shCM.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shCM.roundingPower = glGetUniformLocation(prog, "roundingPower");
|
||||
m_RenderData.pCurrentMonData->m_shCM.applyTint = glGetUniformLocation(prog, "applyTint");
|
||||
m_RenderData.pCurrentMonData->m_shCM.tint = glGetUniformLocation(prog, "tint");
|
||||
m_RenderData.pCurrentMonData->m_shCM.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
|
||||
} else {
|
||||
Debug::log(
|
||||
ERR,
|
||||
"WARNING: CM Shader failed compiling, color management will not work. It's likely because your GPU is an old piece of garbage, don't file bug reports about this!");
|
||||
if (m_eglContextVersion == EGL_CONTEXT_GLES_3_2 /* GLES2 and GLES3.0 can't compile the CM shader */) {
|
||||
prog = createProgram(TEXVERTSRC320, TEXFRAGSRCCM, true, true);
|
||||
m_bCMSupported = prog > 0;
|
||||
if (m_bCMSupported) {
|
||||
m_RenderData.pCurrentMonData->m_shCM.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shCM.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shCM.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shCM.texType = glGetUniformLocation(prog, "texType");
|
||||
m_RenderData.pCurrentMonData->m_shCM.sourceTF = glGetUniformLocation(prog, "sourceTF");
|
||||
m_RenderData.pCurrentMonData->m_shCM.targetTF = glGetUniformLocation(prog, "targetTF");
|
||||
m_RenderData.pCurrentMonData->m_shCM.sourcePrimaries = glGetUniformLocation(prog, "sourcePrimaries");
|
||||
m_RenderData.pCurrentMonData->m_shCM.targetPrimaries = glGetUniformLocation(prog, "targetPrimaries");
|
||||
m_RenderData.pCurrentMonData->m_shCM.maxLuminance = glGetUniformLocation(prog, "maxLuminance");
|
||||
m_RenderData.pCurrentMonData->m_shCM.dstMaxLuminance = glGetUniformLocation(prog, "dstMaxLuminance");
|
||||
m_RenderData.pCurrentMonData->m_shCM.dstRefLuminance = glGetUniformLocation(prog, "dstRefLuminance");
|
||||
m_RenderData.pCurrentMonData->m_shCM.sdrSaturation = glGetUniformLocation(prog, "sdrSaturation");
|
||||
m_RenderData.pCurrentMonData->m_shCM.sdrBrightness = glGetUniformLocation(prog, "sdrBrightnessMultiplier");
|
||||
m_RenderData.pCurrentMonData->m_shCM.alphaMatte = glGetUniformLocation(prog, "texMatte");
|
||||
m_RenderData.pCurrentMonData->m_shCM.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shCM.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shCM.matteTexAttrib = glGetAttribLocation(prog, "texcoordMatte");
|
||||
m_RenderData.pCurrentMonData->m_shCM.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shCM.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
m_RenderData.pCurrentMonData->m_shCM.discardAlpha = glGetUniformLocation(prog, "discardAlpha");
|
||||
m_RenderData.pCurrentMonData->m_shCM.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue");
|
||||
m_RenderData.pCurrentMonData->m_shCM.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shCM.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shCM.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shCM.roundingPower = glGetUniformLocation(prog, "roundingPower");
|
||||
m_RenderData.pCurrentMonData->m_shCM.applyTint = glGetUniformLocation(prog, "applyTint");
|
||||
m_RenderData.pCurrentMonData->m_shCM.tint = glGetUniformLocation(prog, "tint");
|
||||
m_RenderData.pCurrentMonData->m_shCM.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
|
||||
} else {
|
||||
Debug::log(
|
||||
ERR,
|
||||
"WARNING: CM Shader failed compiling, color management will not work. It's likely because your GPU is an old piece of garbage, don't file bug reports about this!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1382,9 +1387,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, const CB
|
||||
const auto imageDescription =
|
||||
m_RenderData.surface.valid() && m_RenderData.surface->colorManagement.valid() ? m_RenderData.surface->colorManagement->imageDescription() : SImageDescription{};
|
||||
|
||||
const bool skipCM = !*PENABLECM /* CM disabled by the user */
|
||||
|| !m_RenderData.surface /* No surface - no point in CM */
|
||||
|| !m_bCMSupported /* CM unsupported - hw failed to compile the shader probably */
|
||||
const bool skipCM = !*PENABLECM /* CM disabled by the user */
|
||||
|| !m_RenderData.surface /* FIXME unknown texture settings should be treated as sRGB and go through CM if monitor isn't in sRGB mode */
|
||||
|| !m_bCMSupported /* CM unsupported - hw failed to compile the shader probably */
|
||||
|| (imageDescription == m_RenderData.pMonitor->imageDescription) /* Source and target have the same image description */
|
||||
|| ((*PPASS == 1 || (*PPASS == 2 && imageDescription.transferFunction == CM_TRANSFER_FUNCTION_ST2084_PQ)) && m_RenderData.pMonitor->activeWorkspace &&
|
||||
m_RenderData.pMonitor->activeWorkspace->m_bHasFullscreenWindow &&
|
||||
@@ -3016,7 +3021,7 @@ CEGLSync::~CEGLSync() {
|
||||
if (sync == EGL_NO_SYNC_KHR)
|
||||
return;
|
||||
|
||||
if (g_pHyprOpenGL->m_sProc.eglDestroySyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync) != EGL_TRUE)
|
||||
if (g_pHyprOpenGL && g_pHyprOpenGL->m_sProc.eglDestroySyncKHR(g_pHyprOpenGL->m_pEglDisplay, sync) != EGL_TRUE)
|
||||
Debug::log(ERR, "eglDestroySyncKHR failed");
|
||||
}
|
||||
|
||||
|
@@ -276,6 +276,14 @@ class CHyprOpenGLImpl {
|
||||
} m_sExts;
|
||||
|
||||
private:
|
||||
enum eEGLContextVersion : uint8_t {
|
||||
EGL_CONTEXT_GLES_2_0 = 0,
|
||||
EGL_CONTEXT_GLES_3_0,
|
||||
EGL_CONTEXT_GLES_3_2,
|
||||
};
|
||||
|
||||
eEGLContextVersion m_eglContextVersion = EGL_CONTEXT_GLES_3_2;
|
||||
|
||||
std::list<GLuint> m_lBuffers;
|
||||
std::list<GLuint> m_lTextures;
|
||||
|
||||
@@ -297,9 +305,9 @@ class CHyprOpenGLImpl {
|
||||
|
||||
SP<CTexture> m_pMissingAssetTexture, m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture; // TODO: don't always load lock
|
||||
|
||||
void logShaderError(const GLuint&, bool program = false);
|
||||
GLuint createProgram(const std::string&, const std::string&, bool dynamic = false);
|
||||
GLuint compileShader(const GLuint&, std::string, bool dynamic = false);
|
||||
void logShaderError(const GLuint&, bool program = false, bool silent = false);
|
||||
GLuint createProgram(const std::string&, const std::string&, bool dynamic = false, bool silent = false);
|
||||
GLuint compileShader(const GLuint&, std::string, bool dynamic = false, bool silent = false);
|
||||
void createBGTextureForMonitor(PHLMONITOR);
|
||||
void initShaders();
|
||||
void initDRMFormats();
|
||||
|
@@ -1411,11 +1411,16 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) {
|
||||
static const hdr_output_metadata NO_HDR_METADATA = {.hdmi_metadata_type1 = hdr_metadata_infoframe{.eotf = 0}};
|
||||
|
||||
static hdr_output_metadata createHDRMetadata(SImageDescription settings, Aquamarine::IOutput::SParsedEDID edid) {
|
||||
if (settings.transferFunction != CM_TRANSFER_FUNCTION_ST2084_PQ)
|
||||
return NO_HDR_METADATA; // empty metadata for SDR
|
||||
uint8_t eotf = 0;
|
||||
switch (settings.transferFunction) {
|
||||
case CM_TRANSFER_FUNCTION_SRGB: eotf = 0; break; // used to send primaries and luminances to AQ. ignored for now
|
||||
case CM_TRANSFER_FUNCTION_ST2084_PQ: eotf = 2; break;
|
||||
// case CM_TRANSFER_FUNCTION_HLG: eotf = 3; break; TODO check display capabilities first
|
||||
default: return NO_HDR_METADATA; // empty metadata for SDR
|
||||
}
|
||||
|
||||
const auto toNits = [](uint32_t value) { return uint16_t(std::round(value)); };
|
||||
const auto to16Bit = [](uint32_t value) { return uint16_t(std::round(value * 50000)); };
|
||||
const auto to16Bit = [](float value) { return uint16_t(std::round(value * 50000)); };
|
||||
|
||||
auto colorimetry = settings.primariesNameSet || settings.primaries == SPCPRimaries{} ? getPrimaries(settings.primariesNamed) : settings.primaries;
|
||||
auto luminances = settings.masteringLuminances.max > 0 ?
|
||||
@@ -1429,7 +1434,7 @@ static hdr_output_metadata createHDRMetadata(SImageDescription settings, A
|
||||
.metadata_type = 0,
|
||||
.hdmi_metadata_type1 =
|
||||
hdr_metadata_infoframe{
|
||||
.eotf = 2,
|
||||
.eotf = eotf,
|
||||
.metadata_type = 0,
|
||||
.display_primaries =
|
||||
{
|
||||
@@ -1454,25 +1459,42 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
|
||||
Debug::log(TRACE, "ColorManagement supportsBT2020 {}, supportsPQ {}", pMonitor->output->parsedEDID.supportsBT2020, SUPPORTSPQ);
|
||||
|
||||
if (pMonitor->output->parsedEDID.supportsBT2020 && SUPPORTSPQ) {
|
||||
// HDR metadata determined by
|
||||
// PPASS = 0 monitor settings
|
||||
// PPASS = 1
|
||||
// windowed: monitor settings
|
||||
// fullscreen surface: surface settings FIXME: fullscreen SDR surface passthrough - pass degamma, ctm, gamma if needed
|
||||
// PPASS = 2
|
||||
// windowed: monitor settings
|
||||
// fullscreen SDR surface: monitor settings
|
||||
// fullscreen HDR surface: surface settings
|
||||
|
||||
bool wantHDR = PHDR;
|
||||
bool hdrIsHandled = false;
|
||||
if (*PPASS && pMonitor->activeWorkspace && pMonitor->activeWorkspace->m_bHasFullscreenWindow && pMonitor->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
|
||||
const auto WINDOW = pMonitor->activeWorkspace->getFullscreenWindow();
|
||||
const auto ROOT_SURF = WINDOW->m_pWLSurface->resource();
|
||||
const auto SURF =
|
||||
ROOT_SURF->findFirstPreorder([ROOT_SURF](SP<CWLSurfaceResource> surf) { return surf->colorManagement.valid() && surf->extends() == ROOT_SURF->extends(); });
|
||||
|
||||
const bool wantHDR = PHDR && *PPASS == 2;
|
||||
if (SURF && SURF->colorManagement.valid() && SURF->colorManagement->hasImageDescription()) {
|
||||
wantHDR = PHDR && *PPASS == 2;
|
||||
|
||||
// we have a surface with image description and it's allowed by wantHDR
|
||||
if (SURF && SURF->colorManagement.valid() && SURF->colorManagement->hasImageDescription() &&
|
||||
(!wantHDR || SURF->colorManagement->imageDescription().transferFunction == CM_TRANSFER_FUNCTION_ST2084_PQ)) {
|
||||
bool needsHdrMetadataUpdate = SURF->colorManagement->needsHdrMetadataUpdate() || pMonitor->m_previousFSWindow != WINDOW;
|
||||
if (SURF->colorManagement->needsHdrMetadataUpdate())
|
||||
SURF->colorManagement->setHDRMetadata(createHDRMetadata(SURF->colorManagement->imageDescription(), pMonitor->output->parsedEDID));
|
||||
if (needsHdrMetadataUpdate)
|
||||
pMonitor->output->state->setHDRMetadata(SURF->colorManagement->hdrMetadata());
|
||||
} else if ((pMonitor->output->state->state().hdrMetadata.hdmi_metadata_type1.eotf == 2) != wantHDR)
|
||||
pMonitor->output->state->setHDRMetadata(wantHDR ? createHDRMetadata(pMonitor->imageDescription, pMonitor->output->parsedEDID) : NO_HDR_METADATA);
|
||||
hdrIsHandled = true;
|
||||
}
|
||||
|
||||
pMonitor->m_previousFSWindow = WINDOW;
|
||||
} else {
|
||||
if ((pMonitor->output->state->state().hdrMetadata.hdmi_metadata_type1.eotf == 2) != PHDR)
|
||||
pMonitor->output->state->setHDRMetadata(PHDR ? createHDRMetadata(pMonitor->imageDescription, pMonitor->output->parsedEDID) : NO_HDR_METADATA);
|
||||
}
|
||||
if (!hdrIsHandled) {
|
||||
if ((pMonitor->output->state->state().hdrMetadata.hdmi_metadata_type1.eotf == 2) != wantHDR)
|
||||
pMonitor->output->state->setHDRMetadata(wantHDR ? createHDRMetadata(pMonitor->imageDescription, pMonitor->output->parsedEDID) : NO_HDR_METADATA);
|
||||
pMonitor->m_previousFSWindow.reset();
|
||||
}
|
||||
}
|
||||
|
@@ -142,7 +142,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||
ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - *PINDICATORHEIGHT - *POUTERGAP - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth,
|
||||
*PINDICATORHEIGHT};
|
||||
|
||||
rect.scale(pMonitor->scale);
|
||||
rect.scale(pMonitor->scale).round();
|
||||
|
||||
const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked || g_pKeybindManager->m_bGroupsLocked;
|
||||
const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE;
|
||||
@@ -278,7 +278,7 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float
|
||||
const CHyprColor COLOR = CHyprColor(*PTEXTCOLOR);
|
||||
const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT;
|
||||
|
||||
tex = g_pHyprOpenGL->renderText(pWindow->m_szTitle, COLOR, *PTITLEFONTSIZE, false, FONTFAMILY, bufferSize.x - 2 /* some padding yk */);
|
||||
tex = g_pHyprOpenGL->renderText(pWindow->m_szTitle, COLOR, *PTITLEFONTSIZE * monitorScale, false, FONTFAMILY, bufferSize.x - 2 /* some padding yk */);
|
||||
|
||||
if (tex)
|
||||
texSize = tex->m_vSize;
|
||||
@@ -573,5 +573,5 @@ CBox CHyprGroupBarDecoration::assignedBoxGlobal() {
|
||||
if (PWORKSPACE && !m_pWindow->m_bPinned)
|
||||
box.translate(PWORKSPACE->m_vRenderOffset->value());
|
||||
|
||||
return box;
|
||||
return box.round();
|
||||
}
|
||||
|
@@ -33,5 +33,13 @@ std::optional<CBox> CRectPassElement::boundingBox() {
|
||||
}
|
||||
|
||||
CRegion CRectPassElement::opaqueRegion() {
|
||||
return data.color.a >= 1.F ? boundingBox()->expand(-data.round) : CRegion{};
|
||||
if (data.color.a < 1.F)
|
||||
return CRegion{};
|
||||
|
||||
CRegion rg = boundingBox()->expand(-data.round);
|
||||
|
||||
if (!data.clipBox.empty())
|
||||
rg.intersect(data.clipBox);
|
||||
|
||||
return rg;
|
||||
}
|
||||
|
@@ -22,8 +22,7 @@ void CTexPassElement::draw(const CRegion& damage) {
|
||||
|
||||
if (data.replaceProjection)
|
||||
g_pHyprOpenGL->m_RenderData.monitorProjection = *data.replaceProjection;
|
||||
g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.roundingPower, data.syncTimeline,
|
||||
data.syncPoint);
|
||||
g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.roundingPower);
|
||||
if (data.replaceProjection)
|
||||
g_pHyprOpenGL->m_RenderData.monitorProjection = g_pHyprOpenGL->m_RenderData.pMonitor->projMatrix;
|
||||
}
|
||||
|
@@ -16,8 +16,6 @@ class CTexPassElement : public IPassElement {
|
||||
int round = 0;
|
||||
float roundingPower = 2.0f;
|
||||
bool flipEndFrame = false;
|
||||
SP<CSyncTimeline> syncTimeline;
|
||||
int64_t syncPoint = 0;
|
||||
std::optional<Mat3x3> replaceProjection;
|
||||
CBox clipBox;
|
||||
};
|
||||
|
@@ -177,8 +177,7 @@ static void startServer(void* data) {
|
||||
}
|
||||
|
||||
static int xwaylandReady(int fd, uint32_t mask, void* data) {
|
||||
CFileDescriptor xwlFd{fd};
|
||||
return g_pXWayland->pServer->ready(std::move(xwlFd), mask);
|
||||
return g_pXWayland->pServer->ready(fd, mask);
|
||||
}
|
||||
|
||||
static bool safeRemove(const std::string& path) {
|
||||
@@ -353,7 +352,7 @@ bool CXWaylandServer::start() {
|
||||
return false;
|
||||
}
|
||||
|
||||
waylandFDs[0].take(); // does this leak?
|
||||
waylandFDs[0].take(); // wl_client owns this fd now
|
||||
|
||||
int notify[2] = {-1, -1};
|
||||
if (pipe(notify) < 0) {
|
||||
@@ -373,30 +372,24 @@ bool CXWaylandServer::start() {
|
||||
pipeSource = wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, notifyFds[0].get(), WL_EVENT_READABLE, ::xwaylandReady, nullptr);
|
||||
pipeFd = std::move(notifyFds[0]);
|
||||
|
||||
serverPID = fork();
|
||||
auto serverPID = fork();
|
||||
if (serverPID < 0) {
|
||||
Debug::log(ERR, "fork failed");
|
||||
die();
|
||||
return false;
|
||||
} else if (serverPID == 0) {
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
Debug::log(ERR, "second fork failed");
|
||||
_exit(1);
|
||||
} else if (pid == 0)
|
||||
runXWayland(notifyFds[1]);
|
||||
|
||||
runXWayland(notifyFds[1]);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CXWaylandServer::ready(CFileDescriptor fd, uint32_t mask) {
|
||||
int CXWaylandServer::ready(int fd, uint32_t mask) {
|
||||
if (mask & WL_EVENT_READABLE) {
|
||||
// xwayland writes twice
|
||||
char buf[64];
|
||||
ssize_t n = read(fd.get(), buf, sizeof(buf));
|
||||
ssize_t n = read(fd, buf, sizeof(buf));
|
||||
if (n < 0 && errno != EINTR) {
|
||||
Debug::log(ERR, "Xwayland: read from displayFd failed");
|
||||
mask = 0;
|
||||
@@ -404,14 +397,6 @@ int CXWaylandServer::ready(CFileDescriptor fd, uint32_t mask) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (waitpid(serverPID, nullptr, 0) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
Debug::log(ERR, "Xwayland: waitpid for fork failed");
|
||||
g_pXWayland->pServer.reset();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// if we don't have readable here, it failed
|
||||
if (!(mask & WL_EVENT_READABLE)) {
|
||||
Debug::log(ERR, "Xwayland: startup failed, not setting up xwm");
|
||||
@@ -422,6 +407,7 @@ int CXWaylandServer::ready(CFileDescriptor fd, uint32_t mask) {
|
||||
Debug::log(LOG, "XWayland is ready");
|
||||
|
||||
wl_event_source_remove(pipeSource);
|
||||
pipeFd.reset();
|
||||
pipeSource = nullptr;
|
||||
|
||||
// start the wm
|
||||
|
@@ -20,7 +20,7 @@ class CXWaylandServer {
|
||||
bool start();
|
||||
|
||||
// called on ready
|
||||
int ready(Hyprutils::OS::CFileDescriptor fd, uint32_t mask);
|
||||
int ready(int fd, uint32_t mask);
|
||||
|
||||
void die();
|
||||
|
||||
@@ -34,8 +34,6 @@ class CXWaylandServer {
|
||||
bool tryOpenSockets();
|
||||
void runXWayland(Hyprutils::OS::CFileDescriptor& notifyFD);
|
||||
|
||||
pid_t serverPID = 0;
|
||||
|
||||
std::string displayName;
|
||||
int display = -1;
|
||||
std::array<Hyprutils::OS::CFileDescriptor, 2> xFDs;
|
||||
|
Reference in New Issue
Block a user