diff --git a/example/hyprland.conf b/example/hyprland.conf index 9dbcb070..6c4a7b4a 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -8,6 +8,8 @@ monitor=,1280x720@60,0x0,0.5,1 general { max_fps=240 sensitivity=0.25 + main_mod=SUPER + gaps_in=5 gaps_out=20 border_size=1 diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 559d4164..7ccc6ce8 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -204,6 +204,14 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) { CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { const auto PMONITOR = getMonitorFromCursor(); + // first loop over floating cuz they're above + // TODO: make an actual Z-system + for (auto& w : m_lWindows) { + wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y}; + if (w.m_iMonitorID == PMONITOR->ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsFloating) + return &w; + } + 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 (w.m_iMonitorID == PMONITOR->ID && wlr_box_contains_point(&box, pos.x, pos.y)) @@ -215,6 +223,15 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { CWindow* CCompositor::windowFromCursor() { const auto PMONITOR = getMonitorFromCursor(); + + // first loop over floating cuz they're above + // TODO: make an actual Z-system + for (auto& w : m_lWindows) { + wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y}; + if (w.m_iMonitorID == PMONITOR->ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsFloating) + return &w; + } + 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 (w.m_iMonitorID == PMONITOR->ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y)) @@ -224,6 +241,17 @@ CWindow* CCompositor::windowFromCursor() { return nullptr; } +CWindow* CCompositor::windowFloatingFromCursor() { + const auto PMONITOR = getMonitorFromCursor(); + for (auto& w : m_lWindows) { + wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y}; + if (w.m_iMonitorID == PMONITOR->ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsFloating) + return &w; + } + + return nullptr; +} + SMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { for (auto& m : m_lMonitors) { if (m.output == out) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index d8175fea..42046990 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -66,6 +66,7 @@ public: CWindow* vectorToWindow(const Vector2D&); CWindow* vectorToWindowIdeal(const Vector2D&); CWindow* windowFromCursor(); + CWindow* windowFloatingFromCursor(); SMonitor* getMonitorFromOutput(wlr_output*); private: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index d53342b9..a0aa4cdf 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -13,6 +13,8 @@ CConfigManager::CConfigManager() { configValues["general:max_fps"].intValue = 240; configValues["general:sensitivity"].floatValue = 0.25f; + configValues["general:main_mod"].strValue = "SUPER"; // exposed to the user for easier configuring + configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask("SUPER"); // actually used and automatically calculated configValues["general:border_size"].intValue = 1; configValues["general:gaps_in"].intValue = 5; @@ -259,6 +261,9 @@ void CConfigManager::loadConfigLoadVars() { for (auto& m : g_pCompositor->m_lMonitors) g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID); + + // Calculate the mod mask for main_mod + configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask(configValues["general:main_mod"].strValue); } void CConfigManager::tick() { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index d69defc9..b6d65f9b 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -12,7 +12,7 @@ struct SMonitor { bool primary = false; - int ID = -1; + uint64_t ID = -1; std::string szName = ""; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 12650963..2b69e2d9 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -213,11 +213,6 @@ void CHyprDwindleLayout::onWindowRemoved(CWindow* pWindow) { if (!PNODE) return; - if (PNODE->isNode) { - Debug::log(LOG, "WHAT THE FUCKKKKKKKK"); - return; - } - const auto PPARENT = PNODE->pParent; if (!PPARENT) { @@ -258,3 +253,45 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) { TOPNODE->recalcSizePosRecursive(); } } + +void CHyprDwindleLayout::changeWindowFloatingMode(CWindow* pWindow) { + const auto PNODE = getNodeFromWindow(pWindow); + + if (!PNODE) { + onWindowCreated(pWindow); + } else { + onWindowRemoved(pWindow); + } +} + +void CHyprDwindleLayout::onBeginDragWindow() { + const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow; + + // Window will be floating. Let's check if it's valid. It should be, but I don't like crashing. + if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) { + Debug::log(ERR, "Dragging attempted on an invalid window!"); + return; + } + + m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal(); + m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition; + m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize; +} + +void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) { + const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow; + + if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) + return; + + const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y); + + if (g_pInputManager->dragButton == BTN_LEFT) { + DRAGGINGWINDOW->m_vRealPosition = m_vBeginDragPositionXY + DELTA; + } else { + DRAGGINGWINDOW->m_vRealSize = m_vBeginDragSizeXY + DELTA; + DRAGGINGWINDOW->m_vRealSize = Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.y, (double)20, (double)999999)); + + g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize); + } +} \ No newline at end of file diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index cb3e4a68..b9136727 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -32,11 +32,18 @@ public: virtual void onWindowCreated(CWindow*); virtual void onWindowRemoved(CWindow*); virtual void recalculateMonitor(const int&); + virtual void changeWindowFloatingMode(CWindow*); + virtual void onBeginDragWindow(); + virtual void onMouseMove(const Vector2D&); -private: + private: std::list m_lDwindleNodesData; + Vector2D m_vBeginDragXY; + Vector2D m_vBeginDragPositionXY; + Vector2D m_vBeginDragSizeXY; + int getNodesOnMonitor(const int&); void applyNodeDataToWindow(SDwindleNodeData*); SDwindleNodeData* getNodeFromWindow(CWindow*); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 2a7ff3aa..bf0d135b 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -6,8 +6,13 @@ interface IHyprLayout { public: - virtual void onWindowCreated(CWindow*) = 0; - virtual void onWindowRemoved(CWindow*) = 0; - virtual void recalculateMonitor(const int&) = 0; + virtual void onWindowCreated(CWindow*) = 0; + virtual void onWindowRemoved(CWindow*) = 0; + virtual void recalculateMonitor(const int&) = 0; + + // Floating windows + virtual void changeWindowFloatingMode(CWindow*) = 0; + virtual void onBeginDragWindow() = 0; + virtual void onMouseMove(const Vector2D&) = 0; }; \ No newline at end of file diff --git a/src/managers/InputManager.cpp b/src/managers/InputManager.cpp index ecf63bf2..cc7d302c 100644 --- a/src/managers/InputManager.cpp +++ b/src/managers/InputManager.cpp @@ -41,6 +41,7 @@ void CInputManager::mouseMoveUnified(uint32_t time) { wlr_seat_pointer_notify_motion(g_pCompositor->m_sWLRSeat, time, surfaceLocal.x, surfaceLocal.y); g_pCompositor->m_pLastMonitor = g_pCompositor->getMonitorFromCursor(); + g_pLayoutManager->getCurrentLayout()->onMouseMove(getMouseCoordsInternal()); } void CInputManager::onMouseButton(wlr_event_pointer_button* e) { @@ -48,10 +49,16 @@ void CInputManager::onMouseButton(wlr_event_pointer_button* e) { switch (e->state) { case WLR_BUTTON_PRESSED: - // todo: keybinds + if (e->button == BTN_LEFT || e->button == BTN_RIGHT) { + currentlyDraggedWindow = g_pCompositor->windowFloatingFromCursor(); + dragButton = e->button; + + g_pLayoutManager->getCurrentLayout()->onBeginDragWindow(); + } break; case WLR_BUTTON_RELEASED: - // todo: keybinds + currentlyDraggedWindow = nullptr; + dragButton = -1; break; } diff --git a/src/managers/InputManager.hpp b/src/managers/InputManager.hpp index 75ad75d6..ce1afcea 100644 --- a/src/managers/InputManager.hpp +++ b/src/managers/InputManager.hpp @@ -3,6 +3,7 @@ #include "../defines.hpp" #include #include "../helpers/WLClasses.hpp" +#include "../Window.hpp" class CInputManager { public: @@ -20,6 +21,11 @@ public: Vector2D getMouseCoordsInternal(); + + // for dragging floating windows + CWindow* currentlyDraggedWindow = nullptr; + int dragButton = -1; + private: std::list m_lKeyboards; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index a4206340..96bf65fa 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -42,6 +42,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t // yes. if (k.handler == "exec") { spawn(k.arg); } else if (k.handler == "killactive") { killActive(k.arg); } + else if (k.handler == "togglefloating") { toggleActiveFloating(k.arg); } found = true; } @@ -64,8 +65,19 @@ void CKeybindManager::spawn(std::string args) { 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); + + g_pCompositor->focusWindow(g_pCompositor->windowFromCursor()); } void CKeybindManager::clearKeybinds() { m_dKeybinds.clear(); +} + +void CKeybindManager::toggleActiveFloating(std::string args) { + const auto ACTIVEWINDOW = g_pCompositor->m_pLastFocus; + + if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) { + ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating; + g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(ACTIVEWINDOW); + } } \ No newline at end of file diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 6400b193..5aeb3a05 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -25,6 +25,7 @@ private: // -------------- Dispatchers -------------- // void killActive(std::string); void spawn(std::string); + void toggleActiveFloating(std::string); };