2021-11-18 18:04:09 +01:00
|
|
|
#include "KeybindManager.hpp"
|
2021-11-21 13:11:51 +01:00
|
|
|
#include "utilities/Util.hpp"
|
2021-11-22 21:20:32 +01:00
|
|
|
#include "events/events.hpp"
|
2022-01-07 13:09:45 +01:00
|
|
|
#include "windowManager.hpp"
|
2021-11-18 18:04:09 +01:00
|
|
|
|
2021-11-19 20:20:05 +01:00
|
|
|
#include <algorithm>
|
2021-11-21 18:25:38 +01:00
|
|
|
#include <string.h>
|
2021-11-19 20:20:05 +01:00
|
|
|
|
2021-11-18 18:04:09 +01:00
|
|
|
Keybind* KeybindManager::findKeybindByKey(int mod, xcb_keysym_t keysym) {
|
2022-04-10 19:54:58 +02:00
|
|
|
const auto IGNOREMODMASK = KeybindManager::modToMask(ConfigManager::getString("ignore_mod"));
|
|
|
|
|
2021-11-18 18:04:09 +01:00
|
|
|
for(auto& key : KeybindManager::keybinds) {
|
2022-04-12 15:20:30 +02:00
|
|
|
if (keysym == key.getKeysym() && (mod == key.getMod() || (mod == (key.getMod() | IGNOREMODMASK)))) {
|
2021-11-18 18:04:09 +01:00
|
|
|
return &key;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
2021-11-19 20:20:05 +01:00
|
|
|
}
|
|
|
|
|
2021-11-21 13:11:51 +01:00
|
|
|
uint32_t KeybindManager::getKeyCodeFromName(std::string name) {
|
|
|
|
if (name == "")
|
|
|
|
return 0;
|
|
|
|
|
2022-04-12 22:14:04 +02:00
|
|
|
if (name.find_first_not_of("1234567890") == std::string::npos) {
|
|
|
|
const auto KC = std::stoi(name);
|
|
|
|
|
|
|
|
if (KC > 10) // 0-9 are OK for parsing they are on the KB
|
|
|
|
return std::stoi(name);
|
|
|
|
}
|
|
|
|
|
2022-04-12 15:29:44 +02:00
|
|
|
|
2021-12-27 09:40:37 +01:00
|
|
|
const auto ORIGINALCASENAME = name;
|
2021-11-21 13:11:51 +01:00
|
|
|
transform(name.begin(), name.end(), name.begin(), ::tolower);
|
|
|
|
|
|
|
|
if (name.length() == 1) {
|
|
|
|
// key
|
|
|
|
std::string command = "xmodmap -pk | grep \"(" + name + ")\"";
|
|
|
|
std::string returnValue = exec(command.c_str());
|
|
|
|
|
|
|
|
try {
|
|
|
|
returnValue = returnValue.substr(returnValue.find_first_of('x') + 1);
|
|
|
|
returnValue = returnValue.substr(0, returnValue.find_first_of(' '));
|
|
|
|
|
|
|
|
return std::stoi(returnValue, nullptr, 16); // return hex to int
|
|
|
|
} catch(...) { }
|
|
|
|
} else {
|
|
|
|
if (name == "return" || name == "enter") {
|
|
|
|
return 0xff0d;
|
|
|
|
} else if (name == "left") {
|
|
|
|
return 0xff51;
|
|
|
|
} else if (name == "right") {
|
|
|
|
return 0xff53;
|
|
|
|
} else if (name == "up") {
|
|
|
|
return 0xff52;
|
|
|
|
} else if (name == "down") {
|
|
|
|
return 0xff54;
|
2021-11-21 15:15:33 +01:00
|
|
|
} else if (name == "space") {
|
|
|
|
return 0x20;
|
2021-12-27 09:40:37 +01:00
|
|
|
} else {
|
|
|
|
// unknown key, find in the xmodmap
|
|
|
|
std::string command = "xmodmap -pk | grep \"(" + ORIGINALCASENAME + ")\"";
|
|
|
|
std::string returnValue = exec(command.c_str());
|
|
|
|
|
|
|
|
try {
|
|
|
|
returnValue = returnValue.substr(returnValue.find_first_of('x') + 1);
|
|
|
|
returnValue = returnValue.substr(0, returnValue.find_first_of(' '));
|
|
|
|
|
|
|
|
return std::stoi(returnValue, nullptr, 16); // return hex to int
|
|
|
|
} catch (...) {
|
|
|
|
Debug::log(ERR, "Unknown key: " + ORIGINALCASENAME);
|
|
|
|
}
|
2021-11-21 13:11:51 +01:00
|
|
|
}
|
2021-11-20 10:04:14 +01:00
|
|
|
}
|
2021-11-21 13:11:51 +01:00
|
|
|
|
|
|
|
return 0;
|
2021-11-19 20:20:05 +01:00
|
|
|
}
|
|
|
|
|
2021-12-06 15:04:47 +01:00
|
|
|
unsigned int KeybindManager::modToMask(std::string mod) {
|
2021-11-19 20:20:05 +01:00
|
|
|
|
2022-04-12 15:29:44 +02:00
|
|
|
if (mod.find_first_not_of("1234567890") == std::string::npos && mod != "")
|
|
|
|
return std::stoi(mod);
|
2022-04-10 19:54:58 +02:00
|
|
|
|
2021-12-06 15:04:47 +01:00
|
|
|
unsigned int sum = 0;
|
|
|
|
|
|
|
|
if (CONTAINS(mod, "SUPER") || CONTAINS(mod, "MOD4")) sum |= XCB_MOD_MASK_4;
|
|
|
|
if (CONTAINS(mod, "SHIFT")) sum |= XCB_MOD_MASK_SHIFT;
|
|
|
|
if (CONTAINS(mod, "CTRL")) sum |= XCB_MOD_MASK_CONTROL;
|
|
|
|
if (CONTAINS(mod, "ALT") || CONTAINS(mod, "MOD1")) sum |= XCB_MOD_MASK_1;
|
2022-03-22 22:55:45 +01:00
|
|
|
if (CONTAINS(mod, "MOD2")) sum |= XCB_MOD_MASK_2;
|
|
|
|
if (CONTAINS(mod, "MOD3")) sum |= XCB_MOD_MASK_3;
|
|
|
|
if (CONTAINS(mod, "MOD5")) sum |= XCB_MOD_MASK_5;
|
|
|
|
if (CONTAINS(mod, "LOCK")) sum |= XCB_MOD_MASK_LOCK;
|
2021-12-06 15:04:47 +01:00
|
|
|
|
|
|
|
return sum;
|
2021-11-19 20:20:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
xcb_keysym_t KeybindManager::getKeysymFromKeycode(xcb_keycode_t keycode) {
|
2021-11-20 09:25:21 +01:00
|
|
|
const auto KEYSYMS = xcb_key_symbols_alloc(g_pWindowManager->DisplayConnection);
|
2021-11-19 20:20:05 +01:00
|
|
|
const auto KEYSYM = (!(KEYSYMS) ? 0 : xcb_key_symbols_get_keysym(KEYSYMS, keycode, 0));
|
|
|
|
xcb_key_symbols_free(KEYSYMS);
|
|
|
|
return KEYSYM;
|
|
|
|
}
|
|
|
|
|
|
|
|
xcb_keycode_t KeybindManager::getKeycodeFromKeysym(xcb_keysym_t keysym) {
|
2021-11-20 09:25:21 +01:00
|
|
|
const auto KEYSYMS = xcb_key_symbols_alloc(g_pWindowManager->DisplayConnection);
|
2021-11-19 20:20:05 +01:00
|
|
|
const auto KEYCODE = (!(KEYSYMS) ? NULL : xcb_key_symbols_get_keycode(KEYSYMS, keysym));
|
|
|
|
xcb_key_symbols_free(KEYSYMS);
|
|
|
|
return KEYCODE ? *KEYCODE : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dispatchers
|
|
|
|
|
2021-11-19 20:34:05 +01:00
|
|
|
void KeybindManager::killactive(std::string args) {
|
|
|
|
// args unused
|
2021-11-30 16:43:28 +01:00
|
|
|
const auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow);
|
|
|
|
|
|
|
|
if (!PLASTWINDOW)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (PLASTWINDOW->getCanKill()) {
|
|
|
|
// Send a kill message
|
|
|
|
xcb_client_message_event_t event;
|
|
|
|
bzero(&event, sizeof(event));
|
|
|
|
event.response_type = XCB_CLIENT_MESSAGE;
|
|
|
|
event.window = PLASTWINDOW->getDrawable();
|
|
|
|
event.type = HYPRATOMS["WM_PROTOCOLS"];
|
|
|
|
event.format = 32;
|
|
|
|
event.data.data32[0] = HYPRATOMS["WM_DELETE_WINDOW"];
|
|
|
|
event.data.data32[1] = 0;
|
|
|
|
|
|
|
|
xcb_send_event(g_pWindowManager->DisplayConnection, 0, PLASTWINDOW->getDrawable(), XCB_EVENT_MASK_NO_EVENT, (const char*)&event);
|
2021-12-21 11:32:15 +01:00
|
|
|
|
|
|
|
return; // Do not remove it yet. The user might've cancelled the operation or something. We will get
|
|
|
|
// an unmap event.
|
2021-11-30 16:43:28 +01:00
|
|
|
} else
|
|
|
|
xcb_kill_client(g_pWindowManager->DisplayConnection, g_pWindowManager->LastWindow);
|
|
|
|
|
|
|
|
g_pWindowManager->closeWindowAllChecks(g_pWindowManager->LastWindow);
|
2021-11-19 20:34:05 +01:00
|
|
|
}
|
|
|
|
|
2021-11-19 20:20:05 +01:00
|
|
|
void KeybindManager::call(std::string args) {
|
2021-11-21 18:25:38 +01:00
|
|
|
|
2021-11-19 20:20:05 +01:00
|
|
|
if (fork() == 0) {
|
2021-11-26 20:25:00 +01:00
|
|
|
//setsid();
|
2021-11-19 20:20:05 +01:00
|
|
|
|
2021-11-21 18:25:38 +01:00
|
|
|
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
2021-11-19 20:20:05 +01:00
|
|
|
|
|
|
|
_exit(0);
|
|
|
|
}
|
2021-11-26 20:25:00 +01:00
|
|
|
//wait(NULL);
|
2021-11-19 22:29:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void KeybindManager::movewindow(std::string arg) {
|
2021-11-20 09:25:21 +01:00
|
|
|
g_pWindowManager->moveActiveWindowTo(arg[0]);
|
2021-11-20 10:04:14 +01:00
|
|
|
}
|
|
|
|
|
2021-12-05 12:05:44 +01:00
|
|
|
void KeybindManager::movefocus(std::string arg) {
|
|
|
|
g_pWindowManager->moveActiveFocusTo(arg[0]);
|
|
|
|
}
|
|
|
|
|
2021-11-25 17:44:46 +01:00
|
|
|
void KeybindManager::movetoworkspace(std::string arg) {
|
|
|
|
try {
|
2022-04-03 22:02:25 +02:00
|
|
|
if (arg == "scratchpad")
|
|
|
|
g_pWindowManager->moveActiveWindowToWorkspace(SCRATCHPAD_ID);
|
|
|
|
else
|
|
|
|
g_pWindowManager->moveActiveWindowToWorkspace(stoi(arg));
|
2021-11-25 17:44:46 +01:00
|
|
|
} catch (...) {
|
|
|
|
Debug::log(ERR, "Invalid arg in movetoworkspace, arg: " + arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-11-20 10:04:14 +01:00
|
|
|
void KeybindManager::changeworkspace(std::string arg) {
|
|
|
|
int ID = -1;
|
|
|
|
try {
|
|
|
|
ID = std::stoi(arg.c_str());
|
|
|
|
} catch (...) { ; }
|
|
|
|
|
|
|
|
if (ID != -1) {
|
|
|
|
Debug::log(LOG, "Changing the current workspace to " + std::to_string(ID));
|
|
|
|
g_pWindowManager->changeWorkspaceByID(ID);
|
|
|
|
}
|
2021-11-21 11:42:44 +01:00
|
|
|
}
|
|
|
|
|
2022-01-07 13:09:45 +01:00
|
|
|
void KeybindManager::changetolastworkspace(std::string arg) {
|
|
|
|
Debug::log(LOG, "Changing the current workspace to the last workspace");
|
|
|
|
g_pWindowManager->changeToLastWorkspace();
|
|
|
|
}
|
|
|
|
|
2021-11-21 11:42:44 +01:00
|
|
|
void KeybindManager::toggleActiveWindowFullscreen(std::string unusedArg) {
|
2021-12-17 19:57:07 +01:00
|
|
|
g_pWindowManager->toggleWindowFullscrenn(g_pWindowManager->LastWindow);
|
2021-11-21 15:15:33 +01:00
|
|
|
}
|
|
|
|
|
2022-04-03 13:39:30 +02:00
|
|
|
void KeybindManager::toggleActiveWindowFloating(std::string arg) {
|
2021-11-21 15:15:33 +01:00
|
|
|
if (const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); PWINDOW) {
|
|
|
|
PWINDOW->setIsFloating(!PWINDOW->getIsFloating());
|
|
|
|
PWINDOW->setDirty(true);
|
2022-04-04 21:40:10 +02:00
|
|
|
PWINDOW->setPinned(false);
|
2021-11-21 15:15:33 +01:00
|
|
|
|
|
|
|
// Fix window as if it's closed if we just made it floating
|
2021-11-22 21:20:32 +01:00
|
|
|
if (PWINDOW->getIsFloating()) {
|
2021-11-21 15:15:33 +01:00
|
|
|
g_pWindowManager->fixWindowOnClose(PWINDOW);
|
2021-11-22 21:20:32 +01:00
|
|
|
g_pWindowManager->calculateNewWindowParams(PWINDOW);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// It's remapped again
|
|
|
|
|
|
|
|
// SAVE ALL INFO NOW, THE POINTER WILL BE DEAD
|
|
|
|
const auto RESTOREACSIZE = PWINDOW->getDefaultSize();
|
|
|
|
const auto RESTOREACPOS = PWINDOW->getDefaultPosition();
|
|
|
|
const auto RESTOREWINID = PWINDOW->getDrawable();
|
2021-11-30 16:43:28 +01:00
|
|
|
const auto RESTORECANKILL = PWINDOW->getCanKill();
|
2022-03-22 16:17:18 +01:00
|
|
|
const auto RESTOREPSEUDO = PWINDOW->getPseudoSize();
|
|
|
|
const auto RESTOREISPSEUDO = PWINDOW->getIsPseudotiled();
|
|
|
|
const auto RESTOREREALS = PWINDOW->getRealSize();
|
|
|
|
const auto RESTOREREALP = PWINDOW->getRealPosition();
|
2022-04-03 13:39:30 +02:00
|
|
|
const auto RESTOREDRAGT = PWINDOW->getDraggingTiled();
|
2021-11-21 15:15:33 +01:00
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
g_pWindowManager->removeWindowFromVectorSafe(PWINDOW->getDrawable());
|
2021-12-21 18:30:35 +01:00
|
|
|
|
|
|
|
CWindow newWindow;
|
|
|
|
newWindow.setDrawable(RESTOREWINID);
|
|
|
|
newWindow.setFirstOpen(false);
|
2022-03-22 16:17:18 +01:00
|
|
|
newWindow.setConstructed(false);
|
2021-12-21 18:30:35 +01:00
|
|
|
g_pWindowManager->addWindowToVectorSafe(newWindow);
|
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
const auto PNEWWINDOW = Events::remapWindow(RESTOREWINID, true);
|
|
|
|
|
|
|
|
PNEWWINDOW->setDefaultPosition(RESTOREACPOS);
|
|
|
|
PNEWWINDOW->setDefaultSize(RESTOREACSIZE);
|
2021-11-30 16:43:28 +01:00
|
|
|
PNEWWINDOW->setCanKill(RESTORECANKILL);
|
2022-03-22 16:17:18 +01:00
|
|
|
PNEWWINDOW->setPseudoSize(RESTOREPSEUDO);
|
|
|
|
PNEWWINDOW->setIsPseudotiled(RESTOREISPSEUDO);
|
|
|
|
PNEWWINDOW->setRealPosition(RESTOREREALP);
|
|
|
|
PNEWWINDOW->setRealSize(RESTOREREALS);
|
2022-04-03 13:39:30 +02:00
|
|
|
PNEWWINDOW->setDraggingTiled(RESTOREDRAGT);
|
2021-11-22 21:20:32 +01:00
|
|
|
}
|
2021-12-21 09:48:41 +01:00
|
|
|
|
|
|
|
// EWMH to let everyone know
|
2021-12-21 09:48:56 +01:00
|
|
|
EWMH::updateClientList();
|
2021-12-21 10:46:22 +01:00
|
|
|
|
|
|
|
EWMH::updateWindow(PWINDOW->getDrawable());
|
2021-12-23 10:06:48 +01:00
|
|
|
|
2022-04-03 13:39:30 +02:00
|
|
|
if (arg != "simple")
|
|
|
|
g_pWindowManager->setAllFloatingWindowsTop();
|
2021-11-21 15:15:33 +01:00
|
|
|
}
|
2022-01-07 13:09:45 +01:00
|
|
|
}
|
2022-03-09 12:13:47 +01:00
|
|
|
|
|
|
|
void KeybindManager::changeSplitRatio(std::string args) {
|
|
|
|
g_pWindowManager->changeSplitRatioCurrent(args[0]);
|
2022-03-22 16:17:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void KeybindManager::togglePseudoActive(std::string args) {
|
|
|
|
const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow);
|
|
|
|
|
|
|
|
if (!PWINDOW)
|
|
|
|
return;
|
|
|
|
|
|
|
|
PWINDOW->setIsPseudotiled(!PWINDOW->getIsPseudotiled());
|
|
|
|
|
|
|
|
PWINDOW->setDirty(true);
|
2022-04-03 22:02:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
2022-04-04 18:14:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void KeybindManager::nextWorkspace(std::string args) {
|
|
|
|
const auto PMONITOR = g_pWindowManager->getMonitorFromCursor();
|
|
|
|
|
|
|
|
if (!PMONITOR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_pWindowManager->changeWorkspaceByID(g_pWindowManager->activeWorkspaces[PMONITOR->ID] + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KeybindManager::lastWorkspace(std::string args) {
|
|
|
|
const auto PMONITOR = g_pWindowManager->getMonitorFromCursor();
|
|
|
|
|
|
|
|
if (!PMONITOR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_pWindowManager->changeWorkspaceByID(g_pWindowManager->activeWorkspaces[PMONITOR->ID] < 2 ? 1 : g_pWindowManager->activeWorkspaces[PMONITOR->ID] - 1);
|
2022-04-04 21:40:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void KeybindManager::pinActive(std::string agrs) {
|
|
|
|
const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow);
|
|
|
|
|
|
|
|
if (!PWINDOW)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (PWINDOW->getIsFloating())
|
|
|
|
PWINDOW->setPinned(!PWINDOW->getPinned());
|
2022-03-09 12:13:47 +01:00
|
|
|
}
|