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