#!/bin/sh  
# \
exec wish "$0" "$@"

#Before running this, run the gnome-tweak-tool. Go to the Workspaces tab and turn "Workspaces only on primary display" to OFF

#wm attributes . -type tooltip
wm attributes . -type dock

proc IsRedhat7 {args} {
    set fid [open /etc/redhat-release r]
    set line [gets $fid]
    close $fid
    if {([string first "Red Hat" $line] != -1) && ([string first "release 7" $line] != -1)} {
        return 1
    }
    return 0
}
if {[IsRedhat7] != 1} { exit }

proc IsOneXscreen {args} {
    if {[catch {exec xrandr --query | fgrep Screen} results]} {
        puts "Error: $results"
        return 0
    }
    set results [split $results \n]
    if {[llength $results] != 1} {
        puts "Error: This tool was designed for one X screen spaning one or more monitors."
        puts "       Please contact Bob Soliday to modify this script for your setup."
        return 0
    }
    return 1
}
if {[IsOneXscreen] != 1} { exit }

proc moveStart {W X Y} {
    global mouse
    set geometry [split [wm geometry .] +]
    set mouse(dx0) [lindex $geometry 1]
    set mouse(dy0) [lindex $geometry 2]
    set mouse(X0) $X
    set mouse(Y0) $Y
}

proc moveDrag {W X Y} {
    global mouse
    set currX [expr $mouse(dx0) + $X - $mouse(X0)]
    set currY [expr $mouse(dy0) + $Y - $mouse(Y0)]
    wm geometry . +$currX+$currY
    update
}

set bordercolor "\#aeb2c3"
set buttoncolor "\#63639c"
set activebuttoncolor "\#b3639c"
proc SetupWidgets {args} {
    global num wsname workspace screen screenData xrandrIndex bordercolor buttoncolor activebuttoncolor
    APSStrictParseArguments {wsNames rows}
    
    frame .leftbar -width 20 -bd 5 -relief groove -bg $bordercolor
    frame .userFrame -bg $bordercolor
    frame .rightbar -width 20 -bd 5 -relief groove -bg $bordercolor
    set column 0
    set row 0
    set index 0
    set num [llength $wsNames]
    set columns [expr int(ceil($num / ($rows * 1.0)))]
    foreach name $wsNames {
	set wsname($index) $name
        button .userFrame.ws$index \
          -text $name \
          -fg white -bg $buttoncolor \
          -font "Adwaita 8 bold" \
          -width 10 \
          -pady 1 -padx 5 \
          -anchor w \
          -command "SelectWorkspace -index [expr $index + 1] -column $column -row $row"
       grid .userFrame.ws$index \
          -column $column -row $row \
          -sticky nsew -padx 2 -pady 2
        incr column
        if {$column == $columns} {
            set column 0
            incr row
        }
	set workspace($index) ""
        incr index
    }
    pack .leftbar -side left -fill y
    pack .userFrame -side left
    pack .rightbar -side left -fill y

    bind .leftbar <Button-1> {moveStart %W %X %Y}
    bind .leftbar <B1-Motion> {moveDrag %W %X %Y}
    bind .rightbar <Button-1> {moveStart %W %X %Y}
    bind .rightbar <B1-Motion> {moveDrag %W %X %Y}

    update idletasks
    set x [expr {[lindex $screenData($xrandrIndex) 0] + [lindex $screenData($xrandrIndex) 2] - [winfo width .]}]
    set y [expr {[lindex $screenData($xrandrIndex) 1] + [lindex $screenData($xrandrIndex) 3]- [winfo height .] - 33}]
    wm geometry . +${x}+${y}
    .userFrame.ws0 configure -bg $activebuttoncolor
}

proc SelectWorkspace {args} {
    global num wsname currentWorkspace buttoncolor activebuttoncolor
    set column -1
    set row -1
    APSStrictParseArguments {index column row}
    set name [.userFrame.ws[expr $index - 1] cget -text]
    if {([.userFrame.ws[expr $index - 1] cget -bg] == $activebuttoncolor) && ($column != -1) && ($row != -1)} {
    } else {
	if {$index == $currentWorkspace} {
	    return
	}
	SwitchWorkspace -newWorkspace $index
        for {set i 0} {$i < $num} {incr i} {
            .userFrame.ws$i configure -bg $buttoncolor
        }
        .userFrame.ws[expr $index - 1] configure -bg $activebuttoncolor
    }

}

proc SwitchWorkspace {args} {
    set cleanup 0
    APSStrictParseArguments {newWorkspace cleanup}
    global screen currentWorkspace workspace screenData xrandrIndex
    if {[catch {exec wmctrl -lG} wmData]} {
	puts "Error: $wmData"
	return
    }
    set wmData [split $wmData \n]
    set workspace($currentWorkspace) ""
    foreach line $wmData {
	set id [lindex $line 0]
	set ws [lindex $line 1]
	set xpos [lindex $line 2]
	set ypos [lindex $line 3]
        if {($xpos < [lindex $screenData($xrandrIndex) 2]) || ($xpos >= [expr [lindex $screenData($xrandrIndex) 0] + [lindex $screenData($xrandrIndex) 2]])} {
            continue
        }
        if {($ypos < [lindex $screenData($xrandrIndex) 3]) || ($ypos >= [expr [lindex $screenData($xrandrIndex) 1] + [lindex $screenData($xrandrIndex) 3]])} {
            continue
        }
	if {$cleanup} {
	    if {$newWorkspace == $ws} {
                #Since we start with workspace 1 selected, move all preexisting windows from workspace 1 to workspace 0 so they are viewable.
		if {[catch {exec wmctrl -i -r $id -t 0} results]} {
		    puts "Error: $results"
		    exit
		}
	    }
	} else {
	    if {$ws == 0} {
                if {[catch {exec xprop -id $id} xpropInfo]} {
                } else {
                    if {[string first _NET_WM_STATE_STICKY $xpropInfo] != -1} {
                        continue
                    }
                }
                if {[catch {exec wmctrl -i -r $id -t $currentWorkspace} results]} {
		    puts "Error: $results"
		    exit
		}
            } elseif {$newWorkspace == $ws} {
                if {[catch {exec wmctrl -i -r $id -t 0} results]} {
		    puts "Error: $results"
		    exit
		}
            }
	}
    }
    set currentWorkspace $newWorkspace
    if {[catch {exec wmctrl -s 0} wmData]} {
	return
    }
}

proc SetupDesktops {args} {
    set count 0
    APSStrictParseArguments {count}
    if {[catch {exec wmctrl -d} results]} {
        puts "Error: $results"
        exit
    }
    set currentCount [llength [split $results \n]]

    if {$currentCount < $count} {
        if {[catch {exec wmctrl -n $count} results]} {
            puts "Error: $results"
            exit
        }
    }
}

proc APSStrictParseArguments {optlist} {
    upvar args arguments
    set length [llength $arguments]
    set index 0
    set leftovers {}
    while {$index<$length} {
        set arg [lindex $arguments $index]
        if {[string index $arg 0]=="-"} {
            set keywordName [string range $arg 1 end]
            if {[lsearch -exact $optlist $keywordName]!=-1} {
                incr index
                if {$index==$length} {
                    lappend leftovers $arg
                } else {
                    set valueString [lindex $arguments $index]
                    uplevel "set $keywordName {$valueString}"
                    incr index
                }
            } else {
                incr index
                lappend leftovers $arg
            }
        } else {
            lappend leftovers $arg
            incr index
        }
    }
    set arguments [concat $leftovers]
    if {$arguments != ""} {
        set procName [lindex [info level [expr {[info level] - 1}]] 0]
        puts stderr "Unknown option(s) given to $procName \"$arguments\""
        return -1
    } else {
        return 0
    }
}


set currentWorkspace 0
set wsNames "One Two Three Four"
set rows 2
set screen 0
set args $argv
if {[llength $args] == 0} {
    puts "usage: WorkspaceSwitcherRH7 -wsNames \"One Two Three Four\" -rows 2 -screen 0"
    puts "  -wsNames contains a list of workspace names on a monitor"
    puts "  -rows is how many rows the workspace names will be divided into"
    puts "  -screen indicates which monitor to control, 0 is on the left.\n"
    puts "Before running this, run the gnome-tweak-tool. Go to the Workspaces tab"
    puts "and turn \"Workspaces only on primary display\" to OFF\n"
    puts "You can run gnome-session-properties and add it to the Startup Programs"
    puts "if you want it to run every time you log in."
    exit
}
APSStrictParseArguments {wsNames rows screen}

#Find out what order the screens are configured under xrandr and 
#translate the -screen option to the corresponding xrander index.
if {[catch {exec xrandr --query | fgrep " connected"} results]} {
    puts "Error: $results"
    exit
}
set results [split $results \n]
set index 0
foreach line $results {
    set geo [lindex $line 2]
    if {$geo == "primary"} {
        set geo [lindex $line 3]
    }
    set geo [split $geo "x+"]
    set screenData($index) $geo
    lappend geoList "$index [lindex $geo 2].[lindex $geo 3]"
    incr index
}
if {($screen >= $index) || ($screen < 0)} {
    puts "Invalid screen number given."
    exit
}

set geoList [lsort -real -index 1 $geoList]
set xrandrIndex [lindex [lindex $geoList $screen] 0]

exec wmctrl -s 0

SetupWidgets -wsNames $wsNames -rows $rows
SetupDesktops -count [expr 1 + [llength $wsNames]]
SwitchWorkspace -newWorkspace 1 -cleanup 1

#port is used to shutdown this app if a new one is launched
#port2 is used by APSMWST to remotely change the workspace
if {$screen == 0} {
    set port 4588
    set port2 4590
} elseif {$screen == 1} {
    set port 4589
    set port2 4591
} elseif {$screen == 2} {
    set port 4592
    set port2 4593
} elseif {$screen == 3} {
    set port 4594
    set port2 4595
} else {
    set port 4589
    set port2 4591
}
proc ChangeWorkspace {cid addr port} {
    if {$addr != "127.0.0.1"} {
	close $cid
	return
    }
    fileevent $cid readable "ChangeWorkspace_handle $cid"
    fconfigure $cid -buffering line    
}

proc ChangeWorkspace_handle {cid} {
    if {[gets $cid request] < 0} {
        close $cid
    } else {
        close $cid
	SelectWorkspace -index [expr $request + 1]
    }
}

proc Shutdown {cid addr port} {
    if {$addr != "127.0.0.1"} {
	close $cid
	return
    }
    close $cid
    exit
}
if [catch {socket -server Shutdown $port}] {
    if {[catch {socket 127.0.0.1 $port} sid]} {
	exit
    } else {
	after 100
	if [catch {socket -server Shutdown $port}] {
	    exit
	}
    }
}
if [catch {socket -server ChangeWorkspace $port2}] {
}
