Index: ui/views/win/hwnd_message_handler.cc |
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc |
index f632827ca29663e93365929d151c4c1c5add9d49..0fbca73c32b4e2ac5831e20d28b09d31055bffc6 100644 |
--- a/ui/views/win/hwnd_message_handler.cc |
+++ b/ui/views/win/hwnd_message_handler.cc |
@@ -333,6 +333,7 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) |
dwm_transition_desired_(false), |
sent_window_size_changing_(false), |
left_button_down_on_caption_(false), |
+ background_fullscreen_hack_(false), |
autohide_factory_(this), |
weak_factory_(this) {} |
@@ -525,25 +526,8 @@ void HWNDMessageHandler::GetWindowPlacement( |
void HWNDMessageHandler::SetBounds(const gfx::Rect& bounds_in_pixels, |
bool force_size_changed) { |
- LONG style = GetWindowLong(hwnd(), GWL_STYLE); |
- if (style & WS_MAXIMIZE) |
- SetWindowLong(hwnd(), GWL_STYLE, style & ~WS_MAXIMIZE); |
- |
- gfx::Size old_size = GetClientAreaBounds().size(); |
- SetWindowPos(hwnd(), NULL, bounds_in_pixels.x(), bounds_in_pixels.y(), |
- bounds_in_pixels.width(), bounds_in_pixels.height(), |
- SWP_NOACTIVATE | SWP_NOZORDER); |
- |
- // If HWND size is not changed, we will not receive standard size change |
- // notifications. If |force_size_changed| is |true|, we should pretend size is |
- // changed. |
- if (old_size == bounds_in_pixels.size() && force_size_changed) { |
- delegate_->HandleClientSizeChanged(GetClientAreaBounds().size()); |
- ResetWindowRegion(false, true); |
- } |
- |
- if (direct_manipulation_helper_) |
- direct_manipulation_helper_->SetBounds(bounds_in_pixels); |
+ background_fullscreen_hack_ = false; |
+ SetBoundsInternal(bounds_in_pixels, force_size_changed); |
} |
void HWNDMessageHandler::SetSize(const gfx::Size& size) { |
@@ -844,6 +828,7 @@ void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon, |
} |
void HWNDMessageHandler::SetFullscreen(bool fullscreen) { |
+ background_fullscreen_hack_ = false; |
fullscreen_handler()->SetFullscreen(fullscreen); |
// If we are out of fullscreen and there was a pending DWM transition for the |
// window, then go ahead and do it now. |
@@ -929,7 +914,8 @@ LRESULT HWNDMessageHandler::OnWndProc(UINT message, |
} |
if (message == WM_ACTIVATE && IsTopLevelWindow(window)) |
- PostProcessActivateMessage(LOWORD(w_param), !!HIWORD(w_param)); |
+ PostProcessActivateMessage(LOWORD(w_param), !!HIWORD(w_param), |
+ reinterpret_cast<HWND>(l_param)); |
return result; |
} |
@@ -1027,12 +1013,51 @@ void HWNDMessageHandler::SetInitialFocus() { |
} |
} |
-void HWNDMessageHandler::PostProcessActivateMessage(int activation_state, |
- bool minimized) { |
+void HWNDMessageHandler::PostProcessActivateMessage( |
+ int activation_state, |
+ bool minimized, |
+ HWND window_gaining_or_losing_activation) { |
DCHECK(IsTopLevelWindow(hwnd())); |
const bool active = activation_state != WA_INACTIVE && !minimized; |
if (delegate_->CanActivate()) |
delegate_->HandleActivationChanged(active); |
+ |
+ if (!::IsWindow(window_gaining_or_losing_activation)) |
+ window_gaining_or_losing_activation = ::GetForegroundWindow(); |
+ |
+ // If the window losing activation is a fullscreen window, we reduce the size |
+ // of the window by 1px. i.e. Not fullscreen. This is to work around an |
+ // apparent bug in the Windows taskbar where in it tracks fullscreen state on |
+ // a per thread basis. This causes it not be a topmost window when any |
+ // maximized window on a thread which has a fullscreen window is active. This |
+ // affects the way these windows interact with the taskbar, they obscure it |
+ // when maximized, autohide does not work correctly, etc. |
+ // By reducing the size of the fullscreen window by 1px, we ensure that the |
+ // taskbar no longer treats the window and in turn the thread as a fullscreen |
+ // thread. This in turn ensures that maximized windows on the same thread |
+ /// don't obscure the taskbar, etc. |
+ if (!active) { |
+ if (fullscreen_handler_->fullscreen() && |
+ ::IsWindow(window_gaining_or_losing_activation)) { |
+ // Reduce the bounds of the window by 1px to ensure that Windows does |
+ // not treat this like a fullscreen window. |
+ MONITORINFO monitor_info = {sizeof(monitor_info)}; |
+ GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), |
+ &monitor_info); |
+ gfx::Rect shrunk_rect(monitor_info.rcMonitor); |
+ shrunk_rect.set_height(shrunk_rect.height() - 1); |
+ background_fullscreen_hack_ = true; |
+ SetBoundsInternal(shrunk_rect, false); |
+ } |
+ } else if (background_fullscreen_hack_) { |
+ // Restore the bounds of the window to fullscreen. |
+ DCHECK(fullscreen_handler_->fullscreen()); |
+ background_fullscreen_hack_ = false; |
+ MONITORINFO monitor_info = {sizeof(monitor_info)}; |
+ GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), |
+ &monitor_info); |
+ SetBoundsInternal(gfx::Rect(monitor_info.rcMonitor), false); |
+ } |
} |
void HWNDMessageHandler::RestoreEnabledIfNecessary() { |
@@ -1078,6 +1103,9 @@ void HWNDMessageHandler::TrackMouseEvents(DWORD mouse_tracking_flags) { |
} |
void HWNDMessageHandler::ClientAreaSizeChanged() { |
+ // Ignore size changes due to fullscreen windows losing activation. |
+ if (background_fullscreen_hack_) |
+ return; |
gfx::Size s = GetClientAreaBounds().size(); |
delegate_->HandleClientSizeChanged(s); |
} |
@@ -2165,9 +2193,17 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) { |
GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) { |
bool work_area_changed = (monitor_rect == last_monitor_rect_) && |
(work_area != last_work_area_); |
+ // If the size of a background fullscreen window changes again, then we |
+ // should reset the |background_fullscreen_hack_| flag. |
+ if (background_fullscreen_hack_ && |
+ (!(window_pos->flags & SWP_NOSIZE) && |
+ (monitor_rect.height() - window_pos->cy != 1))) { |
+ background_fullscreen_hack_ = false; |
+ } |
if (monitor && (monitor == last_monitor_) && |
((fullscreen_handler_->fullscreen() && |
- !fullscreen_handler_->metro_snap()) || |
+ !fullscreen_handler_->metro_snap() && |
+ !background_fullscreen_hack_) || |
work_area_changed)) { |
// A rect for the monitor we're on changed. Normally Windows notifies |
// us about this (and thus we're reaching here due to the SetWindowPos() |
@@ -2575,5 +2611,29 @@ bool HWNDMessageHandler::HandleMouseInputForCaption(unsigned int message, |
return handled; |
} |
+void HWNDMessageHandler::SetBoundsInternal(const gfx::Rect& bounds_in_pixels, |
+ bool force_size_changed) { |
+ LONG style = GetWindowLong(hwnd(), GWL_STYLE); |
+ if (style & WS_MAXIMIZE) |
+ SetWindowLong(hwnd(), GWL_STYLE, style & ~WS_MAXIMIZE); |
+ |
+ gfx::Size old_size = GetClientAreaBounds().size(); |
+ SetWindowPos(hwnd(), NULL, bounds_in_pixels.x(), bounds_in_pixels.y(), |
+ bounds_in_pixels.width(), bounds_in_pixels.height(), |
+ SWP_NOACTIVATE | SWP_NOZORDER); |
+ |
+ // If HWND size is not changed, we will not receive standard size change |
+ // notifications. If |force_size_changed| is |true|, we should pretend size is |
+ // changed. |
+ if (old_size == bounds_in_pixels.size() && force_size_changed && |
+ !background_fullscreen_hack_) { |
+ delegate_->HandleClientSizeChanged(GetClientAreaBounds().size()); |
+ ResetWindowRegion(false, true); |
+ } |
+ |
+ if (direct_manipulation_helper_) |
+ direct_manipulation_helper_->SetBounds(bounds_in_pixels); |
+} |
+ |
} // namespace views |