|
OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/ui/panels/auto_hiding_desktop_bar.h" | |
6 | |
7 #include <shellapi.h> | |
8 #include <windows.h> | |
9 | |
10 #include "base/compiler_specific.h" | |
11 #include "base/logging.h" | |
12 #include "base/timer.h" | |
13 #include "ui/gfx/rect.h" | |
14 #include "views/widget/monitor_win.h" | |
15 | |
16 namespace { | |
17 | |
18 // Maximum number of taskbars we're interested in: bottom, left, and right. | |
19 const int kMaxTaskbars = 3; | |
20 | |
21 // The thickness of the area of an auto-hiding taskbar that is still visible | |
22 // when the taskbar becomes hidden. | |
23 const int kAutoHideTaskbarThickness = 2; | |
jennb
2011/08/26 20:41:57
kHiddenAutoHideTaskbarThickness?
kAutoHideTaskbarT
jianli
2011/08/26 22:18:52
Done.
| |
24 | |
25 // The polling interval to check auto-hiding taskbars. | |
26 const int kCheckTaskbarPollingIntervalMs = 500; | |
27 | |
28 struct Taskbar { | |
29 HWND window; | |
30 AutoHidingDesktopBar::Visibility visibility; | |
31 int thickness; | |
32 }; | |
33 | |
34 class AutoHidingDesktopBarWin : public AutoHidingDesktopBar { | |
35 public: | |
36 explicit AutoHidingDesktopBarWin(Observer* observer); | |
37 virtual ~AutoHidingDesktopBarWin(); | |
38 | |
39 // Overridden from AutoHidingDesktopBar: | |
40 virtual void UpdateWorkArea(const gfx::Rect& work_area) OVERRIDE; | |
41 virtual bool IsEnabled(Alignment alignment) OVERRIDE; | |
42 virtual int GetThickness(Alignment alignment) const OVERRIDE; | |
43 virtual Visibility GetVisibility(Alignment alignment) const OVERRIDE; | |
44 | |
45 private: | |
46 // Callback to perform periodic check for taskbar changes. | |
47 void OnPollingTimer(); | |
48 | |
49 // Returns true if there is at least one auto-hiding taskbar found. | |
50 bool CheckTaskbars(bool notify_observer); | |
51 | |
52 gfx::Rect GetBounds(Alignment alignment) const; | |
53 int GetThicknessFromBounds( | |
54 Alignment alignment, const gfx::Rect& bounds) const; | |
55 Visibility GetVisibilityFromBounds( | |
56 Alignment alignment, const gfx::Rect& bounds) const; | |
57 | |
58 Observer* observer_; | |
59 gfx::Rect work_area_; | |
60 HMONITOR monitor_; | |
61 Taskbar taskbars_[kMaxTaskbars]; | |
62 base::RepeatingTimer<AutoHidingDesktopBarWin> polling_timer_; | |
63 | |
64 DISALLOW_COPY_AND_ASSIGN(AutoHidingDesktopBarWin); | |
65 }; | |
66 | |
67 AutoHidingDesktopBarWin::AutoHidingDesktopBarWin(Observer* observer) | |
68 : observer_(observer) { | |
69 DCHECK(observer); | |
70 memset(taskbars_, 0, sizeof(taskbars_)); | |
71 } | |
72 | |
73 AutoHidingDesktopBarWin::~AutoHidingDesktopBarWin() { | |
74 } | |
75 | |
76 void AutoHidingDesktopBarWin::UpdateWorkArea(const gfx::Rect& work_area) { | |
77 if (work_area_ == work_area) | |
78 return; | |
79 work_area_ = work_area; | |
80 | |
81 RECT rect = work_area_.ToRECT(); | |
82 monitor_ = ::MonitorFromRect(&rect, MONITOR_DEFAULTTOPRIMARY); | |
83 DCHECK(monitor_); | |
84 | |
85 bool exists_taskbar = CheckTaskbars(false); | |
jennb
2011/08/26 20:41:57
s/exists_taskbar/taskbar_exists ?
jianli
2011/08/26 22:18:52
Done.
| |
86 | |
87 // If not any auto-hiding taskbar exists, we do not need to start the polling | |
jennb
2011/08/26 20:41:57
s/not any/no
jianli
2011/08/26 22:18:52
Done.
| |
88 // timer. If a taskbar is then set to auto-hiding, UpdateWorkArea will be | |
89 // called due to the work area change. | |
90 if (exists_taskbar) { | |
91 if (!polling_timer_.IsRunning()) { | |
92 polling_timer_.Start( | |
93 base::TimeDelta::FromMilliseconds(kCheckTaskbarPollingIntervalMs), | |
94 this, | |
95 &AutoHidingDesktopBarWin::OnPollingTimer); | |
96 } | |
97 } else { | |
98 if (polling_timer_.IsRunning()) | |
99 polling_timer_.Stop(); | |
100 } | |
101 } | |
102 | |
103 bool AutoHidingDesktopBarWin::IsEnabled( | |
104 AutoHidingDesktopBar::Alignment alignment) { | |
105 CheckTaskbars(false); | |
106 return taskbars_[static_cast<int>(alignment)].window != NULL; | |
107 } | |
108 | |
109 int AutoHidingDesktopBarWin::GetThickness( | |
110 AutoHidingDesktopBar::Alignment alignment) const { | |
111 return GetThicknessFromBounds(alignment, GetBounds(alignment)); | |
112 } | |
113 | |
114 AutoHidingDesktopBar::Visibility AutoHidingDesktopBarWin::GetVisibility( | |
115 AutoHidingDesktopBar::Alignment alignment) const { | |
116 return GetVisibilityFromBounds(alignment, GetBounds(alignment)); | |
117 } | |
118 | |
119 gfx::Rect AutoHidingDesktopBarWin::GetBounds( | |
120 AutoHidingDesktopBar::Alignment alignment) const { | |
121 HWND taskbar_window = taskbars_[static_cast<int>(alignment)].window; | |
122 if (!taskbar_window) | |
123 return gfx::Rect(); | |
124 | |
125 RECT rect; | |
126 if (!::GetWindowRect(taskbar_window, &rect)) | |
127 return gfx::Rect(); | |
128 return gfx::Rect(rect); | |
129 } | |
130 | |
131 int AutoHidingDesktopBarWin::GetThicknessFromBounds( | |
132 AutoHidingDesktopBar::Alignment alignment, const gfx::Rect& bounds) const { | |
133 switch (alignment) { | |
134 case AutoHidingDesktopBar::ALIGN_BOTTOM: | |
135 return bounds.height(); | |
136 case AutoHidingDesktopBar::ALIGN_LEFT: | |
137 case AutoHidingDesktopBar::ALIGN_RIGHT: | |
138 return bounds.width(); | |
139 default: | |
140 NOTREACHED(); | |
141 return 0; | |
142 } | |
143 } | |
144 | |
145 AutoHidingDesktopBar::Visibility | |
146 AutoHidingDesktopBarWin::GetVisibilityFromBounds( | |
jennb
2011/08/26 20:41:57
Can you write a unittest that just tests this one
jianli
2011/08/26 22:18:52
Done.
| |
147 AutoHidingDesktopBar::Alignment alignment, const gfx::Rect& bounds) const { | |
jennb
2011/08/26 20:41:57
Might help to rename bounds to taskbar_bounds. I k
jianli
2011/08/26 22:18:52
Done.
| |
148 switch (alignment) { | |
149 case AutoHidingDesktopBar::ALIGN_BOTTOM: | |
150 if (bounds.bottom() <= work_area_.bottom()) | |
151 return VISIBLE; | |
152 else if (bounds.y() > work_area_.bottom() - kAutoHideTaskbarThickness) | |
jennb
2011/08/26 20:41:57
Should be >= ?
jianli
2011/08/26 22:18:52
Done.
| |
153 return HIDDEN; | |
154 else | |
155 return ANIMATING; | |
156 | |
157 case AutoHidingDesktopBar::ALIGN_LEFT: | |
158 if (bounds.x() >= work_area_.x()) | |
159 return VISIBLE; | |
160 else if (bounds.x() > work_area_.x() + kAutoHideTaskbarThickness) | |
jennb
2011/08/26 20:41:57
Should this be bounds.right() <= work_area_.x() +
jianli
2011/08/26 22:18:52
Done.
| |
161 return HIDDEN; | |
162 else | |
163 return ANIMATING; | |
164 | |
165 case AutoHidingDesktopBar::ALIGN_RIGHT: | |
166 if (bounds.right() <= work_area_.right()) | |
167 return VISIBLE; | |
168 else if (bounds.x() > work_area_.right() - kAutoHideTaskbarThickness) | |
jennb
2011/08/26 20:41:57
Should be >= ?
jianli
2011/08/26 22:18:52
Done.
| |
169 return HIDDEN; | |
170 else | |
171 return ANIMATING; | |
172 | |
173 default: | |
174 NOTREACHED(); | |
175 return VISIBLE; | |
176 } | |
177 } | |
178 | |
179 void AutoHidingDesktopBarWin::OnPollingTimer() { | |
180 CheckTaskbars(true); | |
181 } | |
182 | |
183 bool AutoHidingDesktopBarWin::CheckTaskbars(bool notify_observer) { | |
184 bool exists_taskbar = false; | |
jennb
2011/08/26 20:41:57
s/exists_taskbar/taskbar_exists
jianli
2011/08/26 22:18:52
Done.
| |
185 UINT edges[] = { ABE_BOTTOM, ABE_LEFT, ABE_RIGHT }; | |
186 for (size_t i = 0; i < kMaxTaskbars; ++i) { | |
187 taskbars_[i].window = | |
188 views::GetTopmostAutoHideTaskbarForEdge(edges[i], monitor_); | |
189 if (taskbars_[i].window) | |
190 exists_taskbar = true; | |
191 } | |
192 if (!exists_taskbar) { | |
jennb
2011/08/26 20:41:57
Maybe we should skip this if-clause and let the co
jianli
2011/08/26 22:18:52
As mentioned above, this is taken care of by work
| |
193 for (size_t i = 0; i < kMaxTaskbars; ++i) { | |
194 taskbars_[i].thickness = 0; | |
195 taskbars_[i].visibility = AutoHidingDesktopBar::HIDDEN; | |
196 } | |
197 return false; | |
198 } | |
199 | |
200 bool thickness_changed = false; | |
201 for (size_t i = 0; i < kMaxTaskbars; ++i) { | |
202 AutoHidingDesktopBar::Alignment alignment = static_cast<Alignment>(i); | |
203 | |
204 gfx::Rect bounds = GetBounds(alignment); | |
205 | |
206 // Check the thickness change. | |
207 int thickness = GetThicknessFromBounds(alignment, bounds); | |
208 if (thickness != taskbars_[i].thickness) { | |
209 taskbars_[i].thickness = thickness; | |
210 thickness_changed = true; | |
211 } | |
212 | |
213 // Check and notify the visibility change. | |
214 AutoHidingDesktopBar::Visibility visibility = | |
215 GetVisibilityFromBounds(alignment, bounds); | |
216 if (visibility != taskbars_[i].visibility) { | |
217 taskbars_[i].visibility = visibility; | |
218 if (notify_observer) { | |
219 observer_->OnAutoHidingDesktopBarVisibilityChanged(alignment, | |
220 visibility); | |
221 } | |
222 } | |
223 } | |
224 | |
225 // Notify the thickness change if needed. | |
226 if (thickness_changed && notify_observer) | |
227 observer_->OnAutoHidingDesktopBarThicknessChanged(); | |
228 | |
229 return true; | |
230 } | |
231 | |
232 } // namespace | |
233 | |
234 // static | |
235 AutoHidingDesktopBar* AutoHidingDesktopBar::Create(Observer* observer) { | |
236 return new AutoHidingDesktopBarWin(observer); | |
237 } | |
OLD | NEW |