OLD | NEW |
| (Empty) |
1 // Copyright 2016 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/shelf/dimmer_view.h" | |
6 | |
7 #include "ash/aura/wm_window_aura.h" | |
8 #include "ash/common/shelf/wm_shelf.h" | |
9 #include "ash/common/shelf/wm_shelf_util.h" | |
10 #include "ash/shell.h" | |
11 #include "grit/ash_resources.h" | |
12 #include "ui/aura/window.h" | |
13 #include "ui/base/resource/resource_bundle.h" | |
14 #include "ui/gfx/canvas.h" | |
15 #include "ui/gfx/image/image_skia_operations.h" | |
16 #include "ui/views/widget/widget.h" | |
17 #include "ui/wm/core/coordinate_conversion.h" | |
18 | |
19 namespace ash { | |
20 | |
21 namespace { | |
22 | |
23 // Alpha to paint dimming image with. | |
24 const int kDimAlpha = 128; | |
25 | |
26 // The time to dim and un-dim. | |
27 const int kTimeToDimMs = 3000; // Slow in dimming. | |
28 const int kTimeToUnDimMs = 200; // Fast in activating. | |
29 | |
30 } // namespace | |
31 | |
32 // static | |
33 DimmerView* DimmerView::Create(WmShelf* shelf, | |
34 bool disable_animations_for_test) { | |
35 views::Widget::InitParams params( | |
36 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); | |
37 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | |
38 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO; | |
39 params.accept_events = false; | |
40 params.parent = WmWindowAura::GetAuraWindow(shelf->GetWindow()); | |
41 params.name = "DimmerView"; | |
42 views::Widget* dimmer = new views::Widget(); | |
43 dimmer->Init(params); | |
44 dimmer->SetBounds(shelf->GetWindow()->GetBoundsInScreen()); | |
45 // The shelf should not take focus when it is initially shown. | |
46 dimmer->set_focus_on_creation(false); | |
47 DimmerView* view = new DimmerView(shelf, disable_animations_for_test); | |
48 dimmer->SetContentsView(view); | |
49 dimmer->Show(); | |
50 return view; | |
51 } | |
52 | |
53 void DimmerView::SetHovered(bool hovered) { | |
54 // Remember the hovered state so that we can correct the state once a | |
55 // possible force state has disappeared. | |
56 is_hovered_ = hovered; | |
57 // Undim also if we were forced to by e.g. an open menu. | |
58 hovered |= force_hovered_; | |
59 background_animator_.SetDuration(hovered ? kTimeToUnDimMs : kTimeToDimMs); | |
60 background_animator_.SetPaintsBackground( | |
61 !hovered, disable_animations_for_test_ ? BACKGROUND_CHANGE_IMMEDIATE | |
62 : BACKGROUND_CHANGE_ANIMATE); | |
63 } | |
64 | |
65 void DimmerView::OnPaintBackground(gfx::Canvas* canvas) { | |
66 SkPaint paint; | |
67 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); | |
68 gfx::ImageSkia shelf_background = | |
69 *rb->GetImageNamed(IDR_ASH_SHELF_DIMMING).ToImageSkia(); | |
70 | |
71 if (!IsHorizontalAlignment(shelf_->GetAlignment())) { | |
72 shelf_background = gfx::ImageSkiaOperations::CreateRotatedImage( | |
73 shelf_background, shelf_->GetAlignment() == SHELF_ALIGNMENT_LEFT | |
74 ? SkBitmapOperations::ROTATION_90_CW | |
75 : SkBitmapOperations::ROTATION_270_CW); | |
76 } | |
77 paint.setAlpha(alpha_); | |
78 canvas->DrawImageInt(shelf_background, 0, 0, shelf_background.width(), | |
79 shelf_background.height(), 0, 0, width(), height(), | |
80 false, paint); | |
81 } | |
82 | |
83 views::Widget* DimmerView::GetWidget() { | |
84 return View::GetWidget(); | |
85 } | |
86 | |
87 const views::Widget* DimmerView::GetWidget() const { | |
88 return View::GetWidget(); | |
89 } | |
90 | |
91 void DimmerView::UpdateBackground(BackgroundAnimator* animator, int alpha) { | |
92 alpha_ = alpha; | |
93 SchedulePaint(); | |
94 } | |
95 | |
96 void DimmerView::BackgroundAnimationEnded(BackgroundAnimator* animator) {} | |
97 | |
98 views::Widget* DimmerView::GetDimmerWidget() { | |
99 return GetWidget(); | |
100 } | |
101 | |
102 void DimmerView::ForceUndimming(bool force) { | |
103 bool previous = force_hovered_; | |
104 force_hovered_ = force; | |
105 // If the forced change does change the result we apply the change. | |
106 if (is_hovered_ || force_hovered_ != is_hovered_ || previous) | |
107 SetHovered(is_hovered_); | |
108 } | |
109 | |
110 int DimmerView::GetDimmingAlphaForTest() { | |
111 return alpha_; | |
112 } | |
113 | |
114 void DimmerView::OnWindowBoundsChanged(WmWindow* window, | |
115 const gfx::Rect& old_bounds, | |
116 const gfx::Rect& new_bounds) { | |
117 // Coming here the shelf got repositioned and since the dimmer is placed | |
118 // in screen coordinates and not relative to the parent it needs to be | |
119 // repositioned accordingly. | |
120 GetWidget()->SetBounds(shelf_->GetWindow()->GetBoundsInScreen()); | |
121 } | |
122 | |
123 DimmerView::DimmerView(WmShelf* shelf, bool disable_animations_for_test) | |
124 : shelf_(shelf), | |
125 alpha_(kDimAlpha), | |
126 is_hovered_(false), | |
127 force_hovered_(false), | |
128 disable_animations_for_test_(disable_animations_for_test), | |
129 background_animator_(this, 0, kDimAlpha) { | |
130 event_filter_.reset(new DimmerEventFilter(this)); | |
131 // Make sure it is undimmed at the beginning and then fire off the dimming | |
132 // animation. | |
133 background_animator_.SetPaintsBackground(false, BACKGROUND_CHANGE_IMMEDIATE); | |
134 SetHovered(false); | |
135 shelf_->GetWindow()->AddObserver(this); | |
136 } | |
137 | |
138 DimmerView::~DimmerView() { | |
139 // Some unit tests will come here with a destroyed window. | |
140 if (shelf_->GetWindow()) | |
141 shelf_->GetWindow()->RemoveObserver(this); | |
142 } | |
143 | |
144 DimmerView::DimmerEventFilter::DimmerEventFilter(DimmerView* owner) | |
145 : owner_(owner), mouse_inside_(false), touch_inside_(false) { | |
146 Shell::GetInstance()->AddPreTargetHandler(this); | |
147 } | |
148 | |
149 DimmerView::DimmerEventFilter::~DimmerEventFilter() { | |
150 Shell::GetInstance()->RemovePreTargetHandler(this); | |
151 } | |
152 | |
153 void DimmerView::DimmerEventFilter::OnMouseEvent(ui::MouseEvent* event) { | |
154 if (event->type() != ui::ET_MOUSE_MOVED && | |
155 event->type() != ui::ET_MOUSE_DRAGGED) | |
156 return; | |
157 | |
158 gfx::Point screen_point(event->location()); | |
159 ::wm::ConvertPointToScreen(static_cast<aura::Window*>(event->target()), | |
160 &screen_point); | |
161 bool inside = owner_->GetBoundsInScreen().Contains(screen_point); | |
162 if (mouse_inside_ || touch_inside_ != inside || touch_inside_) | |
163 owner_->SetHovered(inside || touch_inside_); | |
164 mouse_inside_ = inside; | |
165 } | |
166 | |
167 void DimmerView::DimmerEventFilter::OnTouchEvent(ui::TouchEvent* event) { | |
168 bool touch_inside = false; | |
169 if (event->type() != ui::ET_TOUCH_RELEASED && | |
170 event->type() != ui::ET_TOUCH_CANCELLED) { | |
171 gfx::Point screen_point(event->location()); | |
172 ::wm::ConvertPointToScreen(static_cast<aura::Window*>(event->target()), | |
173 &screen_point); | |
174 touch_inside = owner_->GetBoundsInScreen().Contains(screen_point); | |
175 } | |
176 | |
177 if (mouse_inside_ || touch_inside_ != mouse_inside_ || touch_inside) | |
178 owner_->SetHovered(mouse_inside_ || touch_inside); | |
179 touch_inside_ = touch_inside; | |
180 } | |
181 | |
182 } // namespace ash | |
OLD | NEW |