]> git.sesse.net Git - casparcg/blobdiff - dependencies64/cef/windows/tests/cefclient/browser/views_window.cc
Upgrade CEF to 3.3029.1611.g44e39a8 / Chromium 58.0.3029.81.
[casparcg] / dependencies64 / cef / windows / tests / cefclient / browser / views_window.cc
diff --git a/dependencies64/cef/windows/tests/cefclient/browser/views_window.cc b/dependencies64/cef/windows/tests/cefclient/browser/views_window.cc
new file mode 100644 (file)
index 0000000..459a10a
--- /dev/null
@@ -0,0 +1,722 @@
+// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+
+#include "tests/cefclient/browser/views_window.h"
+
+#include <algorithm>
+
+#include "include/base/cef_bind.h"
+#include "include/base/cef_build.h"
+#include "include/views/cef_box_layout.h"
+#include "include/wrapper/cef_helpers.h"
+#include "include/cef_app.h"
+#include "tests/cefclient/browser/resource.h"
+#include "tests/cefclient/browser/views_style.h"
+#include "tests/shared/browser/resource_util.h"
+#include "tests/shared/common/client_switches.h"
+
+#if !defined(OS_WIN)
+#define VK_RETURN 0x0D
+#define VK_MENU   0x12  // ALT key.
+#endif
+
+namespace client {
+
+namespace {
+
+// Control IDs for Views in the top-level Window.
+enum ControlIds {
+  ID_WINDOW = 1,
+  ID_BROWSER_VIEW,
+  ID_BACK_BUTTON,
+  ID_FORWARD_BUTTON,
+  ID_STOP_BUTTON,
+  ID_RELOAD_BUTTON,
+  ID_URL_TEXTFIELD,
+  ID_MENU_BUTTON,
+
+  // Reserved range of top menu button IDs.
+  ID_TOP_MENU_FIRST,
+  ID_TOP_MENU_LAST = ID_TOP_MENU_FIRST + 10,
+};
+
+typedef std::vector<CefRefPtr<CefLabelButton> > LabelButtons;
+
+// Make all |buttons| the same size.
+void MakeButtonsSameSize(const LabelButtons& buttons) {
+  CefSize size;
+
+  // Determine the largest button size.
+  for (size_t i = 0U; i < buttons.size(); ++i) {
+    const CefSize& button_size = buttons[i]->GetPreferredSize();
+    if (size.width < button_size.width)
+      size.width = button_size.width;
+    if (size.height < button_size.height)
+      size.height = button_size.height;
+  }
+
+  for (size_t i = 0U; i < buttons.size(); ++i) {
+    // Set the button's minimum size.
+    buttons[i]->SetMinimumSize(size);
+
+    // Re-layout the button and all parent Views.
+    buttons[i]->InvalidateLayout();
+  }
+}
+
+void AddTestMenuItems(CefRefPtr<CefMenuModel> test_menu) {
+  test_menu->AddItem(ID_TESTS_GETSOURCE,      "Get Source");
+  test_menu->AddItem(ID_TESTS_GETTEXT,        "Get Text");
+  test_menu->AddItem(ID_TESTS_WINDOW_NEW,     "New Window");
+  test_menu->AddItem(ID_TESTS_WINDOW_POPUP,   "Popup Window");
+  test_menu->AddItem(ID_TESTS_REQUEST,        "Request");
+  test_menu->AddItem(ID_TESTS_PLUGIN_INFO,    "Plugin Info");
+  test_menu->AddItem(ID_TESTS_ZOOM_IN,        "Zoom In");
+  test_menu->AddItem(ID_TESTS_ZOOM_OUT,       "Zoom Out");
+  test_menu->AddItem(ID_TESTS_ZOOM_RESET,     "Zoom Reset");
+  test_menu->AddItem(ID_TESTS_TRACING_BEGIN,  "Begin Tracing");
+  test_menu->AddItem(ID_TESTS_TRACING_END,    "End Tracing");
+  test_menu->AddItem(ID_TESTS_PRINT,          "Print");
+  test_menu->AddItem(ID_TESTS_PRINT_TO_PDF,   "Print to PDF");
+  test_menu->AddItem(ID_TESTS_OTHER_TESTS,    "Other Tests");
+}
+
+void AddFileMenuItems(CefRefPtr<CefMenuModel> file_menu) {
+  file_menu->AddItem(ID_QUIT, "E&xit");
+
+  // Show the accelerator shortcut text in the menu.
+  file_menu->SetAcceleratorAt(file_menu->GetCount() - 1,
+                              'X', false, false, true);
+}
+
+}  // namespace
+
+// static
+CefRefPtr<ViewsWindow> ViewsWindow::Create(
+    Delegate* delegate,
+    CefRefPtr<CefClient> client,
+    const CefString& url,
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefRequestContext> request_context) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(delegate);
+
+  // Create a new ViewsWindow.
+  CefRefPtr<ViewsWindow> views_window = new ViewsWindow(delegate, NULL);
+
+  // Create a new BrowserView.
+  CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
+      client, url, settings, request_context, views_window);
+
+  // Associate the BrowserView with the ViewsWindow.
+  views_window->SetBrowserView(browser_view);
+
+  // Create a new top-level Window. It will show itself after creation.
+  CefWindow::CreateTopLevelWindow(views_window);
+
+  return views_window;
+}
+
+void ViewsWindow::Show() {
+  CEF_REQUIRE_UI_THREAD();
+  if (window_)
+    window_->Show();
+}
+
+void ViewsWindow::Hide() {
+  CEF_REQUIRE_UI_THREAD();
+  if (window_)
+    window_->Hide();
+}
+
+void ViewsWindow::Minimize() {
+  CEF_REQUIRE_UI_THREAD();
+  if (window_)
+    window_->Minimize();
+}
+
+void ViewsWindow::Maximize() {
+  CEF_REQUIRE_UI_THREAD();
+  if (window_)
+    window_->Maximize();
+}
+
+void ViewsWindow::SetBounds(const CefRect& bounds) {
+  CEF_REQUIRE_UI_THREAD();
+  if (window_)
+    window_->SetBounds(bounds);
+}
+
+void ViewsWindow::Close(bool force) {
+  CEF_REQUIRE_UI_THREAD();
+  if (!browser_view_)
+    return;
+
+  CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
+  if (browser) {
+    // This will result in a call to CefWindow::Close() which will then call
+    // ViewsWindow::CanClose().
+    browser->GetHost()->CloseBrowser(force);
+  }
+}
+
+void ViewsWindow::SetAddress(const std::string& url) {
+  CEF_REQUIRE_UI_THREAD();
+  if (!window_ || !with_controls_)
+    return;
+
+  CefRefPtr<CefView> view = window_->GetViewForID(ID_URL_TEXTFIELD);
+  if (view && view->AsTextfield())
+    view->AsTextfield()->SetText(url);
+}
+
+void ViewsWindow::SetTitle(const std::string& title) {
+  CEF_REQUIRE_UI_THREAD();
+  if (window_)
+    window_->SetTitle(title);
+}
+
+void ViewsWindow::SetFavicon(CefRefPtr<CefImage> image) {
+  CEF_REQUIRE_UI_THREAD();
+
+  // Window icons should be 16 DIP in size.
+  DCHECK_EQ(std::max(image->GetWidth(), image->GetHeight()), 16U);
+
+  if (window_)
+    window_->SetWindowIcon(image);
+}
+
+void ViewsWindow::SetFullscreen(bool fullscreen) {
+  CEF_REQUIRE_UI_THREAD();
+  if (window_) {
+    // Hide the top controls while in full-screen mode.
+    if (with_controls_)
+      ShowTopControls(!fullscreen);
+
+    window_->SetFullscreen(fullscreen);
+  }
+}
+
+void ViewsWindow::SetLoadingState(bool isLoading,
+                                  bool canGoBack,
+                                  bool canGoForward) {
+  CEF_REQUIRE_UI_THREAD();
+  if (!window_ || !with_controls_)
+    return;
+
+  EnableView(ID_BACK_BUTTON, canGoBack);
+  EnableView(ID_FORWARD_BUTTON, canGoForward);
+  EnableView(ID_RELOAD_BUTTON, !isLoading);
+  EnableView(ID_STOP_BUTTON, isLoading);
+  EnableView(ID_URL_TEXTFIELD, true);
+}
+
+void ViewsWindow::SetDraggableRegions(
+    const std::vector<CefDraggableRegion>& regions) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (!window_ || !browser_view_)
+    return;
+
+  std::vector<CefDraggableRegion> window_regions;
+
+  // Convert the regions from BrowserView to Window coordinates.
+  std::vector<CefDraggableRegion>::const_iterator it = regions.begin();
+  for (; it != regions.end(); ++it) {
+    CefDraggableRegion region = *it;
+    CefPoint origin = CefPoint(region.bounds.x, region.bounds.y);
+    browser_view_->ConvertPointToWindow(origin);
+    region.bounds.x = origin.x;
+    region.bounds.y = origin.y;
+    window_regions.push_back(region);
+  }
+
+  window_->SetDraggableRegions(window_regions);
+}
+
+void ViewsWindow::TakeFocus(bool next) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (!window_ || !with_controls_)
+    return;
+
+  // Give focus to the URL textfield.
+  window_->GetViewForID(ID_URL_TEXTFIELD)->RequestFocus();
+}
+
+void ViewsWindow::OnBeforeContextMenu(CefRefPtr<CefMenuModel> model) {
+  CEF_REQUIRE_UI_THREAD();
+
+  views_style::ApplyTo(model);
+}
+
+bool ViewsWindow::OnPopupBrowserViewCreated(
+    CefRefPtr<CefBrowserView> browser_view,
+    CefRefPtr<CefBrowserView> popup_browser_view,
+    bool is_devtools) {
+  CEF_REQUIRE_UI_THREAD();
+
+  // The popup browser client is created in CefLifeSpanHandler::OnBeforePopup()
+  // (e.g. via RootWindowViews::InitAsPopup()). The Delegate (RootWindowViews)
+  // knows the association between |client| and itself.
+  Delegate* popup_delegate = delegate_->GetDelegateForPopup(
+      popup_browser_view->GetBrowser()->GetHost()->GetClient());
+
+  // Create a new ViewsWindow for the popup BrowserView.
+  CefRefPtr<ViewsWindow> popup_window =
+      new ViewsWindow(popup_delegate, popup_browser_view);
+
+  // Create a new top-level Window for the popup. It will show itself after
+  // creation.
+  CefWindow::CreateTopLevelWindow(popup_window);
+
+  // We created the Window.
+  return true;
+}
+
+void ViewsWindow::OnButtonPressed(CefRefPtr<CefButton> button) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(with_controls_);
+
+  if (!browser_view_)
+    return;
+
+  CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
+  if (!browser)
+    return;
+
+  switch (button->GetID()) {
+    case ID_BACK_BUTTON:
+      browser->GoBack();
+      break;
+    case ID_FORWARD_BUTTON:
+      browser->GoForward();
+      break;
+    case ID_STOP_BUTTON:
+      browser->StopLoad();
+      break;
+    case ID_RELOAD_BUTTON:
+      browser->Reload();
+      break;
+    case ID_MENU_BUTTON:
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+}
+
+void ViewsWindow::OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,
+                                      const CefPoint& screen_point) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(with_controls_);
+  DCHECK_EQ(ID_MENU_BUTTON, menu_button->GetID());
+
+  menu_button->ShowMenu(button_menu_model_, screen_point,
+                        CEF_MENU_ANCHOR_TOPRIGHT);
+}
+
+void ViewsWindow::ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
+                                 int command_id,
+                                 cef_event_flags_t event_flags) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(with_controls_);
+
+  if (command_id == ID_QUIT) {
+    delegate_->OnExit();
+  } else if (command_id >= ID_TESTS_FIRST && command_id <= ID_TESTS_LAST) {
+    delegate_->OnTest(command_id);
+  } else {
+    NOTREACHED();
+  }
+}
+
+bool ViewsWindow::OnKeyEvent(CefRefPtr<CefTextfield> textfield,
+                             const CefKeyEvent& event) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(with_controls_);
+  DCHECK_EQ(ID_URL_TEXTFIELD, textfield->GetID());
+
+  // Trigger when the return key is pressed.
+  if (window_ && browser_view_ &&
+      event.type == KEYEVENT_RAWKEYDOWN &&
+      event.windows_key_code == VK_RETURN) {
+    CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
+    if (browser) {
+      CefRefPtr<CefView> view = window_->GetViewForID(ID_URL_TEXTFIELD);
+      if (view && view->AsTextfield()) {
+        const CefString& url = view->AsTextfield()->GetText();
+        if (!url.empty())
+          browser->GetMainFrame()->LoadURL(url);
+      }
+    }
+
+    // We handled the event.
+    return true;
+  }
+
+  return false;
+}
+
+void ViewsWindow::OnWindowCreated(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(browser_view_);
+  DCHECK(!window_);
+  DCHECK(window);
+
+  window_ = window;
+  window_->SetID(ID_WINDOW);
+
+  with_controls_ = delegate_->WithControls();
+
+  delegate_->OnViewsWindowCreated(this);
+
+  CefRect bounds = delegate_->GetWindowBounds();
+  if (bounds.IsEmpty()) {
+    // Use the default size.
+    bounds.width = 800;
+    bounds.height = 600;
+  }
+
+  if (bounds.x == 0 && bounds.y == 0) {
+    // Size the Window and center it.
+    window_->CenterWindow(CefSize(bounds.width, bounds.height));
+  } else {
+    // Set the Window bounds as specified.
+    window_->SetBounds(bounds);
+  }
+
+  // Set the background color for regions that are not obscured by other Views.
+  views_style::ApplyTo(window_.get());
+
+  if (with_controls_) {
+    // Add the BrowserView and other controls to the Window.
+    AddControls();
+
+    // Add keyboard accelerators to the Window.
+    AddAccelerators();
+  } else {
+    // Add the BrowserView as the only child of the Window.
+    window_->AddChildView(browser_view_);
+
+    // Choose a reasonable minimum window size.
+    minimum_window_size_ = CefSize(100, 100);
+  }
+  // Show the Window.
+  window_->Show();
+
+  // Give keyboard focus to the BrowserView.
+  browser_view_->RequestFocus();
+}
+
+void ViewsWindow::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(window_);
+
+  delegate_->OnViewsWindowDestroyed(this);
+
+  browser_view_ = NULL;
+  button_menu_model_ = NULL;
+  if (top_menu_bar_) {
+    top_menu_bar_->Reset();
+    top_menu_bar_ = NULL;
+  }
+  window_ = NULL;
+}
+
+bool ViewsWindow::CanClose(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+
+  // Allow the window to close if the browser says it's OK.
+  CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
+  if (browser)
+    return browser->GetHost()->TryCloseBrowser();
+  return true;
+}
+
+bool ViewsWindow::IsFrameless(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  return frameless_;
+}
+
+bool ViewsWindow::OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (command_id == ID_QUIT) {
+    delegate_->OnExit();
+    return true;
+  }
+
+  return false;
+}
+
+bool ViewsWindow::OnKeyEvent(CefRefPtr<CefWindow> window,
+                             const CefKeyEvent& event) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (!window_ || !with_controls_)
+    return false;
+
+  if (event.type == KEYEVENT_RAWKEYDOWN && event.windows_key_code == VK_MENU) {
+    // ALT key is pressed.
+    int last_focused_view = last_focused_view_;
+    bool menu_had_focus = menu_has_focus_;
+    
+    // Toggle menu button focusable.
+    SetMenuFocusable(!menu_has_focus_);
+
+    if (menu_had_focus && last_focused_view != 0) {
+      // Restore focus to the view that was previously focused.
+      window_->GetViewForID(last_focused_view)->RequestFocus();
+    }
+
+    return true;
+  }
+
+  if (menu_has_focus_ && top_menu_bar_)
+    return top_menu_bar_->OnKeyEvent(event);
+
+  return false;
+}
+
+CefSize ViewsWindow::GetMinimumSize(CefRefPtr<CefView> view) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (view->GetID() == ID_WINDOW)
+    return minimum_window_size_;
+
+  return CefSize();
+}
+
+void ViewsWindow::OnFocus(CefRefPtr<CefView> view) {
+  CEF_REQUIRE_UI_THREAD();
+
+  const int view_id = view->GetID();
+
+  // Keep track of the non-menu view that was last focused.
+  if (last_focused_view_ != view_id &&
+      (!top_menu_bar_ || !top_menu_bar_->HasMenuId(view_id))) {
+    last_focused_view_ = view_id;
+  }
+
+  // When focus leaves the menu buttons make them unfocusable.
+  if (menu_has_focus_) {
+    if (top_menu_bar_) {
+      if (!top_menu_bar_->HasMenuId(view_id))
+        SetMenuFocusable(false);
+    } else if (view_id != ID_MENU_BUTTON) {
+      SetMenuFocusable(false);
+    }
+  }
+}
+
+void ViewsWindow::MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
+                                        int command_id,
+                                        cef_event_flags_t event_flags) {
+  ExecuteCommand(menu_model, command_id, event_flags);
+}
+
+ViewsWindow::ViewsWindow(Delegate* delegate,
+                         CefRefPtr<CefBrowserView> browser_view)
+    : delegate_(delegate),
+      with_controls_(false),
+      menu_has_focus_(false),
+      last_focused_view_(false) {
+  DCHECK(delegate_);
+  if (browser_view)
+    SetBrowserView(browser_view);
+
+  CefRefPtr<CefCommandLine> command_line =
+      CefCommandLine::GetGlobalCommandLine();
+  frameless_ = command_line->HasSwitch(switches::kHideFrame);
+
+  if (!command_line->HasSwitch(switches::kHideTopMenu)) {
+    top_menu_bar_ = new ViewsMenuBar(this, ID_TOP_MENU_FIRST);
+  }
+}
+
+void ViewsWindow::SetBrowserView(CefRefPtr<CefBrowserView> browser_view) {
+  DCHECK(!browser_view_);
+  DCHECK(browser_view);
+  DCHECK(browser_view->IsValid());
+  DCHECK(!browser_view->IsAttached());
+  browser_view_ = browser_view;
+  browser_view_->SetID(ID_BROWSER_VIEW);
+}
+
+void ViewsWindow::CreateMenuModel() {
+  // Create the menu button model.
+  button_menu_model_ = CefMenuModel::CreateMenuModel(this);
+  CefRefPtr<CefMenuModel> test_menu =
+      button_menu_model_->AddSubMenu(0, "&Tests");
+  views_style::ApplyTo(button_menu_model_);
+  AddTestMenuItems(test_menu);
+  AddFileMenuItems(button_menu_model_);
+
+  if (top_menu_bar_) {
+    // Add the menus to the top menu bar.
+    AddFileMenuItems(top_menu_bar_->CreateMenuModel("&File", NULL));
+    AddTestMenuItems(top_menu_bar_->CreateMenuModel("&Tests", NULL));
+  }
+}
+
+CefRefPtr<CefLabelButton> ViewsWindow::CreateBrowseButton(
+    const std::string& label,
+    int id) {
+  // The default framed button image resources (IDR_BUTTON_*) look pretty bad
+  // with non-default background colors, so we'll use frameless buttons with
+  // ink drop when a background color is specified.
+  const bool with_frame = !views_style::IsSet();
+
+  CefRefPtr<CefLabelButton> button =
+      CefLabelButton::CreateLabelButton(this, label, with_frame);
+  button->SetID(id);
+  button->SetEnabled(false);  // Disabled by default.
+  button->SetFocusable(false);  // Don't give focus to the button.
+
+  if (!with_frame) {
+    views_style::ApplyTo(button);
+    button->SetInkDropEnabled(true);
+    button->SetHorizontalAlignment(CEF_HORIZONTAL_ALIGNMENT_CENTER);
+  }
+
+  return button;
+}
+
+void ViewsWindow::AddControls() {
+  // Create the MenuModel that will be displayed via the menu button.
+  CreateMenuModel();
+
+  CefRefPtr<CefPanel> top_menu_panel;
+  if (top_menu_bar_)
+    top_menu_panel = top_menu_bar_->GetMenuPanel();
+
+  // Create the browse buttons.
+  LabelButtons browse_buttons;
+  browse_buttons.push_back(CreateBrowseButton("Back", ID_BACK_BUTTON));
+  browse_buttons.push_back(CreateBrowseButton("Forward", ID_FORWARD_BUTTON));
+  browse_buttons.push_back(CreateBrowseButton("Reload", ID_RELOAD_BUTTON));
+  browse_buttons.push_back(CreateBrowseButton("Stop", ID_STOP_BUTTON));
+
+  // Create the URL textfield.
+  CefRefPtr<CefTextfield> url_textfield = CefTextfield::CreateTextfield(this);
+  url_textfield->SetID(ID_URL_TEXTFIELD);
+  url_textfield->SetEnabled(false);  // Disabled by default.
+  views_style::ApplyTo(url_textfield);
+
+  // Create the menu button.
+  CefRefPtr<CefMenuButton> menu_button =
+      CefMenuButton::CreateMenuButton(this, CefString(), false, false);
+  menu_button->SetID(ID_MENU_BUTTON);
+  menu_button->SetImage(CEF_BUTTON_STATE_NORMAL, LoadImageIcon("menu_icon"));
+  views_style::ApplyTo(menu_button.get());
+  menu_button->SetInkDropEnabled(true);
+  // Override the default minimum size.
+  menu_button->SetMinimumSize(CefSize(0, 0));
+
+  // Create the top panel.
+  CefRefPtr<CefPanel> top_panel = CefPanel::CreatePanel(NULL);
+
+  // Use a horizontal box layout for |top_panel|.
+  CefBoxLayoutSettings top_panel_layout_settings;
+  top_panel_layout_settings.horizontal = true;
+  CefRefPtr<CefBoxLayout> top_panel_layout =
+      top_panel->SetToBoxLayout(top_panel_layout_settings);
+
+  // Add the buttons and URL textfield to |top_panel|.
+  for (size_t i = 0U; i < browse_buttons.size(); ++i)
+    top_panel->AddChildView(browse_buttons[i]);
+  top_panel->AddChildView(url_textfield);
+  top_panel->AddChildView(menu_button);
+  views_style::ApplyTo(top_panel);
+
+  // Allow |url_textfield| to grow and fill any remaining space.
+  top_panel_layout->SetFlexForView(url_textfield, 1);
+
+  // Use a vertical box layout for |window|.
+  CefBoxLayoutSettings window_layout_settings;
+  window_layout_settings.horizontal = false;
+  window_layout_settings.between_child_spacing = 2;
+  CefRefPtr<CefBoxLayout> window_layout =
+      window_->SetToBoxLayout(window_layout_settings);
+
+  // Add the top panel and browser view to |window|.
+  if (top_menu_panel)
+    window_->AddChildView(top_menu_panel);
+  window_->AddChildView(top_panel);
+  window_->AddChildView(browser_view_);
+
+  // Allow |browser_view_| to grow and fill any remaining space.
+  window_layout->SetFlexForView(browser_view_, 1);
+
+  // Lay out |window| so we can get the default button sizes.
+  window_->Layout();
+
+  // Make all browse buttons the same size.
+  MakeButtonsSameSize(browse_buttons);
+
+  // Lay out |window| again with the new button sizes.
+  window_->Layout();
+
+  // Minimum window width is the size of all buttons plus some extra.
+  const int min_width = browse_buttons[0]->GetBounds().width * 4 +
+                        menu_button->GetBounds().width + 100;
+  // Minimum window height is the hight of the top toolbar plus some extra.
+  int min_height = top_panel->GetBounds().height + 100;
+  if (top_menu_panel)
+    min_height += top_menu_panel->GetBounds().height;
+
+  minimum_window_size_ = CefSize(min_width, min_height);
+}
+
+void ViewsWindow::AddAccelerators() {
+  // Trigger accelerators without first forwarding to web content.
+  browser_view_->SetPreferAccelerators(true);
+
+  // Specify the accelerators to handle. OnAccelerator will be called when the
+  // accelerator is triggered.
+  window_->SetAccelerator(ID_QUIT, 'X', false, false, true);
+}
+
+void ViewsWindow::SetMenuFocusable(bool focusable) {
+  if (!window_ || !with_controls_)
+    return;
+
+  if (top_menu_bar_) {
+    top_menu_bar_->SetMenuFocusable(focusable);
+  } else {
+    window_->GetViewForID(ID_MENU_BUTTON)->SetFocusable(focusable);
+
+    if (focusable) {
+      // Give focus to menu button.
+      window_->GetViewForID(ID_MENU_BUTTON)->RequestFocus();
+    }
+  }
+
+  menu_has_focus_ = focusable;
+}
+
+void ViewsWindow::EnableView(int id, bool enable) {
+  if (!window_)
+    return;
+  CefRefPtr<CefView> view = window_->GetViewForID(id);
+  if (view)
+    view->SetEnabled(enable);
+}
+
+void ViewsWindow::ShowTopControls(bool show) {
+  if (!window_ || !with_controls_)
+    return;
+
+  // Change the visibility of the panel that contains the buttons.
+  CefRefPtr<CefView> parent_view =
+      window_->GetViewForID(ID_BACK_BUTTON)->GetParentView();
+  if (parent_view->IsVisible() != show) {
+    parent_view->SetVisible(show);
+    parent_view->InvalidateLayout();
+  }
+}
+
+}  // namespace client