core: Properly shutdown wl display (#7018)

* correctly destroy wayland globals

* properly shutdown and cleanup hyprland

* appease the nitpick gods and some comments
This commit is contained in:
Ikalco 2024-07-24 12:07:36 -05:00 committed by GitHub
parent 735e3c6c56
commit 3e543d2ce8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 161 additions and 60 deletions

View file

@ -43,7 +43,7 @@ int handleCritSignal(int signo, void* data) {
Debug::log(LOG, "Hyprland received signal {}", signo); Debug::log(LOG, "Hyprland received signal {}", signo);
if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL) if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL)
g_pCompositor->cleanup(); g_pCompositor->stopCompositor();
return 0; return 0;
} }
@ -193,6 +193,7 @@ CCompositor::CCompositor() {
} }
CCompositor::~CCompositor() { CCompositor::~CCompositor() {
if (!m_bIsShuttingDown)
cleanup(); cleanup();
} }
@ -432,8 +433,16 @@ void CCompositor::cleanEnvironment() {
} }
} }
void CCompositor::stopCompositor() {
Debug::log(LOG, "Hyprland is stopping!");
// this stops the wayland loop, wl_display_run
wl_display_terminate(m_sWLDisplay);
m_bIsShuttingDown = true;
}
void CCompositor::cleanup() { void CCompositor::cleanup() {
if (!m_sWLDisplay || m_bIsShuttingDown) if (!m_sWLDisplay)
return; return;
signal(SIGABRT, SIG_DFL); signal(SIGABRT, SIG_DFL);
@ -507,13 +516,8 @@ void CCompositor::cleanup() {
if (m_critSigSource) if (m_critSigSource)
wl_event_source_remove(m_critSigSource); wl_event_source_remove(m_critSigSource);
wl_event_loop_destroy(m_sWLEventLoop); // this frees all wayland resources, including sockets
wl_display_terminate(m_sWLDisplay); wl_display_destroy(m_sWLDisplay);
m_sWLDisplay = nullptr;
std::string waylandSocket = std::string{getenv("XDG_RUNTIME_DIR")} + "/" + m_szWLDisplaySocket;
std::filesystem::remove(waylandSocket);
std::filesystem::remove(waylandSocket + ".lock");
} }
void CCompositor::initManagers(eManagersInitStage stage) { void CCompositor::initManagers(eManagersInitStage stage) {

View file

@ -71,6 +71,7 @@ class CCompositor {
void initServer(std::string socketName, int socketFd); void initServer(std::string socketName, int socketFd);
void startCompositor(); void startCompositor();
void stopCompositor();
void cleanup(); void cleanup();
void createLockFile(); void createLockFile();
void removeLockFile(); void removeLockFile();

View file

@ -157,11 +157,9 @@ int main(int argc, char** argv) {
// If all's good to go, start. // If all's good to go, start.
g_pCompositor->startCompositor(); g_pCompositor->startCompositor();
g_pCompositor->m_bIsShuttingDown = true; g_pCompositor->cleanup();
// If we are here it means we got yote. Debug::log(LOG, "Hyprland has reached the end.");
Debug::log(LOG, "Hyprland reached the end.");
g_pCompositor.reset();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -1662,7 +1662,7 @@ void CKeybindManager::renameWorkspace(std::string args) {
} }
void CKeybindManager::exitHyprland(std::string argz) { void CKeybindManager::exitHyprland(std::string argz) {
g_pEventLoopManager->doLater([]() { g_pCompositor->cleanup(); }); g_pCompositor->stopCompositor();
} }
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) { void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {

View file

@ -166,3 +166,57 @@ CProtocolManager::CProtocolManager() {
m_pGlobalShortcutsProtocolManager = std::make_unique<CGlobalShortcutsProtocolManager>(); m_pGlobalShortcutsProtocolManager = std::make_unique<CGlobalShortcutsProtocolManager>();
m_pScreencopyProtocolManager = std::make_unique<CScreencopyProtocolManager>(); m_pScreencopyProtocolManager = std::make_unique<CScreencopyProtocolManager>();
} }
CProtocolManager::~CProtocolManager() {
// this is dumb but i don't want to replace all 600 PROTO with the right thing
// Output
PROTO::outputs.clear();
// Core
PROTO::seat.reset();
PROTO::data.reset();
PROTO::compositor.reset();
PROTO::subcompositor.reset();
PROTO::shm.reset();
// Extensions
PROTO::viewport.reset();
PROTO::tearing.reset();
PROTO::fractional.reset();
PROTO::xdgOutput.reset();
PROTO::cursorShape.reset();
PROTO::idleInhibit.reset();
PROTO::relativePointer.reset();
PROTO::xdgDecoration.reset();
PROTO::alphaModifier.reset();
PROTO::gamma.reset();
PROTO::foreignToplevel.reset();
PROTO::pointerGestures.reset();
PROTO::foreignToplevelWlr.reset();
PROTO::shortcutsInhibit.reset();
PROTO::textInputV3.reset();
PROTO::constraints.reset();
PROTO::outputPower.reset();
PROTO::activation.reset();
PROTO::idle.reset();
PROTO::sessionLock.reset();
PROTO::ime.reset();
PROTO::virtualKeyboard.reset();
PROTO::virtualPointer.reset();
PROTO::outputManagement.reset();
PROTO::serverDecorationKDE.reset();
PROTO::focusGrab.reset();
PROTO::tablet.reset();
PROTO::layerShell.reset();
PROTO::presentation.reset();
PROTO::xdgShell.reset();
PROTO::dataWlr.reset();
PROTO::primarySelection.reset();
PROTO::xwaylandShell.reset();
PROTO::lease.reset();
PROTO::sync.reset();
PROTO::mesaDRM.reset();
PROTO::linuxDma.reset();
}

View file

@ -12,6 +12,7 @@
class CProtocolManager { class CProtocolManager {
public: public:
CProtocolManager(); CProtocolManager();
~CProtocolManager();
// TODO: rewrite to use the new protocol framework // TODO: rewrite to use the new protocol framework
std::unique_ptr<CToplevelExportProtocolManager> m_pToplevelExportProtocolManager; std::unique_ptr<CToplevelExportProtocolManager> m_pToplevelExportProtocolManager;

View file

@ -19,8 +19,14 @@ CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEvent
} }
CEventLoopManager::~CEventLoopManager() { CEventLoopManager::~CEventLoopManager() {
for (auto& eventSource : m_sWayland.aqEventSources) {
wl_event_source_remove(eventSource);
}
if (m_sWayland.eventSource) if (m_sWayland.eventSource)
wl_event_source_remove(m_sWayland.eventSource); wl_event_source_remove(m_sWayland.eventSource);
if (m_sIdle.eventSource)
wl_event_source_remove(m_sIdle.eventSource);
} }
static int timerWrite(int fd, uint32_t mask, void* data) { static int timerWrite(int fd, uint32_t mask, void* data) {

View file

@ -8,13 +8,20 @@ static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint
} }
static void handleDisplayDestroy(struct wl_listener* listener, void* data) { static void handleDisplayDestroy(struct wl_listener* listener, void* data) {
g_pProtocolManager->m_pGlobalShortcutsProtocolManager->displayDestroy(); CGlobalShortcutsProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy);
proto->displayDestroy();
} }
void CGlobalShortcutsProtocolManager::displayDestroy() { void CGlobalShortcutsProtocolManager::displayDestroy() {
wl_list_remove(&m_liDisplayDestroy.link);
wl_list_init(&m_liDisplayDestroy.link);
wl_global_destroy(m_pGlobal); wl_global_destroy(m_pGlobal);
} }
CGlobalShortcutsProtocolManager::~CGlobalShortcutsProtocolManager() {
displayDestroy();
}
CGlobalShortcutsProtocolManager::CGlobalShortcutsProtocolManager() { CGlobalShortcutsProtocolManager::CGlobalShortcutsProtocolManager() {
m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &hyprland_global_shortcuts_manager_v1_interface, GLOBAL_SHORTCUTS_VERSION, this, bindManagerInt); m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &hyprland_global_shortcuts_manager_v1_interface, GLOBAL_SHORTCUTS_VERSION, this, bindManagerInt);

View file

@ -17,6 +17,8 @@ struct SShortcutClient {
class CGlobalShortcutsProtocolManager { class CGlobalShortcutsProtocolManager {
public: public:
CGlobalShortcutsProtocolManager(); CGlobalShortcutsProtocolManager();
~CGlobalShortcutsProtocolManager();
void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id);
void displayDestroy(); void displayDestroy();
@ -29,11 +31,12 @@ class CGlobalShortcutsProtocolManager {
std::vector<SShortcut> getAllShortcuts(); std::vector<SShortcut> getAllShortcuts();
wl_listener m_liDisplayDestroy;
private: private:
std::vector<std::unique_ptr<SShortcutClient>> m_vClients; std::vector<std::unique_ptr<SShortcutClient>> m_vClients;
SShortcutClient* clientFromWlClient(wl_client* client); SShortcutClient* clientFromWlClient(wl_client* client);
wl_global* m_pGlobal = nullptr; wl_global* m_pGlobal = nullptr;
wl_listener m_liDisplayDestroy;
}; };

View file

@ -16,15 +16,22 @@ static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint
} }
static void handleDisplayDestroy(struct wl_listener* listener, void* data) { static void handleDisplayDestroy(struct wl_listener* listener, void* data) {
g_pProtocolManager->m_pScreencopyProtocolManager->displayDestroy(); CScreencopyProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy);
proto->displayDestroy();
} }
void CScreencopyProtocolManager::displayDestroy() { void CScreencopyProtocolManager::displayDestroy() {
wl_list_remove(&m_liDisplayDestroy.link);
wl_list_init(&m_liDisplayDestroy.link);
wl_global_destroy(m_pGlobal); wl_global_destroy(m_pGlobal);
} }
static SScreencopyFrame* frameFromResource(wl_resource*); static SScreencopyFrame* frameFromResource(wl_resource*);
CScreencopyProtocolManager::~CScreencopyProtocolManager() {
displayDestroy();
}
CScreencopyProtocolManager::CScreencopyProtocolManager() { CScreencopyProtocolManager::CScreencopyProtocolManager() {
m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &zwlr_screencopy_manager_v1_interface, SCREENCOPY_VERSION, this, bindManagerInt); m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &zwlr_screencopy_manager_v1_interface, SCREENCOPY_VERSION, this, bindManagerInt);

View file

@ -70,6 +70,7 @@ struct SScreencopyFrame {
class CScreencopyProtocolManager { class CScreencopyProtocolManager {
public: public:
CScreencopyProtocolManager(); CScreencopyProtocolManager();
~CScreencopyProtocolManager();
void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id);
void removeClient(CScreencopyClient* client, bool force = false); void removeClient(CScreencopyClient* client, bool force = false);
@ -82,6 +83,8 @@ class CScreencopyProtocolManager {
void onOutputCommit(CMonitor* pMonitor); void onOutputCommit(CMonitor* pMonitor);
wl_listener m_liDisplayDestroy;
private: private:
wl_global* m_pGlobal = nullptr; wl_global* m_pGlobal = nullptr;
std::list<SScreencopyFrame> m_lFrames; std::list<SScreencopyFrame> m_lFrames;
@ -90,8 +93,6 @@ class CScreencopyProtocolManager {
SP<CEventLoopTimer> m_pSoftwareCursorTimer; SP<CEventLoopTimer> m_pSoftwareCursorTimer;
bool m_bTimerArmed = false; bool m_bTimerArmed = false;
wl_listener m_liDisplayDestroy;
std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite; std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite;
SP<Aquamarine::IBuffer> m_pLastMonitorBackBuffer; SP<Aquamarine::IBuffer> m_pLastMonitorBackBuffer;

View file

@ -10,13 +10,20 @@ static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint
} }
static void handleDisplayDestroy(struct wl_listener* listener, void* data) { static void handleDisplayDestroy(struct wl_listener* listener, void* data) {
g_pProtocolManager->m_pTextInputV1ProtocolManager->displayDestroy(); CTextInputV1ProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy);
proto->displayDestroy();
} }
void CTextInputV1ProtocolManager::displayDestroy() { void CTextInputV1ProtocolManager::displayDestroy() {
wl_list_remove(&m_liDisplayDestroy.link);
wl_list_init(&m_liDisplayDestroy.link);
wl_global_destroy(m_pGlobal); wl_global_destroy(m_pGlobal);
} }
CTextInputV1ProtocolManager::~CTextInputV1ProtocolManager() {
displayDestroy();
}
CTextInputV1ProtocolManager::CTextInputV1ProtocolManager() { CTextInputV1ProtocolManager::CTextInputV1ProtocolManager() {
m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &zwp_text_input_manager_v1_interface, TEXT_INPUT_VERSION, this, bindManagerInt); m_pGlobal = wl_global_create(g_pCompositor->m_sWLDisplay, &zwp_text_input_manager_v1_interface, TEXT_INPUT_VERSION, this, bindManagerInt);

View file

@ -47,6 +47,7 @@ struct STextInputV1 {
class CTextInputV1ProtocolManager { class CTextInputV1ProtocolManager {
public: public:
CTextInputV1ProtocolManager(); CTextInputV1ProtocolManager();
~CTextInputV1ProtocolManager();
void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id);
void createTI(wl_client* client, wl_resource* resource, uint32_t id); void createTI(wl_client* client, wl_resource* resource, uint32_t id);
@ -67,9 +68,10 @@ class CTextInputV1ProtocolManager {
void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial); void handleCommitState(wl_client* client, wl_resource* resource, uint32_t serial);
void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index); void handleInvokeAction(wl_client* client, wl_resource* resource, uint32_t button, uint32_t index);
wl_listener m_liDisplayDestroy;
private: private:
wl_global* m_pGlobal = nullptr; wl_global* m_pGlobal = nullptr;
wl_listener m_liDisplayDestroy;
std::vector<std::unique_ptr<STextInputV1>> m_pClients; std::vector<std::unique_ptr<STextInputV1>> m_pClients;
}; };

View file

@ -15,13 +15,20 @@ static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint
} }
static void handleDisplayDestroy(struct wl_listener* listener, void* data) { static void handleDisplayDestroy(struct wl_listener* listener, void* data) {
g_pProtocolManager->m_pToplevelExportProtocolManager->displayDestroy(); CToplevelExportProtocolManager* proto = wl_container_of(listener, proto, m_liDisplayDestroy);
proto->displayDestroy();
} }
void CToplevelExportProtocolManager::displayDestroy() { void CToplevelExportProtocolManager::displayDestroy() {
wl_list_remove(&m_liDisplayDestroy.link);
wl_list_init(&m_liDisplayDestroy.link);
wl_global_destroy(m_pGlobal); wl_global_destroy(m_pGlobal);
} }
CToplevelExportProtocolManager::~CToplevelExportProtocolManager() {
displayDestroy();
}
CToplevelExportProtocolManager::CToplevelExportProtocolManager() { CToplevelExportProtocolManager::CToplevelExportProtocolManager() {
#ifndef GLES32 #ifndef GLES32

View file

@ -13,6 +13,7 @@ class CWindow;
class CToplevelExportProtocolManager { class CToplevelExportProtocolManager {
public: public:
CToplevelExportProtocolManager(); CToplevelExportProtocolManager();
~CToplevelExportProtocolManager();
void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id);
void captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, PHLWINDOW handle); void captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, PHLWINDOW handle);
@ -23,13 +24,13 @@ class CToplevelExportProtocolManager {
void onWindowUnmap(PHLWINDOW pWindow); void onWindowUnmap(PHLWINDOW pWindow);
void onOutputCommit(CMonitor* pMonitor); void onOutputCommit(CMonitor* pMonitor);
wl_listener m_liDisplayDestroy;
private: private:
wl_global* m_pGlobal = nullptr; wl_global* m_pGlobal = nullptr;
std::list<SScreencopyFrame> m_lFrames; std::list<SScreencopyFrame> m_lFrames;
std::list<CScreencopyClient> m_lClients; std::list<CScreencopyClient> m_lClients;
wl_listener m_liDisplayDestroy;
std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite; std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite;
void shareFrame(SScreencopyFrame* frame); void shareFrame(SScreencopyFrame* frame);

View file

@ -6,7 +6,8 @@ static void bindManagerInternal(wl_client* client, void* data, uint32_t ver, uin
} }
static void displayDestroyInternal(struct wl_listener* listener, void* data) { static void displayDestroyInternal(struct wl_listener* listener, void* data) {
((IWaylandProtocol*)data)->onDisplayDestroy(); IWaylandProtocol* proto = wl_container_of(listener, proto, m_liDisplayDestroy);
proto->onDisplayDestroy();
} }
void IWaylandProtocol::onDisplayDestroy() { void IWaylandProtocol::onDisplayDestroy() {

View file

@ -26,8 +26,9 @@ class IWaylandProtocol {
Debug::log(level, std::format("[{}] ", m_szName) + std::vformat(fmt.get(), std::make_format_args(args...))); Debug::log(level, std::format("[{}] ", m_szName) + std::vformat(fmt.get(), std::make_format_args(args...)));
}; };
wl_listener m_liDisplayDestroy;
private: private:
std::string m_szName; std::string m_szName;
wl_global* m_pGlobal = nullptr; wl_global* m_pGlobal = nullptr;
wl_listener m_liDisplayDestroy;
}; };