How can I minimize windows, only on a specific monitor?

I have monitor and laptop screen and have a problem with the "Show desktop" function.

Laptop screen is showing widget that should stay for all the time. Main monitor is used normally.

Whenever I use keyboard shortcut (windows key + d in my case), all windows will be hidden but I only want to hide all the windows on the specific monitor.

Is this possible?

Question similar to https://superuser.com/questions/200945/how-can-i-make-the-show-desktop-function-only-hide-the-windows-on-a-specific-m, with notable difference that I ask about different OS.


Solution 1:

Only minimize windows on one screen

The script below can be used to (only) minimize windows on the left screen or only on the right screen.

The script is run with either 1 or 2 as argument, depending on which screen you'd like to minimize the windows.

The script

#!/usr/bin/env python3
import subprocess
import sys

scr = sys.argv[1]

def get(cmd):
    return subprocess.check_output(cmd).decode("utf-8")

# find the right side of the left screen
edge = [int(s.split("x")[0]) for s in get("xrandr").split() if "+0+" in s][0]
# read the window list
wlist = [w.split() for w in get(["wmctrl", "-lG"]).splitlines()]
for w in wlist:
    # retrieve the window id and -position
    w_id = w[0]; xpos = int(w[2])
    # check the position of the window, decide action depending on arg.
    test = xpos < edge if scr == "1" else xpos >= edge
    if test:
        # check if the window is "normal" and / or minimized
        w_data = get(["xprop", "-id", w_id])
        if all([not "_NET_WM_STATE_HIDDEN" in w_data,
                    "_NET_WM_WINDOW_TYPE_NORMAL" in w_data]):
            subprocess.Popen(["xdotool", "windowminimize", w_id])

How to use

  1. The script needs both wmctrl and xdotool

    sudo apt-get install xdotool wmctrl
    
  2. Copy the script into an empty file, save it as min_screen.py

  3. To run it:

    python3 /path/to/min_screen.py 1
    

    to minimize windows on the left screen, and

    python3 /path/to/min_screen.py 2 
    

    to minimize windows only on the right screen

  4. If all works fine, add it to a shortcut key

Notes

  • The script assumes python3 is installed, but the code is not python3 specific I believe.
  • The script was written on Unity, but unlike workspaces (viewports), handling the screens should not make a difference.
  • The script will not minimize windows with pid 0 (Idle or other tkinterwindows for example). If that is an issue, please mention. Can be solved.

Explanation

The script first looks up the right edge of the left screen, by looking up the string with +0+ in the output of xrandr, looking like:

1680x1050+0+0

The first section, 1680, is the widht of the left screen. Subsequently, all we have to do is look into the window list (wmctrl -lG) and see which of the windows is "below" or "above" 1680, and act accordingly, minimizing with the command xdotool windowminimize <window_id> (or not).

Th "test" finally (mmiz): xprop -id <window_id> is to check if we are dealing with a "normal" window (instead of e.g. your desktop, which is also listed as a window), and if the window is already minimized.

See also the comment in the script.

Binding the script to a keyboard shortcut

1. On Lubuntu

To edit global keyboard shortcuts in Lubuntu see Lubuntu minimize all show desktop keyboard shortcut?

In this case: save script from this answer into a file on the computer, make this file executable, open /.config/openbox/lubuntu-rc.xml and replace

  <keybind key="W-d">
    <action name="ToggleShowDesktop"/>
  </keybind>

by

  <action name="Execute">
   <command>/path/to/show_desktop.py 1</command>
  </action>

where /path/to/show_desktop.pyis (of course) the path to the script, and either 1 or 2 the targeted screen. Make the script executable.

Restart computer to reload config.

2. Unity/Gnome

Make the script executable and choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command:

/path/to/show_desktop.py 1

...to a shortcut of your choice

Solution 2:

Introduction

The script below allows user to click on a display they want, and all windows on that display will be minimized. This script is meant to be bound to a keyboard shortcut, but can run manually if so desired.

Usage is simple:

  1. activate the script, your mouse cursor will turn into a cross
  2. Click on any program window ( but not desktop ) on the display you wish to minimize.
  3. The script will determine all the windows on that display , and minimize ( iconify ) them.

The program doesn't require any additional packages to be installed. The script has been tested on regular Ubuntu 16.04 LTS and Lubuntu 16.04 LTS. Thanks to @JourneymanGeek for testing it on Fedora 24 with KDE as well !

Obtaining the script source code

The script source code can be obtained by manually copying it here, or by getting it from my github repository. To obtain it via git follow these steps:

  1. sudo apt-get install git
  2. cd /opt ; sudo git clone https://github.com/SergKolo/sergrep.git
  3. sudo chmod -R +x sergrep

The file will be called minimize_display_windows.py . Make sure when you bind that to a keyboard shortcut to provide full path to the script. For instance, like so:

 python /opt/sergrep/minimize_display_windows.py

Source code

Ensure the file you save this code to, has executable permissions.

#!/usr/bin/env python
#
###########################################################
# Author: Serg Kolo , contact: [email protected] 
# Date: July 3, 2016
# Purpose:  Minimize windows on a display which user clicks
# Written for: http://askubuntu.com/q/793195/295286  
# Tested on: Ubuntu 16.04 LTS,Lubuntu 16.04 Virtual Machine
###########################################################
# Copyright: Serg Kolo , 2016
#    
#     Permission to use,copy,modify,and distribute this software is hereby granted
#     without fee, provided that  the copyright notice above and this permission statement
#     appear in all copies.
#
#     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
#     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#     DEALINGS IN THE SOFTWARE.
#
#     https://opensource.org/licenses/MIT

from gi.repository import GdkX11,Gdk
import subprocess

def run_sh(cmd):
    # reusable function to 
    # run shell commands
    # Returns stdout of the
    # process
    proc = subprocess.Popen(cmd, shell=True,stdout=subprocess.PIPE)
    out = proc.stdout.read().strip()
    return out 

# First,let the user click on any window
# on the monitor which they want to minimize.
# For that we need to extract integer XID of
# the window from xwininfo output.
# Basically,same as xwininfo -int | awk '/Window id/{print $4}'

user_selected = ""
for item in run_sh("xwininfo -int").split("\n"):
    if "Window id" in item:
       user_selected = item.split()[3]

# Here we basically get all the windows on the screen,
# and check if their XID matches the one user selected
# Once we find that window, we need to know to what display
# that window belongs. 
screen =  Gdk.Screen.get_default()
for window in screen.get_window_stack():
    if str(window.get_xid()) == user_selected:
       close_screen = int(screen.get_monitor_at_window(window))

# We know which display to close now. Loop over all
# windows again, and if they're on the same display
# the one that user chose - iconify it ( in X11 terminology
# that means minimize the window  )
for window in screen.get_window_stack():
    if screen.get_monitor_at_window(window) == close_screen :
       window.iconify()

Demo

A short recording of the script in action can be found on my youtube channel

Side-notes

Originally , I've written another script , but it can only be used in Unity and requires xdotool to be present. For those interested it is posted as gist