From e9313fe3aa30bd0726a3e1494ef4552d4324e7c1 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Tue, 30 Nov 2021 16:43:28 +0100 Subject: [PATCH] better window killing method --- src/KeybindManager.cpp | 24 +++++++++++++++++++++++- src/events/events.cpp | 3 +++ src/window.cpp | 2 +- src/window.hpp | 3 +++ src/windowManager.cpp | 14 ++++++++++++++ src/windowManager.hpp | 1 + 6 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/KeybindManager.cpp b/src/KeybindManager.cpp index 191955b..e3443f3 100644 --- a/src/KeybindManager.cpp +++ b/src/KeybindManager.cpp @@ -89,7 +89,27 @@ xcb_keycode_t KeybindManager::getKeycodeFromKeysym(xcb_keysym_t keysym) { void KeybindManager::killactive(std::string args) { // args unused - xcb_destroy_window(g_pWindowManager->DisplayConnection, g_pWindowManager->LastWindow); + const auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); + + if (!PLASTWINDOW) + return; + + if (PLASTWINDOW->getCanKill()) { + // Send a kill message + xcb_client_message_event_t event; + bzero(&event, sizeof(event)); + event.response_type = XCB_CLIENT_MESSAGE; + event.window = PLASTWINDOW->getDrawable(); + event.type = HYPRATOMS["WM_PROTOCOLS"]; + event.format = 32; + event.data.data32[0] = HYPRATOMS["WM_DELETE_WINDOW"]; + event.data.data32[1] = 0; + + xcb_send_event(g_pWindowManager->DisplayConnection, 0, PLASTWINDOW->getDrawable(), XCB_EVENT_MASK_NO_EVENT, (const char*)&event); + } else + xcb_kill_client(g_pWindowManager->DisplayConnection, g_pWindowManager->LastWindow); + + g_pWindowManager->closeWindowAllChecks(g_pWindowManager->LastWindow); } void KeybindManager::call(std::string args) { @@ -160,12 +180,14 @@ void KeybindManager::toggleActiveWindowFloating(std::string unusedArg) { const auto RESTOREACSIZE = PWINDOW->getDefaultSize(); const auto RESTOREACPOS = PWINDOW->getDefaultPosition(); const auto RESTOREWINID = PWINDOW->getDrawable(); + const auto RESTORECANKILL = PWINDOW->getCanKill(); g_pWindowManager->removeWindowFromVectorSafe(PWINDOW->getDrawable()); const auto PNEWWINDOW = Events::remapWindow(RESTOREWINID, true); PNEWWINDOW->setDefaultPosition(RESTOREACPOS); PNEWWINDOW->setDefaultSize(RESTOREACSIZE); + PNEWWINDOW->setCanKill(RESTORECANKILL); } } diff --git a/src/events/events.cpp b/src/events/events.cpp index 41000ad..557410e 100644 --- a/src/events/events.cpp +++ b/src/events/events.cpp @@ -308,6 +308,9 @@ void Events::eventMapWindow(xcb_generic_event_t* event) { // Do post-creation checks. g_pWindowManager->doPostCreationChecks(pNewWindow); + + // Do ICCCM + g_pWindowManager->getICCCMWMProtocols(pNewWindow); } void Events::eventButtonPress(xcb_generic_event_t* event) { diff --git a/src/window.cpp b/src/window.cpp index 96e9fc3..620aabd 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1,7 +1,7 @@ #include "window.hpp" #include "windowManager.hpp" -CWindow::CWindow() { this->setImmovable(false); this->setNoInterventions(false); this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); this->setParentNodeID(0); this->setChildNodeAID(0); this->setChildNodeBID(0); this->setName(""); } +CWindow::CWindow() { this->setCanKill(false); this->setImmovable(false); this->setNoInterventions(false); this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); this->setParentNodeID(0); this->setChildNodeAID(0); this->setChildNodeBID(0); this->setName(""); } CWindow::~CWindow() { } void CWindow::generateNodeID() { diff --git a/src/window.hpp b/src/window.hpp index b6dd254..e1adb00 100644 --- a/src/window.hpp +++ b/src/window.hpp @@ -65,6 +65,9 @@ public: // Docks etc EXPOSED_MEMBER(Immovable, bool, b); EXPOSED_MEMBER(NoInterventions, bool, b); + + // ICCCM + EXPOSED_MEMBER(CanKill, bool, b); private: diff --git a/src/windowManager.cpp b/src/windowManager.cpp index 95933bc..e9660e0 100644 --- a/src/windowManager.cpp +++ b/src/windowManager.cpp @@ -1348,4 +1348,18 @@ void CWindowManager::doPostCreationChecks(CWindow* pWindow) { Debug::log(LOG, "Post creation checks ended"); // +} + +void CWindowManager::getICCCMWMProtocols(CWindow* pWindow) { + xcb_icccm_get_wm_protocols_reply_t WMProtocolsReply; + if (!xcb_icccm_get_wm_protocols_reply(DisplayConnection, + xcb_icccm_get_wm_protocols(DisplayConnection, pWindow->getDrawable(), HYPRATOMS["WM_PROTOCOLS"]), &WMProtocolsReply, NULL)) + return; + + for (auto i = 0; i < (int)WMProtocolsReply.atoms_len; i++) { + if (WMProtocolsReply.atoms[i] == HYPRATOMS["WM_DELETE_WINDOW"]) + pWindow->setCanKill(true); + } + + xcb_icccm_get_wm_protocols_reply_wipe(&WMProtocolsReply); } \ No newline at end of file diff --git a/src/windowManager.hpp b/src/windowManager.hpp index 52f8cfe..7e06e44 100644 --- a/src/windowManager.hpp +++ b/src/windowManager.hpp @@ -95,6 +95,7 @@ public: bool shouldBeFloatedOnInit(int64_t); void doPostCreationChecks(CWindow*); + void getICCCMWMProtocols(CWindow*); void setupRandrMonitors(); void createAndOpenAllPipes();