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:
Vaxry 2024-05-03 22:34:10 +01:00
parent 1d2acbe193
commit 1237732b97
39 changed files with 1450 additions and 573 deletions

View File

@ -2418,10 +2418,7 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) {
if (*PNOWARPS && !force)
return;
if (!m_sSeat.mouse)
return;
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pos.x, pos.y);
wlr_cursor_warp(m_sWLRCursor, nullptr, pos.x, pos.y);
const auto PMONITORNEW = getMonitorFromVector(pos);
if (PMONITORNEW != m_pLastMonitor)

View File

@ -19,6 +19,9 @@
#include "../config/ConfigValue.hpp"
#include "../managers/CursorManager.hpp"
#include "../hyprerror/HyprError.hpp"
#include "../devices/IPointer.hpp"
#include "../devices/IKeyboard.hpp"
#include "../devices/ITouch.hpp"
static void trimTrailingComma(std::string& str) {
if (!str.empty() && str.back() == ',')
@ -514,23 +517,24 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
result += "{\n";
result += "\"mice\": [\n";
for (auto& m : g_pInputManager->m_lMice) {
for (auto& m : g_pInputManager->m_vPointers) {
result += std::format(
R"#( {{
"address": "0x{:x}",
"name": "{}",
"defaultSpeed": {:.5f}
}},)#",
(uintptr_t)&m, escapeJSONStrings(m.name),
wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f);
(uintptr_t)m.get(), escapeJSONStrings(m->hlName),
wlr_input_device_is_libinput(&m->wlr()->base) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) :
0.f);
}
trimTrailingComma(result);
result += "\n],\n";
result += "\"keyboards\": [\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
for (auto& k : g_pInputManager->m_vKeyboards) {
const auto KM = k->getActiveLayout();
result += std::format(
R"#( {{
"address": "0x{:x}",
@ -543,9 +547,9 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
"active_keymap": "{}",
"main": {}
}},)#",
(uintptr_t)&k, escapeJSONStrings(k.name), escapeJSONStrings(k.currentRules.rules), escapeJSONStrings(k.currentRules.model),
escapeJSONStrings(k.currentRules.layout), escapeJSONStrings(k.currentRules.variant), escapeJSONStrings(k.currentRules.options), escapeJSONStrings(KM),
(k.active ? "true" : "false"));
(uintptr_t)k.get(), escapeJSONStrings(k->hlName), escapeJSONStrings(k->currentRules.rules), escapeJSONStrings(k->currentRules.model),
escapeJSONStrings(k->currentRules.layout), escapeJSONStrings(k->currentRules.variant), escapeJSONStrings(k->currentRules.options), escapeJSONStrings(KM),
(k->active ? "true" : "false"));
}
trimTrailingComma(result);
@ -590,13 +594,13 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
result += "\"touch\": [\n";
for (auto& d : g_pInputManager->m_lTouchDevices) {
for (auto& d : g_pInputManager->m_vTouches) {
result += std::format(
R"#( {{
"address": "0x{:x}",
"name": "{}"
}},)#",
(uintptr_t)&d, escapeJSONStrings(d.name));
(uintptr_t)d.get(), escapeJSONStrings(d->hlName));
}
trimTrailingComma(result);
@ -621,19 +625,20 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
} else {
result += "mice:\n";
for (auto& m : g_pInputManager->m_lMice) {
result += std::format(
"\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)&m, m.name,
(wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f));
for (auto& m : g_pInputManager->m_vPointers) {
result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName,
(wlr_input_device_is_libinput(&m->wlr()->base) ?
libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base)) :
0.f));
}
result += "\n\nKeyboards:\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
for (auto& k : g_pInputManager->m_vKeyboards) {
const auto KM = k->getActiveLayout();
result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tmain: {}\n",
(uintptr_t)&k, k.name, k.currentRules.rules, k.currentRules.model, k.currentRules.layout, k.currentRules.variant, k.currentRules.options, KM,
(k.active ? "yes" : "no"));
(uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant,
k->currentRules.options, KM, (k->active ? "yes" : "no"));
}
result += "\n\nTablets:\n";
@ -652,8 +657,8 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
result += "\n\nTouch:\n";
for (auto& d : g_pInputManager->m_lTouchDevices) {
result += std::format("\tTouch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.name);
for (auto& d : g_pInputManager->m_vTouches) {
result += std::format("\tTouch Device at {:x}:\n\t\t{}\n", (uintptr_t)d.get(), d->hlName);
}
result += "\n\nSwitches:\n";
@ -1069,13 +1074,13 @@ std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string requ
const auto CMD = vars[2];
// get kb
const auto PKEYBOARD = std::find_if(g_pInputManager->m_lKeyboards.begin(), g_pInputManager->m_lKeyboards.end(),
[&](const SKeyboard& other) { return other.name == g_pInputManager->deviceNameToInternalString(KB); });
const auto PKEYBOARD = std::find_if(g_pInputManager->m_vKeyboards.begin(), g_pInputManager->m_vKeyboards.end(),
[&](const auto& other) { return other->hlName == g_pInputManager->deviceNameToInternalString(KB); });
if (PKEYBOARD == g_pInputManager->m_lKeyboards.end())
if (PKEYBOARD == g_pInputManager->m_vKeyboards.end())
return "device not found";
const auto PWLRKEYBOARD = wlr_keyboard_from_input_device(PKEYBOARD->keyboard);
const auto PWLRKEYBOARD = (*PKEYBOARD)->wlr();
const auto LAYOUTS = xkb_keymap_num_layouts(PWLRKEYBOARD->keymap);
xkb_layout_index_t activeLayout = 0;
while (activeLayout < LAYOUTS) {

View File

@ -196,7 +196,7 @@ void CLayerSurface::onMap() {
const bool GRABSFOCUS = layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
// don't focus if constrained
(!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained());
(g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained());
if (GRABSFOCUS) {
g_pInputManager->releaseAllMouseButtons();
@ -383,7 +383,7 @@ void CLayerSurface::onCommit() {
realSize.setValueAndWarp(geometry.size());
}
if (layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) // don't focus if constrained
if (layerSurface->current.keyboard_interactive && (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()) // don't focus if constrained
&& !keyboardExclusive && mapped) {
g_pCompositor->focusSurface(layerSurface->surface);
@ -391,7 +391,7 @@ void CLayerSurface::onCommit() {
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layerSurface->surface, LOCAL.x, LOCAL.y);
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y);
g_pInputManager->m_bEmptyFocusCursorSet = false;
} else if (!layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained()) && keyboardExclusive) {
} else if (!layerSurface->current.keyboard_interactive && (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained()) && keyboardExclusive) {
g_pInputManager->refocus();
}

26
src/devices/IHID.hpp Normal file
View File

@ -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;
};

134
src/devices/IKeyboard.cpp Normal file
View File

@ -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);
}

61
src/devices/IKeyboard.hpp Normal file
View File

@ -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;
};

5
src/devices/IPointer.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "IPointer.hpp"
uint32_t IPointer::getCapabilities() {
return HID_INPUT_CAPABILITY_POINTER;
}

110
src/devices/IPointer.hpp Normal file
View File

@ -0,0 +1,110 @@
#pragma once
#include "IHID.hpp"
#include "../helpers/WLListener.hpp"
#include "../macros.hpp"
#include "../helpers/Vector2D.hpp"
struct wlr_pointer;
/*
Base class for a pointer.
*/
class IPointer : public IHID {
public:
virtual uint32_t getCapabilities();
virtual bool isVirtual() = 0;
virtual wlr_pointer* wlr() = 0;
struct SMotionEvent {
uint32_t timeMs = 0;
Vector2D delta, unaccel;
};
struct SMotionAbsoluteEvent {
uint32_t timeMs = 0;
Vector2D absolute; // 0.0 - 1.0
};
struct SButtonEvent {
uint32_t timeMs = 0;
uint32_t button = 0;
wl_pointer_button_state state = WL_POINTER_BUTTON_STATE_PRESSED;
};
struct SAxisEvent {
uint32_t timeMs = 0;
wl_pointer_axis_source source = WL_POINTER_AXIS_SOURCE_WHEEL;
wl_pointer_axis axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
wl_pointer_axis_relative_direction relativeDirection = WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL;
double delta = 0.0;
int32_t deltaDiscrete = 0;
};
struct SSwipeBeginEvent {
uint32_t timeMs = 0;
uint32_t fingers = 0;
};
struct SSwipeUpdateEvent {
uint32_t timeMs = 0;
uint32_t fingers = 0;
Vector2D delta;
};
struct SSwipeEndEvent {
uint32_t timeMs = 0;
bool cancelled = false;
};
struct SPinchBeginEvent {
uint32_t timeMs = 0;
uint32_t fingers = 0;
};
struct SPinchUpdateEvent {
uint32_t timeMs = 0;
uint32_t fingers = 0;
Vector2D delta;
double scale = 1.0, rotation = 0.0;
};
struct SPinchEndEvent {
uint32_t timeMs = 0;
bool cancelled = false;
};
struct SHoldBeginEvent {
uint32_t timeMs = 0;
uint32_t fingers = 0;
};
struct SHoldEndEvent {
uint32_t timeMs = 0;
bool cancelled = false;
};
struct {
CSignal motion;
CSignal motionAbsolute;
CSignal button;
CSignal axis;
CSignal frame;
CSignal swipeBegin;
CSignal swipeEnd;
CSignal swipeUpdate;
CSignal pinchBegin;
CSignal pinchEnd;
CSignal pinchUpdate;
CSignal holdBegin;
CSignal holdEnd;
} pointerEvents;
std::string hlName;
bool connected = false; // means connected to the cursor
WP<IPointer> self;
};

5
src/devices/ITouch.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "ITouch.hpp"
uint32_t ITouch::getCapabilities() {
return HID_INPUT_CAPABILITY_TOUCH;
}

50
src/devices/ITouch.hpp Normal file
View File

@ -0,0 +1,50 @@
#pragma once
#include "IHID.hpp"
#include "../helpers/WLListener.hpp"
#include "../macros.hpp"
#include "../helpers/Vector2D.hpp"
struct wlr_touch;
class ITouch : public IHID {
public:
virtual uint32_t getCapabilities();
virtual bool isVirtual() = 0;
virtual wlr_touch* wlr() = 0;
struct SDownEvent {
uint32_t timeMs = 0;
int32_t touchID = 0;
Vector2D pos;
};
struct SUpEvent {
uint32_t timeMs = 0;
int32_t touchID = 0;
};
struct SMotionEvent {
uint32_t timeMs = 0;
int32_t touchID = 0;
Vector2D pos;
};
struct SCancelEvent {
uint32_t timeMs = 0;
int32_t touchID = 0;
};
struct {
CSignal down;
CSignal up;
CSignal motion;
CSignal cancel;
CSignal frame;
} touchEvents;
std::string hlName = "";
std::string boundOutput = "";
WP<ITouch> self;
};

64
src/devices/Keyboard.cpp Normal file
View File

@ -0,0 +1,64 @@
#include "Keyboard.hpp"
#include "../defines.hpp"
SP<CKeyboard> CKeyboard::create(wlr_keyboard* keeb) {
SP<CKeyboard> pKeeb = SP<CKeyboard>(new CKeyboard(keeb));
pKeeb->self = pKeeb;
return pKeeb;
}
bool CKeyboard::isVirtual() {
return false;
}
wlr_keyboard* CKeyboard::wlr() {
return keyboard;
}
CKeyboard::CKeyboard(wlr_keyboard* keeb) : keyboard(keeb) {
if (!keeb)
return;
// clang-format off
hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) {
events.destroy.emit();
disconnectCallbacks();
keyboard = nullptr;
}, this, "CKeyboard");
hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) {
auto E = (wlr_keyboard_key_event*)data;
keyboardEvents.key.emit(SKeyEvent{
.timeMs = E->time_msec,
.keycode = E->keycode,
.updateMods = E->update_state,
.state = E->state,
});
}, this, "CKeyboard");
hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) {
keyboardEvents.keymap.emit();
}, this, "CKeyboard");
hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) {
keyboardEvents.modifiers.emit();
}, this, "CKeyboard");
hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) {
keyboardEvents.repeatInfo.emit();
}, this, "CKeyboard");
// clang-format on
deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN";
}
void CKeyboard::disconnectCallbacks() {
hyprListener_destroy.removeCallback();
hyprListener_key.removeCallback();
hyprListener_keymap.removeCallback();
hyprListener_repeatInfo.removeCallback();
hyprListener_modifiers.removeCallback();
}

24
src/devices/Keyboard.hpp Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include "IKeyboard.hpp"
class CKeyboard : public IKeyboard {
public:
static SP<CKeyboard> create(wlr_keyboard* keeb);
virtual bool isVirtual();
virtual wlr_keyboard* wlr();
private:
CKeyboard(wlr_keyboard* keeb);
wlr_keyboard* keyboard = nullptr;
void disconnectCallbacks();
DYNLISTENER(destroy);
DYNLISTENER(key);
DYNLISTENER(modifiers);
DYNLISTENER(keymap);
DYNLISTENER(repeatInfo);
};

169
src/devices/Mouse.cpp Normal file
View File

@ -0,0 +1,169 @@
#include "Mouse.hpp"
#include "../defines.hpp"
SP<CMouse> CMouse::create(wlr_pointer* mouse) {
SP<CMouse> pMouse = SP<CMouse>(new CMouse(mouse));
pMouse->self = pMouse;
return pMouse;
}
CMouse::CMouse(wlr_pointer* mouse_) : mouse(mouse_) {
if (!mouse)
return;
// clang-format off
hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) {
disconnectCallbacks();
mouse = nullptr;
events.destroy.emit();
}, this, "CMouse");
hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) {
auto E = (wlr_pointer_motion_event*)data;
pointerEvents.motion.emit(SMotionEvent{
.timeMs = E->time_msec,
.delta = {E->delta_x, E->delta_y},
.unaccel = {E->unaccel_dx, E->unaccel_dy},
});
}, this, "CMouse");
hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) {
auto E = (wlr_pointer_motion_absolute_event*)data;
pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{
.timeMs = E->time_msec,
.absolute = {E->x, E->y},
});
}, this, "CMouse");
hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) {
auto E = (wlr_pointer_button_event*)data;
pointerEvents.button.emit(SButtonEvent{
.timeMs = E->time_msec,
.button = E->button,
.state = (wl_pointer_button_state)E->state,
});
}, this, "CMouse");
hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) {
auto E = (wlr_pointer_axis_event*)data;
pointerEvents.axis.emit(SAxisEvent{
.timeMs = E->time_msec,
.source = E->source,
.axis = E->orientation,
.relativeDirection = E->relative_direction,
.delta = E->delta,
.deltaDiscrete = E->delta_discrete,
});
}, this, "CMouse");
hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) {
auto E = (wlr_pointer_swipe_begin_event*)data;
pointerEvents.swipeBegin.emit(SSwipeBeginEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
});
}, this, "CMouse");
hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) {
auto E = (wlr_pointer_swipe_end_event*)data;
pointerEvents.swipeEnd.emit(SSwipeEndEvent{
.timeMs = E->time_msec,
.cancelled = E->cancelled,
});
}, this, "CMouse");
hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) {
auto E = (wlr_pointer_swipe_update_event*)data;
pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
.delta = {E->dx, E->dy},
});
}, this, "CMouse");
hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) {
auto E = (wlr_pointer_pinch_begin_event*)data;
pointerEvents.pinchBegin.emit(SPinchBeginEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
});
}, this, "CMouse");
hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) {
auto E = (wlr_pointer_pinch_end_event*)data;
pointerEvents.pinchEnd.emit(SPinchEndEvent{
.timeMs = E->time_msec,
.cancelled = E->cancelled,
});
}, this, "CMouse");
hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) {
auto E = (wlr_pointer_pinch_update_event*)data;
pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
.delta = {E->dx, E->dy},
.scale = E->scale,
.rotation = E->rotation,
});
}, this, "CMouse");
hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) {
auto E = (wlr_pointer_hold_begin_event*)data;
pointerEvents.holdBegin.emit(SHoldBeginEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
});
}, this, "CMouse");
hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) {
auto E = (wlr_pointer_hold_end_event*)data;
pointerEvents.holdEnd.emit(SHoldEndEvent{
.timeMs = E->time_msec,
.cancelled = E->cancelled,
});
}, this, "CMouse");
// clang-format on
deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN";
}
void CMouse::disconnectCallbacks() {
hyprListener_destroy.removeCallback();
hyprListener_motion.removeCallback();
hyprListener_motionAbsolute.removeCallback();
hyprListener_button.removeCallback();
hyprListener_axis.removeCallback();
hyprListener_frame.removeCallback();
hyprListener_swipeBegin.removeCallback();
hyprListener_swipeEnd.removeCallback();
hyprListener_swipeUpdate.removeCallback();
hyprListener_pinchBegin.removeCallback();
hyprListener_pinchEnd.removeCallback();
hyprListener_pinchUpdate.removeCallback();
hyprListener_holdBegin.removeCallback();
hyprListener_holdEnd.removeCallback();
}
bool CMouse::isVirtual() {
return false;
}
wlr_pointer* CMouse::wlr() {
return mouse;
}

36
src/devices/Mouse.hpp Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include "IPointer.hpp"
class CMouse : public IPointer {
public:
static SP<CMouse> create(wlr_pointer* mouse);
virtual bool isVirtual();
virtual wlr_pointer* wlr();
private:
CMouse(wlr_pointer* mouse);
wlr_pointer* mouse = nullptr;
void disconnectCallbacks();
DYNLISTENER(destroy);
DYNLISTENER(motion);
DYNLISTENER(motionAbsolute);
DYNLISTENER(button);
DYNLISTENER(axis);
DYNLISTENER(frame);
DYNLISTENER(swipeBegin);
DYNLISTENER(swipeEnd);
DYNLISTENER(swipeUpdate);
DYNLISTENER(pinchBegin);
DYNLISTENER(pinchEnd);
DYNLISTENER(pinchUpdate);
DYNLISTENER(holdBegin);
DYNLISTENER(holdEnd);
};

View File

@ -0,0 +1,85 @@
#include "TouchDevice.hpp"
#include "../defines.hpp"
SP<CTouchDevice> CTouchDevice::create(wlr_touch* touch) {
SP<CTouchDevice> pTouch = SP<CTouchDevice>(new CTouchDevice(touch));
pTouch->self = pTouch;
return pTouch;
}
CTouchDevice::CTouchDevice(wlr_touch* touch_) : touch(touch_) {
if (!touch)
return;
// clang-format off
hyprListener_destroy.initCallback(&touch->base.events.destroy, [this] (void* owner, void* data) {
events.destroy.emit();
disconnectCallbacks();
touch = nullptr;
}, this, "CTouchDevice");
hyprListener_down.initCallback(&touch->events.down, [this] (void* owner, void* data) {
auto E = (wlr_touch_down_event*)data;
touchEvents.down.emit(SDownEvent{
.timeMs = E->time_msec,
.touchID = E->touch_id,
.pos = {E->x, E->y},
});
}, this, "CTouchDevice");
hyprListener_up.initCallback(&touch->events.up, [this] (void* owner, void* data) {
auto E = (wlr_touch_up_event*)data;
touchEvents.up.emit(SUpEvent{
.timeMs = E->time_msec,
.touchID = E->touch_id
});
}, this, "CTouchDevice");
hyprListener_motion.initCallback(&touch->events.motion, [this] (void* owner, void* data) {
auto E = (wlr_touch_motion_event*)data;
touchEvents.motion.emit(SMotionEvent{
.timeMs = E->time_msec,
.touchID = E->touch_id,
.pos = {E->x, E->y},
});
}, this, "CTouchDevice");
hyprListener_cancel.initCallback(&touch->events.cancel, [this] (void* owner, void* data) {
auto E = (wlr_touch_cancel_event*)data;
touchEvents.cancel.emit(SCancelEvent{
.timeMs = E->time_msec,
.touchID = E->touch_id
});
}, this, "CTouchDevice");
hyprListener_frame.initCallback(&touch->events.frame, [this] (void* owner, void* data) {
touchEvents.frame.emit();
}, this, "CTouchDevice");
// clang-format on
deviceName = touch->base.name ? touch->base.name : "UNKNOWN";
}
bool CTouchDevice::isVirtual() {
return false;
}
wlr_touch* CTouchDevice::wlr() {
return touch;
}
void CTouchDevice::disconnectCallbacks() {
hyprListener_destroy.removeCallback();
hyprListener_down.removeCallback();
hyprListener_up.removeCallback();
hyprListener_motion.removeCallback();
hyprListener_cancel.removeCallback();
hyprListener_frame.removeCallback();
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "ITouch.hpp"
class CTouchDevice : public ITouch {
public:
static SP<CTouchDevice> create(wlr_touch* touch);
virtual bool isVirtual();
virtual wlr_touch* wlr();
private:
CTouchDevice(wlr_touch* touch);
wlr_touch* touch = nullptr;
void disconnectCallbacks();
DYNLISTENER(destroy);
DYNLISTENER(down);
DYNLISTENER(up);
DYNLISTENER(motion);
DYNLISTENER(cancel);
DYNLISTENER(frame);
};

View File

@ -0,0 +1,71 @@
#include "VirtualKeyboard.hpp"
#include "../defines.hpp"
#include "../protocols/VirtualKeyboard.hpp"
SP<CVirtualKeyboard> CVirtualKeyboard::create(SP<CVirtualKeyboardV1Resource> keeb) {
SP<CVirtualKeyboard> pKeeb = SP<CVirtualKeyboard>(new CVirtualKeyboard(keeb));
pKeeb->self = pKeeb;
return pKeeb;
}
CVirtualKeyboard::CVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keeb_) : keyboard(keeb_) {
if (!keeb_)
return;
auto keeb = keeb_->wlr();
// clang-format off
hyprListener_destroy.initCallback(&keeb->base.events.destroy, [this] (void* owner, void* data) {
events.destroy.emit();
disconnectCallbacks();
keyboard.reset();
}, this, "CVirtualKeyboard");
hyprListener_key.initCallback(&keeb->events.key, [this] (void* owner, void* data) {
auto E = (wlr_keyboard_key_event*)data;
keyboardEvents.key.emit(SKeyEvent{
.timeMs = E->time_msec,
.keycode = E->keycode,
.updateMods = E->update_state,
.state = E->state,
});
}, this, "CVirtualKeyboard");
hyprListener_keymap.initCallback(&keeb->events.keymap, [this] (void* owner, void* data) {
keyboardEvents.keymap.emit();
}, this, "CVirtualKeyboard");
hyprListener_modifiers.initCallback(&keeb->events.modifiers, [this] (void* owner, void* data) {
keyboardEvents.modifiers.emit();
}, this, "CVirtualKeyboard");
hyprListener_repeatInfo.initCallback(&keeb->events.repeat_info, [this] (void* owner, void* data) {
keyboardEvents.repeatInfo.emit();
}, this, "CVirtualKeyboard");
// clang-format on
deviceName = keeb->base.name ? keeb->base.name : "UNKNOWN";
}
bool CVirtualKeyboard::isVirtual() {
return true;
}
wlr_keyboard* CVirtualKeyboard::wlr() {
return keyboard.lock()->wlr();
}
void CVirtualKeyboard::disconnectCallbacks() {
hyprListener_destroy.removeCallback();
hyprListener_key.removeCallback();
hyprListener_keymap.removeCallback();
hyprListener_repeatInfo.removeCallback();
hyprListener_modifiers.removeCallback();
}
wl_client* CVirtualKeyboard::getClient() {
return keyboard.lock()->client();
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "IKeyboard.hpp"
class CVirtualKeyboardV1Resource;
class CVirtualKeyboard : public IKeyboard {
public:
static SP<CVirtualKeyboard> create(SP<CVirtualKeyboardV1Resource> keeb);
virtual bool isVirtual();
virtual wlr_keyboard* wlr();
wl_client* getClient();
private:
CVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keeb);
WP<CVirtualKeyboardV1Resource> keyboard;
void disconnectCallbacks();
DYNLISTENER(destroy);
DYNLISTENER(key);
DYNLISTENER(modifiers);
DYNLISTENER(keymap);
DYNLISTENER(repeatInfo);
};

View File

@ -0,0 +1,170 @@
#include "VirtualPointer.hpp"
#include "../protocols/VirtualPointer.hpp"
SP<CVirtualPointer> CVirtualPointer::create(SP<CVirtualPointerV1Resource> resource) {
SP<CVirtualPointer> pPointer = SP<CVirtualPointer>(new CVirtualPointer(resource));
pPointer->self = pPointer;
return pPointer;
}
CVirtualPointer::CVirtualPointer(SP<CVirtualPointerV1Resource> resource) : pointer(resource) {
if (!resource->good())
return;
auto mouse = resource->wlr();
// clang-format off
hyprListener_destroy.initCallback(&mouse->base.events.destroy, [this] (void* owner, void* data) {
disconnectCallbacks();
events.destroy.emit();
}, this, "CVirtualPointer");
hyprListener_motion.initCallback(&mouse->events.motion, [this] (void* owner, void* data) {
auto E = (wlr_pointer_motion_event*)data;
pointerEvents.motion.emit(SMotionEvent{
.timeMs = E->time_msec,
.delta = {E->delta_x, E->delta_y},
.unaccel = {E->unaccel_dx, E->unaccel_dy},
});
}, this, "CVirtualPointer");
hyprListener_motionAbsolute.initCallback(&mouse->events.motion_absolute, [this] (void* owner, void* data) {
auto E = (wlr_pointer_motion_absolute_event*)data;
pointerEvents.motionAbsolute.emit(SMotionAbsoluteEvent{
.timeMs = E->time_msec,
.absolute = {E->x, E->y},
});
}, this, "CVirtualPointer");
hyprListener_button.initCallback(&mouse->events.button, [this] (void* owner, void* data) {
auto E = (wlr_pointer_button_event*)data;
pointerEvents.button.emit(SButtonEvent{
.timeMs = E->time_msec,
.button = E->button,
.state = (wl_pointer_button_state)E->state,
});
}, this, "CVirtualPointer");
hyprListener_axis.initCallback(&mouse->events.axis, [this] (void* owner, void* data) {
auto E = (wlr_pointer_axis_event*)data;
pointerEvents.axis.emit(SAxisEvent{
.timeMs = E->time_msec,
.source = E->source,
.axis = E->orientation,
.relativeDirection = E->relative_direction,
.delta = E->delta,
.deltaDiscrete = E->delta_discrete,
});
}, this, "CVirtualPointer");
hyprListener_swipeBegin.initCallback(&mouse->events.swipe_begin, [this] (void* owner, void* data) {
auto E = (wlr_pointer_swipe_begin_event*)data;
pointerEvents.swipeBegin.emit(SSwipeBeginEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
});
}, this, "CVirtualPointer");
hyprListener_swipeEnd.initCallback(&mouse->events.swipe_end, [this] (void* owner, void* data) {
auto E = (wlr_pointer_swipe_end_event*)data;
pointerEvents.swipeEnd.emit(SSwipeEndEvent{
.timeMs = E->time_msec,
.cancelled = E->cancelled,
});
}, this, "CVirtualPointer");
hyprListener_swipeUpdate.initCallback(&mouse->events.swipe_update, [this] (void* owner, void* data) {
auto E = (wlr_pointer_swipe_update_event*)data;
pointerEvents.swipeUpdate.emit(SSwipeUpdateEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
.delta = {E->dx, E->dy},
});
}, this, "CVirtualPointer");
hyprListener_pinchBegin.initCallback(&mouse->events.pinch_begin, [this] (void* owner, void* data) {
auto E = (wlr_pointer_pinch_begin_event*)data;
pointerEvents.pinchBegin.emit(SPinchBeginEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
});
}, this, "CVirtualPointer");
hyprListener_pinchEnd.initCallback(&mouse->events.pinch_end, [this] (void* owner, void* data) {
auto E = (wlr_pointer_pinch_end_event*)data;
pointerEvents.pinchEnd.emit(SPinchEndEvent{
.timeMs = E->time_msec,
.cancelled = E->cancelled,
});
}, this, "CVirtualPointer");
hyprListener_pinchUpdate.initCallback(&mouse->events.pinch_update, [this] (void* owner, void* data) {
auto E = (wlr_pointer_pinch_update_event*)data;
pointerEvents.pinchUpdate.emit(SPinchUpdateEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
.delta = {E->dx, E->dy},
.scale = E->scale,
.rotation = E->rotation,
});
}, this, "CVirtualPointer");
hyprListener_holdBegin.initCallback(&mouse->events.hold_begin, [this] (void* owner, void* data) {
auto E = (wlr_pointer_hold_begin_event*)data;
pointerEvents.holdBegin.emit(SHoldBeginEvent{
.timeMs = E->time_msec,
.fingers = E->fingers,
});
}, this, "CVirtualPointer");
hyprListener_holdEnd.initCallback(&mouse->events.hold_end, [this] (void* owner, void* data) {
auto E = (wlr_pointer_hold_end_event*)data;
pointerEvents.holdEnd.emit(SHoldEndEvent{
.timeMs = E->time_msec,
.cancelled = E->cancelled,
});
}, this, "CVirtualPointer");
// clang-format on
deviceName = mouse->base.name ? mouse->base.name : "UNKNOWN";
}
bool CVirtualPointer::isVirtual() {
return true;
}
void CVirtualPointer::disconnectCallbacks() {
hyprListener_destroy.removeCallback();
hyprListener_motion.removeCallback();
hyprListener_motionAbsolute.removeCallback();
hyprListener_button.removeCallback();
hyprListener_axis.removeCallback();
hyprListener_frame.removeCallback();
hyprListener_swipeBegin.removeCallback();
hyprListener_swipeEnd.removeCallback();
hyprListener_swipeUpdate.removeCallback();
hyprListener_pinchBegin.removeCallback();
hyprListener_pinchEnd.removeCallback();
hyprListener_pinchUpdate.removeCallback();
hyprListener_holdBegin.removeCallback();
hyprListener_holdEnd.removeCallback();
}
wlr_pointer* CVirtualPointer::wlr() {
return pointer.lock()->wlr();
}

View File

@ -0,0 +1,38 @@
#pragma once
#include "IPointer.hpp"
class CVirtualPointerV1Resource;
class CVirtualPointer : public IPointer {
public:
static SP<CVirtualPointer> create(SP<CVirtualPointerV1Resource> resource);
virtual bool isVirtual();
virtual wlr_pointer* wlr();
private:
CVirtualPointer(SP<CVirtualPointerV1Resource>);
WP<CVirtualPointerV1Resource> pointer;
void disconnectCallbacks();
DYNLISTENER(destroy);
DYNLISTENER(motion);
DYNLISTENER(motionAbsolute);
DYNLISTENER(button);
DYNLISTENER(axis);
DYNLISTENER(frame);
DYNLISTENER(swipeBegin);
DYNLISTENER(swipeEnd);
DYNLISTENER(swipeUpdate);
DYNLISTENER(pinchBegin);
DYNLISTENER(pinchEnd);
DYNLISTENER(pinchUpdate);
DYNLISTENER(holdBegin);
DYNLISTENER(holdEnd);
};

View File

@ -16,23 +16,6 @@
// //
// ---------------------------------------------------- //
void Events::listener_keyboardDestroy(void* owner, void* data) {
SKeyboard* PKEYBOARD = (SKeyboard*)owner;
g_pInputManager->destroyKeyboard(PKEYBOARD);
Debug::log(LOG, "Destroyed keyboard {:x}", (uintptr_t)PKEYBOARD);
}
void Events::listener_keyboardKey(void* owner, void* data) {
SKeyboard* PKEYBOARD = (SKeyboard*)owner;
g_pInputManager->onKeyboardKey((wlr_keyboard_key_event*)data, PKEYBOARD);
}
void Events::listener_keyboardMod(void* owner, void* data) {
SKeyboard* PKEYBOARD = (SKeyboard*)owner;
g_pInputManager->onKeyboardMod(data, PKEYBOARD);
}
void Events::listener_mouseFrame(wl_listener* listener, void* data) {
wlr_seat_pointer_notify_frame(g_pCompositor->m_sSeat.seat);
}
@ -93,12 +76,6 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
g_pInputManager->updateCapabilities();
}
void Events::listener_destroyMouse(void* owner, void* data) {
const auto PMOUSE = (SMouse*)owner;
g_pInputManager->destroyMouse(PMOUSE->mouse);
}
void Events::listener_swipeBegin(wl_listener* listener, void* data) {
const auto EVENT = (wlr_pointer_swipe_begin_event*)data;

View File

@ -54,11 +54,6 @@ namespace Events {
// Virt Ptr
LISTENER(newVirtPtr);
DYNLISTENFUNC(destroyMouse);
DYNLISTENFUNC(keyboardKey);
DYNLISTENFUNC(keyboardMod);
DYNLISTENFUNC(keyboardDestroy);
// Various
LISTENER(requestMouse);

View File

@ -667,7 +667,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
if (!g_pCompositor->m_sSeat.mouse || !g_pInputManager->isConstrained())
if (g_pCompositor->m_sSeat.mouse.expired() || !g_pInputManager->isConstrained())
g_pInputManager->sendMotionEventsToFocused();
// fix some xwayland apps that don't behave nicely

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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));
}

View File

@ -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;
};

View File

@ -5,6 +5,7 @@
#include "../config/ConfigValue.hpp"
#include "TokenManager.hpp"
#include "../protocols/ShortcutsInhibit.hpp"
#include "../devices/IKeyboard.hpp"
#include <regex>
#include <tuple>
@ -323,7 +324,7 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) {
}
};
bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
bool CKeybindManager::onKeyEvent(std::any event, SP<IKeyboard> pKeyboard) {
if (!g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
m_dPressedKeys.clear();
return true;
@ -337,17 +338,19 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
return true;
}
const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
auto e = std::any_cast<IKeyboard::SKeyEvent>(event);
const auto KEYCODE = e.keycode + 8; // Because to xkbcommon it's +8 from libinput
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(pKeyboard->resolveBindsBySym ? pKeyboard->xkbTranslationState : m_pXKBTranslationState, KEYCODE);
const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE);
const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(pKeyboard->wlr()->xkb_state, KEYCODE);
if (handleInternalKeybinds(internalKeysym))
return true;
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
m_uTimeLastMs = e->time_msec;
m_uTimeLastMs = e.timeMs;
m_uLastCode = KEYCODE;
m_uLastMouseCode = 0;
@ -368,7 +371,7 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
}
bool suppressEvent = false;
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
if (e.state == WL_KEYBOARD_KEY_STATE_PRESSED) {
m_dPressedKeys.push_back(KEY);
@ -521,7 +524,7 @@ void CKeybindManager::onSwitchOffEvent(const std::string& switchName) {
int repeatKeyHandler(void* data) {
SKeybind** ppActiveKeybind = (SKeybind**)data;
if (!*ppActiveKeybind)
if (!*ppActiveKeybind || g_pCompositor->m_sSeat.keyboard.expired())
return 0;
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find((*ppActiveKeybind)->handler);
@ -529,7 +532,7 @@ int repeatKeyHandler(void* data) {
Debug::log(LOG, "Keybind repeat triggered, calling dispatcher.");
DISPATCHER->second((*ppActiveKeybind)->arg);
wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pInputManager->m_pActiveKeyboard->repeatRate);
wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pCompositor->m_sSeat.keyboard.lock()->repeatRate);
return 0;
}
@ -650,7 +653,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWi
m_pActiveKeybind = &k;
m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind);
const auto PACTIVEKEEB = g_pInputManager->m_pActiveKeyboard;
const auto PACTIVEKEEB = g_pCompositor->m_sSeat.keyboard.lock();
wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay);
}
@ -1440,22 +1443,20 @@ void CKeybindManager::moveCursorToCorner(std::string arg) {
switch (CORNER) {
case 0:
// bottom left
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x,
PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y);
break;
case 1:
// bottom right
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x,
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x,
PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y);
break;
case 2:
// top right
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x,
PWINDOW->m_vRealPosition.value().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y);
break;
case 3:
// top left
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y);
break;
}
}
@ -1485,7 +1486,7 @@ void CKeybindManager::moveCursor(std::string args) {
x = std::stoi(x_str);
y = std::stoi(y_str);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, x, y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, x, y);
}
void CKeybindManager::workspaceOpt(std::string args) {

View File

@ -9,6 +9,7 @@
class CInputManager;
class CConfigManager;
class CPluginSystem;
class IKeyboard;
struct SKeybind {
std::string key = "";
@ -60,7 +61,7 @@ class CKeybindManager {
CKeybindManager();
~CKeybindManager();
bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*);
bool onKeyEvent(std::any, SP<IKeyboard>);
bool onAxisEvent(wlr_pointer_axis_event*);
bool onMouseEvent(wlr_pointer_button_event*);
void resizeWithBorder(wlr_pointer_button_event*);

View File

@ -14,6 +14,12 @@
#include "../../protocols/VirtualKeyboard.hpp"
#include "../../protocols/VirtualPointer.hpp"
#include "../../devices/Mouse.hpp"
#include "../../devices/VirtualPointer.hpp"
#include "../../devices/Keyboard.hpp"
#include "../../devices/VirtualKeyboard.hpp"
#include "../../devices/TouchDevice.hpp"
CInputManager::CInputManager() {
m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) {
if (!cursorImageUnlocked())
@ -40,20 +46,20 @@ CInputManager::CInputManager() {
m_sListeners.newIdleInhibitor = PROTO::idleInhibit->events.newIdleInhibitor.registerListener([this](std::any data) { this->newIdleInhibitor(data); });
m_sListeners.newVirtualKeyboard =
PROTO::virtualKeyboard->events.newKeyboard.registerListener([this](std::any data) { this->newVirtualKeyboard(std::any_cast<SP<CVirtualKeyboard>>(data)); });
PROTO::virtualKeyboard->events.newKeyboard.registerListener([this](std::any data) { this->newVirtualKeyboard(std::any_cast<SP<CVirtualKeyboardV1Resource>>(data)); });
m_sListeners.newVirtualMouse =
PROTO::virtualPointer->events.newPointer.registerListener([this](std::any data) { this->newVirtualMouse(std::any_cast<SP<CVirtualPointer>>(data)); });
PROTO::virtualPointer->events.newPointer.registerListener([this](std::any data) { this->newVirtualMouse(std::any_cast<SP<CVirtualPointerV1Resource>>(data)); });
}
CInputManager::~CInputManager() {
m_vConstraints.clear();
m_lKeyboards.clear();
m_lMice.clear();
m_vKeyboards.clear();
m_vPointers.clear();
m_vTouches.clear();
m_lTablets.clear();
m_lTabletTools.clear();
m_lTabletPads.clear();
m_vIdleInhibitors.clear();
m_lTouchDevices.clear();
m_lSwitches.clear();
}
@ -181,7 +187,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
}
// constraints
if (g_pCompositor->m_sSeat.mouse && isConstrained()) {
if (!g_pCompositor->m_sSeat.mouse.expired() && isConstrained()) {
const auto SURF = CWLSurface::surfaceFromWlr(g_pCompositor->m_pLastFocus);
const auto CONSTRAINT = SURF->constraint();
@ -651,7 +657,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
if (*PFOLLOWMOUSE == 3) // don't refocus on full loose
break;
if ((!g_pCompositor->m_sSeat.mouse || !isConstrained()) /* No constraints */
if ((g_pCompositor->m_sSeat.mouse.expired() || !isConstrained()) /* No constraints */
&& (w && g_pCompositor->m_pLastWindow.lock() != w) /* window should change */) {
// a bit hacky
// if we only pressed one button, allow us to refocus. m_lCurrentlyHeldButtons.size() > 0 will stick the focus
@ -754,105 +760,84 @@ Vector2D CInputManager::getMouseCoordsInternal() {
}
void CInputManager::newKeyboard(wlr_input_device* keyboard) {
const auto PNEWKEYBOARD = &m_lKeyboards.emplace_back();
const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CKeyboard::create(wlr_keyboard_from_input_device(keyboard)));
PNEWKEYBOARD->keyboard = keyboard;
setupKeyboard(PNEWKEYBOARD);
Debug::log(LOG, "New keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD.get(), (uintptr_t)keyboard);
}
void CInputManager::newVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keyboard) {
const auto PNEWKEYBOARD = m_vKeyboards.emplace_back(CVirtualKeyboard::create(keyboard));
setupKeyboard(PNEWKEYBOARD);
Debug::log(LOG, "New virtual keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD.get(), (uintptr_t)keyboard->wlr());
}
void CInputManager::setupKeyboard(SP<IKeyboard> keeb) {
try {
PNEWKEYBOARD->name = getNameForNewDevice(keyboard->name);
keeb->hlName = getNameForNewDevice(keeb->wlr()->base.name);
} catch (std::exception& e) {
Debug::log(ERR, "Keyboard had no name???"); // logic error
}
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(
&wlr_keyboard_from_input_device(keyboard)->events.keymap,
[&](void* owner, void* data) {
const auto PKEYBOARD = (SKeyboard*)owner;
const auto LAYOUT = getActiveLayoutForKeyboard(PKEYBOARD);
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + LAYOUT});
EMIT_HOOK_EVENT("activeLayout", (std::vector<void*>{PKEYBOARD, (void*)&LAYOUT}));
keeb->events.destroy.registerStaticListener(
[this](void* owner, std::any data) {
auto PKEEB = ((IKeyboard*)owner)->self.lock();
destroyKeyboard(PKEEB);
Debug::log(LOG, "Destroyed keyboard {:x}", (uintptr_t)owner);
},
PNEWKEYBOARD, "Keyboard");
keeb.get());
keeb->keyboardEvents.key.registerStaticListener(
[this](void* owner, std::any data) {
auto PKEEB = ((IKeyboard*)owner)->self.lock();
onKeyboardKey(data, PKEEB);
},
keeb.get());
keeb->keyboardEvents.modifiers.registerStaticListener(
[this](void* owner, std::any data) {
auto PKEEB = ((IKeyboard*)owner)->self.lock();
onKeyboardMod(PKEEB);
},
keeb.get());
keeb->keyboardEvents.keymap.registerStaticListener(
[this](void* owner, std::any data) {
auto PKEEB = ((IKeyboard*)owner)->self.lock();
const auto LAYOUT = PKEEB->getActiveLayout();
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEEB->hlName + "," + LAYOUT});
EMIT_HOOK_EVENT("activeLayout", (std::vector<std::any>{PKEEB, LAYOUT}));
},
keeb.get());
disableAllKeyboards(false);
m_pActiveKeyboard = PNEWKEYBOARD;
g_pCompositor->m_sSeat.keyboard = keeb;
PNEWKEYBOARD->active = true;
keeb->active = true;
applyConfigToKeyboard(PNEWKEYBOARD);
applyConfigToKeyboard(keeb);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard));
Debug::log(LOG, "New keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD, (uintptr_t)keyboard);
}
void CInputManager::newVirtualKeyboard(SP<CVirtualKeyboard> keyboard) {
const auto PNEWKEYBOARD = &m_lKeyboards.emplace_back();
PNEWKEYBOARD->keyboard = &keyboard->wlr()->base;
PNEWKEYBOARD->isVirtual = true;
PNEWKEYBOARD->virtKeyboard = keyboard;
try {
PNEWKEYBOARD->name = getNameForNewDevice(keyboard->wlr()->base.name);
} catch (std::exception& e) {
Debug::log(ERR, "Keyboard had no name???"); // logic error
}
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->wlr()->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "VKeyboard");
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->wlr()->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "VKeyboard");
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->wlr()->base.events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "VKeyboard");
PNEWKEYBOARD->hyprListener_keyboardKeymap.initCallback(
&keyboard->wlr()->events.keymap,
[&](void* owner, void* data) {
const auto PKEYBOARD = (SKeyboard*)owner;
const auto LAYOUT = getActiveLayoutForKeyboard(PKEYBOARD);
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", PKEYBOARD->name + "," + LAYOUT});
EMIT_HOOK_EVENT("activeLayout", (std::vector<void*>{PKEYBOARD, (void*)&LAYOUT}));
},
PNEWKEYBOARD, "VKeyboard");
// TODO: this pointer pass sucks.
PNEWKEYBOARD->listeners.destroyVKeyboard = keyboard->events.destroy.registerListener([this, PNEWKEYBOARD](std::any data) { destroyKeyboard(PNEWKEYBOARD); });
disableAllKeyboards(true);
m_pActiveKeyboard = PNEWKEYBOARD;
PNEWKEYBOARD->active = true;
applyConfigToKeyboard(PNEWKEYBOARD);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->wlr());
Debug::log(LOG, "New virtual keyboard created, pointers Hypr: {:x} and WLR: {:x}", (uintptr_t)PNEWKEYBOARD, (uintptr_t)keyboard->wlr());
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keeb->wlr());
}
void CInputManager::setKeyboardLayout() {
for (auto& k : m_lKeyboards)
applyConfigToKeyboard(&k);
for (auto& k : m_vKeyboards)
applyConfigToKeyboard(k);
g_pKeybindManager->updateXKBTranslationState();
}
void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
auto devname = pKeyboard->name;
void CInputManager::applyConfigToKeyboard(SP<IKeyboard> pKeyboard) {
auto devname = pKeyboard->hlName;
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname);
Debug::log(LOG, "ApplyConfigToKeyboard for \"{}\", hasconfig: {}", pKeyboard->name, (int)HASCONFIG);
ASSERT(pKeyboard);
if (!wlr_keyboard_from_input_device(pKeyboard->keyboard))
return;
Debug::log(LOG, "ApplyConfigToKeyboard for \"{}\", hasconfig: {}", devname, (int)HASCONFIG);
const auto REPEATRATE = g_pConfigManager->getDeviceInt(devname, "repeat_rate", "input:repeat_rate");
const auto REPEATDELAY = g_pConfigManager->getDeviceInt(devname, "repeat_delay", "input:repeat_delay");
@ -884,7 +869,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
// we can ignore those and just apply
}
wlr_keyboard_set_repeat_info(wlr_keyboard_from_input_device(pKeyboard->keyboard), std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
wlr_keyboard_set_repeat_info(pKeyboard->wlr(), std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
pKeyboard->repeatDelay = REPEATDELAY;
pKeyboard->repeatRate = REPEATRATE;
@ -942,7 +927,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
wlr_keyboard_set_keymap(wlr_keyboard_from_input_device(pKeyboard->keyboard), KEYMAP);
wlr_keyboard_set_keymap(pKeyboard->wlr(), KEYMAP);
pKeyboard->updateXKBTranslationState();
@ -957,105 +942,87 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
}
if (wlrMods.locked != 0)
wlr_keyboard_notify_modifiers(wlr_keyboard_from_input_device(pKeyboard->keyboard), 0, 0, wlrMods.locked, 0);
wlr_keyboard_notify_modifiers(pKeyboard->wlr(), 0, 0, wlrMods.locked, 0);
xkb_keymap_unref(KEYMAP);
xkb_context_unref(CONTEXT);
const auto LAYOUTSTR = getActiveLayoutForKeyboard(pKeyboard);
const auto LAYOUTSTR = pKeyboard->getActiveLayout();
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUTSTR});
EMIT_HOOK_EVENT("activeLayout", (std::vector<void*>{pKeyboard, (void*)&LAYOUTSTR}));
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->hlName + "," + LAYOUTSTR});
EMIT_HOOK_EVENT("activeLayout", (std::vector<std::any>{pKeyboard, LAYOUTSTR}));
Debug::log(LOG, "Set the keyboard layout to {} and variant to {} for keyboard \"{}\"", pKeyboard->currentRules.layout, pKeyboard->currentRules.variant,
pKeyboard->keyboard->name);
Debug::log(LOG, "Set the keyboard layout to {} and variant to {} for keyboard \"{}\"", pKeyboard->currentRules.layout, pKeyboard->currentRules.variant, pKeyboard->hlName);
}
void CInputManager::newVirtualMouse(SP<CVirtualPointer> mouse) {
const auto PMOUSE = &m_lMice.emplace_back();
void CInputManager::newVirtualMouse(SP<CVirtualPointerV1Resource> mouse) {
const auto PMOUSE = m_vPointers.emplace_back(CVirtualPointer::create(mouse));
PMOUSE->mouse = &mouse->wlr()->base;
PMOUSE->virtualPointer = mouse;
PMOUSE->virt = true;
try {
PMOUSE->name = getNameForNewDevice(mouse->wlr()->base.name);
} catch (std::exception& e) {
Debug::log(ERR, "Mouse had no name???"); // logic error
}
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, &mouse->wlr()->base);
PMOUSE->connected = true;
setPointerConfigs();
PMOUSE->hyprListener_destroyMouse.initCallback(&mouse->wlr()->base.events.destroy, &Events::listener_destroyMouse, PMOUSE, "Mouse");
// TODO: this pointer pass sucks.
PMOUSE->listeners.destroyMouse = mouse->events.destroy.registerListener([this, PMOUSE](std::any data) { destroyMouse(PMOUSE->mouse); });
g_pCompositor->m_sSeat.mouse = PMOUSE;
m_tmrLastCursorMovement.reset();
setupMouse(PMOUSE);
Debug::log(LOG, "New virtual mouse created, pointer WLR: {:x}", (uintptr_t)mouse->wlr());
}
void CInputManager::newMouse(wlr_input_device* mouse) {
m_lMice.emplace_back();
const auto PMOUSE = &m_lMice.back();
const auto PMOUSE = m_vPointers.emplace_back(CMouse::create(wlr_pointer_from_input_device(mouse)));
PMOUSE->mouse = mouse;
setupMouse(PMOUSE);
Debug::log(LOG, "New mouse created, pointer WLR: {:x}", (uintptr_t)mouse);
}
void CInputManager::setupMouse(SP<IPointer> mauz) {
try {
PMOUSE->name = getNameForNewDevice(mouse->name);
mauz->hlName = getNameForNewDevice(mauz->wlr()->base.name);
} catch (std::exception& e) {
Debug::log(ERR, "Mouse had no name???"); // logic error
}
if (wlr_input_device_is_libinput(mouse)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse);
if (wlr_input_device_is_libinput(&mauz->wlr()->base)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&mauz->wlr()->base);
Debug::log(LOG, "New mouse has libinput sens {:.2f} ({:.2f}) with accel profile {} ({})", libinput_device_config_accel_get_speed(LIBINPUTDEV),
libinput_device_config_accel_get_default_speed(LIBINPUTDEV), (int)libinput_device_config_accel_get_profile(LIBINPUTDEV),
(int)libinput_device_config_accel_get_default_profile(LIBINPUTDEV));
}
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse);
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, &mauz->wlr()->base);
PMOUSE->connected = true;
mauz->connected = true;
setPointerConfigs();
PMOUSE->hyprListener_destroyMouse.initCallback(&mouse->events.destroy, &Events::listener_destroyMouse, PMOUSE, "Mouse");
mauz->events.destroy.registerStaticListener(
[this](void* mouse, std::any data) {
const auto PMOUSE = (IPointer*)mouse;
destroyPointer(PMOUSE->self.lock());
},
mauz.get());
g_pCompositor->m_sSeat.mouse = PMOUSE;
g_pCompositor->m_sSeat.mouse = mauz;
m_tmrLastCursorMovement.reset();
Debug::log(LOG, "New mouse created, pointer WLR: {:x}", (uintptr_t)mouse);
}
void CInputManager::setPointerConfigs() {
for (auto& m : m_lMice) {
const auto PPOINTER = &m;
auto devname = PPOINTER->name;
for (auto& m : m_vPointers) {
auto devname = m->hlName;
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname);
if (HASCONFIG) {
const auto ENABLED = g_pConfigManager->getDeviceInt(devname, "enabled");
if (ENABLED && !m.connected) {
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, m.mouse);
m.connected = true;
} else if (!ENABLED && m.connected) {
wlr_cursor_detach_input_device(g_pCompositor->m_sWLRCursor, m.mouse);
m.connected = false;
if (ENABLED && !m->connected) {
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, &m->wlr()->base);
m->connected = true;
} else if (!ENABLED && m->connected) {
wlr_cursor_detach_input_device(g_pCompositor->m_sWLRCursor, &m->wlr()->base);
m->connected = false;
}
}
if (wlr_input_device_is_libinput(m.mouse)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.mouse);
if (wlr_input_device_is_libinput(&m->wlr()->base)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&m->wlr()->base);
double touchw = 0, touchh = 0;
const auto ISTOUCHPAD = libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) &&
@ -1184,73 +1151,50 @@ void CInputManager::setPointerConfigs() {
libinput_device_config_scroll_set_button_lock(LIBINPUTDEV,
SCROLLBUTTONLOCK == 0 ? LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED : LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED);
Debug::log(LOG, "Applied config to mouse {}, sens {:.2f}", m.name, LIBINPUTSENS);
Debug::log(LOG, "Applied config to mouse {}, sens {:.2f}", m->hlName, LIBINPUTSENS);
}
}
}
void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) {
pKeyboard->hyprListener_keyboardDestroy.removeCallback();
pKeyboard->hyprListener_keyboardMod.removeCallback();
pKeyboard->hyprListener_keyboardKey.removeCallback();
xkb_state_unref(pKeyboard->xkbTranslationState);
void CInputManager::destroyKeyboard(SP<IKeyboard> pKeyboard) {
if (pKeyboard->xkbTranslationState)
xkb_state_unref(pKeyboard->xkbTranslationState);
pKeyboard->xkbTranslationState = nullptr;
m_lKeyboards.remove(*pKeyboard);
std::erase_if(m_vKeyboards, [pKeyboard](const auto& other) { return other == pKeyboard; });
if (m_lKeyboards.size() > 0) {
m_pActiveKeyboard = &m_lKeyboards.back();
m_pActiveKeyboard->active = true;
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(m_pActiveKeyboard->keyboard));
if (m_vKeyboards.size() > 0) {
g_pCompositor->m_sSeat.keyboard = m_vKeyboards.back();
g_pCompositor->m_sSeat.keyboard.lock()->active = true;
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, g_pCompositor->m_sSeat.keyboard.lock()->wlr());
} else {
m_pActiveKeyboard = nullptr;
g_pCompositor->m_sSeat.keyboard.reset();
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, nullptr);
}
}
void CInputManager::destroyMouse(wlr_input_device* mouse) {
for (auto& m : m_lMice) {
if (m.mouse == mouse) {
m_lMice.remove(m);
break;
}
}
void CInputManager::destroyPointer(SP<IPointer> mouse) {
std::erase_if(m_vPointers, [mouse](const auto& other) { return other == mouse; });
g_pCompositor->m_sSeat.mouse = m_lMice.size() > 0 ? &m_lMice.front() : nullptr;
g_pCompositor->m_sSeat.mouse = m_vPointers.size() > 0 ? m_vPointers.front() : nullptr;
if (g_pCompositor->m_sSeat.mouse)
if (!g_pCompositor->m_sSeat.mouse.expired())
unconstrainMouse();
}
void CInputManager::updateKeyboardsLeds(wlr_input_device* pKeyboard) {
auto keyboard = wlr_keyboard_from_input_device(pKeyboard);
void CInputManager::destroyTouchDevice(SP<ITouch> touch) {
Debug::log(LOG, "Touch device at {:x} removed", (uintptr_t)touch.get());
if (keyboard->xkb_state == NULL) {
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);
}
for (auto& kb : m_lKeyboards) {
if ((kb.isVirtual && shouldIgnoreVirtualKeyboard(&kb)) || kb.keyboard == pKeyboard)
continue;
wlr_keyboard_led_update(wlr_keyboard_from_input_device(kb.keyboard), leds);
}
std::erase_if(m_vTouches, [touch](const auto& other) { return other == touch; });
}
void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) {
if (!pKeyboard->enabled)
return;
const bool DISALLOWACTION = pKeyboard->isVirtual && shouldIgnoreVirtualKeyboard(pKeyboard);
const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard);
const auto EMAP = std::unordered_map<std::string, std::any>{{"keyboard", pKeyboard}, {"event", e}};
const auto EMAP = std::unordered_map<std::string, std::any>{{"keyboard", pKeyboard}, {"event", event}};
EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP);
static auto PDPMS = CConfigValue<Hyprlang::INT>("misc:key_press_enables_dpms");
@ -1259,7 +1203,9 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
g_pKeybindManager->dpms("on");
}
bool passEvent = DISALLOWACTION || g_pKeybindManager->onKeyEvent(e, pKeyboard);
bool passEvent = DISALLOWACTION || g_pKeybindManager->onKeyEvent(event, pKeyboard);
auto e = std::any_cast<IKeyboard::SKeyEvent>(event);
PROTO::idle->onActivity();
@ -1267,59 +1213,64 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
const auto IME = m_sIMERelay.m_pIME.lock();
if (IME && IME->hasGrab() && !DISALLOWACTION) {
IME->setKeyboard(wlr_keyboard_from_input_device(pKeyboard->keyboard));
IME->sendKey(e->time_msec, e->keycode, e->state);
IME->setKeyboard(pKeyboard->wlr());
IME->sendKey(e.timeMs, e.keycode, e.state);
} else {
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e->time_msec, e->keycode, e->state);
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, pKeyboard->wlr());
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e.timeMs, e.keycode, e.state);
}
updateKeyboardsLeds(pKeyboard->keyboard);
for (auto& k : m_vKeyboards) {
k->updateLEDs();
}
}
}
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
void CInputManager::onKeyboardMod(SP<IKeyboard> pKeyboard) {
if (!pKeyboard->enabled)
return;
const bool DISALLOWACTION = pKeyboard->isVirtual && shouldIgnoreVirtualKeyboard(pKeyboard);
const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard);
const auto ALLMODS = accumulateModsFromAllKBs();
const auto PWLRKB = pKeyboard->wlr();
auto MODS = wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers;
auto MODS = PWLRKB->modifiers;
MODS.depressed = ALLMODS;
const auto IME = m_sIMERelay.m_pIME.lock();
if (IME && IME->hasGrab() && !DISALLOWACTION) {
IME->setKeyboard(wlr_keyboard_from_input_device(pKeyboard->keyboard));
IME->setKeyboard(PWLRKB);
IME->sendMods(MODS.depressed, MODS.latched, MODS.locked, MODS.group);
} else {
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, PWLRKB);
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &MODS);
}
updateKeyboardsLeds(pKeyboard->keyboard);
const auto PWLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard);
for (auto& k : m_vKeyboards) {
k->updateLEDs();
}
if (PWLRKB->modifiers.group != pKeyboard->activeLayout) {
pKeyboard->activeLayout = PWLRKB->modifiers.group;
const auto LAYOUT = getActiveLayoutForKeyboard(pKeyboard);
const auto LAYOUT = pKeyboard->getActiveLayout();
pKeyboard->updateXKBTranslationState();
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUT});
EMIT_HOOK_EVENT("activeLayout", (std::vector<void*>{pKeyboard, (void*)&LAYOUT}));
g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->hlName + "," + LAYOUT});
EMIT_HOOK_EVENT("activeLayout", (std::vector<std::any>{pKeyboard, LAYOUT}));
}
}
bool CInputManager::shouldIgnoreVirtualKeyboard(SKeyboard* pKeyboard) {
if (!pKeyboard->isVirtual)
bool CInputManager::shouldIgnoreVirtualKeyboard(SP<IKeyboard> pKeyboard) {
if (!pKeyboard->isVirtual())
return false;
return !pKeyboard || (!m_sIMERelay.m_pIME.expired() && m_sIMERelay.m_pIME.lock()->grabClient() == pKeyboard->virtKeyboard.lock()->client());
CVirtualKeyboard* vk = (CVirtualKeyboard*)pKeyboard.get();
return !pKeyboard || (!m_sIMERelay.m_pIME.expired() && m_sIMERelay.m_pIME.lock()->grabClient() == vk->getClient());
}
void CInputManager::refocus() {
@ -1343,7 +1294,7 @@ void CInputManager::updateDragIcon() {
}
void CInputManager::unconstrainMouse() {
if (!g_pCompositor->m_sSeat.mouse)
if (g_pCompositor->m_sSeat.mouse.expired())
return;
for (auto& c : m_vConstraints) {
@ -1378,11 +1329,11 @@ bool CInputManager::isConstrained() {
void CInputManager::updateCapabilities() {
uint32_t caps = 0;
if (!m_lKeyboards.empty())
if (!m_vKeyboards.empty())
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
if (!m_lMice.empty())
if (!m_vPointers.empty())
caps |= WL_SEAT_CAPABILITY_POINTER;
if (!m_lTouchDevices.empty())
if (!m_vTouches.empty())
caps |= WL_SEAT_CAPABILITY_TOUCH;
if (!m_lTabletTools.empty())
caps |= WL_SEAT_CAPABILITY_POINTER;
@ -1395,54 +1346,34 @@ uint32_t CInputManager::accumulateModsFromAllKBs() {
uint32_t finalMask = 0;
for (auto& kb : m_lKeyboards) {
if (kb.isVirtual && shouldIgnoreVirtualKeyboard(&kb))
for (auto& kb : m_vKeyboards) {
if (kb->isVirtual() && shouldIgnoreVirtualKeyboard(kb))
continue;
if (!kb.enabled)
if (!kb->enabled)
continue;
finalMask |= wlr_keyboard_get_modifiers(wlr_keyboard_from_input_device(kb.keyboard));
finalMask |= wlr_keyboard_get_modifiers(kb->wlr());
}
return finalMask;
}
std::string CInputManager::getActiveLayoutForKeyboard(SKeyboard* pKeyboard) {
const auto WLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard);
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 CInputManager::disableAllKeyboards(bool virt) {
for (auto& k : m_lKeyboards) {
if (k.isVirtual != virt)
for (auto& k : m_vKeyboards) {
if (k->isVirtual() != virt)
continue;
k.active = false;
k->active = false;
}
}
void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
const auto PNEWDEV = &m_lTouchDevices.emplace_back();
PNEWDEV->pWlrDevice = pDevice;
const auto PNEWDEV = m_vTouches.emplace_back(CTouchDevice::create(wlr_touch_from_input_device(pDevice)));
try {
PNEWDEV->name = getNameForNewDevice(pDevice->name);
PNEWDEV->hlName = getNameForNewDevice(pDevice->name);
} catch (std::exception& e) {
Debug::log(ERR, "Touch Device had no name???"); // logic error
}
@ -1450,32 +1381,36 @@ void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
setTouchDeviceConfigs(PNEWDEV);
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
Debug::log(LOG, "New touch device added at {:x}", (uintptr_t)PNEWDEV);
PNEWDEV->events.destroy.registerStaticListener(
[this](void* owner, std::any data) {
auto PDEV = ((ITouch*)owner)->self.lock();
destroyTouchDevice(PDEV);
},
PNEWDEV.get());
PNEWDEV->hyprListener_destroy.initCallback(
&pDevice->events.destroy, [&](void* owner, void* data) { destroyTouchDevice((STouchDevice*)data); }, PNEWDEV, "TouchDevice");
Debug::log(LOG, "New touch device added at {:x}", (uintptr_t)PNEWDEV.get());
}
void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) {
auto setConfig = [&](STouchDevice* const PTOUCHDEV) -> void {
if (wlr_input_device_is_libinput(PTOUCHDEV->pWlrDevice)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(PTOUCHDEV->pWlrDevice);
void CInputManager::setTouchDeviceConfigs(SP<ITouch> dev) {
auto setConfig = [&](SP<ITouch> PTOUCHDEV) -> void {
if (wlr_input_device_is_libinput(&PTOUCHDEV->wlr()->base)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(&PTOUCHDEV->wlr()->base);
const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "enabled", "input:touchdevice:enabled");
const auto ENABLED = g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "enabled", "input:touchdevice:enabled");
const auto mode = ENABLED ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
if (libinput_device_config_send_events_get_mode(LIBINPUTDEV) != mode)
libinput_device_config_send_events_set_mode(LIBINPUTDEV, mode);
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->name, "transform", "input:touchdevice:transform"), 0, 7);
Debug::log(LOG, "Setting calibration matrix for device {}", PTOUCHDEV->name);
const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(PTOUCHDEV->hlName, "transform", "input:touchdevice:transform"), 0, 7);
Debug::log(LOG, "Setting calibration matrix for device {}", PTOUCHDEV->hlName);
if (libinput_device_config_calibration_has_matrix(LIBINPUTDEV))
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
auto output = g_pConfigManager->getDeviceString(PTOUCHDEV->name, "output", "input:touchdevice:output");
auto output = g_pConfigManager->getDeviceString(PTOUCHDEV->hlName, "output", "input:touchdevice:output");
bool bound = !output.empty() && output != STRVAL_EMPTY;
const bool AUTODETECT = output == "[[Auto]]";
if (!bound && AUTODETECT) {
const auto DEFAULTOUTPUT = wlr_touch_from_input_device(PTOUCHDEV->pWlrDevice)->output_name;
const auto DEFAULTOUTPUT = PTOUCHDEV->wlr()->output_name;
if (DEFAULTOUTPUT) {
output = DEFAULTOUTPUT;
bound = true;
@ -1484,10 +1419,10 @@ void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) {
PTOUCHDEV->boundOutput = bound ? output : "";
const auto PMONITOR = bound ? g_pCompositor->getMonitorFromName(output) : nullptr;
if (PMONITOR) {
Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV->name, PMONITOR->szName);
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, PTOUCHDEV->pWlrDevice, PMONITOR->output);
Debug::log(LOG, "Binding touch device {} to output {}", PTOUCHDEV->hlName, PMONITOR->szName);
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, &PTOUCHDEV->wlr()->base, PMONITOR->output);
} else if (bound)
Debug::log(ERR, "Failed to bind touch device {} to output '{}': monitor not found", PTOUCHDEV->name, output);
Debug::log(ERR, "Failed to bind touch device {} to output '{}': monitor not found", PTOUCHDEV->hlName, output);
}
};
@ -1496,10 +1431,8 @@ void CInputManager::setTouchDeviceConfigs(STouchDevice* dev) {
return;
}
for (auto& m : m_lTouchDevices) {
const auto PTOUCHDEV = &m;
setConfig(PTOUCHDEV);
for (auto& m : m_vTouches) {
setConfig(m);
}
}
@ -1546,12 +1479,6 @@ void CInputManager::setTabletConfigs() {
}
}
void CInputManager::destroyTouchDevice(STouchDevice* pDevice) {
Debug::log(LOG, "Touch device at {:x} removed", (uintptr_t)pDevice);
m_lTouchDevices.remove(*pDevice);
}
void CInputManager::newSwitch(wlr_input_device* pDevice) {
const auto PNEWDEV = &m_lSwitches.emplace_back();
PNEWDEV->pWlrDevice = pDevice;
@ -1623,16 +1550,16 @@ std::string CInputManager::getNameForNewDevice(std::string internalName) {
auto proposedNewName = deviceNameToInternalString(internalName);
int dupeno = 0;
while (std::find_if(m_lKeyboards.begin(), m_lKeyboards.end(),
[&](const SKeyboard& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_lKeyboards.end())
while (std::find_if(m_vKeyboards.begin(), m_vKeyboards.end(),
[&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vKeyboards.end())
dupeno++;
while (std::find_if(m_lMice.begin(), m_lMice.end(), [&](const SMouse& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) !=
m_lMice.end())
while (std::find_if(m_vPointers.begin(), m_vPointers.end(),
[&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vPointers.end())
dupeno++;
while (std::find_if(m_lTouchDevices.begin(), m_lTouchDevices.end(),
[&](const STouchDevice& other) { return other.name == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_lTouchDevices.end())
while (std::find_if(m_vTouches.begin(), m_vTouches.end(),
[&](const auto& other) { return other->hlName == proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno))); }) != m_vTouches.end())
dupeno++;
while (std::find_if(m_lTabletPads.begin(), m_lTabletPads.end(),

View File

@ -11,8 +11,11 @@
class CPointerConstraint;
class CWindow;
class CIdleInhibitor;
class CVirtualKeyboard;
class CVirtualPointer;
class CVirtualKeyboardV1Resource;
class CVirtualPointerV1Resource;
class IPointer;
class IKeyboard;
class ITouch;
enum eClickBehaviorMode {
CLICKMODE_DEFAULT = 0,
@ -75,23 +78,22 @@ class CInputManager {
void onMouseWarp(wlr_pointer_motion_absolute_event*);
void onMouseButton(wlr_pointer_button_event*);
void onMouseWheel(wlr_pointer_axis_event*);
void onKeyboardKey(wlr_keyboard_key_event*, SKeyboard*);
void onKeyboardMod(void*, SKeyboard*);
void onKeyboardKey(std::any, SP<IKeyboard>);
void onKeyboardMod(SP<IKeyboard>);
void newKeyboard(wlr_input_device*);
void newVirtualKeyboard(SP<CVirtualKeyboard>);
void newVirtualKeyboard(SP<CVirtualKeyboardV1Resource>);
void newMouse(wlr_input_device*);
void newVirtualMouse(SP<CVirtualPointer>);
void newVirtualMouse(SP<CVirtualPointerV1Resource>);
void newTouchDevice(wlr_input_device*);
void newSwitch(wlr_input_device*);
void destroyTouchDevice(STouchDevice*);
void destroyKeyboard(SKeyboard*);
void destroyMouse(wlr_input_device*);
void destroyTouchDevice(SP<ITouch>);
void destroyKeyboard(SP<IKeyboard>);
void destroyPointer(SP<IPointer>);
void destroySwitch(SSwitchDevice*);
void unconstrainMouse();
bool isConstrained();
std::string getActiveLayoutForKeyboard(SKeyboard*);
Vector2D getMouseCoordsInternal();
void refocus();
@ -100,7 +102,7 @@ class CInputManager {
void setKeyboardLayout();
void setPointerConfigs();
void setTouchDeviceConfigs(STouchDevice* dev = nullptr);
void setTouchDeviceConfigs(SP<ITouch> dev = nullptr);
void setTabletConfigs();
void updateDragIcon();
@ -122,21 +124,19 @@ class CInputManager {
bool m_bWasDraggingWindow = false;
// for refocus to be forced
PHLWINDOWREF m_pForcedFocus;
PHLWINDOWREF m_pForcedFocus;
SDrag m_sDrag;
SDrag m_sDrag;
std::list<SKeyboard> m_lKeyboards;
std::list<SMouse> m_lMice;
std::vector<SP<IKeyboard>> m_vKeyboards;
std::vector<SP<IPointer>> m_vPointers;
std::vector<SP<ITouch>> m_vTouches;
// tablets
std::list<STablet> m_lTablets;
std::list<STabletTool> m_lTabletTools;
std::list<STabletPad> m_lTabletPads;
// Touch devices
std::list<STouchDevice> m_lTouchDevices;
// Switches
std::list<SSwitchDevice> m_lSwitches;
@ -159,19 +159,15 @@ class CInputManager {
SSwipeGesture m_sActiveSwipe;
SKeyboard* m_pActiveKeyboard = nullptr;
CTimer m_tmrLastCursorMovement;
CInputMethodRelay m_sIMERelay;
void updateKeyboardsLeds(wlr_input_device* pKeyboard);
// for shared mods
uint32_t accumulateModsFromAllKBs();
// for virtual keyboards: whether we should respect them as normal ones
bool shouldIgnoreVirtualKeyboard(SKeyboard*);
bool shouldIgnoreVirtualKeyboard(SP<IKeyboard>);
// for special cursors that we choose
void setCursorImageUntilUnset(std::string);
@ -213,6 +209,9 @@ class CInputManager {
eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT;
Vector2D m_vLastCursorPosFloored = Vector2D();
void setupKeyboard(SP<IKeyboard> keeb);
void setupMouse(SP<IPointer> mauz);
void processMouseDownNormal(wlr_pointer_button_event* e);
void processMouseDownKill(wlr_pointer_button_event* e);
@ -226,7 +225,7 @@ class CInputManager {
STabletTool* ensureTabletToolPresent(wlr_tablet_tool*);
void applyConfigToKeyboard(SKeyboard*);
void applyConfigToKeyboard(SP<IKeyboard>);
// this will be set after a refocus()
wlr_surface* m_pFoundSurfaceToFocus = nullptr;

View File

@ -2,6 +2,7 @@
#include "../../Compositor.hpp"
#include "../../config/ConfigValue.hpp"
#include "../../protocols/IdleNotify.hpp"
#include "../../devices/ITouch.hpp"
void CInputManager::onTouchDown(wlr_touch_down_event* e) {
static auto PSWIPETOUCH = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_touch");
@ -15,10 +16,10 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
auto PMONITOR = g_pCompositor->getMonitorFromName(e->touch->output_name ? e->touch->output_name : "");
const auto PDEVIT = std::find_if(m_lTouchDevices.begin(), m_lTouchDevices.end(), [&](const STouchDevice& other) { return other.pWlrDevice == &e->touch->base; });
const auto PDEVIT = std::find_if(m_vTouches.begin(), m_vTouches.end(), [&](const auto& other) { return other->wlr() == e->touch; });
if (PDEVIT != m_lTouchDevices.end() && !PDEVIT->boundOutput.empty())
PMONITOR = g_pCompositor->getMonitorFromName(PDEVIT->boundOutput);
if (PDEVIT != m_vTouches.end() && !(*PDEVIT)->boundOutput.empty())
PMONITOR = g_pCompositor->getMonitorFromName((*PDEVIT)->boundOutput);
PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor;

View File

@ -7,7 +7,7 @@ static const struct wlr_keyboard_impl virtualKeyboardImpl = {
.name = "virtual-keyboard",
};
CVirtualKeyboard::CVirtualKeyboard(SP<CZwpVirtualKeyboardV1> resource_) : resource(resource_) {
CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> resource_) : resource(resource_) {
if (!good())
return;
@ -84,20 +84,20 @@ CVirtualKeyboard::CVirtualKeyboard(SP<CZwpVirtualKeyboardV1> resource_) : resour
wlr_keyboard_init(&keyboard, &virtualKeyboardImpl, "CVirtualKeyboard");
}
CVirtualKeyboard::~CVirtualKeyboard() {
CVirtualKeyboardV1Resource::~CVirtualKeyboardV1Resource() {
wlr_keyboard_finish(&keyboard);
events.destroy.emit();
}
bool CVirtualKeyboard::good() {
bool CVirtualKeyboardV1Resource::good() {
return resource->resource();
}
wlr_keyboard* CVirtualKeyboard::wlr() {
wlr_keyboard* CVirtualKeyboardV1Resource::wlr() {
return &keyboard;
}
wl_client* CVirtualKeyboard::client() {
wl_client* CVirtualKeyboardV1Resource::client() {
return resource->client();
}
@ -116,13 +116,13 @@ void CVirtualKeyboardProtocol::onManagerResourceDestroy(wl_resource* res) {
std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; });
}
void CVirtualKeyboardProtocol::destroyResource(CVirtualKeyboard* keeb) {
void CVirtualKeyboardProtocol::destroyResource(CVirtualKeyboardV1Resource* keeb) {
std::erase_if(m_vKeyboards, [&](const auto& other) { return other.get() == keeb; });
}
void CVirtualKeyboardProtocol::onCreateKeeb(CZwpVirtualKeyboardManagerV1* pMgr, wl_resource* seat, uint32_t id) {
const auto RESOURCE = m_vKeyboards.emplace_back(std::make_shared<CVirtualKeyboard>(std::make_shared<CZwpVirtualKeyboardV1>(pMgr->client(), pMgr->version(), id)));
const auto RESOURCE = m_vKeyboards.emplace_back(std::make_shared<CVirtualKeyboardV1Resource>(std::make_shared<CZwpVirtualKeyboardV1>(pMgr->client(), pMgr->version(), id)));
if (!RESOURCE->good()) {
pMgr->noMemory();

View File

@ -7,10 +7,10 @@
#include "virtual-keyboard-unstable-v1.hpp"
#include "../helpers/signal/Signal.hpp"
class CVirtualKeyboard {
class CVirtualKeyboardV1Resource {
public:
CVirtualKeyboard(SP<CZwpVirtualKeyboardV1> resource_);
~CVirtualKeyboard();
CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1> resource_);
~CVirtualKeyboardV1Resource();
struct {
CSignal destroy;
@ -39,14 +39,14 @@ class CVirtualKeyboardProtocol : public IWaylandProtocol {
private:
void onManagerResourceDestroy(wl_resource* res);
void destroyResource(CVirtualKeyboard* keeb);
void destroyResource(CVirtualKeyboardV1Resource* keeb);
void onCreateKeeb(CZwpVirtualKeyboardManagerV1* pMgr, wl_resource* seat, uint32_t id);
//
std::vector<UP<CZwpVirtualKeyboardManagerV1>> m_vManagers;
std::vector<SP<CVirtualKeyboard>> m_vKeyboards;
std::vector<SP<CVirtualKeyboardV1Resource>> m_vKeyboards;
friend class CVirtualKeyboard;
friend class CVirtualKeyboardV1Resource;
};
namespace PROTO {

View File

@ -6,7 +6,7 @@ static const wlr_pointer_impl pointerImpl = {
.name = "virtual-pointer-v1",
};
CVirtualPointer::CVirtualPointer(SP<CZwlrVirtualPointerV1> resource_) : resource(resource_) {
CVirtualPointerV1Resource::CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> resource_) : resource(resource_) {
if (!good())
return;
@ -19,7 +19,7 @@ CVirtualPointer::CVirtualPointer(SP<CZwlrVirtualPointerV1> resource_) : resource
PROTO::virtualPointer->destroyResource(this);
});
wlr_pointer_init(&pointer, &pointerImpl, "CVirtualPointer");
wlr_pointer_init(&pointer, &pointerImpl, "CVirtualPointerV1Resource");
resource->setMotion([this](CZwlrVirtualPointerV1* r, uint32_t timeMs, wl_fixed_t dx, wl_fixed_t dy) {
wlr_pointer_motion_event event = {
@ -108,20 +108,20 @@ CVirtualPointer::CVirtualPointer(SP<CZwlrVirtualPointerV1> resource_) : resource
});
}
CVirtualPointer::~CVirtualPointer() {
CVirtualPointerV1Resource::~CVirtualPointerV1Resource() {
wlr_pointer_finish(&pointer);
events.destroy.emit();
}
bool CVirtualPointer::good() {
bool CVirtualPointerV1Resource::good() {
return resource->resource();
}
wlr_pointer* CVirtualPointer::wlr() {
wlr_pointer* CVirtualPointerV1Resource::wlr() {
return &pointer;
}
wl_client* CVirtualPointer::client() {
wl_client* CVirtualPointerV1Resource::client() {
return resource->client();
}
@ -145,13 +145,13 @@ void CVirtualPointerProtocol::onManagerResourceDestroy(wl_resource* res) {
std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; });
}
void CVirtualPointerProtocol::destroyResource(CVirtualPointer* pointer) {
void CVirtualPointerProtocol::destroyResource(CVirtualPointerV1Resource* pointer) {
std::erase_if(m_vPointers, [&](const auto& other) { return other.get() == pointer; });
}
void CVirtualPointerProtocol::onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id) {
const auto RESOURCE = m_vPointers.emplace_back(std::make_shared<CVirtualPointer>(std::make_shared<CZwlrVirtualPointerV1>(pMgr->client(), pMgr->version(), id)));
const auto RESOURCE = m_vPointers.emplace_back(std::make_shared<CVirtualPointerV1Resource>(std::make_shared<CZwlrVirtualPointerV1>(pMgr->client(), pMgr->version(), id)));
if (!RESOURCE->good()) {
pMgr->noMemory();

View File

@ -8,10 +8,10 @@
#include "wlr-virtual-pointer-unstable-v1.hpp"
#include "../helpers/signal/Signal.hpp"
class CVirtualPointer {
class CVirtualPointerV1Resource {
public:
CVirtualPointer(SP<CZwlrVirtualPointerV1> resource_);
~CVirtualPointer();
CVirtualPointerV1Resource(SP<CZwlrVirtualPointerV1> resource_);
~CVirtualPointerV1Resource();
struct {
CSignal destroy;
@ -37,19 +37,19 @@ class CVirtualPointerProtocol : public IWaylandProtocol {
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
struct {
CSignal newPointer; // SP<CVirtualPointer>
CSignal newPointer; // SP<CVirtualPointerV1Resource>
} events;
private:
void onManagerResourceDestroy(wl_resource* res);
void destroyResource(CVirtualPointer* pointer);
void destroyResource(CVirtualPointerV1Resource* pointer);
void onCreatePointer(CZwlrVirtualPointerManagerV1* pMgr, wl_resource* seat, uint32_t id);
//
std::vector<UP<CZwlrVirtualPointerManagerV1>> m_vManagers;
std::vector<SP<CVirtualPointer>> m_vPointers;
std::vector<SP<CVirtualPointerV1Resource>> m_vPointers;
friend class CVirtualPointer;
friend class CVirtualPointerV1Resource;
};
namespace PROTO {