10

I have a small shell script that plays a little jingle and displays a notification whenever I get a new email.

The problem is that this shell script can get invoked anytime - including when I'm watching a DVD / video in fullscreen mode with the sound turned up quite a bit - which is quite annoying.

I'd like to enhance this script with the ability to detect whether an application is in fullscreen mode. I know this must be somehow possible because notifications don't display under those circumstances.

What command can I use?

1

4 Answers 4

12

Kind of extreme overkill as a shell script, but it should do the trick:

#!/bin/bash
WINDOW=$(echo $(xwininfo -id $(xdotool getactivewindow) -stats | \
                egrep '(Width|Height):' | \
                awk '{print $NF}') | \
         sed -e 's/ /x/')
SCREEN=$(xdpyinfo | grep -m1 dimensions | awk '{print $2}')
if [ "$WINDOW" = "$SCREEN" ]; then
    exit 0
else
    exit 1
fi

Then you can check it:

if is-full-screen ; then echo yup, full screen ; fi

As pointed out below, you'll need to install xdotool first:

sudo apt-get install xdotool
1
  • 1
    Wow... +1 for such an in-depth script. One thing to note: xdotool is a separate package that isn't installed by default. Mar 15, 2011 at 3:18
4

I feel obligated to make a few comments (simplifications):

  1. The above shell code uses the anti-pattern ... | grep | awk. Whenever you see grep | awk, you can replace it with a single invocation of awk. I see this anti-pattern frequently in online help posts/forums. My sense is that most know this and that in real-world code, most people know better, but that, for some reason, it is viewed as pedagogically superior to write it this way (i.e., as grep | awk. But it still annoys me to see it.

  2. I think the above idea can be simplified to:

    # Initializations section of your shell script:
    root_geo="$(xwininfo -root | grep geometry)"
    
    # In the loop:
    [ "$(xwininfo -id $(xdotool getactivewindow) | grep geometry)" = "$root_geo" ] && echo "Running fullscreen"
    
3
  • Happy to be your first upvote ever for any answer and this one is a great rewrite of accepted answer. That said neither answer works on a multi-monitor system. Nov 20, 2019 at 2:11
  • @WinEunuuchs2Unix have you find a solution for multi-monitor system?
    – diralik
    Apr 7, 2022 at 11:50
  • @diralik I don't remember what project I was working on when I posted the comment. So I can't open it up to see what was done (if anything). Apr 8, 2022 at 11:08
2

Here is an alternative, building on top of the answer by @JoeSchmoe, that does not rely on external scripts but also works slightly differently: It does not care whether the fullscreen window is focused.

# Get screen size
root_geo=$(xwininfo -root | awk -F'[ +]' '$3 ~ /-geometry/ {print $4}')
# Check if any window fills the screen
xwininfo -root -tree | grep $root_geo | grep -qv "\(Desktop\|has no name\)"

If there is any window that covers the whole screen, the last command will return exit code 0, otherwise 1. Note that this was devised on KDE Plasma as a desktop - you may need to adjust it for other desktop environments, see below.

Explanation

It first obtains the measurements of the screen and saves it to root_geo. For single time-use, you can also inline that call.

Multiple screens

For multiple screens, if both have the same resolution, you can either hard-code it or modify awk to do this calculation automatically (this assumes they are arranged horizontally):

xwininfo -root | awk -F'[ +x]' '$3 ~ /-geometry/ {printf "%dx%d",$4/2,$5}'

Furthermore, this should get the number of screens you have connected:

xrandr | grep ' connected ' | wc -l

So, putting it together, this should work for any number of screens, as long as they are arranged horizontally without whitespace in between and have the same resolution (quite useful if you use a Laptop and regularly connect to external screens):

root_geo=$(xwininfo -root | awk -F'[ +x]' '$3 ~ /-geometry/ {printf "%dx%d",$4/'"$(xrandr | grep ' connected ' | wc -l)"',$5}')

If they have different resolutions or are arranged in a different way, you could also use xrandr to obtain the resolution for each and construct a regex that matches any of them. Note that this may falsely match on a window that matches the exact dimensions of another screen in a bigger one. You could construct something that matches on the respective screen to remedy this, but I won't dig that deep here.

Checking for fullscreen windows

xwininfo -root -tree | grep $root_geo | grep -qv "\(Desktop\|has no name\)"

Here, you may have to adjust the last pattern.
What this command does is list all existing windows, including your desktop, in a tree-like fashion. So after filtering for the ones that cover the whole screen, you also have to filter out the ones that are there anyways. The easiest way to check is to run the command without the last grep, which produced the following output for me (using KDE Plasma as desktop):

❯ xwininfo -root -tree | grep $root_geo
     0xe001cd (has no name): ()  1920x1080+1920+0  +1920+0
        0xe001ce (has no name): ()  1920x1080+0+0  +1920+0
           0x1e00180 "Desktop — Plasma": ("plasmashell" "plasmashell")  1920x1080+0+0  +1920+0
     0xe0001e (has no name): ()  1920x1080+0+0  +0+0
        0xe0001f (has no name): ()  1920x1080+0+0  +0+0
           0x1e0000b "Desktop — Plasma": ("plasmashell" "plasmashell")  1920x1080+0+0  +0+0

Thus, grepping out Desktop and "has no name" (which seems to be a sort of grouping) was sufficient here.

0

In recent versions of Ubuntu some windows, such as gnome-terminal, are protected from access via xdotool, wmctrl, etc., so unless you use an extension like Unsafe Mode Menu the best you can do is detect if some windows are full screen, which is good enough for Chrome, VLC, Plex, etc.

With that in mind, I modified the accepted script to gracefully handle failing to get window information, as it was hanging:

#!/bin/bash
ACTIVE_WIN=$(xdotool getactivewindow 2>/dev/null)
if [ -z "$ACTIVE_WIN" ]; then
    # protected window that can't be analyzed, e.g. gnome-terminal
    echo "Failed to get active win"
    exit 1
fi
WINDOW=$(echo $(xwininfo -id $ACTIVE_WIN -stats | \
                egrep '(Width|Height):' | \
                awk '{print $NF}') | \
         sed -e 's/ /x/')
SCREEN=$(xdpyinfo | grep -m1 dimensions | awk '{print $2}')
if [ "$WINDOW" = "$SCREEN" ]; then
    exit 0
else
    exit 1
fi

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .