# $Id: green.tcl 524 2012-08-23 13:33:45Z sergei $
# "Green" -- Tkabber plugin which allows Tkabber to properly
# handle changes in the system power state (disconnection on
# suspend and (possibly) re-connection on resume).
# On Windows it requires winpm Tcl extension: http://tkwinpm.googlecode.com
# Written by Konstantin Khomoutov <flatworm@users.sourceforge.net>
# See README for usage guidelines.
# See license.terms for details about distribution.

namespace eval green {
	if {[string equal $::tcl_platform(platform) windows]} {
		if {[catch { package require winpm }]} {
			global errorInfo
			puts stderr "Power management support is unavailable:\
				failed to load \"winpm\" package.\
				The error was:\n\
				$errorInfo"
			return
		}

		winpm bind PBT_APMSUSPEND [namespace current]::on_suspend
		winpm bind PBT_APMRESUMESUSPEND [namespace current]::on_resume
	} else {
		if {![catch { package require dbus-tcl }]} {
			if {![catch { dbus connect system } bus]} {
				dbus filter $bus add -type signal
				dbus listen $bus /org/freedesktop/UPower \
						 org.freedesktop.UPower.Sleeping \
						 [namespace current]::on_suspend
				dbus listen $bus /org/freedesktop/UPower \
						 org.freedesktop.UPower.Resuming \
						 [namespace current]::on_resume
			}
		}
	}

	variable active [list]
	variable options

	custom::defgroup Green \
		[::msgcat::mc "Power management support."] \
		-group Plugins

	custom::defvar options(resume_sessions) 1 \
		[::msgcat::mc "Attempt to resume the sessions that were active\
			when the system has been suspended."] \
		-type boolean \
		-group Green

	custom::defvar options(resume_delay) 10 \
		[::msgcat::mc "Number of seconds to wait before attempting\
			to re-establish the sessions that were active.\
			This may be useful to allow the network connection(s)\
			to come up."] \
		-type integer \
		-group Green
}

proc green::on_suspend {args} {
	# Logout all connections, even those which aren't fully logged in
	variable active [connections 1]

	foreach xlib $active {
		logout $xlib
	}
}

proc green::on_resume {args} {
	variable options
	variable active

	if {!$options(resume_sessions)} return
	if {[llength $active] == 0} return

	after idle after [expr {$options(resume_delay) * 1000}] \
		[namespace current]::do_resume
}

proc green::do_resume {} {
	variable active
	global loginconf_hist

	foreach xlib $active {
		if {[info exists loginconf_hist($xlib)] && ![xlib_connected $xlib]} {
			login $loginconf_hist($xlib)
		}
	}
}

proc green::xlib_connected {xlib} {
	# return 1 if $xlib is already connected or is connecting currently
	expr {[lsearch -exact [connections 1] $xlib] >= 0}
}

