Skip to content

Commit

Permalink
Added scratchpads.
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed Apr 3, 2022
1 parent 0b9a332 commit 0da4b29
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 15 deletions.
4 changes: 4 additions & 0 deletions example/hypr.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,+
Expand Down
18 changes: 17 additions & 1 deletion src/KeybindManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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());
}
1 change: 1 addition & 0 deletions src/KeybindManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
12 changes: 11 additions & 1 deletion src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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() {
Expand Down
4 changes: 3 additions & 1 deletion src/defines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
27 changes: 19 additions & 8 deletions src/events/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}

Expand Down Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions src/ewmh/ewmh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,18 @@ 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;
}

char names[msglen];
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;
}
Expand Down
77 changes: 73 additions & 4 deletions src/windowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -1539,15 +1573,23 @@ 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);

// 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;
}
}
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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());
}

Expand Down Expand Up @@ -2155,6 +2223,7 @@ void CWindowManager::refocusWindowOnClosed() {
// No window or last window valid
if (!PWINDOW || getWindowFromDrawable(LastWindow)) {
setFocusedWindow(Screen->root); //refocus on root

return;
}

Expand Down
3 changes: 3 additions & 0 deletions src/windowManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class CWindowManager {
Vector2D mouseLastPos = Vector2D(0, 0);
int64_t actingOnWindowFloating = 0;

bool scratchpadActive = false;

uint8_t Depth = 32;
xcb_visualtype_t* VisualType;
xcb_colormap_t Colormap;
Expand Down Expand Up @@ -116,6 +118,7 @@ class CWindowManager {
CWindow* findWindowAtCursor();

CWindow* findFirstWindowOnWorkspace(const int&);
CWindow* findPreferredOnScratchpad();

bool shouldBeFloatedOnInit(int64_t);
void doPostCreationChecks(CWindow*);
Expand Down

0 comments on commit 0da4b29

Please sign in to comment.