web-dev-qa-db-fra.com

Programme Bash pour ouvrir des fichiers sur un deuxième moniteur

J'ai écrit un petit script en bash qui ouvre un fichier et le ferme cinq minutes plus tard. Il répète cette procédure encore et encore.

Le problème est que, quel que soit le point de la souris sur lequel le programme est ouvert, j'aimerais qu'il soit ouvert sur mon deuxième moniteur, ce qui est la taille idéale pour la visualisation du fichier.

J'ai essayé d'utiliser les variables d'affichage de la manière suivante (sur la ligne de commande), exportez DISPLAY =: 0.1. Mais quel que soit le programme que j'appelle à partir de la CLI après cette erreur, une erreur est renvoyée. (Erreur: impossible d'ouvrir l'affichage: 0.1)

Quelqu'un a-t-il une suggestion?

modifier:

Voici le script pour ouvrir un fichier appelé thesis.pdf toutes les cinq minutes

#! /bin/bash

while true; do
    evince /home/adam/Desktop/Thesis.pdf &
    sleep 5m
    ps -ef | grep "Thesis.pdf" | awk '{print $2}' | xargs kill
done

exit 0
3
Adam

Pour positionner une fenêtre, vous pouvez utiliser un outil manipulant des événements X tels que xdotool ou wmctrl. Par exemple, avec wmctrl, vous pouvez utiliser -e:

   -e <MVARG>
          Resize  and  move  a  window  that  has been specified with a -r
          action according to the <MVARG> argument.
   <MVARG>
          A move and resize argument has the format 'g,x,y,w,h'.  All five
          components are integers. The first value, g, is the  gravity  of
          the  window,  with  0  being  the most common value (the default
          value for the window). Please see  the  EWMH  specification  for
          other values.

          The four remaining values are a standard geometry specification:
          x,y is the position of the top left corner of  the  window,  and
          w,h  is  the  width and height of the window, with the exception
          that the value of -1 in any position is interpreted to mean that
          the current geometry value should not be modified.

Vous pouvez généralement ignorer la gravité. Pour placer une fenêtre dans le coin supérieur gauche de votre écran et la définir en 1200 x 700 pixels, vous devez exécuter:

wmctrl -r :ACTIVE: -e 1,1,1,1200,700

Le -r vous permet de sélectionner une fenêtre et :ACTIVE: désigne la fenêtre en cours de mise au point.

Vous pouvez également simplifier votre script. Il n'y a aucune raison d'analyser ps, la variable spéciale $! contient le PID du travail le plus récemment placé en arrière-plan. Dans tous les cas, l'analyse de ps échouera souvent car il pourrait y avoir plusieurs processus correspondant à Thesis.pdf. Il y en aura toujours deux: la evince et le grep Thesis.pdf que vous venez d'exécuter.

Donc, avec tout cela en tête, vous pourriez faire:

#! /bin/bash
while true; do
    ## Open the pdf
    evince ~/doc/a.pdf &
    ## Save the PID of evince
    pid="$!"
    ## Wait for a 1.5 seconds. This is to give the window time to
    ## appear. Change it to a higher value if your system is slower. 
    sleep 1.5
    ## Get the X name of the evince window
    name=$(wmctrl -lp | awk -vpid="$pid" '$3==pid{print $1}')
    ## Position the window
    wmctrl -ir "$name" -e 1,1,1,1200,700
    ## Wait
    sleep 5m
    ## Close it
    kill "$pid"
done

Notez que j'ai enlevé le exit 0 puisque, à cause de votre while true, il ne sera jamais atteint et il ne sert à rien. Vous pouvez jouer avec les arguments de position pour déterminer où vous voulez placer la fenêtre.

Enfin, une note sur DISPLAY. Cette variable pointe vers un affichage X. Ce n'est pas un écran, c'est le serveur X actif. De nombreux utilisateurs peuvent exécuter des serveurs X parallèles sur une seule machine. Cela vous permet de choisir sur lequel une fenêtre doit être affichée. Cela n'a absolument rien à voir avec le nombre d'écrans physiques connectés, sauf si chaque écran exécute une session X distincte.

5
terdon

Cette réponse suppose que vous utilisez Unity:

Ce que vous rencontrerez lors de l'écriture d'un script pour ouvrir une application sur un écran ou un poste spécifique

Si vous souhaitez appeler une application et, par la suite, placer sa fenêtre sur une position et une taille spécifiques, le temps entre l'appel de l'application et le moment où la fenêtre effectivement apparaît , est essentiel, mais 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 (de préférence "intelligent") pour vous assurer que le positionnement/redimensionnement est effectué (immédiatement) après l’affichage de la fenêtre.

Le script ci-dessous (une version modifiée de celle-ci ) ouvre une application, éventuellement avec le fichier en tant qu'argument, à n'importe quel emplacement du bureau (également sur le second moniteur). Il attend que la fenêtre apparaisse avant de la déplacer à sa position et à sa taille. Elle fonctionnera donc correctement, que votre système soit lent (ou occupé) ou non.

Le scénario

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

app = (" ").join(sys.argv[5:])

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[3]+"% "+sys.argv[4]+"%"
        cmd4 = "xdotool windowmove "+procs[0][0][1]+" "+sys.argv[1]+" "+sys.argv[2]
        for cmd in [cmd1, cmd2, cmd3, cmd4]:   
            subprocess.call(["/bin/bash", "-c", cmd])
        break
    time.sleep(0.5)
    t = t+1


Comment l'utiliser

  1. installez à la fois xdotool et wmctrl. J'ai utilisé les deux depuis le redimensionnement avec wmctrl peut causer des particularités sur (spécifiquement) Unity.

    Sudo apt-get install wmctrl
    Sudo apt-get install xdotool
    
  2. Copiez le script ci-dessous dans un fichier vide, enregistrez-le sous le nom setwindow (sans extension) dans ~/bin; créez le répertoire si nécessaire.

  3. Rendre le script exécutable (!)
  4. Si vous venez de créer ~bin, exécutez: source ~/.profile
  5. Test-exécuter le script avec la commande comme (par exemple)

    setwindow 0 0 50 100 gedit /path/to/file.txt
    

    En d'autres termes:

    setwindow <horizontal-position> <vertical-position> <horizontal-size (%)> <vertical-size (%)> <application> <file_to_open>
    

Si tout fonctionne bien, utilisez la commande où vous en avez besoin.

Pour ouvrir l'application sur le moniteur à droite

Si vous avez un deuxième moniteur connecté, envisagez les écrans combinés comme un seul grand bureau virtuel, comme dans l'exemple ci-dessous.

enter image description here

Dans cet exemple, pour placer la fenêtre sur l'écran de droite, il vous suffit de définir une position x supérieure à la résolution x de l'écran de gauche. (> 1680 dans ce cas).

Pour ouvrir le fichier avec votre application de manière maximale, définissez <horizontal-size (%)> et <vertical-size (%)> sur 100.

Problème mineur

Dans Unity, lorsque vous (re) positionnez et (re) taillez une fenêtre avec wmctrl ou xdotool, la fenêtre conservera toujours une petite marge par rapport aux bordures de votre écran, sauf si vous définissez à 100%. Vous pouvez voir cela dans l'image (3) ci-dessus; alors que la fenêtre inkscape était placée sur x position 0, vous pouvez toujours voir une marge mineure entre le programme de lancement d'Unity et la fenêtre inkscape.

1
Jacob Vlijm

Je prends une photo absolue dans le noir ici, mais une solution de contournement pour l'instant pourrait être ce script:

#!/bin/bash
# Author: Andrew Martin
# Credit: http://ubuntuforums.org/showthread.php?t=1309247
echo "Enter the primary display from the following:"            # Prompt for the display
xrandr --prop | grep "[^dis]connected" | cut --delimiter=" " -f1    # query connected monitors
read choice                             # read the users's choice of monitor
xrandr --output $choice --primary                   # set the primary monitor

Je crois que cela a fonctionné, pour moi, pour régler mon moniteur central au lieu de mon moniteur d’ordinateur portable sur le "moniteur principal". Ceci, en théorie, ouvrira votre programme sur le moniteur principal? - Je sais que vous avez dit qu'il s'ouvre là où se trouve votre souris, mais c'est un coup bas ...

J'espère que vous le résolvez :)

0
Patrick