Chromium Code Reviews| Index: chrome/browser/ui/panels/auto_hiding_desktop_bar_win.cc |
| =================================================================== |
| --- chrome/browser/ui/panels/auto_hiding_desktop_bar_win.cc (revision 0) |
| +++ chrome/browser/ui/panels/auto_hiding_desktop_bar_win.cc (revision 0) |
| @@ -0,0 +1,237 @@ |
| +// 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_hiding_desktop_bar.h" |
| + |
| +#include <shellapi.h> |
| +#include <windows.h> |
| + |
| +#include "base/compiler_specific.h" |
| +#include "base/logging.h" |
| +#include "base/timer.h" |
| +#include "ui/gfx/rect.h" |
| +#include "views/widget/monitor_win.h" |
| + |
| +namespace { |
| + |
| +// Maximum number of taskbars we're interested in: bottom, left, and right. |
| +const int kMaxTaskbars = 3; |
| + |
| +// The thickness of the area of an auto-hiding taskbar that is still visible |
| +// when the taskbar becomes hidden. |
| +const int kAutoHideTaskbarThickness = 2; |
|
jennb
2011/08/26 20:41:57
kHiddenAutoHideTaskbarThickness?
kAutoHideTaskbarT
jianli
2011/08/26 22:18:52
Done.
|
| + |
| +// The polling interval to check auto-hiding taskbars. |
| +const int kCheckTaskbarPollingIntervalMs = 500; |
| + |
| +struct Taskbar { |
| + HWND window; |
| + AutoHidingDesktopBar::Visibility visibility; |
| + int thickness; |
| +}; |
| + |
| +class AutoHidingDesktopBarWin : public AutoHidingDesktopBar { |
| + public: |
| + explicit AutoHidingDesktopBarWin(Observer* observer); |
| + virtual ~AutoHidingDesktopBarWin(); |
| + |
| + // Overridden from AutoHidingDesktopBar: |
| + virtual void UpdateWorkArea(const gfx::Rect& work_area) OVERRIDE; |
| + virtual bool IsEnabled(Alignment alignment) OVERRIDE; |
| + virtual int GetThickness(Alignment alignment) const OVERRIDE; |
| + virtual Visibility GetVisibility(Alignment alignment) const OVERRIDE; |
| + |
| + private: |
| + // Callback to perform periodic check for taskbar changes. |
| + void OnPollingTimer(); |
| + |
| + // Returns true if there is at least one auto-hiding taskbar found. |
| + bool CheckTaskbars(bool notify_observer); |
| + |
| + gfx::Rect GetBounds(Alignment alignment) const; |
| + int GetThicknessFromBounds( |
| + Alignment alignment, const gfx::Rect& bounds) const; |
| + Visibility GetVisibilityFromBounds( |
| + Alignment alignment, const gfx::Rect& bounds) const; |
| + |
| + Observer* observer_; |
| + gfx::Rect work_area_; |
| + HMONITOR monitor_; |
| + Taskbar taskbars_[kMaxTaskbars]; |
| + base::RepeatingTimer<AutoHidingDesktopBarWin> polling_timer_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(AutoHidingDesktopBarWin); |
| +}; |
| + |
| +AutoHidingDesktopBarWin::AutoHidingDesktopBarWin(Observer* observer) |
| + : observer_(observer) { |
| + DCHECK(observer); |
| + memset(taskbars_, 0, sizeof(taskbars_)); |
| +} |
| + |
| +AutoHidingDesktopBarWin::~AutoHidingDesktopBarWin() { |
| +} |
| + |
| +void AutoHidingDesktopBarWin::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_); |
| + |
| + 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.
|
| + |
| + // 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.
|
| + // timer. If a taskbar is then set to auto-hiding, UpdateWorkArea will be |
| + // called due to the work area change. |
| + if (exists_taskbar) { |
| + if (!polling_timer_.IsRunning()) { |
| + polling_timer_.Start( |
| + base::TimeDelta::FromMilliseconds(kCheckTaskbarPollingIntervalMs), |
| + this, |
| + &AutoHidingDesktopBarWin::OnPollingTimer); |
| + } |
| + } else { |
| + if (polling_timer_.IsRunning()) |
| + polling_timer_.Stop(); |
| + } |
| +} |
| + |
| +bool AutoHidingDesktopBarWin::IsEnabled( |
| + AutoHidingDesktopBar::Alignment alignment) { |
| + CheckTaskbars(false); |
| + return taskbars_[static_cast<int>(alignment)].window != NULL; |
| +} |
| + |
| +int AutoHidingDesktopBarWin::GetThickness( |
| + AutoHidingDesktopBar::Alignment alignment) const { |
| + return GetThicknessFromBounds(alignment, GetBounds(alignment)); |
| +} |
| + |
| +AutoHidingDesktopBar::Visibility AutoHidingDesktopBarWin::GetVisibility( |
| + AutoHidingDesktopBar::Alignment alignment) const { |
| + return GetVisibilityFromBounds(alignment, GetBounds(alignment)); |
| +} |
| + |
| +gfx::Rect AutoHidingDesktopBarWin::GetBounds( |
| + AutoHidingDesktopBar::Alignment alignment) const { |
| + HWND taskbar_window = taskbars_[static_cast<int>(alignment)].window; |
| + if (!taskbar_window) |
| + return gfx::Rect(); |
| + |
| + RECT rect; |
| + if (!::GetWindowRect(taskbar_window, &rect)) |
| + return gfx::Rect(); |
| + return gfx::Rect(rect); |
| +} |
| + |
| +int AutoHidingDesktopBarWin::GetThicknessFromBounds( |
| + AutoHidingDesktopBar::Alignment alignment, const gfx::Rect& bounds) const { |
| + switch (alignment) { |
| + case AutoHidingDesktopBar::ALIGN_BOTTOM: |
| + return bounds.height(); |
| + case AutoHidingDesktopBar::ALIGN_LEFT: |
| + case AutoHidingDesktopBar::ALIGN_RIGHT: |
| + return bounds.width(); |
| + default: |
| + NOTREACHED(); |
| + return 0; |
| + } |
| +} |
| + |
| +AutoHidingDesktopBar::Visibility |
| +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.
|
| + 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.
|
| + switch (alignment) { |
| + case AutoHidingDesktopBar::ALIGN_BOTTOM: |
| + if (bounds.bottom() <= work_area_.bottom()) |
| + return VISIBLE; |
| + 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.
|
| + return HIDDEN; |
| + else |
| + return ANIMATING; |
| + |
| + case AutoHidingDesktopBar::ALIGN_LEFT: |
| + if (bounds.x() >= work_area_.x()) |
| + return VISIBLE; |
| + 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.
|
| + return HIDDEN; |
| + else |
| + return ANIMATING; |
| + |
| + case AutoHidingDesktopBar::ALIGN_RIGHT: |
| + if (bounds.right() <= work_area_.right()) |
| + return VISIBLE; |
| + 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.
|
| + return HIDDEN; |
| + else |
| + return ANIMATING; |
| + |
| + default: |
| + NOTREACHED(); |
| + return VISIBLE; |
| + } |
| +} |
| + |
| +void AutoHidingDesktopBarWin::OnPollingTimer() { |
| + CheckTaskbars(true); |
| +} |
| + |
| +bool AutoHidingDesktopBarWin::CheckTaskbars(bool notify_observer) { |
| + bool exists_taskbar = false; |
|
jennb
2011/08/26 20:41:57
s/exists_taskbar/taskbar_exists
jianli
2011/08/26 22:18:52
Done.
|
| + UINT edges[] = { ABE_BOTTOM, ABE_LEFT, ABE_RIGHT }; |
| + for (size_t i = 0; i < kMaxTaskbars; ++i) { |
| + taskbars_[i].window = |
| + views::GetTopmostAutoHideTaskbarForEdge(edges[i], monitor_); |
| + if (taskbars_[i].window) |
| + exists_taskbar = true; |
| + } |
| + 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
|
| + for (size_t i = 0; i < kMaxTaskbars; ++i) { |
| + taskbars_[i].thickness = 0; |
| + taskbars_[i].visibility = AutoHidingDesktopBar::HIDDEN; |
| + } |
| + return false; |
| + } |
| + |
| + bool thickness_changed = false; |
| + for (size_t i = 0; i < kMaxTaskbars; ++i) { |
| + AutoHidingDesktopBar::Alignment alignment = static_cast<Alignment>(i); |
| + |
| + gfx::Rect bounds = GetBounds(alignment); |
| + |
| + // Check the thickness change. |
| + int thickness = GetThicknessFromBounds(alignment, bounds); |
| + if (thickness != taskbars_[i].thickness) { |
| + taskbars_[i].thickness = thickness; |
| + thickness_changed = true; |
| + } |
| + |
| + // Check and notify the visibility change. |
| + AutoHidingDesktopBar::Visibility visibility = |
| + GetVisibilityFromBounds(alignment, bounds); |
| + if (visibility != taskbars_[i].visibility) { |
| + taskbars_[i].visibility = visibility; |
| + if (notify_observer) { |
| + observer_->OnAutoHidingDesktopBarVisibilityChanged(alignment, |
| + visibility); |
| + } |
| + } |
| + } |
| + |
| + // Notify the thickness change if needed. |
| + if (thickness_changed && notify_observer) |
| + observer_->OnAutoHidingDesktopBarThicknessChanged(); |
| + |
| + return true; |
| +} |
| + |
| +} // namespace |
| + |
| +// static |
| +AutoHidingDesktopBar* AutoHidingDesktopBar::Create(Observer* observer) { |
| + return new AutoHidingDesktopBarWin(observer); |
| +} |
| Property changes on: chrome\browser\ui\panels\auto_hiding_desktop_bar_win.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |