Pop Launcher
Modular IPC-based desktop launcher service, written in Rust. Desktop launchers may interface with this service via spawning the pop-launcher process and communicating to it via JSON IPC over the stdin and stdout pipes. The launcher service will also spawn plugins found in plugin directories on demand, based on the queries sent to the service.
Using IPC enables each plugin to isolate their data from other plugin processes and frontends that are interacting with them. If a plugin crashes, the launcher will continue functioning normally, gracefully cleaning up after the crashed process. Frontends and plugins may also be written in any language. The pop-launcher will do its part to schedule the execution of these plugins in parallel, on demand.
Plugin Directories
- User-local plugins:
~/.local/share/pop-launcher/plugins/{plugin}/
- System-wide install for system administrators:
/etc/pop-launcher/plugins/{plugin}/
- Distribution packaging:
/usr/lib/pop-launcher/plugins/{plugin}/
Plugin Config
A plugin's metadata is defined pop-launcher/plugins/{plugin}/plugin.ron
.
(
name: "PluginName",
description: "Plugin Description: Example",
bin: (
path: "name-of-executable-in-plugin-folder",
)
icon: Name("icon-name-or-path"),
// Optional
query: (
// Optional -- if we should isolate this plugin when the regex matches
isolate: true,
// Optional -- Plugin which searches on empty queries
persistent: true,
// Optional -- avoid sorting results from this plugin
no_sort: true,
// Optional -- pattern that a query must have to be sent to plugin
regex: "pattern"
)
)
Script Directories
- User-local scripts:
~/.local/share/pop-launcher/scripts
- System-wide install for system administrators:
/etc/pop-launcher/scripts
- Distribution packaging:
/usr/lib/pop-launcher/scripts
Example script
nmcli connection up "vpn-name"
JSON IPC
Whether implementing a frontend or a plugin, the JSON codec used by pop-launcher is line-based. Every line will contain a single JSON message That will be serialized or decoded as a Request
, PluginResponse
, or Response
. These types can be referenced in docs.rs. IPC is based on standard input/output streams, so you should take care not to write logs to stdout.
Frontend JSON IPC
The frontend will send Request
s to the pop-launcher service through the stdin pipe. The stdout pipe will respond with Response
s. It is ideal to design your frontend to accept responses asynchronously. Sending Interrupt
or Search
will cancel any active searches being performed, if the plugins that are still actively searching support cancellation.
Plugin JSON IPC
Plugins will receive Request
s from pop-launcher through their stdin pipe. They should respond with PluginResponse
messages.
Request
If you are writing a frontend, you are sending these events to the pop-launcher stdin pipe. If you are writing a plugin, the plugin will be receiving these events from its stdin.
JSON Equivalent
{ "Activate": number }
{ "ActivateContext": { "id": number, "context": id }}
{ "Complete": number }
{ "Context": number }
"Exit"
"Interrupt"
{ "Quit": number }
{ "Search": string }
PluginResponse
If you are writing a plugin, you should send these events to your stdout.
JSON Equivalent
{ "Append": PluginSearchResult }
,"Clear"
,"Close"
,{ "Context": { "id": number, "options": Array<ContextOption> }}
{ "DesktopEntry": { "path": string, "gpu_preference": GpuPreference }}
{ "Fill": string }
"Finished"
Where PluginSearchResult
is:
{
id: number,
name: string,
description: string,
keywords?: Array<string>,
icon?: IconSource,
exec?: string,
window?: [number, number],
}
ContextOption
is:
{
id: number,
name: string
}
GpuPreference
is:
"Default" | "NonDefault"
And IconSource
is either:
{ "Name": string }
, where the name is a system icon, or an icon referred to by path{ "Mime": string }
, where the mime is a mime essence string, to display file-based icons
Response
Those implementing frontends should listen for these events:
JSON Equivalent
"Close"
{ "DesktopEntry": string }
{ "Update": Array<SearchResult>}
{ "Fill": string }
Where SearchResult
is:
{
id: number,
name: string,
description: string,
icon?: IconSource,
category_icon?: IconSource,
window?: [number, number]
}