unix
Yesterday

Xfce и "автоматический" диалог

Сейчас будет еще одна трешевая история из мира открытого ПО, из серии тех что не рассказывают детям, дамам и сотрудникам ППС.

XFCE

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

Одно время им пользовался даже сам Линус Торвальдс, мотивировав переезд чрезмерным разжирением KDE и уходом в лунатизм Gnome 3.

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

БАГ

Разумеется в Xfce есть баги и недоработки, не такие феерические как например в KDE ("Плазма не падает"), но тоже временами доставляющие и долгоживущие, как раз об одном таком «долгожителе» и пойдет наш рассказ.

Как это выглядит в действии:

ноутбук засыпает, ноутбук просыпается и на экране появляется.. диалог «Display Settings».

Казалось бы мелочь, ну появляется и появляется (причем не на всех ОС и ноутбуках), хер бы с ним и так проблем навалом.

Но во-первых временами появляется несколько копий этого диалога, что уже напрягает их потом каждый раз закрывать, а во-вторых я бл#ть не просто так два десятка лет занимаюсь разработкой, чтобы дать какой-то левой программе творить на моей машине беспредел.

Так что меня это огорчило и я полез за боевым топором компилятором.

Ресерч

Первый же поиск дал понять, что это не шиза проблема есть далеко не только у меня, вот например сообщение с форума Xfce еще из 2021 года:

Вот об этой проблеме пишут на форуме Linux Mint:

Репорт бага из Linux Mint

И на форуме Manjaro Linux:

И даже на форуме FreeBSD:

Так что проблема действительно есть, причем именно в Xfce а не в конкретной ОС или настройках окружения.

Дальнейшие изыскания привели в багтрекер, к вот этому задокументированному багу аж из 2013 (!) года:

Я насчитал аж двадцать (20) «duplicate» багов, закрытых за все время жизни этого репорта, но поскольку с 2013го года сам трекер успел переехать с BugZilla на Gitlab (оригинальный тикет этого бага находится тут) — практически гарантированно что-то успело потеряться.

Несмотря на сильно другое изначальное описание, если посмотреть переписку под тикетом — можно увидеть знакомые рога и копыта очертания бага с открытием диалога:

Вот это сообщение в обсуждении на форуме Xfce навело на возможное место в исходном коде, ответственное за проблему:

Разумеется с 2021го года все успело до неузнаваемости измениться и в актуальной на момент написания статьи версии 4.20 это место выглядит уже вот так:

Суть происходящего

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

Из-за данной логики и происходит отображение диалога «Display Settings», по замыслу авторов — для настройки нового устройства, когда например подключается второй монитор или проектор.

"Благими намерениями", вы правильно поняли.

Обратите внимание на вот такую проверку:

 /* Start the display dialog according to the user preferences */
 if (action == ACTION_ON_NEW_OUTPUT_SHOW_DIALOG)
                {
..

Чуть выше по коду в этом же файле displays-x11.c происходит чтение из настроек:

gint action = xfconf_channel_get_int (channel, NOTIFY_PROP, ACTION_ON_NEW_OUTPUT_DEFAULT);
if (action != ACTION_ON_NEW_OUTPUT_DO_NOTHING || old_outputs->len == 0)
     {
..

Таким образом по идее создателей, если вот тут в поле «When display is connected» выставлено значение «Do nothing»:

Тогда никакого диалога при просыпании появляться не будет.

Но есть нюанс.

Нюанс

У Xfce традиционно не очень хорошо с настройками — она их регулярно теряет и сбрасывает при обновлениях, перезаписывает новыми ох#ительными опциями и вообще всячески ломает.

И этот диалог "Display Settings" появляется снова.

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

Решение

Думаю нетрудно догадаться, что радикальное решение оказалось очень простым:

/* Start the display dialog according to the user preferences */
if (action == ACTION_ON_NEW_OUTPUT_SHOW_DIALOG)
{
 //  const gchar *cmd = helper->outputs->len <= 2 ? "xfce4-display-settings -m" : "xfce4-display-settings";
 //  xfce_spawn_command_line (NULL, cmd, FALSE, FALSE, TRUE, NULL);
 g_print("Ignored 'Display Settings' dialog \n");
}

Да, весь блок (он такой один), отвечающий за запуск диалога «Display Settings» был самым банальным образом закомментирован в файле displays-x11.c.

Wayland

Несмотря на то что я лично не пользуюсь Wayland, Xfce его поддерживает и в файле displays-wayland.c есть полностью аналогичное место, где зашит вызов диалога «Display Settings».

Так что если вы используете Wayland и столкнулись с описываемой проблемой — будете знать где именно искать и что делать.

Однако поправить код в таком проекте это лишь пять процентов дела, все остальное — как это потом собрать и запустить.

Сборка

На самом деле мне сильно повезло, что исправление выше находится в небольшом и автономном приложении xfsettingsd, исходники которого в свою очередь находятся в отдельном репозитории xfce4-settings.

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

Забираем исходники xfce4-settings:

git clone https://gitlab.xfce.org/xfce/xfce4-settings.git

Переключаемся на релизную ветку той версии Xfce, которая у вас уже установлена — не забываем, что мы правим лишь один небольшой сервис, а все остальное остается из пакетной версии:

git checkout origin/xfce-4.20 -b xfce-4.20

Вытаскиваем зависимые репозитории:

git submodule update --init --recursive

Запускаем сборку:

./autogen
./configure
gmake

В каталоге xfsettingsd появится одноименный бинарник, с измененной логикой.

Я не стал заморачиваться с отдельным каталогом в PATH и изучать доступные в Xfce механизмы переопределения путей, вместо этого просто подменив бинарник:

cp ./xfsettingsd/xfsettingsd /usr/local/bin/

И все, больше никаких надоедливых диалогов.

Так выглядит проверочное сообщение, добавленное вместо закомментированных вызовов: