mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-22 17:45:59 +01:00
bind: new long press option (#8302)
--------- Co-authored-by: Vaxry <vaxry@vaxry.net>
This commit is contained in:
parent
098e491a43
commit
7affc34ab4
4 changed files with 53 additions and 12 deletions
|
@ -2171,6 +2171,7 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
||||||
bool transparent = false;
|
bool transparent = false;
|
||||||
bool ignoreMods = false;
|
bool ignoreMods = false;
|
||||||
bool multiKey = false;
|
bool multiKey = false;
|
||||||
|
bool longPress = false;
|
||||||
bool hasDescription = false;
|
bool hasDescription = false;
|
||||||
bool dontInhibit = false;
|
bool dontInhibit = false;
|
||||||
const auto BINDARGS = command.substr(4);
|
const auto BINDARGS = command.substr(4);
|
||||||
|
@ -2192,6 +2193,8 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
||||||
ignoreMods = true;
|
ignoreMods = true;
|
||||||
} else if (arg == 's') {
|
} else if (arg == 's') {
|
||||||
multiKey = true;
|
multiKey = true;
|
||||||
|
} else if (arg == 'o') {
|
||||||
|
longPress = true;
|
||||||
} else if (arg == 'd') {
|
} else if (arg == 'd') {
|
||||||
hasDescription = true;
|
hasDescription = true;
|
||||||
} else if (arg == 'p') {
|
} else if (arg == 'p') {
|
||||||
|
@ -2201,8 +2204,8 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (release && repeat)
|
if ((longPress || release) && repeat)
|
||||||
return "flags r and e are mutually exclusive";
|
return "flags e is mutually exclusive with r and o";
|
||||||
|
|
||||||
if (mouse && (repeat || release || locked))
|
if (mouse && (repeat || release || locked))
|
||||||
return "flag m is exclusive";
|
return "flag m is exclusive";
|
||||||
|
@ -2264,9 +2267,9 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
|
||||||
return "Invalid catchall, catchall keybinds are only allowed in submaps.";
|
return "Invalid catchall, catchall keybinds are only allowed in submaps.";
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pKeybindManager->addKeybind(SKeybind{
|
g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER,
|
||||||
parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, COMMAND, locked, m_szCurrentSubmap, DESCRIPTION, release,
|
COMMAND, locked, m_szCurrentSubmap, DESCRIPTION, release, repeat, longPress,
|
||||||
repeat, mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription, dontInhibit});
|
mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription, dontInhibit});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -843,6 +843,7 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
"mouse": {},
|
"mouse": {},
|
||||||
"release": {},
|
"release": {},
|
||||||
"repeat": {},
|
"repeat": {},
|
||||||
|
"longPress": {},
|
||||||
"non_consuming": {},
|
"non_consuming": {},
|
||||||
"has_description": {},
|
"has_description": {},
|
||||||
"modmask": {},
|
"modmask": {},
|
||||||
|
@ -854,9 +855,9 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
|
||||||
"dispatcher": "{}",
|
"dispatcher": "{}",
|
||||||
"arg": "{}"
|
"arg": "{}"
|
||||||
}},)#",
|
}},)#",
|
||||||
kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.nonConsuming ? "true" : "false",
|
kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.longPress ? "true" : "false",
|
||||||
kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode, kb.catchAll ? "true" : "false",
|
kb.nonConsuming ? "true" : "false", kb.hasDescription ? "true" : "false", kb.modmask, escapeJSONStrings(kb.submap), escapeJSONStrings(kb.key), kb.keycode,
|
||||||
escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg));
|
kb.catchAll ? "true" : "false", escapeJSONStrings(kb.description), escapeJSONStrings(kb.handler), escapeJSONStrings(kb.arg));
|
||||||
}
|
}
|
||||||
trimTrailingComma(ret);
|
trimTrailingComma(ret);
|
||||||
ret += "]";
|
ret += "]";
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "eventLoop/EventLoopManager.hpp"
|
#include "eventLoop/EventLoopManager.hpp"
|
||||||
#include "debug/Log.hpp"
|
#include "debug/Log.hpp"
|
||||||
#include "helpers/varlist/VarList.hpp"
|
#include "helpers/varlist/VarList.hpp"
|
||||||
|
#include "eventLoop/EventLoopManager.hpp"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
@ -130,9 +131,25 @@ CKeybindManager::CKeybindManager() {
|
||||||
|
|
||||||
m_tScrollTimer.reset();
|
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 DISPATCHER = g_pKeybindManager->m_mDispatchers.find(m_pLastLongPressKeybind->handler);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Long press timeout passed, calling dispatcher.");
|
||||||
|
DISPATCHER->second(m_pLastLongPressKeybind->arg);
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
g_pEventLoopManager->addTimer(m_pLongPressTimer);
|
||||||
|
|
||||||
static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) {
|
static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) {
|
||||||
// clear cuz realloc'd
|
// clear cuz realloc'd
|
||||||
m_pActiveKeybind = nullptr;
|
m_pActiveKeybind = nullptr;
|
||||||
|
m_pLastLongPressKeybind = nullptr;
|
||||||
m_vPressedSpecialBinds.clear();
|
m_vPressedSpecialBinds.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -140,12 +157,17 @@ CKeybindManager::CKeybindManager() {
|
||||||
CKeybindManager::~CKeybindManager() {
|
CKeybindManager::~CKeybindManager() {
|
||||||
if (m_pXKBTranslationState)
|
if (m_pXKBTranslationState)
|
||||||
xkb_state_unref(m_pXKBTranslationState);
|
xkb_state_unref(m_pXKBTranslationState);
|
||||||
|
if (m_pLongPressTimer && g_pEventLoopManager) {
|
||||||
|
g_pEventLoopManager->removeTimer(m_pLongPressTimer);
|
||||||
|
m_pLongPressTimer.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::addKeybind(SKeybind kb) {
|
void CKeybindManager::addKeybind(SKeybind kb) {
|
||||||
m_lKeybinds.push_back(kb);
|
m_lKeybinds.push_back(kb);
|
||||||
|
|
||||||
m_pActiveKeybind = nullptr;
|
m_pActiveKeybind = nullptr;
|
||||||
|
m_pLastLongPressKeybind = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) {
|
void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) {
|
||||||
|
@ -158,7 +180,8 @@ void CKeybindManager::removeKeybind(uint32_t mod, const SParsedKey& key) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pActiveKeybind = nullptr;
|
m_pActiveKeybind = nullptr;
|
||||||
|
m_pLastLongPressKeybind = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CKeybindManager::stringToModMask(std::string mods) {
|
uint32_t CKeybindManager::stringToModMask(std::string mods) {
|
||||||
|
@ -409,6 +432,8 @@ bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
|
||||||
m_pActiveKeybind = nullptr;
|
m_pActiveKeybind = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_pLastLongPressKeybind = nullptr;
|
||||||
|
|
||||||
bool suppressEvent = false;
|
bool suppressEvent = false;
|
||||||
if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||||
|
|
||||||
|
@ -705,6 +730,15 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (k.longPress) {
|
||||||
|
const auto PACTIVEKEEB = g_pSeatManager->keyboard.lock();
|
||||||
|
|
||||||
|
m_pLongPressTimer->updateTimeout(std::chrono::milliseconds(PACTIVEKEEB->repeatDelay));
|
||||||
|
m_pLastLongPressKeybind = &k;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler);
|
const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler);
|
||||||
|
|
||||||
if (SPECIALTRIGGERED && !pressed)
|
if (SPECIALTRIGGERED && !pressed)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include "../devices/IPointer.hpp"
|
#include "../devices/IPointer.hpp"
|
||||||
|
#include "eventLoop/EventLoopTimer.hpp"
|
||||||
|
|
||||||
class CInputManager;
|
class CInputManager;
|
||||||
class CConfigManager;
|
class CConfigManager;
|
||||||
|
@ -28,6 +29,7 @@ struct SKeybind {
|
||||||
std::string description = "";
|
std::string description = "";
|
||||||
bool release = false;
|
bool release = false;
|
||||||
bool repeat = false;
|
bool repeat = false;
|
||||||
|
bool longPress = false;
|
||||||
bool mouse = false;
|
bool mouse = false;
|
||||||
bool nonConsuming = false;
|
bool nonConsuming = false;
|
||||||
bool transparent = false;
|
bool transparent = false;
|
||||||
|
@ -119,7 +121,8 @@ class CKeybindManager {
|
||||||
|
|
||||||
inline static std::string m_szCurrentSelectedSubmap = "";
|
inline static std::string m_szCurrentSelectedSubmap = "";
|
||||||
|
|
||||||
SKeybind* m_pActiveKeybind = nullptr;
|
SKeybind * m_pActiveKeybind = nullptr, *m_pLastLongPressKeybind = nullptr;
|
||||||
|
SP<CEventLoopTimer> m_pLongPressTimer;
|
||||||
|
|
||||||
uint32_t m_uTimeLastMs = 0;
|
uint32_t m_uTimeLastMs = 0;
|
||||||
uint32_t m_uLastCode = 0;
|
uint32_t m_uLastCode = 0;
|
||||||
|
|
Loading…
Reference in a new issue