diff options
-rw-r--r-- | include/cru/base/Guard.h | 26 | ||||
-rw-r--r-- | src/platform/gui/xcb/Keyboard.cpp | 12 | ||||
-rw-r--r-- | src/platform/gui/xcb/UiApplication.cpp | 4 | ||||
-rw-r--r-- | src/platform/gui/xcb/Window.cpp | 25 |
4 files changed, 49 insertions, 18 deletions
diff --git a/include/cru/base/Guard.h b/include/cru/base/Guard.h index 5a9f9c5d..6b6cf851 100644 --- a/include/cru/base/Guard.h +++ b/include/cru/base/Guard.h @@ -1,5 +1,6 @@ #pragma once +#include <cstdlib> #include <functional> namespace cru { @@ -23,4 +24,29 @@ struct Guard { ExitFunc on_exit; }; + +template <typename T> +struct FreeLater { + FreeLater(T* ptr) : ptr(ptr) {} + ~FreeLater() { ::free(ptr); } + + FreeLater(const FreeLater& other) = delete; + FreeLater& operator=(const FreeLater& other) = delete; + + FreeLater(FreeLater&& other) : ptr(other.ptr) { other.ptr = nullptr; } + FreeLater& operator=(FreeLater&& other) { + if (this != &other) { + ::free(ptr); + ptr = other.ptr; + other.ptr = nullptr; + } + return *this; + } + + operator T*() const { return ptr; } + T* operator->() { return ptr; } + + T* ptr; +}; + } // namespace cru diff --git a/src/platform/gui/xcb/Keyboard.cpp b/src/platform/gui/xcb/Keyboard.cpp index d7559062..e5f6da8e 100644 --- a/src/platform/gui/xcb/Keyboard.cpp +++ b/src/platform/gui/xcb/Keyboard.cpp @@ -1,4 +1,5 @@ #include "cru/platform/gui/xcb/Keyboard.h" +#include "cru/base/Guard.h" #include "cru/platform/gui/Keyboard.h" #include "cru/platform/gui/xcb/UiApplication.h" @@ -82,8 +83,8 @@ KeyCode XorgKeycodeToCruKeyCode(XcbUiApplication *application, // Get keyboard mapping auto mapping_cookie = xcb_get_keyboard_mapping(connection, keycode, 1); - auto *mapping_reply = - xcb_get_keyboard_mapping_reply(connection, mapping_cookie, NULL); + auto mapping_reply = FreeLater( + xcb_get_keyboard_mapping_reply(connection, mapping_cookie, NULL)); if (!mapping_reply) { throw XcbException("Cannot get keyboard mapping."); @@ -107,7 +108,8 @@ using KeymapBitset = KeymapBitset GetXorgKeymap(xcb_connection_t *connection) { auto keymap_cookie = xcb_query_keymap(connection); - auto keymap_reply = xcb_query_keymap_reply(connection, keymap_cookie, NULL); + auto keymap_reply = + FreeLater(xcb_query_keymap_reply(connection, keymap_cookie, NULL)); if (!keymap_reply) { throw XcbException("Cannot get keymap."); @@ -136,8 +138,8 @@ std::unordered_map<KeyCode, bool> GetKeyboardState( // Get keyboard mapping auto mapping_cookie = xcb_get_keyboard_mapping(connection, min_keycode, max_keycode - min_keycode + 1); - auto *mapping_reply = - xcb_get_keyboard_mapping_reply(connection, mapping_cookie, NULL); + auto mapping_reply = FreeLater( + xcb_get_keyboard_mapping_reply(connection, mapping_cookie, NULL)); if (!mapping_reply) { throw XcbException("Cannot get keyboard mapping."); diff --git a/src/platform/gui/xcb/UiApplication.cpp b/src/platform/gui/xcb/UiApplication.cpp index 9daac385..d79f42a7 100644 --- a/src/platform/gui/xcb/UiApplication.cpp +++ b/src/platform/gui/xcb/UiApplication.cpp @@ -1,6 +1,7 @@ #include "cru/platform/gui/xcb/UiApplication.h" #include "cru/base/Base.h" +#include "cru/base/Guard.h" #include "cru/platform/graphics/cairo/CairoGraphicsFactory.h" #include "cru/platform/gui/Window.h" #include "cru/platform/gui/xcb/Cursor.h" @@ -70,7 +71,8 @@ xcb_atom_t XcbUiApplication::GetOrCreateXcbAtom(std::string name) { auto cookie = xcb_intern_atom(xcb_connection_, false, name.size(), name.data()); - auto reply = xcb_intern_atom_reply(xcb_connection_, cookie, nullptr); + auto reply = + FreeLater(xcb_intern_atom_reply(xcb_connection_, cookie, nullptr)); auto atom = reply->atom; xcb_atom_.emplace(std::move(name), atom); return atom; diff --git a/src/platform/gui/xcb/Window.cpp b/src/platform/gui/xcb/Window.cpp index 4aa2d912..f3480fe0 100644 --- a/src/platform/gui/xcb/Window.cpp +++ b/src/platform/gui/xcb/Window.cpp @@ -1,5 +1,6 @@ #include "cru/platform/gui/xcb/Window.h" #include "cru/base/Base.h" +#include "cru/base/Guard.h" #include "cru/platform/Check.h" #include "cru/platform/GraphicsBase.h" #include "cru/platform/graphics/Painter.h" @@ -193,8 +194,8 @@ Rect XcbWindow::GetClientRect() { auto window = *xcb_window_; auto cookie = xcb_get_geometry(application_->GetXcbConnection(), window); - auto reply = - xcb_get_geometry_reply(application_->GetXcbConnection(), cookie, nullptr); + auto reply = FreeLater(xcb_get_geometry_reply( + application_->GetXcbConnection(), cookie, nullptr)); auto position = GetXcbWindowPosition(window); return Rect(position.x, position.y, reply->width, reply->height); @@ -241,8 +242,8 @@ bool XcbWindow::RequestFocus() { Point XcbWindow::GetMousePosition() { auto window = xcb_window_.value_or(application_->GetFirstXcbScreen()->root); auto cookie = xcb_query_pointer(application_->GetXcbConnection(), window); - auto reply = xcb_query_pointer_reply(application_->GetXcbConnection(), cookie, - nullptr); + auto reply = FreeLater(xcb_query_pointer_reply( + application_->GetXcbConnection(), cookie, nullptr)); return Point(reply->win_x, reply->win_y); } @@ -616,8 +617,8 @@ void XcbWindow::DoSetTitle(xcb_window_t window) { void XcbWindow::DoSetClientRect(xcb_window_t window, const Rect &rect) { auto tree_cookie = xcb_query_tree(application_->GetXcbConnection(), window); - auto tree_reply = xcb_query_tree_reply(application_->GetXcbConnection(), - tree_cookie, nullptr); + auto tree_reply = FreeLater(xcb_query_tree_reply( + application_->GetXcbConnection(), tree_cookie, nullptr)); auto parent_position = GetXcbWindowPosition(tree_reply->parent); std::uint32_t values[4]{ @@ -637,8 +638,8 @@ void *XcbWindow::XcbGetProperty(xcb_window_t window, xcb_atom_t property, std::uint32_t *out_length) { auto cookie = xcb_get_property(application_->GetXcbConnection(), false, window, property, type, offset, length); - auto reply = - xcb_get_property_reply(application_->GetXcbConnection(), cookie, NULL); + auto reply = FreeLater( + xcb_get_property_reply(application_->GetXcbConnection(), cookie, NULL)); if (reply->type == XCB_ATOM_NONE) { return nullptr; } @@ -666,14 +667,14 @@ Point XcbWindow::GetXcbWindowPosition(xcb_window_t window) { while (true) { auto cookie = xcb_get_geometry(application_->GetXcbConnection(), window); - auto reply = xcb_get_geometry_reply(application_->GetXcbConnection(), - cookie, nullptr); + auto reply = FreeLater(xcb_get_geometry_reply( + application_->GetXcbConnection(), cookie, nullptr)); result.x += reply->x; result.y += reply->y; auto tree_cookie = xcb_query_tree(application_->GetXcbConnection(), window); - auto tree_reply = xcb_query_tree_reply(application_->GetXcbConnection(), - tree_cookie, nullptr); + auto tree_reply = FreeLater(xcb_query_tree_reply( + application_->GetXcbConnection(), tree_cookie, nullptr)); window = tree_reply->parent; // TODO: Multi-screen offset? if (tree_reply->root == window || window == XCB_WINDOW_NONE) { |