Skip to content

Commit

Permalink
Implement the customized rounded corner context menu
Browse files Browse the repository at this point in the history
Let the `MenuRunner` take an optional `RoundedCornersF`, which is
used in the `MenuScrollView`to render the customized conrners.

In `MenuScrollView`, set rounded corners to the Background,
BubbleBorder, and HighLightBorder based on the `rounded_corners()` .

Apply the customized rounded corner to the Chrome OS status area power
button menu. See the screenshot below.

Screenshots:
New power menu: https://screenshot.googleplex.com/X9v6yEgXKR9zCo9
Also rendered some menus to show how it look with some customized
corners:
https://screenshot.googleplex.com/8JdHiZ945ys4haS

Bug: b:251724976
Change-Id: Ic41babdb03a02ad9f88b7de46b571215c305c80c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3979481
Reviewed-by: Alex Newcomer <newcomer@chromium.org>
Reviewed-by: Allen Bauer <kylixrd@chromium.org>
Commit-Queue: Jiaming Cheng <jiamingc@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1064934}
  • Loading branch information
Jiaming Cheng authored and Chromium LUCI CQ committed Oct 28, 2022
1 parent 02380a1 commit 19ddbef
Show file tree
Hide file tree
Showing 19 changed files with 216 additions and 57 deletions.
24 changes: 23 additions & 1 deletion ash/system/unified/power_button.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/tray/tray_popup_utils.h"
#include "ash/wm/lock_state_controller.h"
#include "base/i18n/rtl.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "quick_settings_metrics_util.h"
#include "ui/base/l10n/l10n_util.h"
Expand All @@ -28,6 +29,23 @@

namespace ash {

namespace {
// Rounded corner constants.
static constexpr int kRoundedCornerRadius = 16;
static constexpr int kNonRoundedCornerRadius = 4;

constexpr gfx::RoundedCornersF kBottomRightNonRoundedCorners(
kRoundedCornerRadius,
kRoundedCornerRadius,
kNonRoundedCornerRadius,
kRoundedCornerRadius);
constexpr gfx::RoundedCornersF kBottomLeftNonRoundedCorners(
kRoundedCornerRadius,
kRoundedCornerRadius,
kRoundedCornerRadius,
kNonRoundedCornerRadius);
} // namespace

class PowerButton::MenuController : public ui::SimpleMenuModel::Delegate,
public views::ContextMenuController {
public:
Expand Down Expand Up @@ -82,10 +100,14 @@ class PowerButton::MenuController : public ui::SimpleMenuModel::Delegate,
views::MenuRunner::FIXED_ANCHOR;
menu_runner_ =
std::make_unique<views::MenuRunner>(root_menu_item_view_, run_types);

menu_runner_->RunMenuAt(source->GetWidget(), /*button_controller=*/nullptr,
source->GetBoundsInScreen(),
views::MenuAnchorPosition::kBubbleTopRight,
source_type);
source_type, /*native_view_for_gestures=*/nullptr,
/*corners=*/
base::i18n::IsRTL() ? kBottomRightNonRoundedCorners
: kBottomLeftNonRoundedCorners);
}

// Builds and saves a SimpleMenuModel to `context_menu_model_`;
Expand Down
20 changes: 18 additions & 2 deletions ui/views/bubble/bubble_border.cc
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,16 @@ void BubbleBorder::SetCornerRadius(int corner_radius) {
corner_radius_ = corner_radius;
}

void BubbleBorder::SetRoundedCorners(int top_left,
int top_right,
int bottom_right,
int bottom_left) {
radii_[0].iset(top_left, top_left);
radii_[1].iset(top_right, top_right);
radii_[2].iset(bottom_right, bottom_right);
radii_[3].iset(bottom_left, bottom_left);
}

void BubbleBorder::SetColor(SkColor color) {
requested_color_ = color;
UpdateColor(nullptr);
Expand Down Expand Up @@ -650,8 +660,14 @@ void BubbleBorder::CalculateVisibleArrowRect(
SkRRect BubbleBorder::GetClientRect(const View& view) const {
gfx::RectF bounds(view.GetLocalBounds());
bounds.Inset(gfx::InsetsF(GetInsets()));
return SkRRect::MakeRectXY(gfx::RectFToSkRect(bounds), corner_radius(),
corner_radius());
SkRRect r_rect = SkRRect::MakeRectXY(gfx::RectFToSkRect(bounds),
corner_radius(), corner_radius());
if (!radii_[0].isZero() || !radii_[1].isZero() || !radii_[2].isZero() ||
!radii_[3].isZero()) {
r_rect.setRectRadii(gfx::RectFToSkRect(bounds), radii_);
}

return r_rect;
}

void BubbleBorder::UpdateColor(View* view) {
Expand Down
10 changes: 10 additions & 0 deletions ui/views/bubble/bubble_border.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "build/chromeos_buildflags.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "ui/color/color_id.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h"
Expand Down Expand Up @@ -167,6 +168,12 @@ class VIEWS_EXPORT BubbleBorder : public Border {
// Set the corner radius, enables Material Design.
void SetCornerRadius(int radius);

// Set the customized rounded corners.
void SetRoundedCorners(int top_left,
int top_right,
int bottom_right,
int bottom_left);

// Get or set the arrow type.
void set_arrow(Arrow arrow) { arrow_ = arrow; }
Arrow arrow() const { return arrow_; }
Expand Down Expand Up @@ -303,6 +310,9 @@ class VIEWS_EXPORT BubbleBorder : public Border {
// material design.
int corner_radius_ = 0;

// The rounded corner radius for the 4 corners.
SkVector radii_[4]{{}, {}, {}, {}};

// Whether a visible arrow should be present.
bool visible_arrow_ = false;
// Cached arrow bounding box, calculated when bounds are calculated.
Expand Down
7 changes: 5 additions & 2 deletions ui/views/controls/menu/menu_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ MenuConfig::MenuConfig() {
MenuConfig::~MenuConfig() = default;

int MenuConfig::CornerRadiusForMenu(const MenuController* controller) const {
if (controller && controller->use_ash_system_ui_layout())
return touchable_corner_radius;
if (controller && controller->use_ash_system_ui_layout()) {
return controller->rounded_corners().has_value() ? 0
: touchable_corner_radius;
}

if (controller && (controller->IsCombobox() ||
(!win11_style_menus && controller->IsContextMenu())))
return auxiliary_corner_radius;
Expand Down
5 changes: 5 additions & 0 deletions ui/views/controls/menu/menu_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3470,4 +3470,9 @@ void MenuController::SetEnabledScrollButtons(bool enabled) {
scroll_buttons_enabled = enabled;
}

void MenuController::SetMenuRoundedCorners(
absl::optional<gfx::RoundedCornersF> corners) {
rounded_corners_ = corners;
}

} // namespace views
18 changes: 17 additions & 1 deletion ui/views/controls/menu/menu_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,15 @@
#include "ui/views/controls/menu/menu_cocoa_watcher_mac.h"
#endif

namespace gfx {
class RoundedCornersF;
} // namespace gfx

namespace ui {
class OSExchangeData;
struct OwnedWindowAnchor;
}
} // namespace ui

namespace views {

class Button;
Expand Down Expand Up @@ -232,6 +237,11 @@ class VIEWS_EXPORT MenuController
}
bool use_ash_system_ui_layout() const { return use_ash_system_ui_layout_; }

// The rounded corners of the context menu.
absl::optional<gfx::RoundedCornersF> rounded_corners() const {
return rounded_corners_;
}

// Notifies |this| that |menu_item| is being destroyed.
void OnMenuItemDestroying(MenuItemView* menu_item);

Expand All @@ -252,6 +262,9 @@ class VIEWS_EXPORT MenuController
// Enables/disables scrolling via scroll buttons
void SetEnabledScrollButtons(bool enabled);

// Sets the customized rounded corners of the context menu.
void SetMenuRoundedCorners(absl::optional<gfx::RoundedCornersF> corners);

private:
friend class internal::MenuRunnerImpl;
friend class test::MenuControllerTest;
Expand Down Expand Up @@ -813,6 +826,9 @@ class VIEWS_EXPORT MenuController
// Whether scroll buttons are currently enabled (as they are temporarily
// disabled when either end of the menu is reached)
bool scroll_buttons_enabled = true;

// The rounded corners of the context menu.
absl::optional<gfx::RoundedCornersF> rounded_corners_ = absl::nullopt;
};

} // namespace views
Expand Down
6 changes: 4 additions & 2 deletions ui/views/controls/menu/menu_runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <utility>

#include "ui/gfx/geometry/rounded_corners_f.h"
#include "ui/views/controls/menu/menu_runner_handler.h"
#include "ui/views/controls/menu/menu_runner_impl.h"
#include "ui/views/views_delegate.h"
Expand Down Expand Up @@ -34,7 +35,8 @@ void MenuRunner::RunMenuAt(Widget* parent,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
ui::MenuSourceType source_type,
gfx::NativeView native_view_for_gestures) {
gfx::NativeView native_view_for_gestures,
absl::optional<gfx::RoundedCornersF> corners) {
// Do not attempt to show the menu if the application is currently shutting
// down. MenuDelegate::OnMenuClosed would not be called.
if (ViewsDelegate::GetInstance() &&
Expand Down Expand Up @@ -80,7 +82,7 @@ void MenuRunner::RunMenuAt(Widget* parent,
}

impl_->RunMenuAt(parent, button_controller, bounds, anchor, run_types_,
native_view_for_gestures);
native_view_for_gestures, corners);
}

bool MenuRunner::IsRunning() const {
Expand Down
18 changes: 12 additions & 6 deletions ui/views/controls/menu/menu_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

#include "base/callback.h"
#include "base/memory/raw_ptr.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/controls/menu/menu_types.h"
#include "ui/views/views_export.h"
Expand All @@ -22,7 +24,7 @@ class TimeTicks;

namespace gfx {
class Rect;
}
} // namespace gfx

namespace ui {
class MenuModel;
Expand Down Expand Up @@ -132,21 +134,25 @@ class VIEWS_EXPORT MenuRunner {
~MenuRunner();

// Runs the menu. MenuDelegate::OnMenuClosed will be notified of the results.
// If |anchor| uses a |BUBBLE_..| type, the bounds will get determined by
// using |bounds| as the thing to point at in screen coordinates.
// If `anchor` uses a `BUBBLE_..` type, the bounds will get determined by
// using `bounds` as the thing to point at in screen coordinates.
// `native_view_for_gestures` is a NativeView that is used for cases where the
// surface hosting the menu has a different gfx::NativeView than the `parent`.
// This is required to correctly route gesture events to the correct
// NativeView in the cases where the surface hosting the menu is a
// WebContents.
// Note that this is a blocking call for a native menu on Mac.
// See http://crbug.com/682544.
// `corners` assigns the customized `RoundedCornersF` to the context menu. If
// it's set, the passed in corner will be used to render each corner radius of
// the context menu. This only works when using `USE_ASH_SYS_UI_LAYOUT`.
// Note that this is a blocking call for a native menu on Mac. See
// http://crbug.com/682544.
void RunMenuAt(Widget* parent,
MenuButtonController* button_controller,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
ui::MenuSourceType source_type,
gfx::NativeView native_view_for_gestures = nullptr);
gfx::NativeView native_view_for_gestures = nullptr,
absl::optional<gfx::RoundedCornersF> corners = absl::nullopt);

// Returns true if we're in a nested run loop running the menu.
bool IsRunning() const;
Expand Down
5 changes: 4 additions & 1 deletion ui/views/controls/menu/menu_runner_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ void MenuRunnerImpl::RunMenuAt(Widget* parent,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
int32_t run_types,
gfx::NativeView native_view_for_gestures) {
gfx::NativeView native_view_for_gestures,
absl::optional<gfx::RoundedCornersF> corners) {
closing_event_time_ = base::TimeTicks();
if (running_) {
// Ignore requests to show the menu while it's already showing. MenuItemView
Expand All @@ -129,6 +130,7 @@ void MenuRunnerImpl::RunMenuAt(Widget* parent,

MenuController* controller = MenuController::GetActiveInstance();
if (controller) {
controller->SetMenuRoundedCorners(corners);
if ((run_types & MenuRunner::IS_NESTED) != 0) {
if (controller->for_drop()) {
controller->Cancel(MenuController::ExitType::kAll);
Expand Down Expand Up @@ -162,6 +164,7 @@ void MenuRunnerImpl::RunMenuAt(Widget* parent,
// No menus are showing, show one.
controller = new MenuController(for_drop_, this);
owns_controller_ = true;
controller->SetMenuRoundedCorners(corners);
}
DCHECK((run_types & MenuRunner::COMBOBOX) == 0 ||
(run_types & MenuRunner::EDITABLE_COMBOBOX) == 0);
Expand Down
18 changes: 12 additions & 6 deletions ui/views/controls/menu/menu_runner_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
#include "ui/views/controls/menu/menu_runner_impl_interface.h"
#include "ui/views/views_export.h"

namespace gfx {
class RoundedCornersF;
} // namespace gfx

namespace views {

class MenuController;
Expand All @@ -42,12 +46,14 @@ class VIEWS_EXPORT MenuRunnerImpl : public MenuRunnerImplInterface,

bool IsRunning() const override;
void Release() override;
void RunMenuAt(Widget* parent,
MenuButtonController* button_controller,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
int32_t run_types,
gfx::NativeView native_view_for_gestures) override;
void RunMenuAt(
Widget* parent,
MenuButtonController* button_controller,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
int32_t run_types,
gfx::NativeView native_view_for_gestures,
absl::optional<gfx::RoundedCornersF> corners = absl::nullopt) override;
void Cancel() override;
base::TimeTicks GetClosingEventTime() const override;

Expand Down
3 changes: 2 additions & 1 deletion ui/views/controls/menu/menu_runner_impl_adapter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ void MenuRunnerImplAdapter::RunMenuAt(
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
int32_t types,
gfx::NativeView native_view_for_gestures) {
gfx::NativeView native_view_for_gestures,
absl::optional<gfx::RoundedCornersF> corners) {
impl_->RunMenuAt(parent, button_controller, bounds, anchor, types,
native_view_for_gestures);
}
Expand Down
18 changes: 12 additions & 6 deletions ui/views/controls/menu/menu_runner_impl_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include "ui/views/controls/menu/menu_runner_impl_interface.h"
#include "ui/views/views_export.h"

namespace gfx {
class RoundedCornersF;
} // namespace gfx

namespace views {

class MenuModelAdapter;
Expand All @@ -33,12 +37,14 @@ class VIEWS_EXPORT MenuRunnerImplAdapter : public MenuRunnerImplInterface {
// MenuRunnerImplInterface:
bool IsRunning() const override;
void Release() override;
void RunMenuAt(Widget* parent,
MenuButtonController* button_controller,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
int32_t types,
gfx::NativeView native_view_for_gestures) override;
void RunMenuAt(
Widget* parent,
MenuButtonController* button_controller,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
int32_t types,
gfx::NativeView native_view_for_gestures,
absl::optional<gfx::RoundedCornersF> corners = absl::nullopt) override;
void Cancel() override;
base::TimeTicks GetClosingEventTime() const override;

Expand Down
18 changes: 12 additions & 6 deletions ui/views/controls/menu/menu_runner_impl_cocoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
@class MenuControllerCocoa;
@class MenuControllerDelegate;

namespace gfx {
class RoundedCornersF;
} // namespace gfx

namespace views {
namespace test {
class MenuRunnerCocoaTest;
Expand All @@ -32,12 +36,14 @@ class VIEWS_EXPORT MenuRunnerImplCocoa : public MenuRunnerImplInterface {

bool IsRunning() const override;
void Release() override;
void RunMenuAt(Widget* parent,
MenuButtonController* button_controller,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
int32_t run_types,
gfx::NativeView native_view_for_gestures) override;
void RunMenuAt(
Widget* parent,
MenuButtonController* button_controller,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
int32_t run_types,
gfx::NativeView native_view_for_gestures,
absl::optional<gfx::RoundedCornersF> corners = absl::nullopt) override;
void Cancel() override;
base::TimeTicks GetClosingEventTime() const override;

Expand Down
Loading

0 comments on commit 19ddbef

Please sign in to comment.