Skip to content

Commit 52ba39f

Browse files
committed
Added mouse wheel support on Linux
1 parent 14eecf1 commit 52ba39f

File tree

10 files changed

+46
-31
lines changed

10 files changed

+46
-31
lines changed

src/config/ParseKeySequence.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ void ParseKeySequence::add_timeout_event(uint16_t timeout, bool is_not, bool can
174174
if (!m_sequence.empty() &&
175175
m_sequence.back().key == Key::timeout &&
176176
m_sequence.back().state == state)
177-
m_sequence.back().timeout = sum_timeouts(m_sequence.back().timeout, timeout);
177+
m_sequence.back().value = sum_timeouts(m_sequence.back().value, timeout);
178178
else
179179
m_sequence.emplace_back(Key::timeout, state, timeout);
180180
}

src/runtime/KeyEvent.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,23 @@ enum class KeyState : uint16_t {
2828
};
2929

3030
struct KeyEvent {
31-
static const int timeout_bits = 12;
31+
static const int value_bits = 12;
3232

3333
Key key;
3434
KeyState state : 4;
35-
uint16_t timeout : timeout_bits;
35+
uint16_t value : value_bits;
3636

3737
KeyEvent()
38-
: key(), state(), timeout() {
38+
: key(), state(), value() {
3939
}
4040
KeyEvent(Key key, KeyState state)
41-
: key(key), state(state), timeout() {
41+
: key(key), state(state), value() {
4242
}
43-
KeyEvent(Key key, KeyState state, uint16_t timeout)
44-
: key(key), state(state), timeout(timeout) {
43+
KeyEvent(Key key, KeyState state, uint16_t value)
44+
: key(key), state(state), value(value) {
4545
}
4646
bool operator==(const KeyEvent& b) const {
47-
return (key == b.key && state == b.state && timeout == b.timeout);
47+
return (key == b.key && state == b.state && value == b.value);
4848
}
4949
bool operator!=(const KeyEvent& b) const {
5050
return !(*this == b);

src/runtime/MatchKeySequence.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace {
2525

2626
// not commutative, first parameter needs to be input sequence
2727
bool timeout_unifiable(const KeyEvent& se, const KeyEvent& ee) {
28-
const auto time_reached = (se.timeout >= ee.timeout);
28+
const auto time_reached = (se.value >= ee.value);
2929
const auto is_not = (is_not_timeout(se.state) || is_not_timeout(ee.state));
3030
return (is_not ? !time_reached : time_reached);
3131
}

src/runtime/Stage.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ namespace {
5353

5454
bool has_mouse_mappings(const KeySequence& sequence) {
5555
return std::any_of(begin(sequence), end(sequence),
56-
[](const KeyEvent& event) { return is_mouse_button(event.key); });
56+
[](const KeyEvent& event) {
57+
return is_mouse_button(event.key) || is_mouse_wheel(event.key);
58+
});
5759
}
5860

5961
bool has_mouse_mappings(const std::vector<Stage::Context>& contexts) {
@@ -392,7 +394,7 @@ void Stage::apply_input(const KeyEvent event, int device_index) {
392394
// suppress short timeout after not-timeout was exceeded
393395
if (m_current_timeout && is_not_timeout(m_current_timeout->state)) {
394396
if (event.key == Key::timeout) {
395-
if (m_current_timeout->timeout == event.timeout) {
397+
if (m_current_timeout->value == event.value) {
396398
m_current_timeout->not_exceeded = true;
397399
}
398400
else if (m_current_timeout->not_exceeded) {

src/runtime/Timeout.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ template<typename R, typename P>
1010
uint16_t duration_to_timeout(const std::chrono::duration<R, P>& duration) {
1111
const auto milliseconds =
1212
std::chrono::duration_cast<std::chrono::milliseconds>(duration);
13-
const auto max = (1 << KeyEvent::timeout_bits) - 1;
13+
const auto max = (1 << KeyEvent::value_bits) - 1;
1414
return static_cast<uint16_t>(std::clamp(
1515
static_cast<int>(milliseconds.count()),
1616
0, max));
@@ -26,7 +26,7 @@ KeyEvent make_input_timeout_event(const std::chrono::duration<R, P>& duration) {
2626
}
2727

2828
inline uint16_t sum_timeouts(uint16_t a, uint16_t b) {
29-
const auto max = (1 << KeyEvent::timeout_bits) - 1;
29+
const auto max = (1 << KeyEvent::value_bits) - 1;
3030
return static_cast<uint16_t>(std::min(
3131
static_cast<int>(a) + static_cast<int>(b), max));
3232
}

src/server/ServerState.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ bool ServerState::translate_input(KeyEvent input, int device_index) {
203203

204204
// automatically insert mouse wheel Down before Up
205205
if (is_mouse_wheel(input.key) && input.state == KeyState::Up)
206-
translate_input({ input.key, KeyState::Down }, device_index);
206+
translate_input({ input.key, KeyState::Down, input.value }, device_index);
207207

208208
if (input.key != Key::timeout)
209209
m_last_key_event = input;
@@ -221,7 +221,7 @@ bool ServerState::translate_input(KeyEvent input, int device_index) {
221221
if (!output.empty() && output.back().key == Key::timeout) {
222222
const auto& request = output.back();
223223
schedule_timeout(
224-
timeout_to_milliseconds(request.timeout),
224+
timeout_to_milliseconds(request.value),
225225
cancel_timeout_on_up(request.state));
226226
output.pop_back();
227227
}
@@ -283,7 +283,7 @@ bool ServerState::flush_send_buffer() {
283283
}
284284

285285
if (event.key == Key::timeout) {
286-
schedule_flush(timeout_to_milliseconds(event.timeout));
286+
schedule_flush(timeout_to_milliseconds(event.value));
287287
++i;
288288
break;
289289
}

src/server/unix/GrabbedDevicesLinux.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -410,11 +410,18 @@ const std::vector<DeviceDesc>& GrabbedDevices::grabbed_device_descs() const {
410410
}
411411

412412
std::optional<KeyEvent> to_key_event(const GrabbedDevices::Event& event) {
413-
if (event.type != EV_KEY)
414-
return { };
415-
416-
return KeyEvent{
417-
static_cast<Key>(event.code),
418-
(event.value == 0 ? KeyState::Up : KeyState::Down),
419-
};
413+
if (event.type == EV_KEY)
414+
return KeyEvent{
415+
static_cast<Key>(event.code),
416+
(event.value == 0 ? KeyState::Up : KeyState::Down),
417+
};
418+
419+
if (event.type == EV_REL && event.code == REL_WHEEL_HI_RES)
420+
return KeyEvent{
421+
(event.value < 0 ? Key::WheelDown : Key::WheelUp),
422+
KeyState::Up,
423+
static_cast<uint16_t>(event.value)
424+
};
425+
426+
return { };
420427
}

src/server/unix/VirtualDeviceLinux.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,8 @@ namespace {
5151
::ioctl(fd, UI_SET_RELBIT, REL_X);
5252
::ioctl(fd, UI_SET_RELBIT, REL_Y);
5353
::ioctl(fd, UI_SET_RELBIT, REL_Z);
54-
::ioctl(fd, UI_SET_RELBIT, REL_WHEEL);
55-
::ioctl(fd, UI_SET_RELBIT, REL_HWHEEL);
56-
#if defined(REL_WHEEL_HI_RES)
5754
::ioctl(fd, UI_SET_RELBIT, REL_WHEEL_HI_RES);
5855
::ioctl(fd, UI_SET_RELBIT, REL_HWHEEL_HI_RES);
59-
#endif
6056

6157
// add absolute axes which are commonly found on keyboards
6258
::ioctl(fd, UI_SET_EVBIT, EV_ABS);
@@ -142,8 +138,18 @@ class VirtualDeviceImpl {
142138
}
143139

144140
bool send_key_event(const KeyEvent& event) {
145-
return send_event(EV_KEY, *event.key, get_key_event_value(event)) &&
146-
send_event(EV_SYN, SYN_REPORT, 0);
141+
if (is_mouse_wheel(event.key)) {
142+
const auto value = (event.value ?
143+
static_cast<int16_t>(event.value) :
144+
event.key == Key::WheelDown ? -120 : 120);
145+
if (!send_event(EV_REL, REL_WHEEL_HI_RES, value))
146+
return false;
147+
}
148+
else {
149+
if (!send_event(EV_KEY, *event.key, get_key_event_value(event)))
150+
return false;
151+
}
152+
return send_event(EV_SYN, SYN_REPORT, 0);
147153
}
148154
};
149155

src/server/verbose_debug_io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ void verbose_debug_io(const KeyEvent& input,
1313
const auto format = [](const KeyEvent& e) {
1414
if (e.key == Key::timeout)
1515
return (e.state == KeyState::Not ? "!" : "") +
16-
std::to_string(timeout_to_milliseconds(e.timeout).count()) + "ms";
16+
std::to_string(timeout_to_milliseconds(e.value).count()) + "ms";
1717

1818
const auto key_name = [](Key key) {
1919
if (const auto name = get_key_name(key))

src/test/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ std::ostream& operator<<(std::ostream& os, const KeyEvent& event) {
5454
os << "Action" << (*event.key - *Key::first_action);
5555
}
5656
else if (event.key == Key::timeout) {
57-
os << timeout_to_milliseconds(event.timeout).count() << "ms";
57+
os << timeout_to_milliseconds(event.value).count() << "ms";
5858
}
5959
else if (auto name = get_key_name(event.key)) {
6060
os << name;

0 commit comments

Comments
 (0)