Получение списка всех дисплеев Xorg

Я хотел бы знать, как я могу получить список всех дисплеев Xorg в моей системе, а также список экранов, связанных с каждым дисплеем. Я потратил некоторое время на просмотр документации Xlib, но не смог найти функцию, которая делает то, что я хочу. Предположим, что у меня нет других зависимостей, кроме ОС POSIX-жалобы и X (например, без GTK). Если то, что я прошу, невозможно предположить, что эти минимальные зависимости, то решение с использованием других библиотек в порядке.

Большое спасибо за вашу помощь!

Ответ 1

Единственный способ узнать список дисплеев - проверить каталог /tmp/.X11-unix.

Как только вы это сделаете, вы можете использовать Xlib для запроса каждого дисплея для получения дополнительной информации.

В качестве примера:

#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <X11/Xlib.h>

int main(void) {
    DIR* d = opendir("/tmp/.X11-unix");

    if (d != NULL) {
        struct dirent *dr;
        while ((dr = readdir(d)) != NULL) {
            if (dr->d_name[0] != 'X')
                continue;

            char display_name[64] = ":";
            strcat(display_name, dr->d_name + 1);

            Display *disp = XOpenDisplay(display_name);
            if (disp != NULL) {
                int count = XScreenCount(disp);
                printf("Display %s has %d screens\n",
                    display_name, count);

                int i;
                for (i=0; i<count; i++)
                    printf(" %d: %dx%d\n",
                        i, XDisplayWidth(disp, i), XDisplayHeight(disp, i));

                XCloseDisplay(disp);
            }
        }
        closedir(d);
    }

    return 0;
}

Запуск выше дает мне этот вывод с моими текущими экранами/экранами:

Display :0 has 1 screens
 0: 3046x1050
Display :1 has 2 screens
 0: 1366x768
 1: 1680x1050

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

Ответ 2

Как и netcoder, проблема состоит из двух отдельных частей:

  • Подключение к серверу X

    Процесс устанавливает соединение с сервером X с помощью XOpenDisplay(). Соединение сбрасывается с помощью XCloseDisplay(). Код netcoders в этом потоке - хороший пример того, как это сделать правильно.

    Как упоминалось в netcoder, проблема в том, что нет надежного способа узнать, к каким X-серверам может подключиться процесс. Его код проверяет типичное место, где расположены гнезда X, /tmp/.X11-unix/. Этот подход не работает вообще, если пользователь удаленно подключен, например, через SSH (при включенной пересылке X). В этом случае на самом деле существует только переменная среды DISPLAY (и, возможно, некоторые файлы обмана) ~/.Xauthority).

    К сожалению, я не знаю ни одного лучшего метода. Я лично предпочитаю использовать файл конфигурации для каждого пользователя - скажем ~/.application/displays -, где пользователь может отображать имена серверов, которые приложение должно пытаться подключить в том же формате, что и переменная среды DISPLAY, в дополнение к по умолчанию один. Это не автоматический (код netcoder), но этот подход мне подходит лучше.

  • Поиск экранов, предоставляемых сервером X

    XScreenCount() вернет количество экранов, предоставленных сервером X, к которому в данный момент подключен процесс. Если вам нужны только размеры экрана, следуйте примеру netcoders. Для получения более подробной информации используйте XScreenOfDisplay(Display,index) для получения указателей Screen; 0 <= index < XScreenCount(Display).

    В коде C макросы ScreenCount() и ScreenOfDisplay() обычно более эффективны, чем фактические вызовы функций.