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

Side by Side Diff: ui/views/win/hwnd_message_handler.cc

Issue 1707233002: Reduce the fullscreen window height by 1px on activation loss. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reset the background fullscreen state member in HWNDMessageHandler::SetBounds and in WM_WINDOWPOSCH… Created 4 years, 10 months 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 | « ui/views/win/hwnd_message_handler.h ('k') | no next file » | 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 "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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « ui/views/win/hwnd_message_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698