Chromium Code Reviews| Index: chrome/browser/ui/panels/auto_hide_bottom_bar_win.cc |
| =================================================================== |
| --- chrome/browser/ui/panels/auto_hide_bottom_bar_win.cc (revision 0) |
| +++ chrome/browser/ui/panels/auto_hide_bottom_bar_win.cc (revision 0) |
| @@ -0,0 +1,191 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/ui/panels/auto_hide_bottom_bar.h" |
| + |
| +#include <windows.h> |
| +#include <shellapi.h> |
| + |
| +#include "base/compiler_specific.h" |
| +#include "base/logging.h" |
| +#include "base/timer.h" |
| +#include "ui/gfx/rect.h" |
| + |
| +namespace { |
| + |
| +// The thickness of the top area of an auto-hide taskbar that is still visible |
| +// when the taskbar is hidden. |
| +const int kAutoHideTaskbarThicknessPx = 2; |
| + |
| +// The polling interval to check auto-hide taskbar. |
| +const int kCheckTaskbarPollingIntervalMs = 500; |
| + |
| +class AutoHideBottomBarWin : public AutoHideBottomBar { |
| + public: |
| + explicit AutoHideBottomBarWin(Observer* observer); |
| + virtual ~AutoHideBottomBarWin(); |
| + |
| + virtual void UpdateWorkArea(const gfx::Rect& work_area) OVERRIDE; |
| + virtual bool IsEnabled() OVERRIDE; |
| + virtual int GetHeight() OVERRIDE; |
| + virtual Visibility GetVisibility() OVERRIDE; |
| + |
| + private: |
| + void ValidateAndGetWindow(); |
| + HWND GetAutoHideWindowOnScreenEdge(UINT edge) const; |
| + gfx::Rect GetBounds(); |
| + int GetHeightFromBounds(const gfx::Rect& bounds) const; |
| + Visibility GetVisibilityFromBounds(const gfx::Rect& bounds) const; |
| + void CheckTaskbar(); |
| + |
| + Observer* observer_; |
| + gfx::Rect work_area_; |
| + HMONITOR monitor_; |
| + HWND window_; |
| + bool aligned_to_bottom_; |
| + Visibility visibility_; |
| + int height_; |
| + base::RepeatingTimer<AutoHideBottomBarWin> polling_timer_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(AutoHideBottomBarWin); |
| +}; |
| + |
| +AutoHideBottomBarWin::AutoHideBottomBarWin(Observer* observer) |
| + : observer_(observer), |
| + window_(NULL), |
| + aligned_to_bottom_(false), |
| + visibility_(VISIBLE), |
| + height_(0) { |
| + DCHECK(observer); |
| +} |
| + |
| +AutoHideBottomBarWin::~AutoHideBottomBarWin() { |
| +} |
| + |
| +void AutoHideBottomBarWin::UpdateWorkArea(const gfx::Rect& work_area) { |
| + if (work_area_ == work_area) |
| + return; |
| + work_area_ = work_area; |
| + |
| + RECT rect = work_area_.ToRECT(); |
| + monitor_ = ::MonitorFromRect(&rect, MONITOR_DEFAULTTOPRIMARY); |
| + DCHECK(monitor_); |
| + |
| + ValidateAndGetWindow(); |
| + |
| + if (window_) { |
| + visibility_ = GetVisibility(); |
| + height_ = GetHeight(); |
| + |
| + if (!polling_timer_.IsRunning()) { |
| + polling_timer_.Start( |
| + base::TimeDelta::FromMilliseconds(kCheckTaskbarPollingIntervalMs), |
| + this, |
| + &AutoHideBottomBarWin::CheckTaskbar); |
| + } |
| + } else { |
| + if (polling_timer_.IsRunning()) |
| + polling_timer_.Stop(); |
| + } |
| +} |
| + |
| +bool AutoHideBottomBarWin::IsEnabled() { |
| + ValidateAndGetWindow(); |
| + return window_ != NULL && aligned_to_bottom_; |
| +} |
| + |
| +int AutoHideBottomBarWin::GetHeight() { |
| + return GetHeightFromBounds(GetBounds()); |
| +} |
| + |
| +AutoHideBottomBar::Visibility AutoHideBottomBarWin::GetVisibility() { |
| + return GetVisibilityFromBounds(GetBounds()); |
| +} |
| + |
| +void AutoHideBottomBarWin::ValidateAndGetWindow() { |
| + // Make sure |window_| is still valid since Shell might be restarted. |
| + if (window_) { |
| + if (::IsWindow(window_)) { |
| + // Re-check the edge alignment. |
| + aligned_to_bottom_ = window_ == GetAutoHideWindowOnScreenEdge(ABE_BOTTOM); |
| + return; |
| + } |
| + |
| + window_ = NULL; |
| + } |
| + |
| + // Otherwise, find the auto-hide taskbar window that could appear in any edge |
| + // of the work area. Note that we have to check all edges because the user |
| + // 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.
|
| + UINT edges[] = { ABE_BOTTOM, ABE_RIGHT, ABE_LEFT, ABE_TOP }; |
| + for (size_t i = 0; i < arraysize(edges); ++i) { |
| + window_ = GetAutoHideWindowOnScreenEdge(edges[i]); |
| + if (window_) { |
| + aligned_to_bottom_ = edges[i] == ABE_BOTTOM; |
| + break; |
| + } |
| + } |
| +} |
| + |
| +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.
|
| + APPBARDATA taskbar_data = { 0 }; |
| + taskbar_data.cbSize = sizeof APPBARDATA; |
| + taskbar_data.uEdge = edge; |
| + HWND window = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR, |
| + &taskbar_data)); |
| + return (::IsWindow(window) && |
| + (::MonitorFromWindow(window, MONITOR_DEFAULTTONULL) == monitor_) && |
| + (::GetWindowLong(window, GWL_EXSTYLE) & WS_EX_TOPMOST)) ? |
| + window : NULL; |
| +} |
| + |
| +gfx::Rect AutoHideBottomBarWin::GetBounds() { |
| + ValidateAndGetWindow(); |
| + if (!window_ || !aligned_to_bottom_) |
|
jennb
2011/08/23 20:28:34
if (!IsEnabled())
jianli
2011/08/26 00:18:16
Changed.
|
| + return gfx::Rect(); |
| + |
| + RECT rect; |
| + if (!::GetWindowRect(window_, &rect)) |
| + return gfx::Rect(); |
| + return gfx::Rect(rect); |
| +} |
| + |
| +int AutoHideBottomBarWin::GetHeightFromBounds(const gfx::Rect& bounds) const { |
| + return bounds.height(); |
| +} |
| + |
| +AutoHideBottomBar::Visibility AutoHideBottomBarWin::GetVisibilityFromBounds( |
| + const gfx::Rect& bounds) const { |
| + if (bounds.bottom() <= work_area_.bottom()) |
| + return VISIBLE; |
| + else if (bounds.y() >= work_area_.bottom() - kAutoHideTaskbarThicknessPx) |
| + return HIDDEN; |
| + else |
| + return ANIMATING; |
| +} |
| + |
| +void AutoHideBottomBarWin::CheckTaskbar() { |
| + gfx::Rect bounds = GetBounds(); |
| + |
| + // Check and notify the visibility change. |
| + Visibility visibility = GetVisibilityFromBounds(bounds); |
| + if (visibility != visibility_) { |
| + visibility_ = visibility; |
| + observer_->OnAutoHideBottomBarVisibilityChanged(visibility); |
| + } |
| + |
| + // Check and notify the height change. |
| + int height = GetHeightFromBounds(bounds); |
| + if (height != height_) { |
| + height_ = height; |
| + observer_->OnAutoHideBottomBarHeightChanged(height); |
| + } |
| +} |
| + |
| +} |
| + |
| +// static |
| +AutoHideBottomBar* AutoHideBottomBar::Create(Observer* observer) { |
| + return new AutoHideBottomBarWin(observer); |
| +} |
| Property changes on: chrome\browser\ui\panels\auto_hide_bottom_bar_win.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |