• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2021 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include "tests/cefclient/browser/views_overlay_controls.h"
6 
7 #include <algorithm>
8 #include <string>
9 
10 #include "include/views/cef_box_layout.h"
11 #include "include/views/cef_window.h"
12 #include "tests/cefclient/browser/views_style.h"
13 
14 namespace client {
15 
16 namespace {
17 
18 constexpr int kInsets = 4;
19 constexpr int kLocationBarPadding = 100;
20 
21 // White with 80% opacity.
22 constexpr auto kBackgroundColor = CefColorSetARGB(255 * .80, 255, 255, 255);
23 
GetLabel(ViewsOverlayControls::Command command,bool maximized)24 std::string GetLabel(ViewsOverlayControls::Command command, bool maximized) {
25   switch (command) {
26     case ViewsOverlayControls::Command::kMinimize:
27       return "-";
28     case ViewsOverlayControls::Command::kMaximize:
29       return maximized ? "O" : "o";
30     case ViewsOverlayControls::Command::kClose:
31       return "X";
32   }
33   NOTREACHED();
34   return std::string();
35 }
36 
37 }  // namespace
38 
39 ViewsOverlayControls::ViewsOverlayControls() = default;
40 
Initialize(CefRefPtr<CefWindow> window,CefRefPtr<CefMenuButton> menu_button,CefRefPtr<CefView> location_bar,bool is_chrome_toolbar)41 void ViewsOverlayControls::Initialize(CefRefPtr<CefWindow> window,
42                                       CefRefPtr<CefMenuButton> menu_button,
43                                       CefRefPtr<CefView> location_bar,
44                                       bool is_chrome_toolbar) {
45   DCHECK(!window_);
46   DCHECK(menu_button);
47   DCHECK(location_bar);
48 
49   window_ = window;
50   window_maximized_ = window_->IsMaximized();
51 
52   // Window control buttons. These controls are currently text which means that
53   // we can't use a transparent background because subpixel text rendering will
54   // break. See comments on the related DCHECK in Label::PaintText.
55   panel_ = CefPanel::CreatePanel(nullptr);
56   views_style::ApplyTo(panel_);
57 
58   // Use a horizontal box layout.
59   CefBoxLayoutSettings panel_layout_settings;
60   panel_layout_settings.horizontal = true;
61   panel_->SetToBoxLayout(panel_layout_settings);
62 
63   panel_->AddChildView(CreateButton(ViewsOverlayControls::Command::kMinimize));
64   panel_->AddChildView(CreateButton(ViewsOverlayControls::Command::kMaximize));
65   panel_->AddChildView(CreateButton(ViewsOverlayControls::Command::kClose));
66 
67   panel_controller_ =
68       window->AddOverlayView(panel_, CEF_DOCKING_MODE_TOP_RIGHT);
69   panel_controller_->SetVisible(true);
70 
71   // Menu button.
72   menu_button->SetBackgroundColor(kBackgroundColor);
73   menu_controller_ =
74       window_->AddOverlayView(menu_button, CEF_DOCKING_MODE_TOP_LEFT);
75   menu_controller_->SetInsets(CefInsets(kInsets, kInsets, 0, 0));
76   menu_controller_->SetVisible(true);
77 
78   // Location bar. Will be made visible in UpdateControls().
79   location_bar_ = location_bar;
80   is_chrome_toolbar_ = is_chrome_toolbar;
81   // Use a 100% transparent background for the Chrome toolbar.
82   location_bar_->SetBackgroundColor(is_chrome_toolbar_ ? 0 : kBackgroundColor);
83   location_controller_ =
84       window_->AddOverlayView(location_bar_, CEF_DOCKING_MODE_CUSTOM);
85 }
86 
Destroy()87 void ViewsOverlayControls::Destroy() {
88   window_ = nullptr;
89   panel_ = nullptr;
90   panel_controller_->Destroy();
91   panel_controller_ = nullptr;
92   menu_controller_->Destroy();
93   menu_controller_ = nullptr;
94   location_bar_ = nullptr;
95   location_controller_->Destroy();
96   location_controller_ = nullptr;
97 }
98 
UpdateControls()99 void ViewsOverlayControls::UpdateControls() {
100   // Update location bar size, position and visibility.
101   auto bounds = window_->GetBounds();
102   bounds.x = kLocationBarPadding;
103   bounds.width -= kLocationBarPadding * 2;
104   bounds.y = kInsets;
105   if (is_chrome_toolbar_) {
106     // Fit the standard Chrome toolbar.
107     const auto preferred_size = location_bar_->GetPreferredSize();
108     bounds.height =
109         std::max(menu_controller_->GetSize().height, preferred_size.height);
110   } else {
111     bounds.height = menu_controller_->GetSize().height;
112   }
113   if (bounds.width < kLocationBarPadding * 2) {
114     // Not enough space.
115     location_controller_->SetVisible(false);
116   } else {
117     location_bar_->SetSize(CefSize(bounds.width, bounds.height));
118     location_controller_->SetBounds(bounds);
119     location_controller_->SetVisible(true);
120   }
121 
122   MaybeUpdateMaximizeButton();
123 }
124 
UpdateDraggableRegions(std::vector<CefDraggableRegion> & window_regions)125 void ViewsOverlayControls::UpdateDraggableRegions(
126     std::vector<CefDraggableRegion>& window_regions) {
127   if (panel_controller_ && panel_controller_->IsVisible()) {
128     window_regions.push_back(CefDraggableRegion(panel_controller_->GetBounds(),
129                                                 /*draggable=*/false));
130   }
131 
132   if (menu_controller_ && menu_controller_->IsVisible()) {
133     window_regions.push_back(
134         CefDraggableRegion(menu_controller_->GetBounds(), /*draggable=*/false));
135   }
136 
137   if (location_controller_ && location_controller_->IsVisible()) {
138     window_regions.push_back(CefDraggableRegion(
139         location_controller_->GetBounds(), /*draggable=*/false));
140   }
141 }
142 
OnButtonPressed(CefRefPtr<CefButton> button)143 void ViewsOverlayControls::OnButtonPressed(CefRefPtr<CefButton> button) {
144   auto command = static_cast<Command>(button->GetID());
145   switch (command) {
146     case ViewsOverlayControls::Command::kMinimize:
147       window_->Minimize();
148       break;
149     case ViewsOverlayControls::Command::kMaximize:
150       if (window_->IsMaximized())
151         window_->Restore();
152       else
153         window_->Maximize();
154       break;
155     case ViewsOverlayControls::Command::kClose:
156       window_->Close();
157       return;
158   }
159 
160   // Explicitly reset button state because the button may have moved and it
161   // won't receive the corresponding mouse move events.
162   button->SetState(CEF_BUTTON_STATE_NORMAL);
163   button->SetInkDropEnabled(false);
164   button->SetInkDropEnabled(true);
165 
166   if (command == Command::kMaximize)
167     MaybeUpdateMaximizeButton();
168 }
169 
CreateButton(Command command)170 CefRefPtr<CefLabelButton> ViewsOverlayControls::CreateButton(Command command) {
171   CefRefPtr<CefLabelButton> button = CefLabelButton::CreateLabelButton(
172       this, GetLabel(command, window_maximized_));
173   button->SetID(static_cast<int>(command));
174   views_style::ApplyTo(button);
175   button->SetInkDropEnabled(true);
176   button->SetFocusable(false);  // Don't give focus to the button.
177   return button;
178 }
179 
MaybeUpdateMaximizeButton()180 void ViewsOverlayControls::MaybeUpdateMaximizeButton() {
181   if (window_->IsMaximized() == window_maximized_)
182     return;
183   window_maximized_ = !window_maximized_;
184 
185   auto max_button = panel_->GetChildViewAt(1);
186   auto command = static_cast<Command>(max_button->GetID());
187   DCHECK(command == Command::kMaximize);
188   max_button->AsButton()->AsLabelButton()->SetText(
189       GetLabel(command, window_maximized_));
190 
191   // Adjust overlay size and placement due to layout changing.
192   panel_controller_->SizeToPreferredSize();
193 }
194 
195 }  // namespace client
196