• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
12 namespace {
13 
GetMinimizeButtonOffsetForWindow(HWND hwnd)14 int GetMinimizeButtonOffsetForWindow(HWND hwnd) {
15   // The WM_GETTITLEBARINFOEX message can fail if we are not active/visible. By
16   // fail we get a location of 0; the return status code is always the same and
17   // similarly the state never seems to change (titlebar_info.rgstate).
18   TITLEBARINFOEX titlebar_info = {0};
19   titlebar_info.cbSize = sizeof(TITLEBARINFOEX);
20   SendMessage(hwnd, WM_GETTITLEBARINFOEX, 0,
21               reinterpret_cast<WPARAM>(&titlebar_info));
22 
23   if (titlebar_info.rgrect[2].left == titlebar_info.rgrect[2].right ||
24       (titlebar_info.rgstate[2] & (STATE_SYSTEM_INVISIBLE |
25                                    STATE_SYSTEM_OFFSCREEN |
26                                    STATE_SYSTEM_UNAVAILABLE))) {
27     return 0;
28   }
29 
30   // WM_GETTITLEBARINFOEX returns rects in screen coordinates in pixels.
31   // We need to convert the minimize button corner offset to DIP before
32   // returning it.
33   POINT minimize_button_corner = { titlebar_info.rgrect[2].left, 0 };
34   MapWindowPoints(HWND_DESKTOP, hwnd, &minimize_button_corner, 1);
35   return minimize_button_corner.x / gfx::win::GetDeviceScaleFactor();
36 }
37 
38 }  // namespace
39 
40 // static
41 int MinimizeButtonMetrics::last_cached_minimize_button_x_delta_ = 0;
42 
MinimizeButtonMetrics()43 MinimizeButtonMetrics::MinimizeButtonMetrics()
44     : hwnd_(NULL),
45       cached_minimize_button_x_delta_(last_cached_minimize_button_x_delta_),
46       was_activated_(false) {
47 }
48 
~MinimizeButtonMetrics()49 MinimizeButtonMetrics::~MinimizeButtonMetrics() {
50 }
51 
Init(HWND hwnd)52 void MinimizeButtonMetrics::Init(HWND hwnd) {
53   DCHECK(!hwnd_);
54   hwnd_ = hwnd;
55 }
56 
OnHWNDActivated()57 void MinimizeButtonMetrics::OnHWNDActivated() {
58   was_activated_ = true;
59   // NOTE: we don't cache here as it seems only after the activate is the value
60   // correct.
61 }
62 
GetMinimizeButtonOffsetX() const63 int MinimizeButtonMetrics::GetMinimizeButtonOffsetX() const {
64   // Under DWM WM_GETTITLEBARINFOEX won't return the right thing until after
65   // WM_NCACTIVATE (maybe it returns classic values?). In an attempt to return a
66   // consistant value we cache the last value across instances and use it until
67   // we get the activate.
68   if (was_activated_ || !ui::win::IsAeroGlassEnabled() ||
69       cached_minimize_button_x_delta_ == 0) {
70     const int minimize_button_offset = GetAndCacheMinimizeButtonOffsetX();
71     if (minimize_button_offset > 0)
72       return minimize_button_offset;
73   }
74 
75   // If we fail to get the minimize button offset via the WM_GETTITLEBARINFOEX
76   // message then calculate and return this via the
77   // cached_minimize_button_x_delta_ member value. Please see
78   // CacheMinimizeButtonDelta() for more details.
79   DCHECK(cached_minimize_button_x_delta_);
80 
81   if (base::i18n::IsRTL())
82     return cached_minimize_button_x_delta_;
83 
84   RECT client_rect = {0};
85   GetClientRect(hwnd_, &client_rect);
86   return client_rect.right - cached_minimize_button_x_delta_;
87 }
88 
GetAndCacheMinimizeButtonOffsetX() const89 int MinimizeButtonMetrics::GetAndCacheMinimizeButtonOffsetX() const {
90   const int minimize_button_offset = GetMinimizeButtonOffsetForWindow(hwnd_);
91   if (minimize_button_offset <= 0)
92     return 0;
93 
94   if (base::i18n::IsRTL()) {
95     cached_minimize_button_x_delta_ = minimize_button_offset;
96   } else {
97     RECT client_rect = {0};
98     GetClientRect(hwnd_, &client_rect);
99     cached_minimize_button_x_delta_ =
100         client_rect.right - minimize_button_offset;
101   }
102   last_cached_minimize_button_x_delta_ = cached_minimize_button_x_delta_;
103   return minimize_button_offset;
104 }
105