Commit 6b13ba3b authored by flackr@chromium.org's avatar flackr@chromium.org

Require a mouse button release event before counting a press event as a new click.

BUG=389162
TEST=EventTest.DoubleClickRequiresRelease

Review URL: https://codereview.chromium.org/398393003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284479 0039d316-1c4b-4281-b951-d872f2087c98
parent 5afb544a
...@@ -327,23 +327,46 @@ bool MouseEvent::IsRepeatedClickEvent( ...@@ -327,23 +327,46 @@ bool MouseEvent::IsRepeatedClickEvent(
int MouseEvent::GetRepeatCount(const MouseEvent& event) { int MouseEvent::GetRepeatCount(const MouseEvent& event) {
int click_count = 1; int click_count = 1;
if (last_click_event_) { if (last_click_event_) {
if (event.type() == ui::ET_MOUSE_RELEASED) if (event.type() == ui::ET_MOUSE_RELEASED) {
return last_click_event_->GetClickCount(); if (event.changed_button_flags() ==
if (IsX11SendEventTrue(event.native_event())) last_click_event_->changed_button_flags()) {
last_click_complete_ = true;
return last_click_event_->GetClickCount();
} else {
// If last_click_event_ has changed since this button was pressed
// return a click count of 1.
return click_count;
}
}
if (event.time_stamp() != last_click_event_->time_stamp())
last_click_complete_ = true;
if (!last_click_complete_ ||
IsX11SendEventTrue(event.native_event())) {
click_count = last_click_event_->GetClickCount(); click_count = last_click_event_->GetClickCount();
else if (IsRepeatedClickEvent(*last_click_event_, event)) } else if (IsRepeatedClickEvent(*last_click_event_, event)) {
click_count = last_click_event_->GetClickCount() + 1; click_count = last_click_event_->GetClickCount() + 1;
}
delete last_click_event_; delete last_click_event_;
} }
last_click_event_ = new MouseEvent(event); last_click_event_ = new MouseEvent(event);
last_click_complete_ = false;
if (click_count > 3) if (click_count > 3)
click_count = 3; click_count = 3;
last_click_event_->SetClickCount(click_count); last_click_event_->SetClickCount(click_count);
return click_count; return click_count;
} }
void MouseEvent::ResetLastClickForTest() {
if (last_click_event_) {
delete last_click_event_;
last_click_event_ = NULL;
last_click_complete_ = false;
}
}
// static // static
MouseEvent* MouseEvent::last_click_event_ = NULL; MouseEvent* MouseEvent::last_click_event_ = NULL;
bool MouseEvent::last_click_complete_ = false;
int MouseEvent::GetClickCount() const { int MouseEvent::GetClickCount() const {
if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/event_types.h" #include "base/event_types.h"
#include "base/gtest_prod_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "ui/events/event_constants.h" #include "ui/events/event_constants.h"
...@@ -402,14 +403,25 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent { ...@@ -402,14 +403,25 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent {
void set_changed_button_flags(int flags) { changed_button_flags_ = flags; } void set_changed_button_flags(int flags) { changed_button_flags_ = flags; }
private: private:
FRIEND_TEST_ALL_PREFIXES(EventTest, DoubleClickRequiresRelease);
FRIEND_TEST_ALL_PREFIXES(EventTest, SingleClickRightLeft);
// Returns the repeat count based on the previous mouse click, if it is // Returns the repeat count based on the previous mouse click, if it is
// recent enough and within a small enough distance. // recent enough and within a small enough distance.
static int GetRepeatCount(const MouseEvent& click_event); static int GetRepeatCount(const MouseEvent& click_event);
// Resets the last_click_event_ for unit tests.
static void ResetLastClickForTest();
// See description above getter for details. // See description above getter for details.
int changed_button_flags_; int changed_button_flags_;
static MouseEvent* last_click_event_; static MouseEvent* last_click_event_;
// We can create a MouseEvent for a native event more than once. We set this
// to true when the next event either has a different timestamp or we see a
// release signalling that the press (click) event was completed.
static bool last_click_complete_;
}; };
class ScrollEvent; class ScrollEvent;
......
...@@ -98,6 +98,68 @@ TEST(EventTest, RepeatedClick) { ...@@ -98,6 +98,68 @@ TEST(EventTest, RepeatedClick) {
EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2)); EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2));
} }
// Tests that an event only increases the click count and gets marked as a
// double click if a release event was seen for the previous click. This
// prevents the same PRESSED event from being processed twice:
// http://crbug.com/389162
TEST(EventTest, DoubleClickRequiresRelease) {
const gfx::Point origin1(0, 0);
const gfx::Point origin2(100, 0);
scoped_ptr<MouseEvent> ev;
base::TimeDelta start = base::TimeDelta::FromMilliseconds(0);
ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin1, origin1, 0, 0));
ev->set_time_stamp(start);
EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin1, origin1, 0, 0));
ev->set_time_stamp(start);
EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin2, origin2, 0, 0));
ev->set_time_stamp(start);
EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
ev.reset(new MouseEvent(ET_MOUSE_RELEASED, origin2, origin2, 0, 0));
ev->set_time_stamp(start);
EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin2, origin2, 0, 0));
ev->set_time_stamp(start);
EXPECT_EQ(2, MouseEvent::GetRepeatCount(*ev));
ev.reset(new MouseEvent(ET_MOUSE_RELEASED, origin2, origin2, 0, 0));
ev->set_time_stamp(start);
EXPECT_EQ(2, MouseEvent::GetRepeatCount(*ev));
MouseEvent::ResetLastClickForTest();
}
// Tests that clicking right and then left clicking does not generate a double
// click.
TEST(EventTest, SingleClickRightLeft) {
const gfx::Point origin(0, 0);
scoped_ptr<MouseEvent> ev;
base::TimeDelta start = base::TimeDelta::FromMilliseconds(0);
ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin, origin,
ui::EF_RIGHT_MOUSE_BUTTON,
ui::EF_RIGHT_MOUSE_BUTTON));
ev->set_time_stamp(start);
EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin, origin,
ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON));
ev->set_time_stamp(start);
EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
ev.reset(new MouseEvent(ET_MOUSE_RELEASED, origin, origin,
ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON));
ev->set_time_stamp(start);
EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev));
ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin, origin,
ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON));
ev->set_time_stamp(start);
EXPECT_EQ(2, MouseEvent::GetRepeatCount(*ev));
MouseEvent::ResetLastClickForTest();
}
TEST(EventTest, KeyEvent) { TEST(EventTest, KeyEvent) {
static const struct { static const struct {
KeyboardCode key_code; KeyboardCode key_code;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment