Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ash/common/wm/window_cycle_list.h" | 5 #include "ash/common/wm/window_cycle_list.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "ash/common/ash_switches.h" | 10 #include "ash/common/ash_switches.h" |
| 11 #include "ash/common/shell_window_ids.h" | 11 #include "ash/common/shell_window_ids.h" |
| 12 #include "ash/common/wm/forwarding_layer_delegate.h" | 12 #include "ash/common/wm/forwarding_layer_delegate.h" |
| 13 #include "ash/common/wm/mru_window_tracker.h" | 13 #include "ash/common/wm/mru_window_tracker.h" |
| 14 #include "ash/common/wm/window_state.h" | 14 #include "ash/common/wm/window_state.h" |
| 15 #include "ash/common/wm_root_window_controller.h" | 15 #include "ash/common/wm_root_window_controller.h" |
| 16 #include "ash/common/wm_shell.h" | 16 #include "ash/common/wm_shell.h" |
| 17 #include "ash/common/wm_window.h" | 17 #include "ash/common/wm_window.h" |
| 18 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 19 #include "ui/views/background.h" | 19 #include "ui/views/background.h" |
| 20 #include "ui/views/border.h" | |
| 21 #include "ui/views/controls/label.h" | |
| 20 #include "ui/views/layout/box_layout.h" | 22 #include "ui/views/layout/box_layout.h" |
| 21 #include "ui/views/painter.h" | 23 #include "ui/views/painter.h" |
| 22 #include "ui/views/view.h" | 24 #include "ui/views/view.h" |
| 23 #include "ui/views/widget/widget.h" | 25 #include "ui/views/widget/widget.h" |
| 24 #include "ui/wm/core/visibility_controller.h" | 26 #include "ui/wm/core/visibility_controller.h" |
| 25 | 27 |
| 26 namespace ash { | 28 namespace ash { |
| 27 | 29 |
| 28 // Returns the window immediately below |window| in the current container. | 30 // Returns the window immediately below |window| in the current container. |
| 29 WmWindow* GetWindowBelow(WmWindow* window) { | 31 WmWindow* GetWindowBelow(WmWindow* window) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 59 | 61 |
| 60 // The window immediately below where window_ belongs. | 62 // The window immediately below where window_ belongs. |
| 61 WmWindow* stack_window_above_; | 63 WmWindow* stack_window_above_; |
| 62 | 64 |
| 63 // If true, minimize window_ on going out of scope. | 65 // If true, minimize window_ on going out of scope. |
| 64 bool minimized_; | 66 bool minimized_; |
| 65 | 67 |
| 66 DISALLOW_COPY_AND_ASSIGN(ScopedShowWindow); | 68 DISALLOW_COPY_AND_ASSIGN(ScopedShowWindow); |
| 67 }; | 69 }; |
| 68 | 70 |
| 71 // This view represents a single WmWindow by displaying a title and a thumbnail | |
| 72 // of the window's contents. | |
| 73 class WindowPreviewView : public views::View { | |
| 74 public: | |
| 75 explicit WindowPreviewView(WmWindow* window) | |
| 76 : window_title_(new views::Label), | |
| 77 preview_background_(new views::View), | |
| 78 mirror_view_(window->CreateViewWithRecreatedLayers().release()) { | |
| 79 window_title_->SetText(window->GetTitle()); | |
| 80 window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
| 81 window_title_->SetEnabledColor(SK_ColorWHITE); | |
| 82 window_title_->SetAutoColorReadabilityEnabled(false); | |
| 83 // The base font is 12pt (for English) so this comes out to 14pt. | |
| 84 const int kLabelSizeDelta = 2; | |
| 85 window_title_->SetFontList( | |
| 86 window_title_->font_list().DeriveWithSizeDelta(kLabelSizeDelta)); | |
| 87 const int kAboveLabelPadding = 5; | |
| 88 const int kBelowLabelPadding = 10; | |
| 89 window_title_->SetBorder(views::Border::CreateEmptyBorder( | |
| 90 kAboveLabelPadding, 0, kBelowLabelPadding, 0)); | |
| 91 AddChildView(window_title_); | |
| 92 | |
| 93 // Preview padding is black at 50% opacity. | |
| 94 preview_background_->set_background( | |
| 95 views::Background::CreateSolidBackground( | |
| 96 SkColorSetA(SK_ColorBLACK, 0xFF / 2))); | |
| 97 AddChildView(preview_background_); | |
| 98 | |
| 99 AddChildView(mirror_view_); | |
| 100 } | |
| 101 ~WindowPreviewView() override {} | |
| 102 | |
| 103 // views::View: | |
| 104 gfx::Size GetPreferredSize() const override { | |
| 105 gfx::Size size = GetSizeForPreviewArea(); | |
| 106 size.Enlarge(0, window_title_->GetPreferredSize().height()); | |
| 107 return size; | |
| 108 } | |
| 109 | |
| 110 void Layout() override { | |
| 111 const gfx::Size preview_area_size = GetSizeForPreviewArea(); | |
| 112 // The window title is positioned above the preview area. | |
| 113 window_title_->SetBounds(0, 0, width(), | |
| 114 height() - preview_area_size.height()); | |
| 115 | |
| 116 gfx::Rect preview_area_bounds(preview_area_size); | |
| 117 preview_area_bounds.set_y(height() - preview_area_size.height()); | |
| 118 mirror_view_->SetSize(GetMirrorViewScaledSize()); | |
| 119 if (mirror_view_->size() == preview_area_size) { | |
| 120 // Padding is not needed, hide the background and set the mirror view | |
| 121 // to take up the entire preview area. | |
| 122 mirror_view_->SetPosition(preview_area_bounds.origin()); | |
| 123 preview_background_->SetVisible(false); | |
| 124 return; | |
| 125 } | |
| 126 | |
| 127 // Padding is needed, so show the background and set the mirror view to be | |
| 128 // centered within it. | |
| 129 preview_background_->SetBoundsRect(preview_area_bounds); | |
| 130 preview_background_->SetVisible(true); | |
| 131 preview_area_bounds.ClampToCenteredSize(mirror_view_->size()); | |
| 132 mirror_view_->SetPosition(preview_area_bounds.origin()); | |
| 133 } | |
| 134 | |
| 135 private: | |
| 136 // The maximum width of a window preview. | |
| 137 static const int kMaxPreviewWidth = 512; | |
| 138 // All previews are the same height (this is achieved via a combination of | |
| 139 // scaling and padding). | |
| 140 static const int kFixedPreviewHeight = 256; | |
| 141 | |
| 142 // Returns the size for the mirror view, scaled to fit within the max bounds. | |
| 143 // Scaling is always 1:1 and we only scale down, never up. | |
| 144 gfx::Size GetMirrorViewScaledSize() const { | |
| 145 gfx::Size mirror_pref_size = mirror_view_->GetPreferredSize(); | |
| 146 | |
| 147 if (mirror_pref_size.width() > kMaxPreviewWidth || | |
| 148 mirror_pref_size.height() > kFixedPreviewHeight) { | |
| 149 float scale = std::min( | |
| 150 kMaxPreviewWidth / static_cast<float>(mirror_pref_size.width()), | |
| 151 kFixedPreviewHeight / static_cast<float>(mirror_pref_size.height())); | |
| 152 mirror_pref_size = | |
| 153 gfx::ScaleToFlooredSize(mirror_pref_size, scale, scale); | |
| 154 } | |
| 155 | |
| 156 return mirror_pref_size; | |
| 157 } | |
| 158 | |
| 159 // Returns the size for the entire preview area (mirror view and additional | |
| 160 // padding). All previews will be the same height, so if the mirror view isn't | |
| 161 // tall enough we will add top and bottom padding. Previews can range in width | |
| 162 // from kMaxPreviewWidth down to half that value. Again, padding will be added | |
| 163 // to the sides to achieve this if the preview is too narrow. | |
| 164 gfx::Size GetSizeForPreviewArea() const { | |
| 165 gfx::Size mirror_size = GetMirrorViewScaledSize(); | |
| 166 float aspect_ratio = | |
| 167 static_cast<float>(mirror_size.width()) / mirror_size.height(); | |
| 168 gfx::Size preview_size = mirror_size; | |
| 169 // Very narrow windows get vertical bars of padding on the sides. | |
| 170 if (aspect_ratio < 0.5f) | |
| 171 preview_size.set_width(mirror_size.height() / 2); | |
| 172 | |
| 173 // All previews are the same height (this may add padding on top and | |
| 174 // bottom). | |
| 175 preview_size.set_height(kFixedPreviewHeight); | |
| 176 // Previews should never be narrower than half their max width (128dip). | |
| 177 preview_size.set_width( | |
| 178 std::max(preview_size.width(), kMaxPreviewWidth / 2)); | |
| 179 | |
| 180 return preview_size; | |
| 181 } | |
| 182 | |
| 183 // Displays the title of the window above the preview. | |
| 184 views::Label* window_title_; | |
| 185 // When visible, shows a darkened background area behind |mirror_view_| | |
| 186 // (effectively padding the preview to fit the desired bounds). | |
| 187 views::View* preview_background_; | |
| 188 // The view that actually renders a thumbnail version of the window. | |
| 189 views::View* mirror_view_; | |
| 190 | |
| 191 DISALLOW_COPY_AND_ASSIGN(WindowPreviewView); | |
| 192 }; | |
| 193 | |
| 69 // A view that shows a collection of windows the user can tab through. | 194 // A view that shows a collection of windows the user can tab through. |
| 70 class WindowCycleView : public views::View { | 195 class WindowCycleView : public views::View { |
| 71 public: | 196 public: |
| 72 explicit WindowCycleView(const WindowCycleList::WindowList& windows) | 197 explicit WindowCycleView(const WindowCycleList::WindowList& windows) |
| 73 : mirror_container_(new views::View()), | 198 : mirror_container_(new views::View()), |
| 74 highlight_view_(new views::View()), | 199 highlight_view_(new views::View()), |
| 75 target_window_(nullptr) { | 200 target_window_(nullptr) { |
| 76 DCHECK(!windows.empty()); | 201 DCHECK(!windows.empty()); |
| 77 SetPaintToLayer(true); | 202 SetPaintToLayer(true); |
| 78 layer()->SetFillsBoundsOpaquely(false); | 203 layer()->SetFillsBoundsOpaquely(false); |
| 79 | 204 |
| 80 set_background(views::Background::CreateSolidBackground( | 205 set_background(views::Background::CreateSolidBackground( |
| 81 SkColorSetA(SK_ColorBLACK, 0xCC))); | 206 SkColorSetA(SK_ColorBLACK, 0xCC))); |
| 82 | 207 |
| 83 const int kInsideBorderPaddingDip = 64; | 208 const int kInsideBorderPaddingDip = 64; |
| 84 const int kBetweenChildPaddingDip = 10; | 209 const int kBetweenChildPaddingDip = 10; |
| 85 views::BoxLayout* layout = new views::BoxLayout( | 210 views::BoxLayout* layout = new views::BoxLayout( |
| 86 views::BoxLayout::kHorizontal, kInsideBorderPaddingDip, | 211 views::BoxLayout::kHorizontal, kInsideBorderPaddingDip, |
| 87 kInsideBorderPaddingDip, kBetweenChildPaddingDip); | 212 kInsideBorderPaddingDip, kBetweenChildPaddingDip); |
| 88 layout->set_cross_axis_alignment( | 213 layout->set_cross_axis_alignment( |
| 89 views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); | 214 views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); |
| 90 mirror_container_->SetLayoutManager(layout); | 215 mirror_container_->SetLayoutManager(layout); |
| 91 mirror_container_->SetPaintToLayer(true); | 216 mirror_container_->SetPaintToLayer(true); |
| 92 mirror_container_->layer()->SetFillsBoundsOpaquely(false); | 217 mirror_container_->layer()->SetFillsBoundsOpaquely(false); |
| 93 // The preview list animates bounds changes (other animatable properties | 218 // The preview list animates bounds changes (other animatable properties |
| 94 // never change). | 219 // never change). |
| 95 mirror_container_->layer()->SetAnimator( | 220 mirror_container_->layer()->SetAnimator( |
| 96 ui::LayerAnimator::CreateImplicitAnimator()); | 221 ui::LayerAnimator::CreateImplicitAnimator()); |
| 97 | 222 |
| 98 for (WmWindow* window : windows) { | 223 for (WmWindow* window : windows) { |
|
sky
2016/07/20 19:48:45
Not related to this change, but recreating layers
Evan Stade
2016/07/20 19:53:42
Yes. It's an open question whether we want to be a
| |
| 99 // |mirror_container_| owns |view|. | 224 // |mirror_container_| owns |view|. |
| 100 views::View* view = window->CreateViewWithRecreatedLayers().release(); | 225 views::View* view = new WindowPreviewView(window); |
| 101 window_view_map_[window] = view; | 226 window_view_map_[window] = view; |
| 102 mirror_container_->AddChildView(view); | 227 mirror_container_->AddChildView(view); |
| 103 } | 228 } |
| 104 | 229 |
| 105 const float kHighlightCornerRadius = 4; | 230 const float kHighlightCornerRadius = 4; |
| 106 highlight_view_->set_background(views::Background::CreateBackgroundPainter( | 231 highlight_view_->set_background(views::Background::CreateBackgroundPainter( |
| 107 true, views::Painter::CreateRoundRectWith1PxBorderPainter( | 232 true, views::Painter::CreateRoundRectWith1PxBorderPainter( |
| 108 SkColorSetA(SK_ColorWHITE, 0x4D), | 233 SkColorSetA(SK_ColorWHITE, 0x4D), |
| 109 SkColorSetA(SK_ColorWHITE, 0x33), kHighlightCornerRadius))); | 234 SkColorSetA(SK_ColorWHITE, 0x33), kHighlightCornerRadius))); |
| 110 highlight_view_->SetPaintToLayer(true); | 235 highlight_view_->SetPaintToLayer(true); |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 } | 462 } |
| 338 } | 463 } |
| 339 | 464 |
| 340 bool WindowCycleList::ShouldShowUi() { | 465 bool WindowCycleList::ShouldShowUi() { |
| 341 return windows_.size() > 1 && | 466 return windows_.size() > 1 && |
| 342 base::CommandLine::ForCurrentProcess()->HasSwitch( | 467 base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 343 switches::kAshEnableWindowCycleUi); | 468 switches::kAshEnableWindowCycleUi); |
| 344 } | 469 } |
| 345 | 470 |
| 346 } // namespace ash | 471 } // namespace ash |
| OLD | NEW |