Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/views/frame/minimize_button_metrics_win.h" | 5 #include "chrome/browser/ui/views/frame/minimize_button_metrics_win.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/i18n/rtl.h" | 8 #include "base/i18n/rtl.h" |
| 9 #include "base/win/windows_version.h" | |
| 9 #include "dwmapi.h" | 10 #include "dwmapi.h" |
| 10 #include "ui/base/win/shell.h" | 11 #include "ui/base/win/shell.h" |
| 11 #include "ui/display/win/dpi.h" | 12 #include "ui/display/win/dpi.h" |
| 12 #include "ui/display/win/screen_win.h" | 13 #include "ui/display/win/screen_win.h" |
| 13 | 14 |
| 14 namespace { | 15 namespace { |
| 15 | 16 |
| 17 const int kWin7ButtonBoundsPositionOffset = 1; | |
| 18 const int kWin8ButtonBoundsPositionOffset = 10; | |
| 19 const int kWin10ButtonBoundsPositionOffset = 6; | |
| 20 const int kInvalidOffset = (int)0x80000000; | |
| 21 | |
| 22 using base::win::GetVersion; | |
| 16 using display::win::ScreenWin; | 23 using display::win::ScreenWin; |
| 17 | 24 |
| 25 static int gButtonBoundsPositionOffset = kInvalidOffset; | |
| 26 | |
| 27 int GetDefaultButtonBoundsOffset() { | |
|
Ilya Kulshin
2016/05/09 19:53:23
Add a comment describing how to determine the offs
kylix_rd
2016/05/09 21:54:23
I think that adding a DCHECK may be too aggressive
| |
| 28 return (GetVersion() >= base::win::VERSION_WIN10) | |
|
Ilya Kulshin
2016/05/09 19:53:23
I think this code would be more readable as a seri
kylix_rd
2016/05/09 21:54:23
Done.
| |
| 29 ? kWin10ButtonBoundsPositionOffset | |
| 30 : (GetVersion() >= base::win::VERSION_WIN8) | |
| 31 ? kWin8ButtonBoundsPositionOffset | |
| 32 : kWin7ButtonBoundsPositionOffset; | |
| 33 } | |
| 34 | |
| 35 // This function attempts to calculate the odd and varying difference | |
| 36 // between the results of DwmGetWindowAttribute with the | |
| 37 // DWMWA_CAPTION_BUTTON_BOUNDS flag and the information from the | |
| 38 // WM_GETTITLEBARINFOEX message. It will return an empirically determined | |
| 39 // offset until the window has been activated and the message returns | |
| 40 // valid rectangles. | |
| 41 int GetButtonBoundsPositionOffset(HWND hwnd, | |
| 42 const RECT& button_bounds, | |
| 43 const RECT& window_bounds, | |
| 44 bool was_activated) { | |
|
Ilya Kulshin
2016/05/09 19:53:23
Consider making these into member functions so you
kylix_rd
2016/05/09 21:54:23
Done.
| |
| 45 if (gButtonBoundsPositionOffset == kInvalidOffset) { | |
| 46 if (!was_activated) | |
| 47 return GetDefaultButtonBoundsOffset(); | |
| 48 TITLEBARINFOEX info = {0}; | |
| 49 info.cbSize = sizeof(info); | |
| 50 SendMessage(hwnd, WM_GETTITLEBARINFOEX, 0, reinterpret_cast<LPARAM>(&info)); | |
| 51 if (info.rgrect[2].right == info.rgrect[2].left || | |
| 52 (info.rgstate[2] & (STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN | | |
| 53 STATE_SYSTEM_UNAVAILABLE))) | |
| 54 return GetDefaultButtonBoundsOffset(); | |
| 55 gButtonBoundsPositionOffset = | |
| 56 info.rgrect[2].left - (button_bounds.left + window_bounds.left); | |
| 57 } | |
| 58 return gButtonBoundsPositionOffset; | |
| 59 } | |
| 60 | |
| 18 int GetMinimizeButtonOffsetForWindow(HWND hwnd, bool was_activated) { | 61 int GetMinimizeButtonOffsetForWindow(HWND hwnd, bool was_activated) { |
| 19 bool dwm_button_pos = false; | 62 bool dwm_button_pos = false; |
| 20 POINT minimize_button_corner = {0}; | 63 POINT minimize_button_corner = {0}; |
| 21 RECT button_bounds = {0}; | 64 RECT button_bounds = {0}; |
| 22 if (SUCCEEDED(DwmGetWindowAttribute(hwnd, DWMWA_CAPTION_BUTTON_BOUNDS, | 65 if (SUCCEEDED(DwmGetWindowAttribute(hwnd, DWMWA_CAPTION_BUTTON_BOUNDS, |
| 23 &button_bounds, sizeof(button_bounds)))) { | 66 &button_bounds, sizeof(button_bounds)))) { |
| 24 if (button_bounds.left != button_bounds.right) { | 67 if (button_bounds.left != button_bounds.right) { |
| 25 // This converts the button coordinate into screen coordinates | 68 // This converts the button coordinate into screen coordinates |
| 26 // thus, ensuring that the identity switcher is placed in the | 69 // thus, ensuring that the identity switcher is placed in the |
| 27 // same location as before. | 70 // same location as before. An additional constant is added because |
| 71 // there is a difference between the caption button bounds and | |
| 72 // the values obtained through WM_GETTITLEBARINFOEX. This difference | |
| 73 // varies between OS versions, and no metric describing this difference | |
| 74 // has been located. | |
| 28 RECT window_bounds = {0}; | 75 RECT window_bounds = {0}; |
| 29 if (GetWindowRect(hwnd, &window_bounds)) { | 76 if (GetWindowRect(hwnd, &window_bounds)) { |
| 30 minimize_button_corner = {button_bounds.left + window_bounds.left, 0}; | 77 int offset = GetButtonBoundsPositionOffset( |
| 78 hwnd, button_bounds, window_bounds, was_activated); | |
| 79 minimize_button_corner = { | |
| 80 button_bounds.left + window_bounds.left + offset, 0}; | |
| 31 dwm_button_pos = true; | 81 dwm_button_pos = true; |
| 32 } | 82 } |
| 33 } | 83 } |
| 34 } | 84 } |
| 35 if (!dwm_button_pos) { | 85 if (!dwm_button_pos) { |
| 36 // Fallback to using the message for the titlebar info only if the above | 86 // Fallback to using the message for the titlebar info only if the above |
| 37 // code fails. It can fail if DWM is disabled globally or only for the | 87 // code fails. It can fail if DWM is disabled globally or only for the |
| 38 // given HWND. The WM_GETTITLEBARINFOEX message can fail if we are not | 88 // given HWND. The WM_GETTITLEBARINFOEX message can fail if we are not |
| 39 // active/visible. By fail we get a location of 0; the return status | 89 // active/visible. By fail we get a location of 0; the return status |
| 40 // code is always the same and similarly the state never seems to change | 90 // code is always the same and similarly the state never seems to change |
| 41 // (titlebar_info.rgstate). | 91 // (titlebar_info.rgstate). |
| 42 TITLEBARINFOEX titlebar_info = {0}; | 92 TITLEBARINFOEX titlebar_info = {0}; |
| 43 titlebar_info.cbSize = sizeof(TITLEBARINFOEX); | 93 titlebar_info.cbSize = sizeof(TITLEBARINFOEX); |
| 44 SendMessage(hwnd, WM_GETTITLEBARINFOEX, 0, | 94 SendMessage(hwnd, WM_GETTITLEBARINFOEX, 0, |
| 45 reinterpret_cast<WPARAM>(&titlebar_info)); | 95 reinterpret_cast<WPARAM>(&titlebar_info)); |
| 46 | 96 |
| 47 // Under DWM WM_GETTITLEBARINFOEX won't return the right thing until after | 97 // Under DWM WM_GETTITLEBARINFOEX won't return the right thing until after |
| 48 // WM_NCACTIVATE (maybe it returns classic values?). In an attempt to | 98 // WM_NCACTIVATE (maybe it returns classic values?). In an attempt to |
| 49 // return a consistant value we cache the last value across instances and | 99 // return a consistant value we cache the last value across instances and |
| 50 // use it until we get the activate. | 100 // use it until we get the activate. |
| 51 if (!was_activated || | 101 if (titlebar_info.rgrect[2].left == titlebar_info.rgrect[2].right || |
| 52 titlebar_info.rgrect[2].left == titlebar_info.rgrect[2].right || | |
| 53 (titlebar_info.rgstate[2] & | 102 (titlebar_info.rgstate[2] & |
| 54 (STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN | | 103 (STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN | |
| 55 STATE_SYSTEM_UNAVAILABLE))) { | 104 STATE_SYSTEM_UNAVAILABLE))) |
| 56 return 0; | 105 return 0; |
| 57 } | |
| 58 minimize_button_corner = {titlebar_info.rgrect[2].left, 0}; | 106 minimize_button_corner = {titlebar_info.rgrect[2].left, 0}; |
| 59 } | 107 } |
| 60 | 108 |
| 61 // WM_GETTITLEBARINFOEX returns rects in screen coordinates in pixels. | 109 // WM_GETTITLEBARINFOEX returns rects in screen coordinates in pixels. |
| 62 // DWMNA_CAPTION_BUTTON_BOUNDS is in window (not client) coordinates, | 110 // DWMNA_CAPTION_BUTTON_BOUNDS is in window (not client) coordinates, |
| 63 // but it has been converted to screen coordinates above. We need to | 111 // but it has been converted to screen coordinates above. We need to |
| 64 // convert the minimize button corner offset to DIP before returning it. | 112 // convert the minimize button corner offset to DIP before returning it. |
| 65 MapWindowPoints(HWND_DESKTOP, hwnd, &minimize_button_corner, 1); | 113 MapWindowPoints(HWND_DESKTOP, hwnd, &minimize_button_corner, 1); |
| 66 gfx::Point pixel_point = {minimize_button_corner.x, 0}; | 114 gfx::Point pixel_point = {minimize_button_corner.x, 0}; |
| 67 gfx::Point dip_point = ScreenWin::ClientToDIPPoint(hwnd, pixel_point); | 115 gfx::Point dip_point = ScreenWin::ClientToDIPPoint(hwnd, pixel_point); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 87 hwnd_ = hwnd; | 135 hwnd_ = hwnd; |
| 88 } | 136 } |
| 89 | 137 |
| 90 void MinimizeButtonMetrics::OnHWNDActivated() { | 138 void MinimizeButtonMetrics::OnHWNDActivated() { |
| 91 was_activated_ = true; | 139 was_activated_ = true; |
| 92 // NOTE: we don't cache here as it seems only after the activate is the | 140 // NOTE: we don't cache here as it seems only after the activate is the |
| 93 // value correct. | 141 // value correct. |
| 94 } | 142 } |
| 95 | 143 |
| 96 int MinimizeButtonMetrics::GetMinimizeButtonOffsetX() const { | 144 int MinimizeButtonMetrics::GetMinimizeButtonOffsetX() const { |
| 97 if (!ui::win::IsAeroGlassEnabled() || cached_minimize_button_x_delta_ == 0) { | 145 if (was_activated_ || !ui::win::IsAeroGlassEnabled() || |
|
kylix_rd
2016/05/09 18:24:52
This was the cause of the regression. The code was
| |
| 146 cached_minimize_button_x_delta_ == 0) { | |
| 98 const int minimize_button_offset = GetAndCacheMinimizeButtonOffsetX(); | 147 const int minimize_button_offset = GetAndCacheMinimizeButtonOffsetX(); |
| 99 if (minimize_button_offset > 0) | 148 if (minimize_button_offset > 0) |
| 100 return minimize_button_offset; | 149 return minimize_button_offset; |
| 101 } | 150 } |
| 102 | 151 |
| 103 // If we fail to get the minimize button offset via the WM_GETTITLEBARINFOEX | 152 // If we fail to get the minimize button offset via the WM_GETTITLEBARINFOEX |
| 104 // message or DwmGetWindowAttribute then calculate and return this via the | 153 // message or DwmGetWindowAttribute then calculate and return this via the |
| 105 // cached_minimize_button_x_delta_ member value. Please see | 154 // cached_minimize_button_x_delta_ member value. Please see |
| 106 // CacheMinimizeButtonDelta() for more details. | 155 // CacheMinimizeButtonDelta() for more details. |
| 107 DCHECK(cached_minimize_button_x_delta_); | 156 DCHECK(cached_minimize_button_x_delta_); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 124 cached_minimize_button_x_delta_ = minimize_button_offset; | 173 cached_minimize_button_x_delta_ = minimize_button_offset; |
| 125 } else { | 174 } else { |
| 126 RECT client_rect = {0}; | 175 RECT client_rect = {0}; |
| 127 GetClientRect(hwnd_, &client_rect); | 176 GetClientRect(hwnd_, &client_rect); |
| 128 cached_minimize_button_x_delta_ = | 177 cached_minimize_button_x_delta_ = |
| 129 client_rect.right - minimize_button_offset; | 178 client_rect.right - minimize_button_offset; |
| 130 } | 179 } |
| 131 last_cached_minimize_button_x_delta_ = cached_minimize_button_x_delta_; | 180 last_cached_minimize_button_x_delta_ = cached_minimize_button_x_delta_; |
| 132 return minimize_button_offset; | 181 return minimize_button_offset; |
| 133 } | 182 } |
| OLD | NEW |