Инструмент для получения размеров окна

14

Мне нужен инструмент, чтобы получить ширину и высоту произвольного окна.

В идеале этот инструмент должен вычитать размер строки меню Ubuntu.

Akronix
источник

Ответы:

6

Из вашего собственного ответа я понимаю, что вы ищете удобный инструмент с графическим интерфейсом, поэтому:

Небольшой графический инструмент для получения как чистого размера, так и реального размера окна (динамически обновляется)

Как объяснено ниже в "Объяснении", оба wmctrlи xdotoolвозвращают немного неправильный размер окна.

введите описание изображения здесь

Скрипт (индикатор) ниже покажет как «реальный» размер, так и чистый размер окна на панели.

Сценарий

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

Как пользоваться

  1. Скрипт должен быть установлен xdotool:

    sudo apt-get install xdotool
    
  2. Скопируйте скрипт в пустой файл, сохраните его как getwindowsize.py

  3. Тестовый запуск скрипта из окна терминала командой:

    python3 /path/to/getwindowsize.py
    
  4. Сценарий выбирает сфокусированное окно для динамического отображения размера окна сети (как в выводе обоих wmctrlи xdotool) и реального размера окна, включая декораторы и т. Д.

    Если вы закроете целевое окно, индикатор покажет сообщение:

    введите описание изображения здесь

  5. Если все работает нормально, добавьте его к сочетанию клавиш: выберите: «Системные настройки»> «Клавиатура»> «Ярлыки»> «Пользовательские ярлыки». Нажмите «+» и добавьте команду:

    python3 /path/to/getwindowsize.py
    

объяснение

Размер окна, отображаемый как с помощью wmctrl, так и xdotool

... немного неверно

Вы упоминаете:

В идеале этот инструмент должен вычитать размер строки меню Ubuntu

Полная история такова, что оба wmctrl -lGи xdotool getwindowgeometryвозвращают размер окна без строки меню или, как это объясняется в этом ответе :

Что происходит, так это то, что wmctrl возвращает геометрию окна внутри украшений (т.е. не включая строку заголовка и границы)

Как получить правильный, «реальный» размер

Чтобы получить информацию правильно, мы можем запустить

xprop -id <window_id> | grep FRAME

Это будет выводить как:

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

Здесь мы получаем значения, которые нам нужно добавить к размеру окна, как вывод wmctrlи xdotoolслева, справа, сверху и снизу окна.

Другими словами, в этом случае, если a wmctrlпоказывает размер 200x100, реальный размер составляет 200x128.

Заметка

Как предполагает OP, пользователь также может выбрать окно после запуска индикатора, заменив:

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

по:

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

В сценарии любая из этих строк может быть раскомментирована.

Якоб Влейм
источник
Ура @ Jacob-vlijm, такой хороший ответ! Только две вещи: 1) Я заменил getactivewindowна selectwindow, поэтому , когда скрипт запускается вы выбираете с помощью курсора в окно , чтобы получить размеры от. Я считаю это поведение намного более удобным. 2) Я загрузил код для вставки Ubuntu , так что его проще настроить: просто скачайте и сохраните как getwindowsize.py
Akronix
@ Akronix Спасибо! звучит как отличная идея, вы не возражаете, если я отредактирую ее в ответ?
Джейкоб Влейм
Конечно @ jacob-vljim. Не стесняйтесь;)
Akronix
11

Вы можете использовать, wmctrl -lGчтобы получить список всех открытых окон в таблице в формате:

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

Пример вывода может выглядеть так:

$ 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
источник
9

Я нашел xwininfo -allпо адресу /unix/14159/how-do-i-find-the-window-dimensions-and-position-accurately-inc включая-decoration .

Это работает, но я все еще открыт для более удобных решений => инструмент GUI в реальном времени.

Akronix
источник
Я отправил ответ, но не заметил, что вы уже нашли xwininfo. Возможно, вас заинтересует сценарий, который я написал - он использует, xwininfoно с всплывающим графическим интерфейсом, смотрите его ниже.
Сергей Колодяжный
2

Можно попробовать:

xdotool search --name gnome-panel getwindowgeometry

Предполагая, что gnome-panel - это имя процесса панели инструментов Ubuntu, но кто знает.

(может потребовать sudo apt-get install xdotool)

Для импровизированного графического интерфейса, который можно улучшить, чтобы отобразить только самое необходимое:

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

Он изменит указатель на крестик xprop, затем вы нажмете на окно, и он напечатает информацию xprop в диалоге GTK.

Эль Гесто
источник
2

xwininfo и его преимущества

Большая проблема с wmctrlи в xdotoolтом , что эти средства должны быть установлены - они не на Ubuntu по умолчанию . Тем не менее, Ubuntu поставляется с xwininfo. Это простой инструмент, который предоставляет информацию о выбранном пользователем окне.

Простым использованием было бы ввести xwininfo | awk '/Width/||/Height/'(обратите внимание, что awkэто используется для фильтрации выходных данных) в терминале, и когда ваш курсор изменится, чтобы xвыбрать любое окно GUI, которое вам нравится, и оно отобразит свою информацию. Например:

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

Итак, преимущества:

  • это просто
  • установлен по умолчанию
  • это просто текст - ничего особенного, и вы можете отфильтровать и настроить его по мере необходимости

На шаг впереди xwininfo - отображение свойств активного окна

Конечно, если у вас терминал открыт 24/7, как у меня, xwininfoэто все, что вам нужно. Некоторые пользователи могут предпочесть использование сочетания клавиш. Приведенный ниже скрипт (предназначенный для привязки к сочетанию клавиш) позволяет отображать графическое всплывающее окно с информацией о текущем активном окне. Как видно на скриншоте, он отображает заголовок окна, информацию о ширине и высоте.

введите описание изображения здесь

Под капотом это не делает ничего особенно впечатляющего. Он использует информацию из dbusсервиса xwininfoи помещает ее в простое всплывающее окно. Исходный код ниже. Помните, что применяются стандартные правила написания сценариев: убедитесь, что у него есть права на выполнение с помощью, chmod +xа при привязке к сочетанию клавиш укажите полный путь к файлу сценария в качестве команды.

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

Использование индикатора верхней панели Unity для информации.

При написании своего ответа я понял, что это будет очень полезная функция для включения в один из моих существующих проектов - индикатор Аятана. Этот индикатор позволяет отображать весь спектр информации об окнах GUI. В настоящее время все еще находится в стадии активной разработки. Функция информации о геометрии была добавлена ​​в репозиторий github и находится на пути к моему личному PPA . И, конечно, он использует, xwininfoхотя и немного по-другому.

введите описание изображения здесь

Сергей Колодяжный
источник