| // Copyright 2013 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 "ui/views/win/appbar.h" |
| |
| #include <shellapi.h> |
| |
| #include "base/auto_reset.h" |
| #include "base/bind.h" |
| #include "base/location.h" |
| #include "base/threading/worker_pool.h" |
| #include "base/win/scoped_com_initializer.h" |
| #include "ui/views/widget/monitor_win.h" |
| |
| namespace views { |
| |
| namespace { |
| |
| void GetEdgesOnWorkerThread(HMONITOR monitor, int* edge) { |
| base::win::ScopedCOMInitializer com_initializer; |
| *edge = 0; |
| if (GetTopmostAutoHideTaskbarForEdge(ABE_LEFT, monitor)) |
| *edge = Appbar::EDGE_LEFT; |
| if (GetTopmostAutoHideTaskbarForEdge(ABE_TOP, monitor)) |
| *edge = Appbar::EDGE_TOP; |
| if (GetTopmostAutoHideTaskbarForEdge(ABE_RIGHT, monitor)) |
| *edge = Appbar::EDGE_RIGHT; |
| if (GetTopmostAutoHideTaskbarForEdge(ABE_BOTTOM, monitor)) |
| *edge = Appbar::EDGE_BOTTOM; |
| } |
| |
| } |
| |
| // static |
| Appbar* Appbar::instance() { |
| static Appbar* appbar = NULL; |
| if (!appbar) |
| appbar = new Appbar(); |
| return appbar; |
| } |
| |
| int Appbar::GetAutohideEdges(HMONITOR monitor, const base::Closure& callback) { |
| // Initialize the map with EDGE_BOTTOM. This is important, as if we return an |
| // initial value of 0 (no auto-hide edges) then we'll go fullscreen and |
| // windows will automatically remove WS_EX_TOPMOST from the appbar resulting |
| // in us thinking there is no auto-hide edges. By returning at least one edge |
| // we don't initially go fullscreen until we figure out the real auto-hide |
| // edges. |
| if (edge_map_.find(monitor) == edge_map_.end()) |
| edge_map_[monitor] = Appbar::EDGE_BOTTOM; |
| if (!in_callback_) { |
| int* edge = new int; |
| base::WorkerPool::PostTaskAndReply( |
| FROM_HERE, |
| base::Bind(&GetEdgesOnWorkerThread, |
| monitor, |
| base::Unretained(edge)), |
| base::Bind(&Appbar::OnGotEdges, |
| weak_factory_.GetWeakPtr(), |
| callback, |
| monitor, |
| edge_map_[monitor], |
| base::Owned(edge)), |
| false); |
| } |
| return edge_map_[monitor]; |
| } |
| |
| Appbar::Appbar() : weak_factory_(this), in_callback_(false) { |
| } |
| |
| Appbar::~Appbar() { |
| } |
| |
| void Appbar::OnGotEdges(const base::Closure& callback, |
| HMONITOR monitor, |
| int returned_edges, |
| int* edges) { |
| edge_map_[monitor] = *edges; |
| if (returned_edges == *edges) |
| return; |
| |
| base::AutoReset<bool> in_callback_setter(&in_callback_, true); |
| callback.Run(); |
| } |
| |
| } // namespace views |