From 8bd4316e5b029c20ef5e7ae0878285abe1f4b873 Mon Sep 17 00:00:00 2001
From: "pkasting@chromium.org"
 <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Thu, 12 Mar 2009 18:02:56 +0000
Subject: Make toggling fullscreen mode on/off significantly less janky-looking
 by means of various crazy hacks. Review URL:
 http://codereview.chromium.org/42106

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@11550 0039d316-1c4b-4281-b951-d872f2087c98
---
 .../autocomplete/autocomplete_edit_view_win.cc     |  7 +++
 .../autocomplete/autocomplete_edit_view_win.h      | 10 ++++
 chrome/browser/views/frame/browser_view.cc         | 59 +++++++++++++++++-----
 chrome/browser/views/frame/browser_view.h          |  4 ++
 chrome/browser/views/location_bar_view.cc          |  5 +-
 5 files changed, 69 insertions(+), 16 deletions(-)

(limited to 'chrome/browser')

diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
index a25845d..6b9c254 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
@@ -406,6 +406,7 @@ AutocompleteEditViewWin::AutocompleteEditViewWin(
       toolbar_model_(toolbar_model),
       command_updater_(command_updater),
       popup_window_mode_(popup_window_mode),
+      force_hidden_(false),
       tracking_click_(false),
       tracking_double_click_(false),
       double_click_time_(0),
@@ -1578,6 +1579,12 @@ void AutocompleteEditViewWin::OnSysChar(TCHAR ch,
     SetMsgHandled(false);
 }
 
+void AutocompleteEditViewWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
+  if (force_hidden_)
+    window_pos->flags &= ~SWP_SHOWWINDOW;
+  SetMsgHandled(true);
+}
+
 void AutocompleteEditViewWin::HandleKeystroke(UINT message,
                                               TCHAR key,
                                               UINT repeat_count,
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.h b/chrome/browser/autocomplete/autocomplete_edit_view_win.h
index 9905f1c..e4c1b02 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_win.h
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.h
@@ -133,6 +133,8 @@ class AutocompleteEditViewWin
   // typed in the specified text and pressed enter.
   void PasteAndGo(const std::wstring& text);
 
+  void set_force_hidden(bool force_hidden) { force_hidden_ = force_hidden; }
+
   // Called before an accelerator is processed to give us a chance to override
   // it.
   bool OverrideAccelerator(const views::Accelerator& accelerator);
@@ -167,6 +169,7 @@ class AutocompleteEditViewWin
     MSG_WM_SYSCHAR(OnSysChar)  // WM_SYSxxx == WM_xxx with ALT down
     MSG_WM_SYSKEYDOWN(OnKeyDown)
     MSG_WM_SYSKEYUP(OnKeyUp)
+    MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
     DEFAULT_REFLECTION_HANDLER()  // avoids black margin area
   END_MSG_MAP()
 
@@ -241,6 +244,7 @@ class AutocompleteEditViewWin
   void OnPaste();
   void OnSetFocus(HWND focus_wnd);
   void OnSysChar(TCHAR ch, UINT repeat_count, UINT flags);
+  void OnWindowPosChanging(WINDOWPOS* window_pos);
 
   // Helper function for OnChar() and OnKeyDown() that handles keystrokes that
   // could change the text in the edit.
@@ -365,6 +369,12 @@ class AutocompleteEditViewWin
   // different presentation (font size / color). This is used for popups.
   bool popup_window_mode_;
 
+  // True if we should prevent attempts to make the window visible when we
+  // handle WM_WINDOWPOSCHANGING.  While toggling fullscreen mode, the main
+  // window is hidden, and if the edit is shown it will draw over the main
+  // window when that window reappears.
+  bool force_hidden_;
+
   // Non-null when the edit is gaining focus from a left click.  This is only
   // needed between when WM_MOUSEACTIVATE and WM_LBUTTONDOWN get processed.  It
   // serves two purposes: first, by communicating to OnLButtonDown() that we're
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 27ddcac..aee2de6 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -209,6 +209,7 @@ BrowserView::BrowserView(Browser* browser)
       contents_container_(NULL),
       initialized_(false),
       fullscreen_(false),
+      ignore_layout_(false),
       can_drop_(false),
       hung_window_detector_(&hung_plugin_action_),
       ticker_(0),
@@ -607,7 +608,7 @@ void BrowserView::SetFullscreen(bool fullscreen) {
   if (fullscreen_ == fullscreen)
     return;  // Nothing to do.
 
-  // Move focus out of the location bar if necessary, and make it unfocusable.
+  // Move focus out of the location bar if necessary.
   LocationBarView* location_bar = toolbar_->GetLocationBarView();
   if (!fullscreen_) {
     views::FocusManager* focus_manager = GetFocusManager();
@@ -615,11 +616,29 @@ void BrowserView::SetFullscreen(bool fullscreen) {
     if (focus_manager->GetFocusedView() == location_bar)
       focus_manager->ClearFocus();
   }
-  location_bar->SetFocusable(fullscreen_);
+  AutocompleteEditViewWin* edit_view =
+      static_cast<AutocompleteEditViewWin*>(location_bar->location_entry());
 
   // Toggle fullscreen mode.
   fullscreen_ = fullscreen;
 
+  // Reduce jankiness during the following position changes by:
+  //   * Hiding the window until it's in the final position
+  //   * Ignoring all intervening Layout() calls, which resize the webpage and
+  //     thus are slow and look ugly
+  ignore_layout_ = true;
+  frame_->set_force_hidden(true);
+  if (fullscreen_) {
+    // If we don't hide the edit and force it to not show until we come out of
+    // fullscreen, then if the user was on the New Tab Page, the edit contents
+    // will appear atop the web contents once we go into fullscreen mode.  This
+    // has something to do with how we move the main window while it's hidden;
+    // if we don't hide the main window below, we don't get this problem.
+    edit_view->set_force_hidden(true);
+    ShowWindow(edit_view->m_hWnd, SW_HIDE);
+  }
+  frame_->Hide();
+
   // Notify bookmark bar, so it can set itself to the appropriate drawing state.
   if (bookmark_bar_view_.get())
     bookmark_bar_view_->OnFullscreenToggled(fullscreen_);
@@ -627,6 +646,11 @@ void BrowserView::SetFullscreen(bool fullscreen) {
   // Size/position/style window appropriately.
   views::Widget* widget = GetWidget();
   HWND hwnd = widget->GetHWND();
+  MONITORINFO monitor_info;
+  monitor_info.cbSize = sizeof(monitor_info);
+  GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY),
+                 &monitor_info);
+  gfx::Rect monitor_rect(monitor_info.rcMonitor);
   if (fullscreen_) {
     // Save current window information.  We force the window into restored mode
     // before going fullscreen because Windows doesn't seem to hide the
@@ -644,15 +668,16 @@ void BrowserView::SetFullscreen(bool fullscreen) {
     SetWindowLong(hwnd, GWL_EXSTYLE,
                   saved_window_info_.ex_style & ~(WS_EX_DLGMODALFRAME |
                   WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
-    MONITORINFO monitor_info;
-    monitor_info.cbSize = sizeof(monitor_info);
-    GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY),
-                   &monitor_info);
-    gfx::Rect new_rect(monitor_info.rcMonitor);
-    SetWindowPos(hwnd, NULL, new_rect.x(), new_rect.y(), new_rect.width(),
-                 new_rect.height(),
+    SetWindowPos(hwnd, NULL, monitor_rect.x(), monitor_rect.y(),
+                 monitor_rect.width(), monitor_rect.height(),
                  SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
+
+    fullscreen_bubble_.reset(new FullscreenExitBubble(widget, browser_.get()));
   } else {
+    // Hide the fullscreen bubble as soon as possible, since the calls below can
+    // take enough time for the user to notice.
+    fullscreen_bubble_.reset();
+
     // Reset original window style and size.  The multiple window size/moves
     // here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be
     // repainted.  Better-looking methods welcome.
@@ -664,11 +689,18 @@ void BrowserView::SetFullscreen(bool fullscreen) {
                  SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
     if (saved_window_info_.maximized)
       frame_->ExecuteSystemMenuCommand(SC_MAXIMIZE);
+
+    // Show the edit again since we're no longer in fullscreen mode.
+    edit_view->set_force_hidden(false);
+    ShowWindow(edit_view->m_hWnd, SW_SHOW);
   }
 
-  // Turn fullscreen bubble on or off.
-  fullscreen_bubble_.reset(fullscreen_ ?
-      new FullscreenExitBubble(widget, browser_.get()) : NULL);
+  // Undo our anti-jankiness hacks and force the window to relayout now that
+  // it's in its final position.
+  ignore_layout_ = false;
+  Layout();
+  frame_->set_force_hidden(false);
+  ShowWindow(hwnd, SW_SHOW);
 }
 
 bool BrowserView::IsFullscreen() const {
@@ -1212,6 +1244,9 @@ std::string BrowserView::GetClassName() const {
 }
 
 void BrowserView::Layout() {
+  if (ignore_layout_)
+    return;
+
   int top = LayoutTabStrip();
   top = LayoutToolbar(top);
   top = LayoutBookmarkAndInfoBars(top);
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index a222819..44d9e0c 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -415,6 +415,10 @@ class BrowserView : public BrowserWindow,
   // True if we're in fullscreen mode.
   bool fullscreen_;
 
+  // True if we should ignore requests to layout.  This is set while toggling
+  // fullscreen mode on and off to reduce jankiness.
+  bool ignore_layout_;
+
   // Saved window information from before entering fullscreen mode.
   SavedWindowInfo saved_window_info_;
 
diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc
index e12f4e2..6ba49c1 100644
--- a/chrome/browser/views/location_bar_view.cc
+++ b/chrome/browser/views/location_bar_view.cc
@@ -385,10 +385,7 @@ void LocationBarView::DoLayout(const bool force_layout) {
                &location_bounds);
   }
 
-  location_entry_view_->SetBounds(location_bounds.x(),
-                                  location_bounds.y(),
-                                  location_bounds.width(),
-                                  location_bounds.height());
+  location_entry_view_->SetBounds(location_bounds);
   if (!force_layout) {
     // If force_layout is false and we got this far it means one of the views
     // was added/removed or changed in size. We need to paint ourselves.
-- 
cgit v1.1