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 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
326 is_first_nccalc_(true), | 326 is_first_nccalc_(true), |
327 menu_depth_(0), | 327 menu_depth_(0), |
328 id_generator_(0), | 328 id_generator_(0), |
329 needs_scroll_styles_(false), | 329 needs_scroll_styles_(false), |
330 in_size_loop_(false), | 330 in_size_loop_(false), |
331 touch_down_contexts_(0), | 331 touch_down_contexts_(0), |
332 last_mouse_hwheel_time_(0), | 332 last_mouse_hwheel_time_(0), |
333 dwm_transition_desired_(false), | 333 dwm_transition_desired_(false), |
334 sent_window_size_changing_(false), | 334 sent_window_size_changing_(false), |
335 left_button_down_on_caption_(false), | 335 left_button_down_on_caption_(false), |
336 background_fullscreen_hack_(false), | |
336 autohide_factory_(this), | 337 autohide_factory_(this), |
337 weak_factory_(this) {} | 338 weak_factory_(this) {} |
338 | 339 |
339 HWNDMessageHandler::~HWNDMessageHandler() { | 340 HWNDMessageHandler::~HWNDMessageHandler() { |
340 delegate_ = NULL; | 341 delegate_ = NULL; |
341 // Prevent calls back into this class via WNDPROC now that we've been | 342 // Prevent calls back into this class via WNDPROC now that we've been |
342 // destroyed. | 343 // destroyed. |
343 ClearUserData(); | 344 ClearUserData(); |
344 } | 345 } |
345 | 346 |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
518 *show_state = ui::SHOW_STATE_MAXIMIZED; | 519 *show_state = ui::SHOW_STATE_MAXIMIZED; |
519 else if (wp.showCmd == SW_SHOWMINIMIZED) | 520 else if (wp.showCmd == SW_SHOWMINIMIZED) |
520 *show_state = ui::SHOW_STATE_MINIMIZED; | 521 *show_state = ui::SHOW_STATE_MINIMIZED; |
521 else | 522 else |
522 *show_state = ui::SHOW_STATE_NORMAL; | 523 *show_state = ui::SHOW_STATE_NORMAL; |
523 } | 524 } |
524 } | 525 } |
525 | 526 |
526 void HWNDMessageHandler::SetBounds(const gfx::Rect& bounds_in_pixels, | 527 void HWNDMessageHandler::SetBounds(const gfx::Rect& bounds_in_pixels, |
527 bool force_size_changed) { | 528 bool force_size_changed) { |
528 LONG style = GetWindowLong(hwnd(), GWL_STYLE); | 529 background_fullscreen_hack_ = false; |
529 if (style & WS_MAXIMIZE) | 530 SetBoundsInternal(bounds_in_pixels, force_size_changed); |
530 SetWindowLong(hwnd(), GWL_STYLE, style & ~WS_MAXIMIZE); | |
531 | |
532 gfx::Size old_size = GetClientAreaBounds().size(); | |
533 SetWindowPos(hwnd(), NULL, bounds_in_pixels.x(), bounds_in_pixels.y(), | |
534 bounds_in_pixels.width(), bounds_in_pixels.height(), | |
535 SWP_NOACTIVATE | SWP_NOZORDER); | |
536 | |
537 // If HWND size is not changed, we will not receive standard size change | |
538 // notifications. If |force_size_changed| is |true|, we should pretend size is | |
539 // changed. | |
540 if (old_size == bounds_in_pixels.size() && force_size_changed) { | |
541 delegate_->HandleClientSizeChanged(GetClientAreaBounds().size()); | |
542 ResetWindowRegion(false, true); | |
543 } | |
544 | |
545 if (direct_manipulation_helper_) | |
546 direct_manipulation_helper_->SetBounds(bounds_in_pixels); | |
547 } | 531 } |
548 | 532 |
549 void HWNDMessageHandler::SetSize(const gfx::Size& size) { | 533 void HWNDMessageHandler::SetSize(const gfx::Size& size) { |
550 SetWindowPos(hwnd(), NULL, 0, 0, size.width(), size.height(), | 534 SetWindowPos(hwnd(), NULL, 0, 0, size.width(), size.height(), |
551 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); | 535 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); |
552 } | 536 } |
553 | 537 |
554 void HWNDMessageHandler::CenterWindow(const gfx::Size& size) { | 538 void HWNDMessageHandler::CenterWindow(const gfx::Size& size) { |
555 HWND parent = GetParent(hwnd()); | 539 HWND parent = GetParent(hwnd()); |
556 if (!IsWindow(hwnd())) | 540 if (!IsWindow(hwnd())) |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
837 } | 821 } |
838 if (!app_icon.isNull()) { | 822 if (!app_icon.isNull()) { |
839 base::win::ScopedHICON previous_icon = app_icon_.Pass(); | 823 base::win::ScopedHICON previous_icon = app_icon_.Pass(); |
840 app_icon_ = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()).Pass(); | 824 app_icon_ = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()).Pass(); |
841 SendMessage(hwnd(), WM_SETICON, ICON_BIG, | 825 SendMessage(hwnd(), WM_SETICON, ICON_BIG, |
842 reinterpret_cast<LPARAM>(app_icon_.get())); | 826 reinterpret_cast<LPARAM>(app_icon_.get())); |
843 } | 827 } |
844 } | 828 } |
845 | 829 |
846 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { | 830 void HWNDMessageHandler::SetFullscreen(bool fullscreen) { |
831 background_fullscreen_hack_ = false; | |
847 fullscreen_handler()->SetFullscreen(fullscreen); | 832 fullscreen_handler()->SetFullscreen(fullscreen); |
848 // If we are out of fullscreen and there was a pending DWM transition for the | 833 // If we are out of fullscreen and there was a pending DWM transition for the |
849 // window, then go ahead and do it now. | 834 // window, then go ahead and do it now. |
850 if (!fullscreen && dwm_transition_desired_) | 835 if (!fullscreen && dwm_transition_desired_) |
851 PerformDwmTransition(); | 836 PerformDwmTransition(); |
852 } | 837 } |
853 | 838 |
854 void HWNDMessageHandler::SizeConstraintsChanged() { | 839 void HWNDMessageHandler::SizeConstraintsChanged() { |
855 LONG style = GetWindowLong(hwnd(), GWL_STYLE); | 840 LONG style = GetWindowLong(hwnd(), GWL_STYLE); |
856 // Ignore if this is not a standard window. | 841 // Ignore if this is not a standard window. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
922 return result; | 907 return result; |
923 } | 908 } |
924 | 909 |
925 if (delegate_) { | 910 if (delegate_) { |
926 delegate_->PostHandleMSG(message, w_param, l_param); | 911 delegate_->PostHandleMSG(message, w_param, l_param); |
927 if (message == WM_NCDESTROY) | 912 if (message == WM_NCDESTROY) |
928 delegate_->HandleDestroyed(); | 913 delegate_->HandleDestroyed(); |
929 } | 914 } |
930 | 915 |
931 if (message == WM_ACTIVATE && IsTopLevelWindow(window)) | 916 if (message == WM_ACTIVATE && IsTopLevelWindow(window)) |
932 PostProcessActivateMessage(LOWORD(w_param), !!HIWORD(w_param)); | 917 PostProcessActivateMessage(LOWORD(w_param), !!HIWORD(w_param), |
918 reinterpret_cast<HWND>(l_param)); | |
933 return result; | 919 return result; |
934 } | 920 } |
935 | 921 |
936 LRESULT HWNDMessageHandler::HandleMouseMessage(unsigned int message, | 922 LRESULT HWNDMessageHandler::HandleMouseMessage(unsigned int message, |
937 WPARAM w_param, | 923 WPARAM w_param, |
938 LPARAM l_param, | 924 LPARAM l_param, |
939 bool* handled) { | 925 bool* handled) { |
940 // Don't track forwarded mouse messages. We expect the caller to track the | 926 // Don't track forwarded mouse messages. We expect the caller to track the |
941 // mouse. | 927 // mouse. |
942 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); | 928 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1020 } | 1006 } |
1021 | 1007 |
1022 void HWNDMessageHandler::SetInitialFocus() { | 1008 void HWNDMessageHandler::SetInitialFocus() { |
1023 if (!(GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_TRANSPARENT) && | 1009 if (!(GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_TRANSPARENT) && |
1024 !(GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_NOACTIVATE)) { | 1010 !(GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_NOACTIVATE)) { |
1025 // The window does not get keyboard messages unless we focus it. | 1011 // The window does not get keyboard messages unless we focus it. |
1026 SetFocus(hwnd()); | 1012 SetFocus(hwnd()); |
1027 } | 1013 } |
1028 } | 1014 } |
1029 | 1015 |
1030 void HWNDMessageHandler::PostProcessActivateMessage(int activation_state, | 1016 void HWNDMessageHandler::PostProcessActivateMessage( |
1031 bool minimized) { | 1017 int activation_state, |
1018 bool minimized, | |
1019 HWND window_gaining_or_losing_activation) { | |
1032 DCHECK(IsTopLevelWindow(hwnd())); | 1020 DCHECK(IsTopLevelWindow(hwnd())); |
1033 const bool active = activation_state != WA_INACTIVE && !minimized; | 1021 const bool active = activation_state != WA_INACTIVE && !minimized; |
1034 if (delegate_->CanActivate()) | 1022 if (delegate_->CanActivate()) |
1035 delegate_->HandleActivationChanged(active); | 1023 delegate_->HandleActivationChanged(active); |
1024 | |
1025 if (!::IsWindow(window_gaining_or_losing_activation)) | |
1026 window_gaining_or_losing_activation = ::GetForegroundWindow(); | |
1027 | |
1028 // If the window losing activation is a fullscreen window, we reduce the size | |
1029 // of the window by 1px. i.e. Not fullscreen. This is to work around an | |
1030 // apparent bug in the Windows taskbar where in it tracks fullscreen state on | |
1031 // a per thread basis. This causes it not be a topmost window when any | |
1032 // maximized window on a thread which has a fullscreen window is active. This | |
1033 // affects the way these windows interact with the taskbar, they obscure it | |
1034 // when maximized, autohide does not work correctly, etc. | |
1035 // By reducing the size of the fullscreen window by 1px, we ensure that the | |
1036 // taskbar no longer treats the window and in turn the thread as a fullscreen | |
1037 // thread. This in turn ensures that maximized windows on the same thread | |
1038 /// don't obscure the taskbar, etc. | |
1039 if (!active) { | |
1040 if (fullscreen_handler_->fullscreen() && | |
1041 ::IsWindow(window_gaining_or_losing_activation)) { | |
1042 // Reduce the bounds of the window by 1px to ensure that Windows does | |
1043 // not treat this like a fullscreen window. | |
1044 MONITORINFO monitor_info = {sizeof(monitor_info)}; | |
1045 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | |
1046 &monitor_info); | |
1047 gfx::Rect shrunk_rect(monitor_info.rcMonitor); | |
1048 shrunk_rect.set_height(shrunk_rect.height() - 1); | |
1049 background_fullscreen_hack_ = true; | |
1050 SetBoundsInternal(shrunk_rect, false); | |
1051 } | |
1052 } else if (background_fullscreen_hack_) { | |
1053 // Restore the bounds of the window to fullscreen. | |
1054 DCHECK(fullscreen_handler_->fullscreen()); | |
1055 background_fullscreen_hack_ = false; | |
1056 MONITORINFO monitor_info = {sizeof(monitor_info)}; | |
1057 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), | |
1058 &monitor_info); | |
1059 SetBoundsInternal(gfx::Rect(monitor_info.rcMonitor), false); | |
1060 } | |
1036 } | 1061 } |
1037 | 1062 |
1038 void HWNDMessageHandler::RestoreEnabledIfNecessary() { | 1063 void HWNDMessageHandler::RestoreEnabledIfNecessary() { |
1039 if (delegate_->IsModal() && !restored_enabled_) { | 1064 if (delegate_->IsModal() && !restored_enabled_) { |
1040 restored_enabled_ = true; | 1065 restored_enabled_ = true; |
1041 // If we were run modally, we need to undo the disabled-ness we inflicted on | 1066 // If we were run modally, we need to undo the disabled-ness we inflicted on |
1042 // the owner's parent hierarchy. | 1067 // the owner's parent hierarchy. |
1043 HWND start = ::GetWindow(hwnd(), GW_OWNER); | 1068 HWND start = ::GetWindow(hwnd(), GW_OWNER); |
1044 while (start) { | 1069 while (start) { |
1045 ::EnableWindow(start, TRUE); | 1070 ::EnableWindow(start, TRUE); |
(...skipping 25 matching lines...) Expand all Loading... | |
1071 tme.hwndTrack = hwnd(); | 1096 tme.hwndTrack = hwnd(); |
1072 tme.dwHoverTime = 0; | 1097 tme.dwHoverTime = 0; |
1073 TrackMouseEvent(&tme); | 1098 TrackMouseEvent(&tme); |
1074 } else if (mouse_tracking_flags != active_mouse_tracking_flags_) { | 1099 } else if (mouse_tracking_flags != active_mouse_tracking_flags_) { |
1075 TrackMouseEvents(active_mouse_tracking_flags_ | TME_CANCEL); | 1100 TrackMouseEvents(active_mouse_tracking_flags_ | TME_CANCEL); |
1076 TrackMouseEvents(mouse_tracking_flags); | 1101 TrackMouseEvents(mouse_tracking_flags); |
1077 } | 1102 } |
1078 } | 1103 } |
1079 | 1104 |
1080 void HWNDMessageHandler::ClientAreaSizeChanged() { | 1105 void HWNDMessageHandler::ClientAreaSizeChanged() { |
1106 // Ignore size changes due to fullscreen windows losing activation. | |
1107 if (background_fullscreen_hack_) | |
1108 return; | |
1081 gfx::Size s = GetClientAreaBounds().size(); | 1109 gfx::Size s = GetClientAreaBounds().size(); |
1082 delegate_->HandleClientSizeChanged(s); | 1110 delegate_->HandleClientSizeChanged(s); |
1083 } | 1111 } |
1084 | 1112 |
1085 bool HWNDMessageHandler::GetClientAreaInsets(gfx::Insets* insets) const { | 1113 bool HWNDMessageHandler::GetClientAreaInsets(gfx::Insets* insets) const { |
1086 if (delegate_->GetClientAreaInsets(insets)) | 1114 if (delegate_->GetClientAreaInsets(insets)) |
1087 return true; | 1115 return true; |
1088 DCHECK(insets->IsEmpty()); | 1116 DCHECK(insets->IsEmpty()); |
1089 | 1117 |
1090 // Returning false causes the default handling in OnNCCalcSize() to | 1118 // Returning false causes the default handling in OnNCCalcSize() to |
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2158 window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW); | 2186 window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW); |
2159 } | 2187 } |
2160 } else if (!GetParent(hwnd())) { | 2188 } else if (!GetParent(hwnd())) { |
2161 RECT window_rect; | 2189 RECT window_rect; |
2162 HMONITOR monitor; | 2190 HMONITOR monitor; |
2163 gfx::Rect monitor_rect, work_area; | 2191 gfx::Rect monitor_rect, work_area; |
2164 if (GetWindowRect(hwnd(), &window_rect) && | 2192 if (GetWindowRect(hwnd(), &window_rect) && |
2165 GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) { | 2193 GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) { |
2166 bool work_area_changed = (monitor_rect == last_monitor_rect_) && | 2194 bool work_area_changed = (monitor_rect == last_monitor_rect_) && |
2167 (work_area != last_work_area_); | 2195 (work_area != last_work_area_); |
2196 // If the size of a background fullscreen window changes again, then we | |
2197 // should reset the |background_fullscreen_hack_| flag. | |
2198 if (background_fullscreen_hack_) { | |
2199 if (monitor_rect.height() - window_pos->cy != 1) | |
sky
2016/02/19 23:29:24
nit: combing ifs.
ananta
2016/02/20 00:12:48
Done.
| |
2200 background_fullscreen_hack_ = false; | |
2201 } | |
2168 if (monitor && (monitor == last_monitor_) && | 2202 if (monitor && (monitor == last_monitor_) && |
2169 ((fullscreen_handler_->fullscreen() && | 2203 ((fullscreen_handler_->fullscreen() && |
2170 !fullscreen_handler_->metro_snap()) || | 2204 !fullscreen_handler_->metro_snap() && |
2205 !background_fullscreen_hack_) || | |
2171 work_area_changed)) { | 2206 work_area_changed)) { |
2172 // A rect for the monitor we're on changed. Normally Windows notifies | 2207 // A rect for the monitor we're on changed. Normally Windows notifies |
2173 // us about this (and thus we're reaching here due to the SetWindowPos() | 2208 // us about this (and thus we're reaching here due to the SetWindowPos() |
2174 // call in OnSettingChange() above), but with some software (e.g. | 2209 // call in OnSettingChange() above), but with some software (e.g. |
2175 // nVidia's nView desktop manager) the work area can change asynchronous | 2210 // nVidia's nView desktop manager) the work area can change asynchronous |
2176 // to any notification, and we're just sent a SetWindowPos() call with a | 2211 // to any notification, and we're just sent a SetWindowPos() call with a |
2177 // new (frequently incorrect) position/size. In either case, the best | 2212 // new (frequently incorrect) position/size. In either case, the best |
2178 // response is to throw away the existing position/size information in | 2213 // response is to throw away the existing position/size information in |
2179 // |window_pos| and recalculate it based on the new work rect. | 2214 // |window_pos| and recalculate it based on the new work rect. |
2180 gfx::Rect new_window_rect; | 2215 gfx::Rect new_window_rect; |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2568 case WM_NCMOUSELEAVE: | 2603 case WM_NCMOUSELEAVE: |
2569 break; | 2604 break; |
2570 | 2605 |
2571 default: | 2606 default: |
2572 left_button_down_on_caption_ = false; | 2607 left_button_down_on_caption_ = false; |
2573 break; | 2608 break; |
2574 } | 2609 } |
2575 return handled; | 2610 return handled; |
2576 } | 2611 } |
2577 | 2612 |
2613 void HWNDMessageHandler::SetBoundsInternal(const gfx::Rect& bounds_in_pixels, | |
2614 bool force_size_changed) { | |
2615 LONG style = GetWindowLong(hwnd(), GWL_STYLE); | |
2616 if (style & WS_MAXIMIZE) | |
2617 SetWindowLong(hwnd(), GWL_STYLE, style & ~WS_MAXIMIZE); | |
2618 | |
2619 gfx::Size old_size = GetClientAreaBounds().size(); | |
2620 SetWindowPos(hwnd(), NULL, bounds_in_pixels.x(), bounds_in_pixels.y(), | |
2621 bounds_in_pixels.width(), bounds_in_pixels.height(), | |
2622 SWP_NOACTIVATE | SWP_NOZORDER); | |
2623 | |
2624 // If HWND size is not changed, we will not receive standard size change | |
2625 // notifications. If |force_size_changed| is |true|, we should pretend size is | |
2626 // changed. | |
2627 if (old_size == bounds_in_pixels.size() && force_size_changed && | |
2628 !background_fullscreen_hack_) { | |
2629 delegate_->HandleClientSizeChanged(GetClientAreaBounds().size()); | |
2630 ResetWindowRegion(false, true); | |
2631 } | |
2632 | |
2633 if (direct_manipulation_helper_) | |
2634 direct_manipulation_helper_->SetBounds(bounds_in_pixels); | |
2635 } | |
2636 | |
2578 | 2637 |
2579 } // namespace views | 2638 } // namespace views |
OLD | NEW |