Skip to content

Commit 81447a0

Browse files
committed
Code cleaning
1 parent da9b2cb commit 81447a0

7 files changed

Lines changed: 149 additions & 87 deletions

File tree

modules/System/FileDescriptor.mpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export namespace CppUtils::System
5454
return std::exchange(m_fileDescriptor, -1);
5555
}
5656

57-
[[nodiscard]] inline constexpr auto isValid() noexcept -> bool
57+
[[nodiscard]] inline constexpr auto isValid() const noexcept -> bool
5858
{
5959
return m_fileDescriptor != -1;
6060
}

modules/System/System.mpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,26 @@ export namespace CppUtils::System
3131
[[nodiscard]] inline auto createSharedMemory(std::string filename = "SharedMemory") -> std::expected<FileDescriptor, std::string_view>
3232
{
3333
using namespace std::literals;
34-
auto fillRandomSuffix = [](std::string& filename) -> void {
34+
auto fillRandomSuffix = [](std::string& path) -> void {
35+
static constexpr auto alphabet = std::string_view{"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"};
3536
using namespace std::chrono;
36-
auto random = duration_cast<nanoseconds>(system_clock::now().time_since_epoch()).count();
37+
auto random = static_cast<std::uint64_t>(duration_cast<nanoseconds>(system_clock::now().time_since_epoch()).count());
3738
for (auto i = 0uz; i < 6uz; ++i)
3839
{
39-
filename[std::size(filename) - 6 + i] = 'A' + static_cast<char>(random & 0b1111) + static_cast<char>((random & 0b1'0000) << 1); // Insère une lettre aléatoire parmi [A-Pa-p] (alphabet sur 32 caractères)
40-
random >>= 5;
40+
path[std::size(path) - 6 + i] = alphabet[random % std::size(alphabet)];
41+
random /= std::size(alphabet);
4142
}
4243
};
43-
filename += "-XXXXXX";
44+
if (std::empty(filename))
45+
filename = "SharedMemory";
46+
auto path = std::string{"/"} + filename + "-XXXXXX";
4447
auto retries = 100uz;
4548
do
4649
{
47-
fillRandomSuffix(filename);
48-
if (auto fileDescriptor = FileDescriptor{shm_open(std::data(filename), O_RDWR | O_CREAT | O_EXCL, 600)}; fileDescriptor.isValid())
50+
fillRandomSuffix(path);
51+
if (auto fileDescriptor = FileDescriptor{shm_open(std::data(path), O_RDWR | O_CREAT | O_EXCL, 0600)}; fileDescriptor.isValid())
4952
{
50-
shm_unlink(std::data(filename));
53+
shm_unlink(std::data(path));
5154
return fileDescriptor;
5255
}
5356
}
@@ -96,13 +99,16 @@ export namespace CppUtils::System
9699
inline MappedSharedMemory& operator=(const MappedSharedMemory&) = delete;
97100
inline MappedSharedMemory& operator=(MappedSharedMemory&& other) noexcept
98101
{
102+
if (this == std::addressof(other))
103+
return *this;
104+
release();
99105
m_sharedMemory = std::exchange(other.m_sharedMemory, {});
100106
return *this;
101107
}
102108

103109
inline ~MappedSharedMemory()
104110
{
105-
munmap(std::data(m_sharedMemory), std::size(m_sharedMemory));
111+
release();
106112
}
107113

108114
[[nodiscard]] inline auto get() const noexcept -> auto*
@@ -115,6 +121,14 @@ export namespace CppUtils::System
115121
return std::size(m_sharedMemory);
116122
}
117123

124+
private:
125+
inline auto release() noexcept -> void
126+
{
127+
if (auto* data = std::data(m_sharedMemory); data != nullptr and std::size(m_sharedMemory) > 0)
128+
munmap(data, std::size(m_sharedMemory));
129+
m_sharedMemory = {};
130+
}
131+
118132
std::span<std::byte> m_sharedMemory;
119133
};
120134
#endif

modules/Window/Window.mpp

Lines changed: 104 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -36,66 +36,69 @@ namespace CppUtils::Window
3636
inline constexpr const auto bytesPerPixel = std::size_t{4};
3737
}
3838

39-
inline auto xdg_wm_base_ping([[maybe_unused]] void* data, xdg_wm_base* xdg_wm_base, std::uint32_t serial) -> void
39+
namespace
4040
{
41-
xdg_wm_base_pong(xdg_wm_base, serial);
42-
}
41+
auto xdg_wm_base_ping([[maybe_unused]] void* data, xdg_wm_base* xdg_wm_base, std::uint32_t serial) -> void
42+
{
43+
xdg_wm_base_pong(xdg_wm_base, serial);
44+
}
4345

44-
inline const auto windowManagerBaseListener = xdg_wm_base_listener{
45-
.ping = xdg_wm_base_ping,
46-
};
46+
constexpr auto windowManagerBaseListener = xdg_wm_base_listener{
47+
.ping = xdg_wm_base_ping,
48+
};
4749

48-
inline auto global_registry_handler(
49-
void* data,
50-
wl_registry* registry,
51-
std::uint32_t id,
52-
const char* interface,
53-
std::uint32_t version) noexcept -> void
54-
{
55-
static const auto waylandRegistryHandlers = std::unordered_map<std::string_view, Wayland::RegisterHandler>{
56-
Wayland::makeHandlerPair(wl_compositor_interface, Wayland::globals.compositor, 3, 4),
57-
Wayland::makeHandlerPair(wl_shm_interface, Wayland::globals.sharedMemory, 1, 1),
58-
Wayland::makeHandlerPair(xdg_wm_base_interface, Wayland::globals.windowManagerBase, 1, 1, [data]() -> void {
59-
xdg_wm_base_add_listener(Wayland::globals.windowManagerBase.get(), &windowManagerBaseListener, data);
60-
})};
61-
auto interfaceName = std::string_view{interface};
62-
if (const auto& iterator = waylandRegistryHandlers.find(interfaceName); iterator != std::cend(waylandRegistryHandlers))
50+
auto global_registry_handler(
51+
void* data,
52+
wl_registry* registry,
53+
std::uint32_t id,
54+
const char* interface,
55+
std::uint32_t version) noexcept -> void
6356
{
64-
iterator->second(registry, id, version);
65-
Logger::print<"success">("{}", interfaceName);
57+
static const auto waylandRegistryHandlers = std::unordered_map<std::string_view, Wayland::RegisterHandler>{
58+
Wayland::makeHandlerPair(wl_compositor_interface, Wayland::globals.compositor, 3, 4),
59+
Wayland::makeHandlerPair(wl_shm_interface, Wayland::globals.sharedMemory, 1, 1),
60+
Wayland::makeHandlerPair(xdg_wm_base_interface, Wayland::globals.windowManagerBase, 1, 1, [data]() -> void {
61+
xdg_wm_base_add_listener(Wayland::globals.windowManagerBase.get(), &windowManagerBaseListener, data);
62+
})};
63+
auto interfaceName = std::string_view{interface};
64+
if (const auto& iterator = waylandRegistryHandlers.find(interfaceName); iterator != std::cend(waylandRegistryHandlers))
65+
{
66+
iterator->second(registry, id, version);
67+
Logger::print<"success">("{}", interfaceName);
68+
}
69+
else
70+
Logger::print<"warning">("{}", interfaceName);
6671
}
67-
else
68-
Logger::print<"warning">("{}", interfaceName);
69-
}
7072

71-
inline auto global_registry_remover(
72-
[[maybe_unused]] void* data,
73-
[[maybe_unused]] wl_registry* registry,
74-
[[maybe_unused]] std::uint32_t id) noexcept -> void
75-
{}
73+
auto global_registry_remover(
74+
[[maybe_unused]] void* data,
75+
[[maybe_unused]] wl_registry* registry,
76+
[[maybe_unused]] std::uint32_t id) noexcept -> void
77+
{}
7678

77-
inline const auto registryListener = wl_registry_listener{
78-
.global = global_registry_handler,
79-
.global_remove = global_registry_remover,
80-
};
79+
constexpr auto registryListener = wl_registry_listener{
80+
.global = global_registry_handler,
81+
.global_remove = global_registry_remover,
82+
};
8183

82-
inline auto wl_buffer_release([[maybe_unused]] void* data, [[maybe_unused]] wl_buffer* buffer) -> void
83-
{
84-
// Todo: basculer sur la frame suivante
85-
}
84+
auto wl_buffer_release([[maybe_unused]] void* data, [[maybe_unused]] wl_buffer* buffer) -> void
85+
{
86+
// Todo: basculer sur la frame suivante
87+
}
8688

87-
inline const auto bufferListener = wl_buffer_listener{
88-
.release = wl_buffer_release,
89-
};
89+
constexpr auto bufferListener = wl_buffer_listener{
90+
.release = wl_buffer_release,
91+
};
9092

91-
inline auto xdg_surface_configure(
92-
void* data,
93-
xdg_surface* xdg_surface,
94-
std::uint32_t serial) -> void;
93+
auto xdg_surface_configure(
94+
void* data,
95+
xdg_surface* xdg_surface,
96+
std::uint32_t serial) -> void;
9597

96-
inline const auto surfaceListener = xdg_surface_listener{
97-
.configure = xdg_surface_configure,
98-
};
98+
constexpr auto surfaceListener = xdg_surface_listener{
99+
.configure = xdg_surface_configure,
100+
};
101+
}
99102
#endif
100103

101104
export class Window final
@@ -123,7 +126,10 @@ namespace CppUtils::Window
123126
const auto screenBufferSize = strideSize * m_size.height();
124127
const auto bufferSize = screenBufferSize * 3; // triple buffering
125128

126-
m_fileDescriptor = System::FileDescriptor{System::allocateSharedMemory(bufferSize, "WaylandBuffer").value()};
129+
auto sharedMemory = System::allocateSharedMemory(bufferSize, "WaylandBuffer");
130+
if (not sharedMemory)
131+
throw std::runtime_error{std::string{sharedMemory.error()}};
132+
m_fileDescriptor = System::FileDescriptor{std::move(sharedMemory).value()};
127133
pixels = System::MappedSharedMemory{m_fileDescriptor, bufferSize};
128134
pool.reset(wl_shm_create_pool(Wayland::globals.sharedMemory.get(), m_fileDescriptor.get(), static_cast<std::int32_t>(bufferSize)));
129135
buffer.reset(
@@ -158,7 +164,7 @@ namespace CppUtils::Window
158164
#endif
159165

160166
#if defined(OS_WINDOWS)
161-
[[nodiscard]] static inline auto generateStyle(Style style) const noexcept -> DWORD
167+
[[nodiscard]] static inline auto generateStyle(Style style) noexcept -> DWORD
162168
{
163169
auto windowStyle = DWORD{0};
164170
if (style & Style::HasBorder)
@@ -190,6 +196,10 @@ namespace CppUtils::Window
190196
wl_display_roundtrip(display);
191197
if (not Wayland::globals.compositor)
192198
return std::unexpected{"Failed to find a Wayland compositor"s};
199+
if (not Wayland::globals.sharedMemory)
200+
return std::unexpected{"Failed to find Wayland shared memory interface (wl_shm)"s};
201+
if (not Wayland::globals.windowManagerBase)
202+
return std::unexpected{"Failed to find xdg_wm_base interface"s};
193203
#endif
194204
return {};
195205
}
@@ -204,6 +214,10 @@ namespace CppUtils::Window
204214
if (m_window == nullptr)
205215
return std::unexpected{"Window creation failed."sv};
206216
#elif defined(OS_LINUX)
217+
if (not Wayland::globals.compositor)
218+
return std::unexpected{"Wayland compositor is not initialized"sv};
219+
if (not Wayland::globals.windowManagerBase)
220+
return std::unexpected{"Wayland window manager base is not initialized"sv};
207221
surface.reset(wl_compositor_create_surface(Wayland::globals.compositor.get()));
208222
if (not surface)
209223
return std::unexpected{"Failed to create a Wayland surface"sv};
@@ -223,14 +237,21 @@ namespace CppUtils::Window
223237
m_style{style},
224238
m_size{size}
225239
{
226-
initWindowManager();
240+
#if defined(OS_LINUX)
241+
if (auto result = initWindowManager(); not result)
242+
throw std::runtime_error{result.error()};
243+
227244
wl_display_roundtrip(Wayland::globals.display.get());
228245
// m_imageStorage = ImageStorage{size};
229-
openWindow();
246+
if (auto result = openWindow(); not result)
247+
throw std::runtime_error{std::string{result.error()}};
248+
249+
m_isOpen = true;
230250
wl_surface_commit(surface.get());
231251
wl_display_roundtrip(Wayland::globals.display.get());
232252
// wl_display_dispatch(Wayland::globals.display.get());
233253
wl_display_flush(Wayland::globals.display.get());
254+
#endif
234255
}
235256

236257
inline ~Window()
@@ -269,30 +290,43 @@ namespace CppUtils::Window
269290

270291
[[nodiscard]] inline auto getPixels() const noexcept -> auto*
271292
{
293+
#if defined(OS_LINUX)
272294
return reinterpret_cast<std::uint32_t*>(m_imageStorage.pixels.get());
295+
#else
296+
return static_cast<std::uint32_t*>(nullptr);
297+
#endif
273298
}
274299

275300
inline auto runLoop() -> void
276301
{
302+
#if defined(OS_LINUX)
303+
if (not m_isOpen)
304+
return;
277305
auto result = 0;
278306
while ((result = wl_display_dispatch(Wayland::globals.display.get())) != -1)
279307
Logger::print<"detail">("Event received, result = {}", result);
280308
Logger::print<"warning">("Wayland dispatch exited with {}", result);
309+
#endif
281310
}
282311

283312
inline auto update() -> void
284313
{
314+
#if defined(OS_LINUX)
315+
if (not m_isOpen or not m_imageStorage.buffer)
316+
return;
285317
Logger::print<"detail">("update");
286318
wl_surface_attach(surface.get(), m_imageStorage.buffer.get(), 0, 0);
287319
wl_surface_damage(surface.get(), 0, 0, std::numeric_limits<std::int32_t>::max(), std::numeric_limits<std::int32_t>::max());
288320
wl_surface_commit(surface.get());
289321
wl_display_flush(Wayland::globals.display.get());
322+
#endif
290323
}
291324

292325
private:
293326
std::string m_title;
294327
[[maybe_unused]] Style m_style;
295328
Container::Size2 m_size;
329+
bool m_isOpen = false;
296330
#if defined(OS_WINDOWS)
297331
static inline constexpr auto windowClassName = L"Window";
298332
HWND m_window;
@@ -306,8 +340,9 @@ namespace CppUtils::Window
306340
#endif
307341
};
308342

309-
export inline auto drawFrame(Window& window) -> void
343+
export inline auto drawFrame([[maybe_unused]] Window& window) -> void
310344
{
345+
#if defined(OS_LINUX)
311346
Logger::print<"detail">("drawFrame");
312347
const auto& imageSize = window.getSize();
313348
if (not window.m_imageStorage.buffer)
@@ -324,18 +359,24 @@ namespace CppUtils::Window
324359
else
325360
pixels[y * imageSize.width() + x] = 0xFF'EE'EE'EE;
326361
}
362+
#endif
327363
}
328364

329-
inline auto xdg_surface_configure(
330-
void* data,
331-
xdg_surface* xdg_surface,
332-
std::uint32_t serial) -> void
365+
#if defined(OS_LINUX)
366+
namespace
333367
{
334-
Logger::print<"detail">("Surface configure !");
335-
auto& window = *static_cast<Window*>(data);
336-
xdg_surface_ack_configure(xdg_surface, serial);
368+
auto xdg_surface_configure(
369+
void* data,
370+
xdg_surface* xdg_surface,
371+
std::uint32_t serial) -> void
372+
{
373+
Logger::print<"detail">("Surface configure !");
374+
auto& window = *static_cast<Window*>(data);
375+
xdg_surface_ack_configure(xdg_surface, serial);
337376

338-
drawFrame(window);
339-
window.update();
377+
drawFrame(window);
378+
window.update();
379+
}
340380
}
381+
#endif
341382
}

tests/Window/Window.mpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ export namespace CppUtils::UnitTest::Window
99
using namespace std::literals;
1010

1111
suite.addTest("Opening a window", [&] {
12+
suite.expect(std::getenv("WAYLAND_DISPLAY") != nullptr);
1213
auto window = CppUtils::Window::Window{"Title", {640, 360}};
13-
std::this_thread::sleep_for(5s);
14+
std::this_thread::sleep_for(3s);
1415
suite.expectEqual(window.getTitle(), "Title"sv);
1516
});
1617
}};

tests/xmake.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@ target("CppUtils-UnitTests", function()
33
add_deps("CppUtils")
44
add_files("**.cpp")
55
add_files("**.mpp", { public = true })
6+
7+
if is_plat("linux") then
8+
add_packages("wayland", "wayland-protocols")
9+
add_rules("wayland.protocols")
10+
end
611
end)

0 commit comments

Comments
 (0)