picandies
Posts: 192
Joined: Wed Nov 26, 2014 5:13 pm

forcing app to stay on top

Mon Mar 25, 2019 4:20 am

I have a tkinter program , where one button employs an os.system call os.system('theapp') that runs a standard rpi editor app. This starts out fine, with the app appearing on top of tkinter, ready to use. However if tkinter is accidentally touched, the app disappears behind tkinter & remains out of reach. How to force the app to stay topmost (or make tkinter stay bottom-most)?

bzt
Posts: 386
Joined: Sat Oct 14, 2017 9:57 pm

Re: forcing app to stay on top

Mon Mar 25, 2019 2:35 pm

Hi,

Don't start the app directly, instead start a small script. That script starts your app in the background (add & at the end of the command) then in a loop it can bring the app's window to the foreground using xdotool. That's a standard raspbian package, you can install it with "apt-get install xdotool".
If xdotool fails, that means the app's window has been closed and you can quit the loop. Something like:

Code: Select all

os.system('theappwrapper.sh')
and theappwrapper.sh:

Solution 1:

Code: Select all

#!/bin/sh

# start the real app, then give it some time to open its window
theapp &
sleep 0.5
while true; do
  # get the window's id, tweak this to your needs. If we can't find that window, exit
  xdotool search "The App" windowactivate --sync || exit
  # wait 1 sec then repeat
  sleep 1
done
Please note I haven't tested this script, I just wrote it from memory as a guide. But it should be fine to get you on the right track.

Solution 2: this also needs xdotool to get the window id, but after that you can use xprop to make the window "Always on Top" without a loop:

Code: Select all

theapp &
sleep 0.5
xprop -id `xdotool search "The App"` -set _NET_WM_STATE_ABOVE true
Not tested either, just a tip.

Solution 3: with xprop only, but first you need to get the window's name if that's constant. Start your theapp, then in another terminal type:

Code: Select all

xprop | grep WM_NAME
Click on the theapp's window and see what this command outputs. If it's consistent, then you can use it in the wrapper:

Code: Select all

theapp &
sleep 0.5
xprop -name "the name from prev command" -set _NET_WM_STATE_ABOVE true

Solution 4: with wmctrl (yet another tool):

Code: Select all

theapp &
sleep 0.5
wmctrl -r "The App" -b add,above
Where "The App" is the window's title.

Please note that window's name and title are not necessarily the same, and that they could change dynamically (an editor typically includes the name of the opened file in them).

Cheers,
bzt

picandies
Posts: 192
Joined: Wed Nov 26, 2014 5:13 pm

Re: forcing app to stay on top

Mon Mar 25, 2019 4:53 pm

BZT--Thanks! those are interesting suggestions, never heard of xdotoll. Seems like a bit of arm wrestling, but sometimes only brute force works.
One concern is depending on what file my app work is opening, my current os call looks like:

os.system('libreoffice '+files[names]) , where files[] is a list of files (which may vary) ...does this mean the script text need to vary as well? I haven't written any scripts, only python...so I'm at the beginning.

Return to “General discussion”