xcbOrg/Window: Destroy connections when no longer in use
This commit is contained in:
@@ -73,6 +73,18 @@ size_t ConnectionManager::getConnectionCount()
|
|||||||
return connections.size();
|
return connections.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove a specific connection from the manager
|
||||||
|
* @param id Connection identifier to remove
|
||||||
|
*/
|
||||||
|
void ConnectionManager::removeConnection(const ConnectionIdentifier& id)
|
||||||
|
{
|
||||||
|
auto it = connections.find(id);
|
||||||
|
if (it != connections.end()) {
|
||||||
|
connections.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace window_search {
|
namespace window_search {
|
||||||
|
|
||||||
struct XcbReplyDeleter {
|
struct XcbReplyDeleter {
|
||||||
@@ -83,14 +95,14 @@ struct XcbReplyDeleter {
|
|||||||
xcb_window_t findById(
|
xcb_window_t findById(
|
||||||
xcb_connection_t* conn, xcb_window_t root, uint32_t targetId)
|
xcb_connection_t* conn, xcb_window_t root, uint32_t targetId)
|
||||||
{
|
{
|
||||||
if (root == targetId) return root;
|
|
||||||
|
|
||||||
xcb_query_tree_cookie_t cookie = xcb_query_tree(conn, root);
|
xcb_query_tree_cookie_t cookie = xcb_query_tree(conn, root);
|
||||||
std::unique_ptr<xcb_query_tree_reply_t, XcbReplyDeleter> reply(
|
std::unique_ptr<xcb_query_tree_reply_t, XcbReplyDeleter> reply(
|
||||||
xcb_query_tree_reply(conn, cookie, nullptr));
|
xcb_query_tree_reply(conn, cookie, nullptr));
|
||||||
|
|
||||||
if (!reply) return 0;
|
if (!reply) return 0;
|
||||||
|
|
||||||
|
if (root == targetId) return root;
|
||||||
|
|
||||||
xcb_window_t* children = xcb_query_tree_children(reply.get());
|
xcb_window_t* children = xcb_query_tree_children(reply.get());
|
||||||
int num_children = xcb_query_tree_children_length(reply.get());
|
int num_children = xcb_query_tree_children_length(reply.get());
|
||||||
|
|
||||||
@@ -262,3 +274,19 @@ xcb_window_t xcb_xorg_find_window_by_name(void* conn, xcb_window_t root,
|
|||||||
connection->getConnection(), root, targetName, outWindowName,
|
connection->getConnection(), root, targetName, outWindowName,
|
||||||
matchType);
|
matchType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dereference a connection (decrements ref count and closes if zero)
|
||||||
|
* @param conn Shared pointer to the connection to dereference
|
||||||
|
*/
|
||||||
|
extern "C" dereference_connection_fn xcb_xorg_dereference_connection;
|
||||||
|
void xcb_xorg_dereference_connection(std::shared_ptr<xcb_xorg::XcbConnection> conn)
|
||||||
|
{
|
||||||
|
if (!conn) return;
|
||||||
|
|
||||||
|
int newRefCount = conn->decrementRefCount();
|
||||||
|
// Remove from connection manager if ref count reaches zero
|
||||||
|
if (newRefCount <= 0) {
|
||||||
|
xcb_xorg::ConnectionManager::removeConnection(conn->getIdentifier());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -126,6 +126,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
static size_t getConnectionCount();
|
static size_t getConnectionCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove a specific connection from the manager
|
||||||
|
* @param id Connection identifier to remove
|
||||||
|
*/
|
||||||
|
static void removeConnection(const ConnectionIdentifier& id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::map<ConnectionIdentifier, std::shared_ptr<XcbConnection>> connections;
|
static std::map<ConnectionIdentifier, std::shared_ptr<XcbConnection>> connections;
|
||||||
};
|
};
|
||||||
@@ -167,6 +173,8 @@ xcb_window_t findByName(xcb_connection_t* conn, xcb_window_t root,
|
|||||||
typedef std::shared_ptr<xcb_xorg::XcbConnection> get_or_create_connection_fn(
|
typedef std::shared_ptr<xcb_xorg::XcbConnection> get_or_create_connection_fn(
|
||||||
int display, int screen);
|
int display, int screen);
|
||||||
typedef void cleanup_connections_fn();
|
typedef void cleanup_connections_fn();
|
||||||
|
typedef void dereference_connection_fn(
|
||||||
|
std::shared_ptr<xcb_xorg::XcbConnection> conn);
|
||||||
typedef xcb_window_t find_window_by_id_fn(
|
typedef xcb_window_t find_window_by_id_fn(
|
||||||
void* conn, xcb_window_t root, uint32_t targetId);
|
void* conn, xcb_window_t root, uint32_t targetId);
|
||||||
typedef xcb_window_t find_window_by_name_fn(void* conn, xcb_window_t root,
|
typedef xcb_window_t find_window_by_name_fn(void* conn, xcb_window_t root,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ struct XcbXorgDllState
|
|||||||
{
|
{
|
||||||
get_or_create_connection_fn* getOrCreateConnection = nullptr;
|
get_or_create_connection_fn* getOrCreateConnection = nullptr;
|
||||||
cleanup_connections_fn* cleanupConnections = nullptr;
|
cleanup_connections_fn* cleanupConnections = nullptr;
|
||||||
|
dereference_connection_fn* dereferenceConnection = nullptr;
|
||||||
find_window_by_id_fn* findWindowById = nullptr;
|
find_window_by_id_fn* findWindowById = nullptr;
|
||||||
find_window_by_name_fn* findWindowByName = nullptr;
|
find_window_by_name_fn* findWindowByName = nullptr;
|
||||||
} fns;
|
} fns;
|
||||||
@@ -54,11 +55,12 @@ std::string WindowSelector::stringify() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
AttachedWindow::AttachedWindow(const smo::device::SenseDeviceSpec& spec)
|
AttachedWindow::AttachedWindow(const smo::device::SenseDeviceSpec& spec)
|
||||||
: deviceSpec(spec), xcbConnection(nullptr)
|
: deviceSpec(spec)
|
||||||
{
|
{
|
||||||
// Validate required function pointers are available
|
// Validate required function pointers are available
|
||||||
if (!xcbXorg.fns.getOrCreateConnection ||
|
if (!xcbXorg.fns.getOrCreateConnection ||
|
||||||
!xcbXorg.fns.findWindowById || !xcbXorg.fns.findWindowByName)
|
!xcbXorg.fns.findWindowById || !xcbXorg.fns.findWindowByName
|
||||||
|
|| !xcbXorg.fns.dereferenceConnection)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("xcbWindow:" + std::string(__func__) +
|
throw std::runtime_error("xcbWindow:" + std::string(__func__) +
|
||||||
": Required xcbXorg function pointers not available");
|
": Required xcbXorg function pointers not available");
|
||||||
@@ -73,7 +75,7 @@ AttachedWindow::AttachedWindow(const smo::device::SenseDeviceSpec& spec)
|
|||||||
(*xcbXorg.fns.getOrCreateConnection)(
|
(*xcbXorg.fns.getOrCreateConnection)(
|
||||||
windowSelector.display, windowSelector.screen);
|
windowSelector.display, windowSelector.screen);
|
||||||
|
|
||||||
xcbConnection = conn.get();
|
xcbConnectionShared = conn;
|
||||||
|
|
||||||
// Find the target window
|
// Find the target window
|
||||||
xcb_window_t foundWindow = 0;
|
xcb_window_t foundWindow = 0;
|
||||||
@@ -83,13 +85,13 @@ AttachedWindow::AttachedWindow(const smo::device::SenseDeviceSpec& spec)
|
|||||||
if (windowSelector.matchType == xcb_xorg::window_search::MatchType::ID)
|
if (windowSelector.matchType == xcb_xorg::window_search::MatchType::ID)
|
||||||
{
|
{
|
||||||
foundWindow = (*xcbXorg.fns.findWindowById)(
|
foundWindow = (*xcbXorg.fns.findWindowById)(
|
||||||
xcbConnection, screen->root,
|
conn.get(), screen->root,
|
||||||
windowSelector.windowId);
|
windowSelector.windowId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foundWindow = (*xcbXorg.fns.findWindowByName)(
|
foundWindow = (*xcbXorg.fns.findWindowByName)(
|
||||||
xcbConnection, screen->root,
|
conn.get(), screen->root,
|
||||||
windowSelector.windowName, actualWindowName,
|
windowSelector.windowName, actualWindowName,
|
||||||
windowSelector.matchType);
|
windowSelector.matchType);
|
||||||
}
|
}
|
||||||
@@ -221,6 +223,13 @@ std::string AttachedWindow::stringify() const {
|
|||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AttachedWindow::~AttachedWindow()
|
||||||
|
{
|
||||||
|
if (xcbConnectionShared && xcbXorg.fns.dereferenceConnection) {
|
||||||
|
(*xcbXorg.fns.dereferenceConnection)(xcbConnectionShared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xcb_window
|
} // namespace xcb_window
|
||||||
|
|
||||||
// SenseApi functions
|
// SenseApi functions
|
||||||
@@ -254,9 +263,13 @@ static int xcbWindow_initializeInd(void)
|
|||||||
dlsym(xcbXorg.dlopenHandle, "xcb_xorg_find_window_by_id"));
|
dlsym(xcbXorg.dlopenHandle, "xcb_xorg_find_window_by_id"));
|
||||||
xcbXorg.fns.findWindowByName = reinterpret_cast<find_window_by_name_fn*>(
|
xcbXorg.fns.findWindowByName = reinterpret_cast<find_window_by_name_fn*>(
|
||||||
dlsym(xcbXorg.dlopenHandle, "xcb_xorg_find_window_by_name"));
|
dlsym(xcbXorg.dlopenHandle, "xcb_xorg_find_window_by_name"));
|
||||||
|
xcbXorg.fns.dereferenceConnection =
|
||||||
|
reinterpret_cast<dereference_connection_fn*>(
|
||||||
|
dlsym(xcbXorg.dlopenHandle, "xcb_xorg_dereference_connection"));
|
||||||
|
|
||||||
if (!xcbXorg.fns.getOrCreateConnection || !xcbXorg.fns.cleanupConnections
|
if (!xcbXorg.fns.getOrCreateConnection || !xcbXorg.fns.cleanupConnections
|
||||||
|| !xcbXorg.fns.findWindowById || !xcbXorg.fns.findWindowByName)
|
|| !xcbXorg.fns.findWindowById || !xcbXorg.fns.findWindowByName
|
||||||
|
|| !xcbXorg.fns.dereferenceConnection)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
std::string("xcbWindow:") + __func__ +
|
std::string("xcbWindow:") + __func__ +
|
||||||
@@ -274,7 +287,7 @@ static int xcbWindow_finalizeInd(void)
|
|||||||
{
|
{
|
||||||
dlclose(xcbXorg.dlopenHandle);
|
dlclose(xcbXorg.dlopenHandle);
|
||||||
xcbXorg.dlopenHandle = nullptr;
|
xcbXorg.dlopenHandle = nullptr;
|
||||||
xcbXorg.fns = { nullptr, nullptr, nullptr, nullptr };
|
xcbXorg.fns = { nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ class AttachedWindow
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AttachedWindow(const smo::device::SenseDeviceSpec& spec);
|
AttachedWindow(const smo::device::SenseDeviceSpec& spec);
|
||||||
~AttachedWindow() = default;
|
~AttachedWindow();
|
||||||
|
|
||||||
const smo::device::SenseDeviceSpec& getDeviceSpec() const { return deviceSpec; }
|
const smo::device::SenseDeviceSpec& getDeviceSpec() const { return deviceSpec; }
|
||||||
const WindowSelector& getWindowSelector() const { return windowSelector; }
|
const WindowSelector& getWindowSelector() const { return windowSelector; }
|
||||||
const std::string& getActualWindowName() const { return actualWindowName; }
|
const std::string& getActualWindowName() const { return actualWindowName; }
|
||||||
void* getXcbConnection() const { return xcbConnection; }
|
void* getXcbConnection() const { return xcbConnectionShared.get(); }
|
||||||
std::string stringify() const;
|
std::string stringify() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -47,7 +47,7 @@ private:
|
|||||||
smo::device::SenseDeviceSpec deviceSpec;
|
smo::device::SenseDeviceSpec deviceSpec;
|
||||||
WindowSelector windowSelector;
|
WindowSelector windowSelector;
|
||||||
std::string actualWindowName;
|
std::string actualWindowName;
|
||||||
void* xcbConnection; // Raw pointer to XCB connection from libxcbXorg
|
std::shared_ptr<xcb_xorg::XcbConnection> xcbConnectionShared;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xcb_window
|
} // namespace xcb_window
|
||||||
|
|||||||
Reference in New Issue
Block a user