Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "views/view.h" | 5 #include "views/view.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/debug/trace_event.h" | |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 12 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 13 #include "third_party/skia/include/core/SkRect.h" | 14 #include "third_party/skia/include/core/SkRect.h" |
| 14 #include "ui/base/accessibility/accessibility_types.h" | 15 #include "ui/base/accessibility/accessibility_types.h" |
| 15 #include "ui/base/dragdrop/drag_drop_types.h" | 16 #include "ui/base/dragdrop/drag_drop_types.h" |
| 16 #include "ui/gfx/canvas_skia.h" | 17 #include "ui/gfx/canvas_skia.h" |
| 17 #include "ui/gfx/compositor/compositor.h" | 18 #include "ui/gfx/compositor/compositor.h" |
| 18 #include "ui/gfx/compositor/layer.h" | 19 #include "ui/gfx/compositor/layer.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 34 #include "views/accessibility/native_view_accessibility_win.h" | 35 #include "views/accessibility/native_view_accessibility_win.h" |
| 35 #endif | 36 #endif |
| 36 #if defined(OS_LINUX) | 37 #if defined(OS_LINUX) |
| 37 #include "ui/base/gtk/scoped_handle_gtk.h" | 38 #include "ui/base/gtk/scoped_handle_gtk.h" |
| 38 #endif | 39 #endif |
| 39 | 40 |
| 40 namespace { | 41 namespace { |
| 41 | 42 |
| 42 // Whether to use accelerated compositing when necessary (e.g. when a view has a | 43 // Whether to use accelerated compositing when necessary (e.g. when a view has a |
| 43 // transformation). | 44 // transformation). |
| 44 #if !defined(OS_CHROMEOS) | 45 //#if !defined(OS_CHROMEOS) |
|
Jói
2011/06/30 19:50:50
Should these commented-out lines be removed altoge
| |
| 45 bool use_acceleration_when_possible = true; | 46 bool use_acceleration_when_possible = true; |
| 46 #else | 47 //#else |
| 47 bool use_acceleration_when_possible = false; | 48 //bool use_acceleration_when_possible = false; |
| 48 #endif | 49 //#endif |
| 49 | 50 |
| 50 // Saves the drawing state, and restores the state when going out of scope. | 51 // Saves the drawing state, and restores the state when going out of scope. |
| 51 class ScopedCanvas { | 52 class ScopedCanvas { |
| 52 public: | 53 public: |
| 53 explicit ScopedCanvas(gfx::Canvas* canvas) : canvas_(canvas) { | 54 explicit ScopedCanvas(gfx::Canvas* canvas) : canvas_(canvas) { |
| 54 if (canvas_) | 55 if (canvas_) |
| 55 canvas_->Save(); | 56 canvas_->Save(); |
| 56 } | 57 } |
| 57 ~ScopedCanvas() { | 58 ~ScopedCanvas() { |
| 58 if (canvas_) | 59 if (canvas_) |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 clip_y_(0.0), | 108 clip_y_(0.0), |
| 108 needs_layout_(true), | 109 needs_layout_(true), |
| 109 flip_canvas_on_paint_for_rtl_ui_(false), | 110 flip_canvas_on_paint_for_rtl_ui_(false), |
| 110 accelerator_registration_delayed_(false), | 111 accelerator_registration_delayed_(false), |
| 111 accelerator_focus_manager_(NULL), | 112 accelerator_focus_manager_(NULL), |
| 112 registered_accelerator_count_(0), | 113 registered_accelerator_count_(0), |
| 113 next_focusable_view_(NULL), | 114 next_focusable_view_(NULL), |
| 114 previous_focusable_view_(NULL), | 115 previous_focusable_view_(NULL), |
| 115 focusable_(false), | 116 focusable_(false), |
| 116 accessibility_focusable_(false), | 117 accessibility_focusable_(false), |
| 118 painting_enabled_(true), | |
| 117 context_menu_controller_(NULL), | 119 context_menu_controller_(NULL), |
| 118 drag_controller_(NULL) { | 120 drag_controller_(NULL) { |
| 119 } | 121 } |
| 120 | 122 |
| 121 View::~View() { | 123 View::~View() { |
| 122 if (parent_) | 124 if (parent_) |
| 123 parent_->RemoveChildView(this); | 125 parent_->RemoveChildView(this); |
| 124 | 126 |
| 125 for (Views::const_iterator i(children_.begin()); i != children_.end(); ++i) { | 127 for (Views::const_iterator i(children_.begin()); i != children_.end(); ++i) { |
| 126 (*i)->parent_ = NULL; | 128 (*i)->parent_ = NULL; |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 } | 380 } |
| 379 | 381 |
| 380 int View::GetHeightForWidth(int w) { | 382 int View::GetHeightForWidth(int w) { |
| 381 if (layout_manager_.get()) | 383 if (layout_manager_.get()) |
| 382 return layout_manager_->GetPreferredHeightForWidth(this, w); | 384 return layout_manager_->GetPreferredHeightForWidth(this, w); |
| 383 return GetPreferredSize().height(); | 385 return GetPreferredSize().height(); |
| 384 } | 386 } |
| 385 | 387 |
| 386 void View::SetVisible(bool visible) { | 388 void View::SetVisible(bool visible) { |
| 387 if (visible != visible_) { | 389 if (visible != visible_) { |
| 390 visible_ = visible; | |
| 388 // If the tab is currently visible, schedule paint to refresh parent. | 391 // If the tab is currently visible, schedule paint to refresh parent. |
| 389 if (visible_) | 392 if (visible_) |
| 390 SchedulePaint(); | 393 SchedulePaint(); |
| 391 else | 394 else |
| 392 DestroyLayerRecurse(); | 395 DestroyLayerRecurse(); |
| 393 | 396 |
| 394 visible_ = visible; | 397 // This notifies all sub-views recursively. |
| 398 PropagateVisibilityNotifications(this, visible_); | |
| 395 | 399 |
| 396 // This notifies all sub-views recursively. | 400 // If we are newly visible, schedule paint. |
| 397 PropagateVisibilityNotifications(this, visible_); | |
| 398 | |
| 399 // If we are newly visible, schedule paint. | |
| 400 if (visible_) | 401 if (visible_) |
| 401 SchedulePaint(); | 402 SchedulePaint(); |
| 402 } | 403 } |
| 403 } | 404 } |
| 404 | 405 |
| 405 bool View::IsVisible() const { | 406 bool View::IsVisible() const { |
| 406 return visible_; | 407 return visible_; |
| 407 } | 408 } |
| 408 | 409 |
| 409 bool View::IsVisibleInRootView() const { | 410 bool View::IsVisibleInRootView() const { |
| 410 return IsVisible() && parent_ ? parent_->IsVisibleInRootView() : false; | 411 return IsVisible() && parent_ ? parent_->IsVisibleInRootView() : false; |
| 411 } | 412 } |
| 412 | 413 |
| 413 void View::SetEnabled(bool enabled) { | 414 void View::SetEnabled(bool enabled) { |
| 414 if (enabled != enabled_) { | 415 if (enabled != enabled_) { |
| 415 enabled_ = enabled; | 416 enabled_ = enabled; |
| 416 OnEnabledChanged(); | 417 OnEnabledChanged(); |
| 417 } | 418 } |
| 418 } | 419 } |
| 419 | 420 |
| 420 bool View::IsEnabled() const { | 421 bool View::IsEnabled() const { |
| 421 return enabled_; | 422 return enabled_; |
| 422 } | 423 } |
| 423 | 424 |
| 424 void View::OnEnabledChanged() { | 425 void View::OnEnabledChanged() { |
| 425 SchedulePaint(); | 426 SchedulePaint(); |
| 426 } | 427 } |
| 427 | 428 |
| 429 void View::SetPaintingEnabled(bool enabled) { | |
| 430 painting_enabled_ = enabled; | |
| 431 } | |
| 432 | |
| 433 bool View::IsPaintingEnabled() const { | |
| 434 return painting_enabled_; | |
| 435 } | |
| 436 | |
| 428 // Transformations ------------------------------------------------------------- | 437 // Transformations ------------------------------------------------------------- |
| 429 | 438 |
| 430 const ui::Transform& View::GetTransform() const { | 439 const ui::Transform& View::GetTransform() const { |
| 431 static const ui::Transform* no_op = new ui::Transform; | 440 static const ui::Transform* no_op = new ui::Transform; |
| 432 return transform() ? *transform() : *no_op; | 441 return transform() ? *transform() : *no_op; |
| 433 } | 442 } |
| 434 | 443 |
| 435 void View::SetTransform(const ui::Transform& transform) { | 444 void View::SetTransform(const ui::Transform& transform) { |
| 436 if (!transform.HasChange()) { | 445 if (!transform.HasChange()) { |
| 437 if (!layer_helper_.get() || !this->transform()) | 446 if (!layer_helper_.get() || !this->transform()) |
| 438 return; | 447 return; |
| 439 layer_helper_->SetTransform(transform); | 448 layer_helper_->SetTransform(transform); |
| 440 | 449 |
| 441 if (!ShouldPaintToLayer()) | 450 if (!ShouldPaintToLayer()) |
| 442 DestroyLayerAndReparent(); | 451 DestroyLayerAndReparent(); |
| 443 else if (layer()) | 452 else if (layer()) |
| 444 layer_helper_->property_setter()->SetTransform(layer(), transform); | 453 layer_helper_->property_setter()->SetTransform(layer(), transform); |
| 445 | 454 |
| 446 SchedulePaint(); | 455 SchedulePaint(); |
| 447 } else { | 456 } else { |
| 448 // Make sure if the view didn't have its own texture and was painting onto | |
| 449 // something else, that gets refreshed too. | |
| 450 if (!ShouldPaintToLayer()) | |
| 451 MarkLayerDirty(); | |
| 452 | |
| 453 if (!layer_helper_.get()) | 457 if (!layer_helper_.get()) |
| 454 layer_helper_.reset(new internal::LayerHelper()); | 458 layer_helper_.reset(new internal::LayerHelper()); |
| 455 layer_helper_->SetTransform(transform); | 459 layer_helper_->SetTransform(transform); |
| 456 if (!layer()) { | 460 if (!layer()) { |
| 457 CreateLayer(); | 461 CreateLayer(); |
| 458 SchedulePaint(); | 462 SchedulePaint(); |
| 459 } else { | 463 } else { |
| 460 layer_helper_->property_setter()->SetTransform(layer(), transform); | 464 layer_helper_->property_setter()->SetTransform(layer(), transform); |
| 461 // We have a layer. When the transform changes and the layer is up to | 465 ScheduleComposite(); |
| 462 // date we don't want to SchedulePaint as it'll trigger painting to the | |
| 463 // layer. Instead we tell the Widget to paint, which makes the | |
| 464 // compositor draw using the existing layer. | |
| 465 // We schedule paint the complete bounds as compositor generally don't | |
| 466 // support partial painting. | |
| 467 Widget* widget = GetWidget(); | |
| 468 if (widget) | |
| 469 widget->SchedulePaintInRect(widget->GetRootView()->bounds()); | |
| 470 } | 466 } |
| 471 } | 467 } |
| 472 } | 468 } |
| 473 | 469 |
| 474 void View::SetPaintToLayer(bool value) { | 470 void View::SetPaintToLayer(bool value) { |
| 475 bool paint_to_layer = layer_helper_.get() && layer_helper_->paint_to_layer(); | 471 bool paint_to_layer = layer_helper_.get() && layer_helper_->paint_to_layer(); |
| 476 if (value == paint_to_layer) | 472 if (value == paint_to_layer) |
| 477 return; | 473 return; |
| 478 | 474 |
| 479 if (value) { | 475 if (value) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 return base::i18n::IsRTL() ? width() - x : x; | 521 return base::i18n::IsRTL() ? width() - x : x; |
| 526 } | 522 } |
| 527 | 523 |
| 528 int View::GetMirroredXWithWidthInView(int x, int w) const { | 524 int View::GetMirroredXWithWidthInView(int x, int w) const { |
| 529 return base::i18n::IsRTL() ? width() - x - w : x; | 525 return base::i18n::IsRTL() ? width() - x - w : x; |
| 530 } | 526 } |
| 531 | 527 |
| 532 // Layout ---------------------------------------------------------------------- | 528 // Layout ---------------------------------------------------------------------- |
| 533 | 529 |
| 534 void View::Layout() { | 530 void View::Layout() { |
| 531 TRACE_EVENT0("View", "Layout"); | |
| 535 needs_layout_ = false; | 532 needs_layout_ = false; |
| 536 | 533 |
| 537 // If we have a layout manager, let it handle the layout for us. | 534 // If we have a layout manager, let it handle the layout for us. |
| 538 if (layout_manager_.get()) | 535 if (layout_manager_.get()) |
| 539 layout_manager_->Layout(this); | 536 layout_manager_->Layout(this); |
| 540 | 537 |
| 541 // Make sure to propagate the Layout() call to any children that haven't | 538 // Make sure to propagate the Layout() call to any children that haven't |
| 542 // received it yet through the layout manager and need to be laid out. This | 539 // received it yet through the layout manager and need to be laid out. This |
| 543 // is needed for the case when the child requires a layout but its bounds | 540 // is needed for the case when the child requires a layout but its bounds |
| 544 // weren't changed by the layout manager. If there is no layout manager, we | 541 // weren't changed by the layout manager. If there is no layout manager, we |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 643 | 640 |
| 644 // static | 641 // static |
| 645 void View::ConvertPointToWidget(const View* src, gfx::Point* p) { | 642 void View::ConvertPointToWidget(const View* src, gfx::Point* p) { |
| 646 DCHECK(src); | 643 DCHECK(src); |
| 647 DCHECK(p); | 644 DCHECK(p); |
| 648 | 645 |
| 649 src->ConvertPointForAncestor(NULL, p); | 646 src->ConvertPointForAncestor(NULL, p); |
| 650 } | 647 } |
| 651 | 648 |
| 652 // static | 649 // static |
| 650 void View::ConvertRectToWidget(const View* src, gfx::Rect* rect) { | |
| 651 DCHECK(src); | |
| 652 DCHECK(rect); | |
| 653 | |
| 654 src->ConvertRectForAncestor(NULL, rect); | |
| 655 } | |
| 656 | |
| 657 // static | |
| 653 void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) { | 658 void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) { |
| 654 DCHECK(dest); | 659 DCHECK(dest); |
| 655 DCHECK(p); | 660 DCHECK(p); |
| 656 | 661 |
| 657 dest->ConvertPointFromAncestor(NULL, p); | 662 dest->ConvertPointFromAncestor(NULL, p); |
| 658 } | 663 } |
| 659 | 664 |
| 660 // static | 665 // static |
| 661 void View::ConvertPointToScreen(const View* src, gfx::Point* p) { | 666 void View::ConvertPointToScreen(const View* src, gfx::Point* p) { |
| 662 DCHECK(src); | 667 DCHECK(src); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 686 } | 691 } |
| 687 | 692 |
| 688 void View::SchedulePaintInRect(const gfx::Rect& rect) { | 693 void View::SchedulePaintInRect(const gfx::Rect& rect) { |
| 689 if (!IsVisible()) | 694 if (!IsVisible()) |
| 690 return; | 695 return; |
| 691 | 696 |
| 692 MarkLayerDirty(); | 697 MarkLayerDirty(); |
| 693 SchedulePaintInternal(rect); | 698 SchedulePaintInternal(rect); |
| 694 } | 699 } |
| 695 | 700 |
| 701 void View::ScheduleComposite() { | |
| 702 ScheduleCompositeInRect(GetLocalBounds()); | |
| 703 } | |
| 704 | |
| 705 void View::ScheduleCompositeInRect(const gfx::Rect& rect) { | |
| 706 if (!IsVisible()) | |
| 707 return; | |
| 708 | |
| 709 SchedulePaintInternal(rect); | |
| 710 } | |
| 711 | |
| 696 void View::Paint(gfx::Canvas* canvas) { | 712 void View::Paint(gfx::Canvas* canvas) { |
| 697 if (!IsVisible()) | 713 TRACE_EVENT0("View", "Paint"); |
| 714 if (!IsVisible() || !IsPaintingEnabled()) | |
| 698 return; | 715 return; |
| 699 | 716 |
| 700 ScopedCanvas scoped_canvas(NULL); | 717 ScopedCanvas scoped_canvas(NULL); |
| 701 scoped_ptr<gfx::Canvas> layer_canvas; | 718 scoped_ptr<gfx::Canvas> layer_canvas; |
| 702 gfx::Rect layer_rect; | 719 gfx::Rect layer_rect; |
| 703 | 720 |
| 704 if (layer()) { | 721 if (layer()) { |
| 705 gfx::Rect dirty_rect; | 722 gfx::Rect dirty_rect; |
| 706 if (!layer_helper_->clip_rect().IsEmpty()) { | 723 if (!layer_helper_->clip_rect().IsEmpty()) { |
| 707 dirty_rect = layer_helper_->clip_rect(); | 724 dirty_rect = layer_helper_->clip_rect(); |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1162 } | 1179 } |
| 1163 | 1180 |
| 1164 void View::OnPaintFocusBorder(gfx::Canvas* canvas) { | 1181 void View::OnPaintFocusBorder(gfx::Canvas* canvas) { |
| 1165 if ((IsFocusable() || IsAccessibilityFocusableInRootView()) && HasFocus()) | 1182 if ((IsFocusable() || IsAccessibilityFocusableInRootView()) && HasFocus()) |
| 1166 canvas->DrawFocusRect(0, 0, width(), height()); | 1183 canvas->DrawFocusRect(0, 0, width(), height()); |
| 1167 } | 1184 } |
| 1168 | 1185 |
| 1169 // Accelerated Painting -------------------------------------------------------- | 1186 // Accelerated Painting -------------------------------------------------------- |
| 1170 | 1187 |
| 1171 void View::PaintComposite() { | 1188 void View::PaintComposite() { |
| 1189 TRACE_EVENT0("View", "PaintComposite"); | |
| 1172 if (!IsVisible()) | 1190 if (!IsVisible()) |
| 1173 return; | 1191 return; |
| 1174 | 1192 |
| 1175 if (layer()) { | 1193 if (layer()) { |
| 1176 OnWillCompositeLayer(); | 1194 OnWillCompositeLayer(); |
| 1177 layer()->Draw(); | 1195 layer()->Draw(); |
| 1178 } | 1196 } |
| 1179 | 1197 |
| 1180 for (int i = 0, count = child_count(); i < count; ++i) | 1198 for (int i = 0, count = child_count(); i < count; ++i) |
| 1181 GetChildViewAt(i)->PaintComposite(); | 1199 GetChildViewAt(i)->PaintComposite(); |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1634 | 1652 |
| 1635 bool View::ConvertPointForAncestor(const View* ancestor, | 1653 bool View::ConvertPointForAncestor(const View* ancestor, |
| 1636 gfx::Point* point) const { | 1654 gfx::Point* point) const { |
| 1637 ui::Transform trans; | 1655 ui::Transform trans; |
| 1638 // TODO(sad): Have some way of caching the transformation results. | 1656 // TODO(sad): Have some way of caching the transformation results. |
| 1639 bool result = GetTransformRelativeTo(ancestor, &trans); | 1657 bool result = GetTransformRelativeTo(ancestor, &trans); |
| 1640 trans.TransformPoint(point); | 1658 trans.TransformPoint(point); |
| 1641 return result; | 1659 return result; |
| 1642 } | 1660 } |
| 1643 | 1661 |
| 1662 bool View::ConvertRectForAncestor(const View* ancestor, | |
| 1663 gfx::Rect* rect) const { | |
| 1664 ui::Transform trans; | |
| 1665 // TODO(sad): Have some way of caching the transformation results. | |
| 1666 bool result = GetTransformRelativeTo(ancestor, &trans); | |
| 1667 trans.TransformRect(rect); | |
| 1668 return result; | |
| 1669 } | |
| 1670 | |
| 1644 bool View::ConvertPointFromAncestor(const View* ancestor, | 1671 bool View::ConvertPointFromAncestor(const View* ancestor, |
| 1645 gfx::Point* point) const { | 1672 gfx::Point* point) const { |
| 1646 ui::Transform trans; | 1673 ui::Transform trans; |
| 1647 bool result = GetTransformRelativeTo(ancestor, &trans); | 1674 bool result = GetTransformRelativeTo(ancestor, &trans); |
| 1648 trans.TransformPointReverse(point); | 1675 trans.TransformPointReverse(point); |
| 1649 return result; | 1676 return result; |
| 1650 } | 1677 } |
| 1651 | 1678 |
| 1652 // Accelerated painting -------------------------------------------------------- | 1679 // Accelerated painting -------------------------------------------------------- |
| 1653 | 1680 |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2033 result.append(GetChildViewAt(i)->PrintViewGraph(false)); | 2060 result.append(GetChildViewAt(i)->PrintViewGraph(false)); |
| 2034 | 2061 |
| 2035 if (first) | 2062 if (first) |
| 2036 result.append("}\n"); | 2063 result.append("}\n"); |
| 2037 | 2064 |
| 2038 return result; | 2065 return result; |
| 2039 } | 2066 } |
| 2040 #endif | 2067 #endif |
| 2041 | 2068 |
| 2042 } // namespace views | 2069 } // namespace views |
| OLD | NEW |