Remove unreleased Noctalia shell compatibility

This commit is contained in:
Ryan Hughes
2026-05-17 12:06:18 -04:00
parent 7517c8b624
commit 5faee9cf76
42 changed files with 14 additions and 1979 deletions
@@ -58,76 +58,11 @@ QtObject {
property color unselectedBorder: root.pick("image-picker.unselected-border", root.foreground)
}
// Noctalia palette tokens used by the compat widgets. Mapped onto the
// foundational palette; not exposed in shell.toml.
readonly property color mPrimary: accent
readonly property color mSecondary: Qt.darker(accent, 1.2)
readonly property color mTertiary: Qt.lighter(accent, 1.3)
readonly property color mSurface: background
readonly property color mSurfaceVariant: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.06)
readonly property color mOnSurface: foreground
readonly property color mOnSurfaceVariant: Qt.darker(foreground, 1.4)
readonly property color mOutline: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.18)
readonly property color mHover: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.14)
readonly property color mOnHover: foreground
readonly property color mError: urgent
readonly property color mOnError: background
// Plugins read this to know whether to skip mid-flight transitions. We
// don't ship theme transitions ourselves, so it's always false.
readonly property bool isTransitioning: false
function alpha(c, opacity) {
if (!c) return Qt.rgba(0, 0, 0, opacity)
return Qt.rgba(c.r, c.g, c.b, opacity)
}
// Noctalia's smartAlpha picks an alpha based on the host theme's perceived
// contrast. A flat 0.6 reads acceptably across our themes; cheap, no math.
function smartAlpha(c) {
return alpha(c, 0.6)
}
// adaptiveOpacity takes a 0..1 ratio and clamps it. Plugins use it for
// fade animations relative to a "full" opacity value.
function adaptiveOpacity(value) {
if (value === undefined || value === null) return 1.0
return Math.max(0, Math.min(1, Number(value)))
}
// Plugins occasionally pass a color key like "accent" or "primary" via
// their own settings. resolveColorKey returns a color; resolveColorKeyOptional
// returns null/undefined-ish for "none".
function resolveColorKey(key) {
var resolved = resolveColorKeyOptional(key)
return resolved === null ? foreground : resolved
}
function resolveColorKeyOptional(key) {
var k = String(key || "").toLowerCase()
if (!k || k === "none") return null
switch (k) {
case "primary": return mPrimary
case "secondary": return mSecondary
case "tertiary": return mTertiary
case "surface": return mSurface
case "surfacevariant": return mSurfaceVariant
case "onsurface": return mOnSurface
case "onsurfacevariant": return mOnSurfaceVariant
case "outline": return mOutline
case "hover": return mHover
case "onhover": return mOnHover
case "error": return mError
case "onerror": return mOnError
case "accent": return accent
case "foreground": return foreground
case "background": return background
case "urgent":
case "red": return urgent
}
return Qt.color(k)
}
function loadColors(raw) {
var lines = String(raw || "").split("\n")
var foundAccent = false
@@ -1,15 +0,0 @@
pragma Singleton
import QtQuick
// Noctalia compat shim. Their plugins normally route translations through
// pluginApi.tr(), not this singleton, so the stub here mostly exists to
// satisfy `import qs.Commons` style usage.
QtObject {
readonly property string langCode: "en"
function tr(key, interp) { return String(key === undefined ? "" : key) }
function trp(key, count, interp) { return String(key === undefined ? "" : key) }
function hasTranslation(key) { return false }
signal translationsLoaded()
}
@@ -1,88 +0,0 @@
pragma Singleton
import QtQuick
// Noctalia compat shim. Their plugins resolve Tabler icon names to glyphs via
// this singleton. The original ships ~3000 mappings; for v1 we cover the
// names most commonly used by the plugins in their repo and fall back to
// "?" for unknowns so missing glyphs are visually obvious.
QtObject {
// Tabler icon names → Nerd Font glyphs. Most entries are mdi-* substitutes
// since Omarchy installs JetBrains Mono Nerd Font which includes Material
// Design Icons. Glyph codepoints embedded as actual chars (Python helper
// when the write tool strips multi-byte codepoints in some positions).
readonly property var glyphs: ({
"bell": "\udb80\udc9a", // mdi-bell
"bell-off": "\udb80\udc9b", // mdi-bell_off
"bell-ring": "\udb80\udd6b", // mdi-bell_ring
"clock": "\udb80\udc50", // mdi-clock
"clock-outline": "\udb80\udc51", // mdi-clock_outline
"wifi": "\udb81\udda9", // mdi-wifi
"wifi-off": "\udb81\uddaa", // mdi-wifi_off
"ethernet": "\udb80\udc02", // mdi-ethernet
"bluetooth": "\udb80\udcaf", // mdi-bluetooth
"bluetooth-off": "\udb80\udcb2", // mdi-bluetooth_off
"volume": "\udb81\udd7e", // mdi-volume_high
"volume-up": "\udb81\udd7e",
"volume-down": "\udb81\udd7f",
"volume-off": "\udb83\udc08", // mdi-volume_variant_off
"volume-mute": "\udb83\udc08",
"headphones": "\udb80\udecb", // mdi-headphones
"microphone": "\udb80\udf6c", // mdi-microphone
"microphone-off": "\udb80\udf6d", // mdi-microphone_off
"play": "\udb81\udc0a", // mdi-play
"pause": "\udb80\udfe4", // mdi-pause
"skip-back": "\udb81\udcae", // mdi-skip_previous
"skip-forward": "\udb81\udcad", // mdi-skip_next
"music": "\udb81\udd5a", // mdi-music
"weather": "\udb81\udd99", // mdi-weather_sunny
"weather-sun": "\udb81\udd99",
"weather-moon": "\udb81\udd94", // mdi-weather_night
"weather-cloud": "\udb81\udd90", // mdi-weather_cloudy
"weather-rain": "\udb81\udd96", // mdi-weather_pouring
"battery": "\udb80\udc83", // mdi-battery
"battery-charging": "\udb80\udc84",
"cpu": "\udb83\udee0", // mdi-cpu_64_bit
"memory": "\udb80\udd5b", // mdi-memory
"tools": "\udb80\udd64", // mdi-tools
"settings": "\udb80\udc93", // mdi-cog
"settings-outline":"\udb80\udcbb",
"power": "\udb80\udc25", // mdi-power
"lock": "\udb80\udd3e", // mdi-lock
"unlock": "\udb80\udd3f",
"refresh": "\udb81\udc50", // mdi-refresh
"ai": "󰚩", // mdi-robot
"robot": "󰚩",
"x": "\udb80\udd56", // mdi-close
"check": "\udb80\udc12", // mdi-check
"chevron-down": "\udb80\udd40",
"chevron-up": "\udb80\udd43",
"chevron-left": "\udb80\udd41",
"chevron-right": "\udb80\udd42",
"plus": "\udb80\udc15",
"minus": "\udb80\udc16",
"leaf": "\udb80\udf2a",
"rocket": "\udb81\udc63",
"balance": "\udb81\uddd1",
"moon": "\udb81\udd94",
"sun": "\udb81\udd99",
"trash": "\udb81\udcd7", // mdi-delete
"edit": "\udb80\udd66",
"search": "\udb80\udd6f",
"menu": "\udb80\udd6c",
"home": "\udb80\udf0c",
"folder": "\udb80\udd99",
"file": "\udb80\udd97",
"calendar": "\udb80\udcf7", // mdi-calendar
"circle": "\udb80\udd2f"
})
function get(name) {
var key = String(name || "").toLowerCase()
if (glyphs[key]) return glyphs[key]
return "?"
}
function has(name) {
return !!glyphs[String(name || "").toLowerCase()]
}
}
@@ -1,19 +0,0 @@
pragma Singleton
import QtQuick
// Noctalia compat shim. Plugins call Logger.d/i/w/e routinely.
QtObject {
function format(args) {
var out = []
for (var i = 0; i < args.length; i++) {
var a = args[i]
out.push(a === undefined ? "undefined" : (a === null ? "null" : String(a)))
}
return out.join(" ")
}
function d() { console.debug(format(arguments)) }
function i() { console.info(format(arguments)) }
function w() { console.warn(format(arguments)) }
function e() { console.error(format(arguments)) }
}
@@ -1,62 +0,0 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
// Noctalia compat shim. Their plugins read Settings.data.* and call
// Settings.getBarPositionForScreen / getBarWidgetsForScreen. We expose a
// read-only view of our shell.json so reads succeed; writes are best routed
// through pluginApi.saveSettings() instead.
QtObject {
id: root
property var data: ({
bar: {
position: "top",
widgets: { left: [], center: [], right: [] }
},
general: {},
colorSchemes: { darkMode: true }
})
// Plugins use this gate around verbose debug logging. Defaulting to false
// keeps their Logger.d calls silent unless we explicitly flip it.
property bool isDebug: false
// shellConfig is wired by shell.qml at startup; reading it keeps Settings.data
// in lockstep with the live shell config.
property var shellConfig: null
onShellConfigChanged: rebuildData()
function rebuildData() {
var sc = shellConfig || {}
var bar = (sc && sc.bar) ? sc.bar : {}
var layout = (bar && bar.layout) ? bar.layout : {}
data = {
bar: {
position: bar.position || "top",
centerAnchor: bar.centerAnchor || "",
fontFamily: bar.fontFamily || "JetBrainsMono Nerd Font",
widgets: {
left: Array.isArray(layout.left) ? layout.left : [],
center: Array.isArray(layout.center) ? layout.center : [],
right: Array.isArray(layout.right) ? layout.right : []
}
},
general: {},
colorSchemes: { darkMode: true }
}
}
function getBarPositionForScreen(name) {
return data && data.bar ? data.bar.position : "top"
}
function getBarWidgetsForScreen(name) {
return data && data.bar ? data.bar.widgets : { left: [], center: [], right: [] }
}
function getScreenOverrideEntry(name) { return null }
function hasScreenOverride(name, key) { return false }
function setScreenOverride(name, key, value) { /* not supported */ }
}
@@ -1,12 +0,0 @@
pragma Singleton
import QtQuick
// Noctalia compat shim. Their plugins occasionally introspect global UI
// state through this singleton. Returning safe defaults lets reads succeed
// without us tracking the state ourselves.
QtObject {
readonly property bool isLoaded: true
property var activeScreen: null
property bool launcherOpen: false
property bool settingsOpen: false
}
@@ -1,104 +0,0 @@
pragma Singleton
import QtQuick
import "." as Commons
// Noctalia compat shim. Sizing/spacing/typography tokens that plugins
// reference unconditionally. Real values picked to roughly match what
// Omarchy renders today — close enough that plugin layouts don't look
// jarring next to native widgets.
QtObject {
id: root
// Radii. Omarchy uses sharp corners; all radius tokens collapse to 0 so
// Noctalia plugins inherit the same look as native widgets.
readonly property real radiusXXS: 0
readonly property real radiusXS: 0
readonly property real radiusS: 0
readonly property real radiusM: 0
readonly property real radiusL: 0
readonly property real radiusXL: 0
readonly property real iRadiusXS: 0
readonly property real iRadiusS: 0
readonly property real iRadiusM: 0
readonly property real iRadiusL: 0
// Margins / paddings. Noctalia uses two parallel scales for margins (one
// tighter, one looser); we map them to the same values.
readonly property real marginXXS: 1
readonly property real marginXS: 2
readonly property real marginS: 4
readonly property real marginM: 6
readonly property real marginL: 10
readonly property real marginXL: 14
readonly property real margin2XXS: 1
readonly property real margin2XS: 2
readonly property real margin2S: 3
readonly property real margin2M: 5
readonly property real margin2L: 8
readonly property real margin2XL: 12
// Border widths.
readonly property real borderS: 1
readonly property real borderM: 1
readonly property real borderL: 2
// Font sizes.
readonly property real fontSizeXXS: 9
readonly property real fontSizeXS: 10
readonly property real fontSizeS: 11
readonly property real fontSizeM: 12
readonly property real fontSizeL: 14
readonly property real fontSizeXL: 16
readonly property real fontSizeXXL: 20
readonly property real fontSizeXXXL: 24
// Font weights.
readonly property int fontWeightLight: 300
readonly property int fontWeightRegular: 400
readonly property int fontWeightMedium: 500
readonly property int fontWeightSemiBold: 600
readonly property int fontWeightBold: 700
// Opacities.
readonly property real opacityLight: 0.4
readonly property real opacityMedium: 0.6
readonly property real opacityHeavy: 0.8
readonly property real opacityFull: 1.0
// Animation durations (ms).
readonly property int animationFast: 100
readonly property int animationNormal: 160
readonly property int animationSlow: 250
readonly property int animationSlower: 400
readonly property int animationSlowest: 600
// Tooltip delay (ms).
readonly property int tooltipDelay: 400
// Capsule (bar pill) tokens. The Omarchy bar is flat, no capsule background,
// so we route these to transparent + the foreground outline for visual hint.
readonly property color capsuleColor: Qt.rgba(0, 0, 0, 0)
readonly property color capsuleBorderColor: Qt.rgba(0, 0, 0, 0)
readonly property real capsuleBorderWidth: 0
readonly property real baseWidgetSize: 22
// UI scale ratio. Noctalia plugins multiply lengths by this when
// applyUiScale is true; we leave it at 1.
readonly property real uiScaleRatio: 1.0
// Helpers. Plugins pass screen names but in practice we ignore them and
// return our shell-wide values.
function getBarHeightForScreen(name) { return 28 }
function getCapsuleHeightForScreen(name) { return 22 }
function getBarFontSizeForScreen(name) { return fontSizeM }
function getBarRadiusForScreen(name) { return radiusM }
function pixelAlignCenter(parentSize, childSize) {
return Math.round((Number(parentSize) - Number(childSize)) / 2)
}
function toOdd(n) {
var i = Math.floor(Number(n))
return i | 1
}
}
@@ -1,10 +0,0 @@
pragma Singleton
import QtQuick
// Noctalia compat shim. Their plugins resolve app icons through XDG icon
// themes; we don't ship that machinery, so iconForAppId returns empty and
// callers fall back to their default glyph.
QtObject {
function iconFromName(name) { return "" }
function iconForAppId(appId) { return "" }
}
@@ -1,18 +0,0 @@
pragma Singleton
import QtQuick
// Noctalia compat shim.
QtObject {
function getFormattedTimestamp() {
return new Date().toISOString()
}
function nowMs() {
return Date.now()
}
function formatDate(date, fmt) {
if (!date) date = new Date()
return Qt.formatDateTime(date, fmt || "yyyy-MM-dd HH:mm:ss")
}
}
@@ -1,10 +1,2 @@
module qs.Commons
singleton Color 1.0 Color.qml
singleton Style 1.0 Style.qml
singleton Logger 1.0 Logger.qml
singleton Settings 1.0 Settings.qml
singleton I18n 1.0 I18n.qml
singleton Time 1.0 Time.qml
singleton Icons 1.0 Icons.qml
singleton ThemeIcons 1.0 ThemeIcons.qml
singleton ShellState 1.0 ShellState.qml