Ubuntu Unity Switcher aka ALT_TAB KILLER

Tested on Ubuntu 12.04 Precise Pangolin.

Usage

Switch to next application in Unity Launcher

tclsh switcher next

Switch to previous application in Unity Launcher

tclsh switcher prev

.xbindkeysrc (Use mouse 8 and mouse 9 buttons as switcher)

"wmctrl -i -a $(switcher prev)"
b:8
"wmctrl -i -a $(switcher next)"
b:9

Requirements

  • tclx
  • xbindkeys
  • xprop
  • wmctrl

Source Code

#!/usr/bin/tclsh
package require Tclx
proc getPanel(Names) {} {
    set panel [exec gsettings get com.canonical.Unity.Launcher favorites]
    regsub -all "', '" $panel "\n" panel
    regsub -all .desktop $panel "" panel
    regsub -all {\['} $panel "" panel
    regsub -all {\']} $panel "" panel
    return $panel
}

proc getOpenWins(ID) {} {
    set open_wins [exec wmctrl -l]
    regsub -all -line {.*N/A.*\n} $open_wins "" open_wins
    regsub -all -line {.*Desktop.*\n} $open_wins "" open_wins
    set open_wins [exec echo $open_wins | awk {{ print $1 }}]
    return $open_wins
}

proc getOpenWins(WM_CLASS) {} {
    set open_winID [getOpenWins(ID)]
    set i 0
    foreach open_winID $open_winID {
        set xprop_output [exec xprop -id $open_winID]
        regexp -line {WM_CLASS\(STRING\) = .*} $xprop_output wm_class
        lappend WM_class $wm_class
        incr i
      }
      return $WM_class
}

 proc getOpenWins(Names) {} {
    set wm_class [getOpenWins(WM_CLASS)]
    foreach class $wm_class {
         regsub -all {WM_CLASS\(STRING\) = .*, \"} $class "" class
         regsub -all "\"" $class "" $class
        puts $class
    }
     puts $wm_names
 }

 proc getOpenWins(IDX) {} {
    # put an A on active window, N next, P previous, X all the rest
    set id [exec xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk {{print $2}}]
    set active_win [exec xprop -id $id]
    regexp -line {WM_CLASS\(STRING\) = .*} $active_win active_wm_class
    set panel [getPanel(Names)]
    set wm_class [getOpenWins(WM_CLASS)]
    set i 0; set index ""
    foreach panel_app $panel {
        # check each panel_app to see if open, then assign index position
        if {[lsearch -nocase $wm_class *$panel_app*]!=-1} {
            lappend index [lsearch $panel *$panel_app*]X
            # put an A on the active window 
            if {[string match -nocase *$panel_app* $active_wm_class]==1} { 
                 set index [lreplace $index $i $i [string replace [lindex $index $i] end end A]]
            }
            incr i
        }
    }
    set active_index [lsearch $index *A]
    set prev_index [expr $active_index-1]
    set next_index [expr $active_index+1]
    if {$active_index==0} {
        set index [lreplace $index 1 1 [string replace [lindex $index 1] end end N]]
        set index [lreplace $index end end [string replace [lindex $index end] end end P]]
    } elseif {$active_index==[lsearch $index [lindex $index end]]} {
        set index [lreplace $index 0 0 [string replace [lindex $index 0] end end N]]
        set index [lreplace $index end-1 end-1 [string replace [lindex $index end-1] end end P]]
    } else {
        set index [lreplace $index $prev_index $prev_index [string replace [lindex $index $prev_index] end end P]]
        set index [lreplace $index $next_index $next_index [string replace [lindex $index $next_index] end end N]]
    }
    return $index
}


set idx [getOpenWins(IDX)]
set panel [getPanel(Names)]
set id [getOpenWins(ID)]
set class [getOpenWins(WM_CLASS)]

# get the next and previous panel positions
set next [lindex $idx [lsearch $idx *N]]
set prev [lindex $idx [lsearch $idx *P]]
# get only the positions without N or P
set next [string range $next 0 end-1]
set prev [string range $prev 0 end-1]
# get the name of the index in panel
set next [lindex $panel $next]
set prev [lindex $panel $prev]
# get the class of app panel
set next [lsearch -nocase $class *$next*]
set prev [lsearch -nocase $class *$prev*]
# get id DONE!
set next [lindex $id $next]
set prev [lindex $id $prev]

if {$argv=="next"} {puts $next}
if {$argv=="prev"} {puts $prev}