Merge remote-tracking branch 'upstream/main' into pr/networking-refactor-pt2

# Conflicts:
#	Modules/Panels/Network/WiFiNetworksList.qml
This commit is contained in:
Turann_
2026-03-11 04:39:39 +03:00
17 changed files with 99 additions and 50 deletions
+2
View File
@@ -824,6 +824,8 @@
"appearance-density-label": "Bar density",
"appearance-desc": "Customize the bar's appearance and position.",
"appearance-display-mode-description": "Choose when the bar is visible.",
"appearance-enable-exclusion-zone-inset-description": "Reduce the exclusion zone by 1 physical pixel so flush windows bleed perfectly under the bar edge.",
"appearance-enable-exclusion-zone-inset-label": "Inset exclusion zone",
"appearance-floating-description": "Display the bar as a floating 'pill'.",
"appearance-floating-label": "Floating bar",
"appearance-font-scale-description": "Adjust the font size scale for text displayed in the bar.",
+1
View File
@@ -12,6 +12,7 @@
"widgetSpacing": 6,
"contentPadding": 2,
"fontScale": 1,
"enableExclusionZoneInset": true,
"backgroundOpacity": 0.93,
"useSeparateOpacity": false,
"floating": false,
+9
View File
@@ -260,6 +260,15 @@
"subTab": 0,
"subTabLabel": "common.appearance"
},
{
"labelKey": "panels.bar.appearance-enable-exclusion-zone-inset-label",
"descriptionKey": "panels.bar.appearance-enable-exclusion-zone-inset-description",
"widget": "NToggle",
"tab": 4,
"tabLabel": "panels.bar.title",
"subTab": 0,
"subTabLabel": "common.appearance"
},
{
"labelKey": "panels.bar.appearance-hide-on-overview-label",
"descriptionKey": "panels.bar.appearance-hide-on-overview-description",
+6 -3
View File
@@ -329,15 +329,18 @@ Singleton {
if (!Settings.data.ui.translucentWidgets)
return baseColor;
let baseOpacity = Settings.data.ui.panelBackgroundOpacity;
let targetOpacity = Settings.data.colorSchemes.darkMode ? baseOpacity : Math.pow(baseOpacity, 2);
let alpha = Math.max(targetOpacity, minAlpha);
let alpha = Math.max(root.panelBackgroundOpacity, minAlpha);
// Combine with the base color's existing alpha
let resultAlpha = Math.max(0, baseColor.a - (1.0 - alpha));
return Qt.alpha(baseColor, resultAlpha);
}
readonly property real panelBackgroundOpacity: {
let baseOpacity = Settings.data.ui.panelBackgroundOpacity;
return Settings.data.colorSchemes.darkMode ? baseOpacity : Math.pow(baseOpacity, 2);
}
readonly property var colorKeyModel: [
{
"key": "none",
+1
View File
@@ -184,6 +184,7 @@ Singleton {
property int widgetSpacing: 6
property int contentPadding: 2
property real fontScale: 1.0
property bool enableExclusionZoneInset: true
// Bar background opacity settings
property real backgroundOpacity: 0.93
+9 -7
View File
@@ -147,13 +147,15 @@ Item {
if (PanelService.getPanel("audioPanel", screen)?.isPanelOpen) {
return "";
} else {
return I18n.tr("tooltips.microphone-volume-at", {
"volume": (() => {
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const displayVolume = Math.min(maxVolume, AudioService.inputVolume);
return Math.round(displayVolume * 100);
})()
});
const nick = AudioService.source?.nickname ?? "";
const volumeText = I18n.tr("tooltips.microphone-volume-at", {
"volume": (() => {
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const displayVolume = Math.min(maxVolume, AudioService.inputVolume);
return Math.round(displayVolume * 100);
})()
});
return nick ? volumeText + "\n" + nick : volumeText;
}
}
+9 -7
View File
@@ -140,13 +140,15 @@ Item {
if (PanelService.getPanel("audioPanel", screen)?.isPanelOpen) {
return "";
} else {
I18n.tr("tooltips.volume-at", {
"volume": (() => {
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const displayVolume = Math.min(maxVolume, AudioService.volume);
return Math.round(displayVolume * 100);
})()
});
const nick = AudioService.sink?.nickname ?? "";
const volumeText = I18n.tr("tooltips.volume-at", {
"volume": (() => {
const maxVolume = Settings.data.audio.volumeOverdrive ? 1.5 : 1.0;
const displayVolume = Math.min(maxVolume, AudioService.volume);
return Math.round(displayVolume * 100);
})()
});
return nick ? volumeText + "\n" + nick : volumeText;
}
}
@@ -38,7 +38,7 @@ Item {
// Enable layer caching to prevent continuous re-rendering
layer.enabled: true
opacity: Settings.data.ui.panelBackgroundOpacity
opacity: Color.panelBackgroundOpacity
Shape {
id: unifiedBackgroundsShape
@@ -106,7 +106,7 @@ Item {
anchors.fill: parent
layer.enabled: true
opacity: Settings.data.ui.panelBackgroundOpacity
opacity: Color.panelBackgroundOpacity
Shape {
id: panelBackgroundsShape
+3 -2
View File
@@ -23,11 +23,12 @@ PanelWindow {
readonly property bool barFloating: Settings.data.bar.floating || false
readonly property real barMarginH: (barFloating && edge === Settings.getBarPositionForScreen(screen?.name)) ? Math.ceil(Settings.data.bar.marginHorizontal) : 0
readonly property real barMarginV: (barFloating && edge === Settings.getBarPositionForScreen(screen?.name)) ? Math.ceil(Settings.data.bar.marginVertical) : 0
// Reduce exclusion zone by 1 physical pixel so app windows blend flush against the bar edge
// Allow users to enable a 1-physical-pixel inset for the exclusion zone so window borders can bleed under the bar
readonly property real bleedOffset: Settings.data.bar.enableExclusionZoneInset ? 1.0 : 0.0
readonly property real bleedInset: {
const info = CompositorService.displayScales[screen?.name];
const scale = (info && info.scale) ? info.scale : 1.0;
return 1.0 / scale;
return bleedOffset / scale;
}
// Invisible - just reserves space
@@ -255,7 +255,7 @@ Variants {
ShapePath {
strokeWidth: -1
fillColor: Qt.alpha(Color.mSurfaceVariant, Settings.data.ui.panelBackgroundOpacity)
fillColor: Qt.alpha(Color.mSurfaceVariant, Color.panelBackgroundOpacity)
// Offset by radius to account for Shape's extended bounds
startX: panelShape.radius + panelShape.radius * panelShape.tlMultX
+1 -1
View File
@@ -450,7 +450,7 @@ SmartPanel {
radius: Style.radiusM
border.width: Style.borderS
border.color: modelData.connected ? Color.mPrimary : Color.mOutline
color: modelData.connected ? Qt.alpha(Color.mPrimary, Math.min(1.15 - Settings.data.ui.panelBackgroundOpacity, 0.75)) : Color.mSurface
color: modelData.connected ? Qt.alpha(Color.mPrimary, Math.min(1.15 - Color.panelBackgroundOpacity, 0.75)) : Color.mSurface
ColumnLayout {
id: ethItemColumn
@@ -63,7 +63,7 @@ Popup {
NText {
text: I18n.tr("system.widget-settings-title", {
"widget": root.widgetId
"widget": DesktopWidgetRegistry.getWidgetDisplayName(root.widgetId)
})
pointSize: Style.fontSizeL
font.weight: Style.fontWeightBold
@@ -226,6 +226,15 @@ ColumnLayout {
text: Math.floor(Settings.data.bar.capsuleOpacity * 100) + "%"
}
NToggle {
Layout.fillWidth: true
label: I18n.tr("panels.bar.appearance-enable-exclusion-zone-inset-label")
description: I18n.tr("panels.bar.appearance-enable-exclusion-zone-inset-description")
checked: Settings.data.bar.enableExclusionZoneInset
defaultValue: Settings.getDefaultValue("bar.enableExclusionZoneInset")
onToggled: checked => Settings.data.bar.enableExclusionZoneInset = checked
}
NToggle {
Layout.fillWidth: true
visible: CompositorService.isNiri
@@ -393,7 +393,7 @@ Item {
radius: Style.radiusM
clip: true
color: (modelData.connected && modelData.state !== BluetoothDeviceState.Disconnecting) ? Qt.alpha(Color.mPrimary, Math.min(1.15 - Settings.data.ui.panelBackgroundOpacity, 0.75)) : Color.mSurface
color: (modelData.connected && modelData.state !== BluetoothDeviceState.Disconnecting) ? Qt.alpha(Color.mPrimary, Math.min(1.15 - Color.panelBackgroundOpacity, 0.75)) : Color.mSurface
ColumnLayout {
id: deviceColumn
+37 -24
View File
@@ -40,40 +40,53 @@ def theme_exists(theme_name: str) -> bool:
return False
GTK_IMPORT = '@import url("noctalia.css");'
def ensure_gtk_css_import(gtk_css: Path, colors_file: Path, label: str) -> bool:
"""
Append the noctalia.css import to gtk.css if not already present.
If gtk.css doesn't exist, create it with the import.
Does not overwrite user modifications (similar to niri template).
"""
if not colors_file.exists():
print(f"Error: {label} noctalia.css not found at {colors_file}", file=sys.stderr)
return False
# If gtk.css is a symlink, replace it with a regular file
if gtk_css.is_symlink():
gtk_css.unlink()
if gtk_css.exists():
content = gtk_css.read_text()
# Already has the import (flexible: allow optional whitespace / different quoting)
if "noctalia.css" in content and "@import" in content:
return True
# Append import to the end
new_content = content.rstrip()
if new_content and not new_content.endswith("\n"):
new_content += "\n"
new_content += "\n" + GTK_IMPORT + "\n"
gtk_css.write_text(new_content)
print(f"Appended {label} noctalia.css import to gtk.css")
else:
gtk_css.write_text(GTK_IMPORT + "\n")
print(f"Created {label} gtk.css with noctalia.css import")
return True
async def apply_gtk3_colors(config_dir: Path):
gtk3_dir = config_dir / "gtk-3.0"
colors_file = gtk3_dir / "noctalia.css"
gtk_css = gtk3_dir / "gtk.css"
if not colors_file.exists():
print(f"Error: noctalia.css not found at {colors_file}", file=sys.stderr)
return False
if gtk_css.is_symlink():
gtk_css.unlink()
elif gtk_css.exists():
backup_name = f"gtk.css.backup.{int(os.path.getmtime(gtk_css))}"
gtk_css.rename(gtk3_dir / backup_name)
print(f"Backed up existing gtk.css to {backup_name}")
gtk_css.symlink_to("noctalia.css")
print(f"Created symlink: {gtk_css} -> noctalia.css")
return True
return ensure_gtk_css_import(gtk_css, colors_file, "GTK3")
async def apply_gtk4_colors(config_dir: Path):
gtk4_dir = config_dir / "gtk-4.0"
colors_file = gtk4_dir / "noctalia.css"
gtk_css = gtk4_dir / "gtk.css"
gtk4_import = '@import url("noctalia.css");'
if not colors_file.exists():
print(f"Error: GTK4 noctalia.css not found at {colors_file}", file=sys.stderr)
return False
gtk_css.write_text(gtk4_import)
print("Updated GTK4 CSS import")
return True
return ensure_gtk_css_import(gtk_css, colors_file, "GTK4")
async def refresh_theme():
+6
View File
@@ -399,6 +399,12 @@ Item {
const layoutNameStart = beforeParenthesis.lastIndexOf(',') + 1;
const layoutName = ev.substring(layoutNameStart);
// Ignore bogus "error" layout reported by virtual keyboards (e.g. wtype)
if (layoutName.toLowerCase() === "error") {
Logger.d("HyprlandService", "Ignoring bogus 'error' layout from activelayout event");
return;
}
KeyboardLayoutService.setCurrentLayout(layoutName);
Logger.d("HyprlandService", "Keyboard layout switched:", layoutName);
} catch (e) {
+1 -1
View File
@@ -189,7 +189,7 @@ Singleton {
// Logger.e("BatteryDebug", "Available Battery count: " + laptopBatteries.length); // can be useful for debugging
if (laptopBatteries.length > 1 && device.nativePath) {
if (device.nativePath === "DisplayDevice") {
return "All batteries (combined)"; // TODO: i18n
return I18n.tr("battery.all-batteries");
}
var match = device.nativePath.match(/(\d+)$/);
if (match) {