Una herramienta para obtener dimensiones de ventana

14

Necesito una herramienta para obtener el ancho y la altura de una ventana arbitraria.

Idealmente, esa herramienta deduciría el tamaño de la barra de menú de Ubuntu.

Akronix
fuente

Respuestas:

6

Por su propia respuesta, entiendo que está buscando una herramienta GUI conveniente, así que:

Pequeña herramienta GUI para obtener tanto el tamaño neto como el tamaño real de una ventana (actualizado dinámicamente)

Como se explica más adelante en "Explicación", tanto wmctrly xdotooldevolver un WindowSize ligeramente incorrecta.

ingrese la descripción de la imagen aquí

El script (indicador) a continuación mostrará tanto el tamaño "real" como el tamaño neto de una ventana en el panel.

La secuencia de comandos

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

Cómo utilizar

  1. El script necesita que se instale xdotool:

    sudo apt-get install xdotool
    
  2. Copie el script en un archivo vacío, guárdelo como getwindowsize.py

  3. Prueba: ejecute el script desde una ventana de terminal con el comando:

    python3 /path/to/getwindowsize.py
    
  4. El script selecciona la ventana enfocada para mostrar dinámicamente el tamaño neto de la ventana (como en la salida de ambos wmctrly xdotool) y el tamaño real de la ventana, incluidos los decoradores, etc.

    Si cierra la ventana de destino, el indicador muestra un mensaje:

    ingrese la descripción de la imagen aquí

  5. Si todo funciona bien, agréguelo a una tecla de acceso directo: elija: Configuración del sistema> "Teclado"> "Accesos directos"> "Accesos directos personalizados". Haga clic en "+" y agregue el comando:

    python3 /path/to/getwindowsize.py
    

Explicación

El tamaño de la ventana, tal como lo muestran wmctrl y xdotool

... es ligeramente incorrecto

Mencionas:

Idealmente, esa herramienta deduciría el tamaño de la barra de menú de Ubuntu

La historia completa es que ambos wmctrl -lGy xdotool getwindowgeometrydevuelven el tamaño de la ventana sin barra de menú, o, como se explica en esta respuesta :

Lo que sucede es que wmctrl está devolviendo la geometría de la ventana dentro de las decoraciones (es decir, sin incluir la barra de título y los bordes)

Cómo obtener el tamaño correcto "real"

Para obtener la información correctamente, podemos ejecutar

xprop -id <window_id> | grep FRAME

Esto saldrá como:

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

Aquí obtenemos los valores que necesitamos agregar al tamaño de la ventana, como salida desde wmctrly xdotool, a la izquierda, derecha, arriba y abajo de la ventana.

En otras palabras, en este caso, si a wmctrlmuestra un tamaño de 200x100, el tamaño real es 200x128.

Nota

Según lo sugerido por OP, el usuario también puede elegir una ventana después de que se inició el indicador, reemplazando:

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

por:

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

En el script, cualquiera de estas líneas puede ser descomentada.

Jacob Vlijm
fuente
Saludos @ Jacob-vlijm, ¡qué buena respuesta! Solo dos cosas: 1) He reemplazado getactivewindowpor selectwindow, por lo que cuando se inicia el script, elige con el cursor la ventana para obtener las dimensiones. Este comportamiento me parece mucho más conveniente. 2) He subido el código para pegar ubuntu , por lo que es más fácil de configurar: simplemente descargue y guarde como getwindowsize.py
Akronix
@Akronix ¡Gracias! Suena como una gran idea, ¿te importaría si la edito en la respuesta?
Jacob Vlijm
Claro @ jacob-vljim. Siéntase libre;)
Akronix
11

Puede usar wmctrl -lGpara obtener una lista de todas las ventanas abiertas, en una tabla con el formato:

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

Un ejemplo de salida podría verse así:

$ 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
fuente
2

Se podría intentar:

xdotool search --name gnome-panel getwindowgeometry

Suponiendo que gnome-panel es el nombre del proceso de la barra de herramientas de ubuntu, pero quién sabe.

(puede requerir a sudo apt-get install xdotool)

Para una cosa de GUI improvisada que uno puede desear mejorar aún más para mostrar solo lo esencial:

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

Cambiará el puntero a la cruz de xprop, luego hará clic en la ventana e imprimirá la información de xprop en un cuadro de diálogo GTK.

El Guesto
fuente
2

xwininfo y sus ventajas

El gran problema con wmctrly xdotooles que esas herramientas necesitan ser instaladas, no están en Ubuntu por defecto . Sin embargo, Ubuntu viene con xwininfo. Es una herramienta simple que proporciona información sobre la ventana seleccionada por el usuario.

El uso simple sería escribir xwininfo | awk '/Width/||/Height/'(aviso que awkse usa para filtrar la salida) en la terminal, y cuando el cursor cambie para xseleccionar cualquier ventana GUI que desee y mostrará su información. Por ejemplo:

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

Entonces las ventajas son:

  • Es simple
  • se instala por defecto
  • es solo texto, nada sofisticado y puede filtrarlo y ajustarlo según sea necesario

Llevando xwininfo un paso más allá: mostrar las propiedades de una ventana activa

Por supuesto, si tiene una terminal abierta las 24 horas, los 7 días de la semana, como yo, xwininfoes todo lo que necesita. Algunos usuarios pueden preferir tener un atajo de teclado. La secuencia de comandos a continuación (que está destinada a estar vinculada a un atajo de teclado) le permite mostrar una ventana emergente gráfica con información sobre su ventana actualmente activa. Como se puede ver en la captura de pantalla, muestra el título de la ventana, la información de ancho y alto.

ingrese la descripción de la imagen aquí

Debajo del capó, esto no hace nada particularmente espectacular. Utiliza información del dbusservicio xwininfoy la pone en una ventana emergente simple. El código fuente está abajo. Recuerde, se aplican las reglas estándar de secuencias de comandos: asegúrese de que tenga permisos ejecutables con chmod +xy cuando se vincula al método abreviado de teclado, proporcione la ruta completa al archivo de secuencia de comandos como 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 $@

Uso del indicador del panel superior de Unity para obtener información.

Al escribir mi respuesta, me di cuenta de que esta sería una característica muy útil para incorporar en uno de mis proyectos existentes: el Indicador Ayatana. Este indicador permite mostrar todo el rango de información sobre las ventanas GUI. Actualmente todavía está en desarrollo activo. La función de información de geometría se ha agregado al repositorio de github y está en camino a mi PPA personal . Y, por supuesto, lo usa, xwininfoaunque de manera ligeramente diferente.

ingrese la descripción de la imagen aquí

Sergiy Kolodyazhnyy
fuente