16

I would like to know how I can obtain a list of all Xorg displays on my system, along with a list of screens associated with each display. I spent some time looking through the Xlib documentation, but was not able to find a function that does what I want. Please assume that I have no other dependencies other than a POSIX-complaint OS and X (e.g., no GTK). If what I ask is not possible assuming these minimal dependencies, then a solution using other libraries is fine.

Thank you very much for your help!

void-pointer
  • 14,247
  • 11
  • 43
  • 61

2 Answers2

25

The only way I know of to get a list of displays is to check the /tmp/.X11-unix directory.

Once you do that, you can use Xlib to query each display for more information.

Per example:

#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;
}

Running the above gives me this output with my current displays/screens:

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

Never found a better way of listing X displays other than that. I'd very much like to know if any better alternative exists.

netcoder
  • 66,435
  • 19
  • 125
  • 142
  • It looks like the display sockets can be in `/usr/spool/sockets/X11/` for hpux and `/var/tsol/doors/.X11-unix/` for some configurations of solaris. Though, I think these are rare enough that you could just rely on `/tmp/.X11-unix/`. – Azmisov Feb 19 '15 at 20:33
  • With libx11-dev run `gcc -o screen screen.c -L/usr/X11/lib -lX11`. – schemacs May 31 '21 at 05:11
  • Silly question, but... how were you able to have the second display server `:1`? I'd like to mock this, but all environments I've ever seen only have the primary display server `:0` – MestreLion Jan 23 '23 at 18:00
  • @MestreLion I *think* the :0 or :1 is the display, which contains the screens. So if you wanted to have an additional display one way of doing that would be to switch to a different tty and starting an addition desktop session – gnarlyninja Feb 21 '23 at 06:21
  • 1
    @MestreLion You can have more display servers by running multiple Xorg sessions. Xorg is just a program running on your computer, so you can run more. Multiseat Xorg is such an example (https://www.x.org/wiki/Development/Documentation/Multiseat/). – nobody Jun 22 '23 at 08:46
5

Like netcoder wrote, the problem has two distinct parts:

  1. Connection to the X server

    The process establishes a connection to an X server using XOpenDisplay(). The connection is torn down using XCloseDisplay(). netcoders code in this thread is a good example of how to do it correctly.

    As netcoder mentioned, the problem is that there is no reliable way find out which X servers a process can connect to. His code checks the typical location where the X sockets are, /tmp/.X11-unix/. That approach does not work at all if the user is remotely connected, for example via SSH (with X forwarding enabled). In that case there is really only the DISPLAY environment variable (and perhaps some trickery wrt. ~/.Xauthority files).

    Unfortunately, I do not know of any better method either. I personally prefer to use a per-user configuration file -- say ~/.application/displays --, where the user can list the server names the application should try to connect in the same format as the DISPLAY environment variable, in addition to the default one. It is not automatic (netcoder's code is), but this approach suits me better.

  2. Finding out about the screens provided by an X server

    XScreenCount() will return the number of screens provided by the X server the process is currently connected to. If you only need the screen dimensions, follow netcoders example. For more detailed information, use XScreenOfDisplay(Display,index) to obtain the Screen pointers; 0 <= index < XScreenCount(Display).

    In C code, the macros ScreenCount() and ScreenOfDisplay() are usually a bit more efficient than the actual function calls.

Nominal Animal
  • 38,216
  • 5
  • 59
  • 86