инструмент или альтернатива wmctrl для KDE Wayland

Вопрос или проблема

Большая часть моего рабочего процесса основана на использовании ярлыков. В настоящее время я использую xbindkeys и wmctrl для запуска или активации приложения. Например: Super+F открывает firefox или запускает его, если он не запущен.

Autokey хорошо работает с KDE, и я также мог бы использовать родной менеджер пользовательских ярлыков KDE, чтобы заменить xbindkeys, но я не могу найти (и я много гуглил) способ определить, запущено ли окно/приложение, и если нет, активировать его.

Я, вероятно, могу использовать ps или подобную команду, чтобы узнать, запущено ли приложение, и если нет, запустить его, но это приводит к конечной проблеме: как программно активировать (или установить фокус) существующее запущенное окно/приложение?

Похоже, есть какое-то решение с gdbus для GNOME, но, конечно, это не сработает в KDE.

У кого-нибудь есть идея или подсказка, что я могу сделать?

После долгих поисков я нашел решение, которое будет работать только для KDE: использование скрипта kwin.

Скрипт следующий:

  1. используйте pgrep, чтобы узнать, запущена ли программа (полезная команда grep)
  2. если запущена:
    1. установите скрипт kwin, который будет явно “активировать” окно с переданным className или заголовком
    2. запустите скрипт
    3. остановите скрипт
    4. удалите скрипт
  3. если не запущена: выполните команду для ее запуска.

Например, если я хочу сфокусироваться или запустить Firefox, я сделаю это с помощью моего скрипта:

ww -f firefox -c firefox

-f: имя класса окна
-c: команда для запуска, если не запущена
-fa: альтернативный фильтр, использующий заголовок окна вместо класса

Это скрипт, который я использую сейчас, и он работает отлично.

Вот решение, которое работает на Wayland с GNOME.

Оно имеет следующее поведение,

  1. Если приложение не запущено, откройте его.
  2. Если приложение запущено и не имеет фокуса, выведите его на фокус.
  3. Если приложение уже в фокусе и существует несколько экземпляров одного и того же приложения, переключайтесь между ними.
  4. Если приложение в фокусе и это единственный экземпляр, ничего не делать.
#!/usr/bin/bash

# Использование: path/to/script <wm_class> <wm_class_instance> <команда для запуска приложения>
#
# Пожалуйста, убедитесь, что у вас установлено следующее:
# - gdbus
# - jq
# - Расширение GNOME Shell: Window Calls
#
# Для установки расширения вы можете использовать следующую команду:
# gnome-extensions install [email protected]
# ИЛИ посетите
# https://extensions.gnome.org/extension/4724/window-calls/
#
# Вы можете получить wm_class и wm_class_instance, используя команду:
# gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/Windows --method org.gnome.Shell.Extensions.Windows.List | cut -c 3- | rev | cut -c4- | rev | jq '.'

wm_class=$1
wm_class_instance=$2

# Получите список окон для текущего рабочего пространства с помощью gdbus
win_list=$(gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/Windows \
  --method org.gnome.Shell.Extensions.Windows.List | cut -c 3- | rev | cut -c4- | rev | jq -c '.[] | select(.in_current_workspace == true)')

# Получите ID текущего окна с фокусом
active_win_id=$(echo "$win_list" | jq -r 'select(.focus == true) | .id')

# Найдите все окна, соответствующие указанному имени приложения в текущем рабочем пространстве
matching_windows=$(echo "$win_list" | jq -r --arg app "$wm_class" --arg instance "$wm_class_instance" 'select(.wm_class == $app and .wm_class_instance == $instance) | .id')

# Переключитесь между окнами, если есть несколько совпадений
if [[ "$matching_windows" == *"$active_win_id"* ]]; then
  # Удалите активное окно из списка и выберите следующий ID окна
  switch_to=$(echo "$matching_windows" | sed "s/$active_win_id//" | awk 'NR==1')

  # Если активное окно последнее в списке, выберите первое окно
  if [ -z "$switch_to" ]; then
    switch_to=$(echo "$matching_windows" | awk 'NR==1')
  fi
else
  # Выберите первое окно для переключения, если активное окно не соответствует приложению
  switch_to=$(echo "$matching_windows" | awk 'NR==1')
fi

# Установите фокус на окно, если оно найдено, или выполните предоставленную команду
if [[ -n "$switch_to" ]]; then
  gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/Windows \
    --method org.gnome.Shell.Extensions.Windows.Activate "$switch_to"
else
  # Если предоставлена команда, выполните ее для открытия приложения
  if [[ -n "${@:3}" ]]; then
    ("${@:3}") &
  fi
fi

exit 0

Вы можете установить это как пользовательские сочетания клавиш gnome,

Бонусный совет: Если вы хотите автоматически создавать резервные копии сочетаний клавиш обратитесь к этому

Этот скрипт AutoKey будет акцентировать внимание на Firefox, если он уже запущен, или запустит и активирует его, если он не запущен:

output = system.exec_command("wmctrl -l", getOutput=True)
if "Firefox" in output:
    window.activate("Firefox",switchDesktop=True)
else:
    subprocess.Popen(["firefox"])

Обратите внимание, что я использовал функцию subprocess.Popen, потому что она позволяет вам выполнять другой код и/или взаимодействовать с процессом с помощью функции subprocess.communicate, пока процесс работает.

Ответ или решение

Краткий обзор инструментов для управления окнами в KDE под Wayland

Вам, вероятно, будет интересно узнать, что разработка под Wayland имеет свои особенности по сравнению с традиционным X11, особенно когда речь заходит о работе с оконными менеджерами и интеграции горячих клавиш. Хотя wmctrl является мощным инструментом для управления окнами в X11, на Wayland с KDE вам придется искать альтернативные решения.

Проблема и контекст

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

  1. Проверить, запущено ли приложение (например, Firefox).
  2. Если приложение запущено, активировать его.
  3. Если приложение не запущено, открыть его.

Можно использовать такие команды, как pgrep для определения, запущено ли приложение, но основная сложность заключается в активации существующих окон. Под GNOME существуют решения, основанные на gdbus, но они не подойдут для KDE.

Решение через KWin Скрипты

Существует эффективный способ решить данную задачу, используя KWin скрипты. Эта методика хорошо удовлетворяет требованиям управления окнами в среде KDE. Вот общий подход:

  1. Использование pgrep: Для проверки, запущено ли приложение.
  2. Создание скрипта KWin: Скрипт KWin должен уметь активировать окно по имени класса или заголовку.
  3. Запуск и остановка скрипта: Запускайте скрипт для фокусировки активного окна и останавливайте его после выполнения.

Пример скрипта

Пример простого скрипта для KWin, который выполняет указанную задачу:

#!/usr/bin/env bash

APP_NAME="firefox"
APP_COMMAND="firefox"
CLASS_NAME="Firefox"

# Проверяем, запущен ли процесс
if pgrep -x "$APP_NAME" > /dev/null; then
    # Программа запущена, активируем окно
    qdbus org.kde.KWin /KWin activeWindow setDesktop $CLASS_NAME
else
    # Программа не запущена, запускаем процесс
    $APP_COMMAND &
fi

Альтернативные решения

Если вы ищете менее сложные пути, вы можете рассмотреть использования AutoKey. Этот инструмент также поддерживает горячие клавиши и может выполнять аналогичные функции управления окнами.

Пример скрипта AutoKey для Firefox:

output = system.exec_command("wmctrl -l", getOutput=True)
if "Firefox" in output:
    window.activate("Firefox", switchDesktop=True)
else:
    subprocess.Popen(["firefox"])

Заключение

Таким образом, для управления окнами в KDE под Wayland можно использовать KWin скрипты или комбинировать решения с помощью инструмента AutoKey. Каждый из этих методов позволит вам эффективно работать с окнами, активируя или открывая необходимые приложения по горячим клавишам. Используя предложенные сценарии, вы сможете адаптировать их под свои нужды и улучшить поток работы в своем окружении KDE.

Оцените материал
Добавить комментарий

Капча загружается...