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_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 |