How to check for a (partly) empty desktop [SOLVED]

About writing shell scripts and making the most of your shell
Forum rules
Topics in this forum are automatically closed 6 months after creation.
Locked
vimes666
Level 6
Level 6
Posts: 1231
Joined: Tue Jan 19, 2016 6:08 pm

How to check for a (partly) empty desktop [SOLVED]

Post by vimes666 »

I stare at an empty desktop a lot.
Not because I have nothing to do but I run a slideshow on my desktop that contains hundreds of images. So it is just nice to look at.
So nice that I also wanted an annotation on the screen along with the images. Hence I wrote a prove of concept script to do that and it seems to work :)
Image

However it soon becomes clear that you don't want this when the desktop background is not visible.
Notify-send has no 'unfocus' option afaik and --urgency=low doesn't seem to have any effect.
So I am looking for a way to test the amount of emptiness on the desktop so I can make the notify-send conditional.

Here's the script:

Code: Select all

#!/usr/bin/bash
# Vimes 2022.
# Dependencies: inotify-tools

myself="${0##*/}"
version="$myself - version 0.1"
echo $version

# Kill other instances of myself
for pid in $(pidof -x "$myself"); do
   (( pid == $$ )) || kill -SIGINT $pid
done

# Activate sleep command as builtin. bash-builtins should be installed for
# this to work. if not sleep will be run as separate process.
enable -f /usr/lib/bash/sleep sleep

# Graceful end
trap "logger \"${myself}[$$] killed\"; exit" SIGHUP SIGINT SIGTERM SIGKILL

# Mainline
# -------------------------------------------------------------------------------------------------------

while true; do
   resp="$(inotifywait -r --event open --format='%w|%f' '/usr/share/backgrounds')" #TODO use monitor mode
   dir="$(cut -d'|' -f1 <<<$resp)"
   file="$(cut -d'|' -f2 <<<$resp)"
   sleep 7          # wait a bit for the transition effect
   notify-send -u low -i "$HOME/.icons/feather-orange/image.svg" "$file" "From: $dir"
done
Last edited by LockBot on Tue May 02, 2023 10:00 pm, edited 2 times in total.
Reason: Topic automatically closed 6 months after creation. New replies are no longer allowed.
If you think the issue is solved, edit your original post and add the word solved to the title.
User avatar
xenopeek
Level 25
Level 25
Posts: 29606
Joined: Wed Jul 06, 2011 3:58 am

Re: How to check for a (partly) empty desktop

Post by xenopeek »

You can do it with wmctrl or xdotool. Doing the loops and math to calculate what percentage of the desktop is occupied is perhaps not the most comfortable to do in bash but it can be done.

wmctrl is probably the easier of the two for this. See the manpages on your PC or online:
https://manpages.ubuntu.com/manpages/ja ... trl.1.html
https://manpages.ubuntu.com/manpages/ja ... ool.1.html

wmctrl -d lists all workspaces ("desktops") and their geometry. Iterate the list and find the `*` marked one to find the current desktop number. wmctrl -l -G lists all windows on all desktops and their geometry. Iterate the list and get the ones for the current desktop number. Then do a bunch of math :) I think some additional step is needed to filter out windows that are currently minimized to the panel.

You can do the same with xdotool, and more precisely, but it requires more commands.
Image
vimes666
Level 6
Level 6
Posts: 1231
Joined: Tue Jan 19, 2016 6:08 pm

Re: How to check for a (partly) empty desktop

Post by vimes666 »

wmctrl -l -G lists all windows on all desktops and their geometry
Yes that would be very helpfull if it would also tell you whether the window is minimized or not, which it does not :( (or I missed something)
xdotool I was trying to avoid because it takes so many steps to get the info I need and it is an extra dependency, but thanks anyway.
If you think the issue is solved, edit your original post and add the word solved to the title.
User avatar
xenopeek
Level 25
Level 25
Posts: 29606
Joined: Wed Jul 06, 2011 3:58 am

Re: How to check for a (partly) empty desktop

Post by xenopeek »

xdotool lets you filter out minimized windows so that's the way to go then. But yes more steps than with wmctrl.
Image
vimes666
Level 6
Level 6
Posts: 1231
Joined: Tue Jan 19, 2016 6:08 pm

Re: How to check for a (partly) empty desktop

Post by vimes666 »

xdotool lets you filter out minimized windows so that's the way to go then. But yes more steps than with wmctrl.
I also need to filter all the rubbisch components like icons and other stuff that is never minimized, but I agree that it is probably the way to go. I was already busy finding a way to calculate the free space, which is not easy keeping overlapping windows in mind. The conclusion was that the easiest way needs at least as much instructions as there are pixels on the screen :)
Suspecting that bash would have to munch too long over that, I set off to make a binary and write that part in cobol (just because). Then suddenly a computer lost its memory and shortly after my monitor died.
Later, continuing on a smaller display I found that gnucobol is no longer in the debian (lmde5) repository :(
I guess I will have to build it myself.
But not now, I have had enough for today..
If you think the issue is solved, edit your original post and add the word solved to the title.
User avatar
Termy
Level 12
Level 12
Posts: 4248
Joined: Mon Sep 04, 2017 8:49 pm
Location: UK
Contact:

Re: How to check for a (partly) empty desktop

Post by Termy »

One thing I really love about i3WM is that it shares a lot of under-the-hood information which can be used when creating quick scripts and programs which conditionally manipulate the window manager. I've already been able to write two fairly simple i3WM tools based on this shared (JSON) information. I wish more traditional window managers would include this feature, because it really enriches them and provide extensibility without the need for fancy low-level libraries or something.

I have to admit, these wmctl(1) and xdotool(1) tools are great at providing access to this information via shell scripts.
I'm also Terminalforlife on GitHub.
vimes666
Level 6
Level 6
Posts: 1231
Joined: Tue Jan 19, 2016 6:08 pm

Re: How to check for a (partly) empty desktop

Post by vimes666 »

and xdotool(1) tools are great
Well either I don't understand xdotool or it is thoroughly broken. It sometimes gives me geometries that are way outside my screen resolution. The worst is that it keeps reporting minimized windows when using --onlyvisible.
After some searching I discovered xwininfo(1) to determine whether a window is minimized or not. Combined with wmctrl I now have all the info I need.
For the moment I only check whether at least one of the windows is larger than 50% of the screen size. That seems to work fine for the moment. The cobol module will have to wait a little :)

Code: Select all

#!/usr/bin/bash
# Vimes 2022.
# Dependencies: inotify-tools

myself="${0##*/}"
version="$myself - version 0.2"
echo $version
logger "${myself}[$$] Started"

# Kill other instances of myself
for pid in $(pidof -x "$myself"); do
   (( pid == $$ )) || kill -SIGINT $pid
done

# Activate sleep command as builtin. bash-builtins should be installed for
# this to work. if not sleep will be run as separate process.
enable -f /usr/lib/bash/sleep sleep

# Graceful end
trap "logger \"${myself}[$$] cancelled\"; exit 1" SIGHUP SIGINT SIGTERM SIGKILL

getwindows() {
   while read window; do
      set -- $window
      [[ "$2" = "-1" ]] && continue   # get rid of the desktop and std panel(s)
      xwininfo -id $1 | grep 'IsViewable' &> /dev/null || continue
      printf "%s\n" "$window"
   done <<<$(wmctrl -Gl)
}

notification_desired() {
   while read line; do
      set -- $line
      (( $5*$6 > $dt_size/2 )) && return 1  # do not notify when a window > desktop / 2
   done < /dev/stdin
   return 0
}

# Mainline
# ──────────────────────────────────────────────────────────────────────────────────────────

dt_width=$(xrandr | grep '*' | awk '{print $1;}' | cut -d'x' -f1)   # get desktop geometry
dt_height=$(xrandr | grep '*' | awk '{print $1;}' | cut -d'x' -f2)
dt_size=$((dt_width*dt_height))

inotifywait -qrm --event open --format='%w|%f' '/usr/share/backgrounds' | {
   while read resp; do 
      [ "$resp" = "$prev_resp" ] && continue  # filter multiples
      dir="$(cut -d'|' -f1 <<<$resp)"
      file="$(cut -d'|' -f2 <<<$resp)"
      [ -d "$dir$file" ] && continue          # filter directories
      
      if getwindows | notification_desired; then
         sleep 6                              # wait a bit for the image to settle
         notify-send -u low -i "$HOME/.icons/feather-orange/image.svg" "$file" "From: $dir"
         prev_resp="$resp"
      fi
   done
}

logger "${myself}[$$] exiting, inotifywait was terminated"
exit 1
If you think the issue is solved, edit your original post and add the word solved to the title.
Locked

Return to “Scripts & Bash”