Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(729)

Unified Diff: chrome/browser/ui/views/frame/minimize_button_metrics_win.cc

Issue 1952473002: Fix for 504133 - wandering identity switcher button (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Must have relied on an include chain which changed for gfx::Point. Now explicitly included. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/views/frame/minimize_button_metrics_win.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/views/frame/minimize_button_metrics_win.cc
diff --git a/chrome/browser/ui/views/frame/minimize_button_metrics_win.cc b/chrome/browser/ui/views/frame/minimize_button_metrics_win.cc
index 986f5e2d855a68e6145e1371767869d93b1a99c3..9d61b121780f56544126c3ea81a7a52b45809560 100644
--- a/chrome/browser/ui/views/frame/minimize_button_metrics_win.cc
+++ b/chrome/browser/ui/views/frame/minimize_button_metrics_win.cc
@@ -6,33 +6,33 @@
#include "base/logging.h"
#include "base/i18n/rtl.h"
+#include "base/win/windows_version.h"
+#include "dwmapi.h"
#include "ui/base/win/shell.h"
#include "ui/display/win/dpi.h"
+#include "ui/display/win/screen_win.h"
+#include "ui/gfx/geometry/point.h"
namespace {
-int GetMinimizeButtonOffsetForWindow(HWND hwnd) {
- // The WM_GETTITLEBARINFOEX message can fail if we are not active/visible. By
- // fail we get a location of 0; the return status code is always the same and
- // similarly the state never seems to change (titlebar_info.rgstate).
- TITLEBARINFOEX titlebar_info = {0};
- titlebar_info.cbSize = sizeof(TITLEBARINFOEX);
- SendMessage(hwnd, WM_GETTITLEBARINFOEX, 0,
- reinterpret_cast<WPARAM>(&titlebar_info));
-
- if (titlebar_info.rgrect[2].left == titlebar_info.rgrect[2].right ||
- (titlebar_info.rgstate[2] & (STATE_SYSTEM_INVISIBLE |
- STATE_SYSTEM_OFFSCREEN |
- STATE_SYSTEM_UNAVAILABLE))) {
- return 0;
- }
-
- // WM_GETTITLEBARINFOEX returns rects in screen coordinates in pixels.
- // We need to convert the minimize button corner offset to DIP before
- // returning it.
- POINT minimize_button_corner = { titlebar_info.rgrect[2].left, 0 };
- MapWindowPoints(HWND_DESKTOP, hwnd, &minimize_button_corner, 1);
- return minimize_button_corner.x / display::win::GetDPIScale();
+// These constants were determined by manually adding various offsets
+// until the identity switcher was placed at the same location as before.
+// When a new or updated OS version is released, a new constant may need
+// to be added to this list and GetDefaultButtonBoundsOffset() is updated.
+const int kWin7ButtonBoundsPositionOffset = 1;
+const int kWin8ButtonBoundsPositionOffset = 10;
+const int kWin10ButtonBoundsPositionOffset = 6;
+const int kInvalidOffset = static_cast<int>(0x80000000);
+
+using base::win::GetVersion;
+using display::win::ScreenWin;
+
+int GetDefaultButtonBoundsOffset() {
+ if (GetVersion() >= base::win::VERSION_WIN10)
+ return kWin10ButtonBoundsPositionOffset;
+ if (GetVersion() >= base::win::VERSION_WIN8)
+ return kWin8ButtonBoundsPositionOffset;
+ return kWin7ButtonBoundsPositionOffset;
}
} // namespace
@@ -40,6 +40,9 @@ int GetMinimizeButtonOffsetForWindow(HWND hwnd) {
// static
int MinimizeButtonMetrics::last_cached_minimize_button_x_delta_ = 0;
+// static
+int MinimizeButtonMetrics::button_bounds_position_offset_ = kInvalidOffset;
+
MinimizeButtonMetrics::MinimizeButtonMetrics()
: hwnd_(nullptr),
cached_minimize_button_x_delta_(last_cached_minimize_button_x_delta_),
@@ -60,6 +63,90 @@ void MinimizeButtonMetrics::OnHWNDActivated() {
// correct.
}
+// This function attempts to calculate the odd and varying difference
+// between the results of DwmGetWindowAttribute with the
+// DWMWA_CAPTION_BUTTON_BOUNDS flag and the information from the
+// WM_GETTITLEBARINFOEX message. It will return an empirically determined
+// offset until the window has been activated and the message returns
+// valid rectangles.
+int MinimizeButtonMetrics::GetButtonBoundsPositionOffset(
+ const RECT& button_bounds,
+ const RECT& window_bounds) const {
+ if (button_bounds_position_offset_ == kInvalidOffset) {
+ if (!was_activated_)
+ return GetDefaultButtonBoundsOffset();
+ TITLEBARINFOEX info = {0};
+ info.cbSize = sizeof(info);
+ SendMessage(hwnd_, WM_GETTITLEBARINFOEX, 0,
+ reinterpret_cast<LPARAM>(&info));
+ if (info.rgrect[2].right == info.rgrect[2].left ||
+ (info.rgstate[2] & (STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN |
+ STATE_SYSTEM_UNAVAILABLE)))
+ return GetDefaultButtonBoundsOffset();
+ button_bounds_position_offset_ =
+ info.rgrect[2].left - (button_bounds.left + window_bounds.left);
+ }
+ return button_bounds_position_offset_;
+}
+
+int MinimizeButtonMetrics::GetMinimizeButtonOffsetForWindow() const {
+ bool dwm_button_pos = false;
+ POINT minimize_button_corner = {0};
+ RECT button_bounds = {0};
+ if (SUCCEEDED(DwmGetWindowAttribute(hwnd_, DWMWA_CAPTION_BUTTON_BOUNDS,
+ &button_bounds, sizeof(button_bounds)))) {
+ if (button_bounds.left != button_bounds.right) {
+ // This converts the button coordinate into screen coordinates
+ // thus, ensuring that the identity switcher is placed in the
+ // same location as before. An additional constant is added because
+ // there is a difference between the caption button bounds and
+ // the values obtained through WM_GETTITLEBARINFOEX. This difference
+ // varies between OS versions, and no metric describing this difference
+ // has been located.
+ RECT window_bounds = {0};
+ if (GetWindowRect(hwnd_, &window_bounds)) {
+ int offset =
+ GetButtonBoundsPositionOffset(button_bounds, window_bounds);
+ minimize_button_corner = {
+ button_bounds.left + window_bounds.left + offset, 0};
+ dwm_button_pos = true;
+ }
+ }
+ }
+ if (!dwm_button_pos) {
+ // Fallback to using the message for the titlebar info only if the above
+ // code fails. It can fail if DWM is disabled globally or only for the
+ // given HWND. The WM_GETTITLEBARINFOEX message can fail if we are not
+ // active/visible. By fail we get a location of 0; the return status
+ // code is always the same and similarly the state never seems to change
+ // (titlebar_info.rgstate).
+ TITLEBARINFOEX titlebar_info = {0};
+ titlebar_info.cbSize = sizeof(TITLEBARINFOEX);
+ SendMessage(hwnd_, WM_GETTITLEBARINFOEX, 0,
+ reinterpret_cast<WPARAM>(&titlebar_info));
+
+ // Under DWM WM_GETTITLEBARINFOEX won't return the right thing until after
+ // WM_NCACTIVATE (maybe it returns classic values?). In an attempt to
+ // return a consistant value we cache the last value across instances and
+ // use it until we get the activate.
+ if (titlebar_info.rgrect[2].left == titlebar_info.rgrect[2].right ||
+ (titlebar_info.rgstate[2] &
+ (STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN |
+ STATE_SYSTEM_UNAVAILABLE)))
+ return 0;
+ minimize_button_corner = {titlebar_info.rgrect[2].left, 0};
+ }
+
+ // WM_GETTITLEBARINFOEX returns rects in screen coordinates in pixels.
+ // DWMNA_CAPTION_BUTTON_BOUNDS is in window (not client) coordinates,
+ // but it has been converted to screen coordinates above. We need to
+ // convert the minimize button corner offset to DIP before returning it.
+ MapWindowPoints(HWND_DESKTOP, hwnd_, &minimize_button_corner, 1);
+ gfx::Point pixel_point = {minimize_button_corner.x, 0};
+ gfx::Point dip_point = ScreenWin::ClientToDIPPoint(hwnd_, pixel_point);
+ return dip_point.x();
+}
+
int MinimizeButtonMetrics::GetMinimizeButtonOffsetX() const {
// Under DWM WM_GETTITLEBARINFOEX won't return the right thing until after
// WM_NCACTIVATE (maybe it returns classic values?). In an attempt to return a
@@ -87,7 +174,7 @@ int MinimizeButtonMetrics::GetMinimizeButtonOffsetX() const {
}
int MinimizeButtonMetrics::GetAndCacheMinimizeButtonOffsetX() const {
- const int minimize_button_offset = GetMinimizeButtonOffsetForWindow(hwnd_);
+ const int minimize_button_offset = GetMinimizeButtonOffsetForWindow();
if (minimize_button_offset <= 0)
return 0;
« no previous file with comments | « chrome/browser/ui/views/frame/minimize_button_metrics_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698