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(
int MouseEvent::GetRepeatCount(const MouseEvent& event) {
int click_count = 1;
if (last_click_event_) {
if (event.type() == ui::ET_MOUSE_RELEASED)
return last_click_event_->GetClickCount();
if (IsX11SendEventTrue(event.native_event()))
if (event.type() == ui::ET_MOUSE_RELEASED) {
if (event.changed_button_flags() ==
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();
else if (IsRepeatedClickEvent(*last_click_event_, event))
} else if (IsRepeatedClickEvent(*last_click_event_, event)) {
click_count = last_click_event_->GetClickCount() + 1;
}
delete last_click_event_;
}
last_click_event_ = new MouseEvent(event);
last_click_complete_ = false;
if (click_count > 3)
click_count = 3;
last_click_event_->SetClickCount(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
MouseEvent* MouseEvent::last_click_event_ = NULL;
bool MouseEvent::last_click_complete_ = false;
int MouseEvent::GetClickCount() const {
if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
......
......@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/event_types.h"
#include "base/gtest_prod_util.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "ui/events/event_constants.h"
......@@ -402,14 +403,25 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent {
void set_changed_button_flags(int flags) { changed_button_flags_ = flags; }
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
// recent enough and within a small enough distance.
static int GetRepeatCount(const MouseEvent& click_event);
// Resets the last_click_event_ for unit tests.
static void ResetLastClickForTest();
// See description above getter for details.
int changed_button_flags_;
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;
......
......@@ -98,6 +98,68 @@ TEST(EventTest, RepeatedClick) {
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) {
static const struct {
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