''"How can I keep my toplevel on top?"'' is a FAQ. See http://tcl.sourceforge.net/faqs/tk/#wm/ontop for portable Tk solutions, and [raise] for related information. ---- **Win32** [MPJ] - June 21, 2002 Now that topmost is supported in the Tcl core (8.4 and higher) for the MsWindows platform you can just use: ====== wm attributes (window) -topmost 1 ====== The example below will cause the topmost setting to be toggled when the F3 key is pressed. ====== bind . "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 [http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/windows_2blf.asp]): ======c 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 flags ====== The 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. The Flags can be one of a number but for this page probably SWP_NOMOVE (2) and SWP_NOSIZE (1) are likely the most useful. So: ======c 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 [GPL]ed WinCtl [http://david.biesack.home.mindspring.com/WinCtl.html] 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 GMT I 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 [ftp://ftp.dcade.de/pub/ml/tcl/packages/topmost10.zip] 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 [ftp://ftp.dcade.de/pub/ml/tcl/packages/topmost20.zip] '''''LES''' on March 30 2004: the two links above are broken'' Usage: ====== package require topmost 2.0; topmost widget ?boolean? ====== Much fun! [Martin Lemburg] ---- [MPJ] - March 9th 2002 Using 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** 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: ====== 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 [list ontop:state %W %s] } } else { if { $index != -1 } { bindtags $W [lreplace $bindtags $index $index] bind bind$W {} } } } 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 50 ====== which 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, 2003 I 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_widget ====== keeps $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, 2004 KDE 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 [http://search.cpan.org/~gbrock/Tk-StayOnTop-0.11/StayOnTop.pm]. Chris Whiting gives this [http://notyet] example of its use. <> ---- Note that if two windows want to stay 'on top' at the same time, a funny flickering occures.... <> Tk | GUI