summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-15 22:11:25 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-15 22:11:25 +0000
commitcba0bf2355b091a874537a3be99955ae3b29f8b0 (patch)
tree3b8e889372624c048d49e6706f39f6a7947fb6c3 /views
parentc3ca81c42c4e70a3046d5a0fc68e376aa60c626e (diff)
downloadchromium_src-cba0bf2355b091a874537a3be99955ae3b29f8b0.zip
chromium_src-cba0bf2355b091a874537a3be99955ae3b29f8b0.tar.gz
chromium_src-cba0bf2355b091a874537a3be99955ae3b29f8b0.tar.bz2
Sort methods in RootView cc/h. Add better documentation and outline future plans.
http://crbug.com/72040 TEST=none TBR=sky Review URL: http://codereview.chromium.org/6525024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75018 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r--views/widget/root_view.cc750
-rw-r--r--views/widget/root_view.h335
2 files changed, 529 insertions, 556 deletions
diff --git a/views/widget/root_view.cc b/views/widget/root_view.cc
index 3a5ce87..b03338e 100644
--- a/views/widget/root_view.cc
+++ b/views/widget/root_view.cc
@@ -35,11 +35,8 @@
namespace views {
-/////////////////////////////////////////////////////////////////////////////
-//
-// A Task to trigger non urgent painting.
-//
-/////////////////////////////////////////////////////////////////////////////
+// Performs painting after a return to the message loop.
+// TODO(beng): CancelableTask, or delete in SchedulePaint rewrite.
class PaintTask : public Task {
public:
explicit PaintTask(RootView* target) : root_view_(target) {
@@ -62,45 +59,68 @@ class PaintTask : public Task {
DISALLOW_COPY_AND_ASSIGN(PaintTask);
};
-const char RootView::kViewClassName[] = "views/RootView";
+namespace {
+
+#ifndef NDEBUG
+// Sets the value of RootView's |is_processing_paint_| member to true as long
+// as ProcessPaint is being called. Sets it to |false| when it returns.
+class ScopedProcessingPaint {
+ public:
+ explicit ScopedProcessingPaint(bool* is_processing_paint)
+ : is_processing_paint_(is_processing_paint) {
+ *is_processing_paint_ = true;
+ }
+
+ ~ScopedProcessingPaint() {
+ *is_processing_paint_ = false;
+ }
+ private:
+ bool* is_processing_paint_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedProcessingPaint);
+};
+#endif
+
+} // namespace
+
// static
+const char RootView::kViewClassName[] = "views/RootView";
bool RootView::debug_paint_enabled_ = false;
-/////////////////////////////////////////////////////////////////////////////
-//
-// RootView - constructors, destructors, initialization
-//
-/////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// RootView, public:
+
+// Creation and lifetime -------------------------------------------------------
RootView::RootView(Widget* widget)
- : mouse_pressed_handler_(NULL),
- mouse_move_handler_(NULL),
- last_click_handler_(NULL),
- widget_(widget),
- ALLOW_THIS_IN_INITIALIZER_LIST(focus_search_(this, false, false)),
+ : widget_(widget),
invalid_rect_urgent_(false),
pending_paint_task_(NULL),
paint_task_needed_(false),
+#ifndef NDEBUG
+ is_processing_paint_(false),
+#endif
+ mouse_pressed_handler_(NULL),
+ mouse_move_handler_(NULL),
+ last_click_handler_(NULL),
explicit_mouse_handler_(false),
#if defined(OS_WIN)
previous_cursor_(NULL),
#endif
default_keyboard_handler_(NULL),
+ last_mouse_event_flags_(0),
+ last_mouse_event_x_(-1),
+ last_mouse_event_y_(-1),
+#if defined(TOUCH_UI)
+ gesture_manager_(GestureManager::GetInstance()),
+ touch_pressed_handler_(NULL),
+#endif
+ ALLOW_THIS_IN_INITIALIZER_LIST(focus_search_(this, false, false)),
focus_on_mouse_pressed_(false),
ignore_set_focus_calls_(false),
focus_traversable_parent_(NULL),
focus_traversable_parent_view_(NULL),
- drag_view_(NULL)
-#if defined(TOUCH_UI)
- ,
- gesture_manager_(GestureManager::GetInstance()),
- touch_pressed_handler_(NULL)
-#endif
-#ifndef NDEBUG
- ,
- is_processing_paint_(false)
-#endif
-{
+ drag_view_(NULL) {
}
RootView::~RootView() {
@@ -113,6 +133,8 @@ RootView::~RootView() {
pending_paint_task_->Cancel(); // Ensure we're not called any more.
}
+// Tree operations -------------------------------------------------------------
+
void RootView::SetContentsView(View* contents_view) {
DCHECK(contents_view && GetWidget()->GetNativeView()) <<
"Can't be called until after the native view is created!";
@@ -130,11 +152,190 @@ void RootView::SetContentsView(View* contents_view) {
Layout();
}
-/////////////////////////////////////////////////////////////////////////////
-//
-// RootView - layout, painting
-//
-/////////////////////////////////////////////////////////////////////////////
+void RootView::NotifyNativeViewHierarchyChanged(bool attached,
+ gfx::NativeView native_view) {
+ PropagateNativeViewHierarchyChanged(attached, native_view, this);
+}
+
+// Painting --------------------------------------------------------------------
+
+bool RootView::NeedsPainting(bool urgent) {
+ bool has_invalid_rect = !invalid_rect_.IsEmpty();
+ if (urgent)
+ return invalid_rect_urgent_ ? has_invalid_rect : false;
+ return has_invalid_rect;
+}
+
+const gfx::Rect& RootView::GetScheduledPaintRect() {
+ return invalid_rect_;
+}
+
+gfx::Rect RootView::GetScheduledPaintRectConstrainedToSize() {
+ if (invalid_rect_.IsEmpty())
+ return invalid_rect_;
+
+ return invalid_rect_.Intersect(GetLocalBounds());
+}
+
+void RootView::ClearPaintRect() {
+ invalid_rect_.SetRect(0, 0, 0, 0);
+
+ // This painting has been done. Reset the urgent flag.
+ invalid_rect_urgent_ = false;
+
+ // If a pending_paint_task_ does Run(), we don't need to do anything.
+ paint_task_needed_ = false;
+}
+
+// static
+void RootView::EnableDebugPaint() {
+ debug_paint_enabled_ = true;
+}
+
+// Input -----------------------------------------------------------------------
+
+void RootView::ProcessMouseDragCanceled() {
+ if (mouse_pressed_handler_) {
+ // Synthesize a release event.
+ MouseEvent release_event(ui::ET_MOUSE_RELEASED, last_mouse_event_x_,
+ last_mouse_event_y_, last_mouse_event_flags_);
+ OnMouseReleased(release_event, true);
+ }
+}
+
+void RootView::ProcessOnMouseExited() {
+ if (mouse_move_handler_ != NULL) {
+ MouseEvent exited_event(ui::ET_MOUSE_EXITED, 0, 0, 0);
+ mouse_move_handler_->OnMouseExited(exited_event);
+ mouse_move_handler_ = NULL;
+ }
+}
+
+bool RootView::ProcessKeyEvent(const KeyEvent& event) {
+ bool consumed = false;
+
+ View* v = GetFocusedView();
+ // Special case to handle right-click context menus triggered by the
+ // keyboard.
+ if (v && v->IsEnabled() && ((event.key_code() == ui::VKEY_APPS) ||
+ (event.key_code() == ui::VKEY_F10 && event.IsShiftDown()))) {
+ v->ShowContextMenu(v->GetKeyboardContextMenuLocation(), false);
+ return true;
+ }
+ for (; v && v != this && !consumed; v = v->parent()) {
+ consumed = (event.type() == ui::ET_KEY_PRESSED) ?
+ v->OnKeyPressed(event) : v->OnKeyReleased(event);
+ }
+
+ if (!consumed && default_keyboard_handler_) {
+ consumed = (event.type() == ui::ET_KEY_PRESSED) ?
+ default_keyboard_handler_->OnKeyPressed(event) :
+ default_keyboard_handler_->OnKeyReleased(event);
+ }
+
+ return consumed;
+}
+
+void RootView::SetDefaultKeyboardHandler(View* v) {
+ default_keyboard_handler_ = v;
+}
+
+bool RootView::ProcessMouseWheelEvent(const MouseWheelEvent& e) {
+ View* v;
+ bool consumed = false;
+ if (GetFocusedView()) {
+ for (v = GetFocusedView(); v && v != this && !consumed; v = v->parent())
+ consumed = v->OnMouseWheel(e);
+ }
+
+ if (!consumed && default_keyboard_handler_) {
+ consumed = default_keyboard_handler_->OnMouseWheel(e);
+ }
+ return consumed;
+}
+
+// Focus -----------------------------------------------------------------------
+
+void RootView::FocusView(View* view) {
+ if (view != GetFocusedView()) {
+ FocusManager* focus_manager = GetFocusManager();
+ // TODO(jcampan): This fails under WidgetGtk with TYPE_CHILD.
+ // (see http://crbug.com/21335) Reenable DCHECK and
+ // verify GetFocusManager works as expecte.
+#if defined(OS_WIN)
+ DCHECK(focus_manager) << "No Focus Manager for Window " <<
+ (GetWidget() ? GetWidget()->GetNativeView() : 0);
+#endif
+ if (!focus_manager)
+ return;
+ focus_manager->SetFocusedView(view);
+ }
+}
+
+View* RootView::GetFocusedView() {
+ FocusManager* focus_manager = GetFocusManager();
+ if (!focus_manager) {
+ // We may not have a FocusManager when the window that contains us is being
+ // deleted. Sadly we cannot wait for the window to be destroyed before we
+ // remove the FocusManager (see xp_frame.cc for more info).
+ return NULL;
+ }
+
+ // Make sure the focused view belongs to this RootView's view hierarchy.
+ View* view = focus_manager->GetFocusedView();
+ if (view && (view->GetRootView() == this))
+ return view;
+
+#if defined(OS_LINUX)
+ if (view && NativeTextfieldViews::IsTextfieldViewsEnabled()) {
+ // hack to deal with two root views.
+ // should be fixed by eliminating one of them
+ return view;
+ }
+#endif
+ return NULL;
+}
+
+void RootView::SetFocusOnMousePressed(bool f) {
+ focus_on_mouse_pressed_ = f;
+}
+
+void RootView::SetFocusTraversableParent(FocusTraversable* focus_traversable) {
+ DCHECK(focus_traversable != this);
+ focus_traversable_parent_ = focus_traversable;
+}
+
+void RootView::SetFocusTraversableParentView(View* view) {
+ focus_traversable_parent_view_ = view;
+}
+
+// System events ---------------------------------------------------------------
+
+void RootView::NotifyThemeChanged() {
+ View::PropagateThemeChanged();
+}
+
+void RootView::NotifyLocaleChanged() {
+ View::PropagateLocaleChanged();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RootView, FocusTraversable implementation:
+
+FocusSearch* RootView::GetFocusSearch() {
+ return &focus_search_;
+}
+
+FocusTraversable* RootView::GetFocusTraversableParent() {
+ return focus_traversable_parent_;
+}
+
+View* RootView::GetFocusTraversableParentView() {
+ return focus_traversable_parent_view_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RootView, View overrides:
void RootView::SchedulePaintInRect(const gfx::Rect& r, bool urgent) {
// If there is an existing invalid rect, add the union of the scheduled
@@ -156,30 +357,6 @@ void RootView::SchedulePaintInRect(const gfx::Rect& r, bool urgent) {
}
}
-void RootView::SchedulePaint() {
- View::SchedulePaint();
-}
-
-#ifndef NDEBUG
-// Sets the value of RootView's |is_processing_paint_| member to true as long
-// as ProcessPaint is being called. Sets it to |false| when it returns.
-class ScopedProcessingPaint {
- public:
- explicit ScopedProcessingPaint(bool* is_processing_paint)
- : is_processing_paint_(is_processing_paint) {
- *is_processing_paint_ = true;
- }
-
- ~ScopedProcessingPaint() {
- *is_processing_paint_ = false;
- }
- private:
- bool* is_processing_paint_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedProcessingPaint);
-};
-#endif
-
void RootView::ProcessPaint(gfx::Canvas* canvas) {
#ifndef NDEBUG
ScopedProcessingPaint processing_paint(&is_processing_paint_);
@@ -225,35 +402,6 @@ void RootView::PaintNow() {
widget->PaintNow(invalid_rect_);
}
-bool RootView::NeedsPainting(bool urgent) {
- bool has_invalid_rect = !invalid_rect_.IsEmpty();
- if (urgent) {
- if (invalid_rect_urgent_)
- return has_invalid_rect;
- else
- return false;
- } else {
- return has_invalid_rect;
- }
-}
-
-const gfx::Rect& RootView::GetScheduledPaintRect() {
- return invalid_rect_;
-}
-
-gfx::Rect RootView::GetScheduledPaintRectConstrainedToSize() {
- if (invalid_rect_.IsEmpty())
- return invalid_rect_;
-
- return invalid_rect_.Intersect(GetLocalBounds());
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// RootView - tree
-//
-/////////////////////////////////////////////////////////////////////////////
-
const Widget* RootView::GetWidget() const {
return widget_;
}
@@ -262,126 +410,6 @@ Widget* RootView::GetWidget() {
return const_cast<Widget*>(const_cast<const RootView*>(this)->GetWidget());
}
-void RootView::NotifyThemeChanged() {
- View::PropagateThemeChanged();
-}
-
-void RootView::NotifyLocaleChanged() {
- View::PropagateLocaleChanged();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// RootView - event dispatch and propagation
-//
-/////////////////////////////////////////////////////////////////////////////
-
-void RootView::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
- if (!is_add) {
- if (!explicit_mouse_handler_ && mouse_pressed_handler_ == child) {
- mouse_pressed_handler_ = NULL;
- }
-
- if (widget_)
- widget_->ViewHierarchyChanged(is_add, parent, child);
-
- if (mouse_move_handler_ == child) {
- mouse_move_handler_ = NULL;
- }
-
- if (GetFocusedView() == child) {
- FocusView(NULL);
- }
-
- if (child == drag_view_)
- drag_view_ = NULL;
-
- if (default_keyboard_handler_ == child) {
- default_keyboard_handler_ = NULL;
- }
-
-#if defined(TOUCH_UI)
- if (touch_pressed_handler_) {
- touch_pressed_handler_ = NULL;
- }
-#endif
-
- FocusManager* focus_manager = widget_->GetFocusManager();
- // An unparanted RootView does not have a FocusManager.
- if (focus_manager)
- focus_manager->ViewRemoved(parent, child);
-
- ViewStorage::GetInstance()->ViewRemoved(parent, child);
- }
-}
-
-void RootView::SetFocusOnMousePressed(bool f) {
- focus_on_mouse_pressed_ = f;
-}
-
-#if defined(TOUCH_UI)
-View::TouchStatus RootView::OnTouchEvent(const TouchEvent& e) {
- // 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_
- View::TouchStatus status = TOUCH_STATUS_UNKNOWN;
-
- if (touch_pressed_handler_) {
- TouchEvent touch_event(e, this, touch_pressed_handler_);
- status = touch_pressed_handler_->ProcessTouchEvent(touch_event);
- gesture_manager_->ProcessTouchEventForGesture(e, this, status);
- if (status == TOUCH_STATUS_END)
- touch_pressed_handler_ = NULL;
- return status;
- }
-
- // Walk up the tree until we find a view that wants the touch event.
- for (touch_pressed_handler_ = GetViewForPoint(e.location());
- touch_pressed_handler_ && (touch_pressed_handler_ != this);
- touch_pressed_handler_ = touch_pressed_handler_->parent()) {
- if (!touch_pressed_handler_->IsEnabled()) {
- // Disabled views eat events but are treated as not handled by the
- // the GestureManager.
- status = TOUCH_STATUS_UNKNOWN;
- break;
- }
-
- // See if this view wants to handle the touch
- TouchEvent touch_event(e, this, touch_pressed_handler_);
- status = touch_pressed_handler_->ProcessTouchEvent(touch_event);
-
- // If the touch didn't initiate a touch-sequence, then reset the touch event
- // handler.
- if (status != TOUCH_STATUS_START)
- touch_pressed_handler_ = NULL;
-
- // The view could have removed itself from the tree when handling
- // OnTouchEvent(). So handle as per OnMousePressed. NB: we
- // assume that the RootView itself cannot be so removed.
- //
- // NOTE: Don't return true here, because we don't want the frame to
- // forward future events to us when there's no handler.
- if (!touch_pressed_handler_)
- break;
-
- // If the view handled the event, leave touch_pressed_handler_ set and
- // return true, which will cause subsequent drag/release events to get
- // forwarded to that view.
- if (status != TOUCH_STATUS_UNKNOWN) {
- gesture_manager_->ProcessTouchEventForGesture(e, this, status);
- return status;
- }
- }
-
- // Reset touch_pressed_handler_ to indicate that no processing is occurring.
- touch_pressed_handler_ = NULL;
-
- // Give the touch event to the gesture manager.
- gesture_manager_->ProcessTouchEventForGesture(e, this, status);
- return status;
-}
-#endif
-
bool RootView::OnMousePressed(const MouseEvent& e) {
// This function does not normally handle non-client messages except for
// non-client double-clicks. Actually, all double-clicks are special as the
@@ -478,43 +506,6 @@ bool RootView::OnMousePressed(const MouseEvent& e) {
return hit_disabled_view;
}
-bool RootView::ConvertPointToMouseHandler(const gfx::Point& l,
- gfx::Point* p) {
- //
- // If the mouse_handler was set explicitly, we need to keep
- // sending events even if it was reparented in a different
- // window. (a non explicit mouse handler is automatically
- // cleared when the control is removed from the hierarchy)
- if (explicit_mouse_handler_) {
- if (mouse_pressed_handler_->GetWidget()) {
- *p = l;
- ConvertPointToScreen(this, p);
- ConvertPointToView(NULL, mouse_pressed_handler_, p);
- } else {
- // If the mouse_pressed_handler_ is not connected, we send the
- // event in screen coordinate system
- *p = l;
- ConvertPointToScreen(this, p);
- return true;
- }
- } else {
- *p = l;
- ConvertPointToView(this, mouse_pressed_handler_, p);
- }
- return true;
-}
-
-void RootView::UpdateCursor(const MouseEvent& e) {
- gfx::NativeCursor cursor = NULL;
- View* v = GetViewForPoint(e.location());
- if (v && v != this) {
- gfx::Point l(e.location());
- View::ConvertPointToView(this, v, &l);
- cursor = v->GetCursorForPoint(e.type(), l);
- }
- SetActiveCursor(cursor);
-}
-
bool RootView::OnMouseDragged(const MouseEvent& e) {
UpdateCursor(e);
@@ -587,141 +578,130 @@ void RootView::OnMouseMoved(const MouseEvent& e) {
}
}
-void RootView::ProcessOnMouseExited() {
- if (mouse_move_handler_ != NULL) {
- MouseEvent exited_event(ui::ET_MOUSE_EXITED, 0, 0, 0);
- mouse_move_handler_->OnMouseExited(exited_event);
- mouse_move_handler_ = NULL;
- }
-}
-
void RootView::SetMouseHandler(View *new_mh) {
// If we're clearing the mouse handler, clear explicit_mouse_handler as well.
explicit_mouse_handler_ = (new_mh != NULL);
mouse_pressed_handler_ = new_mh;
}
-void RootView::ProcessMouseDragCanceled() {
- if (mouse_pressed_handler_) {
- // Synthesize a release event.
- MouseEvent release_event(ui::ET_MOUSE_RELEASED, last_mouse_event_x_,
- last_mouse_event_y_, last_mouse_event_flags_);
- OnMouseReleased(release_event, true);
- }
-}
+#if defined(TOUCH_UI)
+View::TouchStatus RootView::OnTouchEvent(const TouchEvent& e) {
+ // 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_
+ View::TouchStatus status = TOUCH_STATUS_UNKNOWN;
-void RootView::FocusView(View* view) {
- if (view != GetFocusedView()) {
- FocusManager* focus_manager = GetFocusManager();
- // TODO(jcampan): This fails under WidgetGtk with TYPE_CHILD.
- // (see http://crbug.com/21335) Reenable DCHECK and
- // verify GetFocusManager works as expecte.
-#if defined(OS_WIN)
- DCHECK(focus_manager) << "No Focus Manager for Window " <<
- (GetWidget() ? GetWidget()->GetNativeView() : 0);
-#endif
- if (!focus_manager)
- return;
- focus_manager->SetFocusedView(view);
+ if (touch_pressed_handler_) {
+ TouchEvent touch_event(e, this, touch_pressed_handler_);
+ status = touch_pressed_handler_->ProcessTouchEvent(touch_event);
+ gesture_manager_->ProcessTouchEventForGesture(e, this, status);
+ if (status == TOUCH_STATUS_END)
+ touch_pressed_handler_ = NULL;
+ return status;
}
-}
-View* RootView::GetFocusedView() {
- FocusManager* focus_manager = GetFocusManager();
- if (!focus_manager) {
- // We may not have a FocusManager when the window that contains us is being
- // deleted. Sadly we cannot wait for the window to be destroyed before we
- // remove the FocusManager (see xp_frame.cc for more info).
- return NULL;
- }
+ // Walk up the tree until we find a view that wants the touch event.
+ for (touch_pressed_handler_ = GetViewForPoint(e.location());
+ touch_pressed_handler_ && (touch_pressed_handler_ != this);
+ touch_pressed_handler_ = touch_pressed_handler_->parent()) {
+ if (!touch_pressed_handler_->IsEnabled()) {
+ // Disabled views eat events but are treated as not handled by the
+ // the GestureManager.
+ status = TOUCH_STATUS_UNKNOWN;
+ break;
+ }
- // Make sure the focused view belongs to this RootView's view hierarchy.
- View* view = focus_manager->GetFocusedView();
- if (view && (view->GetRootView() == this))
- return view;
+ // See if this view wants to handle the touch
+ TouchEvent touch_event(e, this, touch_pressed_handler_);
+ status = touch_pressed_handler_->ProcessTouchEvent(touch_event);
-#if defined(OS_LINUX)
- if (view && NativeTextfieldViews::IsTextfieldViewsEnabled()) {
- // hack to deal with two root views.
- // should be fixed by eliminating one of them
- return view;
+ // If the touch didn't initiate a touch-sequence, then reset the touch event
+ // handler.
+ if (status != TOUCH_STATUS_START)
+ touch_pressed_handler_ = NULL;
+
+ // The view could have removed itself from the tree when handling
+ // OnTouchEvent(). So handle as per OnMousePressed. NB: we
+ // assume that the RootView itself cannot be so removed.
+ //
+ // NOTE: Don't return true here, because we don't want the frame to
+ // forward future events to us when there's no handler.
+ if (!touch_pressed_handler_)
+ break;
+
+ // If the view handled the event, leave touch_pressed_handler_ set and
+ // return true, which will cause subsequent drag/release events to get
+ // forwarded to that view.
+ if (status != TOUCH_STATUS_UNKNOWN) {
+ gesture_manager_->ProcessTouchEventForGesture(e, this, status);
+ return status;
+ }
}
-#endif
- return NULL;
-}
-FocusSearch* RootView::GetFocusSearch() {
- return &focus_search_;
-}
+ // Reset touch_pressed_handler_ to indicate that no processing is occurring.
+ touch_pressed_handler_ = NULL;
-FocusTraversable* RootView::GetFocusTraversableParent() {
- return focus_traversable_parent_;
+ // Give the touch event to the gesture manager.
+ gesture_manager_->ProcessTouchEventForGesture(e, this, status);
+ return status;
}
+#endif
-void RootView::SetFocusTraversableParent(FocusTraversable* focus_traversable) {
- DCHECK(focus_traversable != this);
- focus_traversable_parent_ = focus_traversable;
+bool RootView::IsVisibleInRootView() const {
+ return IsVisible();
}
-View* RootView::GetFocusTraversableParentView() {
- return focus_traversable_parent_view_;
+std::string RootView::GetClassName() const {
+ return kViewClassName;
}
-void RootView::SetFocusTraversableParentView(View* view) {
- focus_traversable_parent_view_ = view;
+AccessibilityTypes::Role RootView::GetAccessibleRole() {
+ return AccessibilityTypes::ROLE_APPLICATION;
}
-void RootView::NotifyNativeViewHierarchyChanged(bool attached,
- gfx::NativeView native_view) {
- PropagateNativeViewHierarchyChanged(attached, native_view, this);
-}
+void RootView::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
+ if (!is_add) {
+ if (!explicit_mouse_handler_ && mouse_pressed_handler_ == child) {
+ mouse_pressed_handler_ = NULL;
+ }
-bool RootView::ProcessKeyEvent(const KeyEvent& event) {
- bool consumed = false;
+ if (widget_)
+ widget_->ViewHierarchyChanged(is_add, parent, child);
- View* v = GetFocusedView();
- // Special case to handle right-click context menus triggered by the
- // keyboard.
- if (v && v->IsEnabled() && ((event.key_code() == ui::VKEY_APPS) ||
- (event.key_code() == ui::VKEY_F10 && event.IsShiftDown()))) {
- v->ShowContextMenu(v->GetKeyboardContextMenuLocation(), false);
- return true;
- }
- for (; v && v != this && !consumed; v = v->parent()) {
- consumed = (event.type() == ui::ET_KEY_PRESSED) ?
- v->OnKeyPressed(event) : v->OnKeyReleased(event);
- }
+ if (mouse_move_handler_ == child) {
+ mouse_move_handler_ = NULL;
+ }
- if (!consumed && default_keyboard_handler_) {
- consumed = (event.type() == ui::ET_KEY_PRESSED) ?
- default_keyboard_handler_->OnKeyPressed(event) :
- default_keyboard_handler_->OnKeyReleased(event);
- }
+ if (GetFocusedView() == child) {
+ FocusView(NULL);
+ }
- return consumed;
-}
+ if (child == drag_view_)
+ drag_view_ = NULL;
-bool RootView::ProcessMouseWheelEvent(const MouseWheelEvent& e) {
- View* v;
- bool consumed = false;
- if (GetFocusedView()) {
- for (v = GetFocusedView(); v && v != this && !consumed; v = v->parent())
- consumed = v->OnMouseWheel(e);
- }
+ if (default_keyboard_handler_ == child) {
+ default_keyboard_handler_ = NULL;
+ }
- if (!consumed && default_keyboard_handler_) {
- consumed = default_keyboard_handler_->OnMouseWheel(e);
+#if defined(TOUCH_UI)
+ if (touch_pressed_handler_) {
+ touch_pressed_handler_ = NULL;
+ }
+#endif
+
+ FocusManager* focus_manager = widget_->GetFocusManager();
+ // An unparanted RootView does not have a FocusManager.
+ if (focus_manager)
+ focus_manager->ViewRemoved(parent, child);
+
+ ViewStorage::GetInstance()->ViewRemoved(parent, child);
}
- return consumed;
}
-void RootView::SetDefaultKeyboardHandler(View* v) {
- default_keyboard_handler_ = v;
-}
+////////////////////////////////////////////////////////////////////////////////
+// RootView, protected:
-bool RootView::IsVisibleInRootView() const {
- return IsVisible();
-}
+// Size and disposition --------------------------------------------------------
void RootView::ViewBoundsChanged(View* view, bool size_changed,
bool position_changed) {
@@ -759,43 +739,45 @@ void RootView::UnregisterViewForVisibleBoundsNotification(View* view) {
}
}
-void RootView::SetMouseLocationAndFlags(const MouseEvent& e) {
- last_mouse_event_flags_ = e.flags();
- last_mouse_event_x_ = e.x();
- last_mouse_event_y_ = e.y();
-}
-
-std::string RootView::GetClassName() const {
- return kViewClassName;
-}
-
-void RootView::ClearPaintRect() {
- invalid_rect_.SetRect(0, 0, 0, 0);
-
- // This painting has been done. Reset the urgent flag.
- invalid_rect_urgent_ = false;
+// Coordinate conversion -------------------------------------------------------
- // If a pending_paint_task_ does Run(), we don't need to do anything.
- paint_task_needed_ = false;
-}
-
-// static
-void RootView::EnableDebugPaint() {
- debug_paint_enabled_ = true;
+bool RootView::ConvertPointToMouseHandler(const gfx::Point& l,
+ gfx::Point* p) {
+ //
+ // If the mouse_handler was set explicitly, we need to keep
+ // sending events even if it was reparented in a different
+ // window. (a non explicit mouse handler is automatically
+ // cleared when the control is removed from the hierarchy)
+ if (explicit_mouse_handler_) {
+ if (mouse_pressed_handler_->GetWidget()) {
+ *p = l;
+ ConvertPointToScreen(this, p);
+ ConvertPointToView(NULL, mouse_pressed_handler_, p);
+ } else {
+ // If the mouse_pressed_handler_ is not connected, we send the
+ // event in screen coordinate system
+ *p = l;
+ ConvertPointToScreen(this, p);
+ return true;
+ }
+ } else {
+ *p = l;
+ ConvertPointToView(this, mouse_pressed_handler_, p);
+ }
+ return true;
}
-/////////////////////////////////////////////////////////////////////////////
-//
-// RootView - accessibility
-//
-/////////////////////////////////////////////////////////////////////////////
-
-AccessibilityTypes::Role RootView::GetAccessibleRole() {
- return AccessibilityTypes::ROLE_APPLICATION;
-}
+// Input -----------------------------------------------------------------------
-View* RootView::GetDragView() {
- return drag_view_;
+void RootView::UpdateCursor(const MouseEvent& e) {
+ gfx::NativeCursor cursor = NULL;
+ View* v = GetViewForPoint(e.location());
+ if (v && v != this) {
+ gfx::Point l(e.location());
+ View::ConvertPointToView(this, v, &l);
+ cursor = v->GetCursorForPoint(e.type(), l);
+ }
+ SetActiveCursor(cursor);
}
void RootView::SetActiveCursor(gfx::NativeCursor cursor) {
@@ -822,4 +804,16 @@ void RootView::SetActiveCursor(gfx::NativeCursor cursor) {
#endif
}
+void RootView::SetMouseLocationAndFlags(const MouseEvent& e) {
+ last_mouse_event_flags_ = e.flags();
+ last_mouse_event_x_ = e.x();
+ last_mouse_event_y_ = e.y();
+}
+
+// Drag and drop ---------------------------------------------------------------
+
+View* RootView::GetDragView() {
+ return drag_view_;
+}
+
} // namespace views
diff --git a/views/widget/root_view.h b/views/widget/root_view.h
index 680b8a5..ad7273c 100644
--- a/views/widget/root_view.h
+++ b/views/widget/root_view.h
@@ -21,55 +21,55 @@ namespace views {
class PaintTask;
class Widget;
-
#if defined(TOUCH_UI)
class GestureManager;
#endif
-/////////////////////////////////////////////////////////////////////////////
-//
+////////////////////////////////////////////////////////////////////////////////
// RootView class
//
-// The RootView is the root of a View hierarchy. A RootView is always the
-// first and only child of a Widget.
+// The RootView is the root of a View hierarchy. A RootView is attached to a
+// Widget. The Widget is responsible for receiving events from the host
+// environment, converting them to views-compatible events and then forwarding
+// them to the RootView for propagation into the View hierarchy.
//
-// The RootView manages the View hierarchy's interface with the Widget
-// and also maintains the current invalid rect - the region that needs
-// repainting.
+// A RootView can have only one child, called its "Contents View" which is
+// sized to fill the bounds of the RootView (and hence the client area of the
+// Widget). Call SetContentsView() after the associated Widget has been
+// initialized to attach the contents view to the RootView.
+// TODO(beng): Enforce no other callers to AddChildView/tree functions by
+// overriding those methods as private here.
+// TODO(beng): Get rid of the scheduled paint rect tracking that this class
+// does - it is superfluous to the underlying environment's invalid
+// rect tracking.
+// TODO(beng): Move to internal namespace and remove accessors from
+// View/Widget.
+// TODO(beng): Clean up API further, make WidgetImpl a friend.
//
-/////////////////////////////////////////////////////////////////////////////
class RootView : public View,
public FocusTraversable {
public:
static const char kViewClassName[];
+ // Creation and lifetime -----------------------------------------------------
explicit RootView(Widget* widget);
-
virtual ~RootView();
+ // Tree operations -----------------------------------------------------------
+
// Sets the "contents view" of the RootView. This is the single child view
// that is responsible for laying out the contents of the widget.
void SetContentsView(View* contents_view);
- // Layout and Painting functions
-
- // Overridden from View to implement paint scheduling.
- virtual void SchedulePaintInRect(const gfx::Rect& r, bool urgent);
-
- // Convenience to schedule the whole view
- virtual void SchedulePaint();
-
- // Paint this RootView and its child Views.
- virtual void ProcessPaint(gfx::Canvas* canvas);
+ // Called when parent of the host changed.
+ void NotifyNativeViewHierarchyChanged(bool attached,
+ gfx::NativeView native_view);
- // If the invalid rect is non-empty and there is a pending paint the RootView
- // is painted immediately. This is internally invoked as the result of
- // invoking SchedulePaint.
- virtual void PaintNow();
+ // Painting ------------------------------------------------------------------
// Whether or not this View needs repainting. If |urgent| is true, this method
// returns whether this root view needs to paint as soon as possible.
- virtual bool NeedsPainting(bool urgent);
+ bool NeedsPainting(bool urgent);
// Invoked by the Widget to discover what rectangle should be painted.
const gfx::Rect& GetScheduledPaintRect();
@@ -77,30 +77,24 @@ class RootView : public View,
// Returns the region scheduled to paint clipped to the RootViews bounds.
gfx::Rect GetScheduledPaintRectConstrainedToSize();
- // Tree functions
-
- // Get the Widget that hosts this View.
- virtual const Widget* GetWidget() const;
- virtual Widget* GetWidget();
+ // Clears the region that is schedule to be painted. You nearly never need
+ // to invoke this. This is primarily intended for Widgets.
+ void ClearPaintRect();
- // Public API for broadcasting theme change notifications to this View
- // hierarchy.
- void NotifyThemeChanged();
+ // TODO(beng): These should be handled at the NativeWidget level. NativeWidget
+ // should crack and create a gfx::Canvas which is passed to a
+ // paint processing routine here.
+#if defined(OS_WIN)
+ // Invoked from the Widget to service a WM_PAINT call.
+ void OnPaint(HWND hwnd);
+#elif defined(OS_LINUX)
+ void OnPaint(GdkEventExpose* event);
+#endif
- // Public API for broadcasting locale change notifications to this View
- // hierarchy.
- void NotifyLocaleChanged();
+ // Enables debug painting. See |debug_paint_enabled_| for details.
+ static void EnableDebugPaint();
- // The following event methods are overridden to propagate event to the
- // control tree
- virtual bool OnMousePressed(const MouseEvent& e);
- virtual bool OnMouseDragged(const MouseEvent& e);
- virtual void OnMouseReleased(const MouseEvent& e, bool canceled);
- virtual void OnMouseMoved(const MouseEvent& e);
- virtual void SetMouseHandler(View* new_mouse_handler);
-#if defined(TOUCH_UI)
- virtual TouchStatus OnTouchEvent(const TouchEvent& e);
-#endif
+ // Input ---------------------------------------------------------------------
// Invoked By the Widget if the mouse drag is interrupted by
// the system. Invokes OnMouseReleased with a value of true for canceled.
@@ -110,13 +104,6 @@ class RootView : public View,
// bounds.
virtual void ProcessOnMouseExited();
- // Make the provided view focused. Also make sure that our Widget is focused.
- void FocusView(View* view);
-
- // Returns the View in this RootView hierarchy that has the focus, or NULL if
- // no View currently has the focus.
- View* GetFocusedView();
-
// Process a key event. Send the event to the focused view and up the focus
// path, and finally to the default keyboard handler, until someone consumes
// it. Returns whether anyone consumed the event.
@@ -130,48 +117,11 @@ class RootView : public View,
// this a list if needed.
void SetDefaultKeyboardHandler(View* v);
- // Set whether this root view should focus the corresponding hwnd
- // when an unprocessed mouse event occurs.
- void SetFocusOnMousePressed(bool f);
-
// Process a mousewheel event. Return true if the event was processed
// and false otherwise.
// MouseWheel events are sent on the focus path.
virtual bool ProcessMouseWheelEvent(const MouseWheelEvent& e);
- // Overridden to handle special root view case.
- virtual bool IsVisibleInRootView() const;
-
- // FocusTraversable implementation.
- virtual FocusSearch* GetFocusSearch();
- virtual FocusTraversable* GetFocusTraversableParent();
- virtual View* GetFocusTraversableParentView();
-
- // Used to set the FocusTraversable parent after the view has been created
- // (typically when the hierarchy changes and this RootView is added/removed).
- virtual void SetFocusTraversableParent(FocusTraversable* focus_traversable);
-
- // Used to set the View parent after the view has been created.
- virtual void SetFocusTraversableParentView(View* view);
-
- // Called when parent of the host changed.
- void NotifyNativeViewHierarchyChanged(bool attached,
- gfx::NativeView native_view);
-
- // Returns the name of this class: views/RootView
- virtual std::string GetClassName() const;
-
- // Clears the region that is schedule to be painted. You nearly never need
- // to invoke this. This is primarily intended for Widgets.
- void ClearPaintRect();
-
-#if defined(OS_WIN)
- // Invoked from the Widget to service a WM_PAINT call.
- void OnPaint(HWND hwnd);
-#elif defined(OS_LINUX)
- void OnPaint(GdkEventExpose* event);
-#endif
-
// Starts a drag operation for the specified view. This blocks until done.
// If the view has not been deleted during the drag, OnDragDone is invoked
// on the view.
@@ -180,31 +130,74 @@ class RootView : public View,
const OSExchangeData& data,
int operation);
- // Accessibility accessors/mutators, overridden from View.
- virtual AccessibilityTypes::Role GetAccessibleRole();
-
#if defined(TOUCH_UI) && defined(UNIT_TEST)
// For unit testing purposes, we use this method to set a mock
// GestureManager
void SetGestureManager(GestureManager* g) { gesture_manager_ = g; }
#endif
- // Enables debug painting. See |debug_paint_enabled_| for details.
- static void EnableDebugPaint();
+ // Focus ---------------------------------------------------------------------
- protected:
+ // Make the provided view focused. Also make sure that our Widget is focused.
+ void FocusView(View* view);
- // Overridden to properly reset our event propagation member
- // variables when a child is removed
- virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child);
+ // Returns the View in this RootView hierarchy that has the focus, or NULL if
+ // no View currently has the focus.
+ View* GetFocusedView();
+
+ // Set whether this root view should focus the corresponding hwnd
+ // when an unprocessed mouse event occurs.
+ void SetFocusOnMousePressed(bool f);
+
+ // Used to set the FocusTraversable parent after the view has been created
+ // (typically when the hierarchy changes and this RootView is added/removed).
+ virtual void SetFocusTraversableParent(FocusTraversable* focus_traversable);
+
+ // Used to set the View parent after the view has been created.
+ virtual void SetFocusTraversableParentView(View* view);
+
+ // System events -------------------------------------------------------------
+
+ // Public API for broadcasting theme change notifications to this View
+ // hierarchy.
+ void NotifyThemeChanged();
+
+ // Public API for broadcasting locale change notifications to this View
+ // hierarchy.
+ void NotifyLocaleChanged();
+
+ // Overridden from FocusTraversable:
+ virtual FocusSearch* GetFocusSearch();
+ virtual FocusTraversable* GetFocusTraversableParent();
+ virtual View* GetFocusTraversableParentView();
+ // Overridden from View:
+ virtual void SchedulePaintInRect(const gfx::Rect& r, bool urgent);
+ virtual void ProcessPaint(gfx::Canvas* canvas);
+ virtual void PaintNow();
+ virtual const Widget* GetWidget() const;
+ virtual Widget* GetWidget();
+ virtual bool OnMousePressed(const MouseEvent& e);
+ virtual bool OnMouseDragged(const MouseEvent& e);
+ virtual void OnMouseReleased(const MouseEvent& e, bool canceled);
+ virtual void OnMouseMoved(const MouseEvent& e);
+ virtual void SetMouseHandler(View* new_mouse_handler);
+#if defined(TOUCH_UI)
+ virtual TouchStatus OnTouchEvent(const TouchEvent& e);
+#endif
+ virtual bool IsVisibleInRootView() const;
+ virtual std::string GetClassName() const;
+ virtual AccessibilityTypes::Role GetAccessibleRole();
+
+ protected:
+ // Overridden from View:
+ virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child);
#ifndef NDEBUG
virtual bool IsProcessingPaint() const { return is_processing_paint_; }
#endif
private:
friend class View;
- friend class PaintTask;
#if defined(TOUCH_UI)
// Required so the GestureManager can call the Process* entry points
@@ -212,83 +205,50 @@ class RootView : public View,
friend class GestureManager;
#endif
- RootView();
+ // Size and disposition ------------------------------------------------------
+
+ // Notification that size and/or position of a view has changed. This
+ // notifies the appropriate views.
+ void ViewBoundsChanged(View* view, bool size_changed, bool position_changed);
+
+ // Registers a view for notification when the visible bounds relative to the
+ // root of a view changes.
+ void RegisterViewForVisibleBoundsNotification(View* view);
+ void UnregisterViewForVisibleBoundsNotification(View* view);
+
+ // Coordinate conversion -----------------------------------------------------
// Convert a point to our current mouse handler. Returns false if the
// mouse handler is not connected to a Widget. In that case, the
// conversion cannot take place and *p is unchanged
bool ConvertPointToMouseHandler(const gfx::Point& l, gfx::Point *p);
+ // Input ---------------------------------------------------------------------
+
// 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.
void UpdateCursor(const MouseEvent& e);
- // Notification that size and/or position of a view has changed. This
- // notifies the appropriate views.
- void ViewBoundsChanged(View* view, bool size_changed, bool position_changed);
-
- // Registers a view for notification when the visible bounds relative to the
- // root of a view changes.
- void RegisterViewForVisibleBoundsNotification(View* view);
- void UnregisterViewForVisibleBoundsNotification(View* view);
-
- // Returns the next focusable view or view containing a FocusTraversable (NULL
- // if none was found), starting at the starting_view.
- // check_starting_view, can_go_up and can_go_down controls the traversal of
- // the views hierarchy.
- // skip_group_id specifies a group_id, -1 means no group. All views from a
- // group are traversed in one pass.
- View* FindNextFocusableViewImpl(View* starting_view,
- bool check_starting_view,
- bool can_go_up,
- bool can_go_down,
- int skip_group_id,
- FocusTraversable** focus_traversable,
- View** focus_traversable_view);
-
- // Same as FindNextFocusableViewImpl but returns the previous focusable view.
- View* FindPreviousFocusableViewImpl(View* starting_view,
- bool check_starting_view,
- bool can_go_up,
- bool can_go_down,
- int skip_group_id,
- FocusTraversable** focus_traversable,
- View** focus_traversable_view);
-
- // Convenience method that returns true if a view is focusable and does not
- // belong to the specified group.
- bool IsViewFocusableCandidate(View* v, int skip_group_id);
-
- // Returns the view selected for the group of the selected view. If the view
- // does not belong to a group or if no view is selected in the group, the
- // specified view is returned.
- static View* FindSelectedViewForGroup(View* view);
+ // Sets the current cursor, or resets it to the last one if NULL is provided.
+ void SetActiveCursor(gfx::NativeCursor cursor);
// Updates the last_mouse_* fields from e.
void SetMouseLocationAndFlags(const MouseEvent& e);
+ // Drag and drop -------------------------------------------------------------
+
// If a view is dragging, this returns it. Otherwise returns NULL.
View* GetDragView();
- // Sets the current cursor, or resets it to the last one if NULL is provided.
- void SetActiveCursor(gfx::NativeCursor cursor);
+ //////////////////////////////////////////////////////////////////////////////
- // The view currently handing down - drag - up
- View* mouse_pressed_handler_;
-
- // The view currently handling enter / exit
- View* mouse_move_handler_;
-
- // The last view to handle a mouse click, so that we can determine if
- // a double-click lands on the same view as its single-click part.
- View* last_click_handler_;
+ // Tree operations -----------------------------------------------------------
// The host Widget
Widget* widget_;
- // The focus search algorithm.
- FocusSearch focus_search_;
+ // Painting ------------------------------------------------------------------
// The rectangle that should be painted
gfx::Rect invalid_rect_;
@@ -304,6 +264,27 @@ class RootView : public View,
// required.
bool paint_task_needed_;
+#ifndef NDEBUG
+ // True if we're currently processing paint.
+ bool is_processing_paint_;
+#endif
+
+ // True to enable debug painting. Enabling causes the damaged
+ // region to be painted to flash in red.
+ static bool debug_paint_enabled_;
+
+ // Input ---------------------------------------------------------------------
+
+ // The view currently handing down - drag - up
+ View* mouse_pressed_handler_;
+
+ // The view currently handling enter / exit
+ View* mouse_move_handler_;
+
+ // The last view to handle a mouse click, so that we can determine if
+ // a double-click lands on the same view as its single-click part.
+ View* last_click_handler_;
+
// true if mouse_handler_ has been explicitly set
bool explicit_mouse_handler_;
@@ -313,6 +294,25 @@ class RootView : public View,
// Default keyboard handler
View* default_keyboard_handler_;
+ // Last position/flag of a mouse press/drag. Used if capture stops and we need
+ // to synthesize a release.
+ int last_mouse_event_flags_;
+ int last_mouse_event_x_;
+ int last_mouse_event_y_;
+
+#if defined(TOUCH_UI)
+ // The gesture_manager_ for this.
+ GestureManager* gesture_manager_;
+
+ // The view currently handling touch events.
+ View* touch_pressed_handler_;
+#endif
+
+ // Focus ---------------------------------------------------------------------
+
+ // The focus search algorithm.
+ FocusSearch focus_search_;
+
// Whether this root view should make our hwnd focused
// when an unprocessed mouse press event occurs
bool focus_on_mouse_pressed_;
@@ -324,12 +324,6 @@ class RootView : public View,
// Whether this root view belongs to the current active window.
// bool activated_;
- // Last position/flag of a mouse press/drag. Used if capture stops and we need
- // to synthesize a release.
- int last_mouse_event_flags_;
- int last_mouse_event_x_;
- int last_mouse_event_y_;
-
// The parent FocusTraversable, used for focus traversal.
FocusTraversable* focus_traversable_parent_;
@@ -337,6 +331,8 @@ class RootView : public View,
// wrapped inside native components, and is used for the focus traversal.
View* focus_traversable_parent_view_;
+ // Drag and drop -------------------------------------------------------------
+
// Tracks drag state for a view.
View::DragInfo drag_info;
@@ -344,24 +340,7 @@ class RootView : public View,
// view the drag started from.
View* drag_view_;
-#if defined(TOUCH_UI)
- // The gesture_manager_ for this.
- GestureManager* gesture_manager_;
-
- // The view currently handling touch events.
- View* touch_pressed_handler_;
-#endif
-
-#ifndef NDEBUG
- // True if we're currently processing paint.
- bool is_processing_paint_;
-#endif
-
- // True to enable debug painting. Enabling causes the damaged
- // region to be painted to flash in red.
- static bool debug_paint_enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(RootView);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(RootView);
};
} // namespace views