Вопрос или проблема
Большая часть моего рабочего процесса основана на использовании ярлыков. В настоящее время я использую xbindkeys и wmctrl для запуска или активации приложения. Например: Super+F открывает firefox или запускает его, если он не запущен.
Autokey хорошо работает с KDE, и я также мог бы использовать родной менеджер пользовательских ярлыков KDE, чтобы заменить xbindkeys
, но я не могу найти (и я много гуглил) способ определить, запущено ли окно/приложение, и если нет, активировать его.
Я, вероятно, могу использовать ps
или подобную команду, чтобы узнать, запущено ли приложение, и если нет, запустить его, но это приводит к конечной проблеме: как программно активировать (или установить фокус) существующее запущенное окно/приложение?
Похоже, есть какое-то решение с gdbus
для GNOME, но, конечно, это не сработает в KDE.
У кого-нибудь есть идея или подсказка, что я могу сделать?
После долгих поисков я нашел решение, которое будет работать только для KDE: использование скрипта kwin.
Скрипт следующий:
- используйте
pgrep
, чтобы узнать, запущена ли программа (полезная командаgrep
) - если запущена:
- установите скрипт kwin, который будет явно “активировать” окно с переданным className или заголовком
- запустите скрипт
- остановите скрипт
- удалите скрипт
- если не запущена: выполните команду для ее запуска.
Например, если я хочу сфокусироваться или запустить Firefox, я сделаю это с помощью моего скрипта:
ww -f firefox -c firefox
-f
: имя класса окна
-c
: команда для запуска, если не запущена
-fa
: альтернативный фильтр, использующий заголовок окна вместо класса
Это скрипт, который я использую сейчас, и он работает отлично.
Вот решение, которое работает на Wayland с GNOME.
Оно имеет следующее поведение,
- Если приложение не запущено, откройте его.
- Если приложение запущено и не имеет фокуса, выведите его на фокус.
- Если приложение уже в фокусе и существует несколько экземпляров одного и того же приложения, переключайтесь между ними.
- Если приложение в фокусе и это единственный экземпляр, ничего не делать.
#!/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 вам придется искать альтернативные решения.
Проблема и контекст
Текущая задача заключается в том, чтобы управлять окнами приложений, используя горячие клавиши. Вы хотите решить следующие проблемы:
- Проверить, запущено ли приложение (например, Firefox).
- Если приложение запущено, активировать его.
- Если приложение не запущено, открыть его.
Можно использовать такие команды, как pgrep
для определения, запущено ли приложение, но основная сложность заключается в активации существующих окон. Под GNOME существуют решения, основанные на gdbus
, но они не подойдут для KDE.
Решение через KWin Скрипты
Существует эффективный способ решить данную задачу, используя KWin скрипты. Эта методика хорошо удовлетворяет требованиям управления окнами в среде KDE. Вот общий подход:
- Использование
pgrep
: Для проверки, запущено ли приложение. - Создание скрипта KWin: Скрипт KWin должен уметь активировать окно по имени класса или заголовку.
- Запуск и остановка скрипта: Запускайте скрипт для фокусировки активного окна и останавливайте его после выполнения.
Пример скрипта
Пример простого скрипта для 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.