input: Introduce basic hyprland HID classes
Implements an intermediary HID class for mice, keyboards and touch devices, removing the old structs from WLClasses.hpp Yes, virtual ones are duplicated a bit, but will likely be de-duped once wlr_input_device is not used anymore.
This commit is contained in:
parent
1d2acbe193
commit
1237732b97
39 changed files with 1450 additions and 573 deletions
|
|
@ -3,6 +3,7 @@
|
|||
#include "../Compositor.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../protocols/GammaControl.hpp"
|
||||
#include "../devices/ITouch.hpp"
|
||||
|
||||
int ratHandler(void* data) {
|
||||
g_pHyprRenderer->renderMonitor((CMonitor*)data);
|
||||
|
|
@ -145,10 +146,10 @@ void CMonitor::onConnect(bool noRule) {
|
|||
if (!noRule)
|
||||
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
||||
|
||||
for (const auto& PTOUCHDEV : g_pInputManager->m_lTouchDevices) {
|
||||
if (matchesStaticSelector(PTOUCHDEV.boundOutput)) {
|
||||
Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV.name, szName);
|
||||
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTOUCHDEV.pWlrDevice, output);
|
||||
for (const auto& PTOUCHDEV : g_pInputManager->m_vTouches) {
|
||||
if (matchesStaticSelector(PTOUCHDEV->boundOutput)) {
|
||||
Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV->hlName, szName);
|
||||
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, &PTOUCHDEV->wlr()->base, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,78 +1 @@
|
|||
#include "WLClasses.hpp"
|
||||
|
||||
void SKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
|
||||
xkb_state_unref(xkbTranslationState);
|
||||
|
||||
if (keymap) {
|
||||
Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this);
|
||||
xkbTranslationState = xkb_state_new(keymap);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto WLRKB = wlr_keyboard_from_input_device(keyboard);
|
||||
const auto KEYMAP = WLRKB->keymap;
|
||||
const auto STATE = WLRKB->xkb_state;
|
||||
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
|
||||
|
||||
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
|
||||
for (uint32_t i = 0; i < LAYOUTSNUM; ++i) {
|
||||
if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) {
|
||||
Debug::log(LOG, "Updating keyboard {:x}'s translation state from an active index {}", (uintptr_t)this, i);
|
||||
|
||||
CVarList keyboardLayouts(currentRules.layout, 0, ',');
|
||||
CVarList keyboardModels(currentRules.model, 0, ',');
|
||||
CVarList keyboardVariants(currentRules.variant, 0, ',');
|
||||
|
||||
xkb_rule_names rules = {.rules = "", .model = "", .layout = "", .variant = "", .options = ""};
|
||||
|
||||
std::string layout, model, variant;
|
||||
layout = keyboardLayouts[i % keyboardLayouts.size()];
|
||||
model = keyboardModels[i % keyboardModels.size()];
|
||||
variant = keyboardVariants[i % keyboardVariants.size()];
|
||||
|
||||
rules.layout = layout.c_str();
|
||||
rules.model = model.c_str();
|
||||
rules.variant = variant.c_str();
|
||||
|
||||
auto KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
if (!KEYMAP) {
|
||||
Debug::log(ERR, "updateXKBTranslationState: keymap failed 1, fallback without model/variant");
|
||||
rules.model = "";
|
||||
rules.variant = "";
|
||||
KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
if (!KEYMAP) {
|
||||
Debug::log(ERR, "updateXKBTranslationState: keymap failed 2, fallback to us");
|
||||
rules.layout = "us";
|
||||
KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
xkbTranslationState = xkb_state_new(KEYMAP);
|
||||
|
||||
xkb_keymap_unref(KEYMAP);
|
||||
xkb_context_unref(PCONTEXT);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Updating keyboard {:x}'s translation state from an unknown index", (uintptr_t)this);
|
||||
|
||||
xkb_rule_names rules = {
|
||||
.rules = currentRules.rules.c_str(),
|
||||
.model = currentRules.model.c_str(),
|
||||
.layout = currentRules.layout.c_str(),
|
||||
.variant = currentRules.variant.c_str(),
|
||||
.options = currentRules.options.c_str(),
|
||||
};
|
||||
|
||||
const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
xkbTranslationState = xkb_state_new(NEWKEYMAP);
|
||||
|
||||
xkb_keymap_unref(NEWKEYMAP);
|
||||
xkb_context_unref(PCONTEXT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
#include "Region.hpp"
|
||||
|
||||
class CMonitor;
|
||||
class CVirtualKeyboard;
|
||||
class CVirtualPointer;
|
||||
class IPointer;
|
||||
class IKeyboard;
|
||||
|
||||
struct SRenderData {
|
||||
CMonitor* pMonitor;
|
||||
|
|
@ -58,86 +58,12 @@ struct SExtensionFindingData {
|
|||
wlr_surface** found;
|
||||
};
|
||||
|
||||
struct SStringRuleNames {
|
||||
std::string layout = "";
|
||||
std::string model = "";
|
||||
std::string variant = "";
|
||||
std::string options = "";
|
||||
std::string rules = "";
|
||||
};
|
||||
|
||||
struct SKeyboard {
|
||||
wlr_input_device* keyboard;
|
||||
|
||||
DYNLISTENER(keyboardMod);
|
||||
DYNLISTENER(keyboardKey);
|
||||
DYNLISTENER(keyboardKeymap);
|
||||
DYNLISTENER(keyboardDestroy);
|
||||
|
||||
bool isVirtual = false;
|
||||
bool active = false;
|
||||
bool enabled = true;
|
||||
|
||||
WP<CVirtualKeyboard> virtKeyboard;
|
||||
|
||||
xkb_layout_index_t activeLayout = 0;
|
||||
xkb_state* xkbTranslationState = nullptr;
|
||||
|
||||
std::string name = "";
|
||||
std::string xkbFilePath = "";
|
||||
|
||||
SStringRuleNames currentRules;
|
||||
int repeatRate = 0;
|
||||
int repeatDelay = 0;
|
||||
int numlockOn = -1;
|
||||
bool resolveBindsBySym = false;
|
||||
|
||||
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr);
|
||||
|
||||
struct {
|
||||
CHyprSignalListener destroyVKeyboard;
|
||||
} listeners;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SKeyboard& rhs) const {
|
||||
return keyboard == rhs.keyboard;
|
||||
}
|
||||
|
||||
~SKeyboard() {
|
||||
if (xkbTranslationState)
|
||||
xkb_state_unref(xkbTranslationState);
|
||||
}
|
||||
};
|
||||
|
||||
struct SMouse {
|
||||
wlr_input_device* mouse = nullptr;
|
||||
|
||||
std::string name = "";
|
||||
|
||||
bool virt = false;
|
||||
|
||||
bool connected = false; // means connected to the cursor
|
||||
|
||||
WP<CVirtualPointer> virtualPointer;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener destroyMouse;
|
||||
} listeners;
|
||||
|
||||
DYNLISTENER(destroyMouse);
|
||||
|
||||
bool operator==(const SMouse& b) const {
|
||||
return mouse == b.mouse;
|
||||
}
|
||||
};
|
||||
|
||||
class CMonitor;
|
||||
|
||||
struct SSeat {
|
||||
wlr_seat* seat = nullptr;
|
||||
wl_client* exclusiveClient = nullptr;
|
||||
wlr_seat* seat = nullptr;
|
||||
wl_client* exclusiveClient = nullptr;
|
||||
|
||||
SMouse* mouse = nullptr;
|
||||
WP<IPointer> mouse;
|
||||
WP<IKeyboard> keyboard;
|
||||
};
|
||||
|
||||
struct SDrag {
|
||||
|
|
@ -238,20 +164,6 @@ struct SSwipeGesture {
|
|||
CMonitor* pMonitor = nullptr;
|
||||
};
|
||||
|
||||
struct STouchDevice {
|
||||
wlr_input_device* pWlrDevice = nullptr;
|
||||
|
||||
std::string name = "";
|
||||
|
||||
std::string boundOutput = "";
|
||||
|
||||
DYNLISTENER(destroy);
|
||||
|
||||
bool operator==(const STouchDevice& other) const {
|
||||
return pWlrDevice == other.pWlrDevice;
|
||||
}
|
||||
};
|
||||
|
||||
struct SSwitchDevice {
|
||||
wlr_input_device* pWlrDevice = nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,3 +11,11 @@ void CSignalListener::emit(std::any data) {
|
|||
|
||||
m_fHandler(data);
|
||||
}
|
||||
|
||||
CStaticSignalListener::CStaticSignalListener(std::function<void(void*, std::any)> handler, void* owner) : m_pOwner(owner), m_fHandler(handler) {
|
||||
;
|
||||
}
|
||||
|
||||
void CStaticSignalListener::emit(std::any data) {
|
||||
m_fHandler(m_pOwner, data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,3 +22,19 @@ class CSignalListener {
|
|||
};
|
||||
|
||||
typedef std::shared_ptr<CSignalListener> CHyprSignalListener;
|
||||
|
||||
class CStaticSignalListener {
|
||||
public:
|
||||
CStaticSignalListener(std::function<void(void*, std::any)> handler, void* owner);
|
||||
|
||||
CStaticSignalListener(CStaticSignalListener&&) = delete;
|
||||
CStaticSignalListener(CStaticSignalListener&) = delete;
|
||||
CStaticSignalListener(const CStaticSignalListener&) = delete;
|
||||
CStaticSignalListener(const CStaticSignalListener&&) = delete;
|
||||
|
||||
void emit(std::any data);
|
||||
|
||||
private:
|
||||
void* m_pOwner = nullptr;
|
||||
std::function<void(void*, std::any)> m_fHandler;
|
||||
};
|
||||
|
|
@ -11,6 +11,10 @@ void CSignal::emit(std::any data) {
|
|||
dirty = true;
|
||||
}
|
||||
|
||||
for (auto& l : m_vStaticListeners) {
|
||||
l->emit(data);
|
||||
}
|
||||
|
||||
if (dirty)
|
||||
std::erase_if(m_vListeners, [](const auto& other) { return other.expired(); });
|
||||
}
|
||||
|
|
@ -20,3 +24,7 @@ CHyprSignalListener CSignal::registerListener(std::function<void(std::any)> hand
|
|||
m_vListeners.emplace_back(std::weak_ptr<CSignalListener>(listener));
|
||||
return listener;
|
||||
}
|
||||
|
||||
void CSignal::registerStaticListener(std::function<void(void*, std::any)> handler, void* owner) {
|
||||
m_vStaticListeners.emplace_back(std::make_unique<CStaticSignalListener>(handler, owner));
|
||||
}
|
||||
|
|
@ -14,6 +14,11 @@ class CSignal {
|
|||
//
|
||||
[[nodiscard("Listener is unregistered when the ptr is lost")]] CHyprSignalListener registerListener(std::function<void(std::any)> handler);
|
||||
|
||||
// this is for static listeners. They die with this signal.
|
||||
// TODO: can we somehow rid of the void* data and make it a custom this?
|
||||
void registerStaticListener(std::function<void(void*, std::any)> handler, void* owner);
|
||||
|
||||
private:
|
||||
std::vector<std::weak_ptr<CSignalListener>> m_vListeners;
|
||||
std::vector<std::weak_ptr<CSignalListener>> m_vListeners;
|
||||
std::vector<std::unique_ptr<CStaticSignalListener>> m_vStaticListeners;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue