Chỉ khởi chạy ứng dụng nếu chưa mở


16

Tôi muốn bắt chước việc sử dụng Alfred trên Mac OS X, nếu bạn cố mở ứng dụng sau khi tìm kiếm, nó sẽ chỉ mở một cửa sổ mới nếu chương trình chưa chạy, nếu không nó sẽ tập trung vào hiện đang chạy ứng dụng đó. Có cách nào để thay đổi hành vi mặc định của trình khởi chạy để kiểm tra điều này trước khi mở một cửa sổ mới không?


Ngoài ra @pidge Để làm điều này sẽ không khó, nhưng nó cũng sẽ ảnh hưởng đến hành vi "mở bằng" nhấp chuột phải. Tôi đoán đó là một tác dụng phụ không thể chấp nhận.
Jacob Vlijm

1
Tôi nghĩ rằng bạn sẽ có thể tạo một tập lệnh có thể kiểm tra xem một quy trình cụ thể có đang chạy hay không và quyết định khởi chạy một quy trình mới hoặc tập trung vào cửa sổ hiện có. Thật không may, tôi chưa giỏi về kịch bản ... Nhưng @JacobVlijm được biết đến như một anh chàng với các kịch bản cho mọi mục đích;) Bạn sẽ phải thay thế tất cả các trình khởi chạy ban đầu bằng kịch bản tương ứng. Không chắc chắn nếu bạn muốn / có thể làm điều đó - Tôi sẽ không ...
Chỉ huy Byte

2
Nếu bạn đi với tuyến đường kịch bản, bạn có thể sử dụng tập lệnh này làm điểm bắt đầu. Tôi đã viết nó cho LXDE / Openbox ban đầu, nhưng nó cũng hoạt động trong Unity. Thêm thông tin về kịch bản và cách sử dụng của nó ở đây .
Glutimate

1
@ByteCommander chính xác đó là những gì tôi đã nghĩ trong đầu. Bạn thậm chí có thể script- thay thế các lệnh trong các .desktoptập tin. Nếu bạn thay thế lệnh trong .desktoptệp, tuy nhiên, nhấp chuột phải mở với tùy chọn bị hỏng.
Jacob Vlijm

1
Môi trường máy tính để bàn nào?
j0h

Câu trả lời:


6

Cập nhật ngày 7 tháng 4: Một phiên bản khác được thêm và tìm thấy Albert, xem bản cập nhật và phần thưởng dưới đây !!!

Liên quan đến chức năng dấu gạch ngang : Bạn đã hỏi " Có cách nào thay đổi hành vi mặc định của trình khởi chạy để kiểm tra điều này trước khi mở một cửa sổ mới không ". Câu trả lời cơ bản là, không, với tư cách là người dùng thông thường, bạn không có cách nào để thêm hành vi đó vào dấu gạch ngang. Tuy nhiên, nếu có một nhà phát triển phạm vi thống nhất, những người sẵn sàng thực hiện điều đó, bạn có thể tiếp cận họ hoặc tự mình phát triển nếu bạn quyết tâm và sẵn sàng học hỏi. Kỹ năng mã hóa của tôi rất khiêm tốn, do đó tôi sử dụng kịch bản shell và giao diện đồ họa có sẵn cho các kịch bản như một cách giải quyết.

Thông tin liên quan

Bài gốc:

Tôi đã viết một kịch bản sử dụng đoạn hội thoại và wmctrl để đạt được những gì bạn yêu cầu. Lưu ý rằng đây là một tập lệnh đồ họa, có nghĩa là nó sẽ chỉ hoạt động với các cửa sổ, trong GUI và sẽ không hoạt động nếu bạn cố gắng khởi chạy một cái gì đó trong tty. Ngoài ra, từ những gì tôi hiểu Alfred làm chính xác điều tương tự. Bạn có thể tạo một lối tắt trên màn hình cho nó hoặc phím tắt launcher cho nó, như được mô tả ở đâyở đây .

Kịch bản:

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

Ghi chú bên lề: trong phiên bản trước, tập lệnh đã sử dụng echo $?, Để kiểm tra xem các biểu thức trước đó đã thoát thành công chưa. Theo đề xuất của muru (từ bản chỉnh sửa), tôi đã thay đổi mã thành phiên bản nhỏ gọn hơn một chút, vì vậy tôi khuyên bạn nên xem phiên bản trước và phiên bản hiện tại.

Ngoài ra, trước đây wmctrl -a $MYPROGkhông hoạt động với thử nghiệm trình duyệt google-chrome hoặc chromium; vì một số lý do ngu ngốc, một số chương trình có thuộc tính WM_CLASS của cửa sổ được viết hoa, trong khi chương trình được liệt kê dpkg --get-selectionslà chữ thường (chỉ cần đọc man wmctrlvà chạy wmctrl -lx, bạn sẽ biết). Thêm vào đó -ax nên quan tâm đến điều này. Kịch bản hiển thị cửa sổ crom đã mở như bình thường

Một điều nữa - wmctlr hơi kỳ lạ ở chỗ đôi khi nó cần một độ trễ (đã có kinh nghiệm với nó trong một kịch bản khác), vì vậy tôi đã phải thêm sleep 1dòng. Trước đây nó sẽ là loại bật và tắt với firefox, nhưng bây giờ hoạt động bơi lội.

Kịch bản đang hoạt động

Trong phần hoạt hình dưới đây, bạn có thể thấy rằng trong lần chạy đầu tiên của tập lệnh, có một phiên bản firefox mở và tập lệnh chuyển trọng tâm sang cửa sổ đó; trong thử nghiệm thứ hai, tôi mở phiên bản mới của google-chrome, chưa được mở trước đó. (Lưu ý bên lề: Nếu bạn tò mò về máy tính để bàn, nhân tiện, đó là openbox với dock cairo)

Mỗi đề xuất trong các bình luận, hình ảnh động được loại bỏ, chỉ liên kết được đăng. Báo cáo nếu nó bị hỏng xin vui lòng! http://i.stack.imgur.com/puuPZ.gif

Cập nhật, ngày 7 tháng 4

Tôi đã cải thiện phần nào kịch bản để làm cho tất cả các chương trình được liệt kê trong hộp nhập xuống của zenity. Bây giờ người dùng không phải ghi nhớ từng chương trình, mà chỉ có thể cuộn qua danh sách của chúng bằng các phím mũi tên hoặc chỉ cần mở menu thả xuống. Ngoài ra, phiên bản cải tiến này tăng các cửa sổ không phải bằng tên, mà bằng id cửa sổ, mang lại hiệu suất tốt hơn nhiều. Lưu ý, cách tôi đi qua các tệp .desktop là loại dự phòng, sử dụng lệnh cắt hai lần, nhưng vì tập lệnh-fu của tôi không tốt cho đến nay, đây là tất cả những gì tôi có thể làm. Đề xuất cải tiến được chào đón!

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

nhập mô tả hình ảnh ở đây

Tặng kem:

Tôi thực sự đã tìm thấy Albert , phiên bản Linux của Alfred, nhưng bản thân tôi chưa thử. Đáng để kiểm tra mặc dù. Tuy nhiên, như Jacob đã lưu ý, nó vẫn còn lỗi.

Có một ứng dụng tên là Gnome-Do, có đồ họa trông giống với Alfred, tuy nhiên nó không có chức năng tương tự như tập lệnh này.

nhập mô tả hình ảnh ở đây

Hãy cho tôi biết nếu bạn thích tập lệnh này, nếu có bất cứ điều gì cần sửa chữa và đừng quên nêu lên câu trả lời nếu bạn thấy nó hữu ích


Nhân tiện, chú ý cách tôi gõ tên của các chương trình - chính xác như được liệt kê trong dpkg --get-selectons. Khởi chạy trình soạn thảo libreoffice bằng cách gõ "nhà văn" sẽ không hoạt động, nhưng bạn có thể tạo một liên kết tượng trưng đến nó trong thư mục ~ / bin, / bin hoặc / usr / bin của bạn hoặc sử dụng bí danh trong .bashrc hoặc .profile.
Sergiy Kolodyazhnyy

Cũng lưu ý rằng bạn sẽ cần cài đặt wmctl, mặc định nó không xuất hiện, nhưng khá tiện dụng. Tôi cũng đã sử dụng nó để thực hiện điều này
Sergiy Kolodyazhnyy

Bạn có thể thay thế annimation bằng một hình ảnh, liên kết đến annimation? Trình duyệt của tôi tiếp tục "tải" trang, vì vậy tôi không thể làm mới nó. (và phần chú thích không chạy :))
Jacob Vlijm

Cảm ơn! Liên kết hoạt động tốt trong Chrome, không phải trong Firefox.
Jacob Vlijm

@JacobVlijm Ugh, vậy thôi. Không chắc chắn tại sao firefox từ chối chơi nó. Đó chỉ là liên kết imgur với những gì tôi đã tải lên ban đầu
Sergiy Kolodyazhnyy

5

1. Vượt qua thứ hai

Bên dưới tập lệnh có thể được sử dụng thay thế cho Dash, khi nói đến việc chạy các ứng dụng như được mô tả trong câu hỏi của bạn.

Nó tồn tại một cửa sổ có chức năng tương tự như Dash; nếu gõ một hoặc nhiều ký tự của ứng dụng, ứng dụng sẽ xuất hiện trong danh sách. Nhấn Enterđể bắt đầu hoặc nâng ứng dụng, tùy thuộc vào việc nó đã chạy hay chưa.

Bạn có thể gọi nó từ tổ hợp phím tắt hoặc đặt biểu tượng trong trình khởi chạy để sử dụng nó tương tự như Dash (xem thêm bên dưới) hoặc cả hai.

nhập mô tả hình ảnh ở đây

Kịch bản

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

Cách sử dụng

Kịch bản cần wmctrlcài đặt:

sudo apt-get install wmctrl

Sau đó:

  1. Dán đoạn script trên vào một tập tin trống, lưu nó dưới dạng dash_alternative.py
  2. Thêm nó vào tổ hợp phím tắt: Chọn: Cài đặt hệ thống> "Bàn phím"> "Phím tắt"> "Phím tắt tùy chỉnh". Nhấp vào "+" và thêm lệnh:

    python3 /path/to/dash_alternative.py
    

Giải trình

Khi tập lệnh được chạy, Nó liệt kê tất cả các ứng dụng, được trình bày trong /usr/share/applications. Nó tìm kiếm các .dektoptệp, tạo một danh sách tất cả các tên ứng dụng (từ dòng "Name =" đầu tiên) và lệnh để chạy ứng dụng (từ dòng "Exec =" đầu tiên).

Sau đó, một danh sách Zenity được tạo, trình bày tất cả các ứng dụng theo cách được sắp xếp.

Bất cứ khi nào một ứng dụng được chọn, tập lệnh sẽ tìm trong danh sách các tiến trình đang chạy nếu ứng dụng đang chạy. Nếu vậy, cửa sổ tương ứng được nâng lên. Nếu không, một trường hợp mới được mở.

Ghi chú

  1. Để chạy tập lệnh vào ngày 12.04 (vì câu hỏi ban đầu đã được gắn thẻ, 12.04chỉ cần thay đổi shebang thành #!/usr/bin/env pythonvà chạy nó bằng lệnh

    python /path/to/dash_alternative.py
    
  2. Theo như tôi đã thử, kịch bản hoạt động tốt. Các lệnh và tên quy trình tương ứng (không phải) của chúng (ví dụ LibreOffice<> soffice.bin), các loại cửa sổ khác nhau ( nautiluscó một số loại cửa sổ khác nhau, ngoài các cửa sổ "thực"), nhiều pids cho mỗi ứng dụng ( Chromium, Google-chrome) có thể gây ra ngoại lệ, mà tôi đã sửa trong các ví dụ ở trên. Nếu bất cứ ai gặp phải một vấn đề, xin vui lòng đề cập đến nó.

2. Bổ sung: đặt nó làm giải pháp thay thế cho Dash "thực" để chạy các ứng dụng

  1. Sao chép và bảo vệ tập lệnh như đã đề cập ở trên
  2. Lưu biểu tượng bên dưới (nhấp chuột phải> an toàn như) dash_alternative.png

    nhập mô tả hình ảnh ở đây

  3. Sao chép mã dưới đây vào một tập tin trống, lưu nó ~/.local/share/applicationsdưới dạng dash_thesecond.desktop. Đặt đường dẫn chính xác cho /path/to/dash_alternative.py(tập lệnh) và /path/to/dash_alternative.png(biểu tượng)

    [Desktop Entry]
    Name=Dash the Second
    Exec=python3 /path/to/dash_alternative.py
    Icon=/path/to/dash_alternative.png
    Type=Application
    Hidden=false
    
  4. Kéo .desktoptệp vào trình khởi chạy:


1
Rất vui được biết có toàn bộ thư mục các tệp .desktop! Tôi đã tự hỏi làm thế nào để các ứng dụng gốc và cài đặt apt được liệt kê theo tên thay vì các lệnh. Làm tốt lắm!
Sergiy Kolodyazhnyy

@Serg Cảm ơn! và tương tự với bạn :). Ngoài ra còn có một thư mục cục bộ cho .desktopcác tập tin : ~/.local/share/applications. Tôi nghĩ rằng tôi sẽ giới hạn tìm kiếm cho các ứng dụng được cài đặt trên toàn cầu.
Jacob Vlijm

Jacob, tôi không biết python, nhưng có lẽ điều này sẽ hữu ích cho bạn trong việc cải thiện kịch bản của bạn bằng cách biến nó thành một phạm vi thống nhất. Tôi hiểu rằng đây là cách duy nhất để thay đổi chức năng dash chính xác theo cách OP muốn
Sergiy Kolodyazhnyy

@Serg Cảm ơn! đó là một bài viết thú vị, chắc chắn sẽ có một cái nhìn tốt về nó!
Jacob Vlijm

0

Đối với trình khởi chạy (bảng dọc ở bên trái màn hình), đây đã là hành vi mặc định, vì đây là giao diện chuyển đổi tác vụ.

Đối với dấu gạch ngang (bit lớn mở ra khi bạn nhấp vào biểu tượng Ubuntu), không có cách nào để thay đổi hành vi theo cách này, mà không có sự sửa đổi đáng kể đối với chính mã nguồn.

Tuy nhiên, một số ứng dụng có thể đã làm điều này vì chúng được thiết kế để hoạt động theo cách đó. Mặc dù vậy, tất cả các ứng dụng không phải và không nhất thiết phải được triển khai theo cách như vậy.

Tuy nhiên, như một tính năng khác, nếu bạn mở cửa sổ trải rộng bằng Super+ Wvà bắt đầu nhập tên ứng dụng, các cửa sổ cho ứng dụng đó sẽ là những cửa sổ duy nhất được hiển thị.


Tôi thực sự đã tìm thấy phiên bản Linux của những gì OP muốn, xem bài đăng của tôi, phần thưởng. Rõ ràng có ai đó đã có ý tưởng đưa Alfred lên Linux
Sergiy Kolodyazhnyy

1
@Serg hãy thử Albert; Albert vẫn có "lỗi LibreScript", "lỗi Chromium" và "lỗi Chrome". Ngay cả "Lỗi tập tin" ... Albert chỉ đơn giản là luôn mở một phiên bản mới của các ứng dụng đó. LibreOffice đơn giản là không hoạt động. Ngoài ra, trong các bình luận bên dưới liên kết của bạn, bạn có thể tìm thấy một số vấn đề.
Jacob Vlijm

@Serg Không, bạn đã tìm thấy một cách giải quyết, bằng cách thêm một phần mềm bổ sung đang chạy trong nền, cung cấp trải nghiệm người dùng hoàn toàn khác và yêu cầu đào tạo lại cách tìm ứng dụng. Những gì câu hỏi được hỏi là làm thế nào để có tác phẩm này trong dấu gạch ngang Unity. Bạn có thể có được một tính năng tương tự bên ngoài Unity, nhưng cách duy nhất để thay đổi Unity để làm điều này, là thay đổi mã nguồn.
dobey

@dobey Vâng, đó là sự thật; thay đổi chức năng dash là ngoài tầm với của chúng tôi, vì vậy. . . phải làm gì với những gì chúng ta có sẵn, phải không? Trừ khi có một nhà phát triển sẵn sàng viết mã phạm vi thống nhất với chức năng đó. . .
Sergiy Kolodyazhnyy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.