From 0da4b298c5cd6dd082c3c47afd1cdc3a017c6a65 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sun, 3 Apr 2022 22:02:25 +0200 Subject: [PATCH] Added scratchpads. --- example/hypr.conf | 4 ++ src/KeybindManager.cpp | 18 ++++++++- src/KeybindManager.hpp | 1 + src/config/ConfigManager.cpp | 12 +++++- src/defines.hpp | 4 +- src/events/events.cpp | 27 +++++++++---- src/ewmh/ewmh.cpp | 5 +++ src/windowManager.cpp | 77 ++++++++++++++++++++++++++++++++++-- src/windowManager.hpp | 3 ++ 9 files changed, 136 insertions(+), 15 deletions(-) diff --git a/example/hypr.conf b/example/hypr.conf index 56585dc..a2b9af2 100644 --- a/example/hypr.conf +++ b/example/hypr.conf @@ -12,6 +12,7 @@ focus_when_hover=1 # 0 - do not switch the focus when hover (only for tiling) main_mod=SUPER # For moving, resizing intelligent_transients=1 # keeps transients always on top. no_unmap_saving=1 # disables saving unmapped windows (seems to break sometimes) +scratchpad_mon=0 # self-explanatory # Execs # exec-once=/home/me/MyEpicShellScript # will exec the script only when the WM launches @@ -110,6 +111,9 @@ bind=SUPERSHIFT,7,movetoworkspace,7 bind=SUPERSHIFT,8,movetoworkspace,8 bind=SUPERSHIFT,9,movetoworkspace,9 +bind=SUPERSHIFT,S,movetoworkspace,scratchpad +bind=SUPER,S,scratchpad, + bind=SUPER,SPACE,togglefloating, bind=SUPER,equals,splitratio,+ diff --git a/src/KeybindManager.cpp b/src/KeybindManager.cpp index 068e79d..1527f3a 100644 --- a/src/KeybindManager.cpp +++ b/src/KeybindManager.cpp @@ -147,7 +147,10 @@ void KeybindManager::movefocus(std::string arg) { void KeybindManager::movetoworkspace(std::string arg) { try { - g_pWindowManager->moveActiveWindowToWorkspace(stoi(arg)); + if (arg == "scratchpad") + g_pWindowManager->moveActiveWindowToWorkspace(SCRATCHPAD_ID); + else + g_pWindowManager->moveActiveWindowToWorkspace(stoi(arg)); } catch (...) { Debug::log(ERR, "Invalid arg in movetoworkspace, arg: " + arg); } @@ -242,4 +245,17 @@ void KeybindManager::togglePseudoActive(std::string args) { PWINDOW->setIsPseudotiled(!PWINDOW->getIsPseudotiled()); PWINDOW->setDirty(true); +} + +void KeybindManager::toggleScratchpad(std::string args) { + if (g_pWindowManager->getWindowsOnWorkspace(SCRATCHPAD_ID) == 0) + return; + + g_pWindowManager->scratchpadActive = !g_pWindowManager->scratchpadActive; + + g_pWindowManager->setAllWorkspaceWindowsDirtyByID(SCRATCHPAD_ID); + + const auto NEWTOP = g_pWindowManager->findFirstWindowOnWorkspace(SCRATCHPAD_ID); + if (NEWTOP) + g_pWindowManager->setFocusedWindow(NEWTOP->getDrawable()); } \ No newline at end of file diff --git a/src/KeybindManager.hpp b/src/KeybindManager.hpp index 4c72692..3b776d3 100644 --- a/src/KeybindManager.hpp +++ b/src/KeybindManager.hpp @@ -29,4 +29,5 @@ namespace KeybindManager { void movetoworkspace(std::string args); void changeSplitRatio(std::string args); void togglePseudoActive(std::string args); + void toggleScratchpad(std::string args); }; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index afafe70..22148c1 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -19,6 +19,7 @@ void ConfigManager::init() { configValues["main_mod"].strValue = "SUPER"; configValues["intelligent_transients"].intValue = 1; configValues["no_unmap_saving"].intValue = 1; + configValues["scratchpad_mon"].intValue = 1; configValues["focus_when_hover"].intValue = 1; @@ -126,7 +127,8 @@ void handleBind(const std::string& command, const std::string& value) { if (HANDLER == "togglefloating") dispatcher = KeybindManager::toggleActiveWindowFloating; if (HANDLER == "splitratio") dispatcher = KeybindManager::changeSplitRatio; if (HANDLER == "pseudo") dispatcher = KeybindManager::togglePseudoActive; - + if (HANDLER == "scratchpad") dispatcher = KeybindManager::toggleScratchpad; + if (dispatcher && KEY != 0) KeybindManager::keybinds.push_back(Keybind(KeybindManager::modToMask(MOD), KEY, COMMAND, dispatcher)); } @@ -407,6 +409,14 @@ void ConfigManager::loadConfigLoadVars() { isFirstLaunch = false; if (ORIGBORDERSIZE != configValues["border_size"].intValue) EWMH::refreshAllExtents(); + + // scratchpad mon + if (configValues["scratchpad_mon"].intValue > g_pWindowManager->monitors.size()) { + configValues["scratchpad_mon"].intValue = 0; + Debug::log(ERR, "Invalid scratchpad mon, falling back to 0"); + } + if (const auto PSCRATCH = g_pWindowManager->getWorkspaceByID(SCRATCHPAD_ID); PSCRATCH) + PSCRATCH->setMonitor(configValues["scratchpad_mod"].intValue); } void ConfigManager::applyKeybindsToX() { diff --git a/src/defines.hpp b/src/defines.hpp index e3997ff..2615364 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -98,4 +98,6 @@ #define _NET_MOVERESIZE_WINDOW_X (1 << 8) #define _NET_MOVERESIZE_WINDOW_Y (1 << 9) #define _NET_MOVERESIZE_WINDOW_WIDTH (1 << 10) -#define _NET_MOVERESIZE_WINDOW_HEIGHT (1 << 11) \ No newline at end of file +#define _NET_MOVERESIZE_WINDOW_HEIGHT (1 << 11) + +#define SCRATCHPAD_ID 1337420 \ No newline at end of file diff --git a/src/events/events.cpp b/src/events/events.cpp index c7c71ac..218defb 100644 --- a/src/events/events.cpp +++ b/src/events/events.cpp @@ -539,16 +539,20 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) { // Set the parent // check if lastwindow is on our workspace - if (auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); (PLASTWINDOW && PLASTWINDOW->getWorkspaceID() == g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) || wasfloating || (forcemonitor != -1 && forcemonitor != PMONITOR->ID)) { + if (auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); (PLASTWINDOW && PLASTWINDOW->getWorkspaceID() == g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) || wasfloating || (forcemonitor != -1 && forcemonitor != PMONITOR->ID) || PWINDOWINARR->getWorkspaceID() == SCRATCHPAD_ID) { // LastWindow is on our workspace, let's make a new split node - if (wasfloating || (forcemonitor != -1 && forcemonitor != PMONITOR->ID) || (forcemonitor != -1 && PLASTWINDOW->getWorkspaceID() != g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) || PLASTWINDOW->getIsFloating()) { - // if it's force monitor, find the first on a workspace. - if ((forcemonitor != -1 && forcemonitor != PMONITOR->ID) || (forcemonitor != -1 && PLASTWINDOW->getWorkspaceID() != g_pWindowManager->activeWorkspaces[CURRENTSCREEN])) { - PLASTWINDOW = g_pWindowManager->findFirstWindowOnWorkspace(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]); - } else { - // find a window manually by the cursor - PLASTWINDOW = g_pWindowManager->findWindowAtCursor(); + if (PWINDOWINARR->getWorkspaceID() == SCRATCHPAD_ID) + PLASTWINDOW = g_pWindowManager->findPreferredOnScratchpad(); + else { + if (wasfloating || (forcemonitor != -1 && forcemonitor != PMONITOR->ID) || (forcemonitor != -1 && PLASTWINDOW->getWorkspaceID() != g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) || PLASTWINDOW->getIsFloating()) { + // if it's force monitor, find the first on a workspace. + if ((forcemonitor != -1 && forcemonitor != PMONITOR->ID) || (forcemonitor != -1 && PLASTWINDOW->getWorkspaceID() != g_pWindowManager->activeWorkspaces[CURRENTSCREEN])) { + PLASTWINDOW = g_pWindowManager->findFirstWindowOnWorkspace(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]); + } else { + // find a window manually by the cursor + PLASTWINDOW = g_pWindowManager->findWindowAtCursor(); + } } } @@ -664,6 +668,13 @@ void Events::eventMapWindow(xcb_generic_event_t* event) { return; } + if (g_pWindowManager->scratchpadActive) { + KeybindManager::toggleScratchpad(""); + + const auto PNEW = g_pWindowManager->findWindowAtCursor(); + g_pWindowManager->LastWindow = PNEW ? PNEW->getDrawable() : 0; + } + CWindow window; window.setDrawable(E->window); g_pWindowManager->addWindowToVectorSafe(window); diff --git a/src/ewmh/ewmh.cpp b/src/ewmh/ewmh.cpp index 7a487a1..acfa3bc 100644 --- a/src/ewmh/ewmh.cpp +++ b/src/ewmh/ewmh.cpp @@ -98,6 +98,8 @@ void EWMH::updateDesktops() { int msglen = 0; for (auto& work : workspacesVec) { + if (work.getID() == SCRATCHPAD_ID) + continue; msglen += strlen(std::to_string(work.getID()).c_str()) + 1; } @@ -105,6 +107,9 @@ void EWMH::updateDesktops() { int curpos = 0; for (auto& work : workspacesVec) { for (int i = 0; i < strlen(std::to_string(work.getID()).c_str()) + 1; ++i) { + if (work.getID() == SCRATCHPAD_ID) + break; + names[curpos] = std::to_string(work.getID())[i]; ++curpos; } diff --git a/src/windowManager.cpp b/src/windowManager.cpp index c8dd548..0cad85b 100644 --- a/src/windowManager.cpp +++ b/src/windowManager.cpp @@ -195,6 +195,14 @@ void CWindowManager::setupManager() { updateRootCursor(); + CWorkspace scratchpad; + scratchpad.setID(SCRATCHPAD_ID); + for (long unsigned int i = 0; i < monitors.size(); ++i) { + if (monitors[i].primary) + scratchpad.setMonitor(monitors[i].ID); + } + workspaces.push_back(scratchpad); + Debug::log(LOG, "Finished setup!"); // TODO: EWMH @@ -942,6 +950,13 @@ void CWindowManager::setEffectiveSizePosUsingConfig(CWindow* pWindow) { } } + if (pWindow->getWorkspaceID() == SCRATCHPAD_ID) { + TEMPEFFECTIVEPOS = TEMPEFFECTIVEPOS + ((TEMPEFFECTIVESIZE - TEMPEFFECTIVESIZE * 0.75f) * 0.5f); + TEMPEFFECTIVESIZE = TEMPEFFECTIVESIZE * 0.75f; + + setAWindowTop(pWindow->getDrawable()); + } + pWindow->setEffectivePosition(TEMPEFFECTIVEPOS); pWindow->setEffectiveSize(TEMPEFFECTIVESIZE); } @@ -955,7 +970,7 @@ CWindow* CWindowManager::findWindowAtCursor() { const auto WORKSPACE = activeWorkspaces[getMonitorFromCursor()->ID]; for (auto& window : windows) { - if (window.getWorkspaceID() == WORKSPACE && !window.getIsFloating() && window.getDrawable() > 0 && window.getConstructed()) { + if (window.getWorkspaceID() == WORKSPACE && !window.getIsFloating() && window.getDrawable() > 0 && window.getConstructed() && window.getWorkspaceID() != SCRATCHPAD_ID) { if (cursorPos.x >= window.getPosition().x && cursorPos.x <= window.getPosition().x + window.getSize().x @@ -980,6 +995,22 @@ CWindow* CWindowManager::findFirstWindowOnWorkspace(const int& work) { return nullptr; } +CWindow* CWindowManager::findPreferredOnScratchpad() { + Vector2D topSize; + CWindow* pTop = nullptr; + + for (auto& w : windows) { + if (w.getWorkspaceID() == SCRATCHPAD_ID && w.getDrawable() > 0 && w.getConstructed()) { + if (w.getSize().x * w.getSize().y > topSize.x * topSize.y) { + topSize = w.getSize(); + pTop = &w; + } + } + } + + return pTop; +} + void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) { // Get the parent and both children, one of which will be pWindow @@ -1304,6 +1335,9 @@ void CWindowManager::closeWindowAllChecks(int64_t id) { CLOSEDWINDOW->setDead(true); + if (CLOSEDWINDOW->getWorkspaceID() != SCRATCHPAD_ID && scratchpadActive) + scratchpadActive = false; + if (const auto WORKSPACE = getWorkspaceByID(CLOSEDWINDOW->getWorkspaceID()); WORKSPACE && CLOSEDWINDOW->getFullscreen()) WORKSPACE->setHasFullscreenWindow(false); @@ -1539,7 +1573,11 @@ void CWindowManager::moveActiveWindowToWorkspace(int workspace) { PWINDOW = getWindowFromDrawable(LastWindow); PWINDOW->setDead(false); - if (const auto WORKSPACE = getWorkspaceByID(PWINDOW->getWorkspaceID()); WORKSPACE && PWINDOW->getFullscreen()) + const auto WORKSPACE = getWorkspaceByID(PWINDOW->getWorkspaceID()); + + auto workspacesBefore = activeWorkspaces; + + if (WORKSPACE && PWINDOW->getFullscreen()) WORKSPACE->setHasFullscreenWindow(false); changeWorkspaceByID(workspace); @@ -1547,7 +1585,11 @@ void CWindowManager::moveActiveWindowToWorkspace(int workspace) { // Find new mon int NEWMONITOR = 0; for (long unsigned int i = 0; i < activeWorkspaces.size(); ++i) { - if (activeWorkspaces[i] == workspace) { + if (workspace == SCRATCHPAD_ID) { + if (monitors[i].ID == ConfigManager::getInt("scratchpad_mon")) + NEWMONITOR = i; + } + else if (activeWorkspaces[i] == workspace) { NEWMONITOR = i; } } @@ -1561,15 +1603,24 @@ void CWindowManager::moveActiveWindowToWorkspace(int workspace) { } } + const auto LASTFOCUS = LastWindow; + if (newLastWindow) { setFocusedWindow(newLastWindow); } - if (SAVEDFLOATSTATUS) + PWINDOW->setConstructed(false); + + if (SAVEDFLOATSTATUS && workspace != SCRATCHPAD_ID) Events::remapFloatingWindow(PWINDOW->getDrawable(), NEWMONITOR); else Events::remapWindow(PWINDOW->getDrawable(), false, NEWMONITOR); + PWINDOW->setConstructed(true); + + // fix for scratchpad + PWINDOW->setWorkspaceID(workspace); + // fix fullscreen status const auto PWORKSPACE = getWorkspaceByID(workspace); if (PWORKSPACE) { @@ -1578,6 +1629,17 @@ void CWindowManager::moveActiveWindowToWorkspace(int workspace) { } PWINDOW->setDefaultSize(SAVEDDEFAULTSIZE); + + if (workspace == SCRATCHPAD_ID) { + for (int i = 0; i < activeWorkspaces.size(); ++i) { + changeWorkspaceByID(workspacesBefore[i]); + } + + changeWorkspaceByID(WORKSPACE->getID()); + setFocusedWindow(LASTFOCUS); + } + + QueuedPointerWarp = Vector2D(-1,-1); } void CWindowManager::moveActiveWindowTo(char dir) { @@ -1893,6 +1955,9 @@ Vector2D CWindowManager::getCursorPos() { bool CWindowManager::isWorkspaceVisible(int workspaceID) { + if (workspaceID == SCRATCHPAD_ID) + return scratchpadActive; + for (auto& workspace : activeWorkspaces) { if (workspace == workspaceID) return true; @@ -1954,6 +2019,9 @@ void CWindowManager::updateBarInfo() { message.fullscreenOnBar = false; for (auto& workspace : workspaces) { + if (workspace.getID() == SCRATCHPAD_ID) + continue; + message.openWorkspaces.push_back(workspace.getID()); } @@ -2155,6 +2223,7 @@ void CWindowManager::refocusWindowOnClosed() { // No window or last window valid if (!PWINDOW || getWindowFromDrawable(LastWindow)) { setFocusedWindow(Screen->root); //refocus on root + return; } diff --git a/src/windowManager.hpp b/src/windowManager.hpp index 971f9b7..44047e5 100644 --- a/src/windowManager.hpp +++ b/src/windowManager.hpp @@ -38,6 +38,8 @@ public: Vector2D mouseLastPos = Vector2D(0, 0); int64_t actingOnWindowFloating = 0; + bool scratchpadActive = false; + uint8_t Depth = 32; xcb_visualtype_t* VisualType; xcb_colormap_t Colormap; @@ -116,6 +118,7 @@ public: CWindow* findWindowAtCursor(); CWindow* findFirstWindowOnWorkspace(const int&); + CWindow* findPreferredOnScratchpad(); bool shouldBeFloatedOnInit(int64_t); void doPostCreationChecks(CWindow*);