Skip to content

Commit f4982e1

Browse files
add CCExtSessionLockV1
1 parent e441f4e commit f4982e1

File tree

11 files changed

+279
-37
lines changed

11 files changed

+279
-37
lines changed

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ add_executable(controls "tests/Controls.cpp")
143143
target_link_libraries(controls PRIVATE PkgConfig::deps hyprtoolkit)
144144
add_dependencies(tests controls)
145145

146+
add_executable(simpleSessionLock "tests/SimpleSessionLock.cpp")
147+
target_link_libraries(simpleSessionLock PRIVATE PkgConfig::deps hyprtoolkit)
148+
add_dependencies(tests simpleSessionLock)
149+
150+
146151
# Installation
147152
install(TARGETS hyprtoolkit)
148153
install(DIRECTORY "include/hyprtoolkit" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

include/hyprtoolkit/core/Backend.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ namespace Hyprtoolkit {
3232
*/
3333
static Hyprutils::Memory::CSharedPointer<CBackend> create();
3434

35+
/*
36+
Attempt to initialize the platform.
37+
Optional. Can be used in case the outputAdded/Removed events are used to create new windows.
38+
In such a szenario the platform must be initialized before opening a window.
39+
*/
40+
static bool attempt();
41+
3542
/*
3643
Destroy the backend.
3744
Backend will be destroyed once:
@@ -73,9 +80,10 @@ namespace Hyprtoolkit {
7380

7481
Hyprutils::Memory::CSharedPointer<CPalette> getPalette();
7582

83+
void unlockSession();
84+
7685
struct {
7786
Hyprutils::Signal::CSignalT<uint32_t> outputAdded;
78-
Hyprutils::Signal::CSignalT<uint32_t> outputRemoved;
7987
} m_events;
8088

8189
HT_HIDDEN : CBackend();

src/core/Backend.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ SP<CBackend> CBackend::create() {
7171
return g_backend;
7272
};
7373

74+
bool CBackend::attempt() {
75+
g_waylandPlatform = makeUnique<CWaylandPlatform>();
76+
if (!g_waylandPlatform->attempt()) {
77+
g_waylandPlatform = nullptr;
78+
return false;
79+
}
80+
g_openGL = makeShared<COpenGLRenderer>(g_waylandPlatform->m_drmState.fd);
81+
g_renderer = g_openGL;
82+
return true;
83+
}
84+
7485
void CBackend::destroy() {
7586
terminate();
7687
}
@@ -83,14 +94,16 @@ SP<CPalette> CBackend::getPalette() {
8394
return g_palette;
8495
}
8596

97+
void CBackend::unlockSession() {
98+
if (!g_waylandPlatform)
99+
return;
100+
101+
g_waylandPlatform->unlockSessionLock();
102+
}
103+
86104
SP<IWindow> CBackend::openWindow(const SWindowCreationData& data) {
87-
if (!g_waylandPlatform) {
88-
g_waylandPlatform = makeUnique<CWaylandPlatform>();
89-
if (!g_waylandPlatform->attempt())
90-
return nullptr;
91-
g_openGL = makeShared<COpenGLRenderer>(g_waylandPlatform->m_drmState.fd);
92-
g_renderer = g_openGL;
93-
}
105+
if (!g_waylandPlatform && !attempt())
106+
return nullptr;
94107

95108
if (data.type == HT_WINDOW_LAYER) {
96109
if (!g_waylandPlatform->m_waylandState.layerShell)
@@ -101,6 +114,17 @@ SP<IWindow> CBackend::openWindow(const SWindowCreationData& data) {
101114
w->m_rootElement->impl->window = w;
102115
g_waylandPlatform->m_layers.emplace_back(w);
103116
return w;
117+
} else if (data.type == HT_WINDOW_LOCK_SURFACE) {
118+
if (!g_waylandPlatform->m_waylandState.sessionLock) {
119+
g_logger->log(HT_LOG_ERROR, "No session lock manager. Does your compositor support it?");
120+
return nullptr;
121+
}
122+
123+
auto w = makeShared<CWaylandLockSurface>(data);
124+
w->m_self = w;
125+
w->m_rootElement->impl->window = w;
126+
g_waylandPlatform->m_lockSurfaces.emplace_back(w);
127+
return w;
104128
}
105129

106130
auto w = makeShared<CWaylandWindow>(data);

src/core/platforms/WaylandPlatform.cpp

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
#include <algorithm>
44
#include <hyprutils/memory/Casts.hpp>
5+
#include <optional>
56
#include <xkbcommon/xkbcommon-keysyms.h>
67

78
#include "../InternalBackend.hpp"
89
#include "../Input.hpp"
910
#include "../../element/Element.hpp"
1011
#include "../../window/WaylandWindow.hpp"
1112
#include "../../window/WaylandLayer.hpp"
13+
#include "../../window/WaylandLockSurface.hpp"
1214
#include "../../output/WaylandOutput.hpp"
1315
#include "../../Macros.hpp"
1416

@@ -100,15 +102,23 @@ bool CWaylandPlatform::attempt() {
100102
// We just need to deferre it a bit so that the globals are defined before we emit the event.
101103
// But once they are defined, we probably don't want it to be a idle function.
102104
m_idleCallbacks.emplace_back([id]() { g_backend->m_events.outputAdded.emit(id); });
105+
} else if (NAME == ext_session_lock_manager_v1_interface.name) {
106+
TRACE(g_logger->log(HT_LOG_TRACE, " > binding to global: {} (version {}) with id {}", name, 1, id));
107+
m_waylandState.sessionLock = makeShared<CCExtSessionLockManagerV1>(
108+
(wl_proxy*)wl_registry_bind((wl_registry*)m_waylandState.registry->resource(), id, &ext_session_lock_manager_v1_interface, 1));
103109
}
104110
});
105111
m_waylandState.registry->setGlobalRemove([this](CCWlRegistry* r, uint32_t id) {
112+
TRACE(g_logger->log(HT_LOG_TRACE, "Global {} removed", id));
113+
114+
auto lockSurfaceIt = std::ranges::find_if(m_lockSurfaces, [id](const auto& other) { return other->m_outputId == id; });
115+
if (lockSurfaceIt != m_lockSurfaces.end()) {
116+
(*lockSurfaceIt)->m_events.closeRequest.emit();
117+
m_lockSurfaces.erase(lockSurfaceIt);
118+
}
106119
auto outputIt = std::ranges::find_if(m_outputs, [id](const auto& other) { return other->m_id == id; });
107120
if (outputIt != m_outputs.end())
108121
m_outputs.erase(outputIt);
109-
110-
g_logger->log(HT_LOG_DEBUG, "Global {} removed", id);
111-
g_backend->m_events.outputRemoved.emit(id);
112122
});
113123

114124
wl_display_roundtrip(m_waylandState.display);
@@ -127,9 +137,7 @@ bool CWaylandPlatform::attempt() {
127137
}
128138

129139
CWaylandPlatform::~CWaylandPlatform() {
130-
const auto DPY = m_waylandState.display;
131-
m_waylandState = {};
132-
wl_display_disconnect(DPY);
140+
m_outputs.clear();
133141

134142
if (m_drmState.fd >= 0)
135143
close(m_drmState.fd);
@@ -140,6 +148,10 @@ CWaylandPlatform::~CWaylandPlatform() {
140148
xkb_keymap_unref(m_waylandState.seatState.xkbKeymap);
141149
if (m_waylandState.seatState.xkbContext)
142150
xkb_context_unref(m_waylandState.seatState.xkbContext);
151+
152+
const auto DPY = m_waylandState.display;
153+
m_waylandState = {};
154+
wl_display_disconnect(DPY);
143155
}
144156

145157
bool CWaylandPlatform::dispatchEvents() {
@@ -618,3 +630,50 @@ void CWaylandPlatform::stopRepeatTimer() {
618630
m_waylandState.seatState.repeatTimer->cancel();
619631
m_waylandState.seatState.repeatTimer.reset();
620632
}
633+
634+
SP<CCExtSessionLockV1> CWaylandPlatform::aquireSessionLock() {
635+
if (m_waylandState.sessionLockState.sessionLocked && m_waylandState.sessionLockState.sessionUnlocked) {
636+
g_logger->log(HT_LOG_ERROR, "We already unlocked. We shouldn't be calling aquireSessionLock?");
637+
return nullptr;
638+
}
639+
640+
if (!m_waylandState.sessionLockState.lock) {
641+
m_waylandState.sessionLockState.lock = makeShared<CCExtSessionLockV1>(m_waylandState.sessionLock->sendLock());
642+
if (!m_waylandState.sessionLockState.lock) {
643+
g_logger->log(HT_LOG_ERROR, "Failed to create a session lock object!");
644+
return nullptr;
645+
}
646+
647+
m_waylandState.sessionLockState.lock->setLocked([this](CCExtSessionLockV1* r) { m_waylandState.sessionLockState.sessionLocked = true; });
648+
649+
m_waylandState.sessionLockState.lock->setFinished([](CCExtSessionLockV1* r) { //FIXME: we need to make sure the client can exit after this event
650+
});
651+
652+
// roundtrip in case the compositor sends `finished` right away
653+
wl_display_roundtrip(m_waylandState.display);
654+
655+
// FIXME: we need to test if finished was sent right here too!
656+
}
657+
658+
return m_waylandState.sessionLockState.lock;
659+
}
660+
661+
void CWaylandPlatform::unlockSessionLock() {
662+
if (!m_waylandState.sessionLockState.lock)
663+
return;
664+
665+
m_waylandState.sessionLockState.lock->sendUnlockAndDestroy();
666+
m_waylandState.sessionLockState.lock = nullptr;
667+
m_waylandState.sessionLockState.sessionUnlocked = true;
668+
669+
// roundtrip in order to make sure we have unlocked before sending closeRequest
670+
wl_display_roundtrip(m_waylandState.display);
671+
672+
for (const auto& sls : m_lockSurfaces) {
673+
if (sls.expired())
674+
continue;
675+
sls->m_events.closeRequest.emit();
676+
}
677+
678+
m_lockSurfaces.clear();
679+
}

src/core/platforms/WaylandPlatform.hpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <cursor-shape-v1.hpp>
2323
#include <text-input-unstable-v3.hpp>
2424
#include <wlr-layer-shell-unstable-v1.hpp>
25+
#include <ext-session-lock-v1.hpp>
2526

2627
#include <aquamarine/allocator/GBM.hpp>
2728
#include <aquamarine/backend/Misc.hpp>
@@ -33,6 +34,7 @@ namespace Hyprtoolkit {
3334
class IWaylandWindow;
3435
class CWaylandLayer;
3536
class CWaylandOutput;
37+
class CWaylandLockSurface;
3638

3739
class CWaylandPlatform {
3840
public:
@@ -58,6 +60,9 @@ namespace Hyprtoolkit {
5860

5961
void onRepeatTimerFire();
6062

63+
SP<CCExtSessionLockV1> aquireSessionLock();
64+
void unlockSessionLock();
65+
6166
//
6267
std::vector<FIdleCallback> m_idleCallbacks;
6368

@@ -86,6 +91,7 @@ namespace Hyprtoolkit {
8691
Hyprutils::Memory::CSharedPointer<CCZwpTextInputManagerV3> textInputManager;
8792
Hyprutils::Memory::CSharedPointer<CCZwpTextInputV3> textInput;
8893
Hyprutils::Memory::CSharedPointer<CCZwlrLayerShellV1> layerShell;
94+
Hyprutils::Memory::CSharedPointer<CCExtSessionLockManagerV1> sessionLock;
8995

9096
// control
9197
bool dmabufFailed = false;
@@ -111,20 +117,27 @@ namespace Hyprtoolkit {
111117

112118
std::string originalString;
113119
} imState;
120+
121+
struct {
122+
SP<CCExtSessionLockV1> lock = nullptr;
123+
bool sessionLocked = false;
124+
bool sessionUnlocked = false;
125+
} sessionLockState;
114126
} m_waylandState;
115127

116128
struct {
117129
int fd = -1;
118130
std::string nodeName = "";
119131
} m_drmState;
120132

121-
std::vector<UP<CWaylandOutput>> m_outputs;
133+
std::vector<UP<CWaylandOutput>> m_outputs;
122134

123-
std::vector<WP<CWaylandWindow>> m_windows;
124-
std::vector<WP<CWaylandLayer>> m_layers;
125-
WP<IWaylandWindow> m_currentWindow;
126-
uint32_t m_currentMods = 0; // HT modifiers, not xkb
127-
uint32_t m_lastEnterSerial = 0;
135+
std::vector<WP<CWaylandWindow>> m_windows;
136+
std::vector<WP<CWaylandLayer>> m_layers;
137+
std::vector<WP<CWaylandLockSurface>> m_lockSurfaces;
138+
WP<IWaylandWindow> m_currentWindow;
139+
uint32_t m_currentMods = 0; // HT modifiers, not xkb
140+
uint32_t m_lastEnterSerial = 0;
128141
};
129142

130143
inline UP<CWaylandPlatform> g_waylandPlatform;

src/output/WaylandOutput.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "WaylandOutput.hpp"
22
#include "../core/InternalBackend.hpp"
3-
#include "../helpers/Memory.hpp"
43

54
using namespace Hyprtoolkit;
65

@@ -28,14 +27,14 @@ CWaylandOutput::CWaylandOutput(wl_proxy* wlResource, uint32_t id) : m_id(id), m_
2827
m_wlOutput.setName([this](CCWlOutput* r, const char* name) {
2928
m_configuration.name = std::string{name} + m_configuration.name;
3029
m_configuration.port = std::string{name};
31-
g_logger->log(HT_LOG_DEBUG, "wayland output {}: name {}", name, name);
30+
g_logger->log(HT_LOG_DEBUG, "wayland output {}: name {}", m_id, name);
3231
});
3332

3433
m_wlOutput.setScale([this](CCWlOutput* r, int32_t sc) { m_configuration.scale = sc; });
3534

3635
m_wlOutput.setDone([this](CCWlOutput* r) {
3736
m_configuration.done = true;
38-
g_logger->log(HT_LOG_DEBUG, "wayland output {} done", m_id);
37+
g_logger->log(HT_LOG_DEBUG, "wayland output {}: done", m_id);
3938
});
4039

4140
m_wlOutput.setMode([this](CCWlOutput* r, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
@@ -45,13 +44,13 @@ CWaylandOutput::CWaylandOutput(wl_proxy* wlResource, uint32_t id) : m_id(id), m_
4544
else
4645
m_configuration.size = {width, height};
4746

48-
g_logger->log(HT_LOG_DEBUG, "wayland output {} dimensions {}", m_id);
47+
g_logger->log(HT_LOG_DEBUG, "wayland output {}: dimensions {}", m_id, m_configuration.size);
4948
});
5049

5150
m_wlOutput.setGeometry(
5251
[this](CCWlOutput* r, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform_) {
5352
m_configuration.transform = wlTransformToHyprutils((wl_output_transform)transform_);
5453

55-
g_logger->log(HT_LOG_DEBUG, "wayland output {} make {} model {}", m_id, make ? make : "", model ? model : "");
54+
g_logger->log(HT_LOG_DEBUG, "wayland output {}: make {} model {}", m_id, make ? make : "", model ? model : "");
5655
});
5756
}

src/renderer/gl/OpenGL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ static const char* eglErrorToString(EGLint error) {
6262

6363
static void eglLog(EGLenum error, const char* command, EGLint type, EGLLabelKHR thread, EGLLabelKHR obj, const char* msg) {
6464
g_logger->log(eglLogToLevel(type), "[EGL] Command {} errored out with {} (0x{}): {}", command, eglErrorToString(error), error, msg);
65+
RASSERT(false, "");
6566
}
6667

6768
static GLuint compileShader(const GLuint& type, std::string src) {
@@ -502,6 +503,8 @@ COpenGLRenderer::COpenGLRenderer(int drmFD) {
502503
}
503504

504505
COpenGLRenderer::~COpenGLRenderer() {
506+
m_glTextures.clear();
507+
505508
if (m_eglDisplay && m_eglContext != EGL_NO_CONTEXT)
506509
eglDestroyContext(m_eglDisplay, m_eglContext);
507510

src/window/Builder.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "Window.hpp"
22
#include "../core/InternalBackend.hpp"
33
#include "ToolkitWindow.hpp"
4+
#include "core/platforms/WaylandPlatform.hpp"
5+
#include "hyprtoolkit/core/LogTypes.hpp"
46

57
using namespace Hyprtoolkit;
68

0 commit comments

Comments
 (0)