事前に定義されたウィンドウサイズと位置でアプリケーションを起動するにはどうすればよいですか?


22

ターミナルコマンドを代わりに使用して、UnityのCtrl-Alt-Keypadショートカットの影響を達成する方法はあるのでしょうか。guiウィンドウを画面の半分のサイズ(左揃えまたは右揃え)に設定するコマンドが必要です。

背景として、ログイン後に実行するスクリプトを記述しています。Zenityを使用して、開発環境(GVimとIPythonを並べて)を開くかどうかを尋ねます。私が使用して、これらのプログラムのための2つの同じサイズのウィンドウを達成しようとしているset lines= columns=中で、私.gvimrcc.IPythonWidget.width =し、c.IPythonWidget.height =私の中でipython_qtconsole_config.py。ただし、このアプローチには問題があります。


私はそれが十分に詳細にトピックを説明していないため、アップデートをチェックすることをお勧めします私の答えを更新
KOS

回答:


17

何に出会うか

最初にアプリケーションを呼び出してから、そのウィンドウを特定の位置とサイズに配置する場合、アプリケーション呼び出してから実際にウィンドウが表示されるまでの時間は予測できません。システムが占有されている場合、アイドル状態の場合よりも大幅に長くなる可能性があります。

ウィンドウが表示された後、(すぐに)位置決め/サイズ変更が行われるようにするための「スマート」な方法が必要です。

アプリケーションを呼び出し、表示されるのを待って、画面に配置するスクリプト

次のスクリプトを使用すると、アプリケーションを呼び出して、コマンドで表示される位置とサイズを設定できます。

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

いくつかの例:

  • gnome-terminalウィンドウを呼び出して50%にサイズ変更し、右半分に配置するには:

    <script> gnome-terminal 840 0 50 100

    ここに画像の説明を入力してください

  • を呼び出すにgeditは、ウィンドウを左側に配置し、を呼び出しgnome-terminalて右側に配置します(v-size46%に設定してウィンドウ間に少しスペースを空けます)。

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

    ここに画像の説明を入力してください

  • Inkscapeを呼び出すには、ウィンドウを画面の左/上部に配置します。

    <script> inkscape 0 0 50 50

    ここに画像の説明を入力してください

スクリプトとその使用方法

  1. との両方xdotoolをインストールしwmctrlます。でサイズ変更を行うと(具体的に)いくつかの特性が生じる可能性があるため、両方を使用しました。wmctrlUnity

    sudo apt-get install wmctrl
    sudo apt-get install xdotool
  2. 以下のスクリプトを空のファイルにコピーし、setwindow(拡張子なし)として保存し~/binます; 必要に応じてディレクトリを作成します。
  3. スクリプトを実行可能にします(!)
  4. 作成したばかりの場合~bin、次を実行します。source ~/.profile
  5. コマンドを使用してスクリプトをテスト実行します(例)

    setwindow gnome-terminal 0 0 50 100

    言い換えると:

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

すべてが正常に機能する場合は、必要な場所でコマンドを使用します。

スクリプト

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

何をする

スクリプトが呼び出されると、次のようになります。

  1. アプリケーションを起動します
  2. ウィンドウリストを監視します(を使用wmctrl -lp
  3. 新しいウィンドウが表示される場合、新しいウィンドウが呼び出されたアプリケーションに属しているかどうかを確認します(を使用してps -ef ww、ウィンドウのpid とアプリケーションのpidを比較します)
  4. その場合、引数に従ってサイズと位置を設定します。アプリケーションがappr内に「表示」されない場合。15秒、スクリプトは、エラーのためにアプリケーションが実行されないと想定します。その後、スクリプトは終了し、新しいウィンドウが無限に待機するのを防ぎます。

軽微な問題

Unityでは、wmctrlまたはのいずれかxdotoolでウィンドウを(再)配置および(再)サイズ変更すると、ウィンドウは100%に設定しない限り、常に画面の境界に小さな境界を保持します。上記の画像(3)で確認できます。一方、inkscapeウィンドウが上に置かれたx位置0、あなたはまだユニティランチャーとの間にマイナーのマージ見ることができるinkscape窓を。


親愛なるジェイコブ、これは素晴らしいスクリプトです!1つの質問:開いているウィンドウの次元を見つけて、後でスクリプトと一緒に使用するにはどうすればよいですか?
-orschiro

こんにちは@orschiro私は会議のために走らなければなりません...数時間後に戻ってきます:)
ジェイコブVlijm

1
こんにちは、@ orschiro。wmctrlインストール済みの場合、コマンド:wmctrl -lG | grep <windowname>は次のような出力を表示します 0x03600e4f 0 723 197 1114 563 jacob-System-Product-Name dimkeyboard.sh (~/Bureaublad) - gedit。この出力では、3列目から6列目には、寸法x、y、幅、幅、高さが表示されます。
ジェイコブVlijm 16

ジェイコブに感謝します!私は正しくセットアップを行ったと思いますが、それぞれのウィンドウは現在フルスクリーンで開きます。何か案は?
-orschiro

1
私は、アプリケーションにパラメータを追加したので、私はこのスクリプトを愛し、私はそれが私のために動作させるために最初のブロックに次の変更をしなければならなかった: 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> <編集>それは拒否したコードという形式に</編集>。
ロントンプソン

3

あなたが望む実際のコマンドは次のようなものです

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

これにより、現在のウィンドウが画面の半分になり(画面$HALFのサイズに変更)、左側にスナップします。右にスナップするには、次を使用します

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

wmctrlを使用する代わりに、を使用して、興味のあるウィンドウのIDを取得することもできます:ACTIVE:。しかし、それは問題のウィンドウに依存するため、そこでは仕方がありません。見ていman wmctrl多くのために。


そのためのスクリプトを作成しました。私はUnityを使用していないので、Unityが動作することを保証できませんが、Unityが動作しない理由はわかりません。必要wmctrlxdpyinfoありdisper、インストールする必要があります:

sudo apt-get install wmctrl x11-utils disper

次に、以下のスクリプトをとして保存し、~/bin/snap_windows.shで実行可能にして実行chmod a+x ~/bin/snap_windows.shできます。

snap_windows.sh r

右側にスナップします。lウィンドウを最大化するには、左側で引数なしで使用します。現在のウィンドウで実行されるため、ターミナル以外で実行する場合はショートカットを割り当てる必要があります。

このスクリプトは、シングルモニターとデュアルモニターの両方のセットアップで動作するように記述しているため、ユーザーが求めるものよりも少し複雑です。

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

これはを使用して実行できますxdotool

インストールするには、xdotool次を実行できます。

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

次に、ターミナルウィンドウにCtrl+ Alt+ <keypad_key>キーストロークを送信するには、X次を実行します。

xdotool key Ctrl+Alt+<keypad_key_value>

* <keypad_key_value> =下のリストのキーパッドキーの値

GUIプログラムを実行し、キーストロークをそのXウィンドウ(この場合はxdotoolコマンド実行時のアクティブウィンドウ)に送信するには、次を実行できます。

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

* <command> =キーストロークを送信するウィンドウを開くコマンド。<delay> =キーストロークを送信する前にミリ秒単位で待機する時間。<keypad_key_value> =下のリストにあるキーパッドキーの値

ほとんどの場合、スタンドアロンプ​​ロセスとして発行するコマンドを実行する必要があることに注意してください(上記の例のnohup <command> &代わりに実行<command>するなど)。そうしないxdotoolと、<command>実行が完了するまで実行されません。

また、いくつかの遅延を設定する必要があります。そうしないと、ターゲットウィンドウが完全にロードされる前にキーストロークが送信されますX(遅延が発生する500msはずです)。

可能な値<keypad_key_value>は次のとおりです。

  • 090
  • 187
  • 288
  • 389
  • 483
  • 584
  • 685
  • 779
  • 880
  • 981

経験則として、X環境内のキーボードの任意のキーの値を調べるには、実行xevしてキーを押し、端末内にその値を出力します。


編集に何か問題がありますか?
ティム

@Timいいえ、少なくとも最後の行を削除することではなく、それはかなり役に立たないことに同意しますが、コマンド内で変化する可能性があるのは、参照する言語理論の標準表記である山括弧で囲まれている場合、より良いフォーマットです構文のカテゴリ(編集を参照)に追加します。コマンド名は、すぐに認識できるように、バッククォートで囲まれた方がフォーマットが良いと思います(ABの編集を参照)。このすべてが私の頭の上にあるわけではないことに注意してください、私は以前に疑問を持っていたので、メタでこれを尋ねまし
コス

ええ、それは今のように大丈夫です:) <>が標準であり、私は ``すべてのコマンドの周りに行きます:)
ティム

3

Unity用のWorksets(github上)という名前のアプリケーションを作成しました。これにより、グラフィカルユーザーインターフェイスを介して簡単にこれを行うことができます。これは無料でオープンソースです。

tTrayメニュー

基本的には、ここに答えとしてリストされているwmctrlおよびxdotoolソリューションのラッパーであり、このようなセットアップをすばやく作成して保存する簡単な方法を提供します。


1

Jacob Vlijmの優れた投稿に直接コメントする担当者はいませんが、引数を使用setwindowしてアプリケーションを起動できるようにスクリプトを変更しました(で使用する必要がありますgedit --new-window)。変化する:

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

に:

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

0

上からTerdonのスクリプトいじり、いくつかの新しいものを追加しました(モニターを選択し、各モニターの高さを設定する機能)。それは、私が考えるモニターをさらに追加することに拡張可能だろう。うまくいけば、他の人が役に立つと思います。

基本的な構文:

prog_name monitor l/r/m window_name (optional)

prog_nameは、このコードを保存した名前です。monitorは、1または2などのモニター番号です。l / r / mは左または右または最大です。window_nameは、ターゲットウィンドウの名前(またはその一部)です。

例えば:

setwindow 1 m chrome

Bashスクリプト

#!/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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.