mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
views: Add support for absolute positioned overlay views.
To test: Run `cefclient.exe --use-views --hide-frame --hide-controls` Add `--enable-chrome-runtime` for the same behavior using the Chrome location bar instead of a text field.
This commit is contained in:
@@ -341,7 +341,7 @@ void RootWindowViews::OnSetAddress(const std::string& url) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_ && config_->with_controls)
|
||||
if (window_)
|
||||
window_->SetAddress(url);
|
||||
}
|
||||
|
||||
@@ -420,8 +420,7 @@ void RootWindowViews::OnSetLoadingState(bool isLoading,
|
||||
}
|
||||
|
||||
if (window_) {
|
||||
if (config_->with_controls)
|
||||
window_->SetLoadingState(isLoading, canGoBack, canGoForward);
|
||||
window_->SetLoadingState(isLoading, canGoBack, canGoForward);
|
||||
|
||||
if (isLoading) {
|
||||
// Reset to the default window icon when loading begins.
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "tests/cefclient/browser/views_menu_bar.h"
|
||||
|
||||
#include "include/cef_i18n_util.h"
|
||||
#include "include/views/cef_box_layout.h"
|
||||
#include "include/views/cef_window.h"
|
||||
#include "tests/cefclient/browser/views_style.h"
|
||||
@@ -153,9 +154,13 @@ void ViewsMenuBar::OnMenuButtonPressed(
|
||||
CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) {
|
||||
CefRefPtr<CefMenuModel> menu_model = GetMenuModel(menu_button->GetID());
|
||||
|
||||
// Adjust menu position left by button width.
|
||||
// Adjust menu position to align with the button.
|
||||
CefPoint point = screen_point;
|
||||
point.x -= menu_button->GetBounds().width - 4;
|
||||
if (CefIsRTL()) {
|
||||
point.x += menu_button->GetBounds().width - 4;
|
||||
} else {
|
||||
point.x -= menu_button->GetBounds().width - 4;
|
||||
}
|
||||
|
||||
// Keep track of the current |last_nav_with_keyboard_| status and restore it
|
||||
// after displaying the new menu.
|
||||
@@ -211,6 +216,11 @@ void ViewsMenuBar::MouseOutsideMenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
|
||||
CefRefPtr<CefView> button = panel_->GetViewForID(id);
|
||||
CefRect button_bounds = button->GetBounds();
|
||||
if (CefIsRTL()) {
|
||||
// Adjust for right-to-left button layout.
|
||||
button_bounds.x =
|
||||
panel_bounds.width - button_bounds.x - button_bounds.width;
|
||||
}
|
||||
if (button_bounds.Contains(window_point)) {
|
||||
// Trigger the hovered MenuButton.
|
||||
TriggerMenuButton(button);
|
||||
|
192
tests/cefclient/browser/views_overlay_controls.cc
Normal file
192
tests/cefclient/browser/views_overlay_controls.cc
Normal file
@@ -0,0 +1,192 @@
|
||||
// Copyright (c) 2021 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_overlay_controls.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "include/views/cef_box_layout.h"
|
||||
#include "include/views/cef_window.h"
|
||||
#include "tests/cefclient/browser/views_style.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kInsets = 4;
|
||||
constexpr int kLocationBarPadding = 100;
|
||||
|
||||
// White with 80% opacity.
|
||||
constexpr auto kBackgroundColor = CefColorSetARGB(255 * .80, 255, 255, 255);
|
||||
|
||||
std::string GetLabel(ViewsOverlayControls::Command command, bool maximized) {
|
||||
switch (command) {
|
||||
case ViewsOverlayControls::Command::kMinimize:
|
||||
return "-";
|
||||
case ViewsOverlayControls::Command::kMaximize:
|
||||
return maximized ? "O" : "o";
|
||||
case ViewsOverlayControls::Command::kClose:
|
||||
return "X";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ViewsOverlayControls::ViewsOverlayControls() = default;
|
||||
|
||||
void ViewsOverlayControls::Initialize(CefRefPtr<CefWindow> window,
|
||||
CefRefPtr<CefMenuButton> menu_button,
|
||||
CefRefPtr<CefView> location_bar,
|
||||
bool is_chrome_toolbar) {
|
||||
DCHECK(!window_);
|
||||
DCHECK(menu_button);
|
||||
DCHECK(location_bar);
|
||||
|
||||
window_ = window;
|
||||
window_maximized_ = window_->IsMaximized();
|
||||
|
||||
// Window control buttons. These controls are currently text which means that
|
||||
// we can't use a transparent background because subpixel text rendering will
|
||||
// break. See comments on the related DCHECK in Label::PaintText.
|
||||
panel_ = CefPanel::CreatePanel(nullptr);
|
||||
views_style::ApplyTo(panel_);
|
||||
|
||||
// Use a horizontal box layout.
|
||||
CefBoxLayoutSettings panel_layout_settings;
|
||||
panel_layout_settings.horizontal = true;
|
||||
panel_->SetToBoxLayout(panel_layout_settings);
|
||||
|
||||
panel_->AddChildView(CreateButton(ViewsOverlayControls::Command::kMinimize));
|
||||
panel_->AddChildView(CreateButton(ViewsOverlayControls::Command::kMaximize));
|
||||
panel_->AddChildView(CreateButton(ViewsOverlayControls::Command::kClose));
|
||||
|
||||
panel_controller_ =
|
||||
window->AddOverlayView(panel_, CEF_DOCKING_MODE_TOP_RIGHT);
|
||||
panel_controller_->SetVisible(true);
|
||||
|
||||
// Menu button.
|
||||
menu_button->SetBackgroundColor(kBackgroundColor);
|
||||
menu_controller_ =
|
||||
window_->AddOverlayView(menu_button, CEF_DOCKING_MODE_TOP_LEFT);
|
||||
menu_controller_->SetInsets(CefInsets(kInsets, kInsets, 0, 0));
|
||||
menu_controller_->SetVisible(true);
|
||||
|
||||
// Location bar. Will be made visible in UpdateControls().
|
||||
location_bar_ = location_bar;
|
||||
is_chrome_toolbar_ = is_chrome_toolbar;
|
||||
// Use a 100% transparent background for the Chrome toolbar.
|
||||
location_bar_->SetBackgroundColor(is_chrome_toolbar_ ? 0 : kBackgroundColor);
|
||||
location_controller_ =
|
||||
window_->AddOverlayView(location_bar_, CEF_DOCKING_MODE_CUSTOM);
|
||||
}
|
||||
|
||||
void ViewsOverlayControls::Destroy() {
|
||||
window_ = nullptr;
|
||||
panel_ = nullptr;
|
||||
panel_controller_->Destroy();
|
||||
panel_controller_ = nullptr;
|
||||
menu_controller_->Destroy();
|
||||
menu_controller_ = nullptr;
|
||||
location_bar_ = nullptr;
|
||||
location_controller_->Destroy();
|
||||
location_controller_ = nullptr;
|
||||
}
|
||||
|
||||
void ViewsOverlayControls::UpdateControls() {
|
||||
// Update location bar size, position and visibility.
|
||||
auto bounds = window_->GetBounds();
|
||||
bounds.x = kLocationBarPadding;
|
||||
bounds.width -= kLocationBarPadding * 2;
|
||||
bounds.y = kInsets;
|
||||
if (is_chrome_toolbar_) {
|
||||
// Fit the standard Chrome toolbar.
|
||||
const auto preferred_size = location_bar_->GetPreferredSize();
|
||||
bounds.height =
|
||||
std::max(menu_controller_->GetSize().height, preferred_size.height);
|
||||
} else {
|
||||
bounds.height = menu_controller_->GetSize().height;
|
||||
}
|
||||
if (bounds.width < kLocationBarPadding * 2) {
|
||||
// Not enough space.
|
||||
location_controller_->SetVisible(false);
|
||||
} else {
|
||||
location_bar_->SetSize(CefSize(bounds.width, bounds.height));
|
||||
location_controller_->SetBounds(bounds);
|
||||
location_controller_->SetVisible(true);
|
||||
}
|
||||
|
||||
MaybeUpdateMaximizeButton();
|
||||
}
|
||||
|
||||
void ViewsOverlayControls::UpdateDraggableRegions(
|
||||
std::vector<CefDraggableRegion>& window_regions) {
|
||||
if (panel_controller_ && panel_controller_->IsVisible()) {
|
||||
window_regions.push_back(CefDraggableRegion(panel_controller_->GetBounds(),
|
||||
/*draggable=*/false));
|
||||
}
|
||||
|
||||
if (menu_controller_ && menu_controller_->IsVisible()) {
|
||||
window_regions.push_back(
|
||||
CefDraggableRegion(menu_controller_->GetBounds(), /*draggable=*/false));
|
||||
}
|
||||
|
||||
if (location_controller_ && location_controller_->IsVisible()) {
|
||||
window_regions.push_back(CefDraggableRegion(
|
||||
location_controller_->GetBounds(), /*draggable=*/false));
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsOverlayControls::OnButtonPressed(CefRefPtr<CefButton> button) {
|
||||
auto command = static_cast<Command>(button->GetID());
|
||||
switch (command) {
|
||||
case ViewsOverlayControls::Command::kMinimize:
|
||||
window_->Minimize();
|
||||
break;
|
||||
case ViewsOverlayControls::Command::kMaximize:
|
||||
if (window_->IsMaximized())
|
||||
window_->Restore();
|
||||
else
|
||||
window_->Maximize();
|
||||
break;
|
||||
case ViewsOverlayControls::Command::kClose:
|
||||
window_->Close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Explicitly reset button state because the button may have moved and it
|
||||
// won't receive the corresponding mouse move events.
|
||||
button->SetState(CEF_BUTTON_STATE_NORMAL);
|
||||
button->SetInkDropEnabled(false);
|
||||
button->SetInkDropEnabled(true);
|
||||
|
||||
if (command == Command::kMaximize)
|
||||
MaybeUpdateMaximizeButton();
|
||||
}
|
||||
|
||||
CefRefPtr<CefLabelButton> ViewsOverlayControls::CreateButton(Command command) {
|
||||
CefRefPtr<CefLabelButton> button = CefLabelButton::CreateLabelButton(
|
||||
this, GetLabel(command, window_maximized_));
|
||||
button->SetID(static_cast<int>(command));
|
||||
views_style::ApplyTo(button);
|
||||
button->SetInkDropEnabled(true);
|
||||
button->SetFocusable(false); // Don't give focus to the button.
|
||||
return button;
|
||||
}
|
||||
|
||||
void ViewsOverlayControls::MaybeUpdateMaximizeButton() {
|
||||
if (window_->IsMaximized() == window_maximized_)
|
||||
return;
|
||||
window_maximized_ = !window_maximized_;
|
||||
|
||||
auto max_button = panel_->GetChildViewAt(1);
|
||||
auto command = static_cast<Command>(max_button->GetID());
|
||||
DCHECK(command == Command::kMaximize);
|
||||
max_button->AsButton()->AsLabelButton()->SetText(
|
||||
GetLabel(command, window_maximized_));
|
||||
|
||||
// Adjust overlay size and placement due to layout changing.
|
||||
panel_controller_->SizeToPreferredSize();
|
||||
}
|
||||
|
||||
} // namespace client
|
71
tests/cefclient/browser/views_overlay_controls.h
Normal file
71
tests/cefclient/browser/views_overlay_controls.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2021 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.
|
||||
|
||||
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_CONTROLS_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_CONTROLS_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/views/cef_button_delegate.h"
|
||||
#include "include/views/cef_label_button.h"
|
||||
#include "include/views/cef_menu_button.h"
|
||||
#include "include/views/cef_overlay_controller.h"
|
||||
#include "include/views/cef_panel.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Implements window overlay controls that receive absolute positioning on top
|
||||
// of the browser view. All methods must be called on the browser process UI
|
||||
// thread.
|
||||
class ViewsOverlayControls : public CefButtonDelegate {
|
||||
public:
|
||||
enum class Command {
|
||||
kMinimize = 1,
|
||||
kMaximize,
|
||||
kClose,
|
||||
};
|
||||
|
||||
ViewsOverlayControls();
|
||||
|
||||
void Initialize(CefRefPtr<CefWindow> window,
|
||||
CefRefPtr<CefMenuButton> menu_button,
|
||||
CefRefPtr<CefView> location_bar,
|
||||
bool is_chrome_toolbar);
|
||||
void Destroy();
|
||||
|
||||
// Update window control button state and location bar bounds.
|
||||
void UpdateControls();
|
||||
|
||||
// Exclude all regions obscured by overlays.
|
||||
void UpdateDraggableRegions(std::vector<CefDraggableRegion>& window_regions);
|
||||
|
||||
private:
|
||||
// CefButtonDelegate methods:
|
||||
void OnButtonPressed(CefRefPtr<CefButton> button) override;
|
||||
|
||||
CefRefPtr<CefLabelButton> CreateButton(Command command);
|
||||
|
||||
void MaybeUpdateMaximizeButton();
|
||||
|
||||
CefRefPtr<CefWindow> window_;
|
||||
bool window_maximized_;
|
||||
|
||||
// Window control buttons.
|
||||
CefRefPtr<CefPanel> panel_;
|
||||
CefRefPtr<CefOverlayController> panel_controller_;
|
||||
|
||||
// Location bar.
|
||||
CefRefPtr<CefView> location_bar_;
|
||||
bool is_chrome_toolbar_;
|
||||
CefRefPtr<CefOverlayController> location_controller_;
|
||||
|
||||
// Menu button.
|
||||
CefRefPtr<CefOverlayController> menu_controller_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ViewsOverlayControls);
|
||||
DISALLOW_COPY_AND_ASSIGN(ViewsOverlayControls);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_CONTROLS_H_
|
@@ -49,6 +49,13 @@ bool IsSet() {
|
||||
return g_background_color != 0;
|
||||
}
|
||||
|
||||
void ApplyBackgroundTo(CefRefPtr<CefView> view) {
|
||||
if (!IsSet())
|
||||
return;
|
||||
|
||||
view->SetBackgroundColor(g_background_color);
|
||||
}
|
||||
|
||||
void ApplyTo(CefRefPtr<CefPanel> panel) {
|
||||
if (!IsSet())
|
||||
return;
|
||||
|
@@ -19,6 +19,7 @@ namespace views_style {
|
||||
bool IsSet();
|
||||
|
||||
// Apply style to views objects.
|
||||
void ApplyBackgroundTo(CefRefPtr<CefView> view);
|
||||
void ApplyTo(CefRefPtr<CefPanel> panel);
|
||||
void ApplyTo(CefRefPtr<CefLabelButton> label_button);
|
||||
void ApplyTo(CefRefPtr<CefTextfield> textfield);
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/base/cef_callback.h"
|
||||
#include "include/cef_app.h"
|
||||
#include "include/cef_i18n_util.h"
|
||||
#include "include/views/cef_box_layout.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
@@ -190,12 +191,12 @@ void ViewsWindow::Close(bool force) {
|
||||
|
||||
void ViewsWindow::SetAddress(const std::string& url) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!window_ || !with_controls_)
|
||||
if (!window_)
|
||||
return;
|
||||
|
||||
CefRefPtr<CefView> view = window_->GetViewForID(ID_URL_TEXTFIELD);
|
||||
if (view && view->AsTextfield())
|
||||
view->AsTextfield()->SetText(url);
|
||||
// |location_bar_| may instead be a Chrome toolbar.
|
||||
if (location_bar_ && location_bar_->AsTextfield())
|
||||
location_bar_->AsTextfield()->SetText(url);
|
||||
}
|
||||
|
||||
void ViewsWindow::SetTitle(const std::string& title) {
|
||||
@@ -236,14 +237,18 @@ void ViewsWindow::SetLoadingState(bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (!window_ || !with_controls_ || chrome_toolbar_type_ == CEF_CTT_NORMAL)
|
||||
if (!window_ || chrome_toolbar_type_ == CEF_CTT_NORMAL)
|
||||
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);
|
||||
if (with_controls_) {
|
||||
EnableView(ID_BACK_BUTTON, canGoBack);
|
||||
EnableView(ID_FORWARD_BUTTON, canGoForward);
|
||||
EnableView(ID_RELOAD_BUTTON, !isLoading);
|
||||
EnableView(ID_STOP_BUTTON, isLoading);
|
||||
}
|
||||
if (location_bar_) {
|
||||
EnableView(ID_URL_TEXTFIELD, true);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::SetDraggableRegions(
|
||||
@@ -266,20 +271,25 @@ void ViewsWindow::SetDraggableRegions(
|
||||
window_regions.push_back(region);
|
||||
}
|
||||
|
||||
if (overlay_controls_) {
|
||||
// Exclude all regions obscured by overlays.
|
||||
overlay_controls_->UpdateDraggableRegions(window_regions);
|
||||
}
|
||||
|
||||
window_->SetDraggableRegions(window_regions);
|
||||
}
|
||||
|
||||
void ViewsWindow::TakeFocus(bool next) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!window_ || !with_controls_)
|
||||
if (!window_)
|
||||
return;
|
||||
|
||||
if (chrome_toolbar_type_ == CEF_CTT_NORMAL) {
|
||||
top_toolbar_->RequestFocus();
|
||||
} else {
|
||||
// Give focus to the URL textfield.
|
||||
location_->RequestFocus();
|
||||
} else if (location_bar_) {
|
||||
// Give focus to the location bar.
|
||||
location_bar_->RequestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,18 +437,30 @@ void ViewsWindow::OnMenuButtonPressed(
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(with_controls_);
|
||||
DCHECK(with_controls_ || with_overlay_controls_);
|
||||
DCHECK_EQ(ID_MENU_BUTTON, id);
|
||||
|
||||
menu_button->ShowMenu(button_menu_model_, screen_point,
|
||||
CEF_MENU_ANCHOR_TOPRIGHT);
|
||||
auto point = screen_point;
|
||||
if (with_overlay_controls_) {
|
||||
// Align the menu correctly under the button.
|
||||
const int button_width = menu_button->GetSize().width;
|
||||
if (CefIsRTL()) {
|
||||
point.x += button_width - 4;
|
||||
} else {
|
||||
point.x -= button_width - 4;
|
||||
}
|
||||
}
|
||||
|
||||
menu_button->ShowMenu(button_menu_model_, point,
|
||||
with_overlay_controls_ ? CEF_MENU_ANCHOR_TOPLEFT
|
||||
: 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_);
|
||||
DCHECK(with_controls_ || with_overlay_controls_);
|
||||
|
||||
if (command_id == ID_QUIT) {
|
||||
delegate_->OnExit();
|
||||
@@ -452,7 +474,6 @@ void ViewsWindow::ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
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.
|
||||
@@ -460,12 +481,9 @@ bool ViewsWindow::OnKeyEvent(CefRefPtr<CefTextfield> textfield,
|
||||
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);
|
||||
}
|
||||
const CefString& url = textfield->GetText();
|
||||
if (!url.empty())
|
||||
browser->GetMainFrame()->LoadURL(url);
|
||||
}
|
||||
|
||||
// We handled the event.
|
||||
@@ -500,9 +518,14 @@ void ViewsWindow::OnWindowCreated(CefRefPtr<CefWindow> window) {
|
||||
// Set the background color for regions that are not obscured by other Views.
|
||||
views_style::ApplyTo(window_.get());
|
||||
|
||||
if (with_controls_ || with_overlay_controls_) {
|
||||
// Create the MenuModel that will be displayed via the menu button.
|
||||
CreateMenuModel();
|
||||
}
|
||||
|
||||
if (with_controls_) {
|
||||
// Add the BrowserView and other controls to the Window.
|
||||
AddControls();
|
||||
AddBrowserView();
|
||||
|
||||
// Add keyboard accelerators to the Window.
|
||||
AddAccelerators();
|
||||
@@ -535,6 +558,7 @@ void ViewsWindow::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
|
||||
top_menu_bar_ = nullptr;
|
||||
}
|
||||
extensions_panel_ = nullptr;
|
||||
menu_button_ = nullptr;
|
||||
window_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -681,117 +705,41 @@ void ViewsWindow::OnBlur(CefRefPtr<CefView> view) {
|
||||
}
|
||||
|
||||
void ViewsWindow::OnWindowChanged(CefRefPtr<CefView> view, bool added) {
|
||||
if (!with_controls_ || !added)
|
||||
return;
|
||||
|
||||
const int view_id = view->GetID();
|
||||
if (view_id != ID_BROWSER_VIEW)
|
||||
return;
|
||||
|
||||
// Build the remainder of the UI now that the BrowserView has been added to
|
||||
// the CefWindow. This is a requirement to use Chrome toolbars.
|
||||
|
||||
CefRefPtr<CefPanel> top_menu_panel;
|
||||
if (top_menu_bar_)
|
||||
top_menu_panel = top_menu_bar_->GetMenuPanel();
|
||||
|
||||
LabelButtons browse_buttons;
|
||||
CefRefPtr<CefMenuButton> menu_button;
|
||||
|
||||
if (chrome_toolbar_type_ == CEF_CTT_NORMAL) {
|
||||
// Chrome will provide a normal toolbar with location, menu, etc.
|
||||
top_toolbar_ = browser_view_->GetChromeToolbar();
|
||||
DCHECK(top_toolbar_);
|
||||
}
|
||||
|
||||
if (!top_toolbar_) {
|
||||
// Create the 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));
|
||||
|
||||
if (chrome_toolbar_type_ == CEF_CTT_LOCATION) {
|
||||
// Chrome will provide a minimal location bar.
|
||||
location_ = browser_view_->GetChromeToolbar();
|
||||
DCHECK(location_);
|
||||
}
|
||||
if (!location_) {
|
||||
// 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);
|
||||
location_ = url_textfield;
|
||||
if (added) {
|
||||
if (with_controls_) {
|
||||
AddControls();
|
||||
}
|
||||
|
||||
// Create the menu button.
|
||||
menu_button = CefMenuButton::CreateMenuButton(this, CefString());
|
||||
menu_button->SetID(ID_MENU_BUTTON);
|
||||
menu_button->SetImage(
|
||||
CEF_BUTTON_STATE_NORMAL,
|
||||
delegate_->GetImageCache()->GetCachedImage("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(nullptr);
|
||||
|
||||
// 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(location_);
|
||||
|
||||
UpdateExtensionControls();
|
||||
DCHECK(extensions_panel_);
|
||||
top_panel->AddChildView(extensions_panel_);
|
||||
|
||||
top_panel->AddChildView(menu_button);
|
||||
views_style::ApplyTo(top_panel);
|
||||
|
||||
// Allow |location| to grow and fill any remaining space.
|
||||
top_panel_layout->SetFlexForView(location_, 1);
|
||||
|
||||
top_toolbar_ = top_panel;
|
||||
if (with_overlay_controls_) {
|
||||
overlay_controls_ = new ViewsOverlayControls();
|
||||
overlay_controls_->Initialize(window_, CreateMenuButton(),
|
||||
CreateLocationBar(),
|
||||
chrome_toolbar_type_ != CEF_CTT_NONE);
|
||||
}
|
||||
} else {
|
||||
if (overlay_controls_) {
|
||||
// Overlay controls may include the Chrome toolbar, in which case they
|
||||
// need to be removed before the BrowserView.
|
||||
overlay_controls_->Destroy();
|
||||
overlay_controls_ = nullptr;
|
||||
location_bar_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the top panel and browser view to |window|.
|
||||
int top_index = 0;
|
||||
if (top_menu_panel)
|
||||
window_->AddChildViewAt(top_menu_panel, top_index++);
|
||||
window_->AddChildViewAt(top_toolbar_, top_index);
|
||||
void ViewsWindow::OnLayoutChanged(CefRefPtr<CefView> view,
|
||||
const CefRect& new_bounds) {
|
||||
const int view_id = view->GetID();
|
||||
if (view_id != ID_BROWSER_VIEW)
|
||||
return;
|
||||
|
||||
// Lay out |window| so we can get the default button sizes.
|
||||
window_->Layout();
|
||||
|
||||
int min_width = 200;
|
||||
if (!browse_buttons.empty()) {
|
||||
// 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.
|
||||
min_width = browse_buttons[0]->GetBounds().width * 4 +
|
||||
menu_button->GetBounds().width + 100;
|
||||
if (overlay_controls_) {
|
||||
overlay_controls_->UpdateControls();
|
||||
}
|
||||
|
||||
// Minimum window height is the hight of the top toolbar plus some extra.
|
||||
int min_height = top_toolbar_->GetBounds().height + 100;
|
||||
if (top_menu_panel)
|
||||
min_height += top_menu_panel->GetBounds().height;
|
||||
|
||||
minimum_window_size_ = CefSize(min_width, min_height);
|
||||
}
|
||||
|
||||
void ViewsWindow::MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
@@ -812,8 +760,16 @@ ViewsWindow::ViewsWindow(Delegate* delegate,
|
||||
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
CefCommandLine::GetGlobalCommandLine();
|
||||
frameless_ = command_line->HasSwitch(switches::kHideFrame) ||
|
||||
delegate_->WithExtension();
|
||||
|
||||
const bool hide_frame = command_line->HasSwitch(switches::kHideFrame);
|
||||
const bool hide_overlays = command_line->HasSwitch(switches::kHideOverlays);
|
||||
|
||||
// Without a window frame.
|
||||
frameless_ = hide_frame || delegate_->WithExtension();
|
||||
|
||||
// With an overlay that mimics window controls.
|
||||
with_overlay_controls_ =
|
||||
hide_frame && !hide_overlays && !delegate_->WithControls();
|
||||
|
||||
if (MainContext::Get()->UseChromeRuntime()) {
|
||||
const std::string& toolbar_type =
|
||||
@@ -823,7 +779,8 @@ ViewsWindow::ViewsWindow(Delegate* delegate,
|
||||
} else if (toolbar_type == "location") {
|
||||
chrome_toolbar_type_ = CEF_CTT_LOCATION;
|
||||
} else {
|
||||
chrome_toolbar_type_ = CEF_CTT_NORMAL;
|
||||
chrome_toolbar_type_ =
|
||||
with_overlay_controls_ ? CEF_CTT_LOCATION : CEF_CTT_NORMAL;
|
||||
}
|
||||
} else {
|
||||
chrome_toolbar_type_ = CEF_CTT_NONE;
|
||||
@@ -869,16 +826,49 @@ CefRefPtr<CefLabelButton> ViewsWindow::CreateBrowseButton(
|
||||
CefRefPtr<CefLabelButton> button =
|
||||
CefLabelButton::CreateLabelButton(this, label);
|
||||
button->SetID(id);
|
||||
views_style::ApplyTo(button.get());
|
||||
button->SetInkDropEnabled(true);
|
||||
button->SetEnabled(false); // Disabled by default.
|
||||
button->SetFocusable(false); // Don't give focus to the button.
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
void ViewsWindow::AddControls() {
|
||||
// Create the MenuModel that will be displayed via the menu button.
|
||||
CreateMenuModel();
|
||||
CefRefPtr<CefMenuButton> ViewsWindow::CreateMenuButton() {
|
||||
// Create the menu button.
|
||||
DCHECK(!menu_button_);
|
||||
menu_button_ = CefMenuButton::CreateMenuButton(this, CefString());
|
||||
menu_button_->SetID(ID_MENU_BUTTON);
|
||||
menu_button_->SetImage(
|
||||
CEF_BUTTON_STATE_NORMAL,
|
||||
delegate_->GetImageCache()->GetCachedImage("menu_icon"));
|
||||
views_style::ApplyTo(menu_button_.get());
|
||||
menu_button_->SetInkDropEnabled(true);
|
||||
// Override the default minimum size.
|
||||
menu_button_->SetMinimumSize(CefSize(0, 0));
|
||||
return menu_button_;
|
||||
}
|
||||
|
||||
CefRefPtr<CefView> ViewsWindow::CreateLocationBar() {
|
||||
DCHECK(!location_bar_);
|
||||
if (chrome_toolbar_type_ == CEF_CTT_LOCATION) {
|
||||
// Chrome will provide a minimal location bar.
|
||||
location_bar_ = browser_view_->GetChromeToolbar();
|
||||
DCHECK(location_bar_);
|
||||
views_style::ApplyBackgroundTo(location_bar_);
|
||||
}
|
||||
if (!location_bar_) {
|
||||
// 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);
|
||||
location_bar_ = url_textfield;
|
||||
}
|
||||
return location_bar_;
|
||||
}
|
||||
|
||||
void ViewsWindow::AddBrowserView() {
|
||||
// Use a vertical box layout for |window|.
|
||||
CefBoxLayoutSettings window_layout_settings;
|
||||
window_layout_settings.horizontal = false;
|
||||
@@ -896,6 +886,89 @@ void ViewsWindow::AddControls() {
|
||||
// only available after the BrowserView is added.
|
||||
}
|
||||
|
||||
void ViewsWindow::AddControls() {
|
||||
// Build the remainder of the UI now that the BrowserView has been added to
|
||||
// the CefWindow. This is a requirement to use Chrome toolbars.
|
||||
|
||||
CefRefPtr<CefPanel> top_menu_panel;
|
||||
if (top_menu_bar_)
|
||||
top_menu_panel = top_menu_bar_->GetMenuPanel();
|
||||
|
||||
LabelButtons browse_buttons;
|
||||
|
||||
if (chrome_toolbar_type_ == CEF_CTT_NORMAL) {
|
||||
// Chrome will provide a normal toolbar with location, menu, etc.
|
||||
top_toolbar_ = browser_view_->GetChromeToolbar();
|
||||
DCHECK(top_toolbar_);
|
||||
}
|
||||
|
||||
if (!top_toolbar_) {
|
||||
// Create the 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));
|
||||
|
||||
CreateLocationBar();
|
||||
CreateMenuButton();
|
||||
|
||||
// Create the top panel.
|
||||
CefRefPtr<CefPanel> top_panel = CefPanel::CreatePanel(nullptr);
|
||||
|
||||
// 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(location_bar_);
|
||||
|
||||
UpdateExtensionControls();
|
||||
DCHECK(extensions_panel_);
|
||||
top_panel->AddChildView(extensions_panel_);
|
||||
|
||||
top_panel->AddChildView(menu_button_);
|
||||
views_style::ApplyTo(top_panel);
|
||||
|
||||
// Allow |location| to grow and fill any remaining space.
|
||||
top_panel_layout->SetFlexForView(location_bar_, 1);
|
||||
|
||||
top_toolbar_ = top_panel;
|
||||
}
|
||||
|
||||
// Add the top panel and browser view to |window|.
|
||||
int top_index = 0;
|
||||
if (top_menu_panel)
|
||||
window_->AddChildViewAt(top_menu_panel, top_index++);
|
||||
window_->AddChildViewAt(top_toolbar_, top_index);
|
||||
|
||||
// Lay out |window| so we can get the default button sizes.
|
||||
window_->Layout();
|
||||
|
||||
int min_width = 200;
|
||||
if (!browse_buttons.empty()) {
|
||||
// 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.
|
||||
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_toolbar_->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);
|
||||
@@ -926,7 +999,10 @@ void ViewsWindow::SetMenuFocusable(bool focusable) {
|
||||
void ViewsWindow::EnableView(int id, bool enable) {
|
||||
if (!window_)
|
||||
return;
|
||||
CefRefPtr<CefView> view = window_->GetViewForID(id);
|
||||
// Special handling for |location_bar_| which may be an overlay (e.g. not a
|
||||
// child of this view).
|
||||
CefRefPtr<CefView> view =
|
||||
id == ID_URL_TEXTFIELD ? location_bar_ : window_->GetViewForID(id);
|
||||
if (view)
|
||||
view->SetEnabled(enable);
|
||||
}
|
||||
|
@@ -18,12 +18,14 @@
|
||||
#include "include/views/cef_label_button.h"
|
||||
#include "include/views/cef_menu_button.h"
|
||||
#include "include/views/cef_menu_button_delegate.h"
|
||||
#include "include/views/cef_overlay_controller.h"
|
||||
#include "include/views/cef_textfield.h"
|
||||
#include "include/views/cef_textfield_delegate.h"
|
||||
#include "include/views/cef_window.h"
|
||||
#include "include/views/cef_window_delegate.h"
|
||||
#include "tests/cefclient/browser/image_cache.h"
|
||||
#include "tests/cefclient/browser/views_menu_bar.h"
|
||||
#include "tests/cefclient/browser/views_overlay_controls.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
@@ -167,6 +169,8 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
void OnFocus(CefRefPtr<CefView> view) override;
|
||||
void OnBlur(CefRefPtr<CefView> view) override;
|
||||
void OnWindowChanged(CefRefPtr<CefView> view, bool added) override;
|
||||
void OnLayoutChanged(CefRefPtr<CefView> view,
|
||||
const CefRect& new_bounds) override;
|
||||
|
||||
// ViewsMenuBar::Delegate methods:
|
||||
void MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
@@ -185,8 +189,13 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
void CreateMenuModel();
|
||||
CefRefPtr<CefLabelButton> CreateBrowseButton(const std::string& label,
|
||||
int id);
|
||||
CefRefPtr<CefMenuButton> CreateMenuButton();
|
||||
CefRefPtr<CefView> CreateLocationBar();
|
||||
|
||||
// Add controls to the Window.
|
||||
// Add the BrowserView to the Window.
|
||||
void AddBrowserView();
|
||||
|
||||
// Add other controls to the Window.
|
||||
void AddControls();
|
||||
|
||||
// Add keyboard accelerators to the Window.
|
||||
@@ -214,18 +223,22 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
CefRefPtr<CefBrowserView> browser_view_;
|
||||
bool frameless_;
|
||||
bool with_controls_;
|
||||
bool with_overlay_controls_;
|
||||
ChromeToolbarType chrome_toolbar_type_;
|
||||
CefRefPtr<CefWindow> window_;
|
||||
|
||||
CefRefPtr<CefMenuModel> button_menu_model_;
|
||||
CefRefPtr<ViewsMenuBar> top_menu_bar_;
|
||||
CefRefPtr<CefView> top_toolbar_;
|
||||
CefRefPtr<CefView> location_;
|
||||
CefRefPtr<CefMenuButton> menu_button_;
|
||||
CefRefPtr<CefView> location_bar_;
|
||||
bool menu_has_focus_;
|
||||
int last_focused_view_;
|
||||
|
||||
CefSize minimum_window_size_;
|
||||
|
||||
CefRefPtr<ViewsOverlayControls> overlay_controls_;
|
||||
|
||||
// Structure representing an extension.
|
||||
struct ExtensionInfo {
|
||||
ExtensionInfo(CefRefPtr<CefExtension> extension, CefRefPtr<CefImage> image)
|
||||
|
@@ -2,6 +2,24 @@
|
||||
<head>
|
||||
<title>Draggable Regions Test</title>
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.draggable-title {
|
||||
-webkit-app-region: drag;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
background-color: white;
|
||||
opacity: .5;
|
||||
}
|
||||
.content {
|
||||
margin-top: 34px;
|
||||
background-color: white;
|
||||
}
|
||||
.draggable {
|
||||
-webkit-app-region: drag;
|
||||
position: absolute;
|
||||
@@ -23,10 +41,13 @@
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<body>
|
||||
<div class="draggable-title"></div>
|
||||
<div class="content">
|
||||
Draggable regions can be defined using the -webkit-app-region CSS property.
|
||||
<br/>In the below example the red region is draggable and the blue sub-region is non-draggable.
|
||||
<br/>Windows can be resized by default and closed using JavaScript <a href="#" onClick="window.close(); return false;">window.close()</a>.
|
||||
</div>
|
||||
<div class="draggable">
|
||||
<div class="nondraggable"></div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user