Я могу автоматически отправить окно конкретного приложения в самый низкий z-position, когда он теряет фокус?

Я делаю большую часть своей работы в двух приложениях: мой веб-браузер и мой редактор. Я часто переключаюсь назад и вперед между ними с Alt-Tab. У меня также есть клиент IM (Hipchat), открытый в любом случае, но я взаимодействую с ним только редко по сравнению с другими двумя приложениями.

Повторяющееся раздражение - то, что после того, как я взаимодействую с окном Hipchat и Alt-Tab назад, чтобы (сказать) моего редактора, моя память мышц настраивается, чтобы ожидать, что другой Alt-Tab сфокусируется на моем браузере, но я заканчиваю на Hipchat снова.

Там какой-либо путь состоит в том, чтобы заставить Hipchat быть отправленным в дно стека или списка новизны или независимо от того, что это, после того, как это теряет фокус каким-либо образом?

3
задан 14 March 2016 в 16:34

1 ответ

То, что Вы спрашиваете, должно на самом деле позволить окну определенного приложения только появляться или на первом - или на последней позиции, z-wise.

Когда gedit окно (в этом примере) теряет фокус, это отправляется в последний poition (z-wise ниже полупрозрачного окна терминала) вместо того, чтобы убывать только одно положение:

enter image description here enter image description here


Положение Z-окна

В то время как это может быть сделано, мы все еще должны преодолеть некоторые серьезные сложности; Когда окно будет отправлено в самое последнее положение, Вы захотите сохранить z-порядок всех других окон. Однако в настоящее время нет никаких инструментов, которые могут дать нам этот z-порядок окон. Оба xdotool и wmctrl не дайте нам информацию об этом вообще.

Что мы можем сделать, однако должен отслеживать историю фокуса (всех) окон. Так как окно убывает одно положение, если другое окно получает фокус, мы можем завершить z-порядок окон, если мы запускаем фоновый скрипт для наблюдения истории фокуса окон.

Решение два маленьких фоновых сценария

Решение ниже существует двух маленьких фоновых сценариев, для выполнения одновременно.

  1. Сценарий для отслеживания историю фокуса: focus_history.py
  2. Сценарий для отправки окна целевого приложения в последнюю позицию, если это теряет фокус: set_z.py

Сценарий 1

фокус-history.py

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

Сценарий 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

Как настроить

  1. Сценарий использует обоих wmctrl и xdotool

    sudo apt-get install wmctrl xdotool
    
  2. Сценарий 1 копии в пустой файл, сохраните его (точно!) как focus_history.py

  3. Сценарий 2 копии в пустой файл, сохраните его как set_z.py в том же самом каталоге как сценарий 1.

    В главном разделе сценария, в строке:

    proc = "gedit"
    

    замена "gedit" названием процесса Вашего приложения (между кавычками)

  4. Тестовый прогон сценарий: Прежде, чем открыть любые (дополнительные) окна, запустите сценарий 1 командой:

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

    [Сценарий распознает окна, которые были сфокусированы, по крайней мере, однажды. Это будет иметь место, если на сценарии будут работать, входят в систему]

    Как упомянуто, сценарии должны быть в одном и том же каталоге на том же уровне.

  5. Теперь запустите вводные окна и посмотрите, как это ведет себя. Ваше приложение должно переместиться в (самый) фон, если это теряет фокус.

  6. Если все хорошо работает, добавьте его для Запущения Приложений: Тире> Приложения Запуска> Добавляет. Добавьте команду:

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

Примечания

  • установка предполагает, что у Вас есть единственное окно, открытое из целевого приложения. От Вашего вопроса я понимаю, что это имеет место.

Кроме того,

С другой стороны, Вы могли установить сочетание клавиш для повышения окна определенных приложений, если оно существует, как объяснено здесь.

Это потребовало бы однако, чтобы иметь другой ярлык для возвращения к окну первого приложения,

Если...,

Вы установили бы один ярлык для переключения между двумя приложениями. Это однако было бы вне объема этого вопроса...

3
ответ дан 1 December 2019 в 16:25

Другие вопросы по тегам:

Похожие вопросы: