diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 4a8bc16ef6f2..2ae36bc36b3a 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -327,6 +327,7 @@ NativeWindowViews::NativeWindowViews( last_window_state_ = ui::SHOW_STATE_FULLSCREEN; else last_window_state_ = ui::SHOW_STATE_NORMAL; + last_normal_bounds_ = GetBounds(); #endif } diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 379dc4ceaaf3..caaf64ba7134 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -211,6 +211,22 @@ class NativeWindowViews : public NativeWindow, ui::WindowShowState last_window_state_; + // There's an issue with restore on Windows, that sometimes causes the Window + // to receive the wrong size (#2498). To circumvent that, we keep tabs on the + // size of the window while in the normal state (not maximized, minimized or + // fullscreen), so we restore it correctly. + gfx::Rect last_normal_bounds_; + + // last_normal_bounds_ may or may not require update on WM_MOVE. When a + // window is maximized, it is moved (WM_MOVE) to maximum size first and then + // sized (WM_SIZE). In this case, last_normal_bounds_ should not update. We + // keep last_normal_bounds_candidate_ as a candidate which will become valid + // last_normal_bounds_ if the moves are consecutive with no WM_SIZE event in + // between. + gfx::Rect last_normal_bounds_candidate_; + + bool consecutive_moves_; + // In charge of running taskbar related APIs. TaskbarHost taskbar_host_; diff --git a/atom/browser/native_window_views_win.cc b/atom/browser/native_window_views_win.cc index d6f57b6aead8..85230addb0c1 100644 --- a/atom/browser/native_window_views_win.cc +++ b/atom/browser/native_window_views_win.cc @@ -125,6 +125,7 @@ bool NativeWindowViews::PreHandleMSG( return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param)); return false; case WM_SIZE: { + consecutive_moves_ = false; // Handle window state change. HandleSizeEvent(w_param, l_param); return false; @@ -134,6 +135,15 @@ bool NativeWindowViews::PreHandleMSG( ::GetWindowRect(GetAcceleratedWidget(), (LPRECT)l_param); return false; } + case WM_MOVE: { + if (last_window_state_ == ui::SHOW_STATE_NORMAL) { + if (consecutive_moves_) + last_normal_bounds_ = last_normal_bounds_candidate_; + last_normal_bounds_candidate_ = GetBounds(); + consecutive_moves_ = true; + } + return false; + } default: return false; } @@ -152,20 +162,35 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { NotifyWindowMinimize(); break; case SIZE_RESTORED: - switch (last_window_state_) { - case ui::SHOW_STATE_MAXIMIZED: - last_window_state_ = ui::SHOW_STATE_NORMAL; - NotifyWindowUnmaximize(); - break; - case ui::SHOW_STATE_MINIMIZED: - if (IsFullscreen()) { - last_window_state_ = ui::SHOW_STATE_FULLSCREEN; - NotifyWindowEnterFullScreen(); - } else { + if (last_window_state_ == ui::SHOW_STATE_NORMAL) { + // Window was resized so we save it's new size. + last_normal_bounds_ = GetBounds(); + } else { + switch (last_window_state_) { + case ui::SHOW_STATE_MAXIMIZED: last_window_state_ = ui::SHOW_STATE_NORMAL; - NotifyWindowRestore(); - } - break; + + // When the window is restored we resize it to the previous known + // normal size. + SetBounds(last_normal_bounds_, false); + + NotifyWindowUnmaximize(); + break; + case ui::SHOW_STATE_MINIMIZED: + if (IsFullscreen()) { + last_window_state_ = ui::SHOW_STATE_FULLSCREEN; + NotifyWindowEnterFullScreen(); + } else { + last_window_state_ = ui::SHOW_STATE_NORMAL; + + // When the window is restored we resize it to the previous known + // normal size. + SetBounds(last_normal_bounds_, false); + + NotifyWindowRestore(); + } + break; + } } break; }