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

Side by Side Diff: chrome/browser/ui/views/chrome_views_delegate.cc

Issue 2542533002: Don't check autohide taskbar for WS_EX_TOPMOST when we are querying the autohide state. (Closed)
Patch Set: Revert changes to hwnd_message_handler.cc and add comments Created 4 years 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 unified diff | Download patch
« no previous file with comments | « no previous file | ui/views/win/hwnd_message_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/chrome_views_delegate.h" 5 #include "chrome/browser/ui/views/chrome_views_delegate.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 PrefService* GetPrefsForWindow(const views::Widget* window) { 92 PrefService* GetPrefsForWindow(const views::Widget* window) {
93 Profile* profile = GetProfileForWindow(window); 93 Profile* profile = GetProfileForWindow(window);
94 if (!profile) { 94 if (!profile) {
95 // Use local state for windows that have no explicit profile. 95 // Use local state for windows that have no explicit profile.
96 return g_browser_process->local_state(); 96 return g_browser_process->local_state();
97 } 97 }
98 return profile->GetPrefs(); 98 return profile->GetPrefs();
99 } 99 }
100 100
101 #if defined(OS_WIN) 101 #if defined(OS_WIN)
102 bool MonitorHasTopmostAutohideTaskbarForEdge(UINT edge, HMONITOR monitor) { 102 bool MonitorHasAutohideTaskbarForEdge(UINT edge, HMONITOR monitor) {
103 APPBARDATA taskbar_data = { sizeof(APPBARDATA), NULL, 0, edge }; 103 APPBARDATA taskbar_data = { sizeof(APPBARDATA), NULL, 0, edge };
104 taskbar_data.hWnd = ::GetForegroundWindow(); 104 taskbar_data.hWnd = ::GetForegroundWindow();
105 105
106 // TODO(robliao): Remove ScopedTracker below once crbug.com/462368 is fixed. 106 // TODO(robliao): Remove ScopedTracker below once crbug.com/462368 is fixed.
107 tracked_objects::ScopedTracker tracking_profile( 107 tracked_objects::ScopedTracker tracking_profile(
108 FROM_HERE_WITH_EXPLICIT_FUNCTION( 108 FROM_HERE_WITH_EXPLICIT_FUNCTION(
109 "462368 MonitorHasTopmostAutohideTaskbarForEdge")); 109 "462368 MonitorHasAutohideTaskbarForEdge"));
110 110
111 // MSDN documents an ABM_GETAUTOHIDEBAREX, which supposedly takes a monitor 111 // MSDN documents an ABM_GETAUTOHIDEBAREX, which supposedly takes a monitor
112 // rect and returns autohide bars on that monitor. This sounds like a good 112 // rect and returns autohide bars on that monitor. This sounds like a good
113 // idea for multi-monitor systems. Unfortunately, it appears to not work at 113 // idea for multi-monitor systems. Unfortunately, it appears to not work at
114 // least some of the time (erroneously returning NULL) and there's almost no 114 // least some of the time (erroneously returning NULL) and there's almost no
115 // online documentation or other sample code using it that suggests ways to 115 // online documentation or other sample code using it that suggests ways to
116 // address this problem. We do the following:- 116 // address this problem. We do the following:-
117 // 1. Use the ABM_GETAUTOHIDEBAR message. If it works, i.e. returns a valid 117 // 1. Use the ABM_GETAUTOHIDEBAR message. If it works, i.e. returns a valid
118 // window we are done. 118 // window we are done.
119 // 2. If the ABM_GETAUTOHIDEBAR message does not work we query the auto hide 119 // 2. If the ABM_GETAUTOHIDEBAR message does not work we query the auto hide
(...skipping 12 matching lines...) Expand all
132 132
133 taskbar_data.hWnd = ::FindWindow(L"Shell_TrayWnd", NULL); 133 taskbar_data.hWnd = ::FindWindow(L"Shell_TrayWnd", NULL);
134 if (!::IsWindow(taskbar_data.hWnd)) 134 if (!::IsWindow(taskbar_data.hWnd))
135 return false; 135 return false;
136 136
137 SHAppBarMessage(ABM_GETTASKBARPOS, &taskbar_data); 137 SHAppBarMessage(ABM_GETTASKBARPOS, &taskbar_data);
138 if (taskbar_data.uEdge == edge) 138 if (taskbar_data.uEdge == edge)
139 taskbar = taskbar_data.hWnd; 139 taskbar = taskbar_data.hWnd;
140 } 140 }
141 141
142 if (::IsWindow(taskbar) && 142 // We retrieve the autohide information in a worker thread to avoid
143 (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST)) { 143 // reentrancy issues introduced by the SHAppBarMessage API. This introduces
144 // subtle timing bugs like the one below:
Peter Kasting 2016/12/02 21:11:30 Nit: Since this partly duplicates your later comme
ananta 2016/12/03 00:07:25 Done.
145 // 1. A maximized chrome window is fullscreened.
146 // 2. It is switched back to maximized.
147 // 3. In the process the window gets a WM_NCCACLSIZE message which calls us to
148 // get the autohide state.
149 // 4. The worker thread is invoked and the main thread is suspended. The
150 // worker
Peter Kasting 2016/12/02 21:11:30 Nit: Rewrap I might remove "and the main thread i
ananta 2016/12/03 00:07:25 Done.
151 // thread calls the API to get the autohide state. On Windows versions
152 // earlier than Windows 7 taskbars could easily be always on top or not.
153 // This meant that we only want to look for taskbars which have the topmost
154 // bit set. However this causes problems in cases where the window on the
155 // main thread is still in the process of switching away from fullscreen.
156 // In this case the taskbar would not have the topmost bit set.
Peter Kasting 2016/12/02 21:11:30 Nit: Maybe "would not" -> "might not yet"?
ananta 2016/12/03 00:07:25 Done.
157 // 5. The main thread resumes and does not leave space for the taskbar and
158 // hence it does not popup up when hovered on.
Peter Kasting 2016/12/02 21:11:30 Nit: popup -> pop; remove "on"?
ananta 2016/12/03 00:07:25 Done.
159 //
160 // To address point 4 above, it is best to not check for the WS_EX_TOPMOST
161 // window style on the taskbar, as starting from Windows 7, the topmost
162 // style is always set. We don't support XP and Vista anymore.
163 if (::IsWindow(taskbar)) {
144 if (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONEAREST) == monitor) 164 if (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONEAREST) == monitor)
145 return true; 165 return true;
146 // In some cases like when the autohide taskbar is on the left of the 166 // In some cases like when the autohide taskbar is on the left of the
147 // secondary monitor, the MonitorFromWindow call above fails to return the 167 // secondary monitor, the MonitorFromWindow call above fails to return the
148 // correct monitor the taskbar is on. We fallback to MonitorFromPoint for 168 // correct monitor the taskbar is on. We fallback to MonitorFromPoint for
149 // the cursor position in that case, which seems to work well. 169 // the cursor position in that case, which seems to work well.
150 POINT cursor_pos = {0}; 170 POINT cursor_pos = {0};
151 GetCursorPos(&cursor_pos); 171 GetCursorPos(&cursor_pos);
152 if (MonitorFromPoint(cursor_pos, MONITOR_DEFAULTTONEAREST) == monitor) 172 if (MonitorFromPoint(cursor_pos, MONITOR_DEFAULTTONEAREST) == monitor)
153 return true; 173 return true;
154 } 174 }
155 return false; 175 return false;
156 } 176 }
157 177
158 int GetAppbarAutohideEdgesOnWorkerThread(HMONITOR monitor) { 178 int GetAppbarAutohideEdgesOnWorkerThread(HMONITOR monitor) {
159 DCHECK(monitor); 179 DCHECK(monitor);
160 180
161 int edges = 0; 181 int edges = 0;
162 if (MonitorHasTopmostAutohideTaskbarForEdge(ABE_LEFT, monitor)) 182 if (MonitorHasAutohideTaskbarForEdge(ABE_LEFT, monitor))
163 edges |= views::ViewsDelegate::EDGE_LEFT; 183 edges |= views::ViewsDelegate::EDGE_LEFT;
164 if (MonitorHasTopmostAutohideTaskbarForEdge(ABE_TOP, monitor)) 184 if (MonitorHasAutohideTaskbarForEdge(ABE_TOP, monitor))
165 edges |= views::ViewsDelegate::EDGE_TOP; 185 edges |= views::ViewsDelegate::EDGE_TOP;
166 if (MonitorHasTopmostAutohideTaskbarForEdge(ABE_RIGHT, monitor)) 186 if (MonitorHasAutohideTaskbarForEdge(ABE_RIGHT, monitor))
167 edges |= views::ViewsDelegate::EDGE_RIGHT; 187 edges |= views::ViewsDelegate::EDGE_RIGHT;
168 if (MonitorHasTopmostAutohideTaskbarForEdge(ABE_BOTTOM, monitor)) 188 if (MonitorHasAutohideTaskbarForEdge(ABE_BOTTOM, monitor))
169 edges |= views::ViewsDelegate::EDGE_BOTTOM; 189 edges |= views::ViewsDelegate::EDGE_BOTTOM;
170 return edges; 190 return edges;
171 } 191 }
172 #endif 192 #endif
173 193
174 #if defined(USE_ASH) 194 #if defined(USE_ASH)
175 void ProcessAcceleratorNow(const ui::Accelerator& accelerator) { 195 void ProcessAcceleratorNow(const ui::Accelerator& accelerator) {
176 // TODO(afakhry): See if we need here to send the accelerator to the 196 // TODO(afakhry): See if we need here to send the accelerator to the
177 // FocusManager of the active window in a follow-up CL. 197 // FocusManager of the active window in a follow-up CL.
178 ash::WmShell::Get()->accelerator_controller()->Process(accelerator); 198 ash::WmShell::Get()->accelerator_controller()->Process(accelerator);
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 return content::GetContextFactory(); 482 return content::GetContextFactory();
463 } 483 }
464 484
465 std::string ChromeViewsDelegate::GetApplicationName() { 485 std::string ChromeViewsDelegate::GetApplicationName() {
466 return version_info::GetProductName(); 486 return version_info::GetProductName();
467 } 487 }
468 488
469 #if defined(OS_WIN) 489 #if defined(OS_WIN)
470 int ChromeViewsDelegate::GetAppbarAutohideEdges(HMONITOR monitor, 490 int ChromeViewsDelegate::GetAppbarAutohideEdges(HMONITOR monitor,
471 const base::Closure& callback) { 491 const base::Closure& callback) {
492 // We use the SHAppBarMessage API to get the taskbar autohide state. This API
Peter Kasting 2016/12/02 21:11:30 Nit: This whole comment probably belongs directly
ananta 2016/12/03 00:07:25 Done.
493 // spins a modal loop which could cause callers to be reentered. This may not
494 // be desirable and to avoid that we retrieve the taskbar state in a worker
Peter Kasting 2016/12/02 21:11:30 Nit: I'd remove "This may not be desirable and", w
ananta 2016/12/03 00:07:25 Done.
495 // thread. This fixes the reentrancy problems but introduces subtle timing
496 // issues like the one described in the
497 // ChromeViewsDelegate::OnGotAppbarAutohideEdges() function.
Peter Kasting 2016/12/02 21:11:30 Nit: I'd omit this last sentence, as that's really
ananta 2016/12/03 00:07:25 Done.
498
472 // Initialize the map with EDGE_BOTTOM. This is important, as if we return an 499 // Initialize the map with EDGE_BOTTOM. This is important, as if we return an
473 // initial value of 0 (no auto-hide edges) then we'll go fullscreen and 500 // initial value of 0 (no auto-hide edges) then we'll go fullscreen and
474 // windows will automatically remove WS_EX_TOPMOST from the appbar resulting 501 // windows will automatically remove WS_EX_TOPMOST from the appbar resulting
475 // in us thinking there is no auto-hide edges. By returning at least one edge 502 // in us thinking there is no auto-hide edges. By returning at least one edge
476 // we don't initially go fullscreen until we figure out the real auto-hide 503 // we don't initially go fullscreen until we figure out the real auto-hide
477 // edges. 504 // edges.
478 if (!appbar_autohide_edge_map_.count(monitor)) 505 if (!appbar_autohide_edge_map_.count(monitor))
479 appbar_autohide_edge_map_[monitor] = EDGE_BOTTOM; 506 appbar_autohide_edge_map_[monitor] = EDGE_BOTTOM;
480 if (monitor && !in_autohide_edges_callback_) { 507 if (monitor && !in_autohide_edges_callback_) {
481 base::PostTaskAndReplyWithResult( 508 base::PostTaskAndReplyWithResult(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 return ViewsDelegate::GetDialogRelatedButtonHorizontalSpacing(); 550 return ViewsDelegate::GetDialogRelatedButtonHorizontalSpacing();
524 } 551 }
525 552
526 #if !defined(USE_ASH) 553 #if !defined(USE_ASH)
527 views::Widget::InitParams::WindowOpacity 554 views::Widget::InitParams::WindowOpacity
528 ChromeViewsDelegate::GetOpacityForInitParams( 555 ChromeViewsDelegate::GetOpacityForInitParams(
529 const views::Widget::InitParams& params) { 556 const views::Widget::InitParams& params) {
530 return views::Widget::InitParams::OPAQUE_WINDOW; 557 return views::Widget::InitParams::OPAQUE_WINDOW;
531 } 558 }
532 #endif 559 #endif
OLDNEW
« no previous file with comments | « no previous file | ui/views/win/hwnd_message_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698