[download]

local/bin/hudmenu

   1 #!/bin/bash
   2 
   3 if [[ ! $1 ]]; then
   4     win=$(xprop -root _NET_ACTIVE_WINDOW | awk '{ print $5 }')
   5     win=${win%,}
   6 
   7     $0 $win | menu -i hud -l 15 | xargs -rI % $0 $win %
   8     exit
   9 fi
  10 
  11 ################################################################################
  12 
  13 subnum=({0..100})
  14 declare -A pids labels
  15 busname=$(xprop -id $1 _GTK_UNIQUE_BUS_NAME     | cut -d \" -f 2)
  16 objpath=$(xprop -id $1 _GTK_MENUBAR_OBJECT_PATH | cut -d \" -f 2)
  17 
  18 while IFS=\| read id pos sid action label; do
  19     pid=${pids[$id]}
  20     label=${label//_/}
  21 
  22     [[ $pid ]] &&
  23     label="${labels[$id]} > $label"
  24 
  25     if [[ $2 == "$label" ]]; then
  26         busctl --user  -j call $busname $objpath \
  27         org.gtk.Actions Activate sava{sv} -- "${action#unity.}" 0 0
  28         exit
  29     fi
  30 
  31     if [[ $sid ]]; then
  32         pids[$sid]="$pid.$sid"
  33         labels[$sid]="$label"
  34     else
  35         echo "$pid.$id.$pos.$(( ++i )) $label"
  36     fi
  37 done < <( # {{{
  38     busctl --user  -j call $busname $objpath \
  39     org.gtk.Menus Start au -- ${#subnum[@]} ${subnum[@]} | jq -r '
  40         .data[] | .[] |
  41         .[0] as $id   |
  42         .[1] as $pos  |
  43     (.[2] | .[] | select(.label) | [$id, $pos, (.":submenu".data | .[0]), .action.data, .label.data] | @tsv)
  44     ' | tr \\t \|
  45 ) | # }}}
  46 sort -k 1,1V | cut -d ' ' -f 2-
  47 
  48 ################################################################################
  49 
  50 busaddr=$(busctl --user -j call \
  51 com.canonical.AppMenu.Registrar \
  52 /com/canonical/AppMenu/Registrar com.canonical.AppMenu.\
  53 Registrar GetMenuForWindow u $1 | jq -r '.data | join(" ")')
  54 
  55 while read id label; do
  56     if [[ $2 == "$label" ]]; then
  57         busctl --user -j call $busaddr \
  58         com.canonical.dbusmenu Event isvu -- $id clicked i 0 $(date +%s)
  59         exit
  60     fi
  61 
  62     echo "$label"
  63 done < <( # {{{
  64     busctl --user -j call $busaddr \
  65     com.canonical.dbusmenu GetLayout -- iias 0 -1 0 |
  66     jq -r . --tab | awk '
  67         BEGIN {
  68             split("", tree)
  69         }
  70 
  71         /\s+[0-9]+/ {
  72             id = int($1)
  73             next
  74         }
  75 
  76         /"data": "submenu"/ {
  77             submenu = ""
  78             next
  79         }
  80 
  81         /"data": "radio"/     { next }
  82         /"data": "separator"/ { next }
  83         /"data": "checkmark"/ { next }
  84 
  85         /"data": "/ {
  86             gsub("_", "")
  87             sub(/"$/, "")
  88             sub(/"data": "/, "")
  89 
  90             if (!submenu){
  91                 submenu  = $0
  92 
  93                 last  = count
  94                 count = gsub(/\t/, "", submenu)
  95 
  96                 for (i in tree){
  97                     if (count < last && i >= last)
  98                         delete tree[i]
  99                 }
 100 
 101                 tree[count]=$0
 102                 next
 103             }
 104 
 105             menu = ""
 106             for (i in tree)
 107                 menu = (menu ? menu " > " : "") tree[i]
 108 
 109             sub(/^\s+/, "")
 110             gsub(/\t+/, "", menu)
 111 
 112             printf "%d %s > %s\n", id, menu, $0
 113             # menus[id]=id " " menu " > " $0
 114         }
 115     '
 116 ) # }}}