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/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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |