mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge branch 'v5' of github.com:noctalia-dev/noctalia-shell into v5
This commit is contained in:
@@ -831,6 +831,14 @@
|
||||
}
|
||||
},
|
||||
"widgets": {
|
||||
"instances": {
|
||||
"cpu": "CPU",
|
||||
"date": "Date",
|
||||
"input-volume": "Input Volume",
|
||||
"output-volume": "Output Volume",
|
||||
"ram": "RAM",
|
||||
"temp": "Temperature"
|
||||
},
|
||||
"categories": {
|
||||
"custom": "Custom",
|
||||
"info": "Info",
|
||||
@@ -883,9 +891,11 @@
|
||||
"gauge": "Gauge",
|
||||
"graph": "Graph",
|
||||
"id": "ID",
|
||||
"input": "Input",
|
||||
"name": "Name",
|
||||
"none": "None",
|
||||
"on-hover": "On Hover",
|
||||
"output": "Output",
|
||||
"ram-percent": "RAM Percent",
|
||||
"ram-used": "RAM Used",
|
||||
"short": "Short",
|
||||
@@ -946,6 +956,10 @@
|
||||
"label": "Cycle Command",
|
||||
"description": "Command run when cycling keyboard layouts"
|
||||
},
|
||||
"device": {
|
||||
"label": "Device",
|
||||
"description": "Audio stream to control"
|
||||
},
|
||||
"display": {
|
||||
"label": "Display",
|
||||
"description": "Display mode for this widget"
|
||||
|
||||
@@ -729,6 +729,16 @@ void ConfigService::seedBuiltinWidgets(Config& config) {
|
||||
ram.settings["stat"] = std::string("ram_used");
|
||||
seed("ram", std::move(ram));
|
||||
|
||||
WidgetConfig outputVolume;
|
||||
outputVolume.type = "volume";
|
||||
outputVolume.settings["device"] = std::string("output");
|
||||
seed("output_volume", std::move(outputVolume));
|
||||
|
||||
WidgetConfig inputVolume;
|
||||
inputVolume.type = "volume";
|
||||
inputVolume.settings["device"] = std::string("input");
|
||||
seed("input_volume", std::move(inputVolume));
|
||||
|
||||
WidgetConfig date;
|
||||
date.type = "clock";
|
||||
date.settings["format"] = std::string("{:%a %d %b}");
|
||||
|
||||
@@ -356,7 +356,9 @@ std::unique_ptr<Widget> WidgetFactory::create(const std::string& name, wl_output
|
||||
|
||||
if (type == "volume") {
|
||||
const bool showLabel = wc != nullptr ? wc->getBool("show_label", true) : true;
|
||||
auto widget = std::make_unique<VolumeWidget>(m_audio, output, showLabel);
|
||||
const std::string target = wc != nullptr ? wc->getString("device", "output") : std::string("output");
|
||||
const auto volumeTarget = target == "input" ? VolumeWidgetTarget::Input : VolumeWidgetTarget::Output;
|
||||
auto widget = std::make_unique<VolumeWidget>(m_audio, output, showLabel, volumeTarget);
|
||||
widget->setContentScale(contentScale);
|
||||
return widget;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,11 @@
|
||||
|
||||
namespace {
|
||||
|
||||
const char* volumeGlyphName(float volume, bool muted) {
|
||||
const char* volumeGlyphName(float volume, bool muted, VolumeWidgetTarget target) {
|
||||
if (target == VolumeWidgetTarget::Input) {
|
||||
return muted ? "microphone-mute" : "microphone";
|
||||
}
|
||||
|
||||
if (muted || volume <= 0.0f) {
|
||||
return "volume-mute";
|
||||
}
|
||||
@@ -29,8 +33,8 @@ namespace {
|
||||
|
||||
} // namespace
|
||||
|
||||
VolumeWidget::VolumeWidget(PipeWireService* audio, wl_output* output, bool showLabel)
|
||||
: m_audio(audio), m_output(output), m_showLabel(showLabel) {}
|
||||
VolumeWidget::VolumeWidget(PipeWireService* audio, wl_output* output, bool showLabel, VolumeWidgetTarget target)
|
||||
: m_audio(audio), m_output(output), m_showLabel(showLabel), m_target(target) {}
|
||||
|
||||
void VolumeWidget::create() {
|
||||
auto area = std::make_unique<InputArea>();
|
||||
@@ -39,13 +43,17 @@ void VolumeWidget::create() {
|
||||
if (m_audio == nullptr) {
|
||||
return;
|
||||
}
|
||||
const auto* sink = m_audio->defaultSink();
|
||||
if (sink == nullptr) {
|
||||
const auto* node = m_target == VolumeWidgetTarget::Input ? m_audio->defaultSource() : m_audio->defaultSink();
|
||||
if (node == nullptr) {
|
||||
return;
|
||||
}
|
||||
const float delta = data.scrollDelta(1.0f) > 0 ? -kScrollStep : kScrollStep;
|
||||
const float newValue = std::clamp(sink->volume + delta, 0.0f, 1.0f);
|
||||
m_audio->setSinkVolume(sink->id, newValue);
|
||||
const float newValue = std::clamp(node->volume + delta, 0.0f, 1.0f);
|
||||
if (m_target == VolumeWidgetTarget::Input) {
|
||||
m_audio->setSourceVolume(node->id, newValue);
|
||||
} else {
|
||||
m_audio->setSinkVolume(node->id, newValue);
|
||||
}
|
||||
});
|
||||
|
||||
auto glyph = std::make_unique<Glyph>();
|
||||
@@ -103,9 +111,9 @@ void VolumeWidget::syncState(Renderer& renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* sink = m_audio->defaultSink();
|
||||
float volume = sink != nullptr ? sink->volume : 0.0f;
|
||||
bool muted = sink != nullptr ? sink->muted : false;
|
||||
const auto* node = m_target == VolumeWidgetTarget::Input ? m_audio->defaultSource() : m_audio->defaultSink();
|
||||
float volume = node != nullptr ? node->volume : 0.0f;
|
||||
bool muted = node != nullptr ? node->muted : false;
|
||||
|
||||
if (volume == m_lastVolume && muted == m_lastMuted && m_isVertical == m_lastVertical) {
|
||||
return;
|
||||
@@ -115,7 +123,7 @@ void VolumeWidget::syncState(Renderer& renderer) {
|
||||
m_lastMuted = muted;
|
||||
m_lastVertical = m_isVertical;
|
||||
|
||||
m_glyph->setGlyph(volumeGlyphName(volume, muted));
|
||||
m_glyph->setGlyph(volumeGlyphName(volume, muted, m_target));
|
||||
m_glyph->setGlyphSize(Style::barGlyphSize * m_contentScale);
|
||||
m_glyph->setColor(muted ? colorSpecFromRole(ColorRole::OnSurfaceVariant)
|
||||
: widgetForegroundOr(colorSpecFromRole(ColorRole::OnSurface)));
|
||||
|
||||
@@ -9,9 +9,14 @@ class Label;
|
||||
class PipeWireService;
|
||||
struct wl_output;
|
||||
|
||||
enum class VolumeWidgetTarget {
|
||||
Output,
|
||||
Input,
|
||||
};
|
||||
|
||||
class VolumeWidget : public Widget {
|
||||
public:
|
||||
VolumeWidget(PipeWireService* audio, wl_output* output, bool showLabel);
|
||||
VolumeWidget(PipeWireService* audio, wl_output* output, bool showLabel, VolumeWidgetTarget target);
|
||||
|
||||
void create() override;
|
||||
|
||||
@@ -23,6 +28,7 @@ private:
|
||||
PipeWireService* m_audio = nullptr;
|
||||
wl_output* m_output = nullptr;
|
||||
bool m_showLabel = true;
|
||||
VolumeWidgetTarget m_target = VolumeWidgetTarget::Output;
|
||||
Glyph* m_glyph = nullptr;
|
||||
Label* m_label = nullptr;
|
||||
float m_lastVolume = -1.0f;
|
||||
|
||||
@@ -238,6 +238,28 @@ namespace settings {
|
||||
return spec;
|
||||
}
|
||||
|
||||
std::string widgetInstanceDisplayLabel(std::string_view name) {
|
||||
if (name == "cpu") {
|
||||
return tr("settings.widgets.instances.cpu");
|
||||
}
|
||||
if (name == "temp") {
|
||||
return tr("settings.widgets.instances.temp");
|
||||
}
|
||||
if (name == "ram") {
|
||||
return tr("settings.widgets.instances.ram");
|
||||
}
|
||||
if (name == "date") {
|
||||
return tr("settings.widgets.instances.date");
|
||||
}
|
||||
if (name == "output_volume") {
|
||||
return tr("settings.widgets.instances.output-volume");
|
||||
}
|
||||
if (name == "input_volume") {
|
||||
return tr("settings.widgets.instances.input-volume");
|
||||
}
|
||||
return std::string(name);
|
||||
}
|
||||
|
||||
void addPickerEntry(std::vector<WidgetPickerEntry>& entries, std::unordered_set<std::string>& seen,
|
||||
std::string value, std::string label, std::string description, std::string category,
|
||||
WidgetReferenceKind kind) {
|
||||
@@ -317,7 +339,7 @@ namespace settings {
|
||||
|
||||
if (const auto it = cfg.widgets.find(std::string(name)); it != cfg.widgets.end()) {
|
||||
return WidgetReferenceInfo{
|
||||
.title = std::string(name),
|
||||
.title = widgetInstanceDisplayLabel(name),
|
||||
.detail = it->second.type.empty() ? tr("settings.entities.widget.detail.custom")
|
||||
: tr("settings.entities.widget.detail.type", "type", it->second.type),
|
||||
.badge = tr("settings.entities.widget.kinds.named"),
|
||||
@@ -349,7 +371,7 @@ namespace settings {
|
||||
if (isBuiltInWidgetType(name)) {
|
||||
continue;
|
||||
}
|
||||
addPickerEntry(entries, seen, name, name,
|
||||
addPickerEntry(entries, seen, name, widgetInstanceDisplayLabel(name),
|
||||
widget.type.empty() ? tr("settings.entities.widget.detail.custom")
|
||||
: tr("settings.entities.widget.detail.type", "type", widget.type),
|
||||
tr("settings.entities.widget.kinds.named"), WidgetReferenceKind::Named);
|
||||
@@ -423,6 +445,10 @@ namespace settings {
|
||||
{"always", "settings.widgets.options.always"},
|
||||
{"on_hover", "settings.widgets.options.on-hover"},
|
||||
};
|
||||
const std::vector<WidgetSettingSelectOption> volumeDeviceOptions = {
|
||||
{"output", "settings.widgets.options.output"},
|
||||
{"input", "settings.widgets.options.input"},
|
||||
};
|
||||
const std::vector<WidgetSettingSelectOption> workspaceColorRoles = {
|
||||
{"on_surface", ""}, {"primary", ""}, {"secondary", ""}, {"tertiary", ""}, {"error", ""},
|
||||
};
|
||||
@@ -494,6 +520,7 @@ namespace settings {
|
||||
add(boolSpec("drawer", false));
|
||||
add(intSpec("drawer_columns", 3, 1.0, 5.0, 1.0));
|
||||
} else if (type == "volume") {
|
||||
add(segmentedSpec("device", "output", volumeDeviceOptions));
|
||||
add(boolSpec("show_label", true));
|
||||
} else if (type == "wallpaper") {
|
||||
add(stringSpec("glyph", "wallpaper-selector"));
|
||||
|
||||
Reference in New Issue
Block a user