Je me demande s'il y a un moyen quelconque d'obtenir l'effet des raccourcis clavier Ctrl-Alt-Clavier dans Unity en utilisant plutôt les commandes de terminal. Je veux une commande qui définit une fenêtre graphique à la moitié de la taille de l’écran, alignée à gauche ou à droite.
En guise d'arrière-plan, j'écris un script qui s'exécute après la connexion. Il utilise Zenity pour demander si je veux ou non ouvrir mon environnement de développement (GVim et IPython côte à côte). J'ai essayé d'obtenir deux fenêtres de taille égale pour ces programmes en utilisant set lines= columns=
dans mon .gvimrc
et c.IPythonWidget.width =
et c.IPythonWidget.height =
dans mon ipython_qtconsole_config.py
. Cependant, cette approche pose des problèmes.
Si vous souhaitez d'abord appeler une application, puis placer sa fenêtre sur une position et une taille spécifiques, le temps entre appel de l'application et au moment où la fenêtre apparaît réellement, est imprévisible. Si votre système est occupé, il peut être considérablement plus long que s'il est inactif.
Vous avez besoin d'un moyen "intelligent" pour vous assurer que le positionnement/redimensionnement est fait (immédiatement) après la fenêtre apparaît.
Avec le script ci-dessous, vous pouvez appeler une application et définir la position et la taille sur lesquelles elle doit apparaître avec la commande:
<script> <application> <x-position> <y-position> <h-size> <v-size>
Quelques exemples:
Pour appeler gnome-terminal
et redimensionner sa fenêtre à 50% et la placer dans la moitié droite:
<script> gnome-terminal 840 0 50 100
Pour appeler gedit
, placez sa fenêtre à gauche et appelez gnome-terminal
, placez-la à droite (définissez son v-size
46% pour lui laisser un peu d'espace entre les fenêtres):
<script> gedit 0 0 46 100&&<script> gnome-terminal 860 0 46 100
Pour appeler Inkscape, placez sa fenêtre dans le quart gauche/supérieur de l’écran:
<script> inkscape 0 0 50 50
installez à la fois xdotool
et wmctrl
. J'ai utilisé les deux car le redimensionnement avec wmctrl
peut causer des particularités sur (plus précisément) Unity
.
Sudo apt-get install wmctrl
Sudo apt-get install xdotool
setwindow
(sans extension) dans ~/bin
; créez le répertoire si nécessaire.~bin
, exécutez: source ~/.profile
Exécuter le script avec la commande (par exemple)
setwindow gnome-terminal 0 0 50 100
En d'autres termes:
setwindow <application> <horizontal-position> <vertical-position> <horizontal-size (%)> <vertical-size (%)>
Si tout fonctionne bien, utilisez la commande où vous en avez besoin.
#!/usr/bin/env python3
import subprocess
import time
import sys
app = sys.argv[1]
get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8")
ws1 = get("wmctrl -lp"); t = 0
subprocess.Popen(["/bin/bash", "-c", app])
while t < 30:
ws2 = [w.split()[0:3] for w in get("wmctrl -lp").splitlines() if not w in ws1]
procs = [[(p, w[0]) for p in get("ps -e ww").splitlines() \
if app in p and w[2] in p] for w in ws2]
if len(procs) > 0:
w_id = procs[0][0][1]
cmd1 = "wmctrl -ir "+w_id+" -b remove,maximized_horz"
cmd2 = "wmctrl -ir "+w_id+" -b remove,maximized_vert"
cmd3 = "xdotool windowsize --sync "+procs[0][0][1]+" "+sys.argv[4]+"% "+sys.argv[5]+"%"
cmd4 = "xdotool windowmove "+procs[0][0][1]+" "+sys.argv[2]+" "+sys.argv[3]
for cmd in [cmd1, cmd2, cmd3, cmd4]:
subprocess.call(["/bin/bash", "-c", cmd])
break
time.sleep(0.5)
t = t+1
Lorsque le script est appelé, il:
wmctrl -lp
)ps -ef ww
, en comparant le pid de la fenêtre au pid de l'application)Dans Unity, lorsque vous (re) positionnez et (re) taillez une fenêtre avec wmctrl
ou xdotool
, la fenêtre conservera toujours une petite marge sur les bordures de votre écran, sauf si vous la définissez à 100%. Vous pouvez voir cela dans l'image (3) ci-dessus; alors que la fenêtre inkscape
a été placée à x
position 0, vous pouvez toujours voir une marge mineure entre Unity Launcher et la fenêtre inkscape
.
J'ai construit une application nommée Worksets (sur github ) pour Unity qui vous permet de le faire facilement via une interface utilisateur graphique - C'est une source gratuite et ouverte.
Il s’agit en fait d’un wrapper pour les solutions wmctrl et xdotool répertoriées ici en tant que réponses, et offre un moyen simple de créer et d’enregistrer rapidement de telles configurations.
Vous pouvez le faire en utilisant xdotool
name__.
Pour installer xdotool
vous pouvez exécuter:
Sudo apt-get update && Sudo apt-get install xdotool
Puis envoyer un Ctrl+Alt+<keypad_key> Une frappe sur la fenêtre du terminal X
que vous pouvez exécuter:
xdotool key Ctrl+Alt+<keypad_key_value>
* <keypad_key_value> = la valeur de la touche du clavier dans la liste ci-dessous
Pour exécuter un programme graphique et envoyer la frappe à sa fenêtre X
(qui dans ce cas est la fenêtre active au moment de l'exécution de la commande xdotool
name__), vous pouvez exécuter:
<command> && window="$(xdotool getactivewindow)" xdotool key --delay <delay> --window "$window" <keypad_key_value>
* <commande> = commande qui ouvre la fenêtre à laquelle vous souhaitez envoyer la frappe; <délai> = temps d'attente en millisecondes avant l'envoi de la frappe; <keypad_key_value> = valeur de la touche du clavier dans la liste ci-dessous
Notez que dans la plupart des cas, vous devrez exécuter la commande émise en tant que processus autonome (par exemple, en exécutant Nohup <command> &
au lieu de <command>
dans l'exemple ci-dessus), sinon xdotool
ne sera pas exécuté tant que l'exécution de <command>
ne sera pas terminée.
Vous devrez également définir un délai, sinon la frappe sera envoyée avant le chargement complet de la fenêtre cible dans X
(un délai autour de 500ms
devrait suffire).
Les valeurs possibles pour <keypad_key_value>
sont:
90
87
88
89
83
84
85
79
80
81
En règle générale, pour connaître la valeur de n'importe quelle touche du clavier dans l'environnement X
name__, vous pouvez exécuter xev
et appuyer sur la touche pour afficher sa valeur à l'intérieur du terminal.
La commande réelle que vous voulez est quelque chose comme
wmctrl -r :ACTIVE: -b add,maximized_vert &&
wmctrl -r :ACTIVE: -e 0,0,0,$HALF,-1
Cela fera que la fenêtre actuelle occupera la moitié de l’écran (changerez $HALF
en fonction des dimensions de votre écran) et s’accrochant à gauche. Pour accrocher à droite, utilisez
wmctrl -r :ACTIVE: -b add,maximized_vert &&
wmctrl -r :ACTIVE: -e 0,$HALF,0,$HALF,-1
Vous pouvez également jouer avec wmctrl
pour obtenir l'ID des fenêtres qui vous intéressent au lieu d'utiliser :ACTIVE:
. Je ne peux rien y faire car cela dépend des fenêtres en question. Regardez man wmctrl
pour plus.
J'ai écrit un script pour ça. Je n'utilise pas Unity, je ne peux donc pas en garantir le fonctionnement, mais je ne vois pas pourquoi. Il faut que wmctrl
name__, xdpyinfo
et disper
soit installé:
Sudo apt-get install wmctrl x11-utils disper
Enregistrez ensuite le script ci-dessous sous le nom ~/bin/snap_windows.sh
, rendez-le exécutable avec chmod a+x ~/bin/snap_windows.sh
et vous pourrez exécuter
snap_windows.sh r
Pour accrocher sur le côté droit. Utilisez l
pour le côté gauche et aucun argument pour agrandir la fenêtre. Notez qu’il s’exécute sur la fenêtre en cours, vous devrez donc lui attribuer un raccourci si vous souhaitez qu’elle s’exécute sur autre chose que le terminal.
Le script est un peu plus compliqué que ce que vous demandez, car je l’ai écrit pour fonctionner à la fois sur des configurations à simple et à double moniteur.
#!/usr/bin/env bash
## If no side has been given, maximize the current window and exit
if [ ! $1 ]
then
wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz
exit
fi
## If a side has been given, continue
side=$1;
## How many screens are there?
screens=`disper -l | grep -c display`
## Get screen dimensions
WIDTH=`xdpyinfo | grep 'dimensions:' | cut -f 2 -d ':' | cut -f 1 -d 'x'`;
HALF=$(($WIDTH/2));
## If we are running on one screen, snap to Edge of screen
if [ $screens == '1' ]
then
## Snap to the left hand side
if [ $side == 'l' ]
then
## wmctrl format: gravity,posx,posy,width,height
wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,0,0,$HALF,-1
## Snap to the right hand side
else
wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$HALF,0,$HALF,-1
fi
## If we are running on two screens, snap to Edge of right hand screen
## I use 1600 because I know it is the size of my laptop display
## and that it is not the same as that of my 2nd monitor.
else
LAPTOP=1600; ## Change this as approrpiate for your setup.
let "WIDTH-=LAPTOP";
SCREEN=$LAPTOP;
HALF=$(($WIDTH/2));
if [ $side == 'l' ]
then
wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$LAPTOP,0,$HALF,-1
else
let "SCREEN += HALF+2";
wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$SCREEN,0,$HALF,-1;
fi
fi
Je n'ai pas le représentant à commenter directement sur l'excellent post de Jacob Vlijm, mais j'ai modifié le script pour permettre de démarrer une application avec des arguments (nécessaire pour utiliser setwindow
avec gedit --new-window
). Changement:
if app in p and w[2] in p] for w in ws2]
à:
if app.split()[0] in p and w[2] in p] for w in ws2]
J'ai joué avec le script de Terdon d'en haut et j'ai ajouté de nouvelles choses (possibilité de sélectionner le moniteur et de régler la hauteur pour chaque moniteur). Ce serait extensible à ajouter plus de moniteurs, je pense. J'espère que d'autres le trouveront utile.
syntaxe de base:
prog_name monitor l/r/m window_name (optional)
Où nom_prog est ce que vous avez enregistré sous ce code; moniteur est le numéro du moniteur, par exemple. 1 ou 2; l/r/m est à gauche ou à droite ou max; et window_name est le nom (ou une fraction de son nom) de la fenêtre cible.
Par exemple.:
setwindow 1 m chrome
#!/usr/bin/env bash
set -e
#######################- Early Definitions -#######################
snap () {
wmctrl -r ${WIN} -b toggle,add,maximized_vert && wmctrl -r ${WIN} -e 0,${WINX},0,${WINWIDTH},${WINHEIGHT}
}
DISPLAYWIDTH=`xdpyinfo | grep 'dimensions:' | cut -f 2 -d ':' | cut -f 1 -d 'x'`; ## Get screen dimensions
LEFTSCREENWIDTH=1024 ## user set
LEFTSCREENHEIGHT=720 ## user set
RIGHTSCREENHEIGHT=960 ## user set
let "RIGHTSCREENWIDTH=(DISPLAYWIDTH-LEFTSCREENWIDTH)"
#############################- Logic -#############################
if [ ! ${3} ]; then
WIN=":ACTIVE:"
else
WIN=${3}
fi
case ${1} in
1) # monitor one
LEFT=0
WINHEIGHT=${LEFTSCREENHEIGHT}
let "WINWIDTH=LEFTSCREENWIDTH/2"
;;
2) # monitor two
let "LEFT=LEFTSCREENWIDTH"
WINHEIGHT=${RIGHTSCREENHEIGHT}
let "WINWIDTH=RIGHTSCREENWIDTH/2"
;;
"") # error please select a monitor
echo "please select a monitor (1 or 2)"
exit 0
;;
esac
case ${2} in
l|L)
WINX=${LEFT}
snap
;;
r|R)
let "WINX=LEFT+WINWIDTH"
snap
;;
""|m|M)
WINX=${LEFT}
let "WINWIDTH=WINWIDTH*2"
snap
;;
esac
exit 0