-
-
Notifications
You must be signed in to change notification settings - Fork 907
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
39 changed files
with
1,443 additions
and
566 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
#include <string> | ||
#include "../helpers/signal/Signal.hpp" | ||
|
||
enum eHIDCapabilityType : uint32_t { | ||
HID_INPUT_CAPABILITY_KEYBOARD = (1 << 0), | ||
HID_INPUT_CAPABILITY_POINTER = (1 << 1), | ||
HID_INPUT_CAPABILITY_TOUCH = (1 << 2), | ||
}; | ||
|
||
/* | ||
Base class for a HID device. | ||
This could be a keyboard, a mouse, or a touchscreen. | ||
*/ | ||
class IHID { | ||
public: | ||
virtual uint32_t getCapabilities() = 0; | ||
|
||
struct { | ||
CSignal destroy; | ||
} events; | ||
|
||
std::string deviceName; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#include "IKeyboard.hpp" | ||
#include "../defines.hpp" | ||
#include "../helpers/VarList.hpp" | ||
#include "../managers/input/InputManager.hpp" | ||
|
||
uint32_t IKeyboard::getCapabilities() { | ||
return HID_INPUT_CAPABILITY_KEYBOARD; | ||
} | ||
|
||
IKeyboard::~IKeyboard() { | ||
events.destroy.emit(); | ||
|
||
if (!xkbTranslationState) | ||
return; | ||
|
||
xkb_state_unref(xkbTranslationState); | ||
xkbTranslationState = nullptr; | ||
} | ||
|
||
void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { | ||
|
||
if (xkbTranslationState) | ||
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(); | ||
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); | ||
} | ||
|
||
std::string IKeyboard::getActiveLayout() { | ||
const auto WLRKB = wlr(); | ||
const auto KEYMAP = WLRKB->keymap; | ||
const auto STATE = WLRKB->xkb_state; | ||
const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); | ||
|
||
for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { | ||
if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) { | ||
const auto LAYOUTNAME = xkb_keymap_layout_get_name(KEYMAP, i); | ||
|
||
if (LAYOUTNAME) | ||
return std::string(LAYOUTNAME); | ||
return "error"; | ||
} | ||
} | ||
|
||
return "none"; | ||
} | ||
|
||
void IKeyboard::updateLEDs() { | ||
auto keyboard = wlr(); | ||
|
||
if (keyboard->xkb_state == nullptr) | ||
return; | ||
|
||
uint32_t leds = 0; | ||
for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { | ||
if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) | ||
leds |= (1 << i); | ||
} | ||
|
||
if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock())) | ||
return; | ||
|
||
wlr_keyboard_led_update(wlr(), leds); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#pragma once | ||
|
||
#include "IHID.hpp" | ||
#include "../helpers/WLListener.hpp" | ||
#include "../macros.hpp" | ||
#include "../helpers/Vector2D.hpp" | ||
|
||
#include <xkbcommon/xkbcommon.h> | ||
|
||
struct wlr_keyboard; | ||
|
||
class IKeyboard : public IHID { | ||
public: | ||
virtual ~IKeyboard(); | ||
virtual uint32_t getCapabilities(); | ||
virtual bool isVirtual() = 0; | ||
virtual wlr_keyboard* wlr() = 0; | ||
|
||
struct SKeyEvent { | ||
uint32_t timeMs = 0; | ||
uint32_t keycode = 0; | ||
bool updateMods = false; | ||
wl_keyboard_key_state state = WL_KEYBOARD_KEY_STATE_PRESSED; | ||
}; | ||
|
||
struct { | ||
CSignal key; | ||
CSignal modifiers; | ||
CSignal keymap; | ||
CSignal repeatInfo; | ||
} keyboardEvents; | ||
|
||
struct SStringRuleNames { | ||
std::string layout = ""; | ||
std::string model = ""; | ||
std::string variant = ""; | ||
std::string options = ""; | ||
std::string rules = ""; | ||
}; | ||
|
||
void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); | ||
std::string getActiveLayout(); | ||
void updateLEDs(); | ||
|
||
bool active = false; | ||
bool enabled = true; | ||
|
||
xkb_layout_index_t activeLayout = 0; | ||
xkb_state* xkbTranslationState = nullptr; | ||
|
||
std::string hlName = ""; | ||
std::string xkbFilePath = ""; | ||
|
||
SStringRuleNames currentRules; | ||
int repeatRate = 0; | ||
int repeatDelay = 0; | ||
int numlockOn = -1; | ||
bool resolveBindsBySym = false; | ||
|
||
WP<IKeyboard> self; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#include "IPointer.hpp" | ||
|
||
uint32_t IPointer::getCapabilities() { | ||
return HID_INPUT_CAPABILITY_POINTER; | ||
} |
Oops, something went wrong.