diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index f60fb600..fab353c0 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -26,6 +26,7 @@ const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args] dispatch keyword version + kill reload)#"; void request(std::string arg) { @@ -129,6 +130,7 @@ int main(int argc, char** argv) { else if (!strcmp(argv[1], "activewindow")) request("activewindow"); else if (!strcmp(argv[1], "layers")) request("layers"); else if (!strcmp(argv[1], "version")) request("version"); + else if (!strcmp(argv[1], "kill")) request("kill"); else if (!strcmp(argv[1], "devices")) request("devices"); else if (!strcmp(argv[1], "reload")) request("reload"); else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv); diff --git a/src/Window.cpp b/src/Window.cpp index 3d669e70..fc09b330 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -77,4 +77,16 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() { void CWindow::updateWindowDecos() { for (auto& wd : m_dWindowDecorations) wd->updateWindow(this); -} \ No newline at end of file +} + +pid_t CWindow::getPID() { + pid_t PID = -1; + if (!m_bIsX11) { + const auto CLIENT = wl_resource_get_client(m_uSurface.xdg->resource); + wl_client_get_credentials(CLIENT, &PID, nullptr, nullptr); + } else { + PID = m_uSurface.xwayland->pid; + } + + return PID; +} diff --git a/src/Window.hpp b/src/Window.hpp index 8b8cc9c8..9bd44ae0 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -112,5 +112,6 @@ public: wlr_box getFullWindowBoundingBox(); wlr_box getWindowIdealBoundingBoxIgnoreReserved(); void updateWindowDecos(); + pid_t getPID(); }; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index df6234f0..b178fdbf 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -27,16 +27,8 @@ std::string clientsRequest() { std::string result = ""; for (auto& w : g_pCompositor->m_lWindows) { if (w.m_bIsMapped) { - pid_t PID = -1; - if (!w.m_bIsX11) { - const auto CLIENT = wl_resource_get_client(w.m_uSurface.xdg->resource); - wl_client_get_credentials(CLIENT, &PID, nullptr, nullptr); - } else { - PID = w.m_uSurface.xwayland->pid; - } - result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n", - &w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w.m_iWorkspaceID)).c_str()), (int)w.m_bIsFloating, w.m_iMonitorID, g_pXWaylandManager->getAppIDClass(&w).c_str(), g_pXWaylandManager->getTitle(&w).c_str(), PID); + &w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w.m_iWorkspaceID)).c_str()), (int)w.m_bIsFloating, w.m_iMonitorID, g_pXWaylandManager->getAppIDClass(&w).c_str(), g_pXWaylandManager->getTitle(&w).c_str(), w.getPID()); } } @@ -58,16 +50,8 @@ std::string activeWindowRequest() { if (!g_pCompositor->windowValidMapped(PWINDOW)) return "Invalid"; - pid_t PID = -1; - if (!PWINDOW->m_bIsX11) { - const auto CLIENT = wl_resource_get_client(PWINDOW->m_uSurface.xdg->resource); - wl_client_get_credentials(CLIENT, &PID, nullptr, nullptr); - } else { - PID = PWINDOW->m_uSurface.xwayland->pid; - } - return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n", - PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), g_pXWaylandManager->getTitle(PWINDOW).c_str(), PID); + PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), g_pXWaylandManager->getTitle(PWINDOW).c_str(), PWINDOW->getPID()); } std::string layersRequest() { @@ -191,6 +175,12 @@ std::string reloadRequest() { return "ok"; } +std::string killRequest() { + g_pInputManager->setClickMode(CLICKMODE_KILL); + + return "ok"; +} + std::string getReply(std::string); std::string dispatchBatch(std::string request) { @@ -232,6 +222,8 @@ std::string getReply(std::string request) { return workspacesRequest(); else if (request == "clients") return clientsRequest(); + else if (request == "kill") + return killRequest(); else if (request == "activewindow") return activeWindowRequest(); else if (request == "layers") diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index df4501cf..adbe268e 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -57,17 +57,7 @@ void Events::listener_mouseAxis(wl_listener* listener, void* data) { void Events::listener_requestMouse(wl_listener* listener, void* data) { const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data; - if (!g_pHyprRenderer->shouldRenderCursor()) - return; - - if (!EVENT->surface) { - g_pHyprRenderer->m_bWindowRequestedCursorHide = true; - } else { - g_pHyprRenderer->m_bWindowRequestedCursorHide = false; - } - - if (EVENT->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) - wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, EVENT->surface, EVENT->hotspot_x, EVENT->hotspot_y); + g_pInputManager->processMouseRequest(EVENT); } void Events::listener_newInput(wl_listener* listener, void* data) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 10694e1b..aab79458 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -108,7 +108,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t return found; } -bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) { +bool CKeybindManager::handleVT(xkb_keysym_t keysym) { // Handles the CTRL+ALT+FX TTY keybinds if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12)) return false; @@ -119,19 +119,36 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) { wlr_session_change_vt(PSESSION, TTY); for (auto& m : g_pCompositor->m_lMonitors) { - g_pHyprOpenGL->destroyMonitorResources(&m); // mark resources as unusable anymore + g_pHyprOpenGL->destroyMonitorResources(&m); // mark resources as unusable anymore m.noFrameSchedule = true; m.framesToSkip = 2; } Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY); - + return true; } return false; } +bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) { + if (handleVT(keysym)) + return true; + + // handle ESC while in kill mode + if (g_pInputManager->getClickMode() == CLICKMODE_KILL) { + const auto KBKEY = xkb_keysym_from_name("ESCAPE", XKB_KEYSYM_CASE_INSENSITIVE); + + if (keysym == KBKEY) { + g_pInputManager->setClickMode(CLICKMODE_DEFAULT); + return true; + } + } + + return false; +} + // Dispatchers void CKeybindManager::spawn(std::string args) { diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index c9132a11..117a5ec4 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -33,6 +33,7 @@ private: inline static std::string m_szCurrentSelectedSubmap = ""; bool handleInternalKeybinds(xkb_keysym_t); + bool handleVT(xkb_keysym_t); // -------------- Dispatchers -------------- // static void killActive(std::string); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index f99c6ab4..e5780608 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -164,7 +164,10 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords); if (!foundSurface) { - wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor); + if (m_ecbClickBehavior == CLICKMODE_KILL) + wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor); + else + wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor); wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat); @@ -211,10 +214,70 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) { m_tmrLastCursorMovement.reset(); + switch (m_ecbClickBehavior) { + case CLICKMODE_DEFAULT: + processMouseDownNormal(e); + break; + case CLICKMODE_KILL: + processMouseDownKill(e); + break; + default: + break; + } +} + +void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e) { + if (!g_pHyprRenderer->shouldRenderCursor()) + return; + + if (!e->surface) { + g_pHyprRenderer->m_bWindowRequestedCursorHide = true; + } else { + g_pHyprRenderer->m_bWindowRequestedCursorHide = false; + } + + if (m_ecbClickBehavior == CLICKMODE_KILL) { + wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor); + return; + } + + if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, e->surface, e->hotspot_x, e->hotspot_y); +} + +eClickBehaviorMode CInputManager::getClickMode() { + return m_ecbClickBehavior; +} + +void CInputManager::setClickMode(eClickBehaviorMode mode) { + switch (mode) { + case CLICKMODE_DEFAULT: + Debug::log(LOG, "SetClickMode: DEFAULT"); + m_ecbClickBehavior = CLICKMODE_DEFAULT; + wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", g_pCompositor->m_sWLRCursor); + break; + + case CLICKMODE_KILL: + Debug::log(LOG, "SetClickMode: KILL"); + m_ecbClickBehavior = CLICKMODE_KILL; + + // remove constraints + g_pCompositor->m_sSeat.mouse->constraintActive = false; + refocus(); + + // set cursor + wlr_xcursor_manager_set_cursor_image(g_pCompositor->m_sWLRXCursorMgr, "crosshair", g_pCompositor->m_sWLRCursor); + break; + default: + break; + } +} + +void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { const auto PKEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat); - if (!PKEYBOARD) { // ??? - Debug::log(ERR, "No active keyboard in onMouseButton??"); + if (!PKEYBOARD) { // ??? + Debug::log(ERR, "No active keyboard in processMouseDownNormal??"); return; } @@ -242,7 +305,7 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) { currentlyDraggedWindow = nullptr; dragButton = -1; } - + break; } @@ -250,7 +313,30 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) { if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) { wlr_seat_pointer_notify_button(g_pCompositor->m_sSeat.seat, e->time_msec, e->button, e->state); } - +} + +void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) { + switch (e->state) { + case WLR_BUTTON_PRESSED: { + const auto PWINDOW = g_pCompositor->m_pLastWindow; + + if (!g_pCompositor->windowValidMapped(PWINDOW)){ + Debug::log(ERR, "Cannot kill invalid window!"); + break; + } + + // kill the mf + kill(PWINDOW->getPID(), SIGKILL); + break; + } + case WLR_BUTTON_RELEASED: + break; + default: + break; + } + + // reset click behavior mode + m_ecbClickBehavior = CLICKMODE_DEFAULT; } Vector2D CInputManager::getMouseCoordsInternal() { diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 73c59b8f..5089e5e1 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -6,6 +6,11 @@ #include "../../Window.hpp" #include "../../helpers/Timer.hpp" +enum eClickBehaviorMode { + CLICKMODE_DEFAULT = 0, + CLICKMODE_KILL +}; + class CInputManager { public: @@ -31,6 +36,10 @@ public: void updateDragIcon(); void updateCapabilities(wlr_input_device*); + void setClickMode(eClickBehaviorMode); + eClickBehaviorMode getClickMode(); + void processMouseRequest(wlr_seat_pointer_request_set_cursor_event*); + // for dragging floating windows CWindow* currentlyDraggedWindow = nullptr; @@ -57,6 +66,12 @@ public: private: + // for click behavior override + eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT; + + void processMouseDownNormal(wlr_pointer_button_event* e); + void processMouseDownKill(wlr_pointer_button_event* e); + uint32_t m_uiCapabilities = 0; void mouseMoveUnified(uint32_t, bool refocus = false);