Hyprland/src/managers/KeybindManager.cpp

3317 lines
127 KiB
C++
Raw Normal View History

#include "../config/ConfigValue.hpp"
#include "../devices/IKeyboard.hpp"
2024-05-10 18:27:57 +01:00
#include "../managers/SeatManager.hpp"
#include "../protocols/LayerShell.hpp"
#include "../protocols/ShortcutsInhibit.hpp"
#include "../protocols/GlobalShortcuts.hpp"
#include "../protocols/core/DataDevice.hpp"
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
#include "KeybindManager.hpp"
#include "PointerManager.hpp"
#include "Compositor.hpp"
#include "TokenManager.hpp"
#include "eventLoop/EventLoopManager.hpp"
#include "debug/Log.hpp"
#include "../managers/HookSystemManager.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/LayoutManager.hpp"
#include "../managers/EventManager.hpp"
#include "../render/Renderer.hpp"
#include "../hyprerror/HyprError.hpp"
#include "../config/ConfigManager.hpp"
2022-03-19 17:48:18 +01:00
#include <optional>
2024-06-05 08:42:44 +00:00
#include <iterator>
#include <string>
#include <string_view>
#include <cstring>
2022-06-10 12:06:27 +02:00
#include <hyprutils/string/String.hpp>
core: begin using CFileDescriptor from hyprutils (#9122) * config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling.
2025-01-30 12:30:12 +01:00
#include <hyprutils/os/FileDescriptor.hpp>
using namespace Hyprutils::String;
core: begin using CFileDescriptor from hyprutils (#9122) * config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling.
2025-01-30 12:30:12 +01:00
using namespace Hyprutils::OS;
#include <sys/ioctl.h>
#include <fcntl.h>
#include <vector>
#if defined(__linux__)
#include <linux/vt.h>
#elif defined(__NetBSD__) || defined(__OpenBSD__)
#include <dev/wscons/wsdisplay_usl_io.h>
#elif defined(__DragonFly__) || defined(__FreeBSD__)
#include <sys/consio.h>
#endif
static std::vector<std::pair<std::string, std::string>> getHyprlandLaunchEnv(PHLWORKSPACE pInitialWorkspace) {
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
if (!*PINITIALWSTRACKING || g_pConfigManager->m_isLaunchingExecOnce)
return {};
const auto PMONITOR = g_pCompositor->m_lastMonitor;
if (!PMONITOR || !PMONITOR->activeWorkspace)
return {};
std::vector<std::pair<std::string, std::string>> result;
if (!pInitialWorkspace) {
if (PMONITOR->activeSpecialWorkspace)
pInitialWorkspace = PMONITOR->activeSpecialWorkspace;
else
pInitialWorkspace = PMONITOR->activeWorkspace;
}
result.push_back(std::make_pair<>("HL_INITIAL_WORKSPACE_TOKEN",
g_pTokenManager->registerNewToken(SInitialWorkspaceToken{{}, pInitialWorkspace->getConfigName()}, std::chrono::months(1337))));
return result;
}
2022-04-21 15:50:52 +02:00
CKeybindManager::CKeybindManager() {
// initialize all dispatchers
m_mDispatchers["exec"] = spawn;
m_mDispatchers["execr"] = spawnRaw;
m_mDispatchers["killactive"] = closeActive;
m_mDispatchers["forcekillactive"] = killActive;
m_mDispatchers["closewindow"] = closeWindow;
m_mDispatchers["killwindow"] = killWindow;
m_mDispatchers["signal"] = signalActive;
m_mDispatchers["signalwindow"] = signalWindow;
m_mDispatchers["togglefloating"] = toggleActiveFloating;
m_mDispatchers["setfloating"] = setActiveFloating;
m_mDispatchers["settiled"] = setActiveTiled;
m_mDispatchers["workspace"] = changeworkspace;
m_mDispatchers["renameworkspace"] = renameWorkspace;
m_mDispatchers["fullscreen"] = fullscreenActive;
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
m_mDispatchers["fullscreenstate"] = fullscreenStateActive;
m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace;
m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent;
m_mDispatchers["pseudo"] = toggleActivePseudo;
m_mDispatchers["movefocus"] = moveFocusTo;
m_mDispatchers["movewindow"] = moveActiveTo;
m_mDispatchers["swapwindow"] = swapActive;
m_mDispatchers["centerwindow"] = centerWindow;
m_mDispatchers["togglegroup"] = toggleGroup;
m_mDispatchers["changegroupactive"] = changeGroupActive;
m_mDispatchers["movegroupwindow"] = moveGroupWindow;
m_mDispatchers["togglesplit"] = toggleSplit;
m_mDispatchers["swapsplit"] = swapSplit;
m_mDispatchers["splitratio"] = alterSplitRatio;
m_mDispatchers["focusmonitor"] = focusMonitor;
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
m_mDispatchers["movecursor"] = moveCursor;
m_mDispatchers["workspaceopt"] = workspaceOpt;
m_mDispatchers["exit"] = exitHyprland;
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
m_mDispatchers["focusworkspaceoncurrentmonitor"] = focusWorkspaceOnCurrentMonitor;
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
m_mDispatchers["forcerendererreload"] = forceRendererReload;
m_mDispatchers["resizeactive"] = resizeActive;
m_mDispatchers["moveactive"] = moveActive;
m_mDispatchers["cyclenext"] = circleNext;
m_mDispatchers["focuswindowbyclass"] = focusWindow;
m_mDispatchers["focuswindow"] = focusWindow;
m_mDispatchers["tagwindow"] = tagWindow;
m_mDispatchers["toggleswallow"] = toggleSwallow;
m_mDispatchers["submap"] = setSubmap;
m_mDispatchers["pass"] = pass;
m_mDispatchers["sendshortcut"] = sendshortcut;
m_mDispatchers["sendkeystate"] = sendkeystate;
m_mDispatchers["layoutmsg"] = layoutmsg;
m_mDispatchers["dpms"] = dpms;
m_mDispatchers["movewindowpixel"] = moveWindow;
m_mDispatchers["resizewindowpixel"] = resizeWindow;
m_mDispatchers["swapnext"] = swapnext;
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
m_mDispatchers["pin"] = pinActive;
m_mDispatchers["mouse"] = mouse;
m_mDispatchers["bringactivetotop"] = bringActiveToTop;
m_mDispatchers["alterzorder"] = alterZOrder;
m_mDispatchers["focusurgentorlast"] = focusUrgentOrLast;
m_mDispatchers["focuscurrentorlast"] = focusCurrentOrLast;
m_mDispatchers["lockgroups"] = lockGroups;
m_mDispatchers["lockactivegroup"] = lockActiveGroup;
m_mDispatchers["moveintogroup"] = moveIntoGroup;
m_mDispatchers["moveoutofgroup"] = moveOutOfGroup;
m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup;
m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock;
m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup;
m_mDispatchers["event"] = event;
m_mDispatchers["global"] = global;
m_mDispatchers["setprop"] = setProp;
2022-07-26 23:34:03 +02:00
m_tScrollTimer.reset();
m_pLongPressTimer = makeShared<CEventLoopTimer>(
std::nullopt,
[this](SP<CEventLoopTimer> self, void* data) {
if (!m_pLastLongPressKeybind || g_pSeatManager->keyboard.expired())
return;
const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock();
if (!PACTIVEKEEB->allowBinds)
return;
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(m_pLastLongPressKeybind->handler);
Debug::log(LOG, "Long press timeout passed, calling dispatcher.");
DISPATCHER->second(m_pLastLongPressKeybind->arg);
},
nullptr);
m_pRepeatKeyTimer = makeShared<CEventLoopTimer>(
std::nullopt,
[this](SP<CEventLoopTimer> self, void* data) {
if (m_vActiveKeybinds.size() == 0 || g_pSeatManager->keyboard.expired())
return;
const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock();
if (!PACTIVEKEEB->allowBinds)
return;
2024-11-18 19:56:26 +00:00
for (const auto& k : m_vActiveKeybinds) {
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(k->handler);
Debug::log(LOG, "Keybind repeat triggered, calling dispatcher.");
DISPATCHER->second(k->arg);
}
self->updateTimeout(std::chrono::milliseconds(1000 / PACTIVEKEEB->repeatRate));
},
nullptr);
// null in --verify-config mode
if (g_pEventLoopManager) {
g_pEventLoopManager->addTimer(m_pLongPressTimer);
g_pEventLoopManager->addTimer(m_pRepeatKeyTimer);
}
2024-04-20 20:16:42 +01:00
static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) {
// clear cuz realloc'd
m_vActiveKeybinds.clear();
2024-11-18 19:56:26 +00:00
m_pLastLongPressKeybind.reset();
m_vPressedSpecialBinds.clear();
});
2022-04-21 15:50:52 +02:00
}
CKeybindManager::~CKeybindManager() {
if (m_pXKBTranslationState)
xkb_state_unref(m_pXKBTranslationState);
if (m_pLongPressTimer && g_pEventLoopManager) {
g_pEventLoopManager->removeTimer(m_pLongPressTimer);
m_pLongPressTimer.reset();
}
if (m_pRepeatKeyTimer && g_pEventLoopManager) {
g_pEventLoopManager->removeTimer(m_pRepeatKeyTimer);
m_pRepeatKeyTimer.reset();
}
}
2022-03-19 17:48:18 +01:00
void CKeybindManager::addKeybind(SKeybind kb) {
2024-11-18 19:56:26 +00:00
m_vKeybinds.emplace_back(makeShared<SKeybind>(kb));
2022-07-25 14:42:49 +02:00
m_vActiveKeybinds.clear();
2024-11-18 19:56:26 +00:00
m_pLastLongPressKeybind.reset();
2022-04-21 17:06:43 +02:00
}
void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) {
2024-11-18 19:56:26 +00:00
std::erase_if(m_vKeybinds, [&mod, &key](const auto& el) { return el->modmask == mod && el->key == key.key && el->keycode == key.keycode && el->catchAll == key.catchAll; });
2022-07-25 14:42:49 +02:00
m_vActiveKeybinds.clear();
2024-11-18 19:56:26 +00:00
m_pLastLongPressKeybind.reset();
2022-03-19 17:48:18 +01:00
}
uint32_t CKeybindManager::stringToModMask(std::string mods) {
uint32_t modMask = 0;
std::transform(mods.begin(), mods.end(), mods.begin(), ::toupper);
if (mods.contains("SHIFT"))
modMask |= HL_MODIFIER_SHIFT;
if (mods.contains("CAPS"))
modMask |= HL_MODIFIER_CAPS;
if (mods.contains("CTRL") || mods.contains("CONTROL"))
modMask |= HL_MODIFIER_CTRL;
if (mods.contains("ALT") || mods.contains("MOD1"))
modMask |= HL_MODIFIER_ALT;
if (mods.contains("MOD2"))
modMask |= HL_MODIFIER_MOD2;
if (mods.contains("MOD3"))
modMask |= HL_MODIFIER_MOD3;
if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4") || mods.contains("META"))
modMask |= HL_MODIFIER_META;
if (mods.contains("MOD5"))
modMask |= HL_MODIFIER_MOD5;
2022-03-19 17:48:18 +01:00
return modMask;
}
uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) {
if (keycode == 0)
return 0;
switch (keycode - 8) {
case KEY_LEFTMETA: return HL_MODIFIER_META;
case KEY_RIGHTMETA: return HL_MODIFIER_META;
case KEY_LEFTSHIFT: return HL_MODIFIER_SHIFT;
case KEY_RIGHTSHIFT: return HL_MODIFIER_SHIFT;
case KEY_LEFTCTRL: return HL_MODIFIER_CTRL;
case KEY_RIGHTCTRL: return HL_MODIFIER_CTRL;
case KEY_LEFTALT: return HL_MODIFIER_ALT;
case KEY_RIGHTALT: return HL_MODIFIER_ALT;
case KEY_CAPSLOCK: return HL_MODIFIER_CAPS;
case KEY_NUMLOCK: return HL_MODIFIER_MOD2;
default: return 0;
}
}
void CKeybindManager::updateXKBTranslationState() {
if (m_pXKBTranslationState) {
xkb_state_unref(m_pXKBTranslationState);
m_pXKBTranslationState = nullptr;
}
static auto PFILEPATH = CConfigValue<std::string>("input:kb_file");
static auto PRULES = CConfigValue<std::string>("input:kb_rules");
static auto PMODEL = CConfigValue<std::string>("input:kb_model");
static auto PLAYOUT = CConfigValue<std::string>("input:kb_layout");
static auto PVARIANT = CConfigValue<std::string>("input:kb_variant");
static auto POPTIONS = CConfigValue<std::string>("input:kb_options");
const std::string FILEPATH = std::string{*PFILEPATH} == STRVAL_EMPTY ? "" : *PFILEPATH;
const std::string RULES = std::string{*PRULES} == STRVAL_EMPTY ? "" : *PRULES;
const std::string MODEL = std::string{*PMODEL} == STRVAL_EMPTY ? "" : *PMODEL;
const std::string LAYOUT = std::string{*PLAYOUT} == STRVAL_EMPTY ? "" : *PLAYOUT;
const std::string VARIANT = std::string{*PVARIANT} == STRVAL_EMPTY ? "" : *PVARIANT;
const std::string OPTIONS = std::string{*POPTIONS} == STRVAL_EMPTY ? "" : *POPTIONS;
xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()};
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
FILE* const KEYMAPFILE = FILEPATH == "" ? nullptr : fopen(absolutePath(FILEPATH, g_pConfigManager->m_configCurrentPath).c_str(), "r");
auto PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS) :
xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (KEYMAPFILE)
fclose(KEYMAPFILE);
if (!PKEYMAP) {
g_pHyprError->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS +
", layout: " + LAYOUT + " )",
CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
2023-09-06 12:51:36 +02:00
Debug::log(ERR, "[XKBTranslationState] Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant,
rules.rules, rules.model, rules.options);
memset(&rules, 0, sizeof(rules));
PKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
xkb_context_unref(PCONTEXT);
m_pXKBTranslationState = xkb_state_new(PKEYMAP);
xkb_keymap_unref(PKEYMAP);
}
2022-09-20 22:23:02 +01:00
bool CKeybindManager::ensureMouseBindState() {
if (!g_pInputManager->currentlyDraggedWindow)
2022-09-20 22:23:02 +01:00
return false;
2022-09-20 10:02:20 +01:00
if (!g_pInputManager->currentlyDraggedWindow.expired()) {
changeMouseBindMode(MBIND_INVALID);
2022-09-20 22:23:02 +01:00
return true;
2022-09-20 10:02:20 +01:00
}
2022-09-20 22:23:02 +01:00
return false;
2022-09-20 10:02:20 +01:00
}
static void updateRelativeCursorCoords() {
static auto PNOWARPS = CConfigValue<Hyprlang::INT>("cursor:no_warps");
if (*PNOWARPS)
return;
if (g_pCompositor->m_lastWindow)
g_pCompositor->m_lastWindow->m_vRelativeCursorCoordsOnLastWarp = g_pInputManager->getMouseCoordsInternal() - g_pCompositor->m_lastWindow->m_vPosition;
}
bool CKeybindManager::tryMoveFocusToMonitor(PHLMONITOR monitor) {
2023-04-10 21:07:49 +02:00
if (!monitor)
return false;
const auto LASTMONITOR = g_pCompositor->m_lastMonitor.lock();
if (!LASTMONITOR)
return false;
2023-04-10 21:07:49 +02:00
if (LASTMONITOR == monitor) {
Debug::log(LOG, "Tried to move to active monitor");
return false;
}
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
static auto PNOWARPS = CConfigValue<Hyprlang::INT>("cursor:no_warps");
const auto PWORKSPACE = g_pCompositor->m_lastMonitor->activeWorkspace;
const auto PNEWMAINWORKSPACE = monitor->activeWorkspace;
2023-04-10 21:07:49 +02:00
g_pInputManager->unconstrainMouse();
PNEWMAINWORKSPACE->rememberPrevWorkspace(PWORKSPACE);
const auto PNEWWORKSPACE = monitor->activeSpecialWorkspace ? monitor->activeSpecialWorkspace : PNEWMAINWORKSPACE;
const auto PNEWWINDOW = PNEWWORKSPACE->getLastFocusedWindow();
if (PNEWWINDOW) {
updateRelativeCursorCoords();
g_pCompositor->focusWindow(PNEWWINDOW);
PNEWWINDOW->warpCursor();
if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) {
g_pInputManager->m_pForcedFocus = PNEWWINDOW;
g_pInputManager->simulateMouseMovement();
g_pInputManager->m_pForcedFocus.reset();
}
} else {
g_pCompositor->focusWindow(nullptr);
g_pCompositor->warpCursorTo(monitor->middle());
}
g_pCompositor->setActiveMonitor(monitor);
return true;
}
void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO, bool preserveFocusHistory) {
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
static auto PNOWARPS = CConfigValue<Hyprlang::INT>("cursor:no_warps");
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
if (PWINDOWTOCHANGETO == PLASTWINDOW || !PWINDOWTOCHANGETO)
return;
// remove constraints
g_pInputManager->unconstrainMouse();
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
if (PLASTWINDOW && PLASTWINDOW->m_pWorkspace == PWINDOWTOCHANGETO->m_pWorkspace && PLASTWINDOW->isFullscreen()) {
const auto PWORKSPACE = PLASTWINDOW->m_pWorkspace;
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
const auto MODE = PWORKSPACE->m_efFullscreenMode;
if (!PWINDOWTOCHANGETO->m_bPinned)
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
g_pCompositor->setWindowFullscreenInternal(PLASTWINDOW, FSMODE_NONE);
g_pCompositor->focusWindow(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory);
if (!PWINDOWTOCHANGETO->m_bPinned)
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE);
// warp the position + size animation, otherwise it looks weird.
PWINDOWTOCHANGETO->m_vRealPosition->warp();
PWINDOWTOCHANGETO->m_vRealSize->warp();
} else {
updateRelativeCursorCoords();
g_pCompositor->focusWindow(PWINDOWTOCHANGETO, nullptr, preserveFocusHistory);
PWINDOWTOCHANGETO->warpCursor();
// Move mouse focus to the new window if required by current follow_mouse and warp modes
if (*PNOWARPS == 0 || *PFOLLOWMOUSE < 2) {
g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO;
g_pInputManager->simulateMouseMovement();
g_pInputManager->m_pForcedFocus.reset();
}
if (PLASTWINDOW && PLASTWINDOW->m_pMonitor != PWINDOWTOCHANGETO->m_pMonitor) {
// event
const auto PNEWMON = PWINDOWTOCHANGETO->m_pMonitor.lock();
g_pCompositor->setActiveMonitor(PNEWMON);
}
}
};
bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
if (!g_pCompositor->m_sessionActive || g_pCompositor->m_unsafeState) {
m_dPressedKeys.clear();
2022-08-29 11:17:42 +02:00
return true;
}
if (!pKeyboard->allowBinds)
return true;
if (!m_pXKBTranslationState) {
Debug::log(ERR, "BUG THIS: m_pXKBTranslationState nullptr!");
updateXKBTranslationState();
if (!m_pXKBTranslationState)
return true;
}
auto e = std::any_cast<IKeyboard::SKeyEvent>(event);
const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput
2022-07-20 22:45:06 +02:00
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbSymState : m_pXKBTranslationState, KEYCODE);
const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->xkbState, KEYCODE);
2022-08-26 19:19:34 +02:00
if (keysym == XKB_KEY_Escape || internalKeysym == XKB_KEY_Escape)
PROTO::data->abortDndIfPresent();
// handleInternalKeybinds returns true when the key should be suppressed,
// while this function returns true when the key event should be sent
2022-08-26 19:19:34 +02:00
if (handleInternalKeybinds(internalKeysym))
return false;
2022-07-20 22:45:06 +02:00
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
m_uTimeLastMs = e.timeMs;
m_uLastCode = KEYCODE;
m_uLastMouseCode = 0;
2022-07-20 23:17:26 +02:00
bool mouseBindWasActive = ensureMouseBindState();
const auto KEY = SPressedKeyWithMods{
.keysym = keysym,
.keycode = KEYCODE,
.modmaskAtPressTime = MODS,
.sent = true,
.submapAtPress = m_szCurrentSelectedSubmap,
.mousePosAtPress = g_pInputManager->getMouseCoordsInternal(),
};
2022-09-20 10:02:20 +01:00
m_vActiveKeybinds.clear();
2024-11-18 19:56:26 +00:00
m_pLastLongPressKeybind.reset();
bool suppressEvent = false;
if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) {
2022-07-25 14:42:49 +02:00
m_dPressedKeys.push_back(KEY);
2022-07-20 23:17:26 +02:00
suppressEvent = !handleKeybinds(MODS, KEY, true).passEvent;
2022-07-24 14:35:58 +02:00
if (suppressEvent)
2022-07-25 14:24:02 +02:00
shadowKeybinds(keysym, KEYCODE);
m_dPressedKeys.back().sent = !suppressEvent;
} else { // key release
2022-07-20 22:45:06 +02:00
bool foundInPressedKeys = false;
for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) {
if (it->keycode == KEYCODE) {
handleKeybinds(MODS, *it, false);
foundInPressedKeys = true;
suppressEvent = !it->sent;
it = m_dPressedKeys.erase(it);
} else {
++it;
}
}
if (!foundInPressedKeys) {
Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys");
// fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
suppressEvent = !handleKeybinds(MODS, KEY, false).passEvent;
}
2022-07-20 23:17:26 +02:00
shadowKeybinds();
2022-07-20 22:45:06 +02:00
}
return !suppressEvent && !mouseBindWasActive;
2022-07-20 22:45:06 +02:00
}
bool CKeybindManager::onAxisEvent(const IPointer::SAxisEvent& e) {
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
2022-07-21 19:18:03 +03:00
static auto PDELAY = CConfigValue<Hyprlang::INT>("binds:scroll_event_delay");
2022-07-26 23:34:03 +02:00
if (m_tScrollTimer.getMillis() < *PDELAY) {
2022-07-26 23:34:03 +02:00
m_tScrollTimer.reset();
return true; // timer hasn't passed yet!
}
m_tScrollTimer.reset();
m_vActiveKeybinds.clear();
2022-07-21 19:18:03 +03:00
bool found = false;
if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
if (e.delta < 0)
found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_down"}, true).passEvent;
2023-02-23 13:55:27 +00:00
else
found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_up"}, true).passEvent;
} else if (e.source == WL_POINTER_AXIS_SOURCE_WHEEL && e.axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
if (e.delta < 0)
found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_left"}, true).passEvent;
2023-02-23 13:55:27 +00:00
else
found = !handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_right"}, true).passEvent;
2022-07-26 14:50:21 +02:00
}
2023-02-23 13:55:27 +00:00
if (found)
shadowKeybinds();
2022-07-26 14:50:21 +02:00
return !found;
}
bool CKeybindManager::onMouseEvent(const IPointer::SButtonEvent& e) {
2022-07-26 14:50:21 +02:00
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
bool suppressEvent = false;
2022-07-26 14:50:21 +02:00
m_uLastMouseCode = e.button;
m_uLastCode = 0;
m_uTimeLastMs = e.timeMs;
bool mouseBindWasActive = ensureMouseBindState();
const auto KEY_NAME = "mouse:" + std::to_string(e.button);
const auto KEY = SPressedKeyWithMods{
.keyName = KEY_NAME,
.modmaskAtPressTime = MODS,
.mousePosAtPress = g_pInputManager->getMouseCoordsInternal(),
};
2022-09-20 22:23:02 +01:00
m_vActiveKeybinds.clear();
if (e.state == WL_POINTER_BUTTON_STATE_PRESSED) {
m_dPressedKeys.push_back(KEY);
suppressEvent = !handleKeybinds(MODS, KEY, true).passEvent;
2022-07-26 14:50:21 +02:00
if (suppressEvent)
2022-07-26 14:50:21 +02:00
shadowKeybinds();
m_dPressedKeys.back().sent = !suppressEvent;
2022-07-26 14:50:21 +02:00
} else {
bool foundInPressedKeys = false;
for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) {
if (it->keyName == KEY_NAME) {
suppressEvent = !handleKeybinds(MODS, *it, false).passEvent;
foundInPressedKeys = true;
suppressEvent = !it->sent;
it = m_dPressedKeys.erase(it);
} else {
++it;
}
}
if (!foundInPressedKeys) {
Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys (2)");
// fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy
suppressEvent = !handleKeybinds(MODS, KEY, false).passEvent;
}
2022-07-26 14:50:21 +02:00
shadowKeybinds();
2022-07-21 19:18:03 +03:00
}
return !suppressEvent && !mouseBindWasActive;
2022-07-21 19:18:03 +03:00
}
void CKeybindManager::resizeWithBorder(const IPointer::SButtonEvent& e) {
changeMouseBindMode(e.state == WL_POINTER_BUTTON_STATE_PRESSED ? MBIND_RESIZE : MBIND_INVALID);
2023-02-18 23:35:31 +01:00
}
2022-10-04 20:07:21 +01:00
void CKeybindManager::onSwitchEvent(const std::string& switchName) {
handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:" + switchName}, true);
2022-10-04 20:07:21 +01:00
}
void CKeybindManager::onSwitchOnEvent(const std::string& switchName) {
handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:on:" + switchName}, true);
}
void CKeybindManager::onSwitchOffEvent(const std::string& switchName) {
handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:off:" + switchName}, true);
}
eMultiKeyCase CKeybindManager::mkKeysymSetMatches(const std::set<xkb_keysym_t> keybindKeysyms, const std::set<xkb_keysym_t> pressedKeysyms) {
// Returns whether two sets of keysyms are equal, partially equal, or not
// matching. (Partially matching means that pressed is a subset of bound)
std::set<xkb_keysym_t> boundKeysNotPressed;
std::set<xkb_keysym_t> pressedKeysNotBound;
std::set_difference(keybindKeysyms.begin(), keybindKeysyms.end(), pressedKeysyms.begin(), pressedKeysyms.end(),
std::inserter(boundKeysNotPressed, boundKeysNotPressed.begin()));
std::set_difference(pressedKeysyms.begin(), pressedKeysyms.end(), keybindKeysyms.begin(), keybindKeysyms.end(),
std::inserter(pressedKeysNotBound, pressedKeysNotBound.begin()));
if (boundKeysNotPressed.empty() && pressedKeysNotBound.empty())
return MK_FULL_MATCH;
if (boundKeysNotPressed.size() && pressedKeysNotBound.empty())
return MK_PARTIAL_MATCH;
return MK_NO_MATCH;
}
2024-11-18 19:56:26 +00:00
eMultiKeyCase CKeybindManager::mkBindMatches(const SP<SKeybind> keybind) {
if (mkKeysymSetMatches(keybind->sMkMods, m_sMkMods) != MK_FULL_MATCH)
return MK_NO_MATCH;
2024-11-18 19:56:26 +00:00
return mkKeysymSetMatches(keybind->sMkKeys, m_sMkKeys);
}
std::string CKeybindManager::getCurrentSubmap() {
return m_szCurrentSelectedSubmap;
}
SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) {
static auto PDISABLEINHIBIT = CConfigValue<Hyprlang::INT>("binds:disable_keybind_grabbing");
static auto PDRAGTHRESHOLD = CConfigValue<Hyprlang::INT>("binds:drag_threshold");
bool found = false;
SDispatchResult res;
if (pressed) {
if (keycodeToModifier(key.keycode))
m_sMkMods.insert(key.keysym);
else
m_sMkKeys.insert(key.keysym);
} else {
if (keycodeToModifier(key.keycode))
m_sMkMods.erase(key.keysym);
else
m_sMkKeys.erase(key.keysym);
}
2022-04-18 17:16:01 +02:00
2024-11-18 19:56:26 +00:00
for (auto& k : m_vKeybinds) {
const bool SPECIALDISPATCHER = k->handler == "global" || k->handler == "pass" || k->handler == "sendshortcut" || k->handler == "mouse";
const bool SPECIALTRIGGERED =
2024-11-18 19:56:26 +00:00
std::find_if(m_vPressedSpecialBinds.begin(), m_vPressedSpecialBinds.end(), [&](const auto& other) { return other == k; }) != m_vPressedSpecialBinds.end();
const bool IGNORECONDITIONS =
SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released.
2024-11-18 19:56:26 +00:00
if (!k->dontInhibit && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited())
continue;
2024-11-18 19:56:26 +00:00
if (!k->locked && g_pSessionLockManager->isSessionLocked())
continue;
2024-11-18 19:56:26 +00:00
if (!IGNORECONDITIONS && ((modmask != k->modmask && !k->ignoreMods) || k->submap != m_szCurrentSelectedSubmap || k->shadowed))
2022-03-19 17:48:18 +01:00
continue;
2024-11-18 19:56:26 +00:00
if (k->multiKey) {
switch (mkBindMatches(k)) {
case MK_NO_MATCH: continue;
case MK_PARTIAL_MATCH: found = true; continue;
case MK_FULL_MATCH: found = true;
}
} else if (!key.keyName.empty()) {
2024-11-18 19:56:26 +00:00
if (key.keyName != k->key)
2022-07-15 21:54:05 +03:00
continue;
2024-11-18 19:56:26 +00:00
} else if (k->keycode != 0) {
if (key.keycode != k->keycode)
2022-07-08 09:27:17 +02:00
continue;
2024-11-18 19:56:26 +00:00
} else if (k->catchAll) {
if (found || key.submapAtPress != m_szCurrentSelectedSubmap)
continue;
2022-07-08 09:27:17 +02:00
} else {
// in this case, we only have the keysym to go off of for this keybind, and it's invalid
// since there might be something like keycode to match with other keybinds, try the next
if (key.keysym == XKB_KEY_NoSymbol)
continue;
2022-07-08 09:27:17 +02:00
// oMg such performance hit!!11!
// this little maneouver is gonna cost us 4µs
2024-11-18 19:56:26 +00:00
const auto KBKEY = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_NO_FLAGS);
const auto KBKEYLOWER = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
if (KBKEY == XKB_KEY_NoSymbol && KBKEYLOWER == XKB_KEY_NoSymbol) {
2024-03-13 00:26:42 +09:00
// Keysym failed to resolve from the key name of the currently iterated bind.
// This happens for names such as `switch:off:Lid Switch` as well as some keys
// (such as yen and ro).
//
// We can't let compare a 0-value with currently pressed key below,
// because if this key also have no keysym (i.e. key.keysym == 0) it will incorrectly trigger the
// currently iterated bind. That's confirmed to be happening with yen and ro keys.
continue;
}
if (key.keysym != KBKEY && key.keysym != KBKEYLOWER)
2022-07-08 09:27:17 +02:00
continue;
}
2022-04-21 15:50:52 +02:00
2024-11-18 19:56:26 +00:00
if (pressed && k->release && !SPECIALDISPATCHER) {
if (k->nonConsuming)
continue;
found = true; // suppress the event
continue;
}
if (!pressed) {
// Require mods to be matching when the key was first pressed.
2024-11-18 19:56:26 +00:00
if (key.modmaskAtPressTime != modmask && !k->ignoreMods) {
// Handle properly `bindr` where a key is itself a bind mod for example:
// "bindr = SUPER, SUPER_L, exec, $launcher".
// This needs to be handled separately for the above case, because `key.modmaskAtPressTime` is set
// from currently pressed keys as programs see them, but it doesn't yet include the currently
// pressed mod key, which is still being handled internally.
if (keycodeToModifier(key.keycode) == key.modmaskAtPressTime)
continue;
2024-11-18 19:56:26 +00:00
} else if (!k->release && !SPECIALDISPATCHER) {
if (k->nonConsuming)
continue;
found = true; // suppress the event
continue;
}
// Require mouse to stay inside drag_threshold for clicks, outside for drags
// Check if either a mouse bind has triggered or currently over the threshold (maybe there is no mouse bind on the same key)
const auto THRESHOLDREACHED = key.mousePosAtPress.distanceSq(g_pInputManager->getMouseCoordsInternal()) > std::pow(*PDRAGTHRESHOLD, 2);
if (k->click && (g_pInputManager->m_bDragThresholdReached || THRESHOLDREACHED))
continue;
else if (k->drag && !g_pInputManager->m_bDragThresholdReached && !THRESHOLDREACHED)
continue;
2022-07-20 22:45:06 +02:00
}
2024-11-18 19:56:26 +00:00
if (k->longPress) {
const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock();
m_pLongPressTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay));
2024-11-18 19:56:26 +00:00
m_pLastLongPressKeybind = k;
continue;
}
2024-11-18 19:56:26 +00:00
const auto DISPATCHER = m_mDispatchers.find(k->mouse ? "mouse" : k->handler);
2022-04-21 15:50:52 +02:00
if (SPECIALTRIGGERED && !pressed)
2024-11-18 19:56:26 +00:00
std::erase_if(m_vPressedSpecialBinds, [&](const auto& other) { return other == k; });
else if (SPECIALDISPATCHER && pressed)
m_vPressedSpecialBinds.emplace_back(k);
found = true;
2022-04-21 15:50:52 +02:00
// Should never happen, as we check in the ConfigManager, but oh well
if (DISPATCHER == m_mDispatchers.end()) {
2024-11-18 19:56:26 +00:00
Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k->handler);
2022-04-21 15:50:52 +02:00
} else {
// call the dispatcher
Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {}, {})", modmask, key.keyName, key.keysym, DISPATCHER->first);
m_iPassPressed = (int)pressed;
// if the dispatchers says to pass event then we will
2024-11-18 19:56:26 +00:00
if (k->handler == "mouse")
res = DISPATCHER->second((pressed ? "1" : "0") + k->arg);
2022-09-19 19:04:48 +01:00
else
2024-11-18 19:56:26 +00:00
res = DISPATCHER->second(k->arg);
m_iPassPressed = -1;
if (k->handler == "submap")
break;
2022-04-14 23:02:10 +02:00
}
2022-03-19 22:03:40 +01:00
2024-11-18 19:56:26 +00:00
if (k->repeat) {
2024-05-10 18:27:57 +01:00
const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock();
2022-07-25 14:42:49 +02:00
m_vActiveKeybinds.emplace_back(k);
m_pRepeatKeyTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay));
2022-07-25 14:42:49 +02:00
}
2024-11-18 19:56:26 +00:00
if (!k->nonConsuming)
found = true;
2022-03-19 17:48:18 +01:00
}
2022-03-19 22:03:40 +01:00
g_pInputManager->m_bDragThresholdReached = false;
// if keybind wasn't found (or dispatcher said to) then pass event
res.passEvent |= !found;
if (!found && !*PDISABLEINHIBIT && PROTO::shortcutsInhibit->isInhibited()) {
Debug::log(LOG, "Keybind handling is disabled due to an inhibitor");
res.success = false;
if (res.error.empty())
res.error = "Keybind handling is disabled due to an inhibitor";
}
return res;
2022-03-19 17:48:18 +01:00
}
void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint32_t doesntHaveCode) {
2022-07-20 23:17:26 +02:00
// shadow disables keybinds after one has been triggered
2024-11-18 19:56:26 +00:00
for (auto& k : m_vKeybinds) {
2022-07-20 23:17:26 +02:00
bool shadow = false;
2024-11-18 19:56:26 +00:00
if (k->handler == "global" || k->transparent)
continue; // can't be shadowed
2022-07-20 23:17:26 +02:00
2024-11-18 19:56:26 +00:00
if (k->multiKey && (mkBindMatches(k) == MK_FULL_MATCH))
shadow = true;
else {
2024-11-18 19:56:26 +00:00
const auto KBKEY = xkb_keysym_from_name(k->key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
2022-07-20 23:17:26 +02:00
for (auto const& pk : m_dPressedKeys) {
if ((pk.keysym != 0 && (pk.keysym == KBKEY || pk.keysym == KBKEYUPPER))) {
shadow = true;
2022-09-25 20:07:48 +02:00
if (pk.keysym == doesntHave && doesntHave != 0) {
shadow = false;
break;
}
2022-07-25 16:12:06 +02:00
}
2022-07-20 23:17:26 +02:00
2024-11-18 19:56:26 +00:00
if (pk.keycode != 0 && pk.keycode == k->keycode) {
shadow = true;
2022-07-24 12:16:26 +02:00
if (pk.keycode == doesntHaveCode && doesntHaveCode != 0) {
shadow = false;
break;
}
2022-07-25 16:12:06 +02:00
}
2022-07-24 12:16:26 +02:00
}
2022-07-20 23:17:26 +02:00
}
2024-11-18 19:56:26 +00:00
k->shadowed = shadow;
2022-07-20 23:17:26 +02:00
}
}
2022-06-27 13:42:20 +02:00
bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
// Handles the CTRL+ALT+FX TTY keybinds
if (keysym < XKB_KEY_XF86Switch_VT_1 || keysym > XKB_KEY_XF86Switch_VT_12)
return false;
// beyond this point, return true to not handle anything else.
// we'll avoid printing shit to active windows.
if (g_pCompositor->m_aqBackend->hasSession()) {
const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
2022-10-04 16:53:09 +01:00
2022-10-05 21:41:27 +01:00
// vtnr is bugged for some reason.
core: begin using CFileDescriptor from hyprutils (#9122) * config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling.
2025-01-30 12:30:12 +01:00
unsigned int ttynum = 0;
Hyprutils::OS::CFileDescriptor fd{open("/dev/tty", O_RDONLY | O_NOCTTY)};
if (fd.isValid()) {
#if defined(VT_GETSTATE)
struct vt_stat st;
core: begin using CFileDescriptor from hyprutils (#9122) * config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling.
2025-01-30 12:30:12 +01:00
if (!ioctl(fd.get(), VT_GETSTATE, &st))
ttynum = st.v_active;
#elif defined(VT_GETACTIVE)
int vt;
core: begin using CFileDescriptor from hyprutils (#9122) * config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling.
2025-01-30 12:30:12 +01:00
if (!ioctl(fd.get(), VT_GETACTIVE, &vt))
ttynum = vt;
#endif
}
2022-10-05 21:41:27 +01:00
if (ttynum == TTY)
return true;
2022-10-05 21:41:27 +01:00
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "Switching from VT {} to VT {}", ttynum, TTY);
2022-10-05 21:41:27 +01:00
g_pCompositor->m_aqBackend->session->switchVT(TTY);
}
return true;
}
2022-06-27 13:42:20 +02:00
bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
if (handleVT(keysym))
return true;
// handle ESC while in kill mode
if (g_pInputManager->getClickMode() == CLICKMODE_KILL) {
const auto KBKEY = xkb_keysym_from_name("ESCAPE", XKB_KEYSYM_CASE_INSENSITIVE);
if (keysym == KBKEY) {
g_pInputManager->setClickMode(CLICKMODE_DEFAULT);
return true;
}
}
return false;
}
2022-03-19 17:48:18 +01:00
// Dispatchers
SDispatchResult CKeybindManager::spawn(std::string args) {
const uint64_t PROC = spawnWithRules(args, nullptr);
return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)};
}
uint64_t CKeybindManager::spawnWithRules(std::string args, PHLWORKSPACE pInitialWorkspace) {
2022-11-10 13:39:23 +00:00
args = trim(args);
2022-11-10 13:39:23 +00:00
std::string RULES = "";
if (args[0] == '[') {
// we have exec rules
RULES = args.substr(1, args.substr(1).find_first_of(']'));
args = args.substr(args.find_first_of(']') + 1);
2022-11-10 13:39:23 +00:00
}
const uint64_t PROC = spawnRawProc(args, pInitialWorkspace);
2023-02-19 13:59:39 +00:00
if (!RULES.empty()) {
const auto RULESLIST = CVarList(RULES, 0, ';');
for (auto const& r : RULESLIST) {
2023-02-19 13:59:39 +00:00
g_pConfigManager->addExecRule({r, (unsigned long)PROC});
}
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "Applied {} rule arguments for exec.", RULESLIST.size());
2023-02-19 13:59:39 +00:00
}
return PROC;
}
SDispatchResult CKeybindManager::spawnRaw(std::string args) {
const uint64_t PROC = spawnRawProc(args, nullptr);
return {.success = PROC > 0, .error = std::format("Failed to start process {}", args)};
2023-02-19 13:59:39 +00:00
}
uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWorkspace) {
Debug::log(LOG, "Executing {}", args);
2022-03-19 17:48:18 +01:00
const auto HLENV = getHyprlandLaunchEnv(pInitialWorkspace);
int socket[2];
2022-06-17 03:19:36 +08:00
if (pipe(socket) != 0) {
Debug::log(LOG, "Unable to create pipe for fork");
}
2022-06-16 01:06:51 +08:00
core: begin using CFileDescriptor from hyprutils (#9122) * config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling.
2025-01-30 12:30:12 +01:00
CFileDescriptor pipeSock[2] = {CFileDescriptor{socket[0]}, CFileDescriptor{socket[1]}};
pid_t child, grandchild;
2022-06-16 01:06:51 +08:00
child = fork();
2022-06-17 03:19:36 +08:00
if (child < 0) {
2022-06-16 01:06:51 +08:00
Debug::log(LOG, "Fail to create the first fork");
2023-02-19 13:59:39 +00:00
return 0;
2022-06-16 01:06:51 +08:00
}
2022-06-17 03:19:36 +08:00
if (child == 0) {
2022-06-16 01:06:51 +08:00
// run in child
g_pCompositor->restoreNofile();
2022-10-06 19:02:03 +01:00
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, nullptr);
2022-10-06 19:02:03 +01:00
2022-06-16 01:06:51 +08:00
grandchild = fork();
2022-06-17 03:19:36 +08:00
if (grandchild == 0) {
2022-06-16 01:06:51 +08:00
// run in grandchild
for (auto const& e : HLENV) {
setenv(e.first.c_str(), e.second.c_str(), 1);
}
setenv("WAYLAND_DISPLAY", g_pCompositor->m_wlDisplaySocket.c_str(), 1);
int devnull = open("/dev/null", O_WRONLY | O_CLOEXEC);
if (devnull != -1) {
dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO);
close(devnull);
}
2022-06-16 01:06:51 +08:00
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
// exit grandchild
_exit(0);
}
core: begin using CFileDescriptor from hyprutils (#9122) * config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling.
2025-01-30 12:30:12 +01:00
write(pipeSock[1].get(), &grandchild, sizeof(grandchild));
2022-06-16 01:06:51 +08:00
// exit child
2022-03-19 17:48:18 +01:00
_exit(0);
}
2022-06-16 01:06:51 +08:00
// run in parent
core: begin using CFileDescriptor from hyprutils (#9122) * config: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * hyprctl: make fd use CFileDescriptor make use of the new hyprutils CFileDescriptor instead of manual FD handling. * ikeyboard: make fd use CFileDescriptor make use of the new CFileDescriptor instead of manual FD handling, also in sendKeymap remove dead code, it already early returns if keyboard isnt valid, and dont try to close the FD that ikeyboard owns. * core: make SHMFile functions use CFileDescriptor make SHMFile misc functions use CFileDescriptor and its associated usage in dmabuf and keyboard. * core: make explicit sync use CFileDescriptor begin using CFileDescriptor in explicit sync and its timelines and eglsync usage in opengl, there is still a bit left with manual handling that requires future aquamarine change aswell. * eventmgr: make fd and sockets use CFileDescriptor make use of the hyprutils CFileDescriptor instead of manual FD and socket handling and closing. * eventloopmgr: make timerfd use CFileDescriptor make the timerfd use CFileDescriptor instead of manual fd handling * opengl: make gbm fd use CFileDescriptor make the gbm rendernode fd use CFileDescriptor instead of manual fd handling * core: make selection source/offer use CFileDescriptor make data selection source and offers use CFileDescriptor and its associated use in xwm and protocols * protocols: convert protocols fd to CFileDescriptor make most fd handling use CFileDescriptor in protocols * shm: make SHMPool use CfileDescriptor make SHMPool use CFileDescriptor instead of manual fd handling. * opengl: duplicate fd with CFileDescriptor duplicate fenceFD with CFileDescriptor duplicate instead. * xwayland: make sockets and fds use CFileDescriptor instead of manual opening/closing make sockets and fds use CFileDescriptor * keybindmgr: make sockets and fds use CFileDescriptor make sockets and fds use CFileDescriptor instead of manual handling.
2025-01-30 12:30:12 +01:00
read(pipeSock[0].get(), &grandchild, sizeof(grandchild));
// clear child and leave grandchild to init
waitpid(child, nullptr, 0);
if (grandchild < 0) {
2022-06-16 01:06:51 +08:00
Debug::log(LOG, "Fail to create the second fork");
2023-02-19 13:59:39 +00:00
return 0;
2022-06-16 01:06:51 +08:00
}
2022-11-10 13:39:23 +00:00
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "Process Created with pid {}", grandchild);
2022-11-10 13:39:23 +00:00
2023-02-19 13:59:39 +00:00
return grandchild;
2022-03-19 17:48:18 +01:00
}
SDispatchResult CKeybindManager::killActive(std::string args) {
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PWINDOW) {
Debug::log(ERR, "killActive: no window found");
return {.success = false, .error = "killActive: no window found"};
}
kill(PWINDOW->getPID(), SIGKILL);
return {};
}
SDispatchResult CKeybindManager::closeActive(std::string args) {
g_pCompositor->closeWindow(g_pCompositor->m_lastWindow.lock());
return {};
}
SDispatchResult CKeybindManager::closeWindow(std::string args) {
2022-08-30 21:35:27 +02:00
const auto PWINDOW = g_pCompositor->getWindowByRegex(args);
if (!PWINDOW) {
Debug::log(ERR, "closeWindow: no window found");
return {.success = false, .error = "closeWindow: no window found"};
2022-08-30 21:35:27 +02:00
}
g_pCompositor->closeWindow(PWINDOW);
return {};
2022-08-30 21:35:27 +02:00
}
SDispatchResult CKeybindManager::killWindow(std::string args) {
const auto PWINDOW = g_pCompositor->getWindowByRegex(args);
if (!PWINDOW) {
Debug::log(ERR, "killWindow: no window found");
return {.success = false, .error = "killWindow: no window found"};
}
kill(PWINDOW->getPID(), SIGKILL);
return {};
}
SDispatchResult CKeybindManager::signalActive(std::string args) {
if (!isNumber(args))
return {.success = false, .error = "signalActive: signal has to be int"};
try {
const auto SIGNALNUM = std::stoi(args);
if (SIGNALNUM < 1 || SIGNALNUM > 31) {
Debug::log(ERR, "signalActive: invalid signal number {}", SIGNALNUM);
return {.success = false, .error = std::format("signalActive: invalid signal number {}", SIGNALNUM)};
}
kill(g_pCompositor->m_lastWindow.lock()->getPID(), SIGNALNUM);
} catch (const std::exception& e) {
Debug::log(ERR, "signalActive: invalid signal format \"{}\"", args);
return {.success = false, .error = std::format("signalActive: invalid signal format \"{}\"", args)};
}
kill(g_pCompositor->m_lastWindow.lock()->getPID(), std::stoi(args));
return {};
}
SDispatchResult CKeybindManager::signalWindow(std::string args) {
const auto WINDOWREGEX = args.substr(0, args.find_first_of(','));
const auto SIGNAL = args.substr(args.find_first_of(',') + 1);
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
if (!PWINDOW) {
Debug::log(ERR, "signalWindow: no window");
return {.success = false, .error = "signalWindow: no window"};
}
if (!std::all_of(SIGNAL.begin(), SIGNAL.end(), ::isdigit))
return {.success = false, .error = "signalWindow: signal has to be int"};
try {
const auto SIGNALNUM = std::stoi(SIGNAL);
if (SIGNALNUM < 1 || SIGNALNUM > 31) {
Debug::log(ERR, "signalWindow: invalid signal number {}", SIGNALNUM);
return {.success = false, .error = std::format("signalWindow: invalid signal number {}", SIGNALNUM)};
}
kill(PWINDOW->getPID(), SIGNALNUM);
} catch (const std::exception& e) {
Debug::log(ERR, "signalWindow: invalid signal format \"{}\"", SIGNAL);
return {.success = false, .error = std::format("signalWindow: invalid signal format \"{}\"", SIGNAL)};
}
return {};
}
void CKeybindManager::clearKeybinds() {
2024-11-18 19:56:26 +00:00
m_vKeybinds.clear();
2022-03-20 11:14:24 +01:00
}
static SDispatchResult toggleActiveFloatingCore(std::string args, std::optional<bool> floatState) {
PHLWINDOW PWINDOW = nullptr;
2022-03-20 11:14:24 +01:00
if (args != "active" && args.length() > 1)
PWINDOW = g_pCompositor->getWindowByRegex(args);
else
PWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
if (floatState.has_value() && floatState == PWINDOW->m_bIsFloating)
return {};
// remove drag status
if (!g_pInputManager->currentlyDraggedWindow.expired())
g_pKeybindManager->changeMouseBindMode(MBIND_INVALID);
2022-06-30 12:09:05 +02:00
if (PWINDOW->m_sGroupData.pNextWindow.lock() && PWINDOW->m_sGroupData.pNextWindow.lock() != PWINDOW) {
const auto PCURRENT = PWINDOW->getGroupCurrent();
2022-05-31 14:01:00 +02:00
2023-02-19 21:07:32 +00:00
PCURRENT->m_bIsFloating = !PCURRENT->m_bIsFloating;
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PCURRENT);
PHLWINDOW curr = PCURRENT->m_sGroupData.pNextWindow.lock();
2023-02-19 21:07:32 +00:00
while (curr != PCURRENT) {
curr->m_bIsFloating = PCURRENT->m_bIsFloating;
curr = curr->m_sGroupData.pNextWindow.lock();
2023-02-19 21:07:32 +00:00
}
} else {
PWINDOW->m_bIsFloating = !PWINDOW->m_bIsFloating;
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PWINDOW);
}
if (PWINDOW->m_pWorkspace) {
PWINDOW->m_pWorkspace->updateWindows();
PWINDOW->m_pWorkspace->updateWindowData();
}
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID());
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
return {};
2022-03-20 15:55:47 +01:00
}
SDispatchResult CKeybindManager::toggleActiveFloating(std::string args) {
2024-04-04 01:16:47 +01:00
return toggleActiveFloatingCore(args, std::nullopt);
}
SDispatchResult CKeybindManager::setActiveFloating(std::string args) {
2024-04-04 01:16:47 +01:00
return toggleActiveFloatingCore(args, true);
}
SDispatchResult CKeybindManager::setActiveTiled(std::string args) {
2024-04-04 01:16:47 +01:00
return toggleActiveFloatingCore(args, false);
}
SDispatchResult CKeybindManager::centerWindow(std::string args) {
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
if (!PWINDOW || !PWINDOW->m_bIsFloating || PWINDOW->isFullscreen())
return {.success = false, .error = "No floating window found"};
const auto PMONITOR = PWINDOW->m_pMonitor.lock();
auto RESERVEDOFFSET = Vector2D();
if (args == "1")
RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f;
*PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize->goal() / 2.f + RESERVEDOFFSET;
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition->goal();
return {};
}
SDispatchResult CKeybindManager::toggleActivePseudo(std::string args) {
PHLWINDOW PWINDOW = nullptr;
2022-04-02 20:04:32 +02:00
if (args != "active" && args.length() > 1)
PWINDOW = g_pCompositor->getWindowByRegex(args);
else
PWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
2022-04-02 20:04:32 +02:00
PWINDOW->m_bIsPseudotiled = !PWINDOW->m_bIsPseudotiled;
2022-04-02 20:04:32 +02:00
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
if (!PWINDOW->isFullscreen())
g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW);
return {};
2022-04-02 20:04:32 +02:00
}
static SWorkspaceIDName getWorkspaceToChangeFromArgs(std::string args, PHLWORKSPACE PCURRENTWORKSPACE, PHLMONITORREF PMONITOR) {
if (!args.starts_with("previous")) {
return getWorkspaceIDNameFromString(args);
}
const bool PER_MON = args.contains("_per_monitor");
const SWorkspaceIDName PPREVWS = PER_MON ? PMONITOR->getPrevWorkspaceIDName(PCURRENTWORKSPACE->m_iID) : PCURRENTWORKSPACE->getPrevWorkspaceIDName();
// Do nothing if there's no previous workspace, otherwise switch to it.
if (PPREVWS.id == -1 || PPREVWS.id == PCURRENTWORKSPACE->m_iID) {
Debug::log(LOG, "No previous workspace to change to");
return {.id = WORKSPACE_NOT_CHANGED};
}
if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(PPREVWS.id); PWORKSPACETOCHANGETO) {
return {.id = PWORKSPACETOCHANGETO->m_iID, .name = PWORKSPACETOCHANGETO->m_szName};
}
return {.id = PPREVWS.id, .name = PPREVWS.name.empty() ? std::to_string(PPREVWS.id) : PPREVWS.name};
}
2022-04-21 16:38:48 +02:00
SDispatchResult CKeybindManager::changeworkspace(std::string args) {
// Workspace_back_and_forth being enabled means that an attempt to switch to
// the current workspace will instead switch to the previous.
static auto PBACKANDFORTH = CConfigValue<Hyprlang::INT>("binds:workspace_back_and_forth");
static auto PALLOWWORKSPACECYCLES = CConfigValue<Hyprlang::INT>("binds:allow_workspace_cycles");
static auto PWORKSPACECENTERON = CConfigValue<Hyprlang::INT>("binds:workspace_center_on");
static auto PHIDESPECIALONWORKSPACECHANGE = CConfigValue<Hyprlang::INT>("binds:hide_special_on_workspace_change");
const auto PMONITOR = g_pCompositor->m_lastMonitor.lock();
if (!PMONITOR)
return {.success = false, .error = "Last monitor not found"};
const auto PCURRENTWORKSPACE = PMONITOR->activeWorkspace;
const bool EXPLICITPREVIOUS = args.contains("previous");
2022-04-14 23:02:10 +02:00
const auto& [workspaceToChangeTo, workspaceName] = getWorkspaceToChangeFromArgs(args, PCURRENTWORKSPACE, PMONITOR);
if (workspaceToChangeTo == WORKSPACE_INVALID) {
2022-04-20 16:53:41 +02:00
Debug::log(ERR, "Error in changeworkspace, invalid value");
return {.success = false, .error = "Error in changeworkspace, invalid value"};
2022-03-20 15:55:47 +01:00
}
if (workspaceToChangeTo == WORKSPACE_NOT_CHANGED)
return {};
const SWorkspaceIDName PPREVWS = args.contains("_per_monitor") ? PMONITOR->getPrevWorkspaceIDName(PCURRENTWORKSPACE->m_iID) : PCURRENTWORKSPACE->getPrevWorkspaceIDName();
const bool BISWORKSPACECURRENT = workspaceToChangeTo == PCURRENTWORKSPACE->m_iID;
if (BISWORKSPACECURRENT && (!(*PBACKANDFORTH || EXPLICITPREVIOUS) || PPREVWS.id == -1)) {
if (*PHIDESPECIALONWORKSPACECHANGE)
PMONITOR->setSpecialWorkspace(nullptr);
return {.success = false, .error = "Previous workspace doesn't exist"};
}
2022-03-20 15:55:47 +01:00
g_pInputManager->unconstrainMouse();
g_pInputManager->m_bEmptyFocusCursorSet = false;
auto pWorkspaceToChangeTo = g_pCompositor->getWorkspaceByID(BISWORKSPACECURRENT ? PPREVWS.id : workspaceToChangeTo);
if (!pWorkspaceToChangeTo)
pWorkspaceToChangeTo =
g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PPREVWS.id : workspaceToChangeTo, PMONITOR->ID, BISWORKSPACECURRENT ? PPREVWS.name : workspaceName);
2022-03-20 15:55:47 +01:00
if (!BISWORKSPACECURRENT && pWorkspaceToChangeTo->m_bIsSpecialWorkspace) {
PMONITOR->setSpecialWorkspace(pWorkspaceToChangeTo);
g_pInputManager->simulateMouseMovement();
return {};
}
2022-08-21 20:21:21 +10:00
g_pInputManager->releaseAllMouseButtons();
const auto PMONITORWORKSPACEOWNER = PMONITOR == pWorkspaceToChangeTo->m_pMonitor ? PMONITOR : pWorkspaceToChangeTo->m_pMonitor.lock();
2022-05-12 11:27:31 +02:00
if (!PMONITORWORKSPACEOWNER)
return {.success = false, .error = "Workspace to switch to has no monitor"};
updateRelativeCursorCoords();
g_pCompositor->setActiveMonitor(PMONITORWORKSPACEOWNER);
if (BISWORKSPACECURRENT) {
if (*PALLOWWORKSPACECYCLES)
pWorkspaceToChangeTo->rememberPrevWorkspace(PCURRENTWORKSPACE);
else if (!EXPLICITPREVIOUS && !*PBACKANDFORTH)
pWorkspaceToChangeTo->rememberPrevWorkspace(nullptr);
} else
pWorkspaceToChangeTo->rememberPrevWorkspace(PCURRENTWORKSPACE);
if (*PHIDESPECIALONWORKSPACECHANGE)
PMONITORWORKSPACEOWNER->setSpecialWorkspace(nullptr);
PMONITORWORKSPACEOWNER->changeWorkspace(pWorkspaceToChangeTo, false, true);
2022-05-31 14:01:00 +02:00
if (PMONITOR != PMONITORWORKSPACEOWNER) {
Vector2D middle = PMONITORWORKSPACEOWNER->middle();
if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) {
g_pCompositor->focusWindow(PLAST);
if (*PWORKSPACECENTERON == 1)
middle = PLAST->middle();
}
g_pCompositor->warpCursorTo(middle);
}
if (!g_pInputManager->m_bLastFocusOnLS) {
if (g_pCompositor->m_lastFocus)
g_pInputManager->sendMotionEventsToFocused();
else
g_pInputManager->simulateMouseMovement();
}
const static auto PWARPONWORKSPACECHANGE = CConfigValue<Hyprlang::INT>("cursor:warp_on_change_workspace");
if (*PWARPONWORKSPACECHANGE > 0) {
auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow();
auto HLSurface = CWLSurface::fromResource(g_pSeatManager->state.pointerFocus.lock());
if (PLAST && (!HLSurface || HLSurface->getWindow()))
PLAST->warpCursor(*PWARPONWORKSPACECHANGE == 2);
}
return {};
2022-03-21 19:18:33 +01:00
}
SDispatchResult CKeybindManager::fullscreenActive(std::string args) {
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
2022-03-21 19:18:33 +01:00
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
2022-03-21 19:18:33 +01:00
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
const eFullscreenMode MODE = args == "1" ? FSMODE_MAXIMIZED : FSMODE_FULLSCREEN;
if (PWINDOW->isEffectiveInternalFSMode(MODE))
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
else
g_pCompositor->setWindowFullscreenInternal(PWINDOW, MODE);
return {};
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
}
SDispatchResult CKeybindManager::fullscreenStateActive(std::string args) {
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
const auto ARGS = CVarList(args, 2, ' ');
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_SET_PROP);
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
int internalMode, clientMode;
try {
internalMode = std::stoi(ARGS[0]);
} catch (std::exception& e) { internalMode = -1; }
try {
clientMode = std::stoi(ARGS[1]);
} catch (std::exception& e) { clientMode = -1; }
const SFullscreenState STATE = SFullscreenState{.internal = (internalMode != -1 ? (eFullscreenMode)internalMode : PWINDOW->m_sFullscreenState.internal),
.client = (clientMode != -1 ? (eFullscreenMode)clientMode : PWINDOW->m_sFullscreenState.client)};
if (internalMode != -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal && PWINDOW->m_sFullscreenState.client == STATE.client)
g_pCompositor->setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = FSMODE_NONE, .client = FSMODE_NONE});
else if (internalMode != -1 && clientMode == -1 && PWINDOW->m_sFullscreenState.internal == STATE.internal)
g_pCompositor->setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = FSMODE_NONE, .client = PWINDOW->m_sFullscreenState.client});
else if (internalMode == -1 && clientMode != -1 && PWINDOW->m_sFullscreenState.client == STATE.client)
g_pCompositor->setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = PWINDOW->m_sFullscreenState.internal, .client = FSMODE_NONE});
else
g_pCompositor->setWindowFullscreenState(PWINDOW, STATE);
PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(PWINDOW->m_sFullscreenState.internal == PWINDOW->m_sFullscreenState.client, PRIORITY_SET_PROP);
return {};
2022-03-23 16:51:48 +01:00
}
SDispatchResult CKeybindManager::moveActiveToWorkspace(std::string args) {
PHLWINDOW PWINDOW = nullptr;
if (args.contains(',')) {
PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
args = args.substr(0, args.find_last_of(','));
} else {
PWINDOW = g_pCompositor->m_lastWindow.lock();
}
2022-03-23 16:51:48 +01:00
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
2022-03-23 16:51:48 +01:00
const auto& [WORKSPACEID, workspaceName] = getWorkspaceIDNameFromString(args);
if (WORKSPACEID == WORKSPACE_INVALID) {
2022-12-14 18:42:48 +00:00
Debug::log(LOG, "Invalid workspace in moveActiveToWorkspace");
return {.success = false, .error = "Invalid workspace in moveActiveToWorkspace"};
2022-12-14 18:42:48 +00:00
}
if (WORKSPACEID == PWINDOW->workspaceID()) {
Debug::log(LOG, "Not moving to workspace because it didn't change.");
return {.success = false, .error = "Not moving to workspace because it didn't change."};
}
auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID);
PHLMONITOR pMonitor = nullptr;
const auto POLDWS = PWINDOW->m_pWorkspace;
static auto PALLOWWORKSPACECYCLES = CConfigValue<Hyprlang::INT>("binds:allow_workspace_cycles");
updateRelativeCursorCoords();
g_pHyprRenderer->damageWindow(PWINDOW);
if (pWorkspace) {
g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
pMonitor = pWorkspace->m_pMonitor.lock();
g_pCompositor->setActiveMonitor(pMonitor);
} else {
pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false);
pMonitor = pWorkspace->m_pMonitor.lock();
g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
2022-05-31 14:01:00 +02:00
}
2022-06-08 15:52:38 +02:00
POLDWS->m_pLastFocusedWindow = POLDWS->getFirstWindow();
if (pWorkspace->m_bIsSpecialWorkspace)
pMonitor->setSpecialWorkspace(pWorkspace);
else if (POLDWS->m_bIsSpecialWorkspace)
POLDWS->m_pMonitor.lock()->setSpecialWorkspace(nullptr);
if (*PALLOWWORKSPACECYCLES)
pWorkspace->rememberPrevWorkspace(POLDWS);
pMonitor->changeWorkspace(pWorkspace);
g_pCompositor->focusWindow(PWINDOW);
PWINDOW->warpCursor();
return {};
}
2022-04-09 13:26:55 +02:00
SDispatchResult CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
PHLWINDOW PWINDOW = nullptr;
if (args.contains(',')) {
PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
args = args.substr(0, args.find_last_of(','));
} else {
PWINDOW = g_pCompositor->m_lastWindow.lock();
}
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
const auto& [WORKSPACEID, workspaceName] = getWorkspaceIDNameFromString(args);
if (WORKSPACEID == WORKSPACE_INVALID) {
2022-05-18 12:18:58 +02:00
Debug::log(ERR, "Error in moveActiveToWorkspaceSilent, invalid value");
return {.success = false, .error = "Error in moveActiveToWorkspaceSilent, invalid value"};
2022-05-18 12:18:58 +02:00
}
if (WORKSPACEID == PWINDOW->workspaceID())
return {};
2022-05-18 12:18:58 +02:00
g_pHyprRenderer->damageWindow(PWINDOW);
auto pWorkspace = g_pCompositor->getWorkspaceByID(WORKSPACEID);
const auto OLDMIDDLE = PWINDOW->middle();
2022-05-18 12:18:58 +02:00
if (pWorkspace) {
g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
} else {
pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->monitorID(), workspaceName, false);
g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace);
2022-09-12 21:05:52 +02:00
}
2022-05-18 12:18:58 +02:00
if (PWINDOW == g_pCompositor->m_lastWindow) {
if (const auto PATCOORDS = g_pCompositor->vectorToWindowUnified(OLDMIDDLE, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING, PWINDOW); PATCOORDS)
g_pCompositor->focusWindow(PATCOORDS);
else
g_pInputManager->refocus();
}
return {};
2022-05-18 12:18:58 +02:00
}
SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
static auto PFULLCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_fullscreen");
static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback");
static auto PGROUPCYCLE = CConfigValue<Hyprlang::INT>("binds:movefocus_cycles_groupfirst");
char arg = args[0];
2022-04-09 13:26:55 +02:00
2022-05-05 12:50:25 +02:00
if (!isDirection(args)) {
2023-09-06 12:51:36 +02:00
Debug::log(ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
return {.success = false, .error = std::format("Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)};
2022-04-09 13:26:55 +02:00
}
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PLASTWINDOW) {
if (*PMONITORFALLBACK)
tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(arg));
return {};
}
2022-08-08 22:46:11 +02:00
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ?
g_pCompositor->getWindowCycle(PLASTWINDOW, true, {}, false, arg != 'd' && arg != 'b' && arg != 'r') :
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
2022-04-09 13:26:55 +02:00
// Prioritize focus change within groups if the window is a part of it.
if (*PGROUPCYCLE && PLASTWINDOW->m_sGroupData.pNextWindow) {
auto isTheOnlyGroupOnWs = !PWINDOWTOCHANGETO && g_pCompositor->m_monitors.size() == 1;
if (arg == 'l' && (PLASTWINDOW != PLASTWINDOW->getGroupHead() || isTheOnlyGroupOnWs)) {
PLASTWINDOW->setGroupCurrent(PLASTWINDOW->getGroupPrevious());
return {};
}
else if (arg == 'r' && (PLASTWINDOW != PLASTWINDOW->getGroupTail() || isTheOnlyGroupOnWs)) {
PLASTWINDOW->setGroupCurrent(PLASTWINDOW->m_sGroupData.pNextWindow.lock());
return {};
}
}
// Found window in direction, switch to it
2022-04-09 13:33:44 +02:00
if (PWINDOWTOCHANGETO) {
2022-04-13 20:45:06 +02:00
switchToWindow(PWINDOWTOCHANGETO);
return {};
2022-04-13 20:45:06 +02:00
}
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "No window found in direction {}, looking for a monitor", arg);
if (*PMONITORFALLBACK && tryMoveFocusToMonitor(g_pCompositor->getMonitorInDirection(arg)))
return {};
static auto PNOFALLBACK = CConfigValue<Hyprlang::INT>("general:no_focus_fallback");
if (*PNOFALLBACK)
return {.success = false, .error = std::format("Nothing to focus to in direction {}", arg)};
Debug::log(LOG, "No monitor found in direction {}, getting the inverse edge", arg);
const auto PMONITOR = PLASTWINDOW->m_pMonitor.lock();
if (!PMONITOR)
return {.success = false, .error = "last window has no monitor?"};
if (arg == 'l' || arg == 'r') {
if (STICKS(PLASTWINDOW->m_vPosition.x, PMONITOR->vecPosition.x) && STICKS(PLASTWINDOW->m_vSize.x, PMONITOR->vecSize.x))
return {.success = false, .error = "move does not make sense, would return back"};
} else if (STICKS(PLASTWINDOW->m_vPosition.y, PMONITOR->vecPosition.y) && STICKS(PLASTWINDOW->m_vSize.y, PMONITOR->vecSize.y))
return {.success = false, .error = "move does not make sense, would return back"};
CBox box = PMONITOR->logicalBox();
switch (arg) {
case 'l':
box.x += box.w;
box.w = 1;
break;
case 'r':
box.x -= 1;
box.w = 1;
break;
case 'u':
case 't':
box.y += box.h;
box.h = 1;
break;
case 'd':
case 'b':
box.y -= 1;
box.h = 1;
break;
}
const auto PWINDOWCANDIDATE = g_pCompositor->getWindowInDirection(box, PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace, arg,
PLASTWINDOW, PLASTWINDOW->m_bIsFloating);
if (PWINDOWCANDIDATE)
switchToWindow(PWINDOWCANDIDATE);
return {};
}
SDispatchResult CKeybindManager::focusUrgentOrLast(std::string args) {
const auto PWINDOWURGENT = g_pCompositor->getUrgentWindow();
const auto PWINDOWPREV = g_pCompositor->m_lastWindow.lock() ? (g_pCompositor->m_windowFocusHistory.size() < 2 ? nullptr : g_pCompositor->m_windowFocusHistory[1].lock()) :
(g_pCompositor->m_windowFocusHistory.empty() ? nullptr : g_pCompositor->m_windowFocusHistory[0].lock());
if (!PWINDOWURGENT && !PWINDOWPREV)
return {.success = false, .error = "Window not found"};
switchToWindow(PWINDOWURGENT ? PWINDOWURGENT : PWINDOWPREV);
return {};
}
SDispatchResult CKeybindManager::focusCurrentOrLast(std::string args) {
const auto PWINDOWPREV = g_pCompositor->m_lastWindow.lock() ? (g_pCompositor->m_windowFocusHistory.size() < 2 ? nullptr : g_pCompositor->m_windowFocusHistory[1].lock()) :
(g_pCompositor->m_windowFocusHistory.empty() ? nullptr : g_pCompositor->m_windowFocusHistory[0].lock());
2023-02-14 06:16:58 +05:30
if (!PWINDOWPREV)
return {.success = false, .error = "Window not found"};
2023-02-14 06:16:58 +05:30
switchToWindow(PWINDOWPREV);
return {};
2023-02-14 06:16:58 +05:30
}
SDispatchResult CKeybindManager::swapActive(std::string args) {
2023-04-10 21:07:49 +02:00
char arg = args[0];
2022-04-20 16:18:58 +02:00
2023-04-10 21:07:49 +02:00
if (!isDirection(args)) {
2023-09-06 12:51:36 +02:00
Debug::log(ERR, "Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)};
2023-04-10 21:07:49 +02:00
}
2022-05-05 13:02:55 +02:00
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "Swapping active window in direction {}", arg);
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PLASTWINDOW)
return {.success = false, .error = "Window to swap with not found"};
if (PLASTWINDOW->isFullscreen())
return {.success = false, .error = "Can't swap fullscreen window"};
2022-05-05 13:02:55 +02:00
2023-04-10 21:07:49 +02:00
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
if (!PWINDOWTOCHANGETO)
return {.success = false, .error = "Window to swap with not found"};
2022-05-05 13:02:55 +02:00
updateRelativeCursorCoords();
2023-04-10 21:07:49 +02:00
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO);
PLASTWINDOW->warpCursor();
return {};
2023-04-10 21:07:49 +02:00
}
2022-05-05 13:02:55 +02:00
SDispatchResult CKeybindManager::moveActiveTo(std::string args) {
char arg = args[0];
bool silent = args.ends_with(" silent");
if (silent)
args = args.substr(0, args.length() - 7);
2022-05-05 13:02:55 +02:00
if (args.starts_with("mon:")) {
2023-04-10 21:07:49 +02:00
const auto PNEWMONITOR = g_pCompositor->getMonitorFromString(args.substr(4));
if (!PNEWMONITOR)
return {.success = false, .error = std::format("Monitor {} not found", args.substr(4))};
2022-05-05 13:02:55 +02:00
if (silent)
moveActiveToWorkspaceSilent(PNEWMONITOR->activeWorkspace->getConfigName());
else
moveActiveToWorkspace(PNEWMONITOR->activeWorkspace->getConfigName());
return {};
2022-05-05 13:02:55 +02:00
}
2022-05-05 12:50:25 +02:00
if (!isDirection(args)) {
2023-09-06 12:51:36 +02:00
Debug::log(ERR, "Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
return {.success = false, .error = std::format("Cannot move window in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)};
2022-04-20 16:18:58 +02:00
}
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
2022-04-20 16:18:58 +02:00
if (!PLASTWINDOW)
return {.success = false, .error = "Window to move not found"};
if (PLASTWINDOW->isFullscreen())
return {.success = false, .error = "Can't move fullscreen window"};
2022-04-20 16:18:58 +02:00
if (PLASTWINDOW->m_bIsFloating) {
std::optional<float> vPosx, vPosy;
const auto PMONITOR = PLASTWINDOW->m_pMonitor.lock();
const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize();
switch (arg) {
case 'l': vPosx = PMONITOR->vecReservedTopLeft.x + BORDERSIZE + PMONITOR->vecPosition.x; break;
case 'r': vPosx = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize->goal().x - BORDERSIZE + PMONITOR->vecPosition.x; break;
case 't':
case 'u': vPosy = PMONITOR->vecReservedTopLeft.y + BORDERSIZE + PMONITOR->vecPosition.y; break;
case 'b':
case 'd': vPosy = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize->goal().y - BORDERSIZE + PMONITOR->vecPosition.y; break;
}
*PLASTWINDOW->m_vRealPosition = Vector2D(vPosx.value_or(PLASTWINDOW->m_vRealPosition->goal().x), vPosy.value_or(PLASTWINDOW->m_vRealPosition->goal().y));
return {};
}
2023-04-10 21:07:49 +02:00
// If the window to change to is on the same workspace, switch them
2022-04-20 16:18:58 +02:00
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
if (PWINDOWTOCHANGETO) {
updateRelativeCursorCoords();
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PLASTWINDOW, args, silent);
if (!silent)
PLASTWINDOW->warpCursor();
return {};
2023-04-10 21:07:49 +02:00
}
2022-04-20 16:18:58 +02:00
static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback");
if (!*PMONITORFALLBACK)
return {};
2023-04-10 21:07:49 +02:00
// Otherwise, we always want to move to the next monitor in that direction
const auto PMONITORTOCHANGETO = g_pCompositor->getMonitorInDirection(arg);
if (!PMONITORTOCHANGETO)
return {.success = false, .error = "Nowhere to move active window to"};
2023-03-20 01:42:21 +00:00
const auto PWORKSPACE = PMONITORTOCHANGETO->activeWorkspace;
if (silent)
moveActiveToWorkspaceSilent(PWORKSPACE->getConfigName());
else
moveActiveToWorkspace(PWORKSPACE->getConfigName());
return {};
2022-04-20 16:18:58 +02:00
}
SDispatchResult CKeybindManager::toggleGroup(std::string args) {
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
2023-02-19 21:07:32 +00:00
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
2023-02-19 21:07:32 +00:00
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
if (PWINDOW->isFullscreen())
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
if (PWINDOW->m_sGroupData.pNextWindow.expired())
PWINDOW->createGroup();
else
PWINDOW->destroyGroup();
return {};
}
SDispatchResult CKeybindManager::changeGroupActive(std::string args) {
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
2023-02-19 21:07:32 +00:00
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
2023-02-19 21:07:32 +00:00
if (PWINDOW->m_sGroupData.pNextWindow.expired())
return {.success = false, .error = "No next window in group"};
2023-02-19 21:07:32 +00:00
if (PWINDOW->m_sGroupData.pNextWindow.lock() == PWINDOW)
return {.success = false, .error = "Only one window in group"};
2023-02-19 21:07:32 +00:00
if (isNumber(args, false)) {
// index starts from '1'; '0' means last window
const int INDEX = std::stoi(args);
if (INDEX > PWINDOW->getGroupSize())
return {.success = false, .error = "Index too big, there aren't that many windows in this group"};
if (INDEX == 0)
PWINDOW->setGroupCurrent(PWINDOW->getGroupTail());
else
PWINDOW->setGroupCurrent(PWINDOW->getGroupWindowByIndex(INDEX - 1));
return {};
}
2023-02-24 17:24:51 +00:00
if (args != "b" && args != "prev") {
PWINDOW->setGroupCurrent(PWINDOW->m_sGroupData.pNextWindow.lock());
2023-02-24 17:24:51 +00:00
} else {
PWINDOW->setGroupCurrent(PWINDOW->getGroupPrevious());
2023-02-24 17:24:51 +00:00
}
return {};
2022-05-16 17:37:46 +02:00
}
SDispatchResult CKeybindManager::toggleSplit(std::string args) {
2022-05-16 17:37:46 +02:00
SLayoutMessageHeader header;
header.pWindow = g_pCompositor->m_lastWindow.lock();
if (!header.pWindow)
return {.success = false, .error = "Window not found"};
const auto PWORKSPACE = header.pWindow->m_pWorkspace;
if (PWORKSPACE->m_bHasFullscreenWindow)
return {.success = false, .error = "Can't split windows that already split"};
2022-05-16 17:37:46 +02:00
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "togglesplit");
return {};
2022-04-20 16:53:41 +02:00
}
SDispatchResult CKeybindManager::swapSplit(std::string args) {
SLayoutMessageHeader header;
header.pWindow = g_pCompositor->m_lastWindow.lock();
if (!header.pWindow)
return {.success = false, .error = "Window not found"};
const auto PWORKSPACE = header.pWindow->m_pWorkspace;
if (PWORKSPACE->m_bHasFullscreenWindow)
return {.success = false, .error = "Can't split windows that already split"};
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "swapsplit");
return {};
}
SDispatchResult CKeybindManager::alterSplitRatio(std::string args) {
std::optional<float> splitResult;
bool exact = false;
2022-04-20 16:53:41 +02:00
if (args.starts_with("exact")) {
exact = true;
splitResult = getPlusMinusKeywordResult(args.substr(5), 0);
} else
splitResult = getPlusMinusKeywordResult(args, 0);
2022-04-20 16:53:41 +02:00
if (!splitResult.has_value()) {
2022-04-20 16:53:41 +02:00
Debug::log(ERR, "Splitratio invalid in alterSplitRatio!");
return {.success = false, .error = "Splitratio invalid in alterSplitRatio!"};
2022-04-20 16:53:41 +02:00
}
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
2022-04-20 16:53:41 +02:00
if (!PLASTWINDOW)
return {.success = false, .error = "Window not found"};
2022-04-20 16:53:41 +02:00
g_pLayoutManager->getCurrentLayout()->alterSplitRatio(PLASTWINDOW, splitResult.value(), exact);
return {};
2022-05-05 12:50:25 +02:00
}
SDispatchResult CKeybindManager::focusMonitor(std::string arg) {
const auto PMONITOR = g_pCompositor->getMonitorFromString(arg);
2023-04-10 21:07:49 +02:00
tryMoveFocusToMonitor(PMONITOR);
return {};
2022-05-18 12:18:58 +02:00
}
2022-05-22 11:52:39 +02:00
SDispatchResult CKeybindManager::moveCursorToCorner(std::string arg) {
2022-05-22 11:52:39 +02:00
if (!isNumber(arg)) {
Debug::log(ERR, "moveCursorToCorner, arg has to be a number.");
return {.success = false, .error = "moveCursorToCorner, arg has to be a number."};
2022-05-22 11:52:39 +02:00
}
const auto CORNER = std::stoi(arg);
if (CORNER < 0 || CORNER > 3) {
Debug::log(ERR, "moveCursorToCorner, corner not 0 - 3.");
return {.success = false, .error = "moveCursorToCorner, corner not 0 - 3."};
2022-05-22 11:52:39 +02:00
}
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
2022-05-22 11:52:39 +02:00
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
2022-05-22 11:52:39 +02:00
switch (CORNER) {
case 0:
// bottom left
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition->value().x, PWINDOW->m_vRealPosition->value().y + PWINDOW->m_vRealSize->value().y}, true);
2022-05-22 11:52:39 +02:00
break;
case 1:
// bottom right
g_pCompositor->warpCursorTo(
{PWINDOW->m_vRealPosition->value().x + PWINDOW->m_vRealSize->value().x, PWINDOW->m_vRealPosition->value().y + PWINDOW->m_vRealSize->value().y}, true);
2022-05-22 11:52:39 +02:00
break;
case 2:
// top right
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition->value().x + PWINDOW->m_vRealSize->value().x, PWINDOW->m_vRealPosition->value().y}, true);
2022-05-22 11:52:39 +02:00
break;
case 3:
// top left
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition->value().x, PWINDOW->m_vRealPosition->value().y}, true);
2022-05-22 11:52:39 +02:00
break;
}
return {};
2022-05-26 19:05:32 +02:00
}
SDispatchResult CKeybindManager::moveCursor(std::string args) {
std::string x_str, y_str;
int x, y;
size_t i = args.find_first_of(' ');
if (i == std::string::npos) {
Debug::log(ERR, "moveCursor, takes 2 arguments.");
return {.success = false, .error = "moveCursor, takes 2 arguments"};
}
x_str = args.substr(0, i);
y_str = args.substr(i + 1);
if (!isNumber(x_str)) {
Debug::log(ERR, "moveCursor, x argument has to be a number.");
return {.success = false, .error = "moveCursor, x argument has to be a number."};
}
if (!isNumber(y_str)) {
Debug::log(ERR, "moveCursor, y argument has to be a number.");
return {.success = false, .error = "moveCursor, y argument has to be a number."};
}
x = std::stoi(x_str);
y = std::stoi(y_str);
g_pCompositor->warpCursorTo({x, y}, true);
return {};
}
SDispatchResult CKeybindManager::workspaceOpt(std::string args) {
2022-09-25 20:07:48 +02:00
2022-05-26 19:05:32 +02:00
// current workspace
const auto PWORKSPACE = g_pCompositor->m_lastMonitor->activeWorkspace;
2022-05-26 19:05:32 +02:00
if (!PWORKSPACE)
return {.success = false, .error = "Workspace not found"}; // ????
2022-05-26 19:05:32 +02:00
if (args == "allpseudo") {
PWORKSPACE->m_bDefaultPseudo = !PWORKSPACE->m_bDefaultPseudo;
// apply
for (auto const& w : g_pCompositor->m_windows) {
if (!w->m_bIsMapped || w->m_pWorkspace != PWORKSPACE)
2022-05-26 19:05:32 +02:00
continue;
2022-06-30 15:44:26 +02:00
w->m_bIsPseudotiled = PWORKSPACE->m_bDefaultPseudo;
2022-05-26 19:05:32 +02:00
}
} else if (args == "allfloat") {
PWORKSPACE->m_bDefaultFloating = !PWORKSPACE->m_bDefaultFloating;
// apply
// we make a copy because changeWindowFloatingMode might invalidate the iterator
std::vector<PHLWINDOW> ptrs(g_pCompositor->m_windows.begin(), g_pCompositor->m_windows.end());
2022-05-26 19:05:32 +02:00
for (auto const& w : ptrs) {
if (!w->m_bIsMapped || w->m_pWorkspace != PWORKSPACE || w->isHidden())
2022-05-26 19:05:32 +02:00
continue;
if (!w->m_bRequestsFloat && w->m_bIsFloating != PWORKSPACE->m_bDefaultFloating) {
const auto SAVEDPOS = w->m_vRealPosition->goal();
const auto SAVEDSIZE = w->m_vRealSize->goal();
2022-05-26 19:05:32 +02:00
w->m_bIsFloating = PWORKSPACE->m_bDefaultFloating;
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(w);
if (PWORKSPACE->m_bDefaultFloating) {
w->m_vRealPosition->setValueAndWarp(SAVEDPOS);
w->m_vRealSize->setValueAndWarp(SAVEDSIZE);
*w->m_vRealSize = w->m_vRealSize->value() + Vector2D(4, 4);
*w->m_vRealPosition = w->m_vRealPosition->value() - Vector2D(2, 2);
2022-05-26 19:05:32 +02:00
}
}
}
} else {
Debug::log(ERR, "Invalid arg in workspaceOpt, opt \"{}\" doesn't exist.", args);
return {.success = false, .error = std::format("Invalid arg in workspaceOpt, opt \"{}\" doesn't exist.", args)};
2022-05-26 19:05:32 +02:00
}
// recalc mon
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_lastMonitor->ID);
return {};
}
SDispatchResult CKeybindManager::renameWorkspace(std::string args) {
try {
const auto FIRSTSPACEPOS = args.find_first_of(' ');
if (FIRSTSPACEPOS != std::string::npos) {
int workspace = std::stoi(args.substr(0, FIRSTSPACEPOS));
std::string name = args.substr(FIRSTSPACEPOS + 1);
if (const auto& PWS = g_pCompositor->getWorkspaceByID(workspace); PWS)
PWS->rename(name);
else
return {.success = false, .error = "No such workspace"};
} else if (const auto& PWS = g_pCompositor->getWorkspaceByID(std::stoi(args)); PWS)
PWS->rename("");
else
return {.success = false, .error = "No such workspace"};
} catch (std::exception& e) {
Debug::log(ERR, R"(Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. "{}": "{}")", args, e.what());
return {.success = false, .error = std::format(R"(Invalid arg in renameWorkspace, expected numeric id only or a numeric id and string name. "{}": "{}")", args, e.what())};
}
return {};
}
SDispatchResult CKeybindManager::exitHyprland(std::string argz) {
g_pConfigManager->dispatchExecShutdown();
if (g_pCompositor->m_finalRequests)
return {}; // Exiting deferred until requests complete
g_pCompositor->stopCompositor();
return {};
2022-05-30 20:05:38 +02:00
}
SDispatchResult CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
PHLMONITOR PMONITOR = g_pCompositor->getMonitorFromString(args);
2022-05-30 20:05:38 +02:00
if (!PMONITOR) {
Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist");
return {.success = false, .error = "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist"};
}
2022-05-30 20:05:38 +02:00
// get the current workspace
const auto PCURRENTWORKSPACE = g_pCompositor->m_lastMonitor->activeWorkspace;
if (!PCURRENTWORKSPACE) {
Debug::log(ERR, "moveCurrentWorkspaceToMonitor invalid workspace!");
return {.success = false, .error = "moveCurrentWorkspaceToMonitor invalid workspace!"};
}
2022-05-30 20:05:38 +02:00
g_pCompositor->moveWorkspaceToMonitor(PCURRENTWORKSPACE, PMONITOR);
return {};
2022-05-30 20:05:38 +02:00
}
SDispatchResult CKeybindManager::moveWorkspaceToMonitor(std::string args) {
if (!args.contains(' '))
return {.success = false, .error = "Invalid arguments, expected: workspace monitor"};
2022-05-30 20:05:38 +02:00
std::string workspace = args.substr(0, args.find_first_of(' '));
std::string monitor = args.substr(args.find_first_of(' ') + 1);
2022-05-30 20:05:38 +02:00
const auto PMONITOR = g_pCompositor->getMonitorFromString(monitor);
2022-05-30 20:05:38 +02:00
if (!PMONITOR) {
2022-05-30 20:05:38 +02:00
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
return {.success = false, .error = "Ignoring moveWorkspaceToMonitor: monitor doesnt exist"};
2022-05-30 20:05:38 +02:00
}
const auto WORKSPACEID = getWorkspaceIDNameFromString(workspace).id;
2022-05-30 20:05:38 +02:00
if (WORKSPACEID == WORKSPACE_INVALID) {
2022-05-30 20:05:38 +02:00
Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!");
return {.success = false, .error = "moveWorkspaceToMonitor invalid workspace!"};
2022-05-30 20:05:38 +02:00
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
2022-05-31 18:47:32 +02:00
if (!PWORKSPACE) {
Debug::log(ERR, "moveWorkspaceToMonitor workspace doesn't exist!");
return {.success = false, .error = "moveWorkspaceToMonitor workspace doesn't exist!"};
2022-05-31 18:47:32 +02:00
}
2022-05-30 20:05:38 +02:00
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
return {};
2022-05-31 14:01:00 +02:00
}
SDispatchResult CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) {
auto [workspaceID, workspaceName] = getWorkspaceIDNameFromString(args);
if (workspaceID == WORKSPACE_INVALID) {
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!");
return {.success = false, .error = "focusWorkspaceOnCurrentMonitor invalid workspace!"};
}
const auto PCURRMONITOR = g_pCompositor->m_lastMonitor.lock();
if (!PCURRMONITOR) {
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!");
return {.success = false, .error = "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"};
}
auto pWorkspace = g_pCompositor->getWorkspaceByID(workspaceID);
if (!pWorkspace) {
pWorkspace = g_pCompositor->createNewWorkspace(workspaceID, PCURRMONITOR->ID, workspaceName);
// we can skip the moving, since it's already on the current monitor
changeworkspace(pWorkspace->getConfigName());
return {};
}
static auto PBACKANDFORTH = CConfigValue<Hyprlang::INT>("binds:workspace_back_and_forth");
const auto PREVWS = pWorkspace->getPrevWorkspaceIDName();
if (*PBACKANDFORTH && PCURRMONITOR->activeWorkspaceID() == workspaceID && PREVWS.id != -1) {
// Workspace to focus is previous workspace
pWorkspace = g_pCompositor->getWorkspaceByID(PREVWS.id);
if (!pWorkspace)
pWorkspace = g_pCompositor->createNewWorkspace(PREVWS.id, PCURRMONITOR->ID, PREVWS.name);
workspaceID = pWorkspace->m_iID;
}
if (pWorkspace->m_pMonitor != PCURRMONITOR) {
const auto POLDMONITOR = pWorkspace->m_pMonitor.lock();
if (!POLDMONITOR) { // wat
Debug::log(ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!");
return {.success = false, .error = "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"};
}
if (POLDMONITOR->activeWorkspaceID() == workspaceID) {
g_pCompositor->swapActiveWorkspaces(POLDMONITOR, PCURRMONITOR);
return {};
} else {
g_pCompositor->moveWorkspaceToMonitor(pWorkspace, PCURRMONITOR, true);
}
}
changeworkspace(pWorkspace->getConfigName());
return {};
}
SDispatchResult CKeybindManager::toggleSpecialWorkspace(std::string args) {
const auto& [workspaceID, workspaceName] = getWorkspaceIDNameFromString("special:" + args);
if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) {
2022-11-27 22:42:22 +00:00
Debug::log(ERR, "Invalid workspace passed to special");
return {.success = false, .error = "Invalid workspace passed to special"};
2022-11-27 22:42:22 +00:00
}
bool requestedWorkspaceIsAlreadyOpen = false;
const auto PMONITOR = g_pCompositor->m_lastMonitor;
auto specialOpenOnMonitor = PMONITOR->activeSpecialWorkspaceID();
2022-05-31 14:01:00 +02:00
for (auto const& m : g_pCompositor->m_monitors) {
if (m->activeSpecialWorkspaceID() == workspaceID) {
2022-11-27 22:42:22 +00:00
requestedWorkspaceIsAlreadyOpen = true;
2022-05-31 14:01:00 +02:00
break;
}
}
updateRelativeCursorCoords();
PHLWORKSPACEREF focusedWorkspace;
2022-11-27 22:42:22 +00:00
if (requestedWorkspaceIsAlreadyOpen && specialOpenOnMonitor == workspaceID) {
// already open on this monitor
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "Toggling special workspace {} to closed", workspaceID);
PMONITOR->setSpecialWorkspace(nullptr);
focusedWorkspace = PMONITOR->activeWorkspace;
2022-05-31 14:01:00 +02:00
} else {
2023-09-06 12:51:36 +02:00
Debug::log(LOG, "Toggling special workspace {} to open", workspaceID);
2022-11-27 22:42:22 +00:00
auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceID);
2022-07-07 19:01:42 +02:00
if (!PSPECIALWORKSPACE)
PSPECIALWORKSPACE = g_pCompositor->createNewWorkspace(workspaceID, PMONITOR->ID, workspaceName);
2022-07-07 19:01:42 +02:00
PMONITOR->setSpecialWorkspace(PSPECIALWORKSPACE);
focusedWorkspace = PSPECIALWORKSPACE;
}
const static auto PWARPONTOGGLESPECIAL = CConfigValue<Hyprlang::INT>("cursor:warp_on_toggle_special");
if (*PWARPONTOGGLESPECIAL > 0) {
auto PLAST = focusedWorkspace->getLastFocusedWindow();
auto HLSurface = CWLSurface::fromResource(g_pSeatManager->state.pointerFocus.lock());
if (PLAST && (!HLSurface || HLSurface->getWindow()))
PLAST->warpCursor(*PWARPONTOGGLESPECIAL == 2);
2022-08-31 17:02:44 +02:00
}
return {};
}
SDispatchResult CKeybindManager::forceRendererReload(std::string args) {
2022-06-30 23:55:28 +02:00
bool overAgain = false;
for (auto const& m : g_pCompositor->m_monitors) {
2023-03-16 14:03:40 +00:00
if (!m->output)
continue;
auto rule = g_pConfigManager->getMonitorRuleFor(m);
if (!m->applyMonitorRule(&rule, true)) {
2022-06-30 23:55:28 +02:00
overAgain = true;
break;
}
}
2022-06-30 23:55:28 +02:00
if (overAgain)
forceRendererReload(args);
return {};
2022-06-06 19:32:14 +02:00
}
SDispatchResult CKeybindManager::resizeActive(std::string args) {
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PLASTWINDOW)
return {.success = false, .error = "No window found"};
if (PLASTWINDOW->isFullscreen())
return {.success = false, .error = "Window is fullscreen"};
2022-08-09 11:57:09 +03:00
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize->goal());
2022-06-06 19:32:14 +02:00
if (SIZ.x < 1 || SIZ.y < 1)
return {.success = false, .error = "Invalid size provided"};
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PLASTWINDOW->m_vRealSize->goal());
if (PLASTWINDOW->m_vRealSize->goal().x > 1 && PLASTWINDOW->m_vRealSize->goal().y > 1)
PLASTWINDOW->setHidden(false);
return {};
}
SDispatchResult CKeybindManager::moveActive(std::string args) {
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PLASTWINDOW)
return {.success = false, .error = "No window found"};
if (PLASTWINDOW->isFullscreen())
return {.success = false, .error = "Window is fullscreen"};
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition->goal());
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PLASTWINDOW->m_vRealPosition->goal());
return {};
}
SDispatchResult CKeybindManager::moveWindow(std::string args) {
const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
const auto MOVECMD = args.substr(0, args.find_first_of(','));
2022-08-09 11:57:09 +03:00
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
if (!PWINDOW) {
Debug::log(ERR, "moveWindow: no window");
return {.success = false, .error = "moveWindow: no window"};
2022-06-06 19:32:14 +02:00
}
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
if (PWINDOW->isFullscreen())
return {.success = false, .error = "Window is fullscreen"};
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition->goal());
2022-06-06 19:32:14 +02:00
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition->goal(), PWINDOW);
return {};
2022-06-10 11:39:06 +02:00
}
SDispatchResult CKeybindManager::resizeWindow(std::string args) {
const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
const auto MOVECMD = args.substr(0, args.find_first_of(','));
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
if (!PWINDOW) {
Debug::log(ERR, "resizeWindow: no window");
return {.success = false, .error = "resizeWindow: no window"};
}
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
if (PWINDOW->isFullscreen())
return {.success = false, .error = "Window is fullscreen"};
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize->goal());
if (SIZ.x < 1 || SIZ.y < 1)
return {.success = false, .error = "Invalid size provided"};
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize->goal(), CORNER_NONE, PWINDOW);
if (PWINDOW->m_vRealSize->goal().x > 1 && PWINDOW->m_vRealSize->goal().y > 1)
PWINDOW->setHidden(false);
return {};
}
SDispatchResult CKeybindManager::circleNext(std::string arg) {
if (g_pCompositor->m_lastWindow.expired()) {
2022-10-28 21:31:39 +01:00
// if we have a clear focus, find the first window and get the next focusable.
const auto PWS = g_pCompositor->m_lastMonitor->activeWorkspace;
if (PWS && PWS->getWindows() > 0) {
const auto PWINDOW = PWS->getFirstWindow();
2022-10-28 21:31:39 +01:00
switchToWindow(PWINDOW);
}
return {};
2022-10-28 21:31:39 +01:00
}
CVarList args{arg, 0, 's', true};
std::optional<bool> floatStatus = {};
if (args.contains("tile") || args.contains("tiled"))
floatStatus = false;
else if (args.contains("float") || args.contains("floating"))
floatStatus = true;
const auto VISIBLE = args.contains("visible") || args.contains("v");
const auto PREV = args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l");
const auto NEXT = args.contains("next") || args.contains("n"); // prev is default in classic alt+tab
const auto HIST = args.contains("hist") || args.contains("h");
const auto& w = HIST ? g_pCompositor->getWindowCycleHist(g_pCompositor->m_lastWindow, true, floatStatus, VISIBLE, NEXT) :
g_pCompositor->getWindowCycle(g_pCompositor->m_lastWindow.lock(), true, floatStatus, VISIBLE, PREV);
switchToWindow(w, HIST);
return {};
2022-06-10 11:39:06 +02:00
}
2022-06-10 12:06:27 +02:00
SDispatchResult CKeybindManager::focusWindow(std::string regexp) {
2022-07-26 17:30:30 +02:00
const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp);
2022-07-26 17:30:30 +02:00
if (!PWINDOW)
return {.success = false, .error = "No such window found"};
2022-06-10 12:06:27 +02:00
Debug::log(LOG, "Focusing to window name: {}", PWINDOW->m_szTitle);
2022-06-10 12:06:27 +02:00
const auto PWORKSPACE = PWINDOW->m_pWorkspace;
if (!PWORKSPACE) {
Debug::log(ERR, "BUG THIS: null workspace in focusWindow");
return {.success = false, .error = "BUG THIS: null workspace in focusWindow"};
}
updateRelativeCursorCoords();
if (g_pCompositor->m_lastMonitor && g_pCompositor->m_lastMonitor->activeWorkspace != PWINDOW->m_pWorkspace &&
g_pCompositor->m_lastMonitor->activeSpecialWorkspace != PWINDOW->m_pWorkspace) {
Debug::log(LOG, "Fake executing workspace to move focus");
changeworkspace(PWORKSPACE->getConfigName());
}
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto FSWINDOW = PWORKSPACE->getFullscreenWindow();
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
2024-02-26 00:15:59 +00:00
if (PWINDOW->m_bIsFloating) {
// don't make floating implicitly fs
if (!PWINDOW->m_bCreatedOverFullscreen) {
g_pCompositor->changeWindowZOrder(PWINDOW, true);
g_pCompositor->updateFullscreenFadeOnWorkspace(PWORKSPACE);
}
2024-02-26 00:15:59 +00:00
g_pCompositor->focusWindow(PWINDOW);
} else {
if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned)
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
g_pCompositor->setWindowFullscreenClient(FSWINDOW, FSMODE_NONE);
2024-02-26 00:15:59 +00:00
g_pCompositor->focusWindow(PWINDOW);
if (FSWINDOW != PWINDOW && !PWINDOW->m_bPinned)
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE);
// warp the position + size animation, otherwise it looks weird.
PWINDOW->m_vRealPosition->warp();
PWINDOW->m_vRealSize->warp();
2024-02-26 00:15:59 +00:00
}
} else
g_pCompositor->focusWindow(PWINDOW);
2022-06-10 12:06:27 +02:00
PWINDOW->warpCursor();
return {};
2022-06-10 12:06:27 +02:00
}
2022-06-22 20:23:20 +02:00
SDispatchResult CKeybindManager::tagWindow(std::string args) {
PHLWINDOW PWINDOW = nullptr;
CVarList vars{args, 0, 's', true};
if (vars.size() == 1)
PWINDOW = g_pCompositor->m_lastWindow.lock();
else if (vars.size() == 2)
PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
else
return {.success = false, .error = "Invalid number of arguments, expected 1 or 2 arguments"};
if (PWINDOW && PWINDOW->m_tags.applyTag(vars[0])) {
PWINDOW->updateDynamicRules();
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW->m_pSelf.lock());
}
return {};
}
SDispatchResult CKeybindManager::toggleSwallow(std::string args) {
PHLWINDOWREF pWindow = g_pCompositor->m_lastWindow;
if (!valid(pWindow) || !valid(pWindow->m_pSwallowed))
return {};
if (pWindow->m_pSwallowed->m_bCurrentlySwallowed) {
// Unswallow
pWindow->m_pSwallowed->m_bCurrentlySwallowed = false;
pWindow->m_pSwallowed->setHidden(false);
g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow->m_pSwallowed.lock());
} else {
// Reswallow
pWindow->m_pSwallowed->m_bCurrentlySwallowed = true;
pWindow->m_pSwallowed->setHidden(true);
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow->m_pSwallowed.lock());
}
return {};
}
SDispatchResult CKeybindManager::setSubmap(std::string submap) {
2022-06-22 20:23:20 +02:00
if (submap == "reset" || submap == "") {
m_szCurrentSelectedSubmap = "";
Debug::log(LOG, "Reset active submap to the default one.");
2022-09-05 13:50:52 +02:00
g_pEventManager->postEvent(SHyprIPCEvent{"submap", ""});
EMIT_HOOK_EVENT("submap", m_szCurrentSelectedSubmap);
return {};
2022-06-22 20:23:20 +02:00
}
2024-11-18 19:56:26 +00:00
for (const auto& k : g_pKeybindManager->m_vKeybinds) {
if (k->submap == submap) {
2022-06-22 20:23:20 +02:00
m_szCurrentSelectedSubmap = submap;
Debug::log(LOG, "Changed keybind submap to {}", submap);
2022-09-05 13:50:52 +02:00
g_pEventManager->postEvent(SHyprIPCEvent{"submap", submap});
EMIT_HOOK_EVENT("submap", m_szCurrentSelectedSubmap);
return {};
2022-06-22 20:23:20 +02:00
}
}
Debug::log(ERR, "Cannot set submap {}, submap doesn't exist (wasn't registered!)", submap);
return {.success = false, .error = std::format("Cannot set submap {}, submap doesn't exist (wasn't registered!)", submap)};
2022-06-22 20:23:20 +02:00
}
2022-07-26 17:30:30 +02:00
SDispatchResult CKeybindManager::pass(std::string regexp) {
2022-07-26 17:30:30 +02:00
// find the first window passing the regex
const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp);
if (!PWINDOW) {
Debug::log(ERR, "pass: window not found");
return {.success = false, .error = "pass: window not found"};
2022-07-26 17:30:30 +02:00
}
2024-05-10 18:27:57 +01:00
if (!g_pSeatManager->keyboard) {
2022-07-26 17:30:30 +02:00
Debug::log(ERR, "No kb in pass?");
return {.success = false, .error = "No kb in pass?"};
2022-07-26 17:30:30 +02:00
}
const auto XWTOXW = PWINDOW->m_bIsX11 && g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_bIsX11;
const auto LASTMOUSESURF = g_pSeatManager->state.pointerFocus.lock();
const auto LASTKBSURF = g_pSeatManager->state.keyboardFocus.lock();
2022-07-26 17:30:30 +02:00
// pass all mf shit
if (!XWTOXW) {
if (g_pKeybindManager->m_uLastCode != 0)
g_pSeatManager->setKeyboardFocus(PWINDOW->m_pWLSurface->resource());
else
g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface->resource(), {1, 1});
}
2022-09-25 20:07:48 +02:00
2024-05-10 18:27:57 +01:00
g_pSeatManager->sendKeyboardMods(g_pInputManager->accumulateModsFromAllKBs(), 0, 0, 0);
2022-08-08 20:31:48 +02:00
if (g_pKeybindManager->m_iPassPressed == 1) {
if (g_pKeybindManager->m_uLastCode != 0)
2024-05-10 18:27:57 +01:00
g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WL_KEYBOARD_KEY_STATE_PRESSED);
else
2024-05-10 18:27:57 +01:00
g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED);
} else if (g_pKeybindManager->m_iPassPressed == 0)
if (g_pKeybindManager->m_uLastCode != 0)
2024-05-10 18:27:57 +01:00
g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WL_KEYBOARD_KEY_STATE_RELEASED);
else
2024-05-10 18:27:57 +01:00
g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED);
else {
// dynamic call of the dispatcher
if (g_pKeybindManager->m_uLastCode != 0) {
2024-05-10 18:27:57 +01:00
g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WL_KEYBOARD_KEY_STATE_PRESSED);
g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WL_KEYBOARD_KEY_STATE_RELEASED);
} else {
2024-05-10 18:27:57 +01:00
g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_PRESSED);
g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastMouseCode, WL_POINTER_BUTTON_STATE_RELEASED);
2022-09-25 20:07:48 +02:00
}
}
2022-07-26 17:30:30 +02:00
if (XWTOXW)
return {};
// Massive hack:
2024-05-10 18:27:57 +01:00
// this will make g_pSeatManager NOT send the leave event to XWayland apps, provided we are not on an XWayland window already.
// please kill me
if (PWINDOW->m_bIsX11) {
if (g_pKeybindManager->m_uLastCode != 0) {
g_pSeatManager->state.keyboardFocus.reset();
2024-05-10 18:27:57 +01:00
g_pSeatManager->state.keyboardFocusResource.reset();
} else {
g_pSeatManager->state.pointerFocus.reset();
2024-05-10 18:27:57 +01:00
g_pSeatManager->state.pointerFocusResource.reset();
}
}
const auto SL = PWINDOW->m_vRealPosition->goal() - g_pInputManager->getMouseCoordsInternal();
2024-05-10 18:27:57 +01:00
if (g_pKeybindManager->m_uLastCode != 0)
g_pSeatManager->setKeyboardFocus(LASTKBSURF);
else
g_pSeatManager->setPointerFocus(LASTMOUSESURF, SL);
return {};
}
SDispatchResult CKeybindManager::sendshortcut(std::string args) {
// args=<NEW_MODKEYS><NEW_KEY>[,WINDOW_RULES]
const auto ARGS = CVarList(args, 3);
if (ARGS.size() != 3) {
Debug::log(ERR, "sendshortcut: invalid args");
return {.success = false, .error = "sendshortcut: invalid args"};
}
const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]);
const auto KEY = ARGS[1];
uint32_t keycode = 0;
bool isMouse = false;
// similar to parseKey in ConfigManager
if (isNumber(KEY) && std::stoi(KEY) > 9)
keycode = std::stoi(KEY);
else if (KEY.compare(0, 5, "code:") == 0 && isNumber(KEY.substr(5)))
keycode = std::stoi(KEY.substr(5));
else if (KEY.compare(0, 6, "mouse:") == 0 && isNumber(KEY.substr(6))) {
keycode = std::stoi(KEY.substr(6));
isMouse = true;
if (keycode < 272) {
Debug::log(ERR, "sendshortcut: invalid mouse button");
return {.success = false, .error = "sendshortcut: invalid mouse button"};
}
} else {
// here, we need to find the keycode from the key name
// this is not possible through xkb's lib, so we need to iterate through all keycodes
// once found, we save it to the cache
const auto KEYSYM = xkb_keysym_from_name(KEY.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
keycode = 0;
const auto KB = g_pSeatManager->keyboard;
if (!KB) {
Debug::log(ERR, "sendshortcut: no kb");
return {.success = false, .error = "sendshortcut: no kb"};
}
const auto KEYPAIRSTRING = std::format("{}{}", (uintptr_t)KB.get(), KEY);
if (!g_pKeybindManager->m_mKeyToCodeCache.contains(KEYPAIRSTRING)) {
xkb_keymap* km = KB->xkbKeymap;
xkb_state* ks = KB->xkbState;
xkb_keycode_t keycode_min, keycode_max;
keycode_min = xkb_keymap_min_keycode(km);
keycode_max = xkb_keymap_max_keycode(km);
for (xkb_keycode_t kc = keycode_min; kc <= keycode_max; ++kc) {
xkb_keysym_t sym = xkb_state_key_get_one_sym(ks, kc);
if (sym == KEYSYM) {
keycode = kc;
g_pKeybindManager->m_mKeyToCodeCache[KEYPAIRSTRING] = keycode;
}
}
if (!keycode) {
Debug::log(ERR, "sendshortcut: key not found");
return {.success = false, .error = "sendshortcut: key not found"};
}
} else
keycode = g_pKeybindManager->m_mKeyToCodeCache[KEYPAIRSTRING];
}
if (!keycode) {
Debug::log(ERR, "sendshortcut: invalid key");
return {.success = false, .error = "sendshortcut: invalid key"};
}
const std::string regexp = ARGS[2];
PHLWINDOW PWINDOW = nullptr;
const auto LASTSURFACE = g_pCompositor->m_lastFocus.lock();
//if regexp is not empty, send shortcut to current window
//else, dont change focus
if (regexp != "") {
PWINDOW = g_pCompositor->getWindowByRegex(regexp);
if (!PWINDOW) {
Debug::log(ERR, "sendshortcut: window not found");
return {.success = false, .error = "sendshortcut: window not found"};
}
if (!g_pSeatManager->keyboard) {
Debug::log(ERR, "No kb in sendshortcut?");
return {.success = false, .error = "No kb in sendshortcut?"};
}
if (!isMouse)
g_pSeatManager->setKeyboardFocus(PWINDOW->m_pWLSurface->resource());
else
g_pSeatManager->setPointerFocus(PWINDOW->m_pWLSurface->resource(), {1, 1});
}
//copied the rest from pass and modified it
// if wl -> xwl, activate destination
if (PWINDOW && PWINDOW->m_bIsX11 && g_pCompositor->m_lastWindow && !g_pCompositor->m_lastWindow->m_bIsX11)
g_pXWaylandManager->activateSurface(PWINDOW->m_pWLSurface->resource(), true);
// if xwl -> xwl, send to current. Timing issues make this not work.
if (PWINDOW && PWINDOW->m_bIsX11 && g_pCompositor->m_lastWindow && g_pCompositor->m_lastWindow->m_bIsX11)
PWINDOW = nullptr;
g_pSeatManager->sendKeyboardMods(MOD, 0, 0, 0);
if (g_pKeybindManager->m_iPassPressed == 1) {
if (!isMouse)
g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_PRESSED);
else
g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, keycode, WL_POINTER_BUTTON_STATE_PRESSED);
} else if (g_pKeybindManager->m_iPassPressed == 0) {
if (!isMouse)
g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_RELEASED);
else
g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, keycode, WL_POINTER_BUTTON_STATE_RELEASED);
} else {
// dynamic call of the dispatcher
if (!isMouse) {
g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_PRESSED);
g_pSeatManager->sendKeyboardKey(g_pKeybindManager->m_uTimeLastMs, keycode - 8, WL_KEYBOARD_KEY_STATE_RELEASED);
} else {
g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, keycode, WL_POINTER_BUTTON_STATE_PRESSED);
g_pSeatManager->sendPointerButton(g_pKeybindManager->m_uTimeLastMs, keycode, WL_POINTER_BUTTON_STATE_RELEASED);
}
}
g_pSeatManager->sendKeyboardMods(0, 0, 0, 0);
if (!PWINDOW)
return {};
if (PWINDOW->m_bIsX11) { //xwayland hack, see pass
if (!isMouse) {
g_pSeatManager->state.keyboardFocus.reset();
g_pSeatManager->state.keyboardFocusResource.reset();
} else {
g_pSeatManager->state.pointerFocus.reset();
g_pSeatManager->state.pointerFocusResource.reset();
}
}
const auto SL = PWINDOW->m_vRealPosition->goal() - g_pInputManager->getMouseCoordsInternal();
if (!isMouse)
g_pSeatManager->setKeyboardFocus(LASTSURFACE);
else
g_pSeatManager->setPointerFocus(LASTSURFACE, SL);
return {};
}
SDispatchResult CKeybindManager::layoutmsg(std::string msg) {
SLayoutMessageHeader hd = {g_pCompositor->m_lastWindow.lock()};
g_pLayoutManager->getCurrentLayout()->layoutMessage(hd, msg);
return {};
2022-07-28 12:07:41 +02:00
}
SDispatchResult CKeybindManager::dpms(std::string arg) {
SDispatchResult res;
bool enable = arg.starts_with("on");
std::string port = "";
2022-10-05 10:31:47 +01:00
bool isToggle = arg.starts_with("toggle");
2023-06-20 21:35:54 +02:00
if (arg.find_first_of(' ') != std::string::npos)
2022-10-05 10:31:47 +01:00
port = arg.substr(arg.find_first_of(' ') + 1);
2022-07-30 23:51:13 +02:00
for (auto const& m : g_pCompositor->m_monitors) {
2022-10-05 10:31:47 +01:00
if (!port.empty() && m->szName != port)
continue;
if (isToggle)
enable = !m->dpmsStatus;
m->output->state->resetExplicitFences();
m->output->state->setEnabled(enable);
2022-09-25 20:07:48 +02:00
2022-10-05 18:14:11 +01:00
m->dpmsStatus = enable;
if (!m->state.commit()) {
Debug::log(ERR, "Couldn't commit output {}", m->szName);
res.success = false;
res.error = "Couldn't commit output {}";
2022-07-30 23:51:13 +02:00
}
2022-07-31 12:39:49 +02:00
if (enable)
g_pHyprRenderer->damageMonitor(m);
2024-04-29 01:28:26 +01:00
m->events.dpmsChanged.emit();
2022-07-30 23:51:13 +02:00
}
2022-07-31 15:46:42 +02:00
g_pCompositor->m_dpmsStateOn = enable;
g_pPointerManager->recheckEnteredOutputs();
return res;
2022-07-30 23:51:13 +02:00
}
2022-08-24 21:40:36 +02:00
SDispatchResult CKeybindManager::swapnext(std::string arg) {
2022-08-24 21:40:36 +02:00
PHLWINDOW toSwap = nullptr;
2022-08-24 21:40:36 +02:00
if (g_pCompositor->m_lastWindow.expired())
return {};
2022-08-24 21:40:36 +02:00
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
2022-08-24 21:40:36 +02:00
const auto PLASTCYCLED =
validMapped(g_pCompositor->m_lastWindow->m_pLastCycledWindow) && g_pCompositor->m_lastWindow->m_pLastCycledWindow->m_pWorkspace == PLASTWINDOW->m_pWorkspace ?
g_pCompositor->m_lastWindow->m_pLastCycledWindow.lock() :
nullptr;
2022-08-24 22:01:25 +02:00
const bool NEED_PREV = arg == "last" || arg == "l" || arg == "prev" || arg == "p";
toSwap = g_pCompositor->getWindowCycle(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true, std::nullopt, false, NEED_PREV);
2022-08-24 22:01:25 +02:00
// sometimes we may come back to ourselves.
if (toSwap == PLASTWINDOW)
toSwap = g_pCompositor->getWindowCycle(PLASTWINDOW, true, std::nullopt, false, NEED_PREV);
2022-08-24 21:40:36 +02:00
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, toSwap);
2022-08-24 22:01:25 +02:00
PLASTWINDOW->m_pLastCycledWindow = toSwap;
2022-08-24 21:40:36 +02:00
g_pCompositor->focusWindow(PLASTWINDOW);
return {};
2022-08-24 21:40:36 +02:00
}
SDispatchResult CKeybindManager::swapActiveWorkspaces(std::string args) {
const auto MON1 = args.substr(0, args.find_first_of(' '));
const auto MON2 = args.substr(args.find_first_of(' ') + 1);
const auto PMON1 = g_pCompositor->getMonitorFromString(MON1);
const auto PMON2 = g_pCompositor->getMonitorFromString(MON2);
if (!PMON1 || !PMON2)
return {.success = false, .error = "No such monitor found"};
if (PMON1 == PMON2)
return {};
g_pCompositor->swapActiveWorkspaces(PMON1, PMON2);
return {};
}
2022-09-10 13:11:02 +02:00
SDispatchResult CKeybindManager::pinActive(std::string args) {
PHLWINDOW PWINDOW = nullptr;
if (args != "active" && args.length() > 1)
PWINDOW = g_pCompositor->getWindowByRegex(args);
2023-06-20 21:35:54 +02:00
else
PWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PWINDOW) {
Debug::log(ERR, "pin: window not found");
return {.success = false, .error = "pin: window not found"};
}
2022-09-10 13:11:02 +02:00
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
if (!PWINDOW->m_bIsFloating || PWINDOW->isFullscreen())
return {.success = false, .error = "Window does not qualify to be pinned"};
PWINDOW->m_bPinned = !PWINDOW->m_bPinned;
const auto PMONITOR = PWINDOW->m_pMonitor.lock();
if (!PMONITOR) {
Debug::log(ERR, "pin: monitor not found");
return {.success = false, .error = "pin: window not found"};
}
PWINDOW->m_pWorkspace = PMONITOR->activeWorkspace;
2022-09-10 13:11:02 +02:00
PWINDOW->updateDynamicRules();
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
const auto PWORKSPACE = PWINDOW->m_pWorkspace;
2022-09-10 13:11:02 +02:00
PWORKSPACE->m_pLastFocusedWindow = g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS);
2024-03-18 18:11:20 +00:00
g_pEventManager->postEvent(SHyprIPCEvent{"pin", std::format("{:x},{}", (uintptr_t)PWINDOW.get(), (int)PWINDOW->m_bPinned)});
2024-03-18 18:11:20 +00:00
EMIT_HOOK_EVENT("pin", PWINDOW);
return {};
2022-09-10 13:11:02 +02:00
}
2022-09-19 19:04:48 +01:00
SDispatchResult CKeybindManager::mouse(std::string args) {
2023-08-08 16:52:20 +00:00
const auto ARGS = CVarList(args.substr(1), 2, ' ');
2022-09-19 19:04:48 +01:00
const auto PRESSED = args[0] == '1';
if (!PRESSED) {
return changeMouseBindMode(MBIND_INVALID);
}
2023-08-08 16:52:20 +00:00
if (ARGS[0] == "movewindow") {
return changeMouseBindMode(MBIND_MOVE);
} else {
try {
switch (std::stoi(ARGS[1])) {
case 1: return changeMouseBindMode(MBIND_RESIZE_FORCE_RATIO); break;
case 2: return changeMouseBindMode(MBIND_RESIZE_BLOCK_RATIO); break;
default: return changeMouseBindMode(MBIND_RESIZE);
}
} catch (std::exception& e) { return changeMouseBindMode(MBIND_RESIZE); }
}
}
2022-09-20 10:02:20 +01:00
SDispatchResult CKeybindManager::changeMouseBindMode(const eMouseBindMode MODE) {
if (MODE != MBIND_INVALID) {
if (!g_pInputManager->currentlyDraggedWindow.expired() || g_pInputManager->dragMode != MBIND_INVALID)
return {};
decos: groupbar mouse interaction (#3102) * allow groupbar clicking modified: src/Window.cpp modified: src/Window.hpp modified: src/managers/input/InputManager.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.hpp * remove setting pos inside insertWindowToGroup() modified: src/Window.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp * add group window by index and group size functions modified: src/Window.cpp modified: src/Window.hpp modified: src/managers/input/InputManager.cpp * allow dragging into groupbar modified: src/Window.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp * allow dragging from groupbar modified: src/managers/KeybindManager.cpp * try groupbar clicking before border resize modified: src/managers/input/InputManager.cpp * block grabbing groupbar on floating (crash) remove later when crashing is fixed modified: src/managers/KeybindManager.cpp * remove redundant { } modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp * implement getWindowDecorationBox() modified: src/Window.cpp modified: src/Window.hpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/InputManager.cpp modified: src/render/decorations/CHyprDropShadowDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp modified: src/render/decorations/IHyprWindowDecoration.cpp modified: src/render/decorations/IHyprWindowDecoration.hpp * fix crash when moveoutofgroup in floating windows also removes dragging from floating windows limitation modified: src/layout/IHyprLayout.cpp modified: src/managers/KeybindManager.cpp * use CRegion in getWindowDecorationBox() modified: src/helpers/Region.cpp modified: src/helpers/Region.hpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/InputManager.cpp modified: src/render/decorations/IHyprWindowDecoration.cpp modified: src/render/decorations/IHyprWindowDecoration.hpp * add groupbar scrolling modified: src/config/ConfigManager.cpp modified: src/managers/input/InputManager.cpp * change name to getWindowDecorationRegion() modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/InputManager.cpp modified: src/render/decorations/IHyprWindowDecoration.cpp modified: src/render/decorations/IHyprWindowDecoration.hpp * make dragging from group less hacky for floating modified: src/managers/KeybindManager.cpp
2023-08-30 15:39:22 +00:00
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
const PHLWINDOW PWINDOW = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING);
2022-09-19 19:04:48 +01:00
if (!PWINDOW)
return SDispatchResult{.passEvent = true};
internal: refactor fullscreen states (#7104) * refactor fullscreen modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/config/ConfigManager.cpp modified: src/config/ConfigManager.hpp modified: src/debug/HyprCtl.cpp modified: src/desktop/LayerSurface.cpp modified: src/desktop/Window.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/desktop/Workspace.hpp modified: src/events/Windows.cpp modified: src/helpers/Monitor.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/DwindleLayout.hpp modified: src/layout/IHyprLayout.cpp modified: src/layout/IHyprLayout.hpp modified: src/layout/MasterLayout.cpp modified: src/layout/MasterLayout.hpp modified: src/managers/KeybindManager.cpp modified: src/managers/KeybindManager.hpp modified: src/managers/input/IdleInhibitor.cpp modified: src/managers/input/InputManager.cpp modified: src/managers/input/Swipe.cpp modified: src/protocols/ForeignToplevelWlr.cpp modified: src/render/Renderer.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * clean up modified: src/config/ConfigManager.cpp modified: src/debug/HyprCtl.cpp modified: src/desktop/Window.hpp modified: src/desktop/Workspace.cpp modified: src/events/Windows.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/Swipe.cpp * fix mapWindow fullscreen modified: src/events/Windows.cpp * fix typo modified: src/desktop/Workspace.cpp * add fullscreenstate modified: src/config/ConfigManager.cpp modified: src/events/Windows.cpp * change syncFullscreen to lower modified: src/config/ConfigManager.hpp * initialize fs state modified: src/desktop/Window.hpp
2024-07-31 17:55:52 +00:00
if (!PWINDOW->isFullscreen() && MODE == MBIND_MOVE)
PWINDOW->checkInputOnDecos(INPUT_TYPE_DRAG_START, MOUSECOORDS);
2022-09-20 10:02:20 +01:00
if (g_pInputManager->currentlyDraggedWindow.expired())
g_pInputManager->currentlyDraggedWindow = PWINDOW;
g_pInputManager->dragMode = MODE;
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
} else {
if (g_pInputManager->currentlyDraggedWindow.expired() || g_pInputManager->dragMode == MBIND_INVALID)
return {};
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
g_pInputManager->dragMode = MODE;
2022-09-19 19:04:48 +01:00
}
return {};
2022-09-19 19:04:48 +01:00
}
2022-10-14 14:22:20 +01:00
SDispatchResult CKeybindManager::bringActiveToTop(std::string args) {
if (g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_bIsFloating)
g_pCompositor->changeWindowZOrder(g_pCompositor->m_lastWindow.lock(), true);
return {};
}
SDispatchResult CKeybindManager::alterZOrder(std::string args) {
const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
const auto POSITION = args.substr(0, args.find_first_of(','));
auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
if (!PWINDOW && g_pCompositor->m_lastWindow.lock() && g_pCompositor->m_lastWindow->m_bIsFloating)
PWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PWINDOW) {
Debug::log(ERR, "alterZOrder: no window");
return {.success = false, .error = "alterZOrder: no window"};
}
if (POSITION == "top")
g_pCompositor->changeWindowZOrder(PWINDOW, true);
else if (POSITION == "bottom")
g_pCompositor->changeWindowZOrder(PWINDOW, false);
else {
Debug::log(ERR, "alterZOrder: bad position: {}", POSITION);
return {.success = false, .error = "alterZOrder: bad position: {}"};
}
g_pInputManager->simulateMouseMovement();
return {};
2022-10-14 14:22:20 +01:00
}
2023-01-01 16:54:13 +01:00
SDispatchResult CKeybindManager::lockGroups(std::string args) {
2023-06-20 21:35:54 +02:00
if (args == "lock" || args.empty() || args == "lockgroups")
2023-02-21 12:13:35 +00:00
g_pKeybindManager->m_bGroupsLocked = true;
2023-06-20 21:35:54 +02:00
else if (args == "toggle")
2023-03-02 20:50:37 +00:00
g_pKeybindManager->m_bGroupsLocked = !g_pKeybindManager->m_bGroupsLocked;
2023-06-20 21:35:54 +02:00
else
2023-02-21 12:13:35 +00:00
g_pKeybindManager->m_bGroupsLocked = false;
2023-09-15 11:06:59 +00:00
g_pEventManager->postEvent(SHyprIPCEvent{"lockgroups", g_pKeybindManager->m_bGroupsLocked ? "1" : "0"});
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
return {};
2023-02-21 12:13:35 +00:00
}
2023-02-26 13:52:11 +00:00
SDispatchResult CKeybindManager::lockActiveGroup(std::string args) {
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PWINDOW)
return {.success = false, .error = "No window found"};
if (!PWINDOW->m_sGroupData.pNextWindow.lock())
return {.success = false, .error = "Not a group"};
2023-06-20 21:35:54 +02:00
const auto PHEAD = PWINDOW->getGroupHead();
2023-06-20 21:35:54 +02:00
if (args == "lock")
PHEAD->m_sGroupData.locked = true;
2023-06-20 21:35:54 +02:00
else if (args == "toggle")
PHEAD->m_sGroupData.locked = !PHEAD->m_sGroupData.locked;
2023-06-20 21:35:54 +02:00
else
PHEAD->m_sGroupData.locked = false;
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
return {};
}
void CKeybindManager::moveWindowIntoGroup(PHLWINDOW pWindow, PHLWINDOW pWindowInDirection) {
if (pWindow->m_sGroupData.deny)
return;
updateRelativeCursorCoords();
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property!
if (pWindow->m_pMonitor != pWindowInDirection->m_pMonitor) {
pWindow->moveToWorkspace(pWindowInDirection->m_pWorkspace);
pWindow->m_pMonitor = pWindowInDirection->m_pMonitor;
}
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
2024-10-30 10:00:58 +00:00
(*USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail())->insertWindowToGroup(pWindow);
pWindowInDirection->setGroupCurrent(pWindow);
pWindow->updateWindowDecos();
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow);
g_pCompositor->focusWindow(pWindow);
pWindow->warpCursor();
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
pWindow->addWindowDeco(makeUnique<CHyprGroupBarDecoration>(pWindow));
g_pEventManager->postEvent(SHyprIPCEvent{"moveintogroup", std::format("{:x}", (uintptr_t)pWindow.get())});
}
void CKeybindManager::moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& dir) {
static auto BFOCUSREMOVEDWINDOW = CConfigValue<Hyprlang::INT>("group:focus_removed_window");
const auto PWINDOWPREV = pWindow->getGroupPrevious();
eDirection direction;
switch (dir[0]) {
case 't':
case 'u': direction = DIRECTION_UP; break;
case 'd':
case 'b': direction = DIRECTION_DOWN; break;
case 'l': direction = DIRECTION_LEFT; break;
case 'r': direction = DIRECTION_RIGHT; break;
default: direction = DIRECTION_DEFAULT;
}
updateRelativeCursorCoords();
if (pWindow->m_sGroupData.pNextWindow.lock() == pWindow) {
pWindow->destroyGroup();
} else {
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow);
const auto GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked;
g_pKeybindManager->m_bGroupsLocked = true;
g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow, direction);
g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV;
}
if (*BFOCUSREMOVEDWINDOW) {
g_pCompositor->focusWindow(pWindow);
pWindow->warpCursor();
} else {
g_pCompositor->focusWindow(PWINDOWPREV);
PWINDOWPREV->warpCursor();
}
g_pEventManager->postEvent(SHyprIPCEvent{"moveoutofgroup", std::format("{:x}", (uintptr_t)pWindow.get())});
}
SDispatchResult CKeybindManager::moveIntoGroup(std::string args) {
char arg = args[0];
static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked)
return {};
2023-02-26 13:52:11 +00:00
if (!isDirection(args)) {
2023-09-06 12:51:36 +02:00
Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)};
2023-02-26 13:52:11 +00:00
}
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
2023-02-26 13:52:11 +00:00
if (!PWINDOW || PWINDOW->m_sGroupData.deny)
return {};
2023-02-26 13:52:11 +00:00
decos: groupbar mouse interaction (#3102) * allow groupbar clicking modified: src/Window.cpp modified: src/Window.hpp modified: src/managers/input/InputManager.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.hpp * remove setting pos inside insertWindowToGroup() modified: src/Window.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp * add group window by index and group size functions modified: src/Window.cpp modified: src/Window.hpp modified: src/managers/input/InputManager.cpp * allow dragging into groupbar modified: src/Window.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp * allow dragging from groupbar modified: src/managers/KeybindManager.cpp * try groupbar clicking before border resize modified: src/managers/input/InputManager.cpp * block grabbing groupbar on floating (crash) remove later when crashing is fixed modified: src/managers/KeybindManager.cpp * remove redundant { } modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp * implement getWindowDecorationBox() modified: src/Window.cpp modified: src/Window.hpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/InputManager.cpp modified: src/render/decorations/CHyprDropShadowDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp modified: src/render/decorations/IHyprWindowDecoration.cpp modified: src/render/decorations/IHyprWindowDecoration.hpp * fix crash when moveoutofgroup in floating windows also removes dragging from floating windows limitation modified: src/layout/IHyprLayout.cpp modified: src/managers/KeybindManager.cpp * use CRegion in getWindowDecorationBox() modified: src/helpers/Region.cpp modified: src/helpers/Region.hpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/InputManager.cpp modified: src/render/decorations/IHyprWindowDecoration.cpp modified: src/render/decorations/IHyprWindowDecoration.hpp * add groupbar scrolling modified: src/config/ConfigManager.cpp modified: src/managers/input/InputManager.cpp * change name to getWindowDecorationRegion() modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/InputManager.cpp modified: src/render/decorations/IHyprWindowDecoration.cpp modified: src/render/decorations/IHyprWindowDecoration.hpp * make dragging from group less hacky for floating modified: src/managers/KeybindManager.cpp
2023-08-30 15:39:22 +00:00
auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg);
2023-02-26 13:52:11 +00:00
if (!PWINDOWINDIR || !PWINDOWINDIR->m_sGroupData.pNextWindow.lock())
return {};
2023-02-26 13:52:11 +00:00
// Do not move window into locked group if binds:ignore_group_lock is false
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow.lock() && PWINDOW->getGroupHead()->m_sGroupData.locked)))
return {};
moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
return {};
2023-02-26 13:52:11 +00:00
}
2023-02-26 13:55:35 +00:00
SDispatchResult CKeybindManager::moveOutOfGroup(std::string args) {
static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked)
return {.success = false, .error = "Groups locked"};
PHLWINDOW PWINDOW = nullptr;
if (args != "active" && args.length() > 1)
PWINDOW = g_pCompositor->getWindowByRegex(args);
else
PWINDOW = g_pCompositor->m_lastWindow.lock();
2023-02-26 13:55:35 +00:00
if (!PWINDOW)
return {.success = false, .error = "No window found"};
if (!PWINDOW->m_sGroupData.pNextWindow.lock())
return {.success = false, .error = "Window not in a group"};
2023-02-26 13:55:35 +00:00
moveWindowOutOfGroup(PWINDOW);
return {};
}
2023-02-26 13:55:35 +00:00
SDispatchResult CKeybindManager::moveWindowOrGroup(std::string args) {
char arg = args[0];
2023-02-26 13:55:35 +00:00
static auto PIGNOREGROUPLOCK = CConfigValue<Hyprlang::INT>("binds:ignore_group_lock");
2023-02-26 13:55:35 +00:00
if (!isDirection(args)) {
Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
return {.success = false, .error = std::format("Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg)};
}
2023-02-26 13:55:35 +00:00
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PWINDOW)
return {.success = false, .error = "No window found"};
if (PWINDOW->isFullscreen())
return {};
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) {
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
return {};
}
const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg);
const bool ISWINDOWGROUP = PWINDOW->m_sGroupData.pNextWindow;
const bool ISWINDOWGROUPLOCKED = ISWINDOWGROUP && PWINDOW->getGroupHead()->m_sGroupData.locked;
const bool ISWINDOWGROUPSINGLE = ISWINDOWGROUP && PWINDOW->m_sGroupData.pNextWindow.lock() == PWINDOW;
updateRelativeCursorCoords();
// note: PWINDOWINDIR is not null implies !PWINDOW->m_bIsFloating
if (PWINDOWINDIR && PWINDOWINDIR->m_sGroupData.pNextWindow) { // target is group
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || ISWINDOWGROUPLOCKED || PWINDOW->m_sGroupData.deny)) {
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
PWINDOW->warpCursor();
} else
moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
} else if (PWINDOWINDIR) { // target is regular window
if ((!*PIGNOREGROUPLOCK && ISWINDOWGROUPLOCKED) || !ISWINDOWGROUP || (ISWINDOWGROUPSINGLE && PWINDOW->m_eGroupRules & GROUP_SET_ALWAYS)) {
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
PWINDOW->warpCursor();
} else
moveWindowOutOfGroup(PWINDOW, args);
} else if ((*PIGNOREGROUPLOCK || !ISWINDOWGROUPLOCKED) && ISWINDOWGROUP) { // no target window
moveWindowOutOfGroup(PWINDOW, args);
} else if (!PWINDOWINDIR && !ISWINDOWGROUP) { // no target in dir and not in group
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
PWINDOW->warpCursor();
}
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
return {};
}
SDispatchResult CKeybindManager::setIgnoreGroupLock(std::string args) {
static auto PIGNOREGROUPLOCK = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock");
if (args == "toggle")
**PIGNOREGROUPLOCK = !**PIGNOREGROUPLOCK;
else
**PIGNOREGROUPLOCK = args == "on";
g_pEventManager->postEvent(SHyprIPCEvent{"ignoregrouplock", std::to_string(**PIGNOREGROUPLOCK)});
return {};
2023-02-26 13:55:35 +00:00
}
SDispatchResult CKeybindManager::denyWindowFromGroup(std::string args) {
const auto PWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PWINDOW || (PWINDOW && PWINDOW->m_sGroupData.pNextWindow.lock()))
return {};
if (args == "toggle")
PWINDOW->m_sGroupData.deny = !PWINDOW->m_sGroupData.deny;
else
PWINDOW->m_sGroupData.deny = args == "on";
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
return {};
}
SDispatchResult CKeybindManager::global(std::string args) {
const auto APPID = args.substr(0, args.find_first_of(':'));
const auto NAME = args.substr(args.find_first_of(':') + 1);
2023-09-02 19:32:05 +02:00
if (NAME.empty())
return {};
if (!PROTO::globalShortcuts->isTaken(APPID, NAME))
return {};
PROTO::globalShortcuts->sendGlobalShortcutEvent(APPID, NAME, g_pKeybindManager->m_iPassPressed);
return {};
2023-04-10 21:07:49 +02:00
}
2023-07-13 17:55:20 +02:00
SDispatchResult CKeybindManager::moveGroupWindow(std::string args) {
2023-07-13 17:55:20 +02:00
const auto BACK = args == "b" || args == "prev";
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
if (!PLASTWINDOW)
return {.success = false, .error = "No window found"};
if (!PLASTWINDOW->m_sGroupData.pNextWindow.lock())
return {.success = false, .error = "Window not in a group"};
2023-07-13 17:55:20 +02:00
if ((!BACK && PLASTWINDOW->m_sGroupData.pNextWindow->m_sGroupData.head) || (BACK && PLASTWINDOW->m_sGroupData.head)) {
std::swap(PLASTWINDOW->m_sGroupData.head, PLASTWINDOW->m_sGroupData.pNextWindow->m_sGroupData.head);
std::swap(PLASTWINDOW->m_sGroupData.locked, PLASTWINDOW->m_sGroupData.pNextWindow->m_sGroupData.locked);
} else
PLASTWINDOW->switchWithWindowInGroup(BACK ? PLASTWINDOW->getGroupPrevious() : PLASTWINDOW->m_sGroupData.pNextWindow.lock());
PLASTWINDOW->updateWindowDecos();
return {};
2023-07-13 17:55:20 +02:00
}
SDispatchResult CKeybindManager::event(std::string args) {
g_pEventManager->postEvent(SHyprIPCEvent{"custom", args});
return {};
}
#include <utility>
#include <type_traits>
SDispatchResult CKeybindManager::setProp(std::string args) {
CVarList vars(args, 3, ' ');
if (vars.size() < 3)
return {.success = false, .error = "Not enough args"};
const auto PLASTWINDOW = g_pCompositor->m_lastWindow.lock();
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[0]);
if (!PWINDOW)
return {.success = false, .error = "Window not found"};
const auto PROP = vars[1];
const auto VAL = vars[2];
bool noFocus = PWINDOW->m_sWindowData.noFocus.valueOrDefault();
try {
if (PROP == "animationstyle") {
PWINDOW->m_sWindowData.animationStyle = CWindowOverridableVar(VAL, PRIORITY_SET_PROP);
} else if (PROP == "maxsize") {
PWINDOW->m_sWindowData.maxSize = CWindowOverridableVar(configStringToVector2D(VAL), PRIORITY_SET_PROP);
PWINDOW->clampWindowSize(std::nullopt, PWINDOW->m_sWindowData.maxSize.value());
PWINDOW->setHidden(false);
} else if (PROP == "minsize") {
PWINDOW->m_sWindowData.minSize = CWindowOverridableVar(configStringToVector2D(VAL), PRIORITY_SET_PROP);
PWINDOW->clampWindowSize(PWINDOW->m_sWindowData.minSize.value(), std::nullopt);
PWINDOW->setHidden(false);
} else if (PROP == "alpha") {
PWINDOW->m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alpha.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP);
} else if (PROP == "alphainactive") {
PWINDOW->m_sWindowData.alphaInactive =
CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP);
} else if (PROP == "alphafullscreen") {
PWINDOW->m_sWindowData.alphaFullscreen =
CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP);
} else if (PROP == "alphaoverride") {
PWINDOW->m_sWindowData.alpha =
CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alpha.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP);
} else if (PROP == "alphainactiveoverride") {
PWINDOW->m_sWindowData.alphaInactive =
CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaInactive.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP);
} else if (PROP == "alphafullscreenoverride") {
PWINDOW->m_sWindowData.alphaFullscreen =
CWindowOverridableVar(SAlphaValue{PWINDOW->m_sWindowData.alphaFullscreen.valueOrDefault().m_fAlpha, (bool)configStringToInt(VAL).value_or(0)}, PRIORITY_SET_PROP);
} else if (PROP == "activebordercolor" || PROP == "inactivebordercolor") {
CGradientValueData colorData = {};
if (vars.size() > 4) {
for (int i = 3; i < static_cast<int>(vars.size()); ++i) {
const auto TOKEN = vars[i];
if (TOKEN.ends_with("deg"))
colorData.m_angle = std::stoi(TOKEN.substr(0, TOKEN.size() - 3)) * (PI / 180.0);
else
configStringToInt(TOKEN).and_then([&colorData](const auto& e) {
colorData.m_colors.push_back(e);
return std::invoke_result_t<decltype(::configStringToInt), const std::string&>(1);
});
}
} else if (VAL != "-1")
configStringToInt(VAL).and_then([&colorData](const auto& e) {
colorData.m_colors.push_back(e);
return std::invoke_result_t<decltype(::configStringToInt), const std::string&>(1);
});
colorData.updateColorsOk();
if (PROP == "activebordercolor")
PWINDOW->m_sWindowData.activeBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP);
else
PWINDOW->m_sWindowData.inactiveBorderColor = CWindowOverridableVar(colorData, PRIORITY_SET_PROP);
} else if (auto search = NWindowProperties::boolWindowProperties.find(PROP); search != NWindowProperties::boolWindowProperties.end()) {
auto pWindowDataElement = search->second(PWINDOW);
if (VAL == "toggle")
pWindowDataElement->increment(true, PRIORITY_SET_PROP);
else if (VAL == "unset")
pWindowDataElement->unset(PRIORITY_SET_PROP);
else
*pWindowDataElement = CWindowOverridableVar((bool)configStringToInt(VAL).value_or(0), PRIORITY_SET_PROP);
} else if (auto search = NWindowProperties::intWindowProperties.find(PROP); search != NWindowProperties::intWindowProperties.end()) {
if (VAL == "unset")
search->second(PWINDOW)->unset(PRIORITY_SET_PROP);
else if (VAL.starts_with("relative")) {
const Hyprlang::INT V = std::stoi(VAL.substr(VAL.find(' ')));
search->second(PWINDOW)->increment(V, PRIORITY_SET_PROP);
} else if (const auto V = configStringToInt(VAL); V)
*(search->second(PWINDOW)) = CWindowOverridableVar((Hyprlang::INT)*V, PRIORITY_SET_PROP);
} else if (auto search = NWindowProperties::floatWindowProperties.find(PROP); search != NWindowProperties::floatWindowProperties.end()) {
if (VAL == "unset")
search->second(PWINDOW)->unset(PRIORITY_SET_PROP);
else if (VAL.starts_with("relative")) {
const auto V = std::stof(VAL.substr(VAL.find(' ')));
search->second(PWINDOW)->increment(V, PRIORITY_SET_PROP);
} else {
const auto V = std::stof(VAL);
*(search->second(PWINDOW)) = CWindowOverridableVar(V, PRIORITY_SET_PROP);
}
} else
return {.success = false, .error = "Prop not found"};
} catch (std::exception& e) { return {.success = false, .error = std::format("Error parsing prop value: {}", std::string(e.what()))}; }
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
if (!(PWINDOW->m_sWindowData.noFocus.valueOrDefault() == noFocus)) {
g_pCompositor->focusWindow(nullptr);
g_pCompositor->focusWindow(PWINDOW);
g_pCompositor->focusWindow(PLASTWINDOW);
}
for (auto const& m : g_pCompositor->m_monitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
return {};
}
SDispatchResult CKeybindManager::sendkeystate(std::string args) {
// args=<NEW_MODKEYS><NEW_KEY><STATE>[,WINDOW_RULES]
const auto ARGS = CVarList(args, 4);
if (ARGS.size() != 4) {
Debug::log(ERR, "sendkeystate: invalid args");
return {.success = false, .error = "sendkeystate: invalid args"};
}
const auto STATE = ARGS[2];
if (STATE != "down" && STATE != "repeat" && STATE != "up") {
Debug::log(ERR, "sendkeystate: invalid state, must be 'down', 'repeat', or 'up'");
return {.success = false, .error = "sendkeystate: invalid state, must be 'down', 'repeat', or 'up'"};
}
std::string modifiedArgs = ARGS[0] + "," + ARGS[1] + "," + ARGS[3];
const int oldPassPressed = g_pKeybindManager->m_iPassPressed;
if (STATE == "down")
g_pKeybindManager->m_iPassPressed = 1;
else if (STATE == "up")
g_pKeybindManager->m_iPassPressed = 0;
else if (STATE == "repeat")
g_pKeybindManager->m_iPassPressed = 1;
auto result = sendshortcut(modifiedArgs);
if (STATE == "repeat" && result.success)
result = sendshortcut(modifiedArgs);
g_pKeybindManager->m_iPassPressed = oldPassPressed;
if (!result.success && !result.error.empty()) {
size_t pos = result.error.find("sendshortcut:");
if (pos != std::string::npos)
result.error = "sendkeystate:" + result.error.substr(pos + 13);
}
return result;
}