mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge branch 'main' of github.com:noctalia-dev/noctalia-shell
This commit is contained in:
@@ -1889,4 +1889,4 @@
|
||||
"poor": "Poor"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,6 +177,9 @@ Variants {
|
||||
}
|
||||
|
||||
function onBrightnessChanged(newBrightness) {
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
root.currentBrightness = newBrightness;
|
||||
// Don't show OSD if brightness panel is open
|
||||
var brightnessPanel = PanelService.getPanel("brightnessPanel", root.modelData);
|
||||
@@ -327,6 +330,18 @@ Variants {
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
if (typeof BrightnessService !== "undefined" && BrightnessService.monitors) {
|
||||
for (var i = 0; i < BrightnessService.monitors.length; i++) {
|
||||
try {
|
||||
BrightnessService.monitors[i].brightnessUpdated.disconnect(onBrightnessChanged);
|
||||
} catch (e) {
|
||||
// Ignore errors if already disconnected or not connected
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Visual Component
|
||||
sourceComponent: PanelWindow {
|
||||
id: panel
|
||||
|
||||
@@ -141,20 +141,13 @@ Item {
|
||||
launcher.close();
|
||||
|
||||
Qt.callLater(() => {
|
||||
executeAction(action, command);
|
||||
executeAction(action);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function executeAction(action, command) {
|
||||
// If custom command is defined, execute it
|
||||
if (command && command.trim() !== "") {
|
||||
Logger.i("SessionProvider", "Executing custom command for action:", action, "Command:", command);
|
||||
Quickshell.execDetached(["sh", "-c", command]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, use default behavior
|
||||
function executeAction(action) {
|
||||
// Default behavior or custom command handled by CompositorService
|
||||
switch (action) {
|
||||
case "lock":
|
||||
if (PanelService.lockScreen && !PanelService.lockScreen.active) {
|
||||
|
||||
@@ -211,25 +211,7 @@ SmartPanel {
|
||||
// Stop timer but don't reset other properties yet
|
||||
countdownTimer.stop();
|
||||
|
||||
// Find the option to check for custom command
|
||||
var option = null;
|
||||
for (var i = 0; i < powerOptions.length; i++) {
|
||||
if (powerOptions[i].action === action) {
|
||||
option = powerOptions[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If custom command is defined, execute it
|
||||
if (option && option.command && option.command.trim() !== "") {
|
||||
Logger.i("SessionMenu", "Executing custom command for action:", action, "Command:", option.command);
|
||||
Quickshell.execDetached(["sh", "-c", option.command]);
|
||||
cancelTimer();
|
||||
root.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, use default behavior
|
||||
// Use default behavior or custom command handled by CompositorService
|
||||
switch (action) {
|
||||
case "lock":
|
||||
// Access lockScreen via PanelService
|
||||
|
||||
@@ -17,6 +17,29 @@ async def run_command(*args):
|
||||
return stdout.decode().strip()
|
||||
|
||||
|
||||
def theme_exists(theme_name: str) -> bool:
|
||||
"""Check if a GTK theme exists in common locations."""
|
||||
search_paths = [
|
||||
Path.home() / ".themes",
|
||||
Path.home() / ".local/share/themes",
|
||||
Path("/usr/share/themes"),
|
||||
Path("/usr/local/share/themes"),
|
||||
]
|
||||
|
||||
# Add paths from XDG_DATA_DIRS
|
||||
xdg_data_dirs = os.environ.get("XDG_DATA_DIRS", "")
|
||||
if xdg_data_dirs:
|
||||
for path in xdg_data_dirs.split(":"):
|
||||
if path:
|
||||
search_paths.append(Path(path) / "themes")
|
||||
|
||||
for base_path in search_paths:
|
||||
if (base_path / theme_name).is_dir():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
async def apply_gtk3_colors(config_dir: Path):
|
||||
gtk3_dir = config_dir / "gtk-3.0"
|
||||
colors_file = gtk3_dir / "noctalia.css"
|
||||
@@ -66,16 +89,22 @@ async def refresh_theme():
|
||||
else:
|
||||
target_theme = "adw-gtk3-dark"
|
||||
|
||||
theme_available = theme_exists(target_theme)
|
||||
if not theme_available:
|
||||
print(f"Theme '{target_theme}' not found, skipping GTK theme set")
|
||||
|
||||
if has_gsettings:
|
||||
schemas = await run_command("gsettings", "list-schemas")
|
||||
if schemas and "org.gnome.desktop.interface" in schemas:
|
||||
await run_command("gsettings", "set", "org.gnome.desktop.interface", "color-scheme", f"prefer-{mode}")
|
||||
await run_command("gsettings", "set", "org.gnome.desktop.interface", "gtk-theme", f"{target_theme}")
|
||||
if theme_available:
|
||||
await run_command("gsettings", "set", "org.gnome.desktop.interface", "gtk-theme", f"{target_theme}")
|
||||
return
|
||||
|
||||
if has_dconf:
|
||||
await run_command("dconf", "write", "/org/gnome/desktop/interface/color-scheme", f"'prefer-{mode}'")
|
||||
await run_command("dconf", "write", "/org/gnome/desktop/interface/gtk-theme", f"'{target_theme}'")
|
||||
if theme_available:
|
||||
await run_command("dconf", "write", "/org/gnome/desktop/interface/gtk-theme", f"'{target_theme}'")
|
||||
|
||||
|
||||
async def get_config_dir() -> Path:
|
||||
|
||||
@@ -425,10 +425,35 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
// Session management helper for custom commands
|
||||
function getCustomCommand(action) {
|
||||
const powerOptions = Settings.data.sessionMenu.powerOptions || [];
|
||||
for (let i = 0; i < powerOptions.length; i++) {
|
||||
const option = powerOptions[i];
|
||||
if (option.action === action && option.enabled && option.command && option.command.trim() !== "") {
|
||||
return option.command.trim();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function executeSessionAction(action, defaultCommand) {
|
||||
const customCommand = getCustomCommand(action);
|
||||
if (customCommand) {
|
||||
Logger.i("Compositor", `Executing custom command for action: ${action} Command: ${customCommand}`);
|
||||
Quickshell.execDetached(["sh", "-c", customCommand]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Session management
|
||||
function logout() {
|
||||
Logger.i("Compositor", "Logout requested");
|
||||
if (executeSessionAction("logout"))
|
||||
return;
|
||||
|
||||
if (backend && backend.logout) {
|
||||
Logger.i("Compositor", "Logout requested");
|
||||
backend.logout();
|
||||
} else {
|
||||
Logger.w("Compositor", "No backend available for logout");
|
||||
@@ -437,6 +462,9 @@ Singleton {
|
||||
|
||||
function shutdown() {
|
||||
Logger.i("Compositor", "Shutdown requested");
|
||||
if (executeSessionAction("shutdown"))
|
||||
return;
|
||||
|
||||
HooksService.executeSessionHook("shutdown", () => {
|
||||
Quickshell.execDetached(["sh", "-c", "systemctl poweroff || loginctl poweroff"]);
|
||||
});
|
||||
@@ -444,6 +472,9 @@ Singleton {
|
||||
|
||||
function reboot() {
|
||||
Logger.i("Compositor", "Reboot requested");
|
||||
if (executeSessionAction("reboot"))
|
||||
return;
|
||||
|
||||
HooksService.executeSessionHook("reboot", () => {
|
||||
Quickshell.execDetached(["sh", "-c", "systemctl reboot || loginctl reboot"]);
|
||||
});
|
||||
@@ -451,11 +482,17 @@ Singleton {
|
||||
|
||||
function suspend() {
|
||||
Logger.i("Compositor", "Suspend requested");
|
||||
if (executeSessionAction("suspend"))
|
||||
return;
|
||||
|
||||
Quickshell.execDetached(["sh", "-c", "systemctl suspend || loginctl suspend"]);
|
||||
}
|
||||
|
||||
function hibernate() {
|
||||
Logger.i("Compositor", "Hibernate requested");
|
||||
if (executeSessionAction("hibernate"))
|
||||
return;
|
||||
|
||||
Quickshell.execDetached(["sh", "-c", "systemctl hibernate || loginctl hibernate"]);
|
||||
}
|
||||
|
||||
|
||||
@@ -1319,16 +1319,17 @@ Singleton {
|
||||
// Priority (when dGPU monitoring enabled): NVIDIA > AMD dGPU > Intel Arc > AMD iGPU
|
||||
// Priority (when dGPU monitoring disabled): AMD iGPU only (discrete GPUs skipped to preserve D3cold)
|
||||
function selectBestGpu() {
|
||||
const dgpuEnabled = Settings.data.systemMonitor.enableDgpuMonitoring;
|
||||
|
||||
if (root.foundGpuSensors.length === 0) {
|
||||
// No hwmon GPU sensors found, try thermal_zone fallback
|
||||
if (root.gpuThermalZonePath === "" && root.gpuThermalZonePaths.length === 0) {
|
||||
if (dgpuEnabled && root.gpuThermalZonePath === "" && root.gpuThermalZonePaths.length === 0) {
|
||||
// Thermal zone scanner hasn't found GPU zones yet; start a scan
|
||||
thermalZoneScanner.startScan();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const dgpuEnabled = Settings.data.systemMonitor.enableDgpuMonitoring;
|
||||
let best = null;
|
||||
|
||||
for (var i = 0; i < root.foundGpuSensors.length; i++) {
|
||||
|
||||
Reference in New Issue
Block a user