in reply to How to detect X?

As has been said many times already - use $ENV{DISPLAY}. If it is set, but there is no actual display at the place pointed to by this environment variable, then the user is set up incorrectly. Lots of applications will fail, not just yours. If it is not set, but there is an actual X server available, it's probably because the user wants to use the text mode version. So don't go looking for it.

I've seen dual-mode applications before. HP's "sam" comes to mind. Don't worry about it - yours won't be the first to "fail" in this way. Think of it this way: by having DISPLAY set, the user is saying, "I want graphical applications to appear in this location I am specifying." And if that fails, who are you to go display it elsewhere? By having DISPLAY not set, the user is saying, "I don't want any graphical application." Who are you to go and create a graphical display somewhere? This is even worse - since you may create a graphical display as user Z, on user Y's display. Talk about a security hole! (Nevermind the security hole that let you put up the application in the first place - but that's user Y's problem, not user Z's.)

Using DISPLAY is just the convention with X. Trying to outsmart convention will merely annoy users who are aware of the convention, and are using it. For example, I routinely run applications as "DISPLAY= my_application arg1 arg2". This is because I prefer the text mode of these applications. Or I run "DISPLAY=host:2 my_application arg1 arg2" if I want the application to appear somewhere else (say a VNC session). Don't outsmart me - I'm the human, you're just the program running on the computer. I told you to do something, don't tell me I was wrong and do something else.

Just my perspective on it :-)

Update: See italicised text in first paragraph - added for clarification.

Replies are listed 'Best First'.
Re^2: How to detect X?
by Anonymous Monk on Feb 21, 2005 at 17:02 UTC
    Lots of applications will fail,
    Really? For years, I would set $ENV{DISPLAY} in my profile (so if I would telnet/rsh/rlogin to another box, things would display at my screen - and if I started X somewhere else, DISPLAY would be reset). Yet, I would never had an application fail because of that.

    See, if you don't have X running, X applications will fail. Not because $ENV{DISPLAY} is set, but because X isn't running. Non X-application don't give a shit about $ENV{DISPLAY}. The only thing that could "fail" is an X-application displaying on the wrong screen - but that would only happen if the environment had not setup $ENV{DISPLAY} - and then it would use a default variable instead of being undefined. Ho hum.

    Using DISPLAY is just the convention with X.
    Indeed. The fallacy in your reasoning is that there's also a convention about DISPLAY (namely, it being unset) in a non-X environment. Unfortunally, that isn't true.

      I've clarified the part where you seem to misunderstand my statement.

      Restated, it is that I make no assumptions about where the X server is.

      As for non-X environments: if you're in a non-X environment, and do not want to use an X server, then you should not be running X-based programs. HP's "sam" comes to mind again - if I want to run "sam" without the GUI, I have to unset DISPLAY. Maybe HP isn't the epitome of user-friendly unix-based software. Maybe it is. I don't know. But there is precedent for the OP's request, and it is to follow this convention that you don't seem to follow. Just because one person doesn't follow a convention doesn't mean the convention doesn't exist. Sorta like the leading underscores on "private" functions in perl modules...

      Update: Noticing that you point out that "A implies B" does not mean "B implies A". However, what you seem to misunderstand is that "A represents B". The DISPLAY variable represents the X-based display. And thus, if you set it and it's set incorrectly, then you have an incorrectly set display, and the program cannot figure out whether this was intentional or not, and would properly, IMO, refuse to run. No point in bringing up an ugly TUI if the user's environment says "I want a GUI".

        and the program cannot figure out whether this was intentional or not, and would properly, IMO, refuse to run
        But that's what this entire problem is about. How to detect whether X is running or not. The existance of a DISPLAY variable does not mean X is up and running. Just like the existence of PERL5OPT does not mean we're currently being executed by a Perl program. DISPLAY makes sense for X applications. PERL5OPT makes sense for Perl applications. But that's about it. X applications will not run correctly if DISPLAY isn't set up - you are right about that. But that doesn't mean that non X-applications (and the OP's application might present itself as a non-X application) will, or should, refuse to run if a DISPLAY variable is set. The DISPLAY variable does not imply the user saying "I want a GUI". All it says "if I'm going to launch an X-application, that's where I want it to display itself". It's not that firefox downgrades itself to a text-mode browser if it finds out DISPLAY isn't set.
      The fallacy in your reasoning is that there's also a convention about DISPLAY (namely, it being unset) in a non-X environment.
      Depends on what you mean by "non-X environment". Theoretically, any platform could define its own standards/conventions for the use of the DISPLAY variable; X doesn't "own" it. But I don't know of any. Do you? If you're talking about some home-brewed application that uses DISPLAY for its own purposes — well, the author (and users) of such a thing are SOL for potentially conflicting with X. And this is one of the reasons why Global Variables Are Evil. :-)
        My point isn't that other applications would set or use DISPLAY. It just means that DISPLAY could be set (from someone's profile) even if X isn't running.

        Just like that PERL5LIB is set if I run a Python program. Nothing but Perl is using PERL5LIB as far as I know, but that doesn't imply that if PERL5LIB is set, I'm running perl.

Re^2: How to detect X?
by blazar (Canon) on Feb 22, 2005 at 09:44 UTC
    As has been said many times already - use $ENV{DISPLAY}. If it is set, but there is no actual display at the place pointed to by this environment variable, then the user is set up incorrectly. Lots of applications will fail, not just yours. If it is not set, but there is an actual X server available, it's probably because the user wants to use the text mode version. So don't go looking for it.
    Thank you for your insightful and informed cmts. I will certainly follow your advice. However what I'm bothered most is having the GUI version fail because there's not actually an X server running even if DISPLAY is set as if there were. In that case still checking for success with an eval() (after checking DISPLAY, that is) would be lightweight enough and seems to be appropriate. Do you see any possible negative drawback with this approach?

      It somewhat depends on your interface. If it's easy to escape from the text version of your program, then it may be ok. I would suggest not trying to buck convention too much, so in the case of a fall-back, pop up a message box something like this:

      +----------------------------------------+ | DISPLAY set incorrectly. Falling back | | to a text interface. | | | | [ OK ] [ CANCEL ] | +----------------------------------------+
      If you provide on-line help, it should describe the use of the DISPLAY variable to bypass this warning (that is, to set it to a valid X server which you're authenticate to use, or to unset it if there is no such valid X server).

      The reason for this is that if I really meant to use the X version of your program, I want a quick and easy way out, so that I can properly set DISPLAY, and go back in. If you default to the "OK" button above, the user which has DISPLAY set incorrectly but is ok with the text interface just hits enter, while the one who wants to reset DISPLAY merely has to hit escape. It's a trivial compromise between all positions, IMO.

      Another nice-to-have option is a commandline option, say "-tui", which bypasses the DISPLAY check (and the above warning) and simply goes straight into the TUI, regardless of the DISPLAY setting. In other words, this is the user setting DISPLAY for general X use, but telling your program specifically that she wants you to ignore DISPLAY and go directly into an text-based interface.

      Along the same lines is a "-gui" option. It means, use DISPLAY, and don't fall back. If DISPLAY doesn't work, just exit with an error.

      For completeness, an "-auto-ui" option which does what you want the whole program to do. It's the default. :-)