Win32 edit
MPJ - June 21, 2002Now that topmost is supported in the Tcl core (8.4 and higher) for the MsWindows platform you can just use:wm attributes (window) -topmost 1The example below will cause the topmost setting to be toggled when the F3 key is pressed.
bind . <F3> "setontop" proc setontop {} {wm attributes . -topmost [expr [wm attributes . -topmost] ^ 1]}
Miko Don't work for me. Wish is running but the window is invisible ( tested on Win 2K and XP). MPJ ~ Works fine for me on 95/98/2k/XP. To test run wish and type "wm attributes . -topmost 1" which will keep the wish window on top even if it does not have focus.
The API function needed is (see also [1]):
SetWindowPos(HWND hWnd, // handle to window HWND hWndAfter, // placement order handle int x, int y, // position (horizontal, vertical) int cx, int cy, // size (width, height) UINT uFlags) // positioning flagsThe placement order handle can be either another HWND or once of the following constants:
- HWND_BOTTOM (1) Moves to the bottom
- HWND_NOTOPMOST (-2) Place above all non-topmost windows.
- HWND_TOP (0) Move to the top
- HWND_TOPMOST (-1) Move to the top and keep it there.
SetWindowPos([winfo id .], HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)which turns out to be the code used by XRaiseWindow in win/tkWinWindow.c
Melissa Schrumpf recommends the GPLed WinCtl [2] utility, which makes it possible to write
exec WinCtlW.exe -id [wm frame .] topmost &(or might there be more punctuation in the vicinity of the id?).
Martin Lemburg - 25th February 2002, 13:16 GMTI found the original topmost package made by John Rosauer in 12.1997. It works only with tcl/tk v.8.0.The URL is: ftp://ftp.dcade.de/pub/ml/tcl/packages/topmost10.zip [3]I created a stubs enabled topmost package, usable with tcl/tk 8.1.1 and higher.The URL is:ftp://ftp.dcade.de/pub/ml/tcl/packages/topmost20.zip [4]LES on March 30 2004: the two links above are brokenUsage:
package require topmost 2.0; topmost widget ?boolean?Much fun!Martin Lemburg
MPJ - March 9th 2002Using the topmost source as a guideline I wrote this tcl proc using Ffidl. Its usage is similar to the topmost package except that it does not want a widget name but the window title.
load ffidl05.dll ffidl::callout dll_SetWindowPos {int int int int int int int} int [ffidl::symbol user32.dll SetWindowPos] ffidl::callout dll_GetWindowLong {int int} int [ffidl::symbol user32.dll GetWindowLongA] ffidl::callout dll_FindWindowTitle {int pointer-utf8} int [ffidl::symbol user32.dll FindWindowA] # windowname is based on wm title # state is 1 to set or anything else to reset, empty returns the current state proc topmost {windowname {state ""}} { set hwnd [dll_FindWindowTitle 0 $windowname] if {$hwnd == 0 } { return "Not a valid top window" } set WS_EX_TOPMOST 0x8 set GWL_EXSTYLE -20 set TOPMOST -1 set NOTOPMOST -2 set SWP_NOACTIVATE 0x10 set SWP_NOMOVE 0x2 set SWP_NOSIZE 0x1 set screenwidth [lindex [split [wm geometry .] x+] 0] set screenheight [lindex [split [wm geometry .] x+] 1] set result [expr ([dll_GetWindowLong $hwnd $GWL_EXSTYLE] & $WS_EX_TOPMOST )>>3] if {$state == "" } { return $result } if {$state == 1} { dll_SetWindowPos $hwnd $TOPMOST 0 0 \ $screenwidth $screenheight \ [expr $SWP_NOACTIVATE | $SWP_NOMOVE | $SWP_NOSIZE] } else { dll_SetWindowPos $hwnd $NOTOPMOST 0 0 \ $screenwidth $screenheight \ [expr $SWP_NOACTIVATE | $SWP_NOMOVE | $SWP_NOSIZE] } return [expr ([dll_GetWindowLong $hwnd $GWL_EXSTYLE] & $WS_EX_TOPMOST )>>3] }Usage:
topmost [wm title .] ?boolean?
UNIX Systems edit
The -topmost attribute is also supported there provided you've got Tk 8.5 (and provided your WM takes notice, which most do).wm attribute .theWindow -topmost 1
MGS 2003/03/26 - For non-Windows systems, you could something like this:
TFW - Jan 9, 2003I find it convienent to add a checkbox to the system menu to toggle always on top on/off.
Related topic:
SRT - Mar 30, 2004KDE and probably GNOME-compliant window managers have support for the _NET_WM_STATE_STAYS_ON_TOP porperty. The perl/Tk code below may be used to set this property on toplevel windows. Unfortunately, a direct translation to Tcl/Tk is not possible as Tcl/Tk has no support for the "property" method. Nevertheless it would be nice if wm attributes -topmost had similar support builtin.
For ptk, the natural solution is Tk:StayOnTop [5]. Chris Whiting gives this [6] example of its use.
proc ontop {W boolean} { set bindtags [bindtags $W] set index [lsearch $bindtags bind$W] if { $boolean } { if { $index == -1 } { bindtags $W [linsert $bindtags 0 bind$W] bind bind$W <Visibility> [list ontop:state %W %s] } } else { if { $index != -1 } { bindtags $W [lreplace $bindtags $index $index] bind bind$W <Visibility> {} } } } proc ontop:state {W state} { puts "ontop \[$W\] \[$state\]" if { ![string equal [winfo toplevel $W] $W] } { puts " window \[$W\] is not a toplevel" return } if { ![string equal $state VisibilityUnobscured] } { raise $W } } # demo code toplevel .t ontop .t 1 checkbutton .top \ -text "On Top" \ -variable ontop(.) \ -command "ontop . \$ontop(.)" button .exit -text exit -default active -command exit pack .exit -side bottom -anchor se pack .top -side top -padx 50 -pady 50which will raise a window whenever it is obscured. But beware, if you have more than one window, you can have multiple windows fighting over who gets to be on top (if they overlap).
TFW - Jan 9, 2003I find it convienent to add a checkbox to the system menu to toggle always on top on/off.
Related topic:
wm transient $higher_widget $lower_widgetkeeps $higher_widget on top of $lower_widget. Sometimes. As DKF explains, "This doesn't actually enforce it, it just gives a strong hint to the window manager (or OS, depending on platform) that the child is an agent acting on behalf of the parent. Most WMs interpret this as meaning keep it on top of its parent and decorate it like a dialog, but not all. However, that's usually good enough anyway."For more on the subject, see "Modal dialogs".
SRT - Mar 30, 2004KDE and probably GNOME-compliant window managers have support for the _NET_WM_STATE_STAYS_ON_TOP porperty. The perl/Tk code below may be used to set this property on toplevel windows. Unfortunately, a direct translation to Tcl/Tk is not possible as Tcl/Tk has no support for the "property" method. Nevertheless it would be nice if wm attributes -topmost had similar support builtin.
sub keep_on_top { my $w = shift; my($wrapper) = $w->toplevel->wrapper; eval { if (!grep { $_ eq '_NET_WM_STATE_STAYS_ON_TOP' } $w->property('get', '_NET_SUPPORTED', 'root')) { die "_NET_WM_STATE_STAYS_ON_TOP not supported"; } $w->property('set', '_NET_WM_STATE', "ATOM", 32, ["_NET_WM_STATE_STAYS_ON_TOP"], $wrapper); }; if ($@) { warn $@; 0; } else { 1; } }DKF: We don't support a property method because it's too easy to cause damage with it. We prefer a small extension for the task. OTOH, the above is useful grist to the mill of ongoing wm attributes development.DKF: And we support it in Tk 8.5.
For ptk, the natural solution is Tk:StayOnTop [5]. Chris Whiting gives this [6] example of its use.