Home | History | Annotate | Download | only in win
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/views/win/appbar.h"
      6 
      7 #include <shellapi.h>
      8 
      9 #include "base/auto_reset.h"
     10 #include "base/bind.h"
     11 #include "base/location.h"
     12 #include "base/threading/worker_pool.h"
     13 #include "base/win/scoped_com_initializer.h"
     14 #include "ui/views/widget/monitor_win.h"
     15 
     16 namespace views {
     17 
     18 namespace {
     19 
     20 void GetEdgesOnWorkerThread(HMONITOR monitor, int* edge) {
     21   base::win::ScopedCOMInitializer com_initializer;
     22   *edge = 0;
     23   if (GetTopmostAutoHideTaskbarForEdge(ABE_LEFT, monitor))
     24     *edge = Appbar::EDGE_LEFT;
     25   if (GetTopmostAutoHideTaskbarForEdge(ABE_TOP, monitor))
     26     *edge = Appbar::EDGE_TOP;
     27   if (GetTopmostAutoHideTaskbarForEdge(ABE_RIGHT, monitor))
     28     *edge = Appbar::EDGE_RIGHT;
     29   if (GetTopmostAutoHideTaskbarForEdge(ABE_BOTTOM, monitor))
     30     *edge = Appbar::EDGE_BOTTOM;
     31 }
     32 
     33 }
     34 
     35 // static
     36 Appbar* Appbar::instance() {
     37   static Appbar* appbar = NULL;
     38   if (!appbar)
     39     appbar = new Appbar();
     40   return appbar;
     41 }
     42 
     43 int Appbar::GetAutohideEdges(HMONITOR monitor, const base::Closure& callback) {
     44   // Initialize the map with EDGE_BOTTOM. This is important, as if we return an
     45   // initial value of 0 (no auto-hide edges) then we'll go fullscreen and
     46   // windows will automatically remove WS_EX_TOPMOST from the appbar resulting
     47   // in us thinking there is no auto-hide edges. By returning at least one edge
     48   // we don't initially go fullscreen until we figure out the real auto-hide
     49   // edges.
     50   if (edge_map_.find(monitor) == edge_map_.end())
     51     edge_map_[monitor] = Appbar::EDGE_BOTTOM;
     52   if (!in_callback_) {
     53     int* edge = new int;
     54     base::WorkerPool::PostTaskAndReply(
     55         FROM_HERE,
     56         base::Bind(&GetEdgesOnWorkerThread,
     57                    monitor,
     58                    base::Unretained(edge)),
     59         base::Bind(&Appbar::OnGotEdges,
     60                    weak_factory_.GetWeakPtr(),
     61                    callback,
     62                    monitor,
     63                    edge_map_[monitor],
     64                    base::Owned(edge)),
     65         false);
     66   }
     67   return edge_map_[monitor];
     68 }
     69 
     70 Appbar::Appbar() : weak_factory_(this), in_callback_(false) {
     71 }
     72 
     73 Appbar::~Appbar() {
     74 }
     75 
     76 void Appbar::OnGotEdges(const base::Closure& callback,
     77                         HMONITOR monitor,
     78                         int returned_edges,
     79                         int* edges) {
     80   edge_map_[monitor] = *edges;
     81   if (returned_edges == *edges)
     82     return;
     83 
     84   base::AutoReset<bool> in_callback_setter(&in_callback_, true);
     85   callback.Run();
     86 }
     87 
     88 }  // namespace views
     89