Un outil pour obtenir les dimensions des fenêtres

14

J'ai besoin d'un outil pour obtenir la largeur et la hauteur d'une fenêtre arbitraire.

Idéalement, cet outil déduirait la taille de la barre de menus d'Ubuntu.

Akronix
la source

Réponses:

6

D'après votre propre réponse, je comprends que vous recherchez un outil GUI pratique, donc:

Petit outil graphique pour obtenir à la fois la taille nette et la taille réelle d'une fenêtre (mise à jour dynamiquement)

Comme expliqué plus loin dans "Explication", les deux wmctrlet xdotoolrenvoient une taille de fenêtre légèrement incorrecte.

entrez la description de l'image ici

Le script (indicateur) ci-dessous affichera à la fois la taille "réelle" et la taille nette d'une fenêtre dans le panneau.

Le script

#!/usr/bin/env python3
import signal
import gi
gi.require_version('AppIndicator3', '0.1')
gi.require_version('Gtk', '3.0')
import subprocess
from gi.repository import Gtk, AppIndicator3, GObject
import time
from threading import Thread


def get(cmd):
    try:
        return subprocess.check_output(cmd).decode("utf-8").strip()
    except subprocess.CalledProcessError:
        pass

# ---
# uncomment either one of two the lines below; the first one will let the user
# pick a window *after* the indicator started, the second one will pick the 
# currently active window
# ---

window = get(["xdotool", "selectwindow"])
# window = get(["xdotool", "getactivewindow"])

class Indicator():
    def __init__(self):
        self.app = 'test123'
        iconpath = "unity-display-panel"
        self.indicator = AppIndicator3.Indicator.new(
            self.app, iconpath,
            AppIndicator3.IndicatorCategory.OTHER)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)       
        self.indicator.set_menu(self.create_menu())
        self.indicator.set_label(" ...Starting up", self.app)
        # the thread:
        self.update = Thread(target=self.show_seconds)
        # daemonize the thread to make the indicator stopable
        self.update.setDaemon(True)
        self.update.start()

    def create_menu(self):
        menu = Gtk.Menu()
        # separator
        menu_sep = Gtk.SeparatorMenuItem()
        menu.append(menu_sep)
        # quit
        item_quit = Gtk.MenuItem('Quit')
        item_quit.connect('activate', self.stop)
        menu.append(item_quit)
        menu.show_all()
        return menu

    def show_seconds(self):
        sizes1 = None
        while True:
            time.sleep(1)
            sizes2 = self.getsize(window)
            if sizes2 != sizes1:
                GObject.idle_add(
                    self.indicator.set_label,
                    sizes2, self.app,
                    priority=GObject.PRIORITY_DEFAULT
                    )
            sizes1 = sizes2

    def getsize(self, window):
        try:
            nettsize = [int(n) for n in get([
                "xdotool", "getwindowgeometry", window
                ]).splitlines()[-1].split()[-1].split("x")]
        except AttributeError:
            subprocess.Popen(["notify-send", "Missing data", "window "+window+\
                              " does not exist\n(terminating)"])
            self.stop()
        else:
            add = [l for l in get(["xprop", "-id", window]).splitlines() if "FRAME" in l][0].split()
            add = [int(n.replace(",", "")) for n in add[-4:]]
            xadd = add[0]+add[1]; yadd = add[2]+add[3]
            totalsize = [str(s) for s in [nettsize[0]+add[0]+add[1], nettsize[1]+add[2]+add[3]]]
            displ_sizes = ["x".join(geo) for geo in [[str(s) for s in nettsize], totalsize]]
            string = " "+displ_sizes[0]+" / "+displ_sizes[1]
            return string+((25-len(string))*" ")

    def stop(self, *args):
        Gtk.main_quit()

Indicator()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()

Comment utiliser

  1. Le script nécessite l'installation de xdotool:

    sudo apt-get install xdotool
    
  2. Copiez le script dans un fichier vide, enregistrez-le sous getwindowsize.py

  3. Testez-exécutez le script à partir d'une fenêtre de terminal par la commande:

    python3 /path/to/getwindowsize.py
    
  4. Le script choisit la fenêtre focalisée pour afficher dynamiquement la taille nette de la fenêtre (comme dans la sortie des deux wmctrlet xdotool) et la taille réelle de la fenêtre, y compris les décorateurs, etc.

    Si vous fermez la fenêtre ciblée, l'indicateur affiche un message:

    entrez la description de l'image ici

  5. Si tout fonctionne bien, ajoutez-le à une touche de raccourci: choisissez: Paramètres système> "Clavier"> "Raccourcis"> "Raccourcis personnalisés". Cliquez sur le "+" et ajoutez la commande:

    python3 /path/to/getwindowsize.py
    

Explication

La taille de la fenêtre, telle qu'elle est affichée par wmctrl et xdotool

... est légèrement incorrect

Vous mentionnez:

Idéalement, cet outil déduirait la taille de la barre de menus d'Ubuntu

L'histoire complète est que les deux wmctrl -lGet xdotool getwindowgeometryretournent la taille de la fenêtre sans barre de menu, ou, comme cela est expliqué dans cette réponse :

Ce qui se passe, c'est que wmctrl retourne la géométrie de la fenêtre à l'intérieur des décorations (c'est-à-dire sans la barre de titre et les bordures)

Comment obtenir la taille «réelle» correcte

Pour obtenir les informations correctement, nous pouvons exécuter

xprop -id <window_id> | grep FRAME

Cela produira comme:

_NET_FRAME_EXTENTS(CARDINAL) = 0, 0, 28, 0

Ici, nous obtenons les valeurs que nous devons ajouter à la taille de la fenêtre, en tant que sortie de wmctrlet xdotool, à gauche, à droite, en haut et en bas de la fenêtre.

En d'autres termes, dans ce cas, si a wmctrlaffiche une taille de 200x100, la taille réelle est 200x128.

Remarque

Comme suggéré par OP, l'utilisateur peut également choisir une fenêtre après le démarrage de l'indicateur, en remplaçant:

window = get(["xdotool", "getactivewindow"])

par:

window = get(["xdotool", "selectwindow"])

Dans le script, l'une ou l'autre de ces lignes peut être décommentée.

Jacob Vlijm
la source
A bientôt @ Jacob-vlijm, une si bonne réponse! Juste deux choses: 1) J'ai remplacé getactivewindowpar selectwindow, donc lorsque le script est lancé, vous choisissez avec le curseur la fenêtre pour obtenir les dimensions. Je trouve ce comportement beaucoup plus pratique. 2) J'ai téléchargé le code pour coller ubuntu , il est donc plus facile à configurer: il suffit de télécharger et d'enregistrer sous getwindowsize.py
Akronix
@Akronix Merci! sonne comme une excellente idée, cela vous dérangerait si je le modifie dans la réponse?
Jacob Vlijm
Bien sûr @ jacob-vljim. N'hésitez pas;)
Akronix
11

Vous pouvez utiliser wmctrl -lGpour obtenir une liste de toutes les fenêtres ouvertes, dans un tableau au format:

<window ID> <desktop ID> <x-coordinate> <y-coordinate> <width> <height> <client machine> <window title>

Un exemple de sortie pourrait ressembler à ceci:

$ wmctrl -lG
0x02a00002  0 -2020 -1180 1920 1080 MyHostName XdndCollectionWindowImp
0x02a00005  0 0    24   61   1056 MyHostName unity-launcher
0x02a00008  0 0    0    1920 24   MyHostName unity-panel
0x02a0000b  0 -1241 -728 1141 628  MyHostName unity-dash
0x02a0000c  0 -420 -300 320  200  MyHostName Hud
0x03a0000a  0 0    0    1920 1080 MyHostName Desktop
0x0400001d  0 61   24   1859 1056 MyHostName application development - A tool to get window dimensions - Ask Ubuntu - Mozilla Firefox
0x04200084  0 61   52   999  745  MyHostName Untitled Document 1 - gedit
Byte Commander
la source
9

J'ai trouvé xwininfo -allsur /unix/14159/how-do-i-find-the-window-dimensions-and-position-accurately-including-decoration .

Cela fonctionne, mais je suis toujours ouvert à des solutions plus pratiques => un outil GUI en temps réel.

Akronix
la source
J'ai posté une réponse, mais je n'ai pas remarqué que vous aviez xwininfodéjà trouvé . Peut-être que vous seriez intéressé par le script que j'ai écrit - il utilise xwininfomais avec une popup GUI, veuillez le voir ci-dessous.
Sergiy Kolodyazhnyy
2

On pourrait essayer:

xdotool search --name gnome-panel getwindowgeometry

En supposant que gnome-panel est le nom du processus de la barre d'outils d'Ubuntu, mais qui sait.

(peut nécessiter un sudo apt-get install xdotool)

Pour une interface graphique improvisée que l'on peut vouloir améliorer davantage pour afficher uniquement les éléments essentiels:

zenity --text-info --filename=<(xprop)

Il changera le pointeur en croix de xprop, puis vous cliquerez sur la fenêtre, et il imprimera les informations de xprop dans une boîte de dialogue GTK.

El Guesto
la source
2

xwininfo et ses avantages

Le gros problème avec wmctrlet xdotoolc'est que ces outils doivent être installés - ils ne sont pas sur Ubuntu par défaut . Cependant, Ubuntu est livré avec xwininfo. Il s'agit d'un outil simple qui fournit des informations sur la fenêtre sélectionnée par l'utilisateur.

Une utilisation simple serait de taper xwininfo | awk '/Width/||/Height/'(remarque qui awkest utilisée pour filtrer la sortie) dans le terminal, et lorsque votre curseur change pour xsélectionner n'importe quelle fenêtre GUI que vous aimez et il affichera ses informations. Par exemple:

$ xwininfo | awk '/Width/||/Height/'                
  Width: 602
  Height: 398

Les avantages sont donc:

  • C'est simple
  • il est installé par défaut
  • c'est juste du texte - rien d'extraordinaire et vous pouvez le filtrer et le modifier si nécessaire

Aller plus loin avec xwininfo - afficher les propriétés d'une fenêtre active

Bien sûr, si vous avez un terminal ouvert 24/7 comme moi, xwininfoc'est tout ce dont vous avez besoin. Certains utilisateurs peuvent préférer avoir un raccourci clavier. Le script ci-dessous (qui est destiné à être lié à un raccourci clavier) vous permet d'afficher une fenêtre contextuelle graphique avec des informations sur votre fenêtre actuellement active. Comme on peut le voir sur la capture d'écran, il affiche le titre, la largeur et la hauteur de la fenêtre.

entrez la description de l'image ici

Sous le capot, cela ne fait rien de particulièrement spectaculaire. Il utilise les informations du dbusservice xwininfoet les met dans un simple popup. Le code source est ci-dessous. N'oubliez pas que les règles de script standard s'appliquent: assurez-vous qu'il dispose d'autorisations exécutables avec chmod +xet lors de la liaison au raccourci clavier, vous donnez le chemin d'accès complet au fichier de script en tant que commande.

#!/bin/bash 

get_active_window()
{
    qdbus org.ayatana.bamf \
          /org/ayatana/bamf/matcher \
          org.ayatana.bamf.matcher.ActiveWindow
}

get_active_name()
{
    qdbus org.ayatana.bamf $1 \
          org.ayatana.bamf.view.Name
}

main()
{
    active_window=$(get_active_window)
    active_xid=$( awk -F '/' '{print $NF}' <<< "$active_window" )
    echo $active_xid
    active_title=$(get_active_name $active_window)
    dimensions=$(xwininfo -id "$active_xid" | awk '/Width/||/Height/')
    text="$active_title\n""$dimensions"
    zenity --info --text "$text" --width=200 --height=200
}

main $@

Utilisation de l'indicateur du panneau supérieur d'Unity pour plus d'informations.

En écrivant ma réponse, j'ai réalisé que ce serait une fonctionnalité très utile à intégrer dans l'un de mes projets existants - l'indicateur Ayatana. Cet indicateur permet d'afficher toute une gamme d'informations sur les fenêtres GUI. Actuellement en cours de développement actif. La fonctionnalité d'informations sur la géométrie a été ajoutée au référentiel github et est en cours de création dans mon PPA personnel . Et bien sûr, il utilise xwininfobien que de manière légèrement différente.

entrez la description de l'image ici

Sergiy Kolodyazhnyy
la source