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 | |
304 // static HWNDMessageHandler member initialization. | |
305 HWNDMessageHandler::FullscreenWindowMonitorMap* | |
sky
2016/05/13 23:32:36
Use LazyInstance, it's less error prone than what
ananta
2016/05/16 19:56:43
Done.
| |
306 HWNDMessageHandler::fullscreen_monitor_map_ = nullptr; | |
307 int32_t HWNDMessageHandler::instance_count_ = 0; | |
308 | |
303 //////////////////////////////////////////////////////////////////////////////// | 309 //////////////////////////////////////////////////////////////////////////////// |
304 // HWNDMessageHandler, public: | 310 // HWNDMessageHandler, public: |
305 | 311 |
306 long HWNDMessageHandler::last_touch_message_time_ = 0; | 312 long HWNDMessageHandler::last_touch_message_time_ = 0; |
307 | 313 |
308 HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) | 314 HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) |
309 : msg_handled_(FALSE), | 315 : msg_handled_(FALSE), |
310 delegate_(delegate), | 316 delegate_(delegate), |
311 fullscreen_handler_(new FullscreenHandler), | 317 fullscreen_handler_(new FullscreenHandler), |
312 waiting_for_close_now_(false), | 318 waiting_for_close_now_(false), |
(...skipping 18 matching lines...) Expand all Loading... | |
331 left_button_down_on_caption_(false), | 337 left_button_down_on_caption_(false), |
332 background_fullscreen_hack_(false), | 338 background_fullscreen_hack_(false), |
333 autohide_factory_(this), | 339 autohide_factory_(this), |
334 weak_factory_(this) {} | 340 weak_factory_(this) {} |
335 | 341 |
336 HWNDMessageHandler::~HWNDMessageHandler() { | 342 HWNDMessageHandler::~HWNDMessageHandler() { |
337 delegate_ = NULL; | 343 delegate_ = NULL; |
338 // Prevent calls back into this class via WNDPROC now that we've been | 344 // Prevent calls back into this class via WNDPROC now that we've been |
339 // destroyed. | 345 // destroyed. |
340 ClearUserData(); | 346 ClearUserData(); |
347 instance_count_--; | |
348 if (!instance_count_) { | |
349 delete fullscreen_monitor_map_; | |
350 } | |
341 } | 351 } |
342 | 352 |
343 void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) { | 353 void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) { |
344 TRACE_EVENT0("views", "HWNDMessageHandler::Init"); | 354 TRACE_EVENT0("views", "HWNDMessageHandler::Init"); |
345 GetMonitorAndRects(bounds.ToRECT(), &last_monitor_, &last_monitor_rect_, | 355 GetMonitorAndRects(bounds.ToRECT(), &last_monitor_, &last_monitor_rect_, |
346 &last_work_area_); | 356 &last_work_area_); |
347 | 357 |
348 // Create the window. | 358 // Create the window. |
349 WindowImpl::Init(parent, bounds); | 359 WindowImpl::Init(parent, bounds); |
350 // TODO(ananta) | 360 // TODO(ananta) |
(...skipping 25 matching lines...) Expand all Loading... | |
376 | 386 |
377 // Direct Manipulation is enabled on Windows 10+. The CreateInstance function | 387 // Direct Manipulation is enabled on Windows 10+. The CreateInstance function |
378 // returns NULL if Direct Manipulation is not available. | 388 // returns NULL if Direct Manipulation is not available. |
379 direct_manipulation_helper_ = | 389 direct_manipulation_helper_ = |
380 gfx::win::DirectManipulationHelper::CreateInstance(); | 390 gfx::win::DirectManipulationHelper::CreateInstance(); |
381 if (direct_manipulation_helper_) | 391 if (direct_manipulation_helper_) |
382 direct_manipulation_helper_->Initialize(hwnd()); | 392 direct_manipulation_helper_->Initialize(hwnd()); |
383 | 393 |
384 // Disable pen flicks (http://crbug.com/506977) | 394 // Disable pen flicks (http://crbug.com/506977) |
385 base::win::DisableFlicks(hwnd()); | 395 base::win::DisableFlicks(hwnd()); |
396 | |
397 instance_count_++; | |
398 if (!fullscreen_monitor_map_) | |
399 fullscreen_monitor_map_ = new FullscreenWindowMonitorMap; | |
386 } | 400 } |
387 | 401 |
388 void HWNDMessageHandler::InitModalType(ui::ModalType modal_type) { | 402 void HWNDMessageHandler::InitModalType(ui::ModalType modal_type) { |
389 if (modal_type == ui::MODAL_TYPE_NONE) | 403 if (modal_type == ui::MODAL_TYPE_NONE) |
390 return; | 404 return; |
391 // We implement modality by crawling up the hierarchy of windows starting | 405 // We implement modality by crawling up the hierarchy of windows starting |
392 // at the owner, disabling all of them so that they don't receive input | 406 // at the owner, disabling all of them so that they don't receive input |
393 // messages. | 407 // messages. |
394 HWND start = ::GetWindow(hwnd(), GW_OWNER); | 408 HWND start = ::GetWindow(hwnd(), GW_OWNER); |
395 while (start) { | 409 while (start) { |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
806 } | 820 } |
807 } | 821 } |
808 | 822 |
809 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { | 823 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { |
810 background_fullscreen_hack_ = false; | 824 background_fullscreen_hack_ = false; |
811 fullscreen_handler()->SetFullscreen(fullscreen); | 825 fullscreen_handler()->SetFullscreen(fullscreen); |
812 // If we are out of fullscreen and there was a pending DWM transition for the | 826 // If we are out of fullscreen and there was a pending DWM transition for the |
813 // window, then go ahead and do it now. | 827 // window, then go ahead and do it now. |
814 if (!fullscreen && dwm_transition_desired_) | 828 if (!fullscreen && dwm_transition_desired_) |
815 PerformDwmTransition(); | 829 PerformDwmTransition(); |
830 | |
831 // Add the fullscreen window to the fullscreen window map which is used to | |
832 // handle window activations. | |
833 HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY); | |
834 DCHECK(fullscreen_monitor_map_); | |
835 if (fullscreen) { | |
836 (*fullscreen_monitor_map_)[monitor] = hwnd(); | |
837 } else { | |
838 fullscreen_monitor_map_->erase(fullscreen_monitor_map_->find(monitor)); | |
839 } | |
816 } | 840 } |
817 | 841 |
818 void HWNDMessageHandler::SizeConstraintsChanged() { | 842 void HWNDMessageHandler::SizeConstraintsChanged() { |
819 LONG style = GetWindowLong(hwnd(), GWL_STYLE); | 843 LONG style = GetWindowLong(hwnd(), GWL_STYLE); |
820 // Ignore if this is not a standard window. | 844 // Ignore if this is not a standard window. |
821 if (style & (WS_POPUP | WS_CHILD)) | 845 if (style & (WS_POPUP | WS_CHILD)) |
822 return; | 846 return; |
823 | 847 |
824 LONG exstyle = GetWindowLong(hwnd(), GWL_EXSTYLE); | 848 LONG exstyle = GetWindowLong(hwnd(), GWL_EXSTYLE); |
825 // Windows cannot have WS_THICKFRAME set if WS_EX_COMPOSITED is set. | 849 // 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 | 1038 // 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 | 1039 // 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 | 1040 // 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 | 1041 // 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 | 1042 // 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 | 1043 // affects the way these windows interact with the taskbar, they obscure it |
1020 // when maximized, autohide does not work correctly, etc. | 1044 // when maximized, autohide does not work correctly, etc. |
1021 // By reducing the size of the fullscreen window by 1px, we ensure that the | 1045 // 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 | 1046 // 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 | 1047 // thread. This in turn ensures that maximized windows on the same thread |
1024 /// don't obscure the taskbar, etc. | 1048 // don't obscure the taskbar, etc. |
1049 // Please note that this taskbar behavior only occurs if the window becoming | |
1050 // active is on the same monitor as the fullscreen window. | |
1025 if (!active) { | 1051 if (!active) { |
1026 if (IsFullscreen() && ::IsWindow(window_gaining_or_losing_activation)) { | 1052 if (IsFullscreen() && ::IsWindow(window_gaining_or_losing_activation)) { |
1027 // Reduce the bounds of the window by 1px to ensure that Windows does | 1053 HMONITOR active_window_monitor = MonitorFromWindow( |
1028 // not treat this like a fullscreen window. | 1054 window_gaining_or_losing_activation, MONITOR_DEFAULTTOPRIMARY); |
1029 MONITORINFO monitor_info = {sizeof(monitor_info)}; | 1055 HMONITOR fullscreen_window_monitor = MonitorFromWindow( |
1030 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | 1056 hwnd(), MONITOR_DEFAULTTOPRIMARY); |
1031 &monitor_info); | 1057 |
1032 gfx::Rect shrunk_rect(monitor_info.rcMonitor); | 1058 if (active_window_monitor == fullscreen_window_monitor) |
1033 shrunk_rect.set_height(shrunk_rect.height() - 1); | 1059 OnBackgroundFullscreen(0, 0, 0); |
1034 background_fullscreen_hack_ = true; | |
1035 SetBoundsInternal(shrunk_rect, false); | |
1036 } | 1060 } |
1037 } else if (background_fullscreen_hack_) { | 1061 } else if (background_fullscreen_hack_) { |
1038 // Restore the bounds of the window to fullscreen. | 1062 // Restore the bounds of the window to fullscreen. |
1039 DCHECK(IsFullscreen()); | 1063 DCHECK(IsFullscreen()); |
1040 MONITORINFO monitor_info = {sizeof(monitor_info)}; | 1064 MONITORINFO monitor_info = {sizeof(monitor_info)}; |
1041 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | 1065 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), |
1042 &monitor_info); | 1066 &monitor_info); |
1043 SetBoundsInternal(gfx::Rect(monitor_info.rcMonitor), false); | 1067 SetBoundsInternal(gfx::Rect(monitor_info.rcMonitor), false); |
1044 background_fullscreen_hack_ = false; | 1068 background_fullscreen_hack_ = false; |
1069 } else { | |
1070 // If the window becoming active has a fullscreen window on the same | |
1071 // monitor then we need to reduce the size of the fullscreen window by | |
1072 // 1 px. Please refer to the comments above for the reasoning behind | |
1073 // this. | |
1074 CheckAndHandleBackgroundFullscreenOnMonitor( | |
1075 window_gaining_or_losing_activation); | |
1045 } | 1076 } |
1046 } | 1077 } |
1047 | 1078 |
1048 void HWNDMessageHandler::RestoreEnabledIfNecessary() { | 1079 void HWNDMessageHandler::RestoreEnabledIfNecessary() { |
1049 if (delegate_->IsModal() && !restored_enabled_) { | 1080 if (delegate_->IsModal() && !restored_enabled_) { |
1050 restored_enabled_ = true; | 1081 restored_enabled_ = true; |
1051 // If we were run modally, we need to undo the disabled-ness we inflicted on | 1082 // If we were run modally, we need to undo the disabled-ness we inflicted on |
1052 // the owner's parent hierarchy. | 1083 // the owner's parent hierarchy. |
1053 HWND start = ::GetWindow(hwnd(), GW_OWNER); | 1084 HWND start = ::GetWindow(hwnd(), GW_OWNER); |
1054 while (start) { | 1085 while (start) { |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1330 base::Bind(&HWNDMessageHandler::OnSessionChange, | 1361 base::Bind(&HWNDMessageHandler::OnSessionChange, |
1331 base::Unretained(this)))); | 1362 base::Unretained(this)))); |
1332 | 1363 |
1333 // TODO(beng): move more of NWW::OnCreate here. | 1364 // TODO(beng): move more of NWW::OnCreate here. |
1334 return 0; | 1365 return 0; |
1335 } | 1366 } |
1336 | 1367 |
1337 void HWNDMessageHandler::OnDestroy() { | 1368 void HWNDMessageHandler::OnDestroy() { |
1338 windows_session_change_observer_.reset(nullptr); | 1369 windows_session_change_observer_.reset(nullptr); |
1339 delegate_->HandleDestroying(); | 1370 delegate_->HandleDestroying(); |
1371 // If the window going away is a fullscreen window then remove its references | |
1372 // from the full screen window map. | |
1373 FullscreenWindowMonitorMap::iterator index; | |
1374 DCHECK(fullscreen_monitor_map_); | |
1375 for (index = fullscreen_monitor_map_->begin(); | |
1376 index != fullscreen_monitor_map_->end(); | |
1377 index++) { | |
1378 if (index->second == hwnd()) { | |
1379 fullscreen_monitor_map_->erase(index); | |
1380 break; | |
1381 } | |
1382 } | |
1340 } | 1383 } |
1341 | 1384 |
1342 void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel, | 1385 void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel, |
1343 const gfx::Size& screen_size) { | 1386 const gfx::Size& screen_size) { |
1344 delegate_->HandleDisplayChange(); | 1387 delegate_->HandleDisplayChange(); |
1345 // Force a WM_NCCALCSIZE to occur to ensure that we handle auto hide | 1388 // Force a WM_NCCALCSIZE to occur to ensure that we handle auto hide |
1346 // taskbars correctly. | 1389 // taskbars correctly. |
1347 SendFrameChanged(); | 1390 SendFrameChanged(); |
1348 } | 1391 } |
1349 | 1392 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1390 void HWNDMessageHandler::OnExitSizeMove() { | 1433 void HWNDMessageHandler::OnExitSizeMove() { |
1391 delegate_->HandleEndWMSizeMove(); | 1434 delegate_->HandleEndWMSizeMove(); |
1392 SetMsgHandled(FALSE); | 1435 SetMsgHandled(FALSE); |
1393 // Please refer to the notes in the OnSize function for information about | 1436 // Please refer to the notes in the OnSize function for information about |
1394 // the scrolling hack. | 1437 // the scrolling hack. |
1395 // We hide the Windows scrollbar in the OnEnterSizeMove function. We need | 1438 // 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 | 1439 // to add the scroll styles back to ensure that scrolling works in legacy |
1397 // trackpoint drivers. | 1440 // trackpoint drivers. |
1398 if (in_size_loop_ && needs_scroll_styles_) | 1441 if (in_size_loop_ && needs_scroll_styles_) |
1399 AddScrollStylesToWindow(hwnd()); | 1442 AddScrollStylesToWindow(hwnd()); |
1443 // If the window was moved to a monitor which has a fullscreen window active, | |
1444 // we need to reduce the size of the fullscreen window by 1px. | |
1445 CheckAndHandleBackgroundFullscreenOnMonitor(hwnd()); | |
1400 } | 1446 } |
1401 | 1447 |
1402 void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { | 1448 void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { |
1403 gfx::Size min_window_size; | 1449 gfx::Size min_window_size; |
1404 gfx::Size max_window_size; | 1450 gfx::Size max_window_size; |
1405 delegate_->GetMinMaxSize(&min_window_size, &max_window_size); | 1451 delegate_->GetMinMaxSize(&min_window_size, &max_window_size); |
1406 min_window_size = delegate_->DIPToScreenSize(min_window_size); | 1452 min_window_size = delegate_->DIPToScreenSize(min_window_size); |
1407 max_window_size = delegate_->DIPToScreenSize(max_window_size); | 1453 max_window_size = delegate_->DIPToScreenSize(max_window_size); |
1408 | 1454 |
1409 | 1455 |
(...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2337 if (direct_manipulation_helper_) | 2383 if (direct_manipulation_helper_) |
2338 direct_manipulation_helper_->Deactivate(hwnd()); | 2384 direct_manipulation_helper_->Deactivate(hwnd()); |
2339 } | 2385 } |
2340 if (sent_window_size_changing_) { | 2386 if (sent_window_size_changing_) { |
2341 sent_window_size_changing_ = false; | 2387 sent_window_size_changing_ = false; |
2342 delegate_->HandleWindowSizeChanged(); | 2388 delegate_->HandleWindowSizeChanged(); |
2343 } | 2389 } |
2344 SetMsgHandled(FALSE); | 2390 SetMsgHandled(FALSE); |
2345 } | 2391 } |
2346 | 2392 |
2393 LRESULT HWNDMessageHandler::OnBackgroundFullscreen(UINT message, | |
2394 WPARAM w_param, | |
2395 LPARAM l_param) { | |
2396 // Reduce the bounds of the window by 1px to ensure that Windows does | |
2397 // not treat this like a fullscreen window. | |
2398 MONITORINFO monitor_info = { sizeof(monitor_info) }; | |
2399 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | |
2400 &monitor_info); | |
2401 gfx::Rect shrunk_rect(monitor_info.rcMonitor); | |
2402 shrunk_rect.set_height(shrunk_rect.height() - 1); | |
2403 background_fullscreen_hack_ = true; | |
2404 SetBoundsInternal(shrunk_rect, false); | |
2405 return 0; | |
2406 } | |
2407 | |
2347 void HWNDMessageHandler::OnSessionChange(WPARAM status_code) { | 2408 void HWNDMessageHandler::OnSessionChange(WPARAM status_code) { |
2348 // Direct3D presents are ignored while the screen is locked, so force the | 2409 // Direct3D presents are ignored while the screen is locked, so force the |
2349 // window to be redrawn on unlock. | 2410 // window to be redrawn on unlock. |
2350 if (status_code == WTS_SESSION_UNLOCK) | 2411 if (status_code == WTS_SESSION_UNLOCK) |
2351 ForceRedrawWindow(10); | 2412 ForceRedrawWindow(10); |
2352 } | 2413 } |
2353 | 2414 |
2354 void HWNDMessageHandler::HandleTouchEvents(const TouchEvents& touch_events) { | 2415 void HWNDMessageHandler::HandleTouchEvents(const TouchEvents& touch_events) { |
2355 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); | 2416 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); |
2356 for (size_t i = 0; i < touch_events.size() && ref; ++i) | 2417 for (size_t i = 0; i < touch_events.size() && ref; ++i) |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2676 if (old_size == bounds_in_pixels.size() && force_size_changed && | 2737 if (old_size == bounds_in_pixels.size() && force_size_changed && |
2677 !background_fullscreen_hack_) { | 2738 !background_fullscreen_hack_) { |
2678 delegate_->HandleClientSizeChanged(GetClientAreaBounds().size()); | 2739 delegate_->HandleClientSizeChanged(GetClientAreaBounds().size()); |
2679 ResetWindowRegion(false, true); | 2740 ResetWindowRegion(false, true); |
2680 } | 2741 } |
2681 | 2742 |
2682 if (direct_manipulation_helper_) | 2743 if (direct_manipulation_helper_) |
2683 direct_manipulation_helper_->SetBounds(bounds_in_pixels); | 2744 direct_manipulation_helper_->SetBounds(bounds_in_pixels); |
2684 } | 2745 } |
2685 | 2746 |
2747 void HWNDMessageHandler::CheckAndHandleBackgroundFullscreenOnMonitor( | |
2748 HWND window) { | |
2749 HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY); | |
2750 | |
2751 DCHECK(fullscreen_monitor_map_); | |
2752 FullscreenWindowMonitorMap::iterator index = fullscreen_monitor_map_->find( | |
2753 monitor); | |
2754 if (index != fullscreen_monitor_map_->end() && window != index->second) { | |
2755 PostMessage(index->second, | |
sky
2016/05/13 23:32:36
Why bother with the PostMessage? Why not call the
ananta
2016/05/16 19:56:43
The fullscreen window could be a different instanc
ananta
2016/05/16 21:35:42
yeah. done.
| |
2756 WM_CUSTOM_MESSAGE_HANDLE_BACKGROUND_FULLSCREEN, | |
2757 0, | |
2758 0); | |
2759 } | |
2760 } | |
2686 | 2761 |
2687 } // namespace views | 2762 } // namespace views |
OLD | NEW |