4

So I've done some Google searching and this is something that has very little knowledge out there. What would be an effective and foolproof way of detecting whether X11 or Wayland is in use, preferrably at compile-time and with CMake? I need to apply this to a C++ project of mine.

Phobos D'thorga
  • 439
  • 5
  • 17
  • You mean as active display server, not only if the libraries are available? Why not at run-time? (Which will be *much* easier and will be correct all the time.) – Some programmer dude Jul 17 '17 at 02:42
  • Thank you for your response, @Someprogrammerdude, but I need to detect the screen resolution of the user and to do this, I must use code from either X11 or Wayland, hence the need at compile-time. Unless there's a multi-platform way to solving this problem of mine? I did try Qt (since I'm using that already) but it proved unreliable. – Phobos D'thorga Jul 17 '17 at 03:15
  • What if the user changes the resolution *after* the program is built? For example by putting in a new graphics card or connecting a bigger (or smaller) monitor? Do the user of your program need to rebuild your program then? – Some programmer dude Jul 17 '17 at 04:15
  • As an addendum to my previous comment, responsive design, programming and layout is not only important for web-pages. I think it should be a major goal for *all* GUI-oriented programming. – Some programmer dude Jul 17 '17 at 04:24
  • @Someprogrammerdude the code that detects the resolution itself is dynamic, but it must be either Wayland or X11 based library-code to do this. Hence the need to choose between which set of libraries to rely upon at compile time :) – Phobos D'thorga Jul 17 '17 at 04:35
  • Have a small test-program that tries to connect to the Wayland server, and if it fails then have another small test program that tries to connect to the X11 server? – Some programmer dude Jul 17 '17 at 05:34
  • Really at compile-time? That would mean that CMake is a poor choice for your problem. Usually CMake defines variables during configure and does not change the variables for each compiler call. – usr1234567 Jul 17 '17 at 20:50
  • "whether X11 or Wayland is in use" This makes no sense. I can use both at the same time, and more than one of each. – n. m. could be an AI Jul 18 '17 at 14:37
  • This should be configuration option of cmake project. This should not be detected. Note that you probably what to build project on machine which do not have GUI (jerkins build machine with docker swarm for example). – Marek R Aug 12 '22 at 22:33

2 Answers2

2

The accepted answer is very inaccurate and dangerous. It just runs loginctl to dump a large list of user-sessions and greps every line with a username or other string that matches the current user's name, which can lead to false positives and multiple matching lines. Calling whoami is also wasteful. So it's harmful, and inaccurate.

Here's a much better way to get the user's session details, by querying your exact username's details and grabbing their 1st session scope's id.

This is a Bash/ZSH-compatible one-liner solution:

if [ "$(loginctl show-session $(loginctl user-status $USER | grep -E -m 1 'session-[0-9]+\.scope' | sed -E 's/^.*?session-([0-9]+)\.scope.*$/\1/') -p Type | grep -ic "wayland")" -ge 1 ]; then
    echo "Wayland!"
else
    echo "X11"
fi

I really wish that loginctl had a "list all sessions just for a specific user", but it doesn't, so we have to resort to these tricks. At least my trick is a LOT more robust and should always work!

Mitch McMabers
  • 3,634
  • 28
  • 27
0

I assume you want to evaluate the display server during compile time, when calling CMake, instead of for every compilation. That's how CMake works and hot it should be used. One downside is, that you have to re-run CMake for every changed display server.

There is currently no default way to detect the running display server. Similar, there is no default code snippet to evaluate the display server by CMake. Just pick one way of detecting the display server that manually works for you or your environment respectively.

Call this code from CMake and store the result in a variable and use it for your C++ code.

For example loginctl show-session $(loginctl | grep $(whoami) | awk '{print $1}') -p Type works for me. The resulting CMake check is

execute_process(
    "loginctl show-session $(loginctl | grep $(whoami) | awk '{print $1}') -p Type"
    OUTPUT_VARIABLE result_display_server)
if ("${resulting_display_server}" EQUALS "Type=x11")
   set(display_server_x11 TRUE)
else()
   set(display_server_x11 FALSE)
endif()

Probably you have to fiddle around with the condition and check for Type=wayland or similar to get it properly working in your environment.

You can use display_server_x11 and write it into a config.h file to use it within C++ code.

usr1234567
  • 21,601
  • 16
  • 108
  • 128
  • Thank you so much for your addition, I'm going to use this solution of yours most surely :) I did word my question pretty badly though. I should've asked if this was possible to do preferrably at compile time or at the very least, with CMake when the configuration files are generated, like you suggested. – Phobos D'thorga Jul 18 '17 at 00:36
  • 1
    **Nice idea... but your technique for getting the user's session ID is terrible.** It just runs `loginctl` to dump a large list of user-sessions and greps every line with a username or other string that matches the current user's name. Calling `whoami` is also wasteful. So it's harmful, and inaccurate. Here's a much better way to get the user's session details, by querying your exact username's details and grabbing their 1st session scope's id: `loginctl show-session $(loginctl user-status $USER | grep -E -m 1 'session-[0-9]+\.scope' | sed -E 's/^.*?session-([0-9]+)\.scope.*$/\1/') -p Type` – Mitch McMabers Aug 12 '22 at 22:11
  • @MitchMcMabers Thanks for the hint. If you want, you can edit my answer and improve it. I still show how the CMake part is done. – usr1234567 Aug 28 '22 at 21:05