Jak dokładnie znaleźć wymiary i położenie okna, w tym dekoracje?

37

Próbowałem ustalić rozmiar okna do użycia w małym skrypcie. Moja obecna technika służy wmctrl -lGdo wyszukiwania wymiarów. Problem jednak jest taki:

Podane przez niego liczby xiy dotyczą górnego lewego rogu dekoracji okna, a wysokość i szerokość dotyczą tylko obszaru zawartości. Oznacza to, że jeśli dekoracje okna dodadzą 20px wysokości i 2px szerokości, wmctrl zgłosi okno jako 640x480, nawet jeśli zajmuje to 660x482 na ekranie. Jest to problem, ponieważ następnym krokiem mojego skryptu byłoby użycie tego obszaru do poinformowania ffmpeg o nagraniu ekranu. Chciałbym uniknąć zakodowania na stałe wielkości dekoracji okien z mojego obecnego ustawienia.

To, co byłoby odpowiednie, to albo metoda uzyskania rozmiaru dekoracji okna, dzięki czemu mogę użyć ich do ustalenia pozycji obszaru treści 640x480, albo sposób uzyskania bezpośredniego położenia obszaru zawartości, a nie pozycji dekoracji okna .

Macha
źródło
1
Zmieszałem wysokość i szerokość na rysunkach dla schematu.
Macha
Link do martwego obrazu.
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
zamknij pytanie, ale zadaje również inne rzeczy: superuser.com/questions/164047/...
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Odpowiedzi:

36

Poniższy skrypt poda Ci lewe górne współrzędne ekranu i rozmiar okna (bez dekoracji). . . . xwininfo -id $(xdotool getactivewindow)zawiera wystarczającą ilość informacji dla Ciebie.


#!/bin/bash
# Get the coordinates of the active window's
#    top-left corner, and the window's size.
#    This excludes the window decoration.
  unset x y w h
  eval $(xwininfo -id $(xdotool getactivewindow) |
    sed -n -e "s/^ \+Absolute upper-left X: \+\([0-9]\+\).*/x=\1/p" \
           -e "s/^ \+Absolute upper-left Y: \+\([0-9]\+\).*/y=\1/p" \
           -e "s/^ \+Width: \+\([0-9]\+\).*/w=\1/p" \
           -e "s/^ \+Height: \+\([0-9]\+\).*/h=\1/p" )
  echo -n "$x $y $w $h"
#
Peter.O
źródło
Wygląda na to, że działa, ponieważ xdotool getactivewindowzwraca identyfikator okna ramki menedżera okien (w tym dekoracji), a nie zawarte w nim okno klienta.
Adam Spiers,
2
Nie, to zwraca geometrię bez dekoracji, co wyraźnie nie jest tym, o co pytano. Jeśli nie chcesz uwzględniać dekoracji, są na to łatwiejsze sposoby, na przykładxdotool getactivewindow getwindowgeometry
slinkp
1
Nie działa to dla mnie dobrze (tzn. Dekoracje nie są uwzględnione). Ta odpowiedź jest lepsza.
Jan Warchoł
7

Zaakceptowaną odpowiedź można rozszerzyć, aby uzyskać całe okno:

entire=false
x=0
y=0
w=0
h=0
b=0  # b for border
t=0  # t for title (or top)

# ... find out what user wants then 

eval $(xwininfo -id $(xdotool getactivewindow) |
  sed -n -e "s/^ \+Absolute upper-left X: \+\([0-9]\+\).*/x=\1/p" \
         -e "s/^ \+Absolute upper-left Y: \+\([0-9]\+\).*/y=\1/p" \
         -e "s/^ \+Width: \+\([0-9]\+\).*/w=\1/p" \
         -e "s/^ \+Height: \+\([0-9]\+\).*/h=\1/p" \
         -e "s/^ \+Relative upper-left X: \+\([0-9]\+\).*/b=\1/p" \
         -e "s/^ \+Relative upper-left Y: \+\([0-9]\+\).*/t=\1/p" )
if [ "$entire" = true ]
then                     # if user wanted entire window, adjust x,y,w and h
    let x=$x-$b
    let y=$y-$t
    let w=$w+2*$b
    let h=$h+$t+$b
fi
echo "$w"x"$h" $x,$y

Chociaż łatwe, okazuje się, że nie działa na Unity w Ubuntu 14.04, ponieważ informacje względne to 0. Zapytałem Uzyskaj pełne wymiary okna (łącznie z dekoracjami) w Unity i dostałem dobrą odpowiedź. Oto jak użyłem tej odpowiedzi:

aw=$(xdotool getactivewindow)
eval $(xwininfo -id "$aw" |
      sed -n -e "s/^ \+Absolute upper-left X: \+\([0-9]\+\).*/x=\1/p" \
             -e "s/^ \+Absolute upper-left Y: \+\([0-9]\+\).*/y=\1/p" \
             -e "s/^ \+Width: \+\([0-9]\+\).*/w=\1/p" \
             -e "s/^ \+Height: \+\([0-9]\+\).*/h=\1/p" )
if [ "$entire" = true ]
then
    extents=$(xprop _NET_FRAME_EXTENTS -id "$aw" | grep "NET_FRAME_EXTENTS" | cut -d '=' -f 2 | tr -d ' ')
    bl=$(echo $extents | cut -d ',' -f 1) # width of left border
    br=$(echo $extents | cut -d ',' -f 2) # width of right border
    t=$(echo $extents | cut -d ',' -f 3)  # height of title bar
    bb=$(echo $extents | cut -d ',' -f 4) # height of bottom border

    let x=$x-$bl
    let y=$y-$t
    let w=$w+$bl+$br
    let h=$h+$t+$bb
fi

Ta druga metoda działa zarówno w Unity, jak i Xfce i powinna również działać w Gnome.

Colin Keenan
źródło
Górne podejście jest błędne nawet poza Unity na Ubuntu, ponieważ zakłada, że ​​lewa, prawa i dolna krawędź mają tę samą szerokość i nie ma na to żadnej gwarancji. Drugie podejście wygląda lepiej.
Adam Spiers,
Właśnie sprawdziłem drugie podejście - wystarczyło aw=`xdotool getactivewindow`dodać do góry, aby uniknąć zawieszania się na wywołaniu xwininfo. To dobrze wiedzieć, ponieważ rozważam przejście na Unity, gdzie nie mogę uruchomić wmiface bez segfaulta.
slinkp
@slinkp, dziękuję za wskazanie brakującej awdefinicji. Przeredaguję teraz odpowiedź, aby dodać tę linię.
Colin Keenan
Druga część tego działa świetnie! Jedyną zmianą, którą musiałem wprowadzić w Gnome 3, było nie dodawanie wysokości paska tytułu h. Wygląda na to, że pasek tytułowy jest już zawarty w wysokości, która wraca xwininfo.
Jonny Asmar
6

Znacznie prostszy sposób uzyskania rozmiaru i położenia okna:

xdotool getwindowfocus getwindowgeometry
radara
źródło
3

Akceptowana odpowiedź wyraźnie nie obejmuje dekoracji okna. Dla tych, którzy wciąż szukają sposobu uzyskania geometrii, w tym wszystkich dekoracji, zgodnie z tytułem tego pytania, możesz użyć wmiface zgodnie z innym pytaniem https://superuser.com/questions/164047/how-to-get-accurate-window -information-Dimensions-etc-in-linux-x . Przykład:

wmiface frameGeometry `wmiface activeWindow`

Zwraca geometrię i pozycję względem lewego górnego w następujący sposób:

650x437+0+1003

wmiface nie wydaje się być dostarczany ze wszystkimi dystrybucjami Linuksa (nie znalazłem pakietu udostępniającego go na Mint lub Ubuntu), ale mogłem go zainstalować z pakietów tutaj: http://kde-apps.org/content/show .php? content = 40425

I nie ma żadnych dokumentów ani nawet --help, ale README jest tutaj:

https://gitorious.org/wmiface/wmiface/source/ea941eeb2076124734f6a3d3079326c826b462d7:README

slinkp
źródło
Niestety - Żałuję mój upvote dla tego ponieważ Akceptowane odpowiedź ma zawierać dekoracji okna, jak na mój komentarz na jej temat.
Adam Spiers,
Chciałbym, żeby to była prawda, ale niestety ten komentarz jest błędny. Zgadzają się co do aktywnego identyfikatora okna: $ wmiface activeWindow 6291772 $ xdotool getactivewindow 6291772 Ale nie zgadzają się co do geometrii i mogę to potwierdzić np. screenruler, który wmiface zawiera dekorację okna, a xdotool nie. Wypróbuj sam. $ wmiface frame Geometria wmiface activeWindow570x434 + 870 + 31 $ xdotool getwindowgeometry xdotool getactivewindowOkno 6291772 Pozycja: 878,77 (ekran: 0) Geometria: 562x407
slinkp
przepraszam, mam nadzieję, że uda ci się ustalić, co miałem na myśli ... żałuję, że przepływ stosu nie pozwoliłby na próbki kodu blokowego w komentarzach.
slinkp
3

Za pomocą xdotool:

  • Najpierw musisz uzyskać identyfikator okna:

sleep 3s && xdotool getactivewindow, masz 3 sekundy na otwarcie okna

  • Następnie musisz użyć:
    1. Aby uzyskać informacje wyjściowe, użyj tego: xdotool getwindowgeometry $WINDOW_ID
    2. lub jeśli chcesz parametr powłoki, użyj tego: xdotool getwindowgeometry -shell $WINDOW_ID
LyndaOlexandr
źródło
0

Łącząc odpowiedzi na tej stronie wykorzystałem to:

$ sleep 3 && xdotool getwindowfocus getwindowgeometry

Window 88080400
  Position: 4565,2345 (screen: 0)
  Geometry: 1186x885

Uruchom jedną linijkę, a następnie w ciągu 3 sekund kliknij okno, dla którego chcesz ustawić położenie i geometrię.

WinEunuuchs2Unix
źródło