Tôi có thể tự động gửi cửa sổ của một ứng dụng cụ thể đến vị trí z thấp nhất không, khi nó mất tiêu điểm?


3

Tôi làm hầu hết công việc của mình trong hai ứng dụng: trình duyệt web và trình soạn thảo của tôi. Tôi thường xuyên chuyển đổi qua lại giữa chúng bằng Alt-Tab. Tôi cũng có một ứng dụng khách IM (Hipchat) luôn mở, nhưng tôi chỉ tương tác với nó hiếm khi so với hai ứng dụng còn lại.

Một điều khó chịu lặp đi lặp lại là sau khi tôi tương tác với cửa sổ Hipchat và Alt-Tab trở lại (nói) trình chỉnh sửa của tôi, bộ nhớ cơ của tôi được điều chỉnh để mong đợi một Alt-Tab khác tập trung vào trình duyệt của tôi, nhưng tôi lại kết thúc với Hipchat.

Có cách nào để khiến Hipchat được gửi đến cuối danh sách ngăn xếp hoặc lần truy cập gần đây hay không, sau khi nó mất tập trung bằng bất kỳ phương tiện nào?


Vì không có cách nào để đọc thứ tự z hiện tại của các cửa sổ theo cách tĩnh , chỉ có một kịch bản nền sẽ thực hiện công việc. Kịch bản sẽ không thêm gì vào tải, đó có phải là một giải pháp chấp nhận được cho bạn không?
Jacob Vlijm 11/03/2016

Chắc chắn, điều đó tốt.
Sean

Câu trả lời:


3

Những gì bạn yêu cầu thực sự là cho phép cửa sổ của một ứng dụng cụ thể chỉ xuất hiện ở vị trí đầu tiên hoặc cuối cùng, z-khôn ngoan.

Khi cửa sổ gedit (trong ví dụ này) mất tiêu điểm, nó sẽ được gửi đến bài thơ cuối cùng (z-khôn, bên dưới cửa sổ đầu cuối bán trong suốt) thay vì chỉ giảm một vị trí :

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


Vị trí Z của cửa sổ

Trong khi nó có thể được thực hiện, chúng ta vẫn phải khắc phục một số biến chứng nghiêm trọng; Khi cửa sổ được gửi đến vị trí cuối cùng, bạn sẽ muốn giữ thứ tự z của tất cả các cửa sổ khác. Tuy nhiên, hiện tại, không có công cụ nào có thể cung cấp cho chúng tôi thứ tự z này của các cửa sổ. Cả hai xdotoolwmctrlcho chúng tôi không có thông tin về bất cứ điều gì.

Tuy nhiên, những gì chúng ta có thể làm là theo dõi lịch sử tập trung của (tất cả) các cửa sổ. Vì một cửa sổ hạ xuống một vị trí nếu một cửa sổ khác lấy nét, chúng ta có thể kết luận thứ tự z của các cửa sổ nếu chúng ta chạy một kịch bản nền để xem lịch sử lấy nét của các cửa sổ.

Giải pháp hai tập lệnh nền nhỏ

Giải pháp dưới đây tồn tại của hai tập lệnh nền nhỏ, để chạy đồng thời.

  1. Một kịch bản để theo dõi lịch sử tập trung: focus_history.py
  2. Một tập lệnh để gửi cửa sổ của ứng dụng được nhắm mục tiêu đến vị trí cuối cùng nếu nó mất tiêu điểm: set_z.py

Kịch bản 1

tập trung-history

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

rootdata = os.environ["HOME"]+"/.focus_history"
open(rootdata, "wt").write("This is an empty line")

def current_windows():
    try:
        return subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8")
    except subprocess.CalledProcessError:
        pass

def convert_format(w_id):
    return w_id[:2]+(10-len(w_id))*"0"+w_id[2:]

def read_data():
    return open(rootdata).read().splitlines()

def get_top(wlist):
    try:
        top = convert_format(
            [l.split("#")[-1].strip() for l in subprocess.check_output(
                ["xprop", "-root"]
                ).decode("utf-8").splitlines() \
               if "_NET_ACTIVE_WINDOW(WINDOW)" in l][0])
        return [l for l in wlist if top in l][0]
    except IndexError:
        pass

if __name__ == "__main__":
    while True:
        time.sleep(1)
        wdata = current_windows()
        if wdata != None:
            wlist = wdata.splitlines()
            # get frontmost window (as in wmctrl -lG)
            top = get_top(wlist)
            oldlist = read_data()
            if not any([top == oldlist[0], top == None]):
                # clean up closed windows
                [oldlist.remove(l) for l in oldlist if not l.split()[0] in wdata]
                # remove possible other mentions of the active window
                [oldlist.remove(l) for l in oldlist if l.startswith(top.split()[0])]
                open(rootdata, "wt").write(("\n").join([top]+oldlist))

Kịch bản 2

#!/usr/bin/python3
import subprocess
import time
import focus_history

# --- set the process name of your application below
proc = "gedit"
# ---

focus_hist = focus_history.rootdata

def get(val):
    try:
        return subprocess.check_output(val).decode("utf-8").strip()
    except subprocess.CalledProcessError:
        pass

def front_w():
    get_front = str(hex(int(get(["xdotool", "getactivewindow"]))))
    return get_front[:2]+(10-len(get_front))*"0"+get_front[2:]

while True:
    time.sleep(1)
    pid = get(["pgrep", proc])
    front1 = ""
    while pid:
        time.sleep(1)
        frontpid = get(["xdotool", "getactivewindow", "getwindowpid"])
        front2 = frontpid == pid
        if front2 != front1:
            if front2 == False:
                zdata = [l for l in open(focus_hist).read().splitlines()]
                wins = list(reversed([l.split()[0] for l in zdata if not pid in l]))
                for w in wins+[front_w()]:
                    cmd = ["xdotool", "windowraise", w]
                    subprocess.call(cmd)
        pid = get(["pgrep", proc])            
        front1 = front2

Làm thế nào để thiết lập

  1. Kịch bản sử dụng cả hai wmctrlxdotool

    sudo apt-get install wmctrl xdotool
  2. Sao chép tập lệnh 1 vào một tệp trống, lưu nó (chính xác!) Dưới dạng focus_history.py

  3. Sao chép tập lệnh 2 vào một tập tin trống, lưu nó như set_z.py trong cùng thư mục với tập lệnh 1.

    Trong phần đầu của tập lệnh, trong dòng:

    proc = "gedit"

    thay thế "gedit"bằng tên quy trình của ứng dụng của bạn (giữa các trích dẫn)

  4. Kiểm tra- chạy tập lệnh: Trước khi mở bất kỳ cửa sổ (bổ sung) nào , hãy khởi động tập lệnh 1 bằng lệnh:

    python3 /path/to/focus_history.py & python3 /path/to/set_z.py

    [Kịch bản sẽ nhận ra các cửa sổ được tập trung ít nhất một lần. Đó sẽ là trường hợp nếu tập lệnh được chạy khi đăng nhập]

    Như đã đề cập, các tập lệnh nên ở trong một và cùng một thư mục, ở cùng cấp độ.

  5. Bây giờ bắt đầu mở các cửa sổ và xem cách nó hoạt động. Ứng dụng của bạn sẽ chuyển sang nền (rất) nếu mất tập trung.

  6. Nếu tất cả đều hoạt động tốt, hãy thêm nó vào Ứng dụng khởi động: Dash> Ứng dụng khởi động> Thêm. Thêm lệnh:

    /bin/bash -c "sleep 15 && python3 /path/to/focus_history.py & python3 /path/to/set_z.py"

Ghi chú

  • cài đặt giả sử bạn có một single mở cửa sổ của ứng dụng nhắm mục tiêu. Từ câu hỏi của bạn, tôi hiểu đó là trường hợp.

Hoặc

Ngoài ra, bạn có thể đặt phím tắt để nâng cửa sổ của một ứng dụng cụ thể nếu nó tồn tại, như được giải thích ở đây .

Tuy nhiên, điều đó đòi hỏi phải có một lối tắt khác để quay lại cửa sổ của ứng dụng đầu tiên,

Trừ khi...,

Bạn sẽ thiết lập một phím tắt để chuyển đổi giữa hai ứng dụng. Tuy nhiên, điều đó sẽ nằm ngoài phạm vi của câu hỏi này ...


Khi thử nghiệm xdotool windowraise, tôi thấy rằng nó không thực sự nâng bất kỳ cửa sổ nào. Thay vào đó, nếu tôi cố gắng nâng cửa sổ của một ứng dụng cụ thể, biểu tượng khởi chạy tương ứng sẽ rung lên trong giây lát và mũi tên nhỏ bên cạnh biểu tượng sẽ chuyển từ màu trắng sang màu xanh. Các lệnh xdotool khác không làm gì cho đến khi tôi nhấp vào biểu tượng, sau đó tôi lại nhận được hành vi lắc. Có một số cấu hình trình quản lý cửa sổ mà tôi cần đặt để các lệnh tôi phát hành với xdotool được tuân theo không?
Sean

@Sean Không chắc ý của bạn là gì, việc nâng cửa sổ được thực hiện bởi tập lệnh chứ không phải làm gì đó bằng tay. Không có biểu tượng rung lắc có liên quan. Bạn có thể rõ ràng hơn một chút?
Jacob Vlijm

Tôi có nghĩa là trong khi cố gắng hiểu các tập lệnh của bạn, tôi đã đưa ra các lệnh tương tự như vậy, từ dòng lệnh. Các xdotoollệnh đã không làm việc như được quảng cáo từ dòng lệnh, vì vậy không có lý do để hy vọng rằng nó sẽ trong kịch bản một trong hai.
Sean
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.