Uno strumento per ottenere le dimensioni della finestra


14

Ho bisogno di uno strumento per ottenere la larghezza e l'altezza di una finestra arbitraria.

Idealmente, quello strumento dedurrebbe le dimensioni della barra dei menu di Ubuntu.

Risposte:


6

Dalla tua risposta, capisco che stai cercando uno strumento GUI conveniente, quindi:

Piccolo strumento GUI per ottenere sia la dimensione della rete che la dimensione reale di una finestra (aggiornamento dinamico)

Come spiegato più avanti in "Spiegazione", entrambi wmctrle xdotoolrestituiscono un formato di finestra leggermente errato.

inserisci qui la descrizione dell'immagine

Lo script (indicatore) di seguito mostrerà sia la dimensione "reale" che la dimensione netta di una finestra nel pannello.

Il copione

#!/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()

Come usare

  1. Lo script richiede l'installazione di xdotool:

    sudo apt-get install xdotool
    
  2. Copia lo script in un file vuoto, salvalo come getwindowsize.py

  3. Prova- esegui lo script da una finestra terminale con il comando:

    python3 /path/to/getwindowsize.py
    
  4. Lo script seleziona la finestra focalizzata per mostrare dinamicamente la dimensione della finestra (come nell'output di entrambi wmctrle xdotool) e la dimensione reale della finestra, inclusi i decoratori ecc.

    Se chiudi la finestra target, l'indicatore mostra un messaggio:

    inserisci qui la descrizione dell'immagine

  5. Se tutto funziona bene, aggiungilo a un tasto di scelta rapida: scegli: Impostazioni di sistema> "Tastiera"> "Scorciatoie"> "Scorciatoie personalizzate". Fai clic su "+" e aggiungi il comando:

    python3 /path/to/getwindowsize.py
    

Spiegazione

La dimensione della finestra, così come viene visualizzata da wmctrl e xdotool

... è leggermente errato

Tu citi:

Idealmente, quello strumento dedurrebbe le dimensioni della barra dei menu di Ubuntu

La storia completa è che sia wmctrl -lGe xdotool getwindowgeometryrestituire la dimensione della finestra senza barra dei menu, o, come si è spiegato in questa risposta :

Quello che sta succedendo è che wmctrl sta restituendo la geometria della finestra all'interno delle decorazioni (cioè non includendo la barra del titolo e i bordi)

Come ottenere la dimensione corretta, "reale"

Per ottenere correttamente le informazioni, possiamo eseguire

xprop -id <window_id> | grep FRAME

Questo produrrà come:

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

Qui otteniamo i valori che dobbiamo aggiungere alle dimensioni della finestra, come output da wmctrle xdotool, a sinistra, a destra, in alto e in basso nella finestra.

In altre parole, in questo caso, se a wmctrlmostra una dimensione di 200x100, la dimensione reale è 200x128.

Nota

Come suggerito da OP, l'utente può anche selezionare una finestra dopo l'avvio dell'indicatore, sostituendo:

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

di:

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

Nello script, una di queste righe può essere decommentata.


Saluti @ Jacob-vlijm, una risposta così buona! Solo due cose: 1) Ho sostituito getactivewindowda selectwindow, quindi quando lo script viene lanciato scegli con il cursore la finestra da cui ottenere le dimensioni. Trovo questo comportamento molto più conveniente. 2) Ho caricato il codice per incollare Ubuntu , quindi è più facile da configurare: basta scaricare e salvare come getwindowsize.py
Akronix

@Akronix Grazie! sembra un'ottima idea, ti dispiacerebbe se la modifico nella risposta?
Jacob Vlijm,

Sicuro @ jacob-vljim. Sentiti libero;)
Akronix il

11

È possibile utilizzare wmctrl -lGper ottenere un elenco di tutte le finestre aperte, in una tabella con il formato:

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

Un output di esempio potrebbe essere simile al seguente:

$ 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


2

Si potrebbe provare:

xdotool search --name gnome-panel getwindowgeometry

Supponendo che gnome-panel sia il nome del processo della barra degli strumenti di Ubuntu, ma chi lo sa.

(potrebbe richiedere un sudo apt-get install xdotool)

Per una cosa della GUI improvvisata che si potrebbe desiderare di migliorare ulteriormente in modo da visualizzare solo gli elementi essenziali nudi:

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

Cambierà il puntatore alla croce di xprop, quindi fai clic sulla finestra e stamperà le informazioni di xprop in una finestra di dialogo GTK.


2

xwininfo e i suoi vantaggi

Il grosso problema con wmctrle xdotoolè che quegli strumenti devono essere installati - non sono su Ubuntu per impostazione predefinita . Tuttavia, Ubuntu viene fornito con xwininfo. È uno strumento semplice che fornisce informazioni sulla finestra selezionata dall'utente.

L'utilizzo semplice sarebbe quello di digitare xwininfo | awk '/Width/||/Height/'(notare che awkviene utilizzato per filtrare l'output) nel terminale e quando il cursore cambia per xselezionare qualsiasi finestra della GUI che ti piace e visualizzerà le sue informazioni. Per esempio:

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

Quindi i vantaggi sono:

  • è semplice
  • è installato di default
  • è solo testo - niente di speciale e puoi filtrarlo e modificarlo se necessario

Fare un ulteriore passo su xwininfo - visualizzare le proprietà di una finestra attiva

Ovviamente se hai un terminale aperto 24 ore su 24, 7 giorni su 7, come faccio io, xwininfoè tutto ciò di cui hai bisogno. Alcuni utenti potrebbero preferire avere una scorciatoia da tastiera. Lo script seguente (che si intende associare a una scorciatoia da tastiera) consente di visualizzare un popup grafico con informazioni sulla finestra attualmente attiva. Come si può vedere nello screenshot, visualizza il titolo della finestra, le informazioni su larghezza e altezza.

inserisci qui la descrizione dell'immagine

Sotto il cofano questo non fa nulla di particolarmente spettacolare. Utilizza le informazioni dal dbusservizio xwininfoe le mette in un semplice popup. Il codice sorgente è sotto. Ricorda che si applicano le regole standard di scripting: assicurati che disponga delle autorizzazioni eseguibili con chmod +xe quando si esegue il collegamento alla scorciatoia da tastiera, si fornisce il percorso completo al file di script come comando.

#!/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 $@

Utilizzo dell'indicatore del pannello superiore di Unity per informazioni.

Quando ho scritto la mia risposta, mi sono reso conto che questa sarebbe una caratteristica molto utile da incorporare in uno dei miei progetti esistenti: l'indicatore Ayatana. Questo indicatore consente di mostrare l'intera gamma di informazioni sulle finestre della GUI. Attualmente è ancora in fase di sviluppo attivo. La funzione di informazioni sulla geometria è stata aggiunta al repository github ed è in arrivo nel mio PPA personale . E, naturalmente, usa xwininfoanche se in modo leggermente diverso.

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.