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 "ui/views/win/hwnd_message_handler.h" | 5 #include "ui/views/win/hwnd_message_handler.h" |
6 | 6 |
7 #include <dwmapi.h> | 7 #include <dwmapi.h> |
8 #include <oleacc.h> | 8 #include <oleacc.h> |
9 #include <shellapi.h> | 9 #include <shellapi.h> |
10 #include <tchar.h> | 10 #include <tchar.h> |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 // Records the HWND visibility at the time of creation. | 293 // Records the HWND visibility at the time of creation. |
294 bool was_visible_; | 294 bool was_visible_; |
295 // A flag indicating that the unlock operation was canceled. | 295 // A flag indicating that the unlock operation was canceled. |
296 bool cancel_unlock_; | 296 bool cancel_unlock_; |
297 // If true, perform the redraw lock regardless of Aero state. | 297 // If true, perform the redraw lock regardless of Aero state. |
298 bool force_; | 298 bool force_; |
299 | 299 |
300 DISALLOW_COPY_AND_ASSIGN(ScopedRedrawLock); | 300 DISALLOW_COPY_AND_ASSIGN(ScopedRedrawLock); |
301 }; | 301 }; |
302 | 302 |
| 303 // static HWNDMessageHandler member initialization. |
| 304 base::LazyInstance<HWNDMessageHandler::FullscreenWindowMonitorMap> |
| 305 HWNDMessageHandler::fullscreen_monitor_map_ = LAZY_INSTANCE_INITIALIZER; |
| 306 |
303 //////////////////////////////////////////////////////////////////////////////// | 307 //////////////////////////////////////////////////////////////////////////////// |
304 // HWNDMessageHandler, public: | 308 // HWNDMessageHandler, public: |
305 | 309 |
306 long HWNDMessageHandler::last_touch_message_time_ = 0; | 310 long HWNDMessageHandler::last_touch_message_time_ = 0; |
307 | 311 |
308 HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) | 312 HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) |
309 : msg_handled_(FALSE), | 313 : msg_handled_(FALSE), |
310 delegate_(delegate), | 314 delegate_(delegate), |
311 fullscreen_handler_(new FullscreenHandler), | 315 fullscreen_handler_(new FullscreenHandler), |
312 waiting_for_close_now_(false), | 316 waiting_for_close_now_(false), |
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 } | 810 } |
807 } | 811 } |
808 | 812 |
809 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { | 813 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { |
810 background_fullscreen_hack_ = false; | 814 background_fullscreen_hack_ = false; |
811 fullscreen_handler()->SetFullscreen(fullscreen); | 815 fullscreen_handler()->SetFullscreen(fullscreen); |
812 // If we are out of fullscreen and there was a pending DWM transition for the | 816 // If we are out of fullscreen and there was a pending DWM transition for the |
813 // window, then go ahead and do it now. | 817 // window, then go ahead and do it now. |
814 if (!fullscreen && dwm_transition_desired_) | 818 if (!fullscreen && dwm_transition_desired_) |
815 PerformDwmTransition(); | 819 PerformDwmTransition(); |
| 820 |
| 821 // Add the fullscreen window to the fullscreen window map which is used to |
| 822 // handle window activations. |
| 823 HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY); |
| 824 if (fullscreen) { |
| 825 (fullscreen_monitor_map_.Get())[monitor] = this; |
| 826 } else { |
| 827 FullscreenWindowMonitorMap::iterator iter = |
| 828 fullscreen_monitor_map_.Get().find(monitor); |
| 829 if (iter != fullscreen_monitor_map_.Get().end()) |
| 830 fullscreen_monitor_map_.Get().erase(iter); |
| 831 } |
816 } | 832 } |
817 | 833 |
818 void HWNDMessageHandler::SizeConstraintsChanged() { | 834 void HWNDMessageHandler::SizeConstraintsChanged() { |
819 LONG style = GetWindowLong(hwnd(), GWL_STYLE); | 835 LONG style = GetWindowLong(hwnd(), GWL_STYLE); |
820 // Ignore if this is not a standard window. | 836 // Ignore if this is not a standard window. |
821 if (style & (WS_POPUP | WS_CHILD)) | 837 if (style & (WS_POPUP | WS_CHILD)) |
822 return; | 838 return; |
823 | 839 |
824 LONG exstyle = GetWindowLong(hwnd(), GWL_EXSTYLE); | 840 LONG exstyle = GetWindowLong(hwnd(), GWL_EXSTYLE); |
825 // Windows cannot have WS_THICKFRAME set if WS_EX_COMPOSITED is set. | 841 // Windows cannot have WS_THICKFRAME set if WS_EX_COMPOSITED is set. |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 // If the window losing activation is a fullscreen window, we reduce the size | 1030 // If the window losing activation is a fullscreen window, we reduce the size |
1015 // of the window by 1px. i.e. Not fullscreen. This is to work around an | 1031 // of the window by 1px. i.e. Not fullscreen. This is to work around an |
1016 // apparent bug in the Windows taskbar where in it tracks fullscreen state on | 1032 // apparent bug in the Windows taskbar where in it tracks fullscreen state on |
1017 // a per thread basis. This causes it not be a topmost window when any | 1033 // a per thread basis. This causes it not be a topmost window when any |
1018 // maximized window on a thread which has a fullscreen window is active. This | 1034 // maximized window on a thread which has a fullscreen window is active. This |
1019 // affects the way these windows interact with the taskbar, they obscure it | 1035 // affects the way these windows interact with the taskbar, they obscure it |
1020 // when maximized, autohide does not work correctly, etc. | 1036 // when maximized, autohide does not work correctly, etc. |
1021 // By reducing the size of the fullscreen window by 1px, we ensure that the | 1037 // By reducing the size of the fullscreen window by 1px, we ensure that the |
1022 // taskbar no longer treats the window and in turn the thread as a fullscreen | 1038 // taskbar no longer treats the window and in turn the thread as a fullscreen |
1023 // thread. This in turn ensures that maximized windows on the same thread | 1039 // thread. This in turn ensures that maximized windows on the same thread |
1024 /// don't obscure the taskbar, etc. | 1040 // don't obscure the taskbar, etc. |
| 1041 // Please note that this taskbar behavior only occurs if the window becoming |
| 1042 // active is on the same monitor as the fullscreen window. |
1025 if (!active) { | 1043 if (!active) { |
1026 if (IsFullscreen() && ::IsWindow(window_gaining_or_losing_activation)) { | 1044 if (IsFullscreen() && ::IsWindow(window_gaining_or_losing_activation)) { |
1027 // Reduce the bounds of the window by 1px to ensure that Windows does | 1045 HMONITOR active_window_monitor = MonitorFromWindow( |
1028 // not treat this like a fullscreen window. | 1046 window_gaining_or_losing_activation, MONITOR_DEFAULTTOPRIMARY); |
1029 MONITORINFO monitor_info = {sizeof(monitor_info)}; | 1047 HMONITOR fullscreen_window_monitor = |
1030 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | 1048 MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY); |
1031 &monitor_info); | 1049 |
1032 gfx::Rect shrunk_rect(monitor_info.rcMonitor); | 1050 if (active_window_monitor == fullscreen_window_monitor) |
1033 shrunk_rect.set_height(shrunk_rect.height() - 1); | 1051 OnBackgroundFullscreen(); |
1034 background_fullscreen_hack_ = true; | |
1035 SetBoundsInternal(shrunk_rect, false); | |
1036 } | 1052 } |
1037 } else if (background_fullscreen_hack_) { | 1053 } else if (background_fullscreen_hack_) { |
1038 // Restore the bounds of the window to fullscreen. | 1054 // Restore the bounds of the window to fullscreen. |
1039 DCHECK(IsFullscreen()); | 1055 DCHECK(IsFullscreen()); |
1040 MONITORINFO monitor_info = {sizeof(monitor_info)}; | 1056 MONITORINFO monitor_info = {sizeof(monitor_info)}; |
1041 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | 1057 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), |
1042 &monitor_info); | 1058 &monitor_info); |
1043 SetBoundsInternal(gfx::Rect(monitor_info.rcMonitor), false); | 1059 SetBoundsInternal(gfx::Rect(monitor_info.rcMonitor), false); |
1044 background_fullscreen_hack_ = false; | 1060 background_fullscreen_hack_ = false; |
| 1061 } else { |
| 1062 // If the window becoming active has a fullscreen window on the same |
| 1063 // monitor then we need to reduce the size of the fullscreen window by |
| 1064 // 1 px. Please refer to the comments above for the reasoning behind |
| 1065 // this. |
| 1066 CheckAndHandleBackgroundFullscreenOnMonitor( |
| 1067 window_gaining_or_losing_activation); |
1045 } | 1068 } |
1046 } | 1069 } |
1047 | 1070 |
1048 void HWNDMessageHandler::RestoreEnabledIfNecessary() { | 1071 void HWNDMessageHandler::RestoreEnabledIfNecessary() { |
1049 if (delegate_->IsModal() && !restored_enabled_) { | 1072 if (delegate_->IsModal() && !restored_enabled_) { |
1050 restored_enabled_ = true; | 1073 restored_enabled_ = true; |
1051 // If we were run modally, we need to undo the disabled-ness we inflicted on | 1074 // If we were run modally, we need to undo the disabled-ness we inflicted on |
1052 // the owner's parent hierarchy. | 1075 // the owner's parent hierarchy. |
1053 HWND start = ::GetWindow(hwnd(), GW_OWNER); | 1076 HWND start = ::GetWindow(hwnd(), GW_OWNER); |
1054 while (start) { | 1077 while (start) { |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 base::Bind(&HWNDMessageHandler::OnSessionChange, | 1353 base::Bind(&HWNDMessageHandler::OnSessionChange, |
1331 base::Unretained(this)))); | 1354 base::Unretained(this)))); |
1332 | 1355 |
1333 // TODO(beng): move more of NWW::OnCreate here. | 1356 // TODO(beng): move more of NWW::OnCreate here. |
1334 return 0; | 1357 return 0; |
1335 } | 1358 } |
1336 | 1359 |
1337 void HWNDMessageHandler::OnDestroy() { | 1360 void HWNDMessageHandler::OnDestroy() { |
1338 windows_session_change_observer_.reset(nullptr); | 1361 windows_session_change_observer_.reset(nullptr); |
1339 delegate_->HandleDestroying(); | 1362 delegate_->HandleDestroying(); |
| 1363 // If the window going away is a fullscreen window then remove its references |
| 1364 // from the full screen window map. |
| 1365 for (auto iter = fullscreen_monitor_map_.Get().begin(); |
| 1366 iter != fullscreen_monitor_map_.Get().end(); |
| 1367 iter++) { |
| 1368 if (iter->second == this) { |
| 1369 fullscreen_monitor_map_.Get().erase(iter); |
| 1370 break; |
| 1371 } |
| 1372 } |
1340 } | 1373 } |
1341 | 1374 |
1342 void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel, | 1375 void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel, |
1343 const gfx::Size& screen_size) { | 1376 const gfx::Size& screen_size) { |
1344 delegate_->HandleDisplayChange(); | 1377 delegate_->HandleDisplayChange(); |
1345 // Force a WM_NCCALCSIZE to occur to ensure that we handle auto hide | 1378 // Force a WM_NCCALCSIZE to occur to ensure that we handle auto hide |
1346 // taskbars correctly. | 1379 // taskbars correctly. |
1347 SendFrameChanged(); | 1380 SendFrameChanged(); |
1348 } | 1381 } |
1349 | 1382 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1390 void HWNDMessageHandler::OnExitSizeMove() { | 1423 void HWNDMessageHandler::OnExitSizeMove() { |
1391 delegate_->HandleEndWMSizeMove(); | 1424 delegate_->HandleEndWMSizeMove(); |
1392 SetMsgHandled(FALSE); | 1425 SetMsgHandled(FALSE); |
1393 // Please refer to the notes in the OnSize function for information about | 1426 // Please refer to the notes in the OnSize function for information about |
1394 // the scrolling hack. | 1427 // the scrolling hack. |
1395 // We hide the Windows scrollbar in the OnEnterSizeMove function. We need | 1428 // We hide the Windows scrollbar in the OnEnterSizeMove function. We need |
1396 // to add the scroll styles back to ensure that scrolling works in legacy | 1429 // to add the scroll styles back to ensure that scrolling works in legacy |
1397 // trackpoint drivers. | 1430 // trackpoint drivers. |
1398 if (in_size_loop_ && needs_scroll_styles_) | 1431 if (in_size_loop_ && needs_scroll_styles_) |
1399 AddScrollStylesToWindow(hwnd()); | 1432 AddScrollStylesToWindow(hwnd()); |
| 1433 // If the window was moved to a monitor which has a fullscreen window active, |
| 1434 // we need to reduce the size of the fullscreen window by 1px. |
| 1435 CheckAndHandleBackgroundFullscreenOnMonitor(hwnd()); |
1400 } | 1436 } |
1401 | 1437 |
1402 void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { | 1438 void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { |
1403 gfx::Size min_window_size; | 1439 gfx::Size min_window_size; |
1404 gfx::Size max_window_size; | 1440 gfx::Size max_window_size; |
1405 delegate_->GetMinMaxSize(&min_window_size, &max_window_size); | 1441 delegate_->GetMinMaxSize(&min_window_size, &max_window_size); |
1406 min_window_size = delegate_->DIPToScreenSize(min_window_size); | 1442 min_window_size = delegate_->DIPToScreenSize(min_window_size); |
1407 max_window_size = delegate_->DIPToScreenSize(max_window_size); | 1443 max_window_size = delegate_->DIPToScreenSize(max_window_size); |
1408 | 1444 |
1409 | 1445 |
(...skipping 1266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2676 if (old_size == bounds_in_pixels.size() && force_size_changed && | 2712 if (old_size == bounds_in_pixels.size() && force_size_changed && |
2677 !background_fullscreen_hack_) { | 2713 !background_fullscreen_hack_) { |
2678 delegate_->HandleClientSizeChanged(GetClientAreaBounds().size()); | 2714 delegate_->HandleClientSizeChanged(GetClientAreaBounds().size()); |
2679 ResetWindowRegion(false, true); | 2715 ResetWindowRegion(false, true); |
2680 } | 2716 } |
2681 | 2717 |
2682 if (direct_manipulation_helper_) | 2718 if (direct_manipulation_helper_) |
2683 direct_manipulation_helper_->SetBounds(bounds_in_pixels); | 2719 direct_manipulation_helper_->SetBounds(bounds_in_pixels); |
2684 } | 2720 } |
2685 | 2721 |
| 2722 void HWNDMessageHandler::CheckAndHandleBackgroundFullscreenOnMonitor( |
| 2723 HWND window) { |
| 2724 HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY); |
| 2725 |
| 2726 FullscreenWindowMonitorMap::iterator iter = |
| 2727 fullscreen_monitor_map_.Get().find(monitor); |
| 2728 if (iter != fullscreen_monitor_map_.Get().end()) { |
| 2729 DCHECK(iter->second); |
| 2730 if (window != iter->second->hwnd()) |
| 2731 iter->second->OnBackgroundFullscreen(); |
| 2732 } |
| 2733 } |
| 2734 |
| 2735 void HWNDMessageHandler::OnBackgroundFullscreen() { |
| 2736 // Reduce the bounds of the window by 1px to ensure that Windows does |
| 2737 // not treat this like a fullscreen window. |
| 2738 MONITORINFO monitor_info = {sizeof(monitor_info)}; |
| 2739 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), |
| 2740 &monitor_info); |
| 2741 gfx::Rect shrunk_rect(monitor_info.rcMonitor); |
| 2742 shrunk_rect.set_height(shrunk_rect.height() - 1); |
| 2743 background_fullscreen_hack_ = true; |
| 2744 SetBoundsInternal(shrunk_rect, false); |
| 2745 } |
2686 | 2746 |
2687 } // namespace views | 2747 } // namespace views |
OLD | NEW |