| // 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 <shellapi.h> |
| |
| #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<int>(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<int>(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<DesktopBarAlignment>(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(); |
| } |