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