// Copyright (c) 2012 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/display_settings_provider_win.h" #include #include "base/logging.h" #include "ui/views/widget/monitor_win.h" namespace { // The thickness of the area of an auto-hiding taskbar that is still visible // when the taskbar becomes hidden. const int kHiddenAutoHideTaskbarThickness = 2; // The polling interval to check auto-hiding taskbars. const int kCheckTaskbarPollingIntervalMs = 500; } // namespace DisplaySettingsProviderWin::DisplaySettingsProviderWin() : monitor_(NULL) { memset(taskbars_, 0, sizeof(taskbars_)); } DisplaySettingsProviderWin::~DisplaySettingsProviderWin() { } void DisplaySettingsProviderWin::OnDisplaySettingsChanged() { DisplaySettingsProvider::OnDisplaySettingsChanged(); gfx::Rect primary_work_area = GetPrimaryWorkArea(); RECT rect = primary_work_area.ToRECT(); monitor_ = ::MonitorFromRect(&rect, MONITOR_DEFAULTTOPRIMARY); DCHECK(monitor_); bool taskbar_exists = CheckTaskbars(false); // If no auto-hiding taskbar exists, we do not need to start the polling // timer. If a taskbar is then set to auto-hiding, UpdateWorkArea will be // called due to the work area change. if (taskbar_exists) { if (!polling_timer_.IsRunning()) { polling_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCheckTaskbarPollingIntervalMs), this, &DisplaySettingsProviderWin::OnPollingTimer); } } else { if (polling_timer_.IsRunning()) polling_timer_.Stop(); } } bool DisplaySettingsProviderWin::IsAutoHidingDesktopBarEnabled( DesktopBarAlignment alignment) { CheckTaskbars(false); return taskbars_[static_cast(alignment)].window != NULL; } int DisplaySettingsProviderWin::GetDesktopBarThickness( DesktopBarAlignment alignment) const { return GetDesktopBarThicknessFromBounds(alignment, GetBounds(alignment)); } DisplaySettingsProvider::DesktopBarVisibility DisplaySettingsProviderWin::GetDesktopBarVisibility( DesktopBarAlignment alignment) const { return GetDesktopBarVisibilityFromBounds(alignment, GetBounds(alignment)); } gfx::Rect DisplaySettingsProviderWin::GetBounds( DesktopBarAlignment alignment) const { HWND taskbar_window = taskbars_[static_cast(alignment)].window; if (!taskbar_window) return gfx::Rect(); RECT rect; if (!::GetWindowRect(taskbar_window, &rect)) return gfx::Rect(); return gfx::Rect(rect); } int DisplaySettingsProviderWin::GetDesktopBarThicknessFromBounds( DesktopBarAlignment alignment, const gfx::Rect& taskbar_bounds) const { switch (alignment) { case DESKTOP_BAR_ALIGNED_BOTTOM: return taskbar_bounds.height(); case DESKTOP_BAR_ALIGNED_LEFT: case DESKTOP_BAR_ALIGNED_RIGHT: return taskbar_bounds.width(); default: NOTREACHED(); return 0; } } DisplaySettingsProvider::DesktopBarVisibility DisplaySettingsProviderWin::GetDesktopBarVisibilityFromBounds( DesktopBarAlignment alignment, const gfx::Rect& taskbar_bounds) const { gfx::Rect primary_work_area = GetPrimaryWorkArea(); switch (alignment) { case DESKTOP_BAR_ALIGNED_BOTTOM: if (taskbar_bounds.bottom() <= primary_work_area.bottom()) return DESKTOP_BAR_VISIBLE; else if (taskbar_bounds.y() >= primary_work_area.bottom() - kHiddenAutoHideTaskbarThickness) return DESKTOP_BAR_HIDDEN; else return DESKTOP_BAR_ANIMATING; case DESKTOP_BAR_ALIGNED_LEFT: if (taskbar_bounds.x() >= primary_work_area.x()) return DESKTOP_BAR_VISIBLE; else if (taskbar_bounds.right() <= primary_work_area.x() + kHiddenAutoHideTaskbarThickness) return DESKTOP_BAR_HIDDEN; else return DESKTOP_BAR_ANIMATING; case DESKTOP_BAR_ALIGNED_RIGHT: if (taskbar_bounds.right() <= primary_work_area.right()) return DESKTOP_BAR_VISIBLE; else if (taskbar_bounds.x() >= primary_work_area.right() - kHiddenAutoHideTaskbarThickness) return DESKTOP_BAR_HIDDEN; else return DESKTOP_BAR_ANIMATING; default: NOTREACHED(); return DESKTOP_BAR_VISIBLE; } } void DisplaySettingsProviderWin::OnPollingTimer() { CheckTaskbars(true); } bool DisplaySettingsProviderWin::CheckTaskbars(bool notify_observer) { bool taskbar_exists = false; UINT edges[] = { ABE_BOTTOM }; for (size_t i = 0; i < kMaxTaskbars; ++i) { taskbars_[i].window = views::GetTopmostAutoHideTaskbarForEdge(edges[i], monitor_); if (taskbars_[i].window) taskbar_exists = true; } if (!taskbar_exists) { for (size_t i = 0; i < kMaxTaskbars; ++i) { taskbars_[i].thickness = 0; taskbars_[i].visibility = DESKTOP_BAR_HIDDEN; } return false; } for (size_t i = 0; i < kMaxTaskbars; ++i) { DesktopBarAlignment alignment = static_cast(i); gfx::Rect bounds = GetBounds(alignment); // Check the thickness change. int thickness = GetDesktopBarThicknessFromBounds(alignment, bounds); if (thickness != taskbars_[i].thickness) { taskbars_[i].thickness = thickness; if (notify_observer) { FOR_EACH_OBSERVER( DesktopBarObserver, desktop_bar_observers(), OnAutoHidingDesktopBarThicknessChanged(alignment, thickness)); } } // Check and notify the visibility change. DesktopBarVisibility visibility = GetDesktopBarVisibilityFromBounds( alignment, bounds); if (visibility != taskbars_[i].visibility) { taskbars_[i].visibility = visibility; if (notify_observer) { FOR_EACH_OBSERVER( DesktopBarObserver, desktop_bar_observers(), OnAutoHidingDesktopBarVisibilityChanged(alignment, visibility)); } } } return true; } // static DisplaySettingsProvider* DisplaySettingsProvider::Create() { return new DisplaySettingsProviderWin(); }