diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c0059836..228723ca 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -95,6 +95,9 @@ void CCompositor::startCompositor() { // Init all the managers BEFORE we start with the wayland server so that ALL of the stuff is initialized // properly and we dont get any bad mem reads. // + Debug::log(LOG, "Creating the KeybindManager!"); + g_pKeybindManager = std::make_unique(); + Debug::log(LOG, "Creating the ConfigManager!"); g_pConfigManager = std::make_unique(); @@ -196,6 +199,16 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) { return nullptr; } +CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { + for (auto& w : m_lWindows) { + wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; + if (wlr_box_contains_point(&box, pos.x, pos.y)) + return &w; + } + + return nullptr; +} + void CCompositor::focusWindow(CWindow* pWindow) { if (!pWindow) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 7fd26b38..70517aa6 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -12,6 +12,7 @@ #include "managers/XWaylandManager.hpp" #include "managers/InputManager.hpp" #include "managers/LayoutManager.hpp" +#include "managers/KeybindManager.hpp" #include "helpers/Monitor.hpp" #include "Window.hpp" #include "render/Renderer.hpp" @@ -62,6 +63,7 @@ public: bool windowExists(CWindow*); bool windowValidMapped(CWindow*); CWindow* vectorToWindow(const Vector2D&); + CWindow* vectorToWindowIdeal(const Vector2D&); private: void initAllSignals(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ff37f42e..825101c0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1,4 +1,5 @@ #include "ConfigManager.hpp" +#include "../managers/KeybindManager.hpp" #include #include @@ -128,6 +129,27 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string m_dMonitorRules.push_back(newrule); } +void CConfigManager::handleBind(const std::string& command, const std::string& value) { + // example: + // bind=SUPER,G,exec,dmenu_run + + auto valueCopy = value; + + const auto MOD = g_pKeybindManager->stringToModMask(valueCopy.substr(0, valueCopy.find_first_of(","))); + valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1); + + const auto KEY = valueCopy.substr(0, valueCopy.find_first_of(",")); + valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1); + + const auto HANDLER = valueCopy.substr(0, valueCopy.find_first_of(",")); + valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1); + + const auto COMMAND = valueCopy; + + if (KEY != "") + g_pKeybindManager->addKeybind(SKeybind{KEY, MOD, HANDLER, COMMAND}); +} + void CConfigManager::parseLine(std::string& line) { // first check if its not a comment const auto COMMENTSTART = line.find_first_of('#'); @@ -176,8 +198,12 @@ void CConfigManager::parseLine(std::string& line) { } else if (COMMAND == "monitor") { handleMonitor(COMMAND, VALUE); return; + } else if (COMMAND == "bind") { + handleBind(COMMAND, VALUE); + return; } + configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE); } diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index b9c58900..2b6a94b7 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -53,6 +53,7 @@ private: void configSetValueSafe(const std::string&, const std::string&); void handleRawExec(const std::string&, const std::string&); void handleMonitor(const std::string&, const std::string&); + void handleBind(const std::string&, const std::string&); }; inline std::unique_ptr g_pConfigManager; \ No newline at end of file diff --git a/src/managers/InputManager.cpp b/src/managers/InputManager.cpp index 492251fd..0f5f1a98 100644 --- a/src/managers/InputManager.cpp +++ b/src/managers/InputManager.cpp @@ -136,14 +136,16 @@ void CInputManager::onKeyboardKey(wlr_event_keyboard_key* e, SKeyboard* pKeyboar wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sWLRSeat); if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) { - // TODO: keybinds - + for (int i = 0; i < syms; ++i) + g_pKeybindManager->handleKeybinds(MODS, keysyms[i]); } else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) { - + // hee hee } wlr_seat_set_keyboard(g_pCompositor->m_sWLRSeat, pKeyboard->keyboard); wlr_seat_keyboard_notify_key(g_pCompositor->m_sWLRSeat, e->time_msec, e->keycode, e->state); + + g_pCompositor->focusWindow(g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal())); } void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp new file mode 100644 index 00000000..f61f6ac9 --- /dev/null +++ b/src/managers/KeybindManager.cpp @@ -0,0 +1,62 @@ +#include "KeybindManager.hpp" + +void CKeybindManager::addKeybind(SKeybind kb) { + m_dKeybinds.push_back(kb); +} + +uint32_t CKeybindManager::stringToModMask(std::string mods) { + uint32_t modMask = 0; + if (mods.find("SHIFT") != std::string::npos) + modMask |= WLR_MODIFIER_SHIFT; + if (mods.find("CAPS") != std::string::npos) + modMask |= WLR_MODIFIER_CAPS; + if (mods.find("CTRL") != std::string::npos || mods.find("CONTROL") != std::string::npos) + modMask |= WLR_MODIFIER_CTRL; + if (mods.find("ALT") != std::string::npos) + modMask |= WLR_MODIFIER_ALT; + if (mods.find("MOD2") != std::string::npos) + modMask |= WLR_MODIFIER_MOD2; + if (mods.find("MOD3") != std::string::npos) + modMask |= WLR_MODIFIER_MOD3; + if (mods.find("SUPER") != std::string::npos || mods.find("WIN") != std::string::npos || mods.find("LOGO") != std::string::npos || mods.find("MOD4") != std::string::npos) + modMask |= WLR_MODIFIER_LOGO; + if (mods.find("MOD5") != std::string::npos) + modMask |= WLR_MODIFIER_MOD5; + + return modMask; +} + +void CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t& key) { + for (auto& k : m_dKeybinds) { + if (modmask != k.modmask) + continue; + + // oMg such performance hit!!11! + // this little maneouver is gonna cost us 4µs + const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); + + if (key != KBKEY) + continue; + + // yes. + if (k.handler == "exec") { spawn(k.arg); } + else if (k.handler == "killactive") { killActive(k.arg); } + } +} + +// Dispatchers + +void CKeybindManager::spawn(std::string args) { + args = "WAYLAND_DISPLAY=" + std::string(g_pCompositor->m_szWLDisplaySocket) + " DISPLAY=" + std::string(g_pXWaylandManager->m_sWLRXWayland->display_name) + " " + args; + Debug::log(LOG, "Executing %s", args.c_str()); + if (fork() == 0) { + execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr); + + _exit(0); + } +} + +void CKeybindManager::killActive(std::string args) { + if (g_pCompositor->m_pLastFocus && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastFocus)) + g_pXWaylandManager->sendCloseWindow(g_pCompositor->m_pLastFocus); +} \ No newline at end of file diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp new file mode 100644 index 00000000..927b9b44 --- /dev/null +++ b/src/managers/KeybindManager.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "../defines.hpp" +#include +#include "../Compositor.hpp" + +struct SKeybind { + std::string key = 0; + uint32_t modmask = 0; + std::string handler = ""; + std::string arg = ""; +}; + +class CKeybindManager { +public: + void handleKeybinds(const uint32_t&, const xkb_keysym_t&); + void addKeybind(SKeybind); + uint32_t stringToModMask(std::string); + +private: + std::deque m_dKeybinds; + + + // -------------- Dispatchers -------------- // + void killActive(std::string); + void spawn(std::string); + +}; + +inline std::unique_ptr g_pKeybindManager; \ No newline at end of file