Virtual Desks 1: Initial scaffolding
This CL adds the very basic scaffolding which will be
used in subsequent CLs to build the virtual desks feature.
Added in this CL:
- The VirtualDesks base::Feature.
- Bar that will later contain desks' thumbnails.
- The "New desk" button, which currently does nothing.
- Moves gesture taps and mouse release overview handling from
a pre-target handler in WallpaperView to the ShieldView.
Demo: https://bugs.chromium.org/p/chromium/issues/detail?id=866622#c2
BUG=866622
Change-Id: Ie09e7a5b11aaae82fcaf592c009d54ec7245fe10
Reviewed-on: https://chromium-review.googlesource.com/c/1461821
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: Sammie Quon <sammiequon@chromium.org>
Commit-Queue: Ahmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#631513}
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 522fef8..09b425c 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1024,6 +1024,12 @@
"wm/default_state.h",
"wm/default_window_resizer.cc",
"wm/default_window_resizer.h",
+ "wm/desks/desks_bar_view.cc",
+ "wm/desks/desks_bar_view.h",
+ "wm/desks/desks_controller.cc",
+ "wm/desks/desks_controller.h",
+ "wm/desks/new_desk_button.cc",
+ "wm/desks/new_desk_button.h",
"wm/drag_details.cc",
"wm/drag_details.h",
"wm/drag_window_controller.cc",
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 12c3e4d..605f2e9 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -689,6 +689,11 @@
No recent items
</message>
+ <!-- Virtual Desks -->
+ <message name="IDS_ASH_DESKS_NEW_DESK_BUTTON" desc="The label of the new virtual desk (a.k.a. workspaces) button.">
+ New Desk
+ </message>
+
<!-- Status tray charging strings. -->
<message name="IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_TITLE" desc="The title of a notification indicating that a low-current USB charger has been connected.">
Low-power charger connected
diff --git a/ash/ash_strings_grd/IDS_ASH_DESKS_NEW_DESK_BUTTON.png.sha1 b/ash/ash_strings_grd/IDS_ASH_DESKS_NEW_DESK_BUTTON.png.sha1
new file mode 100644
index 0000000..030473f
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_DESKS_NEW_DESK_BUTTON.png.sha1
@@ -0,0 +1 @@
+8254d07d8a4676a52a79a98e0287ea5f80843262
\ No newline at end of file
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc
index 809caaa..168b592 100644
--- a/ash/public/cpp/ash_features.cc
+++ b/ash/public/cpp/ash_features.cc
@@ -57,6 +57,9 @@
const base::Feature kViewsLogin{"ViewsLogin", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kVirtualDesks{"VirtualDesks",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kUseBluetoothSystemInAsh{"UseBluetoothSystemInAsh",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -98,6 +101,10 @@
return use_trilinear_filtering;
}
+bool IsVirtualDesksEnabled() {
+ return base::FeatureList::IsEnabled(kVirtualDesks);
+}
+
bool IsViewsLoginEnabled() {
// Always show webui login if --show-webui-login is present, which is passed
// by session manager for automatic recovery. Otherwise, only show views
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h
index fbedd75..ef3b438 100644
--- a/ash/public/cpp/ash_features.h
+++ b/ash/public/cpp/ash_features.h
@@ -71,6 +71,9 @@
// Enables views login.
ASH_PUBLIC_EXPORT extern const base::Feature kViewsLogin;
+// Enables the Virtual Desks feature.
+ASH_PUBLIC_EXPORT extern const base::Feature kVirtualDesks;
+
// Enables using the BluetoothSystem Mojo interface for Bluetooth operations.
ASH_PUBLIC_EXPORT extern const base::Feature kUseBluetoothSystemInAsh;
@@ -97,6 +100,8 @@
ASH_PUBLIC_EXPORT bool IsViewsLoginEnabled();
+ASH_PUBLIC_EXPORT bool IsVirtualDesksEnabled();
+
ASH_PUBLIC_EXPORT bool IsSupervisedUserDeprecationNoticeEnabled();
} // namespace features
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn
index c81cda8..e55eb8d2 100644
--- a/ash/resources/vector_icons/BUILD.gn
+++ b/ash/resources/vector_icons/BUILD.gn
@@ -54,6 +54,7 @@
"network_ethernet.icon",
"network_mobile_not_connected_x.icon",
"network_vpn.icon",
+ "new_desk_button.icon",
"notification_accessibility.icon",
"notification_accessibility_braille.icon",
"notification_battery_critical.icon",
diff --git a/ash/resources/vector_icons/new_desk_button.icon b/ash/resources/vector_icons/new_desk_button.icon
new file mode 100644
index 0000000..bc219a43
--- /dev/null
+++ b/ash/resources/vector_icons/new_desk_button.icon
@@ -0,0 +1,18 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 7, 5,
+R_H_LINE_TO, 5,
+R_V_LINE_TO, 2,
+H_LINE_TO, 7,
+R_V_LINE_TO, 5,
+H_LINE_TO, 5,
+V_LINE_TO, 7,
+H_LINE_TO, 0,
+V_LINE_TO, 5,
+R_H_LINE_TO, 5,
+V_LINE_TO, 0,
+R_H_LINE_TO, 2,
+CLOSE
diff --git a/ash/shell.cc b/ash/shell.cc
index 693a8736..7c61054 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -131,6 +131,7 @@
#include "ash/wm/ash_focus_rules.h"
#include "ash/wm/container_finder.h"
#include "ash/wm/cursor_manager_chromeos.h"
+#include "ash/wm/desks/desks_controller.h"
#include "ash/wm/event_client_impl.h"
#include "ash/wm/immersive_context_ash.h"
#include "ash/wm/lock_state_controller.h"
@@ -790,6 +791,8 @@
// |overview_controller_|.
split_view_controller_.reset();
+ desks_controller_.reset();
+
// Stop dispatching events (e.g. synthesized mouse exits from window close).
// https://crbug.com/874156
for (RootWindowController* rwc : GetAllRootWindowControllers())
@@ -1226,6 +1229,9 @@
split_view_controller_.reset(new SplitViewController());
+ if (features::IsVirtualDesksEnabled())
+ desks_controller_ = std::make_unique<DesksController>();
+
key_accessibility_enabler_ = std::make_unique<KeyAccessibilityEnabler>();
// The compositor thread and main message loop have to be running in
diff --git a/ash/shell.h b/ash/shell.h
index 53ab4a3f..5995f35a 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -109,6 +109,7 @@
class DisplayOutputProtection;
class ContainedShellController;
class CrosDisplayConfig;
+class DesksController;
class DetachableBaseHandler;
class DetachableBaseNotificationController;
class DisplayColorManager;
@@ -370,6 +371,7 @@
return cros_display_config_.get();
}
::wm::CursorManager* cursor_manager() { return cursor_manager_.get(); }
+ DesksController* desks_controller() { return desks_controller_.get(); }
DetachableBaseHandler* detachable_base_handler() {
return detachable_base_handler_.get();
}
@@ -713,6 +715,7 @@
std::unique_ptr<CrosDisplayConfig> cros_display_config_;
service_manager::Connector* const connector_;
std::unique_ptr<ContainedShellController> contained_shell_controller_;
+ std::unique_ptr<DesksController> desks_controller_;
std::unique_ptr<DetachableBaseHandler> detachable_base_handler_;
std::unique_ptr<DetachableBaseNotificationController>
detachable_base_notification_controller_;
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc
index 684b8d2..d40ed09 100644
--- a/ash/wallpaper/wallpaper_view.cc
+++ b/ash/wallpaper/wallpaper_view.cc
@@ -12,8 +12,6 @@
#include "ash/shell.h"
#include "ash/wallpaper/wallpaper_controller.h"
#include "ash/wallpaper/wallpaper_widget_controller.h"
-#include "ash/wm/overview/overview_controller.h"
-#include "ash/wm/overview/overview_utils.h"
#include "ui/aura/window.h"
#include "ui/display/display.h"
#include "ui/display/manager/display_manager.h"
@@ -95,58 +93,18 @@
} // namespace
-// This event handler receives events in the pre-target phase and takes care of
-// the following:
-// - Disabling overview mode on touch release.
-// - Disabling overview mode on mouse release.
-class PreEventDispatchHandler : public ui::EventHandler {
- public:
- PreEventDispatchHandler() = default;
- ~PreEventDispatchHandler() override = default;
-
- private:
- // ui::EventHandler:
- void OnMouseEvent(ui::MouseEvent* event) override {
- if (event->type() == ui::ET_MOUSE_RELEASED)
- HandleClickOrTap(event);
- }
-
- void OnGestureEvent(ui::GestureEvent* event) override {
- if (event->type() == ui::ET_GESTURE_TAP)
- HandleClickOrTap(event);
- }
-
- void HandleClickOrTap(ui::Event* event) {
- CHECK_EQ(ui::EP_PRETARGET, event->phase());
- OverviewController* controller = Shell::Get()->overview_controller();
- if (!controller->IsSelecting())
- return;
- // Events that happen while app list is sliding out during overview should
- // be ignored to prevent overview from disappearing out from under the user.
- if (!IsSlidingOutOverviewFromShelf())
- controller->ToggleOverview();
- event->StopPropagation();
- }
-
- DISALLOW_COPY_AND_ASSIGN(PreEventDispatchHandler);
-};
-
////////////////////////////////////////////////////////////////////////////////
// WallpaperView, public:
-WallpaperView::WallpaperView()
- : pre_dispatch_handler_(new PreEventDispatchHandler()) {
+WallpaperView::WallpaperView() {
set_context_menu_controller(this);
- AddPreTargetHandler(pre_dispatch_handler_.get());
tablet_mode_observer_.Add(Shell::Get()->tablet_mode_controller());
is_tablet_mode_ = Shell::Get()
->tablet_mode_controller()
->IsTabletModeWindowManagerEnabled();
}
-WallpaperView::~WallpaperView() {
- RemovePreTargetHandler(pre_dispatch_handler_.get());
-}
+WallpaperView::~WallpaperView() = default;
void WallpaperView::OnTabletModeStarted() {
is_tablet_mode_ = true;
diff --git a/ash/wallpaper/wallpaper_view.h b/ash/wallpaper/wallpaper_view.h
index 17ee2210..52abdf19 100644
--- a/ash/wallpaper/wallpaper_view.h
+++ b/ash/wallpaper/wallpaper_view.h
@@ -19,8 +19,6 @@
namespace ash {
-class PreEventDispatchHandler;
-
class WallpaperView : public views::View,
public views::ContextMenuController,
TabletModeObserver {
@@ -49,8 +47,6 @@
tablet_mode_observer_{this};
bool is_tablet_mode_ = false;
- std::unique_ptr<PreEventDispatchHandler> pre_dispatch_handler_;
-
DISALLOW_COPY_AND_ASSIGN(WallpaperView);
};
diff --git a/ash/wm/desks/desks_bar_view.cc b/ash/wm/desks/desks_bar_view.cc
new file mode 100644
index 0000000..88ce533
--- /dev/null
+++ b/ash/wm/desks/desks_bar_view.cc
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium 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 "ash/wm/desks/desks_bar_view.h"
+
+#include "ash/wm/desks/desks_controller.h"
+#include "ash/wm/desks/new_desk_button.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/insets.h"
+
+namespace ash {
+
+DesksBarView::DesksBarView() : new_desk_button_(new NewDeskButton(this)) {
+ SetPaintToLayer(ui::LAYER_SOLID_COLOR);
+ layer()->SetFillsBoundsOpaquely(false);
+ layer()->SetColor(SkColorSetARGB(60, 0, 0, 0));
+
+ AddChildView(new_desk_button_);
+ new_desk_button_->SetEnabled(DesksController::Get()->CanCreateDesks());
+}
+
+// static
+int DesksBarView::GetBarHeight() {
+ // TODO(afakhry): Bar expands when we add the second desk.
+ return 48;
+}
+
+const char* DesksBarView::GetClassName() const {
+ return "DesksBarView";
+}
+
+void DesksBarView::Layout() {
+ constexpr int kButtonRightMargin = 36;
+ constexpr int kIconAndTextHorizontalPadding = 16;
+ constexpr int kIconAndTextVerticalPadding = 8;
+
+ gfx::Size new_desk_button_size = new_desk_button_->GetPreferredSize();
+ new_desk_button_size.Enlarge(2 * kIconAndTextHorizontalPadding,
+ 2 * kIconAndTextVerticalPadding);
+
+ const gfx::Rect button_bounds{
+ bounds().right() - new_desk_button_size.width() - kButtonRightMargin,
+ (bounds().height() - new_desk_button_size.height()) / 2,
+ new_desk_button_size.width(), new_desk_button_size.height()};
+ new_desk_button_->SetBoundsRect(button_bounds);
+
+ // TODO(afakhry): Layout thumbnails.
+}
+
+void DesksBarView::ButtonPressed(views::Button* sender,
+ const ui::Event& event) {
+ auto* controller = DesksController::Get();
+ if (sender == new_desk_button_ && controller->CanCreateDesks()) {
+ controller->NewDesk();
+ return;
+ }
+
+ // TODO(afakhry): Handle thumbnail presses.
+}
+
+} // namespace ash
diff --git a/ash/wm/desks/desks_bar_view.h b/ash/wm/desks/desks_bar_view.h
new file mode 100644
index 0000000..77594a37
--- /dev/null
+++ b/ash/wm/desks/desks_bar_view.h
@@ -0,0 +1,39 @@
+// Copyright 2019 The Chromium 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 ASH_WM_DESKS_DESKS_BAR_VIEW_H_
+#define ASH_WM_DESKS_DESKS_BAR_VIEW_H_
+
+#include "base/macros.h"
+#include "ui/views/controls/button/button.h"
+
+namespace ash {
+
+class NewDeskButton;
+
+// A bar that resides at the top portion of the overview mode's ShieldView,
+// which contains the virtual desks thumbnails, as well as the new desk button.
+class DesksBarView : public views::View, public views::ButtonListener {
+ public:
+ DesksBarView();
+ ~DesksBarView() override = default;
+
+ static int GetBarHeight();
+
+ // views::View:
+ const char* GetClassName() const override;
+ void Layout() override;
+
+ // views::ButtonListener:
+ void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+
+ private:
+ NewDeskButton* new_desk_button_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesksBarView);
+};
+
+} // namespace ash
+
+#endif // ASH_WM_DESKS_DESKS_BAR_VIEW_H_
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
new file mode 100644
index 0000000..4be7a05
--- /dev/null
+++ b/ash/wm/desks/desks_controller.cc
@@ -0,0 +1,26 @@
+// Copyright 2019 The Chromium 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 "ash/wm/desks/desks_controller.h"
+
+#include "ash/shell.h"
+#include "base/logging.h"
+
+namespace ash {
+
+// static
+DesksController* DesksController::Get() {
+ return Shell::Get()->desks_controller();
+}
+
+bool DesksController::CanCreateDesks() const {
+ // TODO(afakhry): Maximum of four desks.
+ return true;
+}
+
+void DesksController::NewDesk() {
+ NOTIMPLEMENTED();
+}
+
+} // namespace ash
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h
new file mode 100644
index 0000000..6d69c98
--- /dev/null
+++ b/ash/wm/desks/desks_controller.h
@@ -0,0 +1,34 @@
+// Copyright 2019 The Chromium 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 ASH_WM_DESKS_DESKS_CONTROLLER_H_
+#define ASH_WM_DESKS_DESKS_CONTROLLER_H_
+
+#include "base/macros.h"
+
+namespace ash {
+
+// Defines a controller for creating, destroying and managing virtual desks and
+// their windows.
+class DesksController {
+ public:
+ DesksController() = default;
+ ~DesksController() = default;
+
+ // Convenience method for returning the DesksController instance. The actual
+ // instance is created and owned by Shell.
+ static DesksController* Get();
+
+ // Returns true if we haven't reached the maximum allowed number of desks.
+ bool CanCreateDesks() const;
+
+ void NewDesk();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DesksController);
+};
+
+} // namespace ash
+
+#endif // ASH_WM_DESKS_DESKS_CONTROLLER_H_
diff --git a/ash/wm/desks/new_desk_button.cc b/ash/wm/desks/new_desk_button.cc
new file mode 100644
index 0000000..9c72659
--- /dev/null
+++ b/ash/wm/desks/new_desk_button.cc
@@ -0,0 +1,95 @@
+// Copyright 2019 The Chromium 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 "ash/wm/desks/new_desk_button.h"
+
+#include <utility>
+
+#include "ash/resources/vector_icons/vector_icons.h"
+#include "ash/strings/grit/ash_strings.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/animation/ink_drop_impl.h"
+#include "ui/views/animation/ink_drop_mask.h"
+#include "ui/views/background.h"
+#include "ui/views/controls/button/label_button_border.h"
+#include "ui/views/style/platform_style.h"
+
+namespace ash {
+
+namespace {
+
+constexpr int kCornerRadius = 16;
+
+constexpr int kImageLabelSpacing = 8;
+
+constexpr float kInkDropVisibleOpacity = 0.2f;
+
+constexpr float kInkDropHighlightVisibleOpacity = 0.3f;
+
+constexpr SkColor kHighlightBackgroundColor = SkColorSetARGB(60, 255, 255, 255);
+
+} // namespace
+
+NewDeskButton::NewDeskButton(views::ButtonListener* listener)
+ : LabelButton(listener,
+ l10n_util::GetStringUTF16(IDS_ASH_DESKS_NEW_DESK_BUTTON)) {
+ SetPaintToLayer();
+ layer()->SetFillsBoundsOpaquely(false);
+ SetHorizontalAlignment(gfx::ALIGN_CENTER);
+ SetImage(views::Button::STATE_NORMAL,
+ gfx::CreateVectorIcon(kNewDeskButtonIcon, SK_ColorWHITE));
+ SetImage(views::Button::STATE_DISABLED,
+ gfx::CreateVectorIcon(kNewDeskButtonIcon, SK_ColorGRAY));
+ SetTextColor(views::Button::STATE_NORMAL, SK_ColorWHITE);
+ SetTextColor(views::Button::STATE_HOVERED, SK_ColorWHITE);
+ SetTextColor(views::Button::STATE_PRESSED, SK_ColorWHITE);
+ SetTextColor(views::Button::STATE_DISABLED, SK_ColorGRAY);
+ SetImageLabelSpacing(kImageLabelSpacing);
+ SetInkDropMode(InkDropMode::ON);
+ set_has_ink_drop_action_on_click(true);
+ set_ink_drop_visible_opacity(kInkDropVisibleOpacity);
+ SetFocusPainter(nullptr);
+ SetBackground(
+ CreateBackgroundFromPainter(views::Painter::CreateSolidRoundRectPainter(
+ kHighlightBackgroundColor, kCornerRadius)));
+}
+
+const char* NewDeskButton::GetClassName() const {
+ return "NewDeskButton";
+}
+
+std::unique_ptr<views::InkDrop> NewDeskButton::CreateInkDrop() {
+ auto ink_drop = CreateDefaultFloodFillInkDropImpl();
+ ink_drop->SetShowHighlightOnHover(true);
+ ink_drop->SetShowHighlightOnFocus(!views::PlatformStyle::kPreferFocusRings);
+ return std::move(ink_drop);
+}
+
+std::unique_ptr<views::InkDropHighlight> NewDeskButton::CreateInkDropHighlight()
+ const {
+ auto highlight = LabelButton::CreateInkDropHighlight();
+ highlight->set_visible_opacity(kInkDropHighlightVisibleOpacity);
+ return highlight;
+}
+
+SkColor NewDeskButton::GetInkDropBaseColor() const {
+ return SK_ColorWHITE;
+}
+
+std::unique_ptr<views::InkDropMask> NewDeskButton::CreateInkDropMask() const {
+ return std::make_unique<views::RoundRectInkDropMask>(size(), gfx::Insets(),
+ kCornerRadius);
+}
+
+std::unique_ptr<views::LabelButtonBorder> NewDeskButton::CreateDefaultBorder()
+ const {
+ std::unique_ptr<views::LabelButtonBorder> border =
+ std::make_unique<views::LabelButtonBorder>();
+ return border;
+}
+
+} // namespace ash
diff --git a/ash/wm/desks/new_desk_button.h b/ash/wm/desks/new_desk_button.h
new file mode 100644
index 0000000..696ca40
--- /dev/null
+++ b/ash/wm/desks/new_desk_button.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium 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 ASH_WM_DESKS_NEW_DESK_BUTTON_H_
+#define ASH_WM_DESKS_NEW_DESK_BUTTON_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "ui/views/controls/button/label_button.h"
+
+namespace ash {
+
+// A button view that shows up in the top-right corner of the screen when
+// overview mode is on, which is used to create a new virtual desk.
+class NewDeskButton : public views::LabelButton {
+ public:
+ NewDeskButton(views::ButtonListener* listener);
+ ~NewDeskButton() override = default;
+
+ // LabelButton:
+ const char* GetClassName() const override;
+ std::unique_ptr<views::InkDrop> CreateInkDrop() override;
+ std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
+ const override;
+ SkColor GetInkDropBaseColor() const override;
+ std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override;
+ std::unique_ptr<views::LabelButtonBorder> CreateDefaultBorder()
+ const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NewDeskButton);
+};
+
+} // namespace ash
+
+#endif // ASH_WM_DESKS_NEW_DESK_BUTTON_H_
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 925df668..18bc21e 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -8,6 +8,7 @@
#include <functional>
#include <utility>
+#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/shelf_types.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/wallpaper_types.h"
@@ -22,6 +23,7 @@
#include "ash/strings/grit/ash_strings.h"
#include "ash/wallpaper/wallpaper_controller.h"
#include "ash/wallpaper/wallpaper_widget_controller.h"
+#include "ash/wm/desks/desks_bar_view.h"
#include "ash/wm/overview/cleanup_animation_observer.h"
#include "ash/wm/overview/drop_target_view.h"
#include "ash/wm/overview/overview_constants.h"
@@ -187,6 +189,9 @@
// ShieldView contains the background for overview mode. It also contains text
// which is shown if there are no windows to be displayed.
+// This view also takes care of disabling overview mode on:
+// - Gesture tap.
+// - Mouse release.
class OverviewGrid::ShieldView : public views::View {
public:
ShieldView() {
@@ -223,6 +228,11 @@
AddChildView(background_view_);
AddChildView(label_container_);
+
+ if (features::IsVirtualDesksEnabled()) {
+ desks_bar_view_ = new DesksBarView;
+ AddChildView(desks_bar_view_);
+ }
}
~ShieldView() override = default;
@@ -249,19 +259,70 @@
label_container_bounds.ClampToCenteredSize(
gfx::Size(label_width, kNoItemsIndicatorHeightDp));
label_container_->SetBoundsRect(label_container_bounds);
+
+ UpdateDesksBarBounds();
}
bool IsLabelVisible() const { return label_container_->visible(); }
protected:
// views::View:
- void Layout() override { background_view_->SetBoundsRect(GetLocalBounds()); }
+ void Layout() override {
+ background_view_->SetBoundsRect(GetLocalBounds());
+ UpdateDesksBarBounds();
+ }
private:
+ // ui::EventHandler:
+ void OnMouseEvent(ui::MouseEvent* event) override {
+ if (event->type() == ui::ET_MOUSE_PRESSED) {
+ // In order to receive subsequent mouse release events in this view, we
+ // must mark the event as handled in this view.
+ event->SetHandled();
+ return;
+ }
+
+ HandleClickReleaseOrTap(event);
+ }
+
+ void OnGestureEvent(ui::GestureEvent* event) override {
+ HandleClickReleaseOrTap(event);
+ }
+
+ void HandleClickReleaseOrTap(ui::Event* event) {
+ if (event->type() != ui::ET_MOUSE_RELEASED &&
+ event->type() != ui::ET_GESTURE_TAP) {
+ return;
+ }
+
+ OverviewController* controller = Shell::Get()->overview_controller();
+ if (!controller->IsSelecting())
+ return;
+
+ // Events that happen while app list is sliding out during overview should
+ // be ignored to prevent overview from disappearing out from under the user.
+ if (!IsSlidingOutOverviewFromShelf())
+ controller->ToggleOverview();
+
+ event->StopPropagation();
+ }
+
+ void UpdateDesksBarBounds() {
+ if (!desks_bar_view_)
+ return;
+
+ // TODO: Make the ShieldView's bounds match the overview grid bounds rather
+ // than the entire screen?
+ const auto bar_bounds =
+ gfx::Rect{bounds().width(), DesksBarView::GetBarHeight()};
+ desks_bar_view_->SetBoundsRect(bar_bounds);
+ }
+
// Owned by views heirarchy.
views::View* background_view_ = nullptr;
RoundedRectView* label_container_ = nullptr;
views::Label* label_ = nullptr;
+ DesksBarView* desks_bar_view_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ShieldView);
};
@@ -1211,7 +1272,7 @@
shield_widget_ = CreateBackgroundWidget(
root_window_, ui::LAYER_NOT_DRAWN, SK_ColorTRANSPARENT, 0, 0,
SK_ColorTRANSPARENT, initial_opacity, /*parent=*/nullptr,
- /*stack_on_top=*/true);
+ /*stack_on_top=*/true, /*accept_events=*/true);
aura::Window* widget_window = shield_widget_->GetNativeWindow();
aura::Window* parent_window = widget_window->parent();
const gfx::Rect bounds = ash::screen_util::SnapBoundsToDisplayEdge(
@@ -1221,9 +1282,9 @@
// Create |shield_view_| and animate its background and label if needed.
shield_view_ = new ShieldView();
+ shield_widget_->SetContentsView(shield_view_);
shield_view_->SetBackgroundColor(GetShieldColor());
shield_view_->SetGridBounds(bounds_);
- shield_widget_->SetContentsView(shield_view_);
if (animate) {
shield_widget_->SetOpacity(initial_opacity);
@@ -1239,7 +1300,7 @@
selection_widget_ = CreateBackgroundWidget(
root_window_, ui::LAYER_TEXTURED, kWindowSelectionColor, 0,
kWindowSelectionRadius, SK_ColorTRANSPARENT, 0.f, /*parent=*/nullptr,
- /*stack_on_top=*/true);
+ /*stack_on_top=*/true, /*accept_events=*/false);
aura::Window* widget_window = selection_widget_->GetNativeWindow();
gfx::Rect target_bounds = SelectedWindow()->target_bounds();
::wm::ConvertRectFromScreen(root_window_, &target_bounds);
@@ -1330,6 +1391,10 @@
std::vector<gfx::Rect> OverviewGrid::GetWindowRects(
OverviewItem* ignored_item) {
gfx::Rect total_bounds = bounds_;
+
+ if (features::IsVirtualDesksEnabled())
+ total_bounds.Inset(0, DesksBarView::GetBarHeight(), 0, 0);
+
// Windows occupy vertically centered area with additional vertical insets.
int horizontal_inset =
gfx::ToFlooredInt(std::min(kOverviewInsetRatio * total_bounds.width(),
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc
index ef7863a..c2f6c14 100644
--- a/ash/wm/overview/overview_item.cc
+++ b/ash/wm/overview/overview_item.cc
@@ -69,7 +69,7 @@
/*root_window=*/nullptr, ui::LAYER_TEXTURED, kBackdropColor,
/*border_thickness=*/0, kBackdropRoundingDp, kBackdropColor,
/*initial_opacity=*/1.f, parent,
- /*stack_on_top=*/false);
+ /*stack_on_top=*/false, /*accept_events=*/false);
widget->GetNativeWindow()->SetName("OverviewBackdrop");
return widget;
}
diff --git a/ash/wm/overview/overview_utils.cc b/ash/wm/overview/overview_utils.cc
index 2f42102..ce0f9d3 100644
--- a/ash/wm/overview/overview_utils.cc
+++ b/ash/wm/overview/overview_utils.cc
@@ -186,7 +186,8 @@
SkColor border_color,
float initial_opacity,
aura::Window* parent,
- bool stack_on_top) {
+ bool stack_on_top,
+ bool accept_events) {
std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>();
views::Widget::InitParams params;
params.type = views::Widget::InitParams::TYPE_POPUP;
@@ -194,7 +195,7 @@
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.layer_type = layer_type;
- params.accept_events = false;
+ params.accept_events = accept_events;
widget->set_focus_on_creation(false);
// Parenting in kShellWindowId_WallpaperContainer allows proper layering of
// the shield and selection widgets. Since that container is created with
diff --git a/ash/wm/overview/overview_utils.h b/ash/wm/overview/overview_utils.h
index a93f7c1a..cfdc97a0 100644
--- a/ash/wm/overview/overview_utils.h
+++ b/ash/wm/overview/overview_utils.h
@@ -50,7 +50,8 @@
// The new background widget starts with |initial_opacity| and then fades in.
// If |parent| is prvoided the return widget will be parented to that window,
// otherwise its parent will be in kShellWindowId_WallpaperContainer of
-// |root_window|.
+// |root_window|. |accept_events| is true if the newly-created widget should
+// handle events.
std::unique_ptr<views::Widget> CreateBackgroundWidget(aura::Window* root_window,
ui::LayerType layer_type,
SkColor background_color,
@@ -59,7 +60,8 @@
SkColor border_color,
float initial_opacity,
aura::Window* parent,
- bool stack_on_top);
+ bool stack_on_top,
+ bool accept_events);
// Calculates the bounds of the |transformed_window|. Those bounds are a union
// of all regular (normal and panel) windows in the |transformed_window|'s
diff --git a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
index add1c61..b51b1f9b 100644
--- a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
+++ b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
@@ -158,7 +158,7 @@
shield_widget_ = CreateBackgroundWidget(
root_window, ui::LAYER_SOLID_COLOR, SK_ColorTRANSPARENT, 0, 0,
SK_ColorTRANSPARENT, /*initial_opacity*/ 1.f, /*parent=*/nullptr,
- /*stack_on_top=*/true);
+ /*stack_on_top=*/true, /*accept_events=*/false);
aura::Window* widget_window = shield_widget_->GetNativeWindow();
const gfx::Rect bounds = widget_window->parent()->bounds();
widget_window->SetBounds(bounds);