mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:17:44 +00:00
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:
parent
33e6cb8b80
commit
423807d772
2 changed files with 41 additions and 25 deletions
|
@ -20,6 +20,7 @@
|
||||||
#include <WindowServer/WSClientConnection.h>
|
#include <WindowServer/WSClientConnection.h>
|
||||||
#include <WindowServer/WSCursor.h>
|
#include <WindowServer/WSCursor.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.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;
|
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) {
|
switch (button) {
|
||||||
case MouseButton::Left:
|
case MouseButton::Left:
|
||||||
return m_left_click_clock;
|
return m_left;
|
||||||
case MouseButton::Right:
|
case MouseButton::Right:
|
||||||
return m_right_click_clock;
|
return m_right;
|
||||||
case MouseButton::Middle:
|
case MouseButton::Middle:
|
||||||
return m_middle_click_clock;
|
return m_middle;
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -629,31 +630,38 @@ void WSWindowManager::process_event_for_doubleclick(WSWindow& window, WSMouseEve
|
||||||
m_double_click_info.reset();
|
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
|
// if the clock is invalid, we haven't clicked with this button on this
|
||||||
// window yet, so there's nothing to do.
|
// window yet, so there's nothing to do.
|
||||||
if (!clock.is_valid()) {
|
if (!metadata.clock.is_valid()) {
|
||||||
clock.start();
|
metadata.clock.start();
|
||||||
} else {
|
} else {
|
||||||
int elapsed_since_last_click = clock.elapsed();
|
int elapsed_since_last_click = metadata.clock.elapsed();
|
||||||
clock.start();
|
metadata.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.
|
|
||||||
if (elapsed_since_last_click < m_double_click_speed) {
|
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)
|
#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
|
#endif
|
||||||
event = WSMouseEvent(WSEvent::MouseDoubleClick, event.position(), event.buttons(), event.button(), event.modifiers(), event.wheel_delta());
|
event = WSMouseEvent(WSEvent::MouseDoubleClick, event.position(), event.buttons(), event.button(), event.modifiers(), event.wheel_delta());
|
||||||
// invalidate this now we've delivered a doubleclick, otherwise
|
// invalidate this now we've delivered a doubleclick, otherwise
|
||||||
// tripleclick will deliver two doubleclick events (incorrectly).
|
// tripleclick will deliver two doubleclick events (incorrectly).
|
||||||
clock = CElapsedTimer();
|
metadata.clock = {};
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// too slow; try again
|
// too slow; try again
|
||||||
clock.start();
|
metadata.clock.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metadata.last_position = event.position();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindowManager::deliver_mouse_event(WSWindow& window, WSMouseEvent& event)
|
void WSWindowManager::deliver_mouse_event(WSWindow& window, WSMouseEvent& event)
|
||||||
|
|
|
@ -205,18 +205,26 @@ private:
|
||||||
InlineLinkedList<WSWindow> m_windows_in_order;
|
InlineLinkedList<WSWindow> m_windows_in_order;
|
||||||
|
|
||||||
struct DoubleClickInfo {
|
struct DoubleClickInfo {
|
||||||
CElapsedTimer& click_clock(MouseButton);
|
struct ClickMetadata {
|
||||||
|
CElapsedTimer clock;
|
||||||
|
Point last_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
ClickMetadata& metadata_for_button(MouseButton);
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
m_left_click_clock = CElapsedTimer();
|
m_left = {};
|
||||||
m_right_click_clock = CElapsedTimer();
|
m_right = {};
|
||||||
m_middle_click_clock = CElapsedTimer();
|
m_middle = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
WeakPtr<WSWindow> m_clicked_window;
|
WeakPtr<WSWindow> m_clicked_window;
|
||||||
CElapsedTimer m_left_click_clock;
|
|
||||||
CElapsedTimer m_right_click_clock;
|
private:
|
||||||
CElapsedTimer m_middle_click_clock;
|
ClickMetadata m_left;
|
||||||
|
ClickMetadata m_right;
|
||||||
|
ClickMetadata m_middle;
|
||||||
};
|
};
|
||||||
DoubleClickInfo m_double_click_info;
|
DoubleClickInfo m_double_click_info;
|
||||||
int m_double_click_speed { 0 };
|
int m_double_click_speed { 0 };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue