Added scratchpads.

This commit is contained in:
vaxerski 2022-04-03 22:02:25 +02:00
parent 0b9a33228b
commit 0da4b298c5
9 changed files with 136 additions and 15 deletions

View file

@ -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,+

View file

@ -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());
}

View file

@ -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);
};

View file

@ -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() {

View file

@ -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)
#define _NET_MOVERESIZE_WINDOW_HEIGHT (1 << 11)
#define SCRATCHPAD_ID 1337420

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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*);