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


16

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


また、@ pidgeこれを行うことは難しくありませんが、右クリックの「開く」動作にも影響します。それは容認できない副作用だと思います。
ジェイコブVlijm

1
特定のプロセスが既に実行されているかどうかを確認し、新しいプロセスを起動するか、既存のウィンドウにフォーカスを与えるかを決定できるスクリプトを作成できると思います。残念ながら、私はまだスクリプティングがあまり得意ではありません...しかし、@ JacobVlijmはあらゆる目的のスクリプトを持つ男として知られています;)ただし、すべての元のランチャーをそれぞれのスクリプトに置き換える必要があります。あなたがそれをしたい/できるかどうかわからない-私はそうしないだろう
バイトコマンダー

2
スクリプトルートを使用する場合は、このスクリプトを出発点として使用できます。最初にLXDE / Openbox用に作成しましたが、Unityでも機能するはずです。スクリプトとその使用法の詳細については、こちらをご覧ください
グルタニメート

1
@ByteCommanderまさにそれが私が念頭に置いていたものでした。スクリプトを使用して、.desktopファイル内のコマンドを置き換えることもできます。.desktopただし、ファイル内のコマンドを置換すると、右クリックで開くオプションが壊れます。
ジェイコブVlijm

1
どのデスクトップ環境ですか?
j0h

回答:


6

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

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

関連情報

元の投稿:

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

スクリプト:

#!/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 /ubuntu//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またはクロムブラウザのテストでは機能しませんでした。いくつかのばかげた理由で、一部のプログラムはウィンドウのWM_CLASSプロパティが大文字になっていますが、でリストされているプログラムdpkg --get-selectionsは小文字です(読んman wmctrlで実行するだけwmctrl -lxです)。-axを追加することでこれを処理できます。スクリプトは、既に開いているクロムウィンドウを表示します

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

動作中のスクリプト

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

コメントの提案ごとに、埋め込みアニメーションが削除され、リンクのみが投稿されました。壊れている場合は報告してください! 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 /ubuntu//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

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

ボーナス:

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

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

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

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


ところで、プログラムの名前を入力する方法に注意してください-に記載されているとおりdpkg --get-selectonsです。「writer」と入力してlibreofficeライターを起動しても機能しませんが、〜/ bin、/ bin、または/ usr / binフォルダーでシンボリックリンクを作成するか、.bashrcまたは.profileでエイリアスを使用できます。
セルギーコロディアズニー

また、wmctlをインストールする必要があることに注意してください。デフォルトでは付属していませんが、かなり便利です。私も作ってそれを使用しました。この
Sergiy Kolodyazhnyy

アニメーションを画像に置き換えて、アニメーションにリンクできますか?私のブラウザはページを「ロード」し続けるため、ページを更新できません。(およびアニメーションは実行されません:))
ジェイコブVlijm

ありがとう!リンクはFirefoxではなくChromeで正常に機能します。
ジェイコブVlijm

@JacobVlijmうーん、そうです。firefoxがそれを再生することを拒否している理由がわかりません。それは私が最初にアップロードされたものにだけimgurのリンクです
Sergiy Kolodyazhnyy

5

1. 2番目のダッシュ

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

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

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

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

スクリプト

#!/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ているため、シェバンをに変更#!/usr/bin/env pythonし、コマンドで実行するだけです)

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

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

  1. 上記のようにスクリプトをコピーして安全にします
  2. 下のアイコン(右クリック>安全な名前)として保存します dash_alternative.png

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

  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ファイルをランチャーにドラッグします。


1
.desktopファイルのフォルダ全体があることを知ってうれしいです!ネイティブアプリケーションとaptがインストールされたアプリケーションは、コマンドではなく名前でどのようにリストされるのかと思っていました。良い仕事だ!
セルギーコロディアズニー

@Sergありがとう!そしてあなたに同じ :)。.desktopファイル用のローカルディレクトリもあります ~/.local/share/applications。グローバルにインストールされたアプリケーションに検索を制限すると思いました。
ジェイコブVlijm

ジェイコブ、私はpythonを知りませんが、多分これは、それを単一スコープに変えることによってスクリプトを改善するのに役立つでしょう。私の理解では、これはOPが望んでいる正確にどのようにALTERダッシュ機能への唯一の道であるということである
Sergiy Kolodyazhnyy

@Sergありがとう!それは興味深い投稿です、間違いなくそれをよく見るでしょう!
ジェイコブVlijm

0

ためのランチャーがタスク切り替えインタフェースであるとして(画面の左側の縦パネル)、これは、既にデフォルトの振る舞いです。

以下のためにダッシュ(あなたがUbuntuのロゴをクリックすると開く大きなビット)、ソースコード自体に、おそらく重要な変更を加えることなく、このように動作を変更する方法はありません。

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

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


私は実際にOPが望んでいたLinuxバージョンを見つけました。私の投稿のボーナスセクションをご覧ください。どうやら誰かが他のLinuxにアルフレッドをもたらすためにアイデアを持っていた
Sergiy Kolodyazhnyy

1
@SergはAlbertを試してください。アルバートには、まだ「LibreOfficeバグ」、「Chromiumバグ」、「Chromeバグ」があります。「ファイルのバグ」でさえも、Albertは単にそれらのアプリケーションの新しいインスタンスを常に開いています。LibreOfficeはまったく機能しません。また、リンクの下のコメントで、多くの問題を見つけることができます。
ジェイコブVlijm

@Sergいいえ、バックグラウンドで実行される追加のソフトウェアを追加することで回避策が見つかりました。これはまったく異なるユーザーエクスペリエンスを提供し、アプリケーションの検索方法を再トレーニングする必要があります。質問は、この作業をUnityダッシュボードで行う方法でした。Unityの外部で同様の機能を使用できる場合がありますが、これを行うためにUnityを変更する唯一の方法は、ソースコードを変更することです。
ドビー

@dobeyまあ、それは本当です。ダッシュ機能の変更は、私たちの手の届かないところにあります。。.gottaは、私たちが利用できるものを処理しますよね?そのような機能を備えたユニティスコープをコーディングする開発者がいない限り。。。
セルギーコロディアズニー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.