input: Introduce basic hyprland HID classes
Implements an intermediary HID class for mice, keyboards and touch devices, removing the old structs from WLClasses.hpp Yes, virtual ones are duplicated a bit, but will likely be de-duped once wlr_input_device is not used anymore.
This commit is contained in:
parent
1d2acbe193
commit
1237732b97
39 changed files with 1450 additions and 573 deletions
26
src/devices/IHID.hpp
Normal file
26
src/devices/IHID.hpp
Normal 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
134
src/devices/IKeyboard.cpp
Normal 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
61
src/devices/IKeyboard.hpp
Normal 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
5
src/devices/IPointer.cpp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#include "IPointer.hpp"
|
||||
|
||||
uint32_t IPointer::getCapabilities() {
|
||||
return HID_INPUT_CAPABILITY_POINTER;
|
||||
}
|
||||
110
src/devices/IPointer.hpp
Normal file
110
src/devices/IPointer.hpp
Normal 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
5
src/devices/ITouch.cpp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#include "ITouch.hpp"
|
||||
|
||||
uint32_t ITouch::getCapabilities() {
|
||||
return HID_INPUT_CAPABILITY_TOUCH;
|
||||
}
|
||||
50
src/devices/ITouch.hpp
Normal file
50
src/devices/ITouch.hpp
Normal 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
64
src/devices/Keyboard.cpp
Normal 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
24
src/devices/Keyboard.hpp
Normal 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
169
src/devices/Mouse.cpp
Normal 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
36
src/devices/Mouse.hpp
Normal 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);
|
||||
};
|
||||
85
src/devices/TouchDevice.cpp
Normal file
85
src/devices/TouchDevice.cpp
Normal 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();
|
||||
}
|
||||
25
src/devices/TouchDevice.hpp
Normal file
25
src/devices/TouchDevice.hpp
Normal 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);
|
||||
};
|
||||
71
src/devices/VirtualKeyboard.cpp
Normal file
71
src/devices/VirtualKeyboard.cpp
Normal 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();
|
||||
}
|
||||
28
src/devices/VirtualKeyboard.hpp
Normal file
28
src/devices/VirtualKeyboard.hpp
Normal 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);
|
||||
};
|
||||
170
src/devices/VirtualPointer.cpp
Normal file
170
src/devices/VirtualPointer.cpp
Normal 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();
|
||||
}
|
||||
38
src/devices/VirtualPointer.hpp
Normal file
38
src/devices/VirtualPointer.hpp
Normal 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);
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue