mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:27:45 +00:00
LibCore: Make CObject reference-counted
Okay, I've spent a whole day on this now, and it finally kinda works! With this patch, CObject and all of its derived classes are reference counted instead of tree-owned. The previous, Qt-like model was nice and familiar, but ultimately also outdated and difficult to reason about. CObject-derived types should now be stored in RefPtr/NonnullRefPtr and each class can be constructed using the forwarding construct() helper: auto widget = GWidget::construct(parent_widget); Note that construct() simply forwards all arguments to an existing constructor. It is inserted into each class by the C_OBJECT macro, see CObject.h to understand how that works. CObject::delete_later() disappears in this patch, as there is no longer a single logical owner of a CObject.
This commit is contained in:
parent
0c72e0c09f
commit
bc319d9e88
45 changed files with 174 additions and 233 deletions
|
@ -20,7 +20,7 @@
|
|||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
HashMap<int, WSClientConnection*>* s_connections;
|
||||
HashMap<int, NonnullRefPtr<WSClientConnection>>* s_connections;
|
||||
|
||||
void WSClientConnection::for_each_client(Function<void(WSClientConnection&)> callback)
|
||||
{
|
||||
|
@ -38,24 +38,20 @@ WSClientConnection* WSClientConnection::from_client_id(int client_id)
|
|||
auto it = s_connections->find(client_id);
|
||||
if (it == s_connections->end())
|
||||
return nullptr;
|
||||
return (*it).value;
|
||||
return (*it).value.ptr();
|
||||
}
|
||||
|
||||
WSClientConnection::WSClientConnection(CLocalSocket& client_socket, int client_id)
|
||||
: Connection(client_socket, client_id)
|
||||
{
|
||||
if (!s_connections)
|
||||
s_connections = new HashMap<int, WSClientConnection*>;
|
||||
s_connections->set(client_id, this);
|
||||
s_connections = new HashMap<int, NonnullRefPtr<WSClientConnection>>;
|
||||
s_connections->set(client_id, *this);
|
||||
}
|
||||
|
||||
WSClientConnection::~WSClientConnection()
|
||||
{
|
||||
// NOTE: Move the windows out of 'm_windows' before teardown. This prevents code
|
||||
// that runs in response to window destruction from trying to iterate over
|
||||
// a partially destroyed window list.
|
||||
auto windows = move(m_windows);
|
||||
s_connections->remove(client_id());
|
||||
}
|
||||
|
||||
void WSClientConnection::send_greeting()
|
||||
|
@ -68,6 +64,11 @@ void WSClientConnection::send_greeting()
|
|||
post_message(message);
|
||||
}
|
||||
|
||||
void WSClientConnection::die()
|
||||
{
|
||||
s_connections->remove(client_id());
|
||||
}
|
||||
|
||||
void WSClientConnection::post_error(const String& error_message)
|
||||
{
|
||||
dbgprintf("WSClientConnection::post_error: client_id=%d: %s\n", client_id(), error_message.characters());
|
||||
|
@ -370,7 +371,7 @@ void WSClientConnection::handle_request(const WSAPIDestroyMenubarRequest& reques
|
|||
void WSClientConnection::handle_request(const WSAPICreateMenuRequest& request)
|
||||
{
|
||||
int menu_id = m_next_menu_id++;
|
||||
auto menu = make<WSMenu>(this, menu_id, request.text());
|
||||
auto menu = WSMenu::construct(this, menu_id, request.text());
|
||||
m_menus.set(menu_id, move(menu));
|
||||
WSAPI_ServerMessage response;
|
||||
response.type = WSAPI_ServerMessage::Type::DidCreateMenu;
|
||||
|
@ -389,6 +390,7 @@ void WSClientConnection::handle_request(const WSAPIDestroyMenuRequest& request)
|
|||
auto& menu = *(*it).value;
|
||||
WSWindowManager::the().close_menu(menu);
|
||||
m_menus.remove(it);
|
||||
remove_child(menu);
|
||||
WSAPI_ServerMessage response;
|
||||
response.type = WSAPI_ServerMessage::Type::DidDestroyMenu;
|
||||
response.menu.menu_id = menu_id;
|
||||
|
@ -738,7 +740,7 @@ void WSClientConnection::handle_request(const WSAPIGetClipboardContentsRequest&)
|
|||
void WSClientConnection::handle_request(const WSAPICreateWindowRequest& request)
|
||||
{
|
||||
int window_id = m_next_window_id++;
|
||||
auto window = make<WSWindow>(*this, request.window_type(), window_id, request.is_modal(), request.is_resizable(), request.is_fullscreen());
|
||||
auto window = WSWindow::construct(*this, request.window_type(), window_id, request.is_modal(), request.is_resizable(), request.is_fullscreen());
|
||||
window->set_background_color(request.background_color());
|
||||
window->set_has_alpha_channel(request.has_alpha_channel());
|
||||
window->set_title(request.title());
|
||||
|
@ -766,11 +768,15 @@ void WSClientConnection::handle_request(const WSAPIDestroyWindowRequest& request
|
|||
}
|
||||
auto& window = *(*it).value;
|
||||
WSWindowManager::the().invalidate(window);
|
||||
m_windows.remove(it);
|
||||
WSAPI_ServerMessage response;
|
||||
response.type = WSAPI_ServerMessage::Type::DidDestroyWindow;
|
||||
response.window_id = window.window_id();
|
||||
post_message(response);
|
||||
|
||||
dbg() << *this << " removing window child " << window << " refs: " << window.ref_count() << " parent: " << window.parent();
|
||||
remove_child(window);
|
||||
ASSERT(it->value.ptr() == &window);
|
||||
m_windows.remove(window_id);
|
||||
}
|
||||
|
||||
void WSClientConnection::post_paint_message(WSWindow& window)
|
||||
|
|
|
@ -17,9 +17,9 @@ class WSMenuBar;
|
|||
class WSClientConnection final : public IPC::Server::Connection<WSAPI_ServerMessage, WSAPI_ClientMessage> {
|
||||
C_OBJECT(WSClientConnection)
|
||||
public:
|
||||
explicit WSClientConnection(CLocalSocket&, int client_id);
|
||||
~WSClientConnection() override;
|
||||
void send_greeting() override;
|
||||
virtual void send_greeting() override;
|
||||
virtual void die() override;
|
||||
bool handle_message(const WSAPI_ClientMessage&, const ByteBuffer&& = {}) override;
|
||||
|
||||
static WSClientConnection* from_client_id(int client_id);
|
||||
|
@ -40,11 +40,14 @@ public:
|
|||
|
||||
WSMenu* find_menu_by_id(int menu_id)
|
||||
{
|
||||
// FIXME: Remove this const_cast when Optional knows how to vend a non-const fallback value somehow.
|
||||
return const_cast<WSMenu*>(m_menus.get(menu_id).value_or(nullptr));
|
||||
auto menu = m_menus.get(menu_id);
|
||||
if (!menu.has_value())
|
||||
return nullptr;
|
||||
return const_cast<WSMenu*>(menu.value().ptr());
|
||||
}
|
||||
|
||||
private:
|
||||
explicit WSClientConnection(CLocalSocket&, int client_id);
|
||||
virtual void event(CEvent&) override;
|
||||
|
||||
void on_request(const WSAPIClientRequest&);
|
||||
|
@ -88,9 +91,9 @@ private:
|
|||
|
||||
void post_error(const String&);
|
||||
|
||||
HashMap<int, NonnullOwnPtr<WSWindow>> m_windows;
|
||||
HashMap<int, NonnullRefPtr<WSWindow>> m_windows;
|
||||
HashMap<int, NonnullOwnPtr<WSMenuBar>> m_menubars;
|
||||
HashMap<int, NonnullOwnPtr<WSMenu>> m_menus;
|
||||
HashMap<int, NonnullRefPtr<WSMenu>> m_menus;
|
||||
WeakPtr<WSMenuBar> m_app_menubar;
|
||||
|
||||
int m_next_menubar_id { 10000 };
|
||||
|
|
|
@ -116,7 +116,7 @@ WSWindow& WSMenu::ensure_menu_window()
|
|||
next_item_location.move_by(0, height);
|
||||
}
|
||||
|
||||
auto window = make<WSWindow>(*this, WSWindowType::Menu);
|
||||
auto window = WSWindow::construct(*this, WSWindowType::Menu);
|
||||
window->set_rect(0, 0, width, height());
|
||||
m_menu_window = move(window);
|
||||
draw();
|
||||
|
|
|
@ -88,5 +88,5 @@ private:
|
|||
WSMenuBar* m_menubar { nullptr };
|
||||
WSMenuItem* m_hovered_item { nullptr };
|
||||
NonnullOwnPtrVector<WSMenuItem> m_items;
|
||||
OwnPtr<WSWindow> m_menu_window;
|
||||
RefPtr<WSWindow> m_menu_window;
|
||||
};
|
||||
|
|
|
@ -27,7 +27,7 @@ WSMenuManager::~WSMenuManager()
|
|||
|
||||
void WSMenuManager::setup()
|
||||
{
|
||||
m_window = make<WSWindow>(*this, WSWindowType::Menubar);
|
||||
m_window = WSWindow::construct(*this, WSWindowType::Menubar);
|
||||
m_window->set_rect(WSWindowManager::the().menubar_rect());
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ private:
|
|||
void draw();
|
||||
void tick_clock();
|
||||
|
||||
OwnPtr<WSWindow> m_window;
|
||||
RefPtr<WSWindow> m_window;
|
||||
WSCPUMonitor m_cpu_monitor;
|
||||
String m_username;
|
||||
ObjectPtr<CTimer> m_timer;
|
||||
|
|
|
@ -328,7 +328,7 @@ void WSWindow::request_update(const Rect& rect)
|
|||
void WSWindow::popup_window_menu(const Point& position)
|
||||
{
|
||||
if (!m_window_menu) {
|
||||
m_window_menu = make<WSMenu>(nullptr, -1, "(Window Menu)");
|
||||
m_window_menu = WSMenu::construct(nullptr, -1, "(Window Menu)");
|
||||
m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 1, "Minimize"));
|
||||
m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, 2, "Unminimize"));
|
||||
m_window_menu->add_item(make<WSMenuItem>(*m_window_menu, WSMenuItem::Type::Separator));
|
||||
|
|
|
@ -182,5 +182,5 @@ private:
|
|||
unsigned m_wm_event_mask { 0 };
|
||||
DisjointRectSet m_pending_paint_rects;
|
||||
Rect m_unmaximized_rect;
|
||||
OwnPtr<WSMenu> m_window_menu;
|
||||
RefPtr<WSMenu> m_window_menu;
|
||||
};
|
||||
|
|
|
@ -57,7 +57,7 @@ WSWindowManager::WSWindowManager()
|
|||
};
|
||||
|
||||
u8 system_menu_name[] = { 0xc3, 0xb8, 0 };
|
||||
m_system_menu = make<WSMenu>(nullptr, -1, String((const char*)system_menu_name));
|
||||
m_system_menu = WSMenu::construct(nullptr, -1, String((const char*)system_menu_name));
|
||||
|
||||
int appIndex = 1;
|
||||
for (const auto& app : apps) {
|
||||
|
|
|
@ -248,7 +248,7 @@ private:
|
|||
|
||||
u8 m_keyboard_modifiers { 0 };
|
||||
|
||||
OwnPtr<WSMenu> m_system_menu;
|
||||
RefPtr<WSMenu> m_system_menu;
|
||||
Color m_menu_selection_color;
|
||||
WeakPtr<WSMenuBar> m_current_menubar;
|
||||
WeakPtr<WSMenu> m_current_menu;
|
||||
|
|
|
@ -135,7 +135,7 @@ void WSWindowSwitcher::refresh()
|
|||
m_rect.set_height(window_count * item_height() + padding() * 2);
|
||||
m_rect.center_within(WSScreen::the().rect());
|
||||
if (!m_switcher_window)
|
||||
m_switcher_window = make<WSWindow>(*this, WSWindowType::WindowSwitcher);
|
||||
m_switcher_window = WSWindow::construct(*this, WSWindowType::WindowSwitcher);
|
||||
m_switcher_window->set_rect(m_rect);
|
||||
draw();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
WSWindow* switcher_window() { return m_switcher_window.ptr(); }
|
||||
|
||||
private:
|
||||
OwnPtr<WSWindow> m_switcher_window;
|
||||
RefPtr<WSWindow> m_switcher_window;
|
||||
Rect m_rect;
|
||||
bool m_visible { false };
|
||||
Vector<WeakPtr<WSWindow>> m_windows;
|
||||
|
|
|
@ -24,7 +24,7 @@ int main(int, char**)
|
|||
WSScreen screen(wm_config->read_num_entry("Screen", "Width", 1024),
|
||||
wm_config->read_num_entry("Screen", "Height", 768));
|
||||
WSCompositor::the();
|
||||
WSWindowManager window_manager;
|
||||
auto wm = WSWindowManager::construct();
|
||||
|
||||
dbgprintf("Entering WindowServer main loop.\n");
|
||||
loop.exec();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue