WindowServer: Don't transform quick far-apart clicks into double-clicks

We now require that the two clicks that make up a double-click be no
more than 4px apart.

This fixes the annoying behavior where you'd often get incorrect
double-click events on GUI widgets.
This commit is contained in:
Andreas Kling 2019-09-08 10:15:08 +02:00
parent 33e6cb8b80
commit 423807d772
Notes: sideshowbarker 2024-07-19 12:13:03 +09:00
2 changed files with 41 additions and 25 deletions

View File

@ -20,6 +20,7 @@
#include <WindowServer/WSClientConnection.h>
#include <WindowServer/WSCursor.h>
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
@ -598,15 +599,15 @@ void WSWindowManager::set_cursor_tracking_button(WSButton* button)
m_cursor_tracking_button = button ? button->make_weak_ptr() : nullptr;
}
CElapsedTimer& WSWindowManager::DoubleClickInfo::click_clock(MouseButton button)
auto WSWindowManager::DoubleClickInfo::metadata_for_button(MouseButton button) -> ClickMetadata&
{
switch (button) {
case MouseButton::Left:
return m_left_click_clock;
return m_left;
case MouseButton::Right:
return m_right_click_clock;
return m_right;
case MouseButton::Middle:
return m_middle_click_clock;
return m_middle;
default:
ASSERT_NOT_REACHED();
}
@ -629,31 +630,38 @@ void WSWindowManager::process_event_for_doubleclick(WSWindow& window, WSMouseEve
m_double_click_info.reset();
}
auto& clock = m_double_click_info.click_clock(event.button());
auto& metadata = m_double_click_info.metadata_for_button(event.button());
// if the clock is invalid, we haven't clicked with this button on this
// window yet, so there's nothing to do.
if (!clock.is_valid()) {
clock.start();
if (!metadata.clock.is_valid()) {
metadata.clock.start();
} else {
int elapsed_since_last_click = clock.elapsed();
clock.start();
// FIXME: It might be a sensible idea to also add a distance travel check.
// If the pointer moves too far, it's not a double click.
int elapsed_since_last_click = metadata.clock.elapsed();
metadata.clock.start();
if (elapsed_since_last_click < m_double_click_speed) {
auto diff = event.position() - metadata.last_position;
auto distance_travelled = (int)sqrt(diff.x() * diff.x() + diff.y() * diff.y());
if (distance_travelled > 4) {
// too far; try again
metadata.clock.start();
} else {
#if defined(DOUBLECLICK_DEBUG)
dbg() << "Transforming MouseUp to MouseDoubleClick (" << elapsed_since_last_click << " < " << m_double_click_speed << ")!";
dbg() << "Transforming MouseUp to MouseDoubleClick (" << elapsed_since_last_click << " < " << m_double_click_speed << ")!";
#endif
event = WSMouseEvent(WSEvent::MouseDoubleClick, event.position(), event.buttons(), event.button(), event.modifiers(), event.wheel_delta());
// invalidate this now we've delivered a doubleclick, otherwise
// tripleclick will deliver two doubleclick events (incorrectly).
clock = CElapsedTimer();
event = WSMouseEvent(WSEvent::MouseDoubleClick, event.position(), event.buttons(), event.button(), event.modifiers(), event.wheel_delta());
// invalidate this now we've delivered a doubleclick, otherwise
// tripleclick will deliver two doubleclick events (incorrectly).
metadata.clock = {};
}
} else {
// too slow; try again
clock.start();
metadata.clock.start();
}
}
metadata.last_position = event.position();
}
void WSWindowManager::deliver_mouse_event(WSWindow& window, WSMouseEvent& event)

View File

@ -205,18 +205,26 @@ private:
InlineLinkedList<WSWindow> m_windows_in_order;
struct DoubleClickInfo {
CElapsedTimer& click_clock(MouseButton);
struct ClickMetadata {
CElapsedTimer clock;
Point last_position;
};
ClickMetadata& metadata_for_button(MouseButton);
void reset()
{
m_left_click_clock = CElapsedTimer();
m_right_click_clock = CElapsedTimer();
m_middle_click_clock = CElapsedTimer();
m_left = {};
m_right = {};
m_middle = {};
}
WeakPtr<WSWindow> m_clicked_window;
CElapsedTimer m_left_click_clock;
CElapsedTimer m_right_click_clock;
CElapsedTimer m_middle_click_clock;
private:
ClickMetadata m_left;
ClickMetadata m_right;
ClickMetadata m_middle;
};
DoubleClickInfo m_double_click_info;
int m_double_click_speed { 0 };