Deskmeter OS Integration
Display your current deskmeter task using GNOME Shell extension or standalone GTK window.
Location: dmos/ (OS-specific components)
Quick Start
GTK Task Window (Immediate - No logout)
# Run with auto port detection
python3 dmos/task_window.py
# Make it always-on-top
wmctrl -r "Deskmeter Task" -b add,above,sticky
GNOME Extension (Requires logout)
cd dmos/gnome-extension
./install.sh
# Enable extension
gnome-extensions enable deskmeter-indicator@local
# Log out and back in (required on Wayland)
Components
1. GTK Task Window (dmos/task_window.py)
Standalone GTK4 window showing current task, always-on-top and visible on all workspaces.
Features:
- No window decorations (minimal UI)
- Updates every 500ms
- Workspace change detection (updates 2.2s after switch)
- Auto port detection (tries 10001, then 10000)
Usage:
# Auto-detect port
python3 dmos/task_window.py
# Specify port
python3 dmos/task_window.py 10001
# Or via environment
DESKMETER_PORT=10001 python3 dmos/task_window.py
Window States:
Loading...- Initial statework/default- Current task pathoffline - dmweb not running(red) - Cannot connecterror - invalid API response(orange) - Invalid JSONno task- Valid response, no task set
Close:
Alt+F4pkill -f task_window.py
2. GNOME Extension (dmos/gnome-extension/)
Panel indicator integrated into GNOME Shell top bar.
Features:
- Native panel integration (left side)
- Workspace switch detection with 2.2s debounce
- Auto port detection (10001, 10000)
- Error handling (won't crash GNOME Shell)
- Auto-truncates long paths (shows
.../last/two)
Files:
extension.js- Main extension codemetadata.json- Extension metadata (GNOME 40-49)stylesheet.css- Panel styling
Installation:
cd dmos/gnome-extension
./install.sh # First install
# OR
./update.sh # After code changes
# Restart GNOME Shell:
# X11: Alt+F2 → 'r' → Enter
# Wayland: Log out and back in
Check Status:
# List enabled extensions
gnome-extensions list --enabled | grep deskmeter
# View logs
journalctl --user -u org.gnome.Shell@wayland.service -f | grep deskmeter
# Debug with Looking Glass
# Alt+F2 → 'lg' → Extensions tab
Port Auto-Detection
Both components automatically detect dmweb port:
Priority Order:
- Command line argument (window only)
- Environment variable
DESKMETER_PORT(window only) - Auto-detection: tries 10001, then 10000
Test Ports:
curl http://localhost:10001/api/current_task
curl http://localhost:10000/api/current_task
Configure Ports:
# In dmos/task_window.py (line 36)
DEFAULT_PORTS = [10001, 10000]
// In dmos/gnome-extension/deskmeter-indicator@local/extension.js (line 11)
const DEFAULT_PORTS = [10001, 10000];
Requirements
Both Components
- dmweb Flask server running (
cd dmapp/dmweb && python3 run.py) /api/current_taskendpoint accessible
GTK Window
- Python 3 with GTK4:
sudo apt install python3-gi gir1.2-gtk-4.0 - wmctrl:
sudo apt install wmctrl
GNOME Extension
- GNOME Shell 40-49
- Works on X11 and Wayland
Troubleshooting
dmweb Not Running
# Check if dmweb is running
ps aux | grep dmweb
# Check listening ports
ss -tlnp | grep -E "(10000|10001)"
# Start dmweb
cd dmapp/dmweb
python3 run.py
# Test API
curl http://localhost:10000/api/current_task
# Expected: {"task_id":"abc12345","task_path":"work/default"}
GTK Window Issues
"offline - dmweb not running":
- Start dmweb (see above)
Window not staying on top:
wmctrl -r "Deskmeter Task" -b add,above,sticky
GTK4 not found:
sudo apt install python3-gi gir1.2-gtk-4.0
Window doesn't update on workspace change:
# Test wmctrl
wmctrl -d
# Should show workspaces with * marking current
GNOME Extension Issues
Extension not showing in panel:
# Check if enabled
gnome-extensions list --enabled | grep deskmeter
# Re-enable
gnome-extensions enable deskmeter-indicator@local
# View errors
journalctl --user -u org.gnome.Shell@wayland.service --since "5 minutes ago" | grep -i deskmeter
Shows "detecting..." forever:
- dmweb not running on 10001 or 10000
- Start dmweb and log out/in
Shows "offline":
# Test API endpoint
curl http://localhost:10000/api/current_task
# Check dmweb logs for errors
Changes not appearing after update:
- Ensure
./update.shran successfully - Must restart GNOME Shell (X11) or logout/login (Wayland)
- Check logs:
journalctl -f -o cat /usr/bin/gnome-shell
Comparison: Window vs Extension
| Feature | GTK Window | GNOME Extension |
|---|---|---|
| Visibility | Separate window | Panel indicator |
| Screen space | Takes window space | Minimal (panel) |
| Setup | Run anytime | Requires logout |
| Restart needed | No | Yes (Wayland) |
| All workspaces | ✅ (sticky) | ✅ (panel) |
| Integration | Standalone | Native GNOME |
Use GTK window for:
- Quick testing
- No logout required
- Temporary usage
Use GNOME extension for:
- Permanent setup
- Cleaner integration
- Less screen clutter
Configuration
GTK Window Settings
Edit dmos/task_window.py:
# Update frequency (line 37)
UPDATE_INTERVAL = 2000 # milliseconds
# Workspace check frequency (line 38)
WORKSPACE_CHECK_INTERVAL = 200 # milliseconds
# Window size (line ~50)
self.set_default_size(400, 60) # width x height
# Font size (line ~27)
self.label.set_markup('<span font_desc="14">Loading...</span>')
GNOME Extension Settings
Edit dmos/gnome-extension/deskmeter-indicator@local/extension.js:
// Debounce delay (line 10)
const DEBOUNCE_DELAY = 2200; // milliseconds
// Port list (line 11)
const DEFAULT_PORTS = [10001, 10000];
// Update interval (line 12)
const UPDATE_INTERVAL = 30000; // 30 seconds
Auto-start (Optional)
GTK Window on Login
# Create desktop entry
cat > ~/.config/autostart/deskmeter-task-window.desktop <<EOF
[Desktop Entry]
Type=Application
Name=Deskmeter Task Window
Exec=/home/mariano/wdir/dm/dmos/task_window.py
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
EOF
GNOME Extension
Enabled extensions auto-start with GNOME Shell. Just ensure it's enabled:
gnome-extensions enable deskmeter-indicator@local
Files Structure
dmos/
├── gnome-extension/
│ ├── deskmeter-indicator@local/
│ │ ├── extension.js # Main extension code
│ │ ├── metadata.json # GNOME metadata
│ │ ├── stylesheet.css # Panel styling
│ │ └── deskmeter-indicator@local.zip # Packaged extension
│ ├── install.sh # Initial installation
│ └── update.sh # Update after changes
└── task_window.py # GTK4 window app
Testing Checklist
GTK Window
- Window appears without decorations
- Shows current task path
- Can be moved/positioned
- Closes with Alt+F4
- Updates on workspace change (~2s delay)
- Can set always-on-top with wmctrl
- Auto-detects port (check console)
GNOME Extension
- Shows in panel (left side)
- Displays current task
- Updates on workspace switch (~2s delay)
- Doesn't crash GNOME Shell if dmweb offline
- Can disable:
gnome-extensions disable deskmeter-indicator@local - Truncates long paths correctly
Performance
GTK Window
- Workspace checks: 200ms interval (lightweight wmctrl)
- Task updates: 2000ms interval
- Post-switch delay: 2200ms (allows dmcore to update)
- CPU usage: ~0.1-0.2%
GNOME Extension
- Event-driven (workspace switches)
- Periodic refresh: 30s
- Debounce delay: 2200ms
- Minimal overhead (GNOME Shell event loop)
Development
Updating Extension
cd dmos/gnome-extension
# 1. Edit extension.js, metadata.json, or stylesheet.css
# 2. Update installed version
./update.sh
# 3. Restart GNOME Shell
# X11: Alt+F2 → 'r' → Enter
# Wayland: Log out and back in
# 4. Check logs for errors
journalctl -f -o cat /usr/bin/gnome-shell | grep deskmeter
Updating Window
# 1. Edit dmos/task_window.py
# 2. Kill running instance
pkill -f task_window.py
# 3. Run updated version
python3 dmos/task_window.py
API Endpoint
Both components use the same endpoint:
URL: http://localhost:{PORT}/api/current_task
Response:
{
"task_id": "abc12345",
"task_path": "work/default"
}
Error Handling:
- Connection refused → "offline"
- Invalid JSON → "error"
- Missing task_path → "no task"
Need Help?
- Start dmweb:
cd dmapp/dmweb && python3 run.py - Test API:
curl http://localhost:10000/api/current_task - Try window first:
python3 dmos/task_window.py(no logout) - Check logs:
journalctlfor extension, console for window - Verify ports:
ss -tlnp | grep -E "(10000|10001)"
Ready to test! Start with the GTK window for immediate feedback, then try the extension for permanent integration.