- Add support for using material icons on launcher items (for plugins) - Allow plugins to omit icons - Update plugin docs - add developer note so the next one working on launcher will not spend hours debugging the wrong place as I just did :)
LauncherExample Plugin
A demonstration plugin that showcases the DMS launcher plugin system capabilities.
Purpose
This plugin serves as a comprehensive example for developers creating launcher plugins for DMS. It demonstrates:
- Plugin Structure: Proper manifest, launcher, and settings components
- Trigger System: Customizable trigger strings for plugin activation (including empty triggers)
- Item Management: Providing searchable items to the launcher
- Action Execution: Handling different types of actions (toast, copy, script)
- Settings Integration: Configurable plugin settings with persistence
Features
Example Items
- Test Items 1-3: Demonstrate toast notifications
- Copy Action: Shows clipboard integration
- Script Action: Demonstrates command execution
Trigger System
- Default Trigger:
#(configurable in settings) - Empty Trigger Option: Items can always be visible without needing a trigger
- Usage: Type
#in launcher to filter to this plugin (when trigger is set) - Search: Type
# testto search within plugin items
Action Types
toast:message- Shows toast notificationcopy:text- Copies text to clipboardscript:command- Executes shell command (demo only)
File Structure
PLUGINS/LauncherExample/
├── plugin.json # Plugin manifest
├── LauncherExampleLauncher.qml # Main launcher component
├── LauncherExampleSettings.qml # Settings interface
└── README.md # This documentation
Installation
- Plugin Directory: Copy to
~/.config/DankMaterialShell/plugins/LauncherExample - Enable Plugin: Settings → Plugins → Enable "LauncherExample"
- Configure: Set custom trigger in plugin settings if desired
Usage
With Trigger (Default)
- Open launcher (Ctrl+Space or launcher button)
- Type
#to activate plugin trigger - Browse available items or add search terms
- Press Enter to execute selected item
Without Trigger (Empty Trigger Mode)
- Enable "No trigger (always show)" in plugin settings
- Open launcher - plugin items are always visible
- Search works normally with plugin items included
- Press Enter to execute selected item
Search Examples
#- Show all plugin items (with trigger enabled)# test- Show items matching "test"# copy- Show items matching "copy"test- Show all items matching "test" (with empty trigger enabled)
Developer Guide
Plugin Contract
Launcher Component Requirements:
// Required properties
property var pluginService: null
property string trigger: "#"
// Required signals
signal itemsChanged()
// Required functions
function getItems(query): array
function executeItem(item): void
Item Structure:
{
name: "Item Name", // Display name
icon: "icon_name", // Icon (optional, see Icon Types below)
comment: "Description", // Subtitle text
action: "type:data", // Action to execute
categories: ["PluginName"] // Category array
}
Icon Types:
The icon field supports three formats:
-
Material Design Icons - Use
material:prefix:icon: "material:lightbulb" // Material Symbols Rounded fontExamples:
material:star,material:favorite,material:settings -
Desktop Theme Icons - Use icon name directly:
icon: "firefox" // Uses system icon themeExamples:
firefox,chrome,folder,text-editor -
No Icon - Omit the
iconfield entirely:{ name: "😀 Grinning Face", // No icon field comment: "Copy emoji", action: "copy:😀", categories: ["MyPlugin"] }Perfect for emoji pickers or text-only items where the icon area should be hidden
Action Format: type:data where:
type- Action handler (toast, copy, script, etc.)data- Action-specific data
Settings Integration
// Save setting
pluginService.savePluginData("pluginId", "key", value)
// Load setting
pluginService.loadPluginData("pluginId", "key", defaultValue)
Trigger Configuration
The trigger can be configured in two ways:
-
Empty Trigger (No Trigger Mode):
- Check "No trigger (always show)" in settings
- Saves
trigger: ""andnoTrigger: true - Items always appear in launcher alongside regular apps
-
Custom Trigger:
- Enter any string (e.g.,
#,!,@,!ex) - Uncheck "No trigger" checkbox
- Items only appear when trigger is typed
- Enter any string (e.g.,
Manifest Structure
{
"id": "launcherExample",
"name": "LauncherExample",
"type": "launcher",
"capabilities": ["launcher"],
"component": "./LauncherExampleLauncher.qml",
"settings": "./LauncherExampleSettings.qml",
"permissions": ["settings_read", "settings_write"]
}
Note: The trigger field in the manifest is optional and serves as the default trigger value.
Extending This Plugin
Adding New Items
function getItems(query) {
return [
{
name: "My Item",
icon: "custom_icon",
comment: "Does something cool",
action: "custom:action_data",
categories: ["LauncherExample"]
}
]
}
Adding New Actions
function executeItem(item) {
const actionParts = item.action.split(":")
const actionType = actionParts[0]
const actionData = actionParts.slice(1).join(":")
switch (actionType) {
case "custom":
handleCustomAction(actionData)
break
}
}
Custom Trigger Logic
Component.onCompleted: {
if (pluginService) {
trigger = pluginService.loadPluginData("launcherExample", "trigger", "#")
}
}
onTriggerChanged: {
if (pluginService) {
pluginService.savePluginData("launcherExample", "trigger", trigger)
}
}
Best Practices
- Unique Triggers: Choose triggers that don't conflict with other plugins
- Clear Descriptions: Write helpful item comments
- Error Handling: Gracefully handle action failures
- Performance: Return results quickly in getItems()
- Cleanup: Destroy temporary objects in executeItem()
- Empty Trigger Support: Consider if your plugin should support empty trigger mode
Testing
Test the plugin by:
- Installing and enabling in DMS
- Testing with trigger enabled
- Testing with empty trigger (no trigger mode)
- Trying each action type
- Testing search functionality
- Verifying settings persistence
This plugin provides a solid foundation for building more sophisticated launcher plugins with custom functionality!