You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
4.5 KiB

#utilities for punk apps to call
package provide punkapp [namespace eval punkapp {
variable version
set version 0.1
}]
namespace eval punkapp {
proc hide_dot_window {} {
#alternative to wm withdraw .
#see https://wiki.tcl-lang.org/page/wm+withdraw
wm geometry . 1x1+0+0
wm overrideredirect . 1
wm transient .
}
proc is_toplevel {w} {
if {![llength [info commands winfo]]} {
return 0
}
expr {[winfo toplevel $w] eq $w && ![catch {$w cget -menu}]}
}
proc get_toplevels {{w .}} {
if {![llength [info commands winfo]]} {
return [list]
}
set list {}
if {[is_toplevel $w]} {
lappend list $w
}
foreach w [winfo children $w] {
lappend list {*}[get_toplevels $w]
}
return $list
}
proc exit {{toplevel ""}} {
set toplevels [get_toplevels]
if {[string length $toplevel]} {
set wposn [lsearch $toplevels $toplevel]
if {$wposn > 0} {
destroy $toplevel
}
} else {
#review
puts stderr "punkapp::exit called without toplevel - showing console"
show_console
return 0
}
set controllable [get_user_controllable_toplevels]
if {![llength $controllable]} {
show_console
}
}
proc get_visible_toplevels {{w .}} {
if {![llength [info commands winfo]]} {
return [list]
}
set list [get_toplevels $w]
set mapped [lmap v $list {expr {[winfo ismapped $v] ? $v : {}}}]
set mapped [concat {*}$mapped] ;#ignore {}
set visible [list]
foreach m $mapped {
if {[wm overrideredirect $m] == 0 } {
lappend visible $m
} else {
if {[winfo height $m] >1 && [winfo width $m] > 1} {
#technically even a 1x1 is visible.. but in practice even a 10x10 is hardly likely to be noticeable when overrideredirect == 1
#as a convention - 1x1 with no controls is used to make a window invisible so we'll treat anything larger as visible
lappend visible $m
}
}
}
return $visible
}
proc get_user_controllable_toplevels {{w .}} {
set visible [get_visible_toplevels $w]
set controllable [list]
foreach v $visible {
if {[wm overrideredirect $v] == 0} {
append controllable $v
}
}
#only return visible windows with overrideredirect == 0 because there exists some user control.
#todo - review.. consider checking if position is outside screen areas? Technically controllable.. but not easily
return $controllable
}
proc hide_console {args} {
set defaults [dict create -force 0]
if {([llength $args] % 2) != 0} {
error "hide_console expects pairs of arguments. e.g -force 1"
}
set known_opts [dict keys $defaults]
dict for {k v} $args {
if {$k ni $known_opts} {
error "Unrecognised options '$k' known options: $known_opts"
}
}
set opts [dict merge $defaults $args]
set force [dict get $opts -force]
if {!$force} {
if {![llength [get_user_controllable_toplevels]]} {
puts stderr "Cannot hide console while no user-controllable windows available"
return 0
}
}
if {$::tcl_platform(platform) eq "windows"} {
package require twapi
set h [twapi::get_console_window]
twapi::hide_window $h
return 1
} else {
#todo
puts stderr "punkapp::hide_console unimplemented on this platform (todo)"
return 0
}
}
proc show_console {} {
if {$::tcl_platform(platform) eq "windows"} {
package require twapi
if {![catch {set h [twapi::get_console_window]} errM]} {
twapi::show_window $h -activate -normal
} else {
#no console - assume launched from something like wish?
catch {console show}
}
} else {
#todo
puts stderr "punkapp::show_console unimplemented on this platform"
}
}
}