| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ash/wm/overview/window_selector_item.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "ash/common/material_design/material_design_controller.h" | |
| 11 #include "ash/common/shell_window_ids.h" | |
| 12 #include "ash/common/wm/window_state.h" | |
| 13 #include "ash/common/wm_lookup.h" | |
| 14 #include "ash/common/wm_root_window_controller.h" | |
| 15 #include "ash/common/wm_window.h" | |
| 16 #include "ash/common/wm_window_property.h" | |
| 17 #include "ash/wm/overview/overview_animation_type.h" | |
| 18 #include "ash/wm/overview/scoped_overview_animation_settings.h" | |
| 19 #include "ash/wm/overview/scoped_overview_animation_settings_factory.h" | |
| 20 #include "ash/wm/overview/scoped_transform_overview_window.h" | |
| 21 #include "ash/wm/overview/window_selector.h" | |
| 22 #include "ash/wm/overview/window_selector_controller.h" | |
| 23 #include "base/auto_reset.h" | |
| 24 #include "base/strings/string_util.h" | |
| 25 #include "base/strings/utf_string_conversions.h" | |
| 26 #include "base/time/time.h" | |
| 27 #include "grit/ash_resources.h" | |
| 28 #include "grit/ash_strings.h" | |
| 29 #include "ui/base/l10n/l10n_util.h" | |
| 30 #include "ui/base/resource/resource_bundle.h" | |
| 31 #include "ui/gfx/canvas.h" | |
| 32 #include "ui/gfx/geometry/safe_integer_conversions.h" | |
| 33 #include "ui/gfx/geometry/vector2d.h" | |
| 34 #include "ui/gfx/paint_vector_icon.h" | |
| 35 #include "ui/gfx/transform_util.h" | |
| 36 #include "ui/gfx/vector_icons.h" | |
| 37 #include "ui/strings/grit/ui_strings.h" | |
| 38 #include "ui/views/background.h" | |
| 39 #include "ui/views/border.h" | |
| 40 #include "ui/views/controls/button/image_button.h" | |
| 41 #include "ui/views/layout/box_layout.h" | |
| 42 #include "ui/views/window/non_client_view.h" | |
| 43 #include "ui/wm/core/window_util.h" | |
| 44 | |
| 45 namespace ash { | |
| 46 | |
| 47 namespace { | |
| 48 | |
| 49 // In the conceptual overview table, the window margin is the space reserved | |
| 50 // around the window within the cell. This margin does not overlap so the | |
| 51 // closest distance between adjacent windows will be twice this amount. | |
| 52 static const int kWindowMargin = 30; | |
| 53 static const int kWindowMarginMD = 5; | |
| 54 | |
| 55 // Cover the transformed window including the gaps between the windows with a | |
| 56 // transparent shield to block the input events from reaching the transformed | |
| 57 // window while in overview. | |
| 58 static const int kWindowSelectorMargin = kWindowMarginMD * 2; | |
| 59 | |
| 60 // Foreground label color. | |
| 61 static const SkColor kLabelColor = SK_ColorWHITE; | |
| 62 | |
| 63 // TODO(tdanderson): Move this to a central location. | |
| 64 static const SkColor kCloseButtonColor = SK_ColorWHITE; | |
| 65 | |
| 66 // Label background color used with Material Design. | |
| 67 // TODO(varkha): Make background color conform to window header. | |
| 68 static const SkColor kLabelBackgroundColor = SkColorSetARGB(25, 255, 255, 255); | |
| 69 | |
| 70 // Corner radius for the selection tiles used with Material Design. | |
| 71 static int kLabelBackgroundRadius = 2; | |
| 72 | |
| 73 // Label shadow color. | |
| 74 static const SkColor kLabelShadow = SkColorSetARGB(176, 0, 0, 0); | |
| 75 | |
| 76 // Vertical padding for the label, on top of it. | |
| 77 static const int kVerticalLabelPadding = 20; | |
| 78 | |
| 79 // Horizontal padding for the label, on both sides. Used with Material Design. | |
| 80 static const int kHorizontalLabelPaddingMD = 8; | |
| 81 | |
| 82 // Solid shadow length from the label | |
| 83 static const int kVerticalShadowOffset = 1; | |
| 84 | |
| 85 // Amount of blur applied to the label shadow | |
| 86 static const int kShadowBlur = 10; | |
| 87 | |
| 88 // Height of an item header in Material Design. | |
| 89 static const int kHeaderHeight = 32; | |
| 90 | |
| 91 // Opacity for dimmed items. | |
| 92 static const float kDimmedItemOpacity = 0.5f; | |
| 93 | |
| 94 // Duration of background opacity transition for the selected label. | |
| 95 static const int kSelectorFadeInMilliseconds = 350; | |
| 96 | |
| 97 // Calculates the |window| bounds after being transformed to the selector's | |
| 98 // space. The returned Rect is in virtual screen coordinates. | |
| 99 gfx::Rect GetTransformedBounds(WmWindow* window) { | |
| 100 gfx::RectF bounds( | |
| 101 window->GetRootWindow()->ConvertRectToScreen(window->GetTargetBounds())); | |
| 102 gfx::Transform new_transform = TransformAboutPivot( | |
| 103 gfx::Point(bounds.x(), bounds.y()), window->GetTargetTransform()); | |
| 104 new_transform.TransformRect(&bounds); | |
| 105 | |
| 106 // With Material Design the preview title is shown above the preview window. | |
| 107 // Hide the window header for apps or browser windows with no tabs (web apps) | |
| 108 // to avoid showing both the window header and the preview title. | |
| 109 if (ash::MaterialDesignController::IsOverviewMaterial()) { | |
| 110 gfx::RectF header_bounds(bounds); | |
| 111 header_bounds.set_height( | |
| 112 window->GetIntProperty(WmWindowProperty::TOP_VIEW_INSET)); | |
| 113 new_transform.TransformRect(&header_bounds); | |
| 114 bounds.Inset(0, gfx::ToCeiledInt(header_bounds.height()), 0, 0); | |
| 115 } | |
| 116 return ToEnclosingRect(bounds); | |
| 117 } | |
| 118 | |
| 119 // Convenience method to fade in a Window with predefined animation settings. | |
| 120 // Note: The fade in animation will occur after a delay where the delay is how | |
| 121 // long the lay out animations take. | |
| 122 void SetupFadeInAfterLayout(views::Widget* widget) { | |
| 123 WmWindow* window = WmLookup::Get()->GetWindowForWidget(widget); | |
| 124 window->SetOpacity(0.0f); | |
| 125 std::unique_ptr<ScopedOverviewAnimationSettings> | |
| 126 scoped_overview_animation_settings = | |
| 127 ScopedOverviewAnimationSettingsFactory::Get() | |
| 128 ->CreateOverviewAnimationSettings( | |
| 129 OverviewAnimationType:: | |
| 130 OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, | |
| 131 window); | |
| 132 window->SetOpacity(1.0f); | |
| 133 } | |
| 134 | |
| 135 // An image button with a close window icon. | |
| 136 class OverviewCloseButton : public views::ImageButton { | |
| 137 public: | |
| 138 explicit OverviewCloseButton(views::ButtonListener* listener); | |
| 139 ~OverviewCloseButton() override; | |
| 140 | |
| 141 private: | |
| 142 gfx::ImageSkia icon_image_; | |
| 143 | |
| 144 DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton); | |
| 145 }; | |
| 146 | |
| 147 OverviewCloseButton::OverviewCloseButton(views::ButtonListener* listener) | |
| 148 : views::ImageButton(listener) { | |
| 149 if (ash::MaterialDesignController::IsOverviewMaterial()) { | |
| 150 icon_image_ = gfx::CreateVectorIcon(gfx::VectorIconId::WINDOW_CONTROL_CLOSE, | |
| 151 kCloseButtonColor); | |
| 152 SetImage(views::CustomButton::STATE_NORMAL, &icon_image_); | |
| 153 SetImage(views::CustomButton::STATE_HOVERED, &icon_image_); | |
| 154 SetImage(views::CustomButton::STATE_PRESSED, &icon_image_); | |
| 155 SetImageAlignment(views::ImageButton::ALIGN_CENTER, | |
| 156 views::ImageButton::ALIGN_MIDDLE); | |
| 157 SetMinimumImageSize(gfx::Size(kHeaderHeight, kHeaderHeight)); | |
| 158 } else { | |
| 159 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 160 SetImage(views::CustomButton::STATE_NORMAL, | |
| 161 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE)); | |
| 162 SetImage(views::CustomButton::STATE_HOVERED, | |
| 163 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE_H)); | |
| 164 SetImage(views::CustomButton::STATE_PRESSED, | |
| 165 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE_P)); | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 OverviewCloseButton::~OverviewCloseButton() { | |
| 170 } | |
| 171 | |
| 172 // A View having rounded corners and a specified background color which is | |
| 173 // only painted within the bounds defined by the rounded corners. | |
| 174 // TODO(varkha): This duplicates code from RoundedImageView. Refactor these | |
| 175 // classes and move into ui/views. | |
| 176 class RoundedContainerView : public views::View { | |
| 177 public: | |
| 178 RoundedContainerView(int corner_radius, SkColor background) | |
| 179 : corner_radius_(corner_radius), background_(background) {} | |
| 180 | |
| 181 ~RoundedContainerView() override {} | |
| 182 | |
| 183 void OnPaint(gfx::Canvas* canvas) override { | |
| 184 views::View::OnPaint(canvas); | |
| 185 | |
| 186 SkScalar radius = SkIntToScalar(corner_radius_); | |
| 187 const SkScalar kRadius[8] = {radius, radius, radius, radius, | |
| 188 radius, radius, radius, radius}; | |
| 189 SkPath path; | |
| 190 gfx::Rect bounds(size()); | |
| 191 bounds.set_height(bounds.height() + radius); | |
| 192 path.addRoundRect(gfx::RectToSkRect(bounds), kRadius); | |
| 193 | |
| 194 SkPaint paint; | |
| 195 paint.setAntiAlias(true); | |
| 196 canvas->ClipPath(path, true); | |
| 197 canvas->DrawColor(background_); | |
| 198 } | |
| 199 | |
| 200 private: | |
| 201 int corner_radius_; | |
| 202 SkColor background_; | |
| 203 | |
| 204 DISALLOW_COPY_AND_ASSIGN(RoundedContainerView); | |
| 205 }; | |
| 206 | |
| 207 } // namespace | |
| 208 | |
| 209 WindowSelectorItem::OverviewLabelButton::OverviewLabelButton( | |
| 210 views::ButtonListener* listener, | |
| 211 const base::string16& text) | |
| 212 : LabelButton(listener, text) {} | |
| 213 | |
| 214 WindowSelectorItem::OverviewLabelButton::~OverviewLabelButton() { | |
| 215 } | |
| 216 | |
| 217 void WindowSelectorItem::OverviewLabelButton::SetBackgroundColor( | |
| 218 SkColor color) { | |
| 219 label()->SetBackgroundColor(color); | |
| 220 } | |
| 221 | |
| 222 gfx::Rect WindowSelectorItem::OverviewLabelButton::GetChildAreaBounds() { | |
| 223 gfx::Rect bounds = GetLocalBounds(); | |
| 224 bounds.Inset(padding_); | |
| 225 if (ash::MaterialDesignController::IsOverviewMaterial()) | |
| 226 bounds.Inset(kHorizontalLabelPaddingMD, 0, kHorizontalLabelPaddingMD, 0); | |
| 227 return bounds; | |
| 228 } | |
| 229 | |
| 230 // Container View that has an item label and a close button as children. | |
| 231 class WindowSelectorItem::CaptionContainerView : public views::View { | |
| 232 public: | |
| 233 CaptionContainerView(WindowSelectorItem::OverviewLabelButton* label, | |
| 234 views::ImageButton* close_button) | |
| 235 : label_(label), close_button_(close_button) { | |
| 236 AddChildView(label_); | |
| 237 AddChildView(close_button_); | |
| 238 } | |
| 239 | |
| 240 protected: | |
| 241 // views::View: | |
| 242 void Layout() override { | |
| 243 // Position close button in the top right corner sized to its icon size and | |
| 244 // the label in the top left corner as tall as the button and extending to | |
| 245 // the button's left edge. | |
| 246 // The rest of this container view serves as a shield to prevent input | |
| 247 // events from reaching the transformed window in overview. | |
| 248 gfx::Rect bounds(GetLocalBounds()); | |
| 249 bounds.Inset(kWindowSelectorMargin, kWindowSelectorMargin); | |
| 250 const int visible_height = close_button_->GetPreferredSize().height(); | |
| 251 gfx::Insets label_padding(0, 0, bounds.height() - visible_height, | |
| 252 visible_height); | |
| 253 label_->set_padding(label_padding); | |
| 254 label_->SetBoundsRect(bounds); | |
| 255 bounds.set_x(bounds.right() - visible_height); | |
| 256 bounds.set_width(visible_height); | |
| 257 bounds.set_height(visible_height); | |
| 258 close_button_->SetBoundsRect(bounds); | |
| 259 } | |
| 260 | |
| 261 void OnBoundsChanged(const gfx::Rect& previous_bounds) override { Layout(); } | |
| 262 | |
| 263 private: | |
| 264 WindowSelectorItem::OverviewLabelButton* label_; | |
| 265 views::ImageButton* close_button_; | |
| 266 | |
| 267 DISALLOW_COPY_AND_ASSIGN(CaptionContainerView); | |
| 268 }; | |
| 269 | |
| 270 WindowSelectorItem::WindowSelectorItem(WmWindow* window, | |
| 271 WindowSelector* window_selector) | |
| 272 : dimmed_(false), | |
| 273 root_window_(window->GetRootWindow()), | |
| 274 transform_window_(window), | |
| 275 in_bounds_update_(false), | |
| 276 caption_container_view_(nullptr), | |
| 277 window_label_button_view_(nullptr), | |
| 278 close_button_(new OverviewCloseButton(this)), | |
| 279 window_selector_(window_selector) { | |
| 280 CreateWindowLabel(window->GetTitle()); | |
| 281 if (!ash::MaterialDesignController::IsOverviewMaterial()) { | |
| 282 views::Widget::InitParams params; | |
| 283 params.type = views::Widget::InitParams::TYPE_POPUP; | |
| 284 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 285 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | |
| 286 close_button_widget_.reset(new views::Widget); | |
| 287 close_button_widget_->set_focus_on_creation(false); | |
| 288 window->GetRootWindowController()->ConfigureWidgetInitParamsForContainer( | |
| 289 close_button_widget_.get(), kShellWindowId_OverlayContainer, ¶ms); | |
| 290 close_button_widget_->Init(params); | |
| 291 close_button_->SetVisible(false); | |
| 292 close_button_widget_->SetContentsView(close_button_); | |
| 293 close_button_widget_->SetSize(close_button_->GetPreferredSize()); | |
| 294 close_button_widget_->Show(); | |
| 295 | |
| 296 gfx::Rect close_button_rect(close_button_->GetPreferredSize()); | |
| 297 // Align the center of the button with position (0, 0) so that the | |
| 298 // translate transform does not need to take the button dimensions into | |
| 299 // account. | |
| 300 close_button_rect.set_x(-close_button_rect.width() / 2); | |
| 301 close_button_rect.set_y(-close_button_rect.height() / 2); | |
| 302 WmLookup::Get() | |
| 303 ->GetWindowForWidget(close_button_widget_.get()) | |
| 304 ->SetBounds(close_button_rect); | |
| 305 } | |
| 306 GetWindow()->AddObserver(this); | |
| 307 } | |
| 308 | |
| 309 WindowSelectorItem::~WindowSelectorItem() { | |
| 310 GetWindow()->RemoveObserver(this); | |
| 311 } | |
| 312 | |
| 313 WmWindow* WindowSelectorItem::GetWindow() { | |
| 314 return transform_window_.window(); | |
| 315 } | |
| 316 | |
| 317 void WindowSelectorItem::RestoreWindow() { | |
| 318 transform_window_.RestoreWindow(); | |
| 319 } | |
| 320 | |
| 321 void WindowSelectorItem::ShowWindowOnExit() { | |
| 322 transform_window_.ShowWindowOnExit(); | |
| 323 } | |
| 324 | |
| 325 void WindowSelectorItem::PrepareForOverview() { | |
| 326 transform_window_.PrepareForOverview(); | |
| 327 } | |
| 328 | |
| 329 bool WindowSelectorItem::Contains(const WmWindow* target) const { | |
| 330 return transform_window_.Contains(target); | |
| 331 } | |
| 332 | |
| 333 void WindowSelectorItem::SetBounds(const gfx::Rect& target_bounds, | |
| 334 OverviewAnimationType animation_type) { | |
| 335 if (in_bounds_update_) | |
| 336 return; | |
| 337 base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true); | |
| 338 target_bounds_ = target_bounds; | |
| 339 | |
| 340 gfx::Rect inset_bounds(target_bounds); | |
| 341 if (ash::MaterialDesignController::IsOverviewMaterial()) | |
| 342 inset_bounds.Inset(kWindowMarginMD, kWindowMarginMD); | |
| 343 else | |
| 344 inset_bounds.Inset(kWindowMargin, kWindowMargin); | |
| 345 SetItemBounds(inset_bounds, animation_type); | |
| 346 | |
| 347 // SetItemBounds is called before UpdateHeaderLayout so the header can | |
| 348 // properly use the updated windows bounds. | |
| 349 UpdateHeaderLayout(animation_type); | |
| 350 if (!ash::MaterialDesignController::IsOverviewMaterial()) | |
| 351 UpdateWindowLabel(target_bounds, animation_type); | |
| 352 } | |
| 353 | |
| 354 void WindowSelectorItem::SetSelected(bool selected) { | |
| 355 if (!ash::MaterialDesignController::IsOverviewMaterial()) | |
| 356 return; | |
| 357 WmWindow* window = | |
| 358 WmLookup::Get()->GetWindowForWidget(window_label_selector_.get()); | |
| 359 ui::ScopedLayerAnimationSettings animation_settings( | |
| 360 window->GetLayer()->GetAnimator()); | |
| 361 animation_settings.SetTransitionDuration( | |
| 362 base::TimeDelta::FromMilliseconds(kSelectorFadeInMilliseconds)); | |
| 363 animation_settings.SetTweenType(selected ? gfx::Tween::FAST_OUT_LINEAR_IN | |
| 364 : gfx::Tween::LINEAR_OUT_SLOW_IN); | |
| 365 animation_settings.SetPreemptionStrategy( | |
| 366 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
| 367 window->SetOpacity(selected ? 0.0f : 1.0f); | |
| 368 } | |
| 369 | |
| 370 void WindowSelectorItem::RecomputeWindowTransforms() { | |
| 371 if (in_bounds_update_ || target_bounds_.IsEmpty()) | |
| 372 return; | |
| 373 base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true); | |
| 374 gfx::Rect inset_bounds(target_bounds_); | |
| 375 if (ash::MaterialDesignController::IsOverviewMaterial()) | |
| 376 inset_bounds.Inset(kWindowMarginMD, kWindowMarginMD); | |
| 377 else | |
| 378 inset_bounds.Inset(kWindowMargin, kWindowMargin); | |
| 379 SetItemBounds(inset_bounds, OverviewAnimationType::OVERVIEW_ANIMATION_NONE); | |
| 380 UpdateHeaderLayout(OverviewAnimationType::OVERVIEW_ANIMATION_NONE); | |
| 381 } | |
| 382 | |
| 383 void WindowSelectorItem::SendAccessibleSelectionEvent() { | |
| 384 window_label_button_view_->NotifyAccessibilityEvent( | |
| 385 ui::AX_EVENT_SELECTION, true); | |
| 386 } | |
| 387 | |
| 388 void WindowSelectorItem::SetDimmed(bool dimmed) { | |
| 389 dimmed_ = dimmed; | |
| 390 SetOpacity(dimmed ? kDimmedItemOpacity : 1.0f); | |
| 391 } | |
| 392 | |
| 393 void WindowSelectorItem::ButtonPressed(views::Button* sender, | |
| 394 const ui::Event& event) { | |
| 395 if (sender == close_button_) { | |
| 396 transform_window_.Close(); | |
| 397 return; | |
| 398 } | |
| 399 CHECK(sender == window_label_button_view_); | |
| 400 window_selector_->SelectWindow(transform_window_.window()); | |
| 401 } | |
| 402 | |
| 403 void WindowSelectorItem::OnWindowDestroying(WmWindow* window) { | |
| 404 window->RemoveObserver(this); | |
| 405 transform_window_.OnWindowDestroyed(); | |
| 406 } | |
| 407 | |
| 408 void WindowSelectorItem::OnWindowTitleChanged(WmWindow* window) { | |
| 409 // TODO(flackr): Maybe add the new title to a vector of titles so that we can | |
| 410 // filter any of the titles the window had while in the overview session. | |
| 411 window_label_button_view_->SetText(window->GetTitle()); | |
| 412 UpdateCloseButtonAccessibilityName(); | |
| 413 } | |
| 414 | |
| 415 float WindowSelectorItem::GetItemScale(const gfx::Size& size) { | |
| 416 gfx::Size inset_size(size.width(), size.height() - 2 * kWindowMarginMD); | |
| 417 return ScopedTransformOverviewWindow::GetItemScale( | |
| 418 GetWindow()->GetTargetBounds().size(), inset_size, | |
| 419 GetWindow()->GetIntProperty(WmWindowProperty::TOP_VIEW_INSET), | |
| 420 close_button_->GetPreferredSize().height()); | |
| 421 } | |
| 422 | |
| 423 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, | |
| 424 OverviewAnimationType animation_type) { | |
| 425 DCHECK(root_window_ == GetWindow()->GetRootWindow()); | |
| 426 gfx::Rect screen_rect = transform_window_.GetTargetBoundsInScreen(); | |
| 427 | |
| 428 // Avoid division by zero by ensuring screen bounds is not empty. | |
| 429 gfx::Size screen_size(screen_rect.size()); | |
| 430 screen_size.SetToMax(gfx::Size(1, 1)); | |
| 431 screen_rect.set_size(screen_size); | |
| 432 | |
| 433 int top_view_inset = 0; | |
| 434 int title_height = 0; | |
| 435 if (ash::MaterialDesignController::IsOverviewMaterial()) { | |
| 436 top_view_inset = | |
| 437 GetWindow()->GetIntProperty(WmWindowProperty::TOP_VIEW_INSET); | |
| 438 title_height = close_button_->GetPreferredSize().height(); | |
| 439 } | |
| 440 gfx::Rect selector_item_bounds = | |
| 441 ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio( | |
| 442 screen_rect, target_bounds, top_view_inset, title_height); | |
| 443 gfx::Transform transform = ScopedTransformOverviewWindow::GetTransformForRect( | |
| 444 screen_rect, selector_item_bounds); | |
| 445 ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings; | |
| 446 transform_window_.BeginScopedAnimation(animation_type, &animation_settings); | |
| 447 // Rounded corners are achieved by using a mask layer on the original window | |
| 448 // before the transform. Dividing by scale factor obtains the corner radius | |
| 449 // which when scaled will yield |kLabelBackgroundRadius|. | |
| 450 transform_window_.SetTransform( | |
| 451 root_window_, transform, | |
| 452 gfx::ToFlooredInt(kLabelBackgroundRadius / | |
| 453 GetItemScale(target_bounds.size()))); | |
| 454 transform_window_.set_overview_transform(transform); | |
| 455 } | |
| 456 | |
| 457 void WindowSelectorItem::SetOpacity(float opacity) { | |
| 458 window_label_->SetOpacity(opacity); | |
| 459 if (!ash::MaterialDesignController::IsOverviewMaterial()) | |
| 460 close_button_widget_->SetOpacity(opacity); | |
| 461 | |
| 462 transform_window_.SetOpacity(opacity); | |
| 463 } | |
| 464 | |
| 465 void WindowSelectorItem::UpdateWindowLabel( | |
| 466 const gfx::Rect& window_bounds, | |
| 467 OverviewAnimationType animation_type) { | |
| 468 if (!window_label_->IsVisible()) { | |
| 469 window_label_->Show(); | |
| 470 SetupFadeInAfterLayout(window_label_.get()); | |
| 471 } | |
| 472 | |
| 473 gfx::Rect label_bounds = root_window_->ConvertRectFromScreen(window_bounds); | |
| 474 window_label_button_view_->set_padding( | |
| 475 gfx::Insets(label_bounds.height() - kVerticalLabelPadding, 0, 0, 0)); | |
| 476 std::unique_ptr<ScopedOverviewAnimationSettings> animation_settings = | |
| 477 ScopedOverviewAnimationSettingsFactory::Get() | |
| 478 ->CreateOverviewAnimationSettings( | |
| 479 animation_type, | |
| 480 WmLookup::Get()->GetWindowForWidget(window_label_.get())); | |
| 481 | |
| 482 WmWindow* window_label_window = | |
| 483 WmLookup::Get()->GetWindowForWidget(window_label_.get()); | |
| 484 window_label_window->SetBounds(label_bounds); | |
| 485 } | |
| 486 | |
| 487 void WindowSelectorItem::CreateWindowLabel(const base::string16& title) { | |
| 488 const bool material = ash::MaterialDesignController::IsOverviewMaterial(); | |
| 489 window_label_.reset(new views::Widget); | |
| 490 views::Widget::InitParams params; | |
| 491 params.type = views::Widget::InitParams::TYPE_POPUP; | |
| 492 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 493 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | |
| 494 params.visible_on_all_workspaces = true; | |
| 495 window_label_->set_focus_on_creation(false); | |
| 496 root_window_->GetRootWindowController() | |
| 497 ->ConfigureWidgetInitParamsForContainer( | |
| 498 window_label_.get(), kShellWindowId_OverlayContainer, ¶ms); | |
| 499 window_label_->Init(params); | |
| 500 window_label_button_view_ = new OverviewLabelButton(this, title); | |
| 501 window_label_button_view_->SetBorder(views::Border::NullBorder()); | |
| 502 window_label_button_view_->SetEnabledTextColors(kLabelColor); | |
| 503 window_label_button_view_->set_animate_on_state_change(false); | |
| 504 if (material) { | |
| 505 window_label_button_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
| 506 } else { | |
| 507 window_label_button_view_->SetHorizontalAlignment(gfx::ALIGN_CENTER); | |
| 508 window_label_button_view_->SetTextShadows(gfx::ShadowValues( | |
| 509 1, gfx::ShadowValue(gfx::Vector2d(0, kVerticalShadowOffset), | |
| 510 kShadowBlur, kLabelShadow))); | |
| 511 } | |
| 512 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | |
| 513 window_label_button_view_->SetFontList(bundle.GetFontList( | |
| 514 material ? ui::ResourceBundle::BaseFont : ui::ResourceBundle::BoldFont)); | |
| 515 if (material) { | |
| 516 caption_container_view_ = | |
| 517 new CaptionContainerView(window_label_button_view_, close_button_); | |
| 518 window_label_->SetContentsView(caption_container_view_); | |
| 519 window_label_button_view_->SetVisible(false); | |
| 520 window_label_->Show(); | |
| 521 | |
| 522 views::View* background_view = | |
| 523 new RoundedContainerView(kLabelBackgroundRadius, kLabelBackgroundColor); | |
| 524 window_label_selector_.reset(new views::Widget); | |
| 525 params.activatable = views::Widget::InitParams::Activatable::ACTIVATABLE_NO; | |
| 526 params.accept_events = false; | |
| 527 window_label_selector_->Init(params); | |
| 528 window_label_selector_->set_focus_on_creation(false); | |
| 529 window_label_selector_->SetContentsView(background_view); | |
| 530 window_label_selector_->Show(); | |
| 531 } else { | |
| 532 window_label_->SetContentsView(window_label_button_view_); | |
| 533 } | |
| 534 } | |
| 535 | |
| 536 void WindowSelectorItem::UpdateHeaderLayout( | |
| 537 OverviewAnimationType animation_type) { | |
| 538 gfx::Rect transformed_window_bounds = | |
| 539 root_window_->ConvertRectFromScreen(GetTransformedBounds(GetWindow())); | |
| 540 | |
| 541 if (ash::MaterialDesignController::IsOverviewMaterial()) { | |
| 542 gfx::Rect label_rect(close_button_->GetPreferredSize()); | |
| 543 label_rect.set_y(-label_rect.height()); | |
| 544 label_rect.set_width(transformed_window_bounds.width()); | |
| 545 | |
| 546 if (!window_label_button_view_->visible()) { | |
| 547 window_label_button_view_->SetVisible(true); | |
| 548 SetupFadeInAfterLayout(window_label_.get()); | |
| 549 SetupFadeInAfterLayout(window_label_selector_.get()); | |
| 550 } | |
| 551 WmWindow* window_label_window = | |
| 552 WmLookup::Get()->GetWindowForWidget(window_label_.get()); | |
| 553 WmWindow* window_label_selector_window = | |
| 554 WmLookup::Get()->GetWindowForWidget(window_label_selector_.get()); | |
| 555 window_label_selector_window->SetBounds(label_rect); | |
| 556 // |window_label_window| covers both the transformed window and the header | |
| 557 // as well as the gap between the windows to prevent events from reaching | |
| 558 // the window including its sizing borders. | |
| 559 label_rect.set_height(label_rect.height() + | |
| 560 transformed_window_bounds.height()); | |
| 561 label_rect.Inset(-kWindowSelectorMargin, -kWindowSelectorMargin); | |
| 562 window_label_window->SetBounds(label_rect); | |
| 563 std::unique_ptr<ScopedOverviewAnimationSettings> animation_settings = | |
| 564 ScopedOverviewAnimationSettingsFactory::Get() | |
| 565 ->CreateOverviewAnimationSettings(animation_type, | |
| 566 window_label_window); | |
| 567 gfx::Transform label_transform; | |
| 568 label_transform.Translate(transformed_window_bounds.x(), | |
| 569 transformed_window_bounds.y()); | |
| 570 window_label_window->SetTransform(label_transform); | |
| 571 window_label_selector_window->SetTransform(label_transform); | |
| 572 } else { | |
| 573 if (!close_button_->visible()) { | |
| 574 close_button_->SetVisible(true); | |
| 575 SetupFadeInAfterLayout(close_button_widget_.get()); | |
| 576 } | |
| 577 WmWindow* close_button_widget_window = | |
| 578 WmLookup::Get()->GetWindowForWidget(close_button_widget_.get()); | |
| 579 std::unique_ptr<ScopedOverviewAnimationSettings> animation_settings = | |
| 580 ScopedOverviewAnimationSettingsFactory::Get() | |
| 581 ->CreateOverviewAnimationSettings(animation_type, | |
| 582 close_button_widget_window); | |
| 583 | |
| 584 gfx::Transform close_button_transform; | |
| 585 close_button_transform.Translate(transformed_window_bounds.right(), | |
| 586 transformed_window_bounds.y()); | |
| 587 close_button_widget_window->SetTransform(close_button_transform); | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 void WindowSelectorItem::UpdateCloseButtonAccessibilityName() { | |
| 592 close_button_->SetAccessibleName(l10n_util::GetStringFUTF16( | |
| 593 IDS_ASH_OVERVIEW_CLOSE_ITEM_BUTTON_ACCESSIBLE_NAME, | |
| 594 GetWindow()->GetTitle())); | |
| 595 } | |
| 596 | |
| 597 } // namespace ash | |
| OLD | NEW |