Ceci est similaire à placez rapidement une fenêtre sur un autre écran en utilisant uniquement le clavier , mais je veux pouvoir utiliser la ligne de commande (de sorte que tout ce que j'ai à faire est de rappeler la ligne de commande à partir du histoire de bash).
Par exemple, envoyer
eDP1
,VGA1
, etHDMI1
(et les maximiser après avoir déménagé - mais pas les fous F11 manière, la maximisation normale du style de gestionnaire de fenêtre).
Je voudrais spécifier windows par le nom de l'exécutable.
Le script ci-dessous envoie des fenêtres, appartenant à un WM_CLASS
(application) spécifique, à un écran spécifique, par le nom de l'écran . Comment cela est fait est expliqué dans le script et également plus loin.
Le script suppose que les écrans sont disposés horizontalement et plus ou moins alignés en haut (avec une différence <100 PX).
#!/usr/bin/env python3
import subprocess
import sys
# just a helper function, to reduce the amount of code
get = lambda cmd: subprocess.check_output(cmd).decode("utf-8")
# get the data on all currently connected screens, their x-resolution
screendata = [l.split() for l in get(["xrandr"]).splitlines() if " connected" in l]
screendata = sum([[(w[0], s.split("+")[-2]) for s in w if s.count("+") == 2] for w in screendata], [])
def get_class(classname):
# function to get all windows that belong to a specific window class (application)
w_list = [l.split()[0] for l in get(["wmctrl", "-l"]).splitlines()]
return [w for w in w_list if classname in get(["xprop", "-id", w])]
scr = sys.argv[2]
try:
# determine the left position of the targeted screen (x)
pos = [sc for sc in screendata if sc[0] == scr][0]
except IndexError:
# warning if the screen's name is incorrect (does not exist)
print(scr, "does not exist. Check the screen name")
else:
for w in get_class(sys.argv[1]):
# first move and resize the window, to make sure it fits completely inside the targeted screen
# else the next command will fail...
subprocess.Popen(["wmctrl", "-ir", w, "-e", "0,"+str(int(pos[1])+100)+",100,300,300"])
# maximize the window on its new screen
subprocess.Popen(["xdotool", "windowsize", "-sync", w, "100%", "100%"])
Le script nécessite à la fois wmctrl
et xdotool
:
Sudo apt-get install xdotool wmctrl
Copiez le script ci-dessous dans un fichier vide, enregistrez-le sous le nom move_wclass.py
Exécutez-le à l'aide de la commande:
python3 /path/to/move_wclass.py <WM_CLASS> <targeted_screen>
par exemple:
python3 /path/to/move_wclass.py gnome-terminal VGA-1
Pour le WM_CLASS
, vous pouvez utiliser la partie du WM_CLASS
, comme dans l'exemple. Le nom de l'écran doit être le exact et le nom complet.
L'explication porte principalement sur le concept, pas tellement sur le codage.
Dans la sortie de xrandr, pour chaque écran connecté, il y a une chaîne/ligne, ressemblant à:
VGA-1 connected 1280x1024+1680+0
Cette ligne nous donne des informations sur la position de l'écran et son nom , comme expliqué ici .
Le script répertorie les informations pour tous les écrans. Lorsque le script est exécuté avec l'écran et la classe window comme arguments, il recherche la position (x-) de l'écran, toutes les fenêtres (-id's) d'une certaine classe (à l'aide de wmctrl -l
et la sortie de xprop -id <window_id>
.
Par la suite, le script déplace toutes les fenêtres, une par une, vers une position sur l'écran ciblé (à l'aide de wmctrl -ir <window_id> -e 0,<x>,<y>,<width>,<height>
) et l'agrandit (avec xdotool windowsize 100% 100%
).
Le script a bien fonctionné sur les tests avec lesquels je l'ai exécuté. Utiliser wmctrl
, et même xdotool
, sur Unity peut présenter certaines particularités tenaces, qui doivent parfois être résolues par l'expérience plutôt que par le raisonnement. Si vous rencontrez des exceptions, veuillez mentionner.
J'ai réécrit le code @jacobs python en bash simple et en le faisant fonctionner (j'ai testé cela sur ubuntu 16 cannelle).
Je devais ajouter remove,maximized_vert, remove,maximized_horz
sans que Windows ne bouge pas.
#!/bin/bash
if [ ! -z "$1" ] || [ -z "$2" ]; then
command=$(wmctrl -l | grep $1 | cut -d" " -f1)
if [ ! -z "$command" ]; then
position=$(xrandr | grep "^$2" | cut -d"+" -f2)
if [ ! -z "$position" ]; then
for window in $command; do
wmctrl -ir $window -b remove,maximized_vert
wmctrl -ir $window -b remove,maximized_horz
wmctrl -ir $window -e 0,$position,0,1920,1080
wmctrl -ir $window -b add,maximized_vert
wmctrl -ir $window -b add,maximized_horz
done
else
echo -e "not found monitor with given name"
fi
else
echo -e "not found windows with given name"
fi
else
echo -e "specify window and monitor name;\nmove.sh window-name monitor-name"
fi
Sudo apt-get install xdotool wmctrl
/path/to/script.sh "window-name" "monitor-name"
Pour mémoire, voici ce que j’utilise pour combiner cette question et Restaurer plusieurs paramètres de moniteur :
# configure multiplr displays and
# move the windows to their appropriate displays
import subprocess
import os
import wmctrl
import re
mydisplays = [("VGA1",0,"left"),
("eDP1",1080,"normal"),
("HDMI1",3000,"left")]
# https://askubuntu.com/questions/702002/restore-multiple-monitor-settings
def set_displays ():
subprocess.check_call(" && ".join([
"xrandr --output %s --pos %dx0 --rotate %s" % d for d in mydisplays]),
Shell=True)
# https://askubuntu.com/questions/702071/move-windows-to-specific-screens-using-the-command-line
mywindows = [("/emacs$","VGA1"),
("/chrome$","HDMI1"),
("gnome-terminal","eDP1")]
def max_windows ():
didi = dict([(d,x) for d,x,_ in mydisplays])
for w in wmctrl.Window.list():
try:
exe = os.readlink("/proc/%d/exe" % (w.pid))
for (r,d) in mywindows:
if re.search(r,exe):
x = didi[d]
print "%s(%s) --> %s (%d)" % (r,exe,d,x)
w.set_properties(("remove","maximized_vert","maximized_horz"))
w.resize_and_move(x,0,w.w,w.h)
w.set_properties(("add","maximized_vert","maximized_horz"))
break
except OSError:
continue
def cmdlines (cmd):
return subprocess.check_output(cmd).splitlines()
def show_displays ():
for l in cmdlines(["xrandr"]):
if " connected " in l:
print l
if __== '__main__':
show_displays()
set_displays()
show_displays()
max_windows()
vous auriez besoin d'utiliser wmctrl version 0.3 ou ultérieure (à cause de ma requête d'extraction ).