|
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_hide_bottom_bar.h" | |
6 | |
7 #include <windows.h> | |
8 #include <shellapi.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 | |
15 namespace { | |
16 | |
17 // The thickness of the top area of an auto-hide taskbar that is still visible | |
18 // when the taskbar is hidden. | |
19 const int kAutoHideTaskbarThicknessPx = 2; | |
20 | |
21 // The polling interval to check auto-hide taskbar. | |
22 const int kCheckTaskbarPollingIntervalMs = 500; | |
23 | |
24 class AutoHideBottomBarWin : public AutoHideBottomBar { | |
25 public: | |
26 explicit AutoHideBottomBarWin(Observer* observer); | |
27 virtual ~AutoHideBottomBarWin(); | |
28 | |
29 virtual void UpdateWorkArea(const gfx::Rect& work_area) OVERRIDE; | |
30 virtual bool IsEnabled() OVERRIDE; | |
31 virtual int GetHeight() OVERRIDE; | |
32 virtual Visibility GetVisibility() OVERRIDE; | |
33 | |
34 private: | |
35 void ValidateAndGetWindow(); | |
36 HWND GetAutoHideWindowOnScreenEdge(UINT edge) const; | |
37 gfx::Rect GetBounds(); | |
38 int GetHeightFromBounds(const gfx::Rect& bounds) const; | |
39 Visibility GetVisibilityFromBounds(const gfx::Rect& bounds) const; | |
40 void CheckTaskbar(); | |
41 | |
42 Observer* observer_; | |
43 gfx::Rect work_area_; | |
44 HMONITOR monitor_; | |
45 HWND window_; | |
46 bool aligned_to_bottom_; | |
47 Visibility visibility_; | |
48 int height_; | |
49 base::RepeatingTimer<AutoHideBottomBarWin> polling_timer_; | |
50 | |
51 DISALLOW_COPY_AND_ASSIGN(AutoHideBottomBarWin); | |
52 }; | |
53 | |
54 AutoHideBottomBarWin::AutoHideBottomBarWin(Observer* observer) | |
55 : observer_(observer), | |
56 window_(NULL), | |
57 aligned_to_bottom_(false), | |
58 visibility_(VISIBLE), | |
59 height_(0) { | |
60 DCHECK(observer); | |
61 } | |
62 | |
63 AutoHideBottomBarWin::~AutoHideBottomBarWin() { | |
64 } | |
65 | |
66 void AutoHideBottomBarWin::UpdateWorkArea(const gfx::Rect& work_area) { | |
67 if (work_area_ == work_area) | |
68 return; | |
69 work_area_ = work_area; | |
70 | |
71 RECT rect = work_area_.ToRECT(); | |
72 monitor_ = ::MonitorFromRect(&rect, MONITOR_DEFAULTTOPRIMARY); | |
73 DCHECK(monitor_); | |
74 | |
75 ValidateAndGetWindow(); | |
76 | |
77 if (window_) { | |
78 visibility_ = GetVisibility(); | |
79 height_ = GetHeight(); | |
80 | |
81 if (!polling_timer_.IsRunning()) { | |
82 polling_timer_.Start( | |
83 base::TimeDelta::FromMilliseconds(kCheckTaskbarPollingIntervalMs), | |
84 this, | |
85 &AutoHideBottomBarWin::CheckTaskbar); | |
86 } | |
87 } else { | |
88 if (polling_timer_.IsRunning()) | |
89 polling_timer_.Stop(); | |
90 } | |
91 } | |
92 | |
93 bool AutoHideBottomBarWin::IsEnabled() { | |
94 ValidateAndGetWindow(); | |
95 return window_ != NULL && aligned_to_bottom_; | |
96 } | |
97 | |
98 int AutoHideBottomBarWin::GetHeight() { | |
99 return GetHeightFromBounds(GetBounds()); | |
100 } | |
101 | |
102 AutoHideBottomBar::Visibility AutoHideBottomBarWin::GetVisibility() { | |
103 return GetVisibilityFromBounds(GetBounds()); | |
104 } | |
105 | |
106 void AutoHideBottomBarWin::ValidateAndGetWindow() { | |
107 // Make sure |window_| is still valid since Shell might be restarted. | |
108 if (window_) { | |
109 if (::IsWindow(window_)) { | |
110 // Re-check the edge alignment. | |
111 aligned_to_bottom_ = window_ == GetAutoHideWindowOnScreenEdge(ABE_BOTTOM); | |
112 return; | |
113 } | |
114 | |
115 window_ = NULL; | |
116 } | |
117 | |
118 // Otherwise, find the auto-hide taskbar window that could appear in any edge | |
119 // of the work area. Note that we have to check all edges because the user | |
120 // might move the taskbar from non-bottom edge to bottom edge. | |
Peter Kasting
2011/08/23 20:39:18
Note that it is technically possible to have multi
jianli
2011/08/26 00:18:16
Fixed.
| |
121 UINT edges[] = { ABE_BOTTOM, ABE_RIGHT, ABE_LEFT, ABE_TOP }; | |
122 for (size_t i = 0; i < arraysize(edges); ++i) { | |
123 window_ = GetAutoHideWindowOnScreenEdge(edges[i]); | |
124 if (window_) { | |
125 aligned_to_bottom_ = edges[i] == ABE_BOTTOM; | |
126 break; | |
127 } | |
128 } | |
129 } | |
130 | |
131 HWND AutoHideBottomBarWin::GetAutoHideWindowOnScreenEdge(UINT edge) const { | |
Peter Kasting
2011/08/23 20:39:18
It looks like this function is almost identical to
jianli
2011/08/26 00:18:16
Done.
| |
132 APPBARDATA taskbar_data = { 0 }; | |
133 taskbar_data.cbSize = sizeof APPBARDATA; | |
134 taskbar_data.uEdge = edge; | |
135 HWND window = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR, | |
136 &taskbar_data)); | |
137 return (::IsWindow(window) && | |
138 (::MonitorFromWindow(window, MONITOR_DEFAULTTONULL) == monitor_) && | |
139 (::GetWindowLong(window, GWL_EXSTYLE) & WS_EX_TOPMOST)) ? | |
140 window : NULL; | |
141 } | |
142 | |
143 gfx::Rect AutoHideBottomBarWin::GetBounds() { | |
144 ValidateAndGetWindow(); | |
145 if (!window_ || !aligned_to_bottom_) | |
jennb
2011/08/23 20:28:34
if (!IsEnabled())
jianli
2011/08/26 00:18:16
Changed.
| |
146 return gfx::Rect(); | |
147 | |
148 RECT rect; | |
149 if (!::GetWindowRect(window_, &rect)) | |
150 return gfx::Rect(); | |
151 return gfx::Rect(rect); | |
152 } | |
153 | |
154 int AutoHideBottomBarWin::GetHeightFromBounds(const gfx::Rect& bounds) const { | |
155 return bounds.height(); | |
156 } | |
157 | |
158 AutoHideBottomBar::Visibility AutoHideBottomBarWin::GetVisibilityFromBounds( | |
159 const gfx::Rect& bounds) const { | |
160 if (bounds.bottom() <= work_area_.bottom()) | |
161 return VISIBLE; | |
162 else if (bounds.y() >= work_area_.bottom() - kAutoHideTaskbarThicknessPx) | |
163 return HIDDEN; | |
164 else | |
165 return ANIMATING; | |
166 } | |
167 | |
168 void AutoHideBottomBarWin::CheckTaskbar() { | |
169 gfx::Rect bounds = GetBounds(); | |
170 | |
171 // Check and notify the visibility change. | |
172 Visibility visibility = GetVisibilityFromBounds(bounds); | |
173 if (visibility != visibility_) { | |
174 visibility_ = visibility; | |
175 observer_->OnAutoHideBottomBarVisibilityChanged(visibility); | |
176 } | |
177 | |
178 // Check and notify the height change. | |
179 int height = GetHeightFromBounds(bounds); | |
180 if (height != height_) { | |
181 height_ = height; | |
182 observer_->OnAutoHideBottomBarHeightChanged(height); | |
183 } | |
184 } | |
185 | |
186 } | |
187 | |
188 // static | |
189 AutoHideBottomBar* AutoHideBottomBar::Create(Observer* observer) { | |
190 return new AutoHideBottomBarWin(observer); | |
191 } | |
OLD | NEW |