Önceden tanımlanmış bir pencere boyutu ve konumuna sahip bir uygulamayı nasıl başlatabilirim?


22

Unity'de terminal komutlarını kullanarak Ctrl-Alt-Tuş takımı kısayollarının etkisini terminal komutlarını kullanarak elde etmenin bir yolu var mı? Bir gui penceresini ekranın yarısına kadar sola veya sağa hizalayarak ayarlayan bir komut istiyorum.

Arka plan olarak, oturum açtıktan sonra çalışan bir komut dosyası yazıyorum. Geliştirme ortamımı açmak isteyip istemediğimi sormak için Zenity'yi kullanıyor (GVim ve IPython yan yana). Ben kullanarak bu programlar için iki eşit büyüklükte pencereler ulaşmak için çalışıyorlar set lines= columns=içinde benim .gvimrcve c.IPythonWidget.width =ve c.IPythonWidget.height =gözlerimi de ipython_qtconsole_config.py. Ancak, bu yaklaşımla ilgili problemler var.


Cevabımı güncelledim çünkü konuyu yeterince ayrıntılı bir şekilde açıklamadı, güncellemeyi kontrol etmek isteyebilirsiniz
kos

Yanıtlar:


17

Neye rastlayacaksın

Öncelikle bir uygulamayı arayıp, sonradan, belirli bir konumda ve boyutta üzerindeki pencereyi yerleştirmek istiyorsanız, arasındaki zaman uygulamayı çağırarak ve pencere aslında göründüğü an , tahmin edilemez. Sisteminiz meşgulsa, boşta olduğundan önemli ölçüde daha uzun olabilir.

Konumlandırma / yeniden boyutlandırmanın, pencere göründükten hemen sonra (hemen) yapıldığından emin olmak için "akıllı" bir yol gerekir .

Bir uygulamayı çağırmak için komut dosyası, görünmesini bekleyin ve ekranda konumlandırın

Aşağıdaki komut dosyası ile bir uygulamayı arayabilir ve komutuyla görünmesi gereken konumu ve boyutu belirleyebilirsiniz:

<script> <application> <x-position> <y-position> <h-size> <v-size>

Birkaç örnek:

  • gnome-terminalPenceresini% 50 olarak çağırıp yeniden boyutlandırmak ve sağ tarafa yerleştirmek için:

    <script> gnome-terminal 840 0 50 100

    görüntü tanımını buraya girin

  • Aramak geditiçin penceresini sola ve aramayı gnome-terminalsağa yerleştirin ( v-sizepencerelerin arasında biraz boşluk bırakacak şekilde% 46'yı ayarlayın):

    <script> gedit 0 0 46 100&&<script> gnome-terminal 860 0 46 100

    görüntü tanımını buraya girin

  • Inkscape'i aramak için penceresini ekranın sol / üst çeyreğine yerleştirin:

    <script> inkscape 0 0 50 50

    görüntü tanımını buraya girin

Senaryo ve nasıl kullanılacağı

  1. Her iki yüklemek xdotoolve wmctrl. Her ikisini de kullandım çünkü yeniden boyutlandırma wmctrlbazı özelliklere neden olabilir (özellikle) Unity.

    sudo apt-get install wmctrl
    sudo apt-get install xdotool
  2. Aşağıdaki betiği boş bir dosyaya kopyalayın, içinde setwindow(uzantısız) olarak kaydedin ~/bin; Gerekirse dizini oluşturun.
  3. Komut dosyasını çalıştırılabilir yap (!)
  4. Yeni oluşturduysanız ~bin, çalıştırın:source ~/.profile
  5. Komut dosyasını komutla test et (örneğin)

    setwindow gnome-terminal 0 0 50 100

    Diğer bir deyişle:

    setwindow <application> <horizontal-position> <vertical-position> <horizontal-size (%)> <vertical-size (%)>

Hepsi iyi çalışıyorsa, komutu istediğiniz yere kullanın.

Senaryo

#!/usr/bin/env python3
import subprocess
import time
import sys

app = sys.argv[1]

get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8")
ws1 = get("wmctrl -lp"); t = 0
subprocess.Popen(["/bin/bash", "-c", app])

while t < 30:      
    ws2 = [w.split()[0:3] for w in get("wmctrl -lp").splitlines() if not w in ws1]
    procs = [[(p, w[0]) for p in get("ps -e ww").splitlines() \
              if app in p and w[2] in p] for w in ws2]
    if len(procs) > 0:
        w_id = procs[0][0][1]
        cmd1 = "wmctrl -ir "+w_id+" -b remove,maximized_horz"
        cmd2 = "wmctrl -ir "+w_id+" -b remove,maximized_vert"
        cmd3 = "xdotool windowsize --sync "+procs[0][0][1]+" "+sys.argv[4]+"% "+sys.argv[5]+"%"
        cmd4 = "xdotool windowmove "+procs[0][0][1]+" "+sys.argv[2]+" "+sys.argv[3]
        for cmd in [cmd1, cmd2, cmd3, cmd4]:   
            subprocess.call(["/bin/bash", "-c", cmd])
        break
    time.sleep(0.5)
    t = t+1

Bu ne yapar

Betik çağrıldığında:

  1. uygulamayı başlatır
  2. pencerede bir göz tutar (kullanarak wmctrl -lp)
  3. eğer yeni bir pencere belirirse, yeni pencerenin çağrılan uygulamaya ait olup olmadığını kontrol eder (kullanarak ps -ef ww, pencere pidini uygulama pidiyle karşılaştırarak)
  4. öyleyse, argümanlarınıza göre boyutu ve konumu belirler. Bir uygulamanın yaklaşık olarak "görünmemesi" durumunda. 15 saniye, komut dosyası, uygulamanın bir hata nedeniyle çalışmayacağını varsayıyor. Betik daha sonra yeni pencerenin sonsuz olarak beklemesini önlemek için sona erer.

Küçük sorun

Birlik'te, bir pencereyi ( wmctrlveya ) yeniden konumlandırıp (yeniden) boyutlandırdığınızda ya da ile bir pencereyi boyutlandırdığınızda xdotool,% 100 olarak ayarlanmadıkça, pencere her zaman ekranınızın sınırlarına küçük bir kenar boşluğu tutacaktır. Bunu yukarıdaki resimde (3) görebilirsiniz; inkscapepencere x0 konumuna getirilirken, Unity Launcher ile inkscapepencere arasında küçük bir kenarlık görmeye devam edebilirsiniz .


Sevgili Jacob, bu harika bir senaryo! Bir soru: Daha sonra senaryo ile birlikte kullanılacak açık pencerenin boyutunu nasıl bulabilirim?
orschiro

Merhaba @orschiro Bir toplantı için koşmak zorundayım ... birkaç saat sonra döneceğim :)
Jacob Vlijm

1
@Orschiro Merhaba, varsayarak wmctrlyüklü, komut: wmctrl -lG | grep <windowname>Size şöyle bir çıktı gösterecektir: 0x03600e4f 0 723 197 1114 563 jacob-System-Product-Name dimkeyboard.sh (~/Bureaublad) - gedit. Bu çıktıda, 3. ile 6. sütun, x, y, genişlik, genişlik, yükseklik boyutlarını gösterir.
Jacob Vlijm

Çok takdir Jacob! Kurulumu doğru yaptım ancak ilgili pencere şimdi tam ekranda açılıyor. Herhangi bir fikir?
orschiro

1
Bu betiği sevdim, ancak benim için çalışmasını sağlamak için ilk satırda aşağıdaki değişiklikleri yapmak zorunda kaldım, çünkü uygulamaya parametreler ekledim: appAndParams = sys.argv[1] app = appAndParams[0].split(' ', 1)[0] get = lambda x: subprocess.check_output(["/bin/bash", "-c",x]).decode("utf-8") ws1 = get("wmctrl -lp"); t = 0 subprocess.Popen(["/bin/bash", "-c", appAndParams])</pre> <edit> bu kodu biçimlendirmeyi reddediyor . </edit>
Ron Thompson,

3

İstediğiniz gerçek komut, bunun gibi bir şey

wmctrl -r :ACTIVE: -b add,maximized_vert && 
wmctrl -r :ACTIVE: -e 0,0,0,$HALF,-1

Bu, geçerli pencerenin ekranın yarısını kaplamasını sağlar (ekranınızın $HALFboyutlarına göre değişir ) ve sol tarafa geçer. Sağa yaslamak için

wmctrl -r :ACTIVE: -b add,maximized_vert && 
wmctrl -r :ACTIVE: -e 0,$HALF,0,$HALF,-1 

Ayrıca wmctrlkullanmak yerine ilgilendiğiniz pencerelerin kimliğini almak için de oynayabilirsiniz :ACTIVE:. Oradaki pencerelere bağlı olduğu için orada yardım edemem. man wmctrlDaha fazlası için bir göz atın .


Bunun için bir senaryo yazdım. Birlik kullanmıyorum, bu yüzden onunla çalışacağını garanti edemiyorum, ama neden olmasın diye bir sebep görmüyorum. Bu ihtiyacı wmctrl, xdpyinfove disperyüklenmiş olması:

sudo apt-get install wmctrl x11-utils disper

Ardından, aşağıdaki betiği farklı şekilde kaydedin, ~/bin/snap_windows.shçalıştırılabilir hale getirin chmod a+x ~/bin/snap_windows.shve

snap_windows.sh r

Sağ tarafa geçme. lSol taraf için kullanın ve pencereyi büyütmek için hiçbir argüman yok. Geçerli pencerede çalıştığını ve terminalden başka bir şeyde çalışmasını istiyorsanız bir kısayol atamanız gerekeceğini unutmayın.

Senaryo, istediğinden biraz daha karmaşık çünkü hem tek hem de çift monitör kurulumlarında çalışmak için yazdım.

#!/usr/bin/env bash

## If no side has been given, maximize the current window and exit
if [ ! $1 ]
then
    wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz
    exit
fi

## If a side has been given, continue
side=$1;
## How many screens are there?
screens=`disper -l | grep -c display`
## Get screen dimensions
WIDTH=`xdpyinfo | grep 'dimensions:' | cut -f 2 -d ':' | cut -f 1 -d 'x'`;
HALF=$(($WIDTH/2));

## If we are running on one screen, snap to edge of screen
if [ $screens == '1' ]
then
    ## Snap to the left hand side
    if [ $side == 'l' ]
    then
        ## wmctrl format: gravity,posx,posy,width,height
    wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,0,0,$HALF,-1
    ## Snap to the right hand side
    else
    wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$HALF,0,$HALF,-1 
    fi
## If we are running on two screens, snap to edge of right hand screen
## I use 1600 because I know it is the size of my laptop display
## and that it is not the same as that of my 2nd monitor.
else
    LAPTOP=1600; ## Change this as approrpiate for your setup.
    let "WIDTH-=LAPTOP";
    SCREEN=$LAPTOP;
    HALF=$(($WIDTH/2));
    if [ $side == 'l' ]
    then
        wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$LAPTOP,0,$HALF,-1
    else
    let "SCREEN += HALF+2";
    wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$SCREEN,0,$HALF,-1;
    fi
fi

3

Bunu kullanarak yapabilirsiniz xdotool.

Yüklemek xdotooliçin çalıştırabilirsiniz:

sudo apt-get update && sudo apt-get install xdotool

Sonra terminal penceresine bir Ctrl+ Alt+ <keypad_key>tuş vuruşu göndermek için Xçalıştırabilirsiniz:

xdotool key Ctrl+Alt+<keypad_key_value>

* <keypad_key_value> = aşağıdaki listede tuş takımı tuşunun değeri

Bir GUI programını çalıştırmak ve tuş vuruşunu kendi Xpenceresine göndermek için (bu durumda xdotoolkomut çalıştırma sırasında aktif olan penceredir ) çalıştırabilirsiniz:

<command> && window="$(xdotool getactivewindow)" xdotool key --delay <delay> --window "$window" <keypad_key_value>

* <komut> = tuş vuruşunu göndermek istediğiniz pencereyi açan komut; <delay> = tuş vuruşunu göndermeden önce milisaniyede bekleme süresi; <keypad_key_value> = tuş takımı tuşunun aşağıdaki listedeki değeri

Çoğu durumda tek başına bir işlem olarak verdiğiniz komutu çalıştırmanız gerektiğine dikkat edin (örneğin, yukarıdaki örnek nohup <command> &yerine çalıştırılarak <command>), aksi takdirde işlem tamamlanıncaya xdotoolkadar çalıştırılmaz <command>.

Ayrıca, biraz gecikme ayarlamanız gerekecek, aksi takdirde, hedef pencere tam olarak yüklenmeden önce tuş vuruşunu gönderilecektir X(çevresinde bir gecikme 500msolması gerekir).

Olası değerler <keypad_key_value>:

  • 0: 90
  • 1: 87
  • 2: 88
  • 3: 89
  • 4: 83
  • 5: 84
  • 6: 85
  • 7: 79
  • 8: 80
  • 9: 81

Temel bir kural olarak, Xortamdaki klavyedeki herhangi bir tuşun değerini bulmak xeviçin, kişi terminalin içindeki değerini göstermek için tuşa basabilir.


Düzenlemelerimizde bir sorun mu var?
Tim

@Tim Hayır, en azından son derece kaldırılmıyor, ki bunun oldukça yararsız olduğuna katılıyorum, ancak bir komut içinde ne çeşitlilik gösterebilir ki bence dil teorisindeki standart notasyon olan köşeli parantez içine alınırsa daha iyi biçimlendirilmiş. sözdizimsel bir kategoriye (düzenlemenize atıfta bulunun) ve bence hemen tanımlanması için (AB düzenlemesine atıfta bulunularak) hemen geri çekilirse, komut adının daha iyi biçimlendirildiğini düşünüyorum; hepsi bu değil bu ihbarı kafamın üst kapalı, daha önce şüphelerim vardı ve sorduğum bu meta üzerinde
kos

Evet, şimdi olduğu gibi sorun yok :) <> standart, ve ben `` herhangi bir emir etrafında gideceğim :)
Tim

3

Ben (üzerinde çalışma gruplarının adında bir uygulama oluşturmak zorunda github It ücretsiz ve açık kaynak - Bir grafik kullanıcı arabirimi üzerinden kolayca bu yapalım Birlik).

tTray menüsü

Temelde burada cevap olarak listelenen wmctrl ve xdotool çözümleri için bir sarmalayıcıdır ve bu tür kurulumları hızlı bir şekilde yapmak ve kaydetmek için kolay bir yol sağlar.


1

Ben Jacob Vlijm mükemmel yazı doğrudan yorum yapmayı temsilcisi yok ama (kullanmak için gerekli argümanlarla bir uygulama başlangıç izin vermek için komut dosyası modifiye setwindowile gedit --new-window). Değişiklik:

if app in p and w[2] in p] for w in ws2]

için:

if app.split()[0] in p and w[2] in p] for w in ws2]

0

Terdon'un senaryosunu yukarıdan oynamış ve bazı yeni şeyler ekledim (monitörü seçme ve her monitör için yüksekliğini ayarlama yeteneği). Sanırım daha fazla monitör ekleyerek genişletilebilir. Umarım diğerleri onu yararlı bulacaktır.

Temel sözdizimi:

prog_name monitor l/r/m window_name (optional)

Prog_name, bu kodu her ne şekilde saklarsanız saklayın; monitör, monitör numarasıdır, örneğin 1 veya 2; l / r / m, sola veya sağa veya maks; ve window_name, hedef pencerenin adıdır (veya adının bir kısmıdır).

Örneğin:

setwindow 1 m chrome

Bash betiği

#!/usr/bin/env bash
set -e
#######################-    Early Definitions    -#######################

snap () {
    wmctrl -r ${WIN} -b toggle,add,maximized_vert && wmctrl -r ${WIN} -e 0,${WINX},0,${WINWIDTH},${WINHEIGHT}
    }

DISPLAYWIDTH=`xdpyinfo | grep 'dimensions:' | cut -f 2 -d ':' | cut -f 1 -d 'x'`;       ## Get screen dimensions
LEFTSCREENWIDTH=1024    ## user set
LEFTSCREENHEIGHT=720    ## user set
RIGHTSCREENHEIGHT=960   ## user set
let "RIGHTSCREENWIDTH=(DISPLAYWIDTH-LEFTSCREENWIDTH)"

#############################-    Logic    -#############################

if [ ! ${3} ]; then
    WIN=":ACTIVE:"
else
    WIN=${3}
fi
case ${1} in
    1)  # monitor one
        LEFT=0
        WINHEIGHT=${LEFTSCREENHEIGHT}
        let "WINWIDTH=LEFTSCREENWIDTH/2"
    ;;
    2)  # monitor two
        let "LEFT=LEFTSCREENWIDTH"
        WINHEIGHT=${RIGHTSCREENHEIGHT}
        let "WINWIDTH=RIGHTSCREENWIDTH/2"
    ;;
    "") # error please select a monitor
        echo "please select a monitor (1 or 2)"
        exit 0
    ;;
esac
case ${2} in
    l|L)
        WINX=${LEFT}
        snap
    ;;
    r|R)
        let "WINX=LEFT+WINWIDTH"
        snap
    ;;
    ""|m|M)
        WINX=${LEFT}
        let "WINWIDTH=WINWIDTH*2"
        snap
    ;;
esac

exit 0
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.