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 |