web-dev-qa-db-ja.com

まだ開いていない場合にのみアプリを起動します

Mac OS XでのAlfredの使用を模倣したいと思います。検索後にアプリを開こうとすると、プログラムがまだ実行されていない場合にのみ新しいウィンドウが開きます。そうでない場合は、そのアプリケーションの現在実行中のインスタンス。とにかく、新しいウィンドウを開く前にこれを確認するためにランチャーのデフォルトの動作を変更する必要はありますか?

15
Dan Jenson

4月7日更新:別のバージョンが追加され、Albertが見つかりました。更新とボーナスをご覧ください!!!

ダッシュ機能について:「」と尋ねました。とにかく、ランチャーのデフォルトの動作を変更して、開く前にこれを確認します新しいウィンドウ」。基本的な答えは、いや、通常のユーザーとしては、その動作をダッシュ​​に追加する方法はありません。ただし、それを実装するユニティスコープ開発者がいる場合は、解決策と学習意欲がある場合は、それらにアプローチするか、自分で開発することができます。私のコーディングスキルは非常に控えめであるため、回避策としてシェルスクリプトとスクリプトのグラフィカルフロントエンドを使用します。

関連情報

元の投稿:

私は、Zenityダイアログとwmctrlを使用して、あなたが求めたものを達成するスクリプトを書きました。これはグラフィカルスクリプトであることに注意してください。つまり、GUIのウィンドウでのみ機能し、ttyで何かを起動しようとしても機能しません。その上、私が理解していることから、アルフレッドはまったく同じことをしています。 here および here の説明に従って、デスクトップショートカットまたはランチャーショートカットを作成できます。

スクリプト:

#!/bin/bash
# Author: Serg Kolo
# Description: A launcher script that checks whether
#       or not a window of a particular program already exists
#       If a window of such program is open, bring it to focus
#       Otherwise - launch a new window
#       Written for https://askubuntu.com/q/440142/295286
# Date: April 6 , 2015
#


MYPROG=$( zenity --entry --title='MY LAUNCHER' --text='Type the name of application to run' )
sleep 0.5
wmctrl -lx | awk '{print $3}' | grep -i "$MYPROG"

if [ $? -eq 0 ]; then
    sleep 1         
    wmctrl -xa $MYPROG
   #as an alternative try the line bellow
   #wmctrl -a $MYPROG
    exit 1
else 
    $MYPROG &
    exit 0
fi

サイドノート:以前のバージョンでは、スクリプトはecho $?を使用して、以前の式が正常に終了したかどうかをテストしました。 muruの提案(編集から)に従って、コードをややコンパクトなバージョンに変更したため、以前のバージョンと現在のバージョンを確認することをお勧めします。

また、以前はwmctrl -a $MYPROGはgoogle-chromeまたはchrome-browserのテストでは機能しませんでした。いくつかの愚かな理由で、一部のプログラムはウィンドウのWM_CLASSプロパティが大文字になっていますが、dpkg --get-selectionsでリストされているプログラムは小文字です(man wmctrlを読み取ってwmctrl -lxを実行します)。 -axを追加することでこれを処理できます。スクリプトは、既に開いているクロムウィンドウを表示します

別のこと-wmctlrは時々遅延を必要とする(別のスクリプトでそれを経験した)という点でやや奇妙なので、sleep 1行を追加する必要がありました。以前は、Firefoxでのオンとオフのようなものでしたが、現在は泳ぎながら動作します。

動作中のスクリプト

以下のアニメーションでは、スクリプトの最初の実行時に、Firefoxのインスタンスが1つ開いており、スクリプトがそのウィンドウにフォーカスを切り替えていることがわかります。 2番目のテストでは、これまで開いていなかったgoogle-chromeの新しいインスタンスを開きます。 (サイドノート:ちなみに、カイロドックを備えたopenboxであるデスクトップについて熱心な場合)

コメントの提案ごとに、埋め込みアニメーションが削除され、リンクのみが投稿されました。壊れている場合は報告してください! http://i.stack.imgur.com/puuPZ.gif

4月7日更新

Zenityのドロップダウンエントリボックスにリストされているすべてのプログラムを作成するために、スクリプトをいくらか改善しました。これで、ユーザーは各プログラムを記憶する必要がなくなりましたが、矢印キーを使用してそれらのリストをスクロールするか、ドロップダウンメニューを開くだけで済みます。また、この改善されたバージョンは、名前ではなくウィンドウIDによってウィンドウを上げるため、パフォーマンスが大幅に向上します。注:.desktopファイルを使用する方法は、cutコマンドを2回使用することで冗長になりますが、これまでのscript-fuはあまり良くないので、これですべてができます。改善のための提案を歓迎します!

#!/bin/bash
# Author: Serg Kolo
# Description: Second version of a launcher script that checks whether
#       or not a window of a particular program already exists
#       If a window of such program is open, bring it to focus
#       Otherwise - launch a new window
#       Written for https://askubuntu.com/q/440142/295286
# Date: April 7 , 2015
#

set -x

MYPROG=$(zenity --entry --text 'Select program from list' --entry-text $(ls /usr/share/applications/*.desktop | cut -d'/' -f5 | cut -d'.' -f1 | xargs echo))
sleep 0.5
# Do we have a window of such program ?
wmctrl -lx| awk '{print $3}'  | grep -i $MYPROG

if [ $? -eq 0 ]; then
    sleep 0.5 # if yes, find that window id, and raise it
    WINID=$(wmctrl -lx | grep -i $MYPROG | awk 'NR==1{print $1}')
    wmctrl -ia $WINID &
 #  exit 0  
else
    echo $MYPROG | grep -i libreoffice
    if [ $? -eq 0  ]
    then
        MYPROG=$(echo $MYPROG | sed 's/-/ --/g')
    fi
    $MYPROG &

#  exit 0 
fi

enter image description here

ボーナス:

実際に Albert を見つけました。これはLinuxバージョンのAlfredですが、自分で試したことはありません。しかし、チェックアウトする価値があります。しかし、ジェイコブがすでに指摘したように、まだバグがあります。

Gnome-Doと呼ばれるアプリがあります。これは、Alfredにグラフィカルに似ていますが、このスクリプトと同じ機能はありません。

enter image description here

このスクリプトが気に入った場合、修正が必要な場合はお知らせください。役立つと思われる場合は、回答を忘れずに投票してください。

6

1. 2番目のダッシュ

質問で説明されているようにアプリケーションを実行する場合、Dashの代替として使用できるスクリプトの下。

Dashと同じ機能を持つウィンドウが存在します。アプリケーションの1つ以上の文字を入力すると、アプリケーションがリストに表示されます。押す Enter 既に実行中かどうかに応じて、アプリケーションを起動または起動します。

ショートカットキーの組み合わせから呼び出すか、ランチャーでアイコンを設定してDashと同様に使用できます(以下を参照)。

enter image description here

スクリプト

#!/usr/bin/env python3
import subprocess
import os
import getpass
import time

user = getpass.getuser()
get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8")
skip = ["%F", "%U", "%f", "%u"]; trim = ["chrome", "chromium", "nautilus"]

def apply(command):
    if "libreoffice" in command:
        proc = [l.split()[0] for l in get("ps -u "+user).splitlines() if "soffice.bin" in l]
        module = command.split("--")[-1]
        time.sleep(0.1)
        try:
            ws = sum([[w.split()[0] for w in get("wmctrl -lp").splitlines() if process in w and module in w.lower()] for process in proc], [])[0]
            subprocess.call(["wmctrl", "-ia", ws])
        except IndexError:
            subprocess.Popen(["/bin/bash", "-c", command+"&"])
    else:
        check = command.split("/")[-1][:14]
        proc = [p.split()[0] for p in get("ps -u "+user).splitlines() if check in p]
        time.sleep(0.5)
        try:
            ws = sum([[w.split()[0] for w in get("wmctrl -lp").splitlines() if process in w] for process in proc], [])
            if command == "nautilus":
                real_window = [w for w in ws if "_NET_WM_WINDOW_TYPE_NORMAL" in get("xprop -id "+w)][0]
            else:
                real_window = ws[0]
            subprocess.call(["wmctrl", "-ia", real_window])
        except IndexError:
            subprocess.Popen(["/bin/bash", "-c", command+"&"])
# default directories of .desktop files; globally, locally, LibreOffice- specific when separately installed
globally = "/usr/share/applications"; locally = os.environ["HOME"]+"/.local/share/applications"; lo_dir = "/opt/libreoffice4.4/share/xdg"
# create list of .desktop files; local ones have preference
local_files = [it for it in os.listdir(locally) if it.endswith(".desktop")]
global_files = [it for it in os.listdir(globally) if it.endswith(".desktop")]
lo_spec = [it for it in os.listdir(lo_dir) if it.endswith(".desktop")] if os.path.exists(lo_dir) else []
for f in [f for f in local_files if f in global_files]:
    global_files.remove(f)
for f in [f for f in local_files if f in lo_spec]:
    lo_spec.remove(f)
dtfiles = [globally+"/"+f for f in global_files]+[locally+"/"+f for f in local_files]+[lo_dir+"/"+f for f in lo_spec]
# create list of application names / commands
valid = []
for f in dtfiles:
    content = open(f).read()
    if all(["NoDisplay=true" not in content,"Exec=" in content]):
        lines = content.splitlines()
        name = [l.replace("Name=", "") for l in lines if "Name=" in l][0]
        command = [l.replace("Exec=", "") for l in lines if all(["Exec=" in l, not "TryExec=" in l])][0]
        valid.append((name, command))
valid.sort(key=lambda x: x[0])
# create zenity list + window
list_items = '"'+'" "'.join([f[0] for f in valid])+'"'
proposed = 'zenity --list --text "Type one or more characters... " --column="Application List" '+\
           '--title="Dash the Second" --height 450 --width 300 '+list_items
try:
    choice = subprocess.check_output(["/bin/bash", "-c", proposed]).decode("utf-8").strip().split("|")[0]
    command = [r[1] for r in valid if r[0] == choice][0]
    # command fixes:
    for s in skip:
        command = command.replace(" "+s, "")
    for t in trim:
        if t in command:
            command = t
    apply(command)
except subprocess.CalledProcessError:
    pass

使い方

スクリプトにはwmctrlがインストールされている必要があります。

Sudo apt-get install wmctrl

次に:

  1. 上記のスクリプトを空のファイルに貼り付けて、dash_alternative.pyとして保存します
  2. ショートカットキーの組み合わせに追加します。[システム設定]> [キーボード]> [ショートカット]> [カスタムショートカット]を選択します。 「+」をクリックして、コマンドを追加します。

    python3 /path/to/dash_alternative.py
    

説明

スクリプトが実行されると、/usr/share/applicationsで表されるすべてのアプリケーションがリストされます。 .dektopファイルを検索し、すべてのアプリケーション名のリスト(最初の "Name ="行から)と、アプリケーションを実行するコマンド(最初の "Exec ="行から)を作成します。

その後、Zenityリストが作成され、すべてのアプリケーションがソートされた方法で表示されます。

アプリケーションが選択されるたびに、スクリプトはアプリケーションが実行されている場合、実行中のプロセスのリストを調べます。その場合、対応するウィンドウが表示されます。そうでない場合は、新しいインスタンスが開かれます。

ノート

  1. 12.04でスクリプトを実行するには(元の質問に12.04というタグが付けられていたため、単にShebangを#!/usr/bin/env pythonに変更し、コマンドで実行します。

    python /path/to/dash_alternative.py
    
  2. 私がテストした限り、スクリプトは正常に機能します。コマンドおよびそれらの(ではない)対応するプロセス名(例:LibreOffice <> soffice.bin)、異なるウィンドウタイプ(nautilusには、「実際の」ウィンドウ以外にいくつかの異なるウィンドウタイプがあります)、複数のpidアプリケーションごと(ChromiumGoogle-chrome)例外が発生する可能性がありますが、上記の例で修正しました。誰かが問題に遭遇した場合、それを言及してください。

2.追加:アプリケーションを実行するための「実際の」ダッシュの代替として設定する

  1. 上記のようにスクリプトをコピーして安全にします
  2. 下のアイコンを右クリックして[セーフ]としてdash_alternative.pngとして保存します

    enter image description here

  3. 以下のコードを空のファイルにコピーし、~/.local/share/applicationsとしてdash_thesecond.desktopとして保存します。 /path/to/dash_alternative.py(スクリプト)および/path/to/dash_alternative.png(アイコン)の正しいパスを設定します

    [Desktop Entry]
    Name=Dash the Second
    Exec=python3 /path/to/dash_alternative.py
    Icon=/path/to/dash_alternative.png
    Type=Application
    Hidden=false
    
  4. .desktopファイルをランチャーにドラッグします。

4
Jacob Vlijm

launcher(画面の左側の垂直パネル)の場合、これはタスク切り替えインターフェイスであるため、既にデフォルトの動作です。

dash(Ubuntuロゴをクリックすると開く大きなビット)の場合、おそらくソースコード自体に大幅な変更を加えることなく、この方法で動作を変更する方法はありません。

ただし、一部のアプリは、そのように動作するように設計されているため、既にこれを行っている場合があります。ただし、すべてのアプリは、このような方法で実装されているわけではなく、必ずしも実装されるべきではありません。

ただし、別の機能として、ウィンドウを開いた場合、 Super+W、アプリケーション名の入力を開始すると、そのアプリケーションのウィンドウのみが表示されます。

0
dobey