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:

committed by
Chromium LUCI CQ

parent
80caa81cdd
commit
0fb44a3ebe
ash
ash_strings.grd
ash_strings_grd
IDS_ASH_VIDEO_CONFERENCE_SETTINGS_BUTTON_TOOLTIP.png.sha1IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_AUDIO_SETTINGS.png.sha1IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_FACE_RETOUCH.png.sha1IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_PORTRAIT_RELIGHTING.png.sha1IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_PRIVACY_SETTINGS.png.sha1IDS_ASH_VIDEO_CONFERENCE_SETTINGS_STUDIO_LOOK_PREFERENCE.png.sha1
constants
resources
vector_icons
system
media/capture/video/chromeos/mojom
@ -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
|
1
ash/ash_strings_grd/IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_PORTRAIT_RELIGHTING.png.sha1
Normal file
1
ash/ash_strings_grd/IDS_ASH_VIDEO_CONFERENCE_SETTINGS_MENU_PORTRAIT_RELIGHTING.png.sha1
Normal file
@ -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",
|
||||
|
22
ash/resources/vector_icons/security.icon
Normal file
22
ash/resources/vector_icons/security.icon
Normal file
@ -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;
|
||||
};
|
||||
|
Reference in New Issue
Block a user