Покрути тебя focus through monitors

I have 3 monitors on my development machine, which runs Ubuntu + Unity. I usually посвяти тебе one монитор to Веб browsing and IM, and the other two to terminals where I run vim or enter commands. гm looking for в single-key-sequence to переключатель between them at-will.

I would like to know how I хан переключатель focus to (top-) windows on each монитор. The behavior гm looking or is sort-of like ALT+TAB, except instead of rotating between applications (which only makes the most-recently-used instance of application available in the rotation), I хан покрути тебя focus between monitors.

Схвати в compromise, I could стенд to использовал the ALT+TAB mechanism if I could have each and every window in the list. I still вообразил this getting annoying, though.

5
задан 30 October 2015 в 23:36

1 ответ

Сценарий (сценарии) для вращения фокуса через мониторы

В установке ниже, включены два сценария: один фоновый сценарий для отслеживания историю сфокусированных окон (см. объяснение внизу для чтения, почему это необходимо), и один сценарий "действия", чтобы поместить под сочетанием клавиш, установить внимание на следующий экран. Если следующий экран в настоящее время не имеет никакого окна для установки внимания на, сообщение отображено:

enter image description here

Сценарии

Сценарий 1; фоновый сценарий, сохраните его (точно) как focus_track.py

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

rootdata = os.environ["HOME"]+"/.focus_history"

def get_screendata():
    return sorted([int(s.split("+")[-2]) for s in subprocess.check_output(["xrandr"]).decode("utf-8").split() if s.count("+") == 2])

def current_windows():
    try:
        return subprocess.check_output(["wmctrl", "-lG"]).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):
    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]

if __name__ == "__main__":
    open(rootdata, "wt").write("This is an empty line")
    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 top == oldlist[0]:
                # 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; сценарий действия, сохраните его как next_focus.py В одном и том же каталоге как сценарий 1.

#!/usr/bin/env python3
import subprocess
import focus_track

# read existing windows and their order (x-wise) from file
windows = [w.split() for w in focus_track.read_data()]
w_data = [[w[0], int(w[2])] for w in windows]
# get position of currently focussed window
currfocus = focus_track.get_top(focus_track.current_windows().splitlines()).split()[2]
# get screendata
screens = focus_track.get_screendata()

def screen_pos(x):
    return [(int(x) > n) for n in screens].count(True)

scr_position = screen_pos(currfocus)
next_screen = 1 if scr_position == len(screens) else scr_position+1
try:
    next_focus = [w for w in w_data if screen_pos(w[1]) == next_screen][0]
    subprocess.Popen(["wmctrl", "-ia", next_focus[0]])
except IndexError:
    subprocess.Popen(["notify-send", "No window to focus on next screen"])

Как использовать

  1. Потребности сценариев wmctrl быть установленным

    sudo apt-get install wmctrl
    
  2. Сценарий 1 копии в пустой файл, сохраните его как (точно) focus_track.py. Имя важно, начиная с обеих функций доли сценариев; сценарий 1 импортируется в сценарий 2.
  3. Сценарий 2 копии в пустой файл, сохраните его как (точно) next_focus.py в одном и том же каталоге как сценарий 1.
  4. Тестовый прогон установка: N.B. Запустите фоновый сценарий прежде, чем открыться (и таким образом сфокусироваться) окна. Windows, открытый перед фоновыми запусками сценария, не "зарегистрирован", непока они не фокусируются

    • Запустите фоновый сценарий (с, например, терминал) с командой:

      python3 /path/to/focus_track.py
      
    • На Ваших различных экранах откройте окна.

    • Выполненный сценарий 2 с командой:

      python3 /path/to/next_focus.py
      

    Фокус должен переключиться на следующий экран. Если текущий экран является последним в строке, фокус переключается на первый экран.

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

    python3 /path/to/focus_track.py
    

    и добавьте сценарий 2 к сочетанию клавиш: выберите: Параметры настройки системы> "Клавиатура"> "Ярлыки"> "Пользовательские Ярлыки". Нажмите "+" и добавьте команду:

    python3 /path/to/next_focus.py
    

    к сочетанию клавиш Вашей симпатии.

Примечания

  • Так как фоновый сценарий отслеживает историю фокуса для непосредственного надлежащего функционирования, это должно предпочтительно запуститься, прежде чем Вы начнете работать над своим компьютером, например, над входят в систему (использующий Приложения Запуска).
  • Сценарий предполагает, что экраны настраиваются слева направо, не - наложение. Их выравнивание по вертикали не важно как бы то ни было.
  • Чтобы "сэкономить топливо" и сделать загрузку сценария незначительно маленькой, сценарий обновляет историю фокуса (только) однажды в секунду. Окно поэтому определяется, как сфокусировано, если оно фокусируется для, по крайней мере, между 0,5 и 1 секундой.
  • Хотя я протестировал его на двух - экранная установка, это должно (и я вполне уверен, это делает), работа правильно над установкой с 3 (+) экраны.




Объяснение:

Что это берет

Для переключения фокуса от одного экрана до другого необходимо определить, который является передней стороной большая часть окна на экран. Главная проблема однако, что окна, распространенные по нескольким экранам, на самом деле все в одном и тот же стек, и таким образом заказаны в одной и той же последовательности (z-wise). Инструменты мы имеем (wmctrl, xdotool, xprop и т.д.) в лучшем случае может только определить в настоящее время активное окно. Они не дают нам информации вообще о порядке окна на другие экраны, так как окна ниже активного окна.

enter image description here

Поэтому на первый взгляд кажется довольно невозможным переключить фокус от одного экрана до другого.
Однако:

Как получить информацию

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

Пример:
У нас в настоящее время есть пять окон: A, B, C, D, E. Если их фокус изменяется через D, E, A, C, B, мы знаем, что z-порядок окон: B, C, A, E, D (по всей длине)

Вместе с их положениями (x-wise) и экранными данными (x-разрешение экранов) у нас есть вся информация, в которой мы нуждаемся. Для переключения фокуса на следующий экран мы затем просто должны искать первое окно, расположенное на следующем экране.

2
ответ дан 23 November 2019 в 10:36

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

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