summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-24 21:47:56 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-24 21:47:56 +0000
commit36df22b48817bc7fe7159e498f65b5e8b00f1605 (patch)
tree15e7aa8f769102d90479c5c59330a5309f4dbc3c /views
parentaf5ee7f3fe7c555578bd9c0cf1290bcf6af553e7 (diff)
downloadchromium_src-36df22b48817bc7fe7159e498f65b5e8b00f1605.zip
chromium_src-36df22b48817bc7fe7159e498f65b5e8b00f1605.tar.gz
chromium_src-36df22b48817bc7fe7159e498f65b5e8b00f1605.tar.bz2
Transformable views: Use the transformation for points and events.
Added and updated API for converting points between views' coordinate systems, taking transformations into consideration. This in turn gives us, for free, transformation for located events (mouse events, touch events). BUG=none TEST=ViewTest.TransformEvent Review URL: http://codereview.chromium.org/6534015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75960 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r--views/events/event.cc10
-rw-r--r--views/events/event.h26
-rw-r--r--views/touchui/gesture_manager.cc16
-rw-r--r--views/view.cc180
-rw-r--r--views/view.h65
-rw-r--r--views/view_unittest.cc127
-rw-r--r--views/widget/root_view.cc20
-rw-r--r--views/widget/root_view.h8
8 files changed, 358 insertions, 94 deletions
diff --git a/views/events/event.cc b/views/events/event.cc
index 2a814bd..49fe29b 100644
--- a/views/events/event.cc
+++ b/views/events/event.cc
@@ -5,6 +5,7 @@
#include "views/events/event.h"
#include "views/view.h"
+#include "views/widget/root_view.h"
namespace views {
@@ -45,6 +46,15 @@ LocatedEvent::LocatedEvent(const LocatedEvent& model, View* from, View* to)
}
////////////////////////////////////////////////////////////////////////////////
+// LocatedEvent, private:
+
+LocatedEvent::LocatedEvent(const LocatedEvent& model, RootView* root)
+ : Event(model),
+ location_(model.location_) {
+ View::ConvertPointFromWidget(root, &location_);
+}
+
+////////////////////////////////////////////////////////////////////////////////
// KeyEvent, public:
KeyEvent::KeyEvent(ui::EventType type, ui::KeyboardCode key_code,
diff --git a/views/events/event.h b/views/events/event.h
index 5382573..83f8bbf 100644
--- a/views/events/event.h
+++ b/views/events/event.h
@@ -24,6 +24,7 @@ using ui::OSExchangeData;
namespace views {
+class RootView;
class View;
////////////////////////////////////////////////////////////////////////////////
@@ -145,6 +146,11 @@ class LocatedEvent : public Event {
int y() const { return location_.y(); }
const gfx::Point& location() const { return location_; }
+ protected:
+ // This constructor is to allow converting the location of an event from the
+ // widget's coordinate system to the RootView's coordinate system.
+ LocatedEvent(const LocatedEvent& model, RootView* root);
+
private:
gfx::Point location_;
};
@@ -211,6 +217,12 @@ class MouseEvent : public LocatedEvent {
}
private:
+ friend class RootView;
+
+ MouseEvent(const MouseEvent& model, RootView* root)
+ : LocatedEvent(model, root) {
+ }
+
DISALLOW_COPY_AND_ASSIGN(MouseEvent);
};
@@ -251,6 +263,13 @@ class TouchEvent : public LocatedEvent {
bool identity() const { return touch_id_; }
private:
+ friend class RootView;
+
+ TouchEvent(const TouchEvent& model, RootView* root)
+ : LocatedEvent(model, root),
+ touch_id_(model.touch_id_) {
+ }
+
// The identity (typically finger) of the touch starting at 0 and incrementing
// for each separable additional touch that the hardware can detect.
const int touch_id_;
@@ -308,6 +327,13 @@ class MouseWheelEvent : public LocatedEvent {
int offset() const { return offset_; }
private:
+ friend class RootView;
+
+ MouseWheelEvent(const MouseWheelEvent& model, RootView* root)
+ : LocatedEvent(model, root),
+ offset_(model.offset_) {
+ }
+
int offset_;
DISALLOW_COPY_AND_ASSIGN(MouseWheelEvent);
diff --git a/views/touchui/gesture_manager.cc b/views/touchui/gesture_manager.cc
index 2d6c7d0..2442469 100644
--- a/views/touchui/gesture_manager.cc
+++ b/views/touchui/gesture_manager.cc
@@ -30,9 +30,19 @@ bool GestureManager::ProcessTouchEventForGesture(const TouchEvent& event,
// appear in a subsequent CL. This interim version permits verifying that the
// event distribution code works by turning all touch inputs into
// mouse approximations.
+
+ // TODO(sad): Clean this up.
+ // This is currently only called where |source| is a RootView. Now, RootView
+ // expects the mouse-events in the widget's coordinate system, and not in the
+ // RV's coordinate system. But |event| is in the RV's coordinate system. So it
+ // is necessary to construct the synthetic event in the widget's coordinate
+ // system.
+ gfx::Point location = event.location();
+ View::ConvertPointToWidget(source, &location);
+
if (event.type() == ui::ET_TOUCH_PRESSED) {
DVLOG(1) << "GestureManager::ProcessTouchEventForGesture: TouchPressed";
- MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, event.x(), event.y(),
+ MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, location.x(), location.y(),
event.flags());
source->OnMousePressed(mouse_event);
return true;
@@ -40,7 +50,7 @@ bool GestureManager::ProcessTouchEventForGesture(const TouchEvent& event,
if (event.type() == ui::ET_TOUCH_RELEASED) {
DVLOG(1) << "GestureManager::ProcessTouchEventForGesture: TouchReleased";
- MouseEvent mouse_event(ui::ET_MOUSE_RELEASED, event.x(), event.y(),
+ MouseEvent mouse_event(ui::ET_MOUSE_RELEASED, location.x(), location.y(),
event.flags());
source->OnMouseReleased(mouse_event, false);
return true;
@@ -48,7 +58,7 @@ bool GestureManager::ProcessTouchEventForGesture(const TouchEvent& event,
if (event.type() == ui::ET_TOUCH_MOVED) {
DVLOG(1) << "GestureManager::ProcessTouchEventForGesture: TouchMotion";
- MouseEvent mouse_event(ui::ET_MOUSE_DRAGGED, event.x(), event.y(),
+ MouseEvent mouse_event(ui::ET_MOUSE_DRAGGED, location.x(), location.y(),
event.flags());
source->OnMouseDragged(mouse_event);
return true;
diff --git a/views/view.cc b/views/view.cc
index 8ffb77e..b36a3a4 100644
--- a/views/view.cc
+++ b/views/view.cc
@@ -10,12 +10,11 @@
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
-#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkRect.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/gfx/canvas_skia.h"
#include "ui/gfx/path.h"
-#include "ui/gfx/skia_util.h"
+#include "ui/gfx/transform.h"
#include "views/background.h"
#include "views/layout/layout_manager.h"
#include "views/views_delegate.h"
@@ -61,8 +60,8 @@ View::View()
parent_(NULL),
is_visible_(true),
registered_for_visible_bounds_notification_(false),
- clip_x_(0),
- clip_y_(0),
+ clip_x_(0.0),
+ clip_y_(0.0),
needs_layout_(true),
flip_canvas_on_paint_for_rtl_ui_(false),
accelerator_registration_delayed_(false),
@@ -357,45 +356,66 @@ bool View::IsEnabled() const {
// Transformations -------------------------------------------------------------
-void View::SetRotation(double degree) {
+const ui::Transform& View::GetTransform() const {
+ static const ui::Transform* no_op = ui::Transform::Create();
+ if (transform_.get())
+ return *transform_.get();
+ return *no_op;
+}
+
+void View::SetRotation(float degree) {
+ InitTransform();
+ transform_->SetRotate(degree);
+}
+
+void View::SetScaleX(float x) {
InitTransform();
- transform_->setRotate(SkDoubleToScalar(degree),
- SkIntToScalar(0), SkIntToScalar(0));
+ transform_->SetScaleX(x);
}
-void View::SetScaleX(double x) {
+void View::SetScaleY(float y) {
InitTransform();
- transform_->setScaleX(SkDoubleToScalar(x));
+ transform_->SetScaleY(y);
}
-void View::SetScaleY(double y) {
+void View::SetScale(float x, float y) {
InitTransform();
- transform_->setScaleY(SkDoubleToScalar(y));
+ transform_->SetScale(x, y);
}
-void View::SetScale(double x, double y) {
+void View::SetTranslateX(float x) {
InitTransform();
- transform_->setScale(SkDoubleToScalar(x), SkDoubleToScalar(y));
+ transform_->SetTranslateX(x);
}
-void View::SetTranslateX(int x) {
+void View::SetTranslateY(float y) {
InitTransform();
- transform_->setTranslateX(SkIntToScalar(x));
+ transform_->SetTranslateY(y);
}
-void View::SetTranslateY(int y) {
+void View::SetTranslate(float x, float y) {
InitTransform();
- transform_->setTranslateY(SkIntToScalar(y));
+ transform_->SetTranslate(x, y);
}
-void View::SetTranslate(int x, int y) {
+void View::ConcatRotation(float degree) {
InitTransform();
- transform_->setTranslate(SkIntToScalar(x), SkIntToScalar(y));
+ transform_->ConcatRotate(degree);
+}
+
+void View::ConcatScale(float x, float y) {
+ InitTransform();
+ transform_->ConcatScale(x, y);
+}
+
+void View::ConcatTranslate(float x, float y) {
+ InitTransform();
+ transform_->ConcatTranslate(x, y);
}
void View::ResetTransform() {
transform_.reset(NULL);
- clip_x_ = clip_y_ = 0;
+ clip_x_ = clip_y_ = 0.0;
}
@@ -554,19 +574,15 @@ void View::ConvertPointToWidget(const View* src, gfx::Point* p) {
DCHECK(src);
DCHECK(p);
- gfx::Point offset;
- for (const View* v = src; v; v = v->parent()) {
- offset.set_x(offset.x() + v->GetMirroredX());
- offset.set_y(offset.y() + v->y());
- }
- p->SetPoint(p->x() + offset.x(), p->y() + offset.y());
+ src->ConvertPointForAncestor(NULL, p);
}
// static
void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) {
- gfx::Point t;
- ConvertPointToWidget(dest, &t);
- p->SetPoint(p->x() - t.x(), p->y() - t.y());
+ DCHECK(dest);
+ DCHECK(p);
+
+ dest->ConvertPointFromAncestor(NULL, p);
}
// static
@@ -585,12 +601,55 @@ void View::ConvertPointToScreen(const View* src, gfx::Point* p) {
}
gfx::Rect View::ConvertRectToParent(const gfx::Rect& rect) const {
- if (!transform_.get() || transform_->isIdentity())
- return rect;
- SkRect src = gfx::RectToSkRect(rect);
- if (!transform_->mapRect(&src))
+ if (!transform_.get() || !transform_->HasChange())
return rect;
- return gfx::SkRectToRect(src);
+ gfx::Rect x_rect = rect;
+ transform_->TransformRect(&x_rect);
+ return x_rect;
+}
+
+bool View::ConvertPointForAncestor(const View* ancestor,
+ gfx::Point* point) const {
+ scoped_ptr<ui::Transform> trans(ui::Transform::Create());
+
+ // TODO(sad): Have some way of caching the transformation results.
+
+ const View* v = this;
+ for (; v && v != ancestor; v = v->parent()) {
+ if (v->GetTransform().HasChange()) {
+ if (!trans->ConcatTransform(v->GetTransform()))
+ return false;
+ }
+ trans->ConcatTranslate(static_cast<float>(v->GetMirroredX()),
+ static_cast<float>(v->y()));
+ }
+
+ if (trans->HasChange()) {
+ trans->TransformPoint(point);
+ }
+
+ return v == ancestor;
+}
+
+bool View::ConvertPointFromAncestor(const View* ancestor,
+ gfx::Point* point) const {
+ scoped_ptr<ui::Transform> trans(ui::Transform::Create());
+
+ const View* v = this;
+ for (; v && v != ancestor; v = v->parent()) {
+ if (v->GetTransform().HasChange()) {
+ if (!trans->ConcatTransform(v->GetTransform()))
+ return false;
+ }
+ trans->ConcatTranslate(static_cast<float>(v->GetMirroredX()),
+ static_cast<float>(v->y()));
+ }
+
+ if (trans->HasChange()) {
+ trans->TransformPointReverse(point);
+ }
+
+ return v == ancestor;
}
// Painting --------------------------------------------------------------------
@@ -627,13 +686,14 @@ void View::Paint(gfx::Canvas* canvas) {
// consideration whether or not the view uses a right-to-left layout so that
// we paint our view in its mirrored position if need be.
if (canvas->ClipRectInt(GetMirroredX(), y(),
- width() - clip_x_, height() - clip_y_)) {
+ width() - static_cast<int>(clip_x_),
+ height() - static_cast<int>(clip_y_))) {
// Non-empty clip, translate the graphics such that 0,0 corresponds to
// where this view is located (related to its parent).
canvas->TranslateInt(GetMirroredX(), y());
- if (transform_.get())
- canvas->AsCanvasSkia()->concat(*transform_.get());
+ if (transform_.get() && transform_->HasChange())
+ canvas->Transform(*transform_.get());
// If the View we are about to paint requested the canvas to be flipped, we
// should change the transform appropriately.
@@ -675,6 +735,11 @@ ThemeProvider* View::GetThemeProvider() const {
// Input -----------------------------------------------------------------------
View* View::GetViewForPoint(const gfx::Point& point) {
+ return GetEventHandlerForPoint(point, NULL);
+}
+
+View* View::GetEventHandlerForPoint(const gfx::Point& point,
+ gfx::Point* xpoint) {
// Walk the child Views recursively looking for the View that most
// tightly encloses the specified point.
for (int i = child_count() - 1; i >= 0; --i) {
@@ -685,8 +750,10 @@ View* View::GetViewForPoint(const gfx::Point& point) {
gfx::Point point_in_child_coords(point);
View::ConvertPointToView(this, child, &point_in_child_coords);
if (child->HitTest(point_in_child_coords))
- return child->GetViewForPoint(point_in_child_coords);
+ return child->GetEventHandlerForPoint(point_in_child_coords, xpoint);
}
+ if (xpoint)
+ xpoint->SetPoint(point.x(), point.y());
return this;
}
@@ -1323,10 +1390,8 @@ void View::RemoveDescendantToNotify(View* view) {
// Transformations -------------------------------------------------------------
void View::InitTransform() {
- if (!transform_.get()) {
- transform_.reset(new SkMatrix);
- transform_->reset();
- }
+ if (!transform_.get())
+ transform_.reset(ui::Transform::Create());
}
// Coordinate conversion -------------------------------------------------------
@@ -1340,27 +1405,9 @@ void View::ConvertPointToView(const View* src,
DCHECK(dst);
DCHECK(point);
- const View* v;
- gfx::Point offset;
-
- for (v = dst; v && v != src; v = v->parent())
- offset.SetPoint(offset.x() + v->GetMirroredX(), offset.y() + v->y());
-
- // The source was not found. The caller wants a conversion
- // from a view to a transitive parent.
- if (src && v == NULL && try_other_direction) {
- gfx::Point p;
- // note: try_other_direction is force to FALSE so we don't
- // end up in an infinite recursion should both src and dst
- // are not parented.
- ConvertPointToView(dst, src, &p, false);
- // since the src and dst are inverted, p should also be negated
- point->SetPoint(point->x() - p.x(), point->y() - p.y());
- } else {
- point->SetPoint(point->x() - offset.x(), point->y() - offset.y());
-
- // If src is NULL, sp is in the screen coordinate system
- if (src == NULL) {
+ if (src == NULL || src->Contains(dst)) {
+ dst->ConvertPointFromAncestor(src, point);
+ if (!src) {
const Widget* widget = dst->GetWidget();
if (widget) {
gfx::Rect b;
@@ -1368,6 +1415,13 @@ void View::ConvertPointToView(const View* src,
point->SetPoint(point->x() - b.x(), point->y() - b.y());
}
}
+ } else if (src && try_other_direction) {
+ if (!src->ConvertPointForAncestor(dst, point)) {
+ // |src| is not an ancestor of |dst|, and |dst| is not an ancestor of
+ // |src| either. At this stage, |point| is in the widget's coordinate
+ // system. So convert from the widget's to |dst|'s coordiante system now.
+ ConvertPointFromWidget(dst, point);
+ }
}
}
diff --git a/views/view.h b/views/view.h
index 490662d..eb7ff06 100644
--- a/views/view.h
+++ b/views/view.h
@@ -26,8 +26,6 @@
using ui::OSExchangeData;
-// TODO(sad): Use platform independent wrapper for transform matrix.
-class SkMatrix;
class ViewAccessibility;
namespace gfx {
@@ -38,6 +36,7 @@ class Path;
namespace ui {
class ThemeProvider;
+class Transform;
}
using ui::ThemeProvider;
@@ -331,25 +330,31 @@ class View : public AcceleratorTarget {
// Methods for setting transformations for a view (e.g. rotation, scaling).
- const SkMatrix* transform() { return transform_.get(); }
+ const ui::Transform& GetTransform() const;
// Clipping parameters. Clipping happens from the right and/or bottom. The
// clipping amount is in parent's coordinate system, as in, if the view is
// rotated, then the clipping will be applied after the rotation (and other
// transformations, if any).
- void set_clip_x(int x) { clip_x_ = x; }
- void set_clip_y(int y) { clip_y_ = y; }
- void set_clip(int x, int y) { clip_x_ = x; clip_y_ = y; }
+ void set_clip_x(float x) { clip_x_ = x; }
+ void set_clip_y(float y) { clip_y_ = y; }
+ void set_clip(float x, float y) { clip_x_ = x; clip_y_ = y; }
- void SetRotation(double degree);
+ void SetRotation(float degree);
- void SetScaleX(double x);
- void SetScaleY(double y);
- void SetScale(double x, double y);
+ void SetScaleX(float x);
+ void SetScaleY(float y);
+ void SetScale(float x, float y);
- void SetTranslateX(int x);
- void SetTranslateY(int y);
- void SetTranslate(int x, int y);
+ void SetTranslateX(float x);
+ void SetTranslateY(float y);
+ void SetTranslate(float x, float y);
+
+ // The following functions apply the transformations on top of the existing
+ // transform.
+ void ConcatRotation(float degree);
+ void ConcatScale(float x, float y);
+ void ConcatTranslate(float x, float y);
// Reset the transformation matrix.
void ResetTransform();
@@ -476,9 +481,9 @@ class View : public AcceleratorTarget {
// Convert a point from source coordinate system to dst coordinate system.
//
- // source is a parent or a child of dst, directly or transitively.
- // If source and dst are not in the same View hierarchy, the result is
- // undefined.
+ // |src| and |dst| needs to be in the same widget, but doesn't need to be in
+ // the same view hierarchy.
+ // If |src| and |dst| are not in the same widget, the result is undefined.
// Source can be NULL in which case it means the screen coordinate system
static void ConvertPointToView(const View* src,
const View* dst,
@@ -560,10 +565,18 @@ class View : public AcceleratorTarget {
}
// Input ---------------------------------------------------------------------
+ // The points (and mouse locations) in the following functions are in the
+ // view's coordinates, except for a RootView.
+ // TODO(sad): Remove
// Returns the deepest descendant that contains the specified point.
virtual View* GetViewForPoint(const gfx::Point& point);
+ // Returns the deepest descendant that contains the specified point, and the
+ // point in the returned view's coordinates.
+ virtual View* GetEventHandlerForPoint(const gfx::Point& point,
+ gfx::Point* xpoint);
+
// Return the cursor that should be used for this view or NULL if
// the default cursor should be used. The provided point is in the
// receiver's coordinate system. The caller is responsible for managing the
@@ -1227,16 +1240,28 @@ class View : public AcceleratorTarget {
// Initialize the transform matrix when necessary.
void InitTransform();
- // Coordinate conersion ------------------------------------------------------
+ // Coordinate conversion -----------------------------------------------------
// This is the actual implementation for ConvertPointToView()
// Attempts a parent -> child conversion and then a
// child -> parent conversion if try_other_direction is true
+ // Applies necessary transformations during the conversion.
static void ConvertPointToView(const View* src,
const View* dst,
gfx::Point* point,
bool try_other_direction);
+ // Convert a point in the view's coordinate to an ancestor view's coordinate
+ // system using necessary transformations. Returns whether the point was
+ // successfully converted to the ancestor's coordinate system.
+ bool ConvertPointForAncestor(const View* ancestor, gfx::Point* point) const;
+
+ // Convert a point in the ancestor's coordinate system to the view's
+ // coordinate system using necessary transformations. Returns whether the
+ // point was successfully from the ancestor's coordinate system to the view's
+ // coordinate system.
+ bool ConvertPointFromAncestor(const View* ancestor, gfx::Point* point) const;
+
// Input ---------------------------------------------------------------------
// RootView invokes these. These in turn invoke the appropriate OnMouseXXX
@@ -1328,12 +1353,12 @@ class View : public AcceleratorTarget {
// Transformations -----------------------------------------------------------
// The transformation matrix (rotation, translate, scale).
- scoped_ptr<SkMatrix> transform_;
+ scoped_ptr<ui::Transform> transform_;
// Clipping parameters. skia transformation matrix does not give us clipping.
// So we do it ourselves.
- int clip_x_;
- int clip_y_;
+ float clip_x_;
+ float clip_y_;
// Layout --------------------------------------------------------------------
diff --git a/views/view_unittest.cc b/views/view_unittest.cc
index 0d30b6c..74aadd5 100644
--- a/views/view_unittest.cc
+++ b/views/view_unittest.cc
@@ -1587,6 +1587,133 @@ TEST_F(ViewTest, TransformPaint) {
widget->CloseNow();
}
+TEST_F(ViewTest, TransformEvent) {
+ TestView* v1 = new TestView();
+ v1->SetBounds(0, 0, 500, 300);
+
+ TestView* v2 = new TestView();
+ v2->SetBounds(100, 100, 200, 100);
+
+ Widget* widget = CreateWidget();
+#if defined(OS_WIN)
+ WidgetWin* window_win = static_cast<WidgetWin*>(widget);
+ window_win->set_window_style(WS_OVERLAPPEDWINDOW);
+ window_win->Init(NULL, gfx::Rect(50, 50, 650, 650));
+#endif
+ RootView* root = widget->GetRootView();
+
+ root->AddChildView(v1);
+ v1->AddChildView(v2);
+
+ // At this moment, |v2| occupies (100, 100) to (300, 200) in |root|.
+
+ // Rotate |v1| counter-clockwise.
+ v1->SetRotation(-90.0);
+ v1->SetTranslateY(500);
+
+ // |v2| now occupies (100, 200) to (200, 400) in |root|.
+ v1->Reset();
+ v2->Reset();
+
+ MouseEvent pressed(ui::ET_MOUSE_PRESSED,
+ 110, 210,
+ ui::EF_LEFT_BUTTON_DOWN);
+ root->OnMousePressed(pressed);
+ EXPECT_EQ(0, v1->last_mouse_event_type_);
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_);
+ EXPECT_EQ(190, v2->location_.x());
+ EXPECT_EQ(10, v2->location_.y());
+
+ MouseEvent released(ui::ET_MOUSE_RELEASED, 0, 0, 0);
+ root->OnMouseReleased(released, false);
+
+ // Now rotate |v2| inside |v1| clockwise.
+ v2->SetRotation(90.0);
+ v2->SetTranslateX(100);
+
+ // Now, |v2| occupies (100, 100) to (200, 300) in |v1|, and (100, 300) to
+ // (300, 400) in |root|.
+
+ v1->Reset();
+ v2->Reset();
+
+ MouseEvent p2(ui::ET_MOUSE_PRESSED,
+ 110, 320,
+ ui::EF_LEFT_BUTTON_DOWN);
+ root->OnMousePressed(p2);
+ EXPECT_EQ(0, v1->last_mouse_event_type_);
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_);
+ EXPECT_EQ(10, v2->location_.x());
+ EXPECT_EQ(20, v2->location_.y());
+
+ root->OnMouseReleased(released, false);
+
+ v1->ResetTransform();
+ v2->ResetTransform();
+
+ TestView* v3 = new TestView();
+ v3->SetBounds(10, 10, 20, 30);
+ v2->AddChildView(v3);
+
+ // Rotate |v3| clockwise with respect to |v2|.
+ v3->SetRotation(90.0);
+ v3->SetTranslateX(30);
+
+ // Scale |v2| with respect to |v1| along both axis.
+ v2->SetScale(0.8, 0.5);
+
+ // |v3| occupies (108, 105) to (132, 115) in |root|.
+
+ v1->Reset();
+ v2->Reset();
+ v3->Reset();
+
+ MouseEvent p3(ui::ET_MOUSE_PRESSED,
+ 112, 110,
+ ui::EF_LEFT_BUTTON_DOWN);
+ root->OnMousePressed(p3);
+
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_);
+ EXPECT_EQ(10, v3->location_.x());
+ EXPECT_EQ(25, v3->location_.y());
+
+ root->OnMouseReleased(released, false);
+
+ v1->ResetTransform();
+ v2->ResetTransform();
+ v3->ResetTransform();
+
+ v1->Reset();
+ v2->Reset();
+ v3->Reset();
+
+ // Rotate |v3| clockwise with respect to |v2|, and scale it along both axis.
+ v3->SetRotation(90.0);
+ v3->SetTranslateX(30);
+ // Rotation sets some scaling transformation. Using SetScale would overwrite
+ // that and pollute the rotation. So combine the scaling with the existing
+ // transforamtion.
+ v3->ConcatScale(0.8, 0.5);
+
+ // Translate |v2| with respect to |v1|.
+ v2->SetTranslate(10, 10);
+
+ // |v3| now occupies (120, 120) to (144, 130) in |root|.
+
+ MouseEvent p4(ui::ET_MOUSE_PRESSED,
+ 124, 125,
+ ui::EF_LEFT_BUTTON_DOWN);
+ root->OnMousePressed(p4);
+
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_);
+ EXPECT_EQ(10, v3->location_.x());
+ EXPECT_EQ(25, v3->location_.y());
+
+ root->OnMouseReleased(released, false);
+
+ widget->CloseNow();
+}
+
////////////////////////////////////////////////////////////////////////////////
// OnVisibleBoundsChanged()
diff --git a/views/widget/root_view.cc b/views/widget/root_view.cc
index d7b9007..4919bf4 100644
--- a/views/widget/root_view.cc
+++ b/views/widget/root_view.cc
@@ -116,7 +116,8 @@ bool RootView::ProcessKeyEvent(const KeyEvent& event) {
return consumed;
}
-bool RootView::ProcessMouseWheelEvent(const MouseWheelEvent& e) {
+bool RootView::ProcessMouseWheelEvent(const MouseWheelEvent& event) {
+ MouseWheelEvent e(event, this);
View* v;
bool consumed = false;
View* focused_view = GetFocusManager()->GetFocusedView();
@@ -181,7 +182,9 @@ Widget* RootView::GetWidget() {
return const_cast<Widget*>(const_cast<const RootView*>(this)->GetWidget());
}
-bool RootView::OnMousePressed(const MouseEvent& e) {
+bool RootView::OnMousePressed(const MouseEvent& event) {
+ MouseEvent e(event, this);
+
// This function does not normally handle non-client messages except for
// non-client double-clicks. Actually, all double-clicks are special as the
// are formed from a single-click followed by a double-click event. When the
@@ -265,7 +268,8 @@ bool RootView::OnMousePressed(const MouseEvent& e) {
return hit_disabled_view;
}
-bool RootView::OnMouseDragged(const MouseEvent& e) {
+bool RootView::OnMouseDragged(const MouseEvent& event) {
+ MouseEvent e(event, this);
UpdateCursor(e);
if (mouse_pressed_handler_) {
@@ -279,7 +283,8 @@ bool RootView::OnMouseDragged(const MouseEvent& e) {
return false;
}
-void RootView::OnMouseReleased(const MouseEvent& e, bool canceled) {
+void RootView::OnMouseReleased(const MouseEvent& event, bool canceled) {
+ MouseEvent e(event, this);
UpdateCursor(e);
if (mouse_pressed_handler_) {
@@ -296,7 +301,8 @@ void RootView::OnMouseReleased(const MouseEvent& e, bool canceled) {
}
}
-void RootView::OnMouseMoved(const MouseEvent& e) {
+void RootView::OnMouseMoved(const MouseEvent& event) {
+ MouseEvent e(event, this);
View* v = GetViewForPoint(e.location());
// Find the first enabled view, or the existing move handler, whichever comes
// first. The check for the existing handler is because if a view becomes
@@ -344,7 +350,9 @@ void RootView::SetMouseHandler(View *new_mh) {
}
#if defined(TOUCH_UI)
-View::TouchStatus RootView::OnTouchEvent(const TouchEvent& e) {
+View::TouchStatus RootView::OnTouchEvent(const TouchEvent& event) {
+ TouchEvent e(event, this);
+
// If touch_pressed_handler_ is non null, we are currently processing
// a touch down on the screen situation. In that case we send the
// event to touch_pressed_handler_
diff --git a/views/widget/root_view.h b/views/widget/root_view.h
index df74ede..e38c686 100644
--- a/views/widget/root_view.h
+++ b/views/widget/root_view.h
@@ -149,10 +149,14 @@ class RootView : public View,
// Update the cursor given a mouse event. This is called by non mouse_move
// event handlers to honor the cursor desired by views located under the
- // cursor during drag operations.
+ // cursor during drag operations. The location of the mouse should be in the
+ // current coordinate system (i.e. any necessary transformation should be
+ // applied to the point prior to calling this).
void UpdateCursor(const MouseEvent& e);
- // Updates the last_mouse_* fields from e.
+ // Updates the last_mouse_* fields from e. The location of the mouse should be
+ // in the current coordinate system (i.e. any necessary transformation should
+ // be applied to the point prior to calling this).
void SetMouseLocationAndFlags(const MouseEvent& e);
//////////////////////////////////////////////////////////////////////////////