Скрипт переноса окна браузера на второй монитор при запуске другого приложения

Собственно, мучал chatgpt на скрипт для переноса окна firefox на второй физический монитор при запуске IDE и возвращении его на первый монитор при закрытии IDE. Автоматизация не удалась. После 4х часов обоюдного мозго.. кхм, 2ух "Слишком частые запросы, попробуйте через час" - родилось, прости Хоспаде, вот это:

# Задаем имя класса, который мы будем мониторить
target_class="java"

# Задаем имя класса окна Firefox, которое мы будем мониторить
firefox_class="^Firefox$|^firefox$"

# Функция для переноса окна на второй монитор и максимизирования окна
function move_window() {
  wmctrl -i -r "$1" -e 0,"${monitors[1]}",-1,-1,-1
  wmctrl -i -r "$1" -b add,maximized_vert,maximized_horz
}

# Функция для возвращения окна на первый монитор
function return_window() {
  wmctrl -i -r "$1" -b remove,maximized_vert,maximized_horz
  wmctrl -i -r "$1" -e 0,"${monitors[0]}",-1,-1,-1
}

# Функция для мониторинга окна
function monitor_window() {
  window_id=$(xwininfo -root -tree | grep "$target_class" | tail -1 | awk '{print $1}')
  if [ -n "$window_id" ]; then
    # Проверяем, что Firefox еще не запущен и класс окна Firefox уже добавлен в список мониторимых окон
    if ! echo "${monitored_windows[*]}" | grep -Eiq "$firefox_class" && xwininfo -root -tree | grep -Eiq "$firefox_class" >/dev/null; then
      # Запоминаем ID окна Firefox и добавляем его класс в список мониторимых окон
      firefox_id=$(xwininfo -root -tree | grep "$firefox_class" | tail -1 | awk '{print $1}')
      monitored_windows+=("$firefox_class")
      # Переносим окно Firefox на второй монитор и максимизируем его
      move_window "$firefox_id"
    fi
  else
    # Если окно jetbrains-idea закрыто, возвращаем окно Firefox на первый монитор
    for id in $(echo "${monitored_windows[*]}" | tr ' ' '\n'); do
      return_window "$(xwininfo -root -tree | grep "$id" | tail -1 | awk '{print $1}')"
    done
    # Очищаем список мониторимых окон
    monitored_windows=()
  fi
}

# Функция для перехвата событий запуска и закрытия процесса
function monitor_window_class() {
  window_class=$1
  start_actions=$2
  end_actions=$3

  while true; do
    if xwininfo -root -tree | grep "$window_class" >/dev/null; then
      if [ -z "$start_actions" ]; then
        echo "Window $window_class opened."
      else
        echo "Running start actions..."
        eval "$start_actions"
      fi
      wait_for_window_close "$window_class"
      if [ -z "$end_actions" ]; then
        echo "Window $window_class closed."
      else
        echo "Running end actions..."
        eval "$end_actions"
      fi
    fi
    sleep 1
  done
}

#Функция для ожидания завершения процесса
function wait_for_window_close() {
window_class=$1
while xwininfo -root -tree | grep "$window_class" >/dev/null; do
sleep 1
done
}

Собственно: нихрена не работает. Точнее bash +x script.sh без ошибок отрабатывает, но окно firefox как было в мониторе 1 - так и осталось. И ощущение, что скрипт выполняется 1 раз, а не висит в бесконечном цикле. Нужен бородатый дядя в свитере, который понимает shell scripting и пон в чём тут проблема.
Вариант 2: меня устроит любое не жирное типа KDE решение, которое будет делать то же самое(автоматизировать мои хотелки): WE, DM или просто программулина.
koshon
Собственно: нихрена не работает. Точнее bash +x script.sh без ошибок отрабатывает
Это не скрипт. Это библиотека. Список функций без их запуска.
koshon
скрипт выполняется 1 раз, а не висит в бесконечном цикле.
Потому что там никакого бесконечного цикла и нет.
Lupus pilum mutat, non mentem.
koshon
. После 4х часов обоюдного мозго.. кхм
За это бесполезно потраченное время уже бы весь bash выучил)))
Lupus pilum mutat, non mentem.
jim945
koshon
. После 4х часов обоюдного мозго.. кхм
За это бесполезно потраченное время уже бы весь bash выучил)))
Не думаю бы, что за 4 часа освоил)). А ещё прочёл бы доку wmi и прочих утилит.
А что значит библа? Почему только функции без запуска?
Ни у кого что-ли нет рабочего решения? неужели никто так не хотел "извратиться"?))
koshon
А что значит библа? Почему только функции без запуска?
Это у chatgpt спроси. Он же писал)))
Lupus pilum mutat, non mentem.
jim945
Потому что там никакого бесконечного цикла и нет.
while true - тогда зачем там?
А вы вежливо спрашивали?

Умный программ Sage, миленький. Напиши скрипт на bash для переноса окна firefox между экранами при манипуляции с какой-нибудь программой.

Ниже приведен простой скрипт на bash, который переносит окно Firefox между экранами, когда вы переключаетесь между другими окнами. Для работы этого скрипта необходимо установить утилиту xdotool.

#!/bin/bash

# Устанавливаем окно Firefox по умолчанию
WINDOW=$(xdotool search –class firefox | head -n 1)
xdotool windowactivate $WINDOW

# Бесконечный цикл для отслеживания событий переключения окон
while true
do
# Получаем текущее активное окно
ACTIVE_WINDOW=$(xdotool getactivewindow)

# Если это не окно Firefox, переносим его на другой экран
if [[ $(xdotool getwindowname $ACTIVE_WINDOW) != *"Mozilla Firefox"* ]]; then
# Получаем текущий экран
CURRENT_SCREEN=$(xdotool getdisplaygeometry | awk '{print $1}')

# Получаем координаты центра окна
WINDOW_X=$(xdotool getwindowgeometry $ACTIVE_WINDOW | awk '/Geometry/ {print $2}' | awk -Fx '{print $1}')
WINDOW_Y=$(xdotool getwindowgeometry $ACTIVE_WINDOW | awk '/Geometry/ {print $2}' | awk -Fx '{print $2}')
WINDOW_WIDTH=$(xdotool getwindowgeometry $ACTIVE_WINDOW | awk '/Geometry/ {print $4}' | awk -Fx '{print $1}')
WINDOW_HEIGHT=$(xdotool getwindowgeometry $ACTIVE_WINDOW | awk '/Geometry/ {print $4}' | awk -Fx '{print $2}')
CENTER_X=$((WINDOW_X + WINDOW_WIDTH / 2))

# Определяем, на каком экране находится центр окна
if [[ $CENTER_X -lt $CURRENT_SCREEN ]]; then
# Переносим окно на следующий экран
xdotool windowmove $ACTIVE_WINDOW $((CURRENT_SCREEN + 1)) $WINDOW_Y
else
# Переносим окно на предыдущий экран
xdotool windowmove $ACTIVE_WINDOW $((CURRENT_SCREEN - 1)) $WINDOW_Y
fi
fi

# Ожидаем 1 секунду и повторяем цикл
sleep 1
done

Вы можете сохранить этот скрипт в файл и запустить его в фоновом режиме при запуске вашей системы. Например, вы можете добавить его в автозапуск в системных настройках или в файл ~/.xinitrc (если вы используете X11).
Ошибки в тексте-неповторимый стиль автора©
grinch
while true - тогда зачем там?
Какая разница? Всё равно этот код не запускается же.
Lupus pilum mutat, non mentem.
Добил я всё равно этот скрипт. Ещё нужен wmctrl, но это такая мелочь. Не хотел с xdotool, т.к. может пересекаться когда ты просто что-то делаешь с клавы.
Вначале первые три переменные можно менять под любые окна и с разным временем проверки запущенного окна, на которое ориентируемся
firefox_class_name="firefox"
IDE_class_name="jetbrains"
sleep_time=60
1. Добавил его в меню опенбокса, когда нужно будет запустить IDE'шку - тогда скрипт запускается и висит пока последняя запущена, а потом идет нафиг.
2. Можно его повесить при загрузке системы, но мне не нравится, так как он будет бесконечно висеть и потреблять какие-никакие ресурсы бесполезно. Тогда нужно функцию main подправить под while.
Был бы благодарен от опытных шеллостроителей объективных замечаний по первому скрипту. Что я подразумеваю под объективными: "здесь можно сделать так {код} т.к. это сокращает кол-во вызовов того-то", т.е. получается экономия системных ресурсов. Ну или может просто становится проще/удобочитаемее. Уверен, что никто нахрен (разве что от непреодолимой скуки) не полезет разбираться в чужом коде, но мало ли). Не факт, что я их сразу(или вообще когда-то) же внесу в правки, но точно учту как замечания/опыт.
Оставляю здесь и ниже на гитхабе

#!/bin/bash
set -Eeuox pipefail

firefox_class_name="firefox"
IDE_class_name="jetbrains"
sleep_time=60

declare primary_monitor_xsize_px

function set_primary_monitor_xsize() {
  local regex=".* primary ([0-9]+)x[0-9]+\+[0-9]+\+[0-9]+.*"
  local output=$(xrandr --current)
  if [[ $output =~ $regex ]]; then
    primary_monitor_xsize_px="${BASH_REMATCH[1]}"
  fi
}

function isWindowExist() {
  local class_name="$1"
  local found=$(wmctrl -lx | awk -v class="${class_name}" '
    BEGIN{found=0}
    $3 ~ class {
      found=1
    }
    END {
      print found
    }
  '
  )
  echo "${found}"
}

function isWindowOnPrimaryMonitor() {
  local class_name="$1"
  local geometry="${primary_monitor_xsize_px}"
  local found=$(wmctrl -lxG | awk -v class="${class_name}" -v geometry="${geometry}" '
    BEGIN{found=0}
    $7 ~ class && $3 < geometry {
      found=1
    }
    END {
      print found
    }
  '
  )
  echo "${found}"
}

function move_window() {
  local moving_window_class="$1"
  wmctrl -x -r "${moving_window_class}" -e 0,"${primary_monitor_xsize_px}",0,-1,-1
}

function return_window() {
  local returning_window_class="$1"
  wmctrl -x -r "${returning_window_class}" -e 0,0,0,-1,-1
}

function main() {
  set_primary_monitor_xsize
  if [[ "$(isWindowOnPrimaryMonitor "${firefox_class_name}")" == "1" ]]; then
    move_window "${firefox_class_name}"
  fi
  while [[ "$(isWindowExist "${IDE_class_name}")" == "1" ]]; do
    sleep ${sleep_time}
  done
  return_window "${firefox_class_name}"
}

function cleanup() {
  trap - SIGINT SIGTERM ERR EXIT
}

main
cleanup


https://github.com/EvVlF/moveFirefox/blob/main/moveFirefox.sh
 
Зарегистрироваться или войдите чтобы оставить сообщение.