Is there a way to detect that a Zenity dialog has lost focus?

I would like to keep the dialog box in the foreground unless the user presses ESC.

I am attempting to add it to this script:


# requires these packages from ubuntu repository:
# wmctrl, zenity, x11-utils 
# and the script mouse-speed

# This procect on git:        https://github.com/rubo77/mouse-speed

######## configuration ##########
# seconds between micro breaks
microbreak_time=$(( 10 * 60 ))
# micro break duration in seconds
# seconds between long breaks
longbreak_time=$(( 120 * 60 ))

# message to display 
message="Try focussing a far object outside the window with the eye to relax!"
longbreak_message="Change your seating or continue work in a standing/sitting position"
#postpone label


# global zoom of your window manager:
# height in px of the top system-bar:
# sum in px of all horizontal borders:
# get width of screen and height of screen
SCREEN_WIDTH=$(xwininfo -root | awk '$1=="Width:" {print $2}')
SCREEN_HEIGHT=$(xwininfo -root | awk '$1=="Height:" {print $2}')
# width and height

function slow_down(){
    #zenity --warning --text "slow down mouse";
    mouse-speed -d 30

while true; do
    # short loop every few minutes to look around
    sleep $microbreak_time
    echo "99"
    sleep $(( $microbreak_duration - 2 ))
    echo "# Mouse speed reset to 100%"
    sleep 2
    echo "100"
    ) | if ( sleep 1 && wmctrl -F -a "$window_title" -b add,maximized_vert,maximized_horz && sleep 3 &&  wmctrl -F -a "$window_title" -b add,above ) & ( zenity --progress --text "$message" --percentage=0 --auto-close  --height=$H --width=$W --pulsate --title="$window_title" --cancel-label="$postpone" ); then
        #zenity --info --text "Maus normal speed!"
        mouse-speed -r
done &
while true; do
    # second long loop to change seat position
    sleep $longbreak_time
    zenity --warning --text "$longbreak_message" --title="$window_title - long break"
# This will wait one second and then steal focus and make the Zenity dialog box always-on-top (aka. 'above').

(sleep 1 && wmctrl -F -a "I am on top" -b add,above) &
(zenity --info --title="I am on top" --text="How to help Zenity to get focus and be always on top")


  • I wonder if add,fullscreen will also work – rubo77 Sep 1 '14 at 6:34
  • I also added ` -b add,maximized_vert,maximized_horz` in a second wmctrl call. Now I need to call the script also if the zenity window is minimized, resized or moved – rubo77 Sep 7 '14 at 7:50
  • At startup things may get really slow, so I suggest this: (while ! wmctrl -F -a "$$ the title" -b add,above;do sleep 1;done) & and also put the script pid on title to make it more unique. – Aquarius Power Nov 15 '14 at 13:59

You may run into problems if you run this as a cron job. Cron's environment is not aware of your X display, dbus or desktop and will not display the zenity box or keep it on top. Adding DISPLAY=:0 prior to both wmctrl and zenity resolves the issue:

(sleep 1 && DISPLAY=:0 wmctrl -F -a "I am on top" -b add,above) & (DISPLAY=:0 zenity --info --title="I am on top" --text="How to help Zenity to get focus and be always on top")


This solution is mostly the same as the one by @Jan, but uses the PID instead of the window title to identify the window, and additionally is Bourne Shell compatible (-> does not require bash).

# This will wait 200ms, steal focus and set the Zenity dialog box
# to "always-on-top".

modify_win_by_pid() {

    sleep 0.2
    win_id=`wmctrl -l -p | grep ${pid} | awk '{print $1}'`
    wmctrl -i - ${win_id} -b add,above

zenity --info --title="I am on top" --text="I received focus and will stay on top" &
modify_win_by_pid $!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.