minimize_button_metrics_win.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1// Copyright (c) 2012 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 "chrome/browser/ui/views/frame/minimize_button_metrics_win.h"
6
7#include "base/logging.h"
8#include "base/i18n/rtl.h"
9#include "ui/base/win/shell.h"
10#include "ui/gfx/win/dpi.h"
11
12namespace {
13
14int GetMinimizeButtonOffsetForWindow(HWND hwnd) {
15  // The WM_GETTITLEBARINFOEX message can fail if we are not active/visible.
16  TITLEBARINFOEX titlebar_info = {0};
17  titlebar_info.cbSize = sizeof(TITLEBARINFOEX);
18  SendMessage(hwnd, WM_GETTITLEBARINFOEX, 0,
19              reinterpret_cast<WPARAM>(&titlebar_info));
20
21  // NOTE: TITLEBARINFOEX coordinates are not scaled (they are physical). As
22  // Chrome is not DPIAware we need to properly scale the coordinates as
23  // MapWindowPoints() expects scaled coordinates.
24  POINT minimize_button_corner = { titlebar_info.rgrect[2].left /
25                                   gfx::win::GetUndocumentedDPIScale(),
26                                   0 };
27  MapWindowPoints(HWND_DESKTOP, hwnd, &minimize_button_corner, 1);
28  return minimize_button_corner.x / gfx::win::GetDeviceScaleFactor();
29}
30
31}  // namespace
32
33// static
34int MinimizeButtonMetrics::last_cached_minimize_button_x_delta_ = 0;
35
36MinimizeButtonMetrics::MinimizeButtonMetrics()
37    : hwnd_(NULL),
38      cached_minimize_button_x_delta_(last_cached_minimize_button_x_delta_),
39      was_activated_(false) {
40}
41
42MinimizeButtonMetrics::~MinimizeButtonMetrics() {
43}
44
45void MinimizeButtonMetrics::Init(HWND hwnd) {
46  DCHECK(!hwnd_);
47  hwnd_ = hwnd;
48}
49
50void MinimizeButtonMetrics::OnHWNDActivated() {
51  was_activated_ = true;
52  // NOTE: we don't cache here as it seems only after the activate is the value
53  // correct.
54}
55
56int MinimizeButtonMetrics::GetMinimizeButtonOffsetX() const {
57  // Under DWM WM_GETTITLEBARINFOEX won't return the right thing until after
58  // WM_NCACTIVATE (maybe it returns classic values?). In an attempt to return a
59  // consistant value we cache the last value across instances and use it until
60  // we get the activate.
61  if (was_activated_ || !ui::win::IsAeroGlassEnabled() ||
62      cached_minimize_button_x_delta_ == 0) {
63    const int minimize_button_offset = GetAndCacheMinimizeButtonOffsetX();
64    if (minimize_button_offset > 0)
65      return minimize_button_offset;
66  }
67
68  // If we fail to get the minimize button offset via the WM_GETTITLEBARINFOEX
69  // message then calculate and return this via the
70  // cached_minimize_button_x_delta_ member value. Please see
71  // CacheMinimizeButtonDelta() for more details.
72  DCHECK(cached_minimize_button_x_delta_);
73
74  if (base::i18n::IsRTL())
75    return cached_minimize_button_x_delta_;
76
77  RECT client_rect = {0};
78  GetClientRect(hwnd_, &client_rect);
79  return client_rect.right - cached_minimize_button_x_delta_;
80}
81
82int MinimizeButtonMetrics::GetAndCacheMinimizeButtonOffsetX() const {
83  const int minimize_button_offset = GetMinimizeButtonOffsetForWindow(hwnd_);
84  if (minimize_button_offset <= 0)
85    return 0;
86
87  if (base::i18n::IsRTL()) {
88    cached_minimize_button_x_delta_ = minimize_button_offset;
89  } else {
90    RECT client_rect = {0};
91    GetClientRect(hwnd_, &client_rect);
92    cached_minimize_button_x_delta_ =
93        client_rect.right - minimize_button_offset;
94  }
95  last_cached_minimize_button_x_delta_ = cached_minimize_button_x_delta_;
96  return minimize_button_offset;
97}
98