EDIT: Whole post has been edited to add the new really functional version.
So I recently installed i3wm in my Qubes desktop because it feels better for me.
I've coded a bash script to help me organize the rofi menu, because dmenu sucks for me.
In dom0:
- Install rofi in dom0 with sudo qubes-dom0-update rofi
- Create the folder ~/.config/rofi
- Create the file rofi_qubes_os_menu.sh inside with this content:
#!/bin/bash
app_menu () {
qube_name="$1"
running_status="$2"
last_qube_menu="$3"
# Create an option to boot/shutdown/kill VM
if [ "$running_status" = "bold" ]; then
change_status_option='Shutdown\nKill'
else
change_status_option='Power on'
fi
# Rebuild the name format used by the .desktop files
qube=$(echo "$qube_name" | sed -r 's/-/_d/g')
# Get the name of available apps
apps=$(grep -h "^Name=" ~/.local/share/applications/org.qubes-os.vm._$qube.* | sed 's/^Name=//')
# Let the user select the app. Also, make a settings option available
chosen=$(echo -e "Back\n$apps\n$change_status_option\nSettings" | rofi -dmenu -p "$1 - Select app")
if [ "$chosen" = "Back" ]; then
show_qubes "$last_qube_menu"
elif [ "$chosen" = "Power on" ]; then
qvm-start $qube_name
elif [ "$chosen" = "Shutdown" ]; then
qvm-shutdown $qube_name
elif [ "$chosen" = "Kill" ]; then
qvm-kill $qube_name
elif [ "$chosen" = "Settings" ]; then
exo-open ~/.local/share/applications/org.qubes-os.qubes-vm-settings._$qube.desktop
else
$(grep -h "^Exec=" $(grep -rl "^Name=$chosen" ~/.local/share/applications/org.qubes-os.vm._$qube.* | head -n1) | sed 's/^Exec=//')
fi
}
show_qubes () {
# Get a list of all available qubes VMs
options=$(qvm-ls --fields NAME,STATE,CLASS,LABEL,PROVIDES_NETWORK --raw-data | grep "$1" | \
while IFS='|' read -r name state class label net; do
if [ "$state" = "Halted" ]; then
is_running_weight="normal"
is_running_icon="\U25C9"
else
is_running_weight="bold"
is_running_icon="\U25CF"
fi
echo -e "<span>$is_running_icon </span><span>$name</span>"
done)
chosen=$(echo -e "<span>Back</span>\n$options" | rofi -dmenu -markup-rows -p "Select qube")
# Depending on the chosen one, do things
if [ "$chosen" = "<span>Back</span>" ]; then
main_menu
else
app_menu $(echo -e "$chosen" | cut -d '>' -f 4 | cut -d '<' -f 1) $(echo -e "$chosen" | cut -d "'" -f 4) "$1"
fi
}
disp_app_menu () {
# Rebuild the name format used by the .desktop files
qube=$(echo "$1" | sed -r 's/-/_d/g')
# Get the name of available apps
apps=$(grep -h "^Name=" ~/.local/share/applications/org.qubes-os.dispvm._$qube.* | sed 's/^Name=//')
# Let the user select the app. Also, make a settings option available
chosen=$(echo -e "Back\n$apps\nSettings" | rofi -dmenu -p "$1 - Select app")
if [[ "$chosen" = "Back" ]]; then
show_disp
elif [[ "$chosen" = "Settings" ]]; then
exo-open ~/.local/share/applications/org.qubes-os.qubes-vm-settings._$qube.desktop
else
$(grep -h "^Exec=" $(grep -rl "^Name=$chosen" ~/.local/share/applications/org.qubes-os.dispvm._$qube.* | head -n1) | sed 's/^Exec=//')
fi
}
show_disp () {
# Get a list of all available AppVMs that do not provide network (candidates for Diposable VMs)
options=$(qvm-ls --fields NAME,CLASS,LABEL,PROVIDES_NETWORK --raw-data | grep "|AppVM|.*|False$" | \
while IFS='|' read -r name class label net; do
is_disposable=$(qvm-prefs "$name" template_for_dispvms 2>/dev/null)
if [ "$is_disposable" = "True" ]; then
echo -e "<span>\U25CF </span><span>$name</span>"
fi
done)
chosen=$(echo -e "<span>Back</span>\n$options" | rofi -dmenu -markup-rows -p "Select qube")
# Depending on the chosen one, do things
if [ "$chosen" = "<span>Back</span>" ]; then
main_menu
else
disp_app_menu $(echo -e "$chosen" | cut -d '>' -f 4 | cut -d '<' -f 1)
fi
}
dom0_menu () {
# Get the name of available apps
apps=$(grep -h "^Name=" /usr/share/applications/* | sed 's/^Name=//')
# Let the user select the app. Also, make a settings option available
chosen=$(echo -e "Back\n$apps" | rofi -dmenu -p "dom0 - Select app")
if [ "$chosen" = "Back" ]; then
main_menu
else
$(grep -h "^Exec=" $(grep -rl "^Name=$chosen" /usr/share/applications/ | head -n1) | sed 's/^Exec=//')
fi
}
main_menu () {
chosen=$(echo -e "Exit\nApp VMs\nActive Disposable VMs\nSpawn disposable VM\nStandalone VMs\nTemplates\nServices\ndom0" | rofi -dmenu -markup-rows -p "Select option")
if [ "$chosen" = "Exit" ]; then
exit
elif [ "$chosen" = "dom0" ]; then
dom0_menu
elif [ "$chosen" = "Services" ]; then
show_qubes '|True$'
elif [ "$chosen" = "Templates" ]; then
show_qubes '|TemplateVM|.*|False$'
elif [ "$chosen" = "Standalone VMs" ]; then
show_qubes '|StandaloneVM|.*|False$'
elif [ "$chosen" = "Active Disposable VMs" ]; then
show_qubes '|DispVM|.*|False$'
elif [ "$chosen" = "Spawn disposable VM" ]; then
show_disp
elif [ "$chosen" = "App VMs" ]; then
show_qubes '|AppVM|.*|False$'
# User presses Esc or clicks away
#elif [ $? -eq 1 ]; then
# exit
fi
}
main_menu
~/.config/i3/config to launch rofi (or replace the one used by dmenu). Example: bindsym $mod+d exec --no-startup-id ~/.config/rofi/rofi_qubes_os_menu.shNow everything works perfectly. It's only left to do this things: - If user presses "Esc": go back to the previous section