mirror of
https://github.com/edu4rdshl/Strata.git
synced 2026-07-17 23:24:46 +00:00
fix: rename D-Bus name to dev.edu4rdshl.Strata; drop recursive theme reload
Two changes for 0.7.0: BREAKING (D-Bus): the service is renamed from org.gnome.Strata to dev.edu4rdshl.Strata. The org.gnome.* namespace is reserved for official GNOME software; Strata is third-party, so it now uses the reverse-DNS of its own domain (matching the strata@edu4rdshl.dev UUID). Bus name, object path (/dev/edu4rdshl/Strata), and interface (dev.edu4rdshl.Strata.Manager) all change. Daemon and extension are updated together; only external busctl scripts / non-GNOME front-ends that hard-coded the old name need updating. The GSettings schema (org.gnome.shell.extensions.strata) is unchanged - that namespace is correct for GNOME Shell extension settings. Fix recursion: the theme-context 'changed' handler reloaded light.css, but load_stylesheet itself emits 'changed', so it fed back into itself and hit "too much recursion" - flooding the journal and spinning the CPU on screen unlock (which restyles widgets and fires 'changed'). The subscription is removed; light.css is loaded once. Dark/light switching is unaffected (it is the panel's class toggle, not this load). A GNOME Shell theme switch no longer auto-re-applies the sheet, which is recoverable by re-enabling. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
3f32c19fd0
commit
b41c9662cb
8 changed files with 40 additions and 44 deletions
|
|
@ -72,7 +72,7 @@ ssh fedoradev 'glib-compile-schemas ~/.local/share/gnome-shell/extensions/strata
|
||||||
|
|
||||||
## D-Bus interface summary
|
## D-Bus interface summary
|
||||||
|
|
||||||
Service `org.gnome.Strata`, object `/org/gnome/Strata`, interface `org.gnome.Strata.Manager`.
|
Service `dev.edu4rdshl.Strata`, object `/dev/edu4rdshl/Strata`, interface `dev.edu4rdshl.Strata.Manager`.
|
||||||
|
|
||||||
Methods: `GetHistory(offset u32, limit u32) -> json s`,
|
Methods: `GetHistory(offset u32, limit u32) -> json s`,
|
||||||
`SearchHistory(query s, limit u32) -> json s`,
|
`SearchHistory(query s, limit u32) -> json s`,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ together and the trade-offs at each layer.
|
||||||
| | ItemAdded / ItemDeleted / HistoryCleared |
|
| | ItemAdded / ItemDeleted / HistoryCleared |
|
||||||
+--------+-------------------------------------------------------------------------+
|
+--------+-------------------------------------------------------------------------+
|
||||||
|
|
|
|
||||||
| session D-Bus (org.gnome.Strata)
|
| session D-Bus (dev.edu4rdshl.Strata)
|
||||||
v
|
v
|
||||||
+----------------------- strata-daemon (Rust process) --------------------------+
|
+----------------------- strata-daemon (Rust process) --------------------------+
|
||||||
| |
|
| |
|
||||||
|
|
@ -68,7 +68,7 @@ hot ingest path (it fires `SubmitItem` and returns immediately).
|
||||||
### Startup
|
### Startup
|
||||||
|
|
||||||
The extension listens for `notify::g-name-owner` on the D-Bus proxy. When
|
The extension listens for `notify::g-name-owner` on the D-Bus proxy. When
|
||||||
the daemon's `org.gnome.Strata` name becomes owned, the panel triggers
|
the daemon's `dev.edu4rdshl.Strata` name becomes owned, the panel triggers
|
||||||
its initial fetch. No polling, no fixed delays.
|
its initial fetch. No polling, no fixed delays.
|
||||||
|
|
||||||
## Ingest path
|
## Ingest path
|
||||||
|
|
@ -313,7 +313,7 @@ and it is small and isolated.
|
||||||
| App to history | Password leak | `x-kde-passwordManagerHint` opt-out |
|
| App to history | Password leak | `x-kde-passwordManagerHint` opt-out |
|
||||||
| User to search | SQL injection | rusqlite `params![]`, FTS5 input bound as value |
|
| User to search | SQL injection | rusqlite `params![]`, FTS5 input bound as value |
|
||||||
| Daemon to FS | Path traversal via id | Ids are server-generated UUID v4 |
|
| Daemon to FS | Path traversal via id | Ids are server-generated UUID v4 |
|
||||||
| Daemon to extension | Signal spoofing | D-Bus enforces single owner of `org.gnome.Strata` |
|
| Daemon to extension | Signal spoofing | D-Bus enforces single owner of `dev.edu4rdshl.Strata` |
|
||||||
| Stored item to paste | Command execution | No spawn, no launch_uri, no markup parsing |
|
| Stored item to paste | Command execution | No spawn, no launch_uri, no markup parsing |
|
||||||
|
|
||||||
## Non-GNOME front-end
|
## Non-GNOME front-end
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ Strata is **two components**, and you need **both** for it to work:
|
||||||
|
|
||||||
| Component | Language | Role |
|
| Component | Language | Role |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| [`strata-daemon/`](strata-daemon/) | Rust + tokio + zbus | Storage (SQLite + FTS5), dedup, thumbnails, D-Bus service `org.gnome.Strata` |
|
| [`strata-daemon/`](strata-daemon/) | Rust + tokio + zbus | Storage (SQLite + FTS5), dedup, thumbnails, D-Bus service `dev.edu4rdshl.Strata` |
|
||||||
| [`strata@edu4rdshl.dev/`](strata@edu4rdshl.dev/) | GJS (GNOME Shell extension) | Top-bar panel, search UI, paste-back, clipboard ingest |
|
| [`strata@edu4rdshl.dev/`](strata@edu4rdshl.dev/) | GJS (GNOME Shell extension) | Top-bar panel, search UI, paste-back, clipboard ingest |
|
||||||
|
|
||||||
The extension auto-connects to the daemon on enable. If the daemon is managed
|
The extension auto-connects to the daemon on enable. If the daemon is managed
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ manually if you're using a non-GNOME front-end.
|
||||||
|
|
||||||
## D-Bus interface
|
## D-Bus interface
|
||||||
|
|
||||||
- **Bus name:** `org.gnome.Strata`
|
- **Bus name:** `dev.edu4rdshl.Strata`
|
||||||
- **Object path:** `/org/gnome/Strata`
|
- **Object path:** `/dev/edu4rdshl/Strata`
|
||||||
- **Interface:** `org.gnome.Strata.Manager`
|
- **Interface:** `dev.edu4rdshl.Strata.Manager`
|
||||||
|
|
||||||
| Member | Signature | Notes |
|
| Member | Signature | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
|
@ -51,15 +51,15 @@ manually if you're using a non-GNOME front-end.
|
||||||
./target/release/strata-daemon
|
./target/release/strata-daemon
|
||||||
|
|
||||||
# In another terminal:
|
# In another terminal:
|
||||||
busctl --user call org.gnome.Strata /org/gnome/Strata \
|
busctl --user call dev.edu4rdshl.Strata /dev/edu4rdshl/Strata \
|
||||||
org.gnome.Strata.Manager GetHistory uu 0 10
|
dev.edu4rdshl.Strata.Manager GetHistory uu 0 10
|
||||||
|
|
||||||
# Submit text:
|
# Submit text:
|
||||||
busctl --user call org.gnome.Strata /org/gnome/Strata \
|
busctl --user call dev.edu4rdshl.Strata /dev/edu4rdshl/Strata \
|
||||||
org.gnome.Strata.Manager SubmitItem say "text/plain;charset=utf-8" 5 104 101 108 108 111
|
dev.edu4rdshl.Strata.Manager SubmitItem say "text/plain;charset=utf-8" 5 104 101 108 108 111
|
||||||
|
|
||||||
# Listen for new items:
|
# Listen for new items:
|
||||||
busctl --user monitor org.gnome.Strata
|
busctl --user monitor dev.edu4rdshl.Strata
|
||||||
```
|
```
|
||||||
|
|
||||||
## Supported clipboard payloads
|
## Supported clipboard payloads
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ pub struct StrataManager {
|
||||||
pub shutdown_tx: tokio::sync::mpsc::UnboundedSender<()>,
|
pub shutdown_tx: tokio::sync::mpsc::UnboundedSender<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interface(name = "org.gnome.Strata.Manager")]
|
#[interface(name = "dev.edu4rdshl.Strata.Manager")]
|
||||||
impl StrataManager {
|
impl StrataManager {
|
||||||
/// Called by the GJS extension when it detects a clipboard change via Meta.Selection.
|
/// Called by the GJS extension when it detects a clipboard change via Meta.Selection.
|
||||||
/// `content` is the raw bytes of the clipboard payload (D-Bus `ay`).
|
/// `content` is the raw bytes of the clipboard payload (D-Bus `ay`).
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ async fn main() -> Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let dbus_conn = zbus::connection::Builder::session()?
|
let dbus_conn = zbus::connection::Builder::session()?
|
||||||
.serve_at("/org/gnome/Strata", manager)?
|
.serve_at("/dev/edu4rdshl/Strata", manager)?
|
||||||
.build()
|
.build()
|
||||||
.await
|
.await
|
||||||
.context("Building D-Bus connection")?;
|
.context("Building D-Bus connection")?;
|
||||||
|
|
@ -61,14 +61,14 @@ async fn main() -> Result<()> {
|
||||||
// would be refused.
|
// would be refused.
|
||||||
dbus_conn
|
dbus_conn
|
||||||
.request_name_with_flags(
|
.request_name_with_flags(
|
||||||
"org.gnome.Strata",
|
"dev.edu4rdshl.Strata",
|
||||||
zbus::fdo::RequestNameFlags::ReplaceExisting
|
zbus::fdo::RequestNameFlags::ReplaceExisting
|
||||||
| zbus::fdo::RequestNameFlags::AllowReplacement,
|
| zbus::fdo::RequestNameFlags::AllowReplacement,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.context("Acquiring D-Bus name org.gnome.Strata")?;
|
.context("Acquiring D-Bus name dev.edu4rdshl.Strata")?;
|
||||||
|
|
||||||
tracing::info!("D-Bus service registered as org.gnome.Strata");
|
tracing::info!("D-Bus service registered as dev.edu4rdshl.Strata");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// Clipboard monitor (Wayland protocols - optional, soft-fail on GNOME).
|
// Clipboard monitor (Wayland protocols - optional, soft-fail on GNOME).
|
||||||
|
|
@ -312,7 +312,7 @@ async fn process_bytes(
|
||||||
if is_new {
|
if is_new {
|
||||||
let iface = conn
|
let iface = conn
|
||||||
.object_server()
|
.object_server()
|
||||||
.interface::<_, StrataManager>("/org/gnome/Strata")
|
.interface::<_, StrataManager>("/dev/edu4rdshl/Strata")
|
||||||
.await
|
.await
|
||||||
.context("Getting StrataManager interface ref")?;
|
.context("Getting StrataManager interface ref")?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import Gio from 'gi://Gio';
|
||||||
|
|
||||||
const STRATA_IFACE_XML = `
|
const STRATA_IFACE_XML = `
|
||||||
<node>
|
<node>
|
||||||
<interface name="org.gnome.Strata.Manager">
|
<interface name="dev.edu4rdshl.Strata.Manager">
|
||||||
|
|
||||||
<method name="GetHistory">
|
<method name="GetHistory">
|
||||||
<arg type="u" direction="in" name="offset"/>
|
<arg type="u" direction="in" name="offset"/>
|
||||||
|
|
@ -75,5 +75,5 @@ const STRATA_IFACE_XML = `
|
||||||
|
|
||||||
export const StrataProxy = Gio.DBusProxy.makeProxyWrapper(STRATA_IFACE_XML);
|
export const StrataProxy = Gio.DBusProxy.makeProxyWrapper(STRATA_IFACE_XML);
|
||||||
|
|
||||||
export const BUS_NAME = 'org.gnome.Strata';
|
export const BUS_NAME = 'dev.edu4rdshl.Strata';
|
||||||
export const OBJECT_PATH = '/org/gnome/Strata';
|
export const OBJECT_PATH = '/dev/edu4rdshl/Strata';
|
||||||
|
|
|
||||||
|
|
@ -440,7 +440,7 @@ export default class StrataExtension extends Extension {
|
||||||
_connectSignals() {
|
_connectSignals() {
|
||||||
this._itemAddedId = Gio.DBus.session.signal_subscribe(
|
this._itemAddedId = Gio.DBus.session.signal_subscribe(
|
||||||
BUS_NAME,
|
BUS_NAME,
|
||||||
'org.gnome.Strata.Manager',
|
'dev.edu4rdshl.Strata.Manager',
|
||||||
'ItemAdded',
|
'ItemAdded',
|
||||||
OBJECT_PATH,
|
OBJECT_PATH,
|
||||||
null,
|
null,
|
||||||
|
|
@ -450,7 +450,7 @@ export default class StrataExtension extends Extension {
|
||||||
|
|
||||||
this._itemDeletedId = Gio.DBus.session.signal_subscribe(
|
this._itemDeletedId = Gio.DBus.session.signal_subscribe(
|
||||||
BUS_NAME,
|
BUS_NAME,
|
||||||
'org.gnome.Strata.Manager',
|
'dev.edu4rdshl.Strata.Manager',
|
||||||
'ItemDeleted',
|
'ItemDeleted',
|
||||||
OBJECT_PATH,
|
OBJECT_PATH,
|
||||||
null,
|
null,
|
||||||
|
|
@ -473,7 +473,7 @@ export default class StrataExtension extends Extension {
|
||||||
|
|
||||||
this._historyClearedId = Gio.DBus.session.signal_subscribe(
|
this._historyClearedId = Gio.DBus.session.signal_subscribe(
|
||||||
BUS_NAME,
|
BUS_NAME,
|
||||||
'org.gnome.Strata.Manager',
|
'dev.edu4rdshl.Strata.Manager',
|
||||||
'HistoryCleared',
|
'HistoryCleared',
|
||||||
OBJECT_PATH,
|
OBJECT_PATH,
|
||||||
null,
|
null,
|
||||||
|
|
@ -600,22 +600,23 @@ export default class StrataExtension extends Extension {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Load light.css into the global St theme context. Scoped under
|
/** Load light.css into the global St theme context ONCE. It is scoped under
|
||||||
* `.strata-theme-light`, so it does nothing until the panel adds that
|
* `.strata-theme-light`, so it stays inert until the panel adds that class
|
||||||
* class. Reloaded on theme-context changes (a Shell-theme switch drops
|
* (dark/light switching is the panel's class toggle, independent of this).
|
||||||
* dynamically loaded stylesheets). */
|
*
|
||||||
|
* We deliberately do NOT subscribe to the theme context's 'changed'
|
||||||
|
* signal: load_stylesheet itself emits 'changed', so reloading on it feeds
|
||||||
|
* back into itself and hits "too much recursion" (it fired on screen
|
||||||
|
* unlock, which restyles widgets). The only thing a one-time load gives up
|
||||||
|
* is re-applying after a GNOME Shell *theme* switch (which replaces the
|
||||||
|
* St.Theme and drops this sheet) - a rare action, recoverable by toggling
|
||||||
|
* the extension. That trade is worth never touching the signal. */
|
||||||
_loadThemeStylesheet() {
|
_loadThemeStylesheet() {
|
||||||
try {
|
try {
|
||||||
const themeContext = St.ThemeContext.get_for_stage(global.stage);
|
const themeContext = St.ThemeContext.get_for_stage(global.stage);
|
||||||
this._lightCssFile = this.dir.get_child('light.css');
|
this._lightCssFile = this.dir.get_child('light.css');
|
||||||
themeContext.get_theme().load_stylesheet(this._lightCssFile);
|
this._stTheme = themeContext.get_theme();
|
||||||
this._stThemeChangedId = themeContext.connect('changed', () => {
|
this._stTheme.load_stylesheet(this._lightCssFile);
|
||||||
try {
|
|
||||||
themeContext.get_theme().load_stylesheet(this._lightCssFile);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('[Strata] light.css reload failed:', e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[Strata] Failed to load light.css:', e);
|
console.error('[Strata] Failed to load light.css:', e);
|
||||||
}
|
}
|
||||||
|
|
@ -623,16 +624,11 @@ export default class StrataExtension extends Extension {
|
||||||
|
|
||||||
_unloadThemeStylesheet() {
|
_unloadThemeStylesheet() {
|
||||||
try {
|
try {
|
||||||
const themeContext = St.ThemeContext.get_for_stage(global.stage);
|
this._stTheme?.unload_stylesheet(this._lightCssFile);
|
||||||
if (this._stThemeChangedId) {
|
|
||||||
themeContext.disconnect(this._stThemeChangedId);
|
|
||||||
this._stThemeChangedId = null;
|
|
||||||
}
|
|
||||||
if (this._lightCssFile)
|
|
||||||
themeContext.get_theme().unload_stylesheet(this._lightCssFile);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[Strata] Failed to unload light.css:', e);
|
console.error('[Strata] Failed to unload light.css:', e);
|
||||||
}
|
}
|
||||||
|
this._stTheme = null;
|
||||||
this._lightCssFile = null;
|
this._lightCssFile = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue