Chromium Code Reviews
|
| 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 |