0

vc-ui: Adds VC settings menu

Adds the VC settings menu, which can be opened by the gear icon in the VC panel.
This menu contains items for opening audio/privacy settings and Studio Look preferences.

UI deck: go/vcsettings-v2
Screenshot: https://screenshot.googleplex.com/Wpge33ZxvZJqXVQ.png
Mojo change in CrOS Camera Service: CL:5687008, CL:5790113

Bug: b:354069928
Change-Id: I8c7c58abf9e5de05a03f3199f41a3b51756b0f18
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5796482
Reviewed-by: Xiaoqian Dai <xdai@chromium.org>
Reviewed-by: Takashi Toyoshima <toyoshim@chromium.org>
Commit-Queue: Ryota Okuji <okuji@chromium.org>
Reviewed-by: Juliana Chang <julianachang@chromium.org>
Reviewed-by: Andre Le <leandre@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1344588}
This commit is contained in:
Ryota Okuji
2024-08-21 05:16:16 +00:00
committed by Chromium LUCI CQ
parent 80caa81cdd
commit 0fb44a3ebe
18 changed files with 358 additions and 31 deletions

@ -1119,7 +1119,7 @@ Style notes:
Volume
</message>
<message name="IDS_ASH_STATUS_TRAY_VOLUME_SLIDER_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessibile text for the slider when it is focused and not muted.">
<ph name="VOLUME_LEVEL">$1<ex>55</ex></ph>, Hitting enter will mute audio.
<ph name="VOLUME_LEVEL">$1<ex>55</ex></ph>, Hitting enter will mute audio.
</message>
<message name="IDS_ASH_STATUS_TRAY_VOLUME_SLIDER_MUTED_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessible text for the slider when it is muted.">
<ph name="VOLUME_LEVEL">$1<ex>55</ex></ph>, Muted </message>
@ -1817,6 +1817,24 @@ You can also use the keyboard shortcut. First, highlight text, then press <ph na
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_SIDETONE_TOGGLE_TOOLTIP" desc="Tooltip shown for a toggle to enable or disable sidetone.">
Toggle sidetone
</message>
<message name="IDS_ASH_VIDEO_CONFERENCE_SETTINGS_BUTTON_TOOLTIP" desc="Tooltip for the settings button in the VC bubble which opens a menu containing the VC settings.">
Settings
</message>
<message name="IDS_ASH_VIDEO_CONFERENCE_SETTINGS_STUDIO_LOOK_PREFERENCE" desc="Text for the Studio Look preference title in the VC settings menu.">
Studio Look preference
</message>
<message name="IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_AUDIO_SETTINGS" desc="Text for the audio settings item in the VC settings menu.">
Audio settings
</message>
<message name="IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_FACE_RETOUCH" desc="Text for the face retouch preference in the VC settings menu.">
Face retouch
</message>
<message name="IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_PORTRAIT_RELIGHTING" desc="Text for the portrait relighting preference in the VC settings menu.">
Improve lighting
</message>
<message name="IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_PRIVACY_SETTINGS" desc="Text for the privacy settings item in the VC settings menu.">
Privacy settings
</message>
<message name="IDS_ASH_VIDEO_CONFERENCE_SIDETONE_ENABLED_BUBBLE_TITLE" desc="The title of the bubble when sidetone is enabled.">
Listen to your mic sound
</message>
@ -1835,7 +1853,7 @@ You can also use the keyboard shortcut. First, highlight text, then press <ph na
<message name="IDS_ASH_VIDEO_CONFERENCE_SIDETONE_BUBBLE_DISMISS_BUTTON" desc="The dismiss button of the bubble when sidetone is enabled.">
Dismiss
</message>
<message name="IDS_ASH_VIDEO_CONFERENCE_CREAT_WITH_AI_NAME" desc="Text for name of the 'Create With AI' button in the VC bubble, which invokes the webui for the creation.">
<message name="IDS_ASH_VIDEO_CONFERENCE_CREAT_WITH_AI_NAME" desc="Text for name of the 'Create With AI' button in the VC bubble, which invokes the webui for the creation.">
Create with AI
</message>
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_LINUX_APP_WARNING_TEXT" desc="Text for the warning label placed inside the VC bubble when there's any linux app running.">
@ -4920,10 +4938,10 @@ No devices connected.
Enter your PIN
</message>
<message name="IDS_ASH_IN_SESSION_AUTH_DIALOG_ACCESSIBLE_NAME" desc="The accessible name of the in session auth dialog">
Verify your identity
Verify your identity
</message>
<message name="IDS_ASH_IN_SESSION_AUTH_DIALOG_ACCESSIBLE_DESCRIPTION" desc="The accessible name of the in session auth dialog">
Press escape to close
Press escape to close
</message>
<message name="IDS_ASH_LOGIN_PIN_INPUT_DIGITS_REMAINING" desc="Screen reader message telling the user how many digits are remaining for the PIN input field. [ICU Syntax]">
{NUM_DIGITS, plural,

@ -0,0 +1 @@
29df8b034a1e958f7ce734e3c68e746d7afc0ce3

@ -0,0 +1 @@
5c46bf8b3d7785d059dbf6be7527280ea6b0c944

@ -0,0 +1 @@
5c46bf8b3d7785d059dbf6be7527280ea6b0c944

@ -0,0 +1 @@
5c46bf8b3d7785d059dbf6be7527280ea6b0c944

@ -0,0 +1 @@
5c46bf8b3d7785d059dbf6be7527280ea6b0c944

@ -0,0 +1 @@
5c46bf8b3d7785d059dbf6be7527280ea6b0c944

@ -1521,7 +1521,7 @@ inline constexpr char kDeviceGeolocationAllowed[] =
inline constexpr char kUserPreviousGeolocationAccessLevel[] =
"ash.user.previous_geolocation_access_level";
// An boolean pref indicating whether a user has enabled the improve location
// A boolean pref indicating whether a user has enabled the improve location
// toggle.
inline constexpr char kUserGeolocationAccuracyEnabled[] =
"ash.user.geolocation_accuracy_enabled";
@ -1952,7 +1952,7 @@ inline constexpr char kAutozoomNudges[] = "ash.camera.autozoom_nudges";
inline constexpr char kCameraAppDevToolsOpen[] =
"ash.camera.cca_dev_tools_open";
// An boolean pref that specifies the recovery service activation for user.
// A boolean pref that specifies the recovery service activation for user.
// When the pref is set to `true`, the user data recovery is activated. When the
// pref is set to `false`, the user data recovery is not activated. The default
// value of the pref is `true`. Controlled by RecoveryFactorBehavior policy.
@ -1967,16 +1967,22 @@ inline constexpr char kApnMigratedIccids[] = "ash.cellular.apn_migrated_iccids";
// -1 means disabled.
inline constexpr char kBackgroundBlur[] = "ash.camera.background_blur";
// An boolean pref that indicates whether background replacement is applied.
// A boolean pref that indicates whether background replacement is applied.
inline constexpr char kBackgroundReplace[] = "ash.camera.background_replace";
// An string pref that indicates the image path of the camera background.
inline constexpr char kBackgroundImagePath[] =
"ash.camera.background_image_path";
// An boolean pref that indicates whether portrait relighting is applied.
// A boolean pref that indicates whether portrait relighting is applied.
inline constexpr char kPortraitRelighting[] = "ash.camera.portrait_relighting";
// A boolean pref that indicates whether face retouch is applied.
inline constexpr char kFaceRetouch[] = "ash.camera.face_retouch";
// A boolean pref that indicates whether Studio Look is applied.
inline constexpr char kStudioLook[] = "ash.camera.studio_look";
// Specifies if ARC app sync metrics should be recorded, i.e. this is the
// initial session after sync consent screen.
inline constexpr char kRecordArcAppSyncMetrics[] =

@ -399,6 +399,7 @@ aggregate_vector_icons("ash_vector_icons") {
"resume.icon",
"save_desk_as_template.icon",
"save_desk_for_later.icon",
"security.icon",
"select_to_speak_next_paragraph.icon",
"select_to_speak_next_sentence.icon",
"select_to_speak_pause.icon",

@ -0,0 +1,22 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 48,
MOVE_TO, 24, 2,
LINE_TO, 6, 10,
R_V_LINE_TO, 12,
R_CUBIC_TO, 0, 11.1f, 7.67f, 21.47f, 18, 24,
R_CUBIC_TO, 10.33f, -2.53f, 18, -12.9f, 18, -24,
V_LINE_TO, 10,
LINE_TO, 24, 2,
CLOSE,
R_MOVE_TO, 0, 21.98f,
R_H_LINE_TO, 14,
R_CUBIC_TO, -1.06f, 8.24f, -6.55f, 15.58f, -14, 17.87f,
V_LINE_TO, 24,
H_LINE_TO, 10,
V_LINE_TO, 12.6f,
R_LINE_TO, 14, -6.22f,
R_V_LINE_TO, 17.6f,
CLOSE

@ -65,6 +65,8 @@ bool AudioEffectsController::IsEffectSupported(VcEffectId effect_id) {
case VcEffectId::kPortraitRelighting:
case VcEffectId::kCameraFraming:
case VcEffectId::kTestEffect:
case VcEffectId::kFaceRetouch:
case VcEffectId::kStudioLook:
NOTREACHED();
}
}
@ -84,6 +86,8 @@ std::optional<int> AudioEffectsController::GetEffectState(
case VcEffectId::kPortraitRelighting:
case VcEffectId::kCameraFraming:
case VcEffectId::kTestEffect:
case VcEffectId::kFaceRetouch:
case VcEffectId::kStudioLook:
NOTREACHED();
}
}
@ -119,6 +123,8 @@ void AudioEffectsController::OnEffectControlActivated(
case VcEffectId::kPortraitRelighting:
case VcEffectId::kCameraFraming:
case VcEffectId::kTestEffect:
case VcEffectId::kFaceRetouch:
case VcEffectId::kStudioLook:
NOTREACHED();
}
}

@ -405,7 +405,19 @@ void CameraEffectsController::RegisterProfilePrefs(
registry->RegisterBooleanPref(prefs::kBackgroundReplace, false);
registry->RegisterBooleanPref(prefs::kPortraitRelighting, false);
// If the Studio Look feature is available, the portrait relighting and face
// retouch prefs are used to determine which effects are applied. Enable both
// of them by default. Otherwise, disable both of them.
registry->RegisterBooleanPref(prefs::kPortraitRelighting,
features::IsVcStudioLookEnabled());
registry->RegisterBooleanPref(prefs::kFaceRetouch,
features::IsVcStudioLookEnabled());
// If the Studio Look feature is available, disable Studio Look by default.
// Otherwise, set it to always true to apply effects based on the portrait
// relighting and face retouch pref values.
registry->RegisterBooleanPref(prefs::kStudioLook,
!features::IsVcStudioLookEnabled());
registry->RegisterFilePathPref(prefs::kBackgroundImagePath, base::FilePath());
}
@ -643,6 +655,10 @@ std::optional<int> CameraEffectsController::GetEffectState(
current_effects_->blur_enabled);
case VcEffectId::kPortraitRelighting:
return current_effects_->relight_enabled;
case VcEffectId::kFaceRetouch:
return current_effects_->retouch_enabled;
case VcEffectId::kStudioLook:
return current_effects_->studio_look_enabled;
case VcEffectId::kCameraFraming:
return Shell::Get()->autozoom_controller()->GetState() !=
cros::mojom::CameraAutoFramingState::OFF;
@ -696,6 +712,38 @@ void CameraEffectsController::OnEffectControlActivated(
case VcEffectId::kPortraitRelighting: {
new_effects->relight_enabled =
state.value_or(!new_effects->relight_enabled);
if (!features::IsVcStudioLookEnabled()) {
// Make sure that `studio_look_enabled` is set to true. Otherwise, this
// will override the value of `relight_enabled`.
new_effects->studio_look_enabled = true;
}
// TODO(b/354069928): Toggle off the Studio Look button when both
// relighting and retouch are disabled.
break;
}
case VcEffectId::kFaceRetouch: {
new_effects->retouch_enabled =
state.value_or(!new_effects->retouch_enabled);
if (!features::IsVcStudioLookEnabled()) {
// Make sure that `studio_look_enabled` is set to true. Otherwise, this
// will override the value of `retouch_enabled`.
new_effects->studio_look_enabled = true;
}
// TODO(b/354069928): Toggle off the Studio Look button when both
// relighting and retouch are disabled.
break;
}
case VcEffectId::kStudioLook: {
new_effects->studio_look_enabled =
state.value_or(!new_effects->studio_look_enabled);
if (new_effects->studio_look_enabled && !new_effects->relight_enabled &&
!new_effects->retouch_enabled) {
// When Studio Look is toggled enabled but portrait relighting and face
// retouch are currently both disabled, the portrait relighting and face
// retouch prefs are updated to be enabled.
new_effects->relight_enabled = true;
new_effects->retouch_enabled = true;
}
break;
}
case VcEffectId::kCameraFraming: {
@ -849,9 +897,10 @@ void CameraEffectsController::SetCameraEffects(
&CameraEffectsController::OnCopyBackgroundImageFileComplete,
weak_factory_.GetWeakPtr(), std::move(config), is_initialization,
std::move(copy_background_image_complete_callback)));
} else {
SetCameraEffectsInCameraHalDispatcherImpl(std::move(config));
return;
}
SetCameraEffectsInCameraHalDispatcherImpl(std::move(config));
}
void CameraEffectsController::OnCopyBackgroundImageFileComplete(
@ -924,6 +973,10 @@ CameraEffectsController::GetEffectsConfigFromPref() {
effects->relight_enabled =
pref_change_registrar_->prefs()->GetBoolean(prefs::kPortraitRelighting);
effects->retouch_enabled =
pref_change_registrar_->prefs()->GetBoolean(prefs::kFaceRetouch);
effects->studio_look_enabled =
pref_change_registrar_->prefs()->GetBoolean(prefs::kStudioLook);
return effects;
}
@ -959,6 +1012,17 @@ void CameraEffectsController::SetEffectsConfigToPref(
pref_change_registrar_->prefs()->SetBoolean(prefs::kPortraitRelighting,
new_config->relight_enabled);
}
if (new_config->retouch_enabled != current_effects_->retouch_enabled) {
pref_change_registrar_->prefs()->SetBoolean(prefs::kFaceRetouch,
new_config->retouch_enabled);
}
if (new_config->studio_look_enabled !=
current_effects_->studio_look_enabled) {
pref_change_registrar_->prefs()->SetBoolean(
prefs::kStudioLook, new_config->studio_look_enabled);
}
}
bool CameraEffectsController::IsEffectControlAvailable(
@ -1028,42 +1092,44 @@ void CameraEffectsController::InitializeEffectControls() {
AddEffect(std::move(effect));
}
// If portrait relight UI controls are present, construct the effect
// and its state.
// If portrait relight UI controls are present, construct the effect and its
// state. If the Studio Look feature is available, the same UI control is used
// for Studio Look.
if (IsEffectControlAvailable(cros::mojom::CameraEffect::kPortraitRelight)) {
auto effect_id = features::IsVcStudioLookEnabled()
? VcEffectId::kStudioLook
: VcEffectId::kPortraitRelighting;
std::unique_ptr<VcHostedEffect> effect = std::make_unique<VcHostedEffect>(
/*type=*/VcEffectType::kToggle,
/*get_state_callback=*/
base::BindRepeating(&CameraEffectsController::GetEffectState,
base::Unretained(this),
VcEffectId::kPortraitRelighting),
/*effect_id=*/VcEffectId::kPortraitRelighting);
base::Unretained(this), effect_id),
effect_id);
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
std::string face_retouch_override = command_line->GetSwitchValueASCII(
media::switches::kFaceRetouchOverride);
bool is_studio_look_enabled =
bool show_studio_look_ui =
face_retouch_override ==
media::switches::kFaceRetouchForceEnabledWithRelighting ||
face_retouch_override ==
media::switches::kFaceRetouchForceEnabledWithoutRelighting;
media::switches::kFaceRetouchForceEnabledWithoutRelighting ||
features::IsVcStudioLookEnabled();
auto effect_state = std::make_unique<VcEffectState>(
/*icon=*/is_studio_look_enabled
? &kVideoConferenceStudioLookIcon
: &kVideoConferencePortraitRelightOnIcon,
/*icon=*/show_studio_look_ui ? &kVideoConferenceStudioLookIcon
: &kVideoConferencePortraitRelightOnIcon,
/*label_text=*/
l10n_util::GetStringUTF16(
is_studio_look_enabled
show_studio_look_ui
? IDS_ASH_VIDEO_CONFERENCE_BUBBLE_STUDIO_LOOK_NAME
: IDS_ASH_VIDEO_CONFERENCE_BUBBLE_PORTRAIT_RELIGHT_NAME),
/*accessible_name_id=*/
IDS_ASH_VIDEO_CONFERENCE_BUBBLE_PORTRAIT_RELIGHT_NAME,
/*button_callback=*/
base::BindRepeating(&CameraEffectsController::OnEffectControlActivated,
base::Unretained(this),
/*effect_id=*/VcEffectId::kPortraitRelighting,
base::Unretained(this), effect_id,
/*value=*/std::nullopt));
effect->AddState(std::move(effect_state));

@ -4,34 +4,205 @@
#include "ash/system/video_conference/bubble/settings_button.h"
#include "ash/public/cpp/system_tray_client.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_id.h"
#include "ash/style/switch.h"
#include "ash/system/camera/camera_effects_controller.h"
#include "ash/system/model/system_tray_model.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/button/toggle_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/layout/box_layout_view.h"
namespace ash::video_conference {
namespace {
constexpr gfx::Size kIconSize{20, 20};
// Rounded corner constants.
static constexpr int kRoundedCornerRadius = 16;
static constexpr int kNonRoundedCornerRadius = 4;
static constexpr int kIconSize = 20;
enum CommandId {
kAudioSettings = 1,
kPrivacySettings = 2,
kPortraitRelighting = 3,
kFaceRetouch = 4,
};
constexpr gfx::Size kIconSizeGfx{kIconSize, kIconSize};
constexpr gfx::RoundedCornersF kTopRightNonRoundedCorners(
kRoundedCornerRadius,
kNonRoundedCornerRadius,
kRoundedCornerRadius,
kRoundedCornerRadius);
} // namespace
SettingsButton::SettingsButton() {
class SettingsButton::MenuController : public ui::SimpleMenuModel::Delegate,
public views::ContextMenuController {
public:
MenuController() = default;
MenuController(const MenuController&) = delete;
MenuController& operator=(const MenuController&) = delete;
~MenuController() override = default;
// ui::SimpleMenuModel::Delegate:
bool IsCommandIdChecked(int command_id) const override {
std::optional<int> state;
if (command_id == CommandId::kPortraitRelighting) {
state =
effects_controller_->GetEffectState(VcEffectId::kPortraitRelighting);
} else if (command_id == CommandId::kFaceRetouch) {
state = effects_controller_->GetEffectState(VcEffectId::kFaceRetouch);
} else {
return false;
}
return *state != 0;
}
// ui::SimpleMenuModel::Delegate:
void ExecuteCommand(int command_id, int event_flags) override {
auto* client = Shell::Get()->system_tray_model()->client();
switch (command_id) {
case CommandId::kAudioSettings:
client->ShowAudioSettings();
break;
case CommandId::kPrivacySettings:
client->ShowPrivacyAndSecuritySettings();
break;
case CommandId::kPortraitRelighting:
effects_controller_->OnEffectControlActivated(
VcEffectId::kPortraitRelighting, /*state=*/std::nullopt);
break;
case CommandId::kFaceRetouch:
effects_controller_->OnEffectControlActivated(VcEffectId::kFaceRetouch,
/*state=*/std::nullopt);
break;
}
}
// views::ContextMenuController:
void ShowContextMenuForViewImpl(views::View* source,
const gfx::Point& point,
ui::MenuSourceType source_type) override {
BuildMenuModel();
menu_model_adapter_ = std::make_unique<views::MenuModelAdapter>(
menu_model_.get(), base::BindRepeating(&MenuController::OnMenuClosed,
base::Unretained(this)));
std::unique_ptr<views::MenuItemView> menu =
menu_model_adapter_->CreateMenu();
int run_types = views::MenuRunner::USE_ASH_SYS_UI_LAYOUT |
views::MenuRunner::CONTEXT_MENU |
views::MenuRunner::FIXED_ANCHOR;
menu_runner_ =
std::make_unique<views::MenuRunner>(std::move(menu), run_types);
menu_runner_->RunMenuAt(source->GetWidget(), /*button_controller=*/nullptr,
source->GetBoundsInScreen(),
views::MenuAnchorPosition::kBubbleBottomLeft,
source_type, /*native_view_for_gestures=*/nullptr,
kTopRightNonRoundedCorners);
}
private:
// Builds and saves SimpleMenuModel to `context_menu_model_`.
void BuildMenuModel() {
menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
// TODO(b/354069928): Add accessible names.
menu_model_->AddItemWithIcon(
CommandId::kAudioSettings,
l10n_util::GetStringUTF16(
IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_AUDIO_SETTINGS),
ui::ImageModel::FromVectorIcon(kPrivacyIndicatorsMicrophoneIcon,
cros_tokens::kCrosSysOnSurface,
kIconSize));
menu_model_->AddItemWithIcon(
CommandId::kPrivacySettings,
l10n_util::GetStringUTF16(
IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_PRIVACY_SETTINGS),
ui::ImageModel::FromVectorIcon(
kSecurityIcon, cros_tokens::kCrosSysOnSurface, kIconSize));
menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
menu_model_->AddTitle(l10n_util::GetStringUTF16(
IDS_ASH_VIDEO_CONFERENCE_SETTINGS_STUDIO_LOOK_PREFERENCE));
menu_model_->AddCheckItem(
CommandId::kPortraitRelighting,
l10n_util::GetStringUTF16(
IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_PORTRAIT_RELIGHTING));
menu_model_->AddCheckItem(
CommandId::kFaceRetouch,
l10n_util::GetStringUTF16(
IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_FACE_RETOUCH));
}
void OnMenuClosed() {
menu_runner_.reset();
menu_model_.reset();
menu_model_adapter_.reset();
}
raw_ptr<CameraEffectsController> effects_controller_ =
Shell::Get()->camera_effects_controller();
std::unique_ptr<ui::SimpleMenuModel> menu_model_;
std::unique_ptr<views::MenuModelAdapter> menu_model_adapter_;
std::unique_ptr<views::MenuRunner> menu_runner_;
};
SettingsButton::SettingsButton()
: views::Button(base::BindRepeating(&SettingsButton::OnButtonActivated,
base::Unretained(this))),
context_menu_(std::make_unique<MenuController>()) {
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>());
layout->SetOrientation(views::BoxLayout::Orientation::kHorizontal);
AddChildView(views::Builder<views::ImageView>()
.SetImage(ui::ImageModel::FromVectorIcon(
kSystemMenuSettingsIcon, cros_tokens::kCrosSysOnSurface))
.SetImageSize(kIconSize)
.SetImageSize(kIconSizeGfx)
.Build());
AddChildView(views::Builder<views::ImageView>()
.SetImage(ui::ImageModel::FromVectorIcon(
kDropDownArrowIcon, cros_tokens::kCrosSysOnSurface))
.SetImageSize(kIconSize)
.SetImageSize(kIconSizeGfx)
.Build());
SetTooltipText(l10n_util::GetStringUTF16(
IDS_ASH_VIDEO_CONFERENCE_SETTINGS_BUTTON_TOOLTIP));
GetViewAccessibility().SetName(l10n_util::GetStringUTF16(
IDS_ASH_VIDEO_CONFERENCE_SETTINGS_BUTTON_TOOLTIP));
}
SettingsButton::~SettingsButton() = default;
void SettingsButton::OnButtonActivated(const ui::Event& event) {
ui::MenuSourceType source_type;
if (event.IsMouseEvent()) {
source_type = ui::MENU_SOURCE_MOUSE;
} else if (event.IsTouchEvent()) {
source_type = ui::MENU_SOURCE_TOUCH;
} else if (event.IsKeyEvent()) {
source_type = ui::MENU_SOURCE_KEYBOARD;
} else {
source_type = ui::MENU_SOURCE_STYLUS;
}
context_menu_->ShowContextMenuForView(
/*source=*/this, GetBoundsInScreen().CenterPoint(), source_type);
}
BEGIN_METADATA(SettingsButton)

@ -17,8 +17,20 @@ class SettingsButton : public views::Button {
public:
SettingsButton();
~SettingsButton() override;
SettingsButton(const SettingsButton&) = delete;
SettingsButton& operator=(const SettingsButton&) = delete;
private:
class MenuController;
// Shows the context menu using `MenuController`. This method is passed in to
// the `Button` view as the `OnPressedCallback`.
void OnButtonActivated(const ui::Event& event);
// The context menu, which will be set as the controller to show the settings
// button menu view.
std::unique_ptr<MenuController> context_menu_;
};
} // namespace ash::video_conference

@ -191,6 +191,8 @@ VideoConferenceTrayEffectsManager::GetDlcIdsForEffectId(VcEffectId effect_id) {
case VcEffectId::kNoiseCancellation:
case VcEffectId::kStyleTransfer:
case VcEffectId::kCameraFraming:
case VcEffectId::kFaceRetouch:
case VcEffectId::kStudioLook:
return {};
}
}

@ -114,7 +114,9 @@ enum class VcEffectId {
kLiveCaption = 3,
kCameraFraming = 4,
kStyleTransfer = 5,
kMaxValue = kStyleTransfer,
kFaceRetouch = 6,
kStudioLook = 7,
kMaxValue = kStudioLook,
};
// Represents a single video conference effect that's being "hosted" by an

@ -32,6 +32,10 @@ std::string GetEffectHistogramNameBase(VcEffectId effect_id) {
return "Ash.VideoConferenceTray.LiveCaption";
case VcEffectId::kCameraFraming:
return "Ash.VideoConferenceTray.CameraFraming";
case VcEffectId::kFaceRetouch:
return "Ash.VideoConferenceTray.FaceRetouch";
case VcEffectId::kStudioLook:
return "Ash.VideoConferenceTray.StudioLook";
}
}
@ -82,4 +86,4 @@ cc::SkottieColorMap CreateColorMapForGradientAnimation(
return map;
}
} // namespace ash::video_conference_utils
} // namespace ash::video_conference_utils

@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Next min version: 6
// Next min version: 7
module cros.mojom;
import "mojo/public/mojom/base/file_path.mojom";
// [Deprecated in version 1]
//
// Set of effects that can be enabled.
// Used by EffectsConfig to indicate which effect the g3 shared library
// should be applying. Needs to be kept in sync with g3 version found in
@ -102,4 +104,13 @@ struct EffectsConfig {
// The inference backend to run portrait relighing model.
[MinVersion=5] InferenceBackend relighting_inference_backend;
// Whether face retouch should be enabled.
[MinVersion=6] bool retouch_enabled;
// Whether Studio Look should be enabled. If the Studio Look feature is not
// available, set it to always true. Otherwise, it can be set to false by UI,
// which will override |retouch_enabled| and |relight_enabled| and disable
// both effects.
[MinVersion=6] bool studio_look_enabled = true;
};