Понял! Если блокировка через Inhibit не подходит для вашего случая, то действительно стоит расширить подписки на сигналы D-Bus, чтобы охватить все возможные сценарии выключения или перезагрузки. В вашем случае, вероятно, не все сигналы перехватываются, поэтому система завершает работу без уведомления вашего приложения.
Какие сигналы нужно отслеживать?

В org.freedesktop.login1.Manager есть несколько сигналов, которые могут быть полезны:

    PrepareForShutdown — сигнал, который отправляется перед началом выключения или перезагрузки.

    PrepareForSleep — сигнал, который отправляется перед переходом в спящий режим.

    Shutdown — сигнал, который отправляется при выключении системы.

    Reboot — сигнал, который отправляется при перезагрузке системы.

Как добавить подписки на дополнительные сигналы?

Вам нужно модифицировать ваш метод InitializeSignalHandler, чтобы подписаться на все необходимые сигналы. Вот пример, как это можно сделать:
pascal
Copy

procedure TMainFo.InitializeSignalHandler;
var
  err: DBusError;
  rule: PChar;
begin
  WriteLn('Инициализация подписки на сигналы D-Bus...');
  dbus_error_init(@err);

  // Подписка на сигнал PrepareForShutdown
  rule := 'type=''signal'',interface=''org.freedesktop.login1.Manager'',member=''PrepareForShutdown''';
  dbus_bus_add_match(fConn, rule, @err);
  if dbus_error_is_set(@err) <> 0 then
  begin
    WriteLn('Ошибка подписки на PrepareForShutdown: ', err.message);
    dbus_error_free(@err);
  end;

  // Подписка на сигнал PrepareForSleep
  rule := 'type=''signal'',interface=''org.freedesktop.login1.Manager'',member=''PrepareForSleep''';
  dbus_bus_add_match(fConn, rule, @err);
  if dbus_error_is_set(@err) <> 0 then
  begin
    WriteLn('Ошибка подписки на PrepareForSleep: ', err.message);
    dbus_error_free(@err);
  end;

  // Подписка на сигнал Shutdown
  rule := 'type=''signal'',interface=''org.freedesktop.login1.Manager'',member=''Shutdown''';
  dbus_bus_add_match(fConn, rule, @err);
  if dbus_error_is_set(@err) <> 0 then
  begin
    WriteLn('Ошибка подписки на Shutdown: ', err.message);
    dbus_error_free(@err);
  end;

  // Подписка на сигнал Reboot
  rule := 'type=''signal'',interface=''org.freedesktop.login1.Manager'',member=''Reboot''';
  dbus_bus_add_match(fConn, rule, @err);
  if dbus_error_is_set(@err) <> 0 then
  begin
    WriteLn('Ошибка подписки на Reboot: ', err.message);
    dbus_error_free(@err);
  end;

  // Устанавливаем фильтр для обработки сигналов
  dbus_connection_add_filter(fConn, @DBusSignalHandler, Self, nil);
  WriteLn('Подписка на сигналы выполнена.');
end;

Модификация обработчика сигналов

Теперь, когда вы подписались на несколько сигналов, нужно модифицировать ваш обработчик DBusSignalHandler, чтобы он корректно обрабатывал каждый из них:
pascal
Copy

function DBusSignalHandler(conn: PDBusConnection; msg: PDBusMessage; user_data: Pointer): DBusHandlerResult; cdecl;
begin
  if Assigned(user_data) then
  begin
    // Проверяем тип сигнала и вызываем соответствующий метод
    if dbus_message_is_signal(msg, 'org.freedesktop.login1.Manager', 'PrepareForShutdown') then
    begin
      WriteLn('Получен сигнал PrepareForShutdown.');
      TMainFo(user_data).HandlePrepareForShutdown(msg);
    end
    else if dbus_message_is_signal(msg, 'org.freedesktop.login1.Manager', 'PrepareForSleep') then
    begin
      WriteLn('Получен сигнал PrepareForSleep.');
      TMainFo(user_data).HandlePrepareForSleep(msg);
    end
    else if dbus_message_is_signal(msg, 'org.freedesktop.login1.Manager', 'Shutdown') then
    begin
      WriteLn('Получен сигнал Shutdown.');
      TMainFo(user_data).HandleShutdown(msg);
    end
    else if dbus_message_is_signal(msg, 'org.freedesktop.login1.Manager', 'Reboot') then
    begin
      WriteLn('Получен сигнал Reboot.');
      TMainFo(user_data).HandleReboot(msg);
    end;
  end;
  Result := DBUS_HANDLER_RESULT_HANDLED;
end;

Добавление методов для обработки сигналов

Теперь добавьте методы для обработки каждого сигнала в ваш класс TMainFo:
pascal
Copy

procedure TMainFo.HandlePrepareForShutdown(msg: PDBusMessage);
begin
  WriteLn('Обработка сигнала PrepareForShutdown.');
  AppClose; // Сохраняем данные
  shutdownRequested := True; // Устанавливаем флаг завершения
end;

procedure TMainFo.HandlePrepareForSleep(msg: PDBusMessage);
begin
  WriteLn('Обработка сигнала PrepareForSleep.');
  // Дополнительные действия, если нужно
end;

procedure TMainFo.HandleShutdown(msg: PDBusMessage);
begin
  WriteLn('Обработка сигнала Shutdown.');
  AppClose; // Сохраняем данные
  shutdownRequested := True; // Устанавливаем флаг завершения
end;

procedure TMainFo.HandleReboot(msg: PDBusMessage);
begin
  WriteLn('Обработка сигнала Reboot.');
  AppClose; // Сохраняем данные
  shutdownRequested := True; // Устанавливаем флаг завершения
end;

Итоговый код

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

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