Fallback on xrandr to get linux DPI info.

xdpyinfo is not always available on Linux (even with a DE), whereas
xrandr is (AFAICT) at least dependency of KDE and XFCE.  But xrandr
fails when used remotely, so keep it too.
It does look like a violation of EAFP, which admittedly I did not know was a Python standard -- I haven't really seen it used in many major packages. As a codebase we have not really been following that convention, though.

I haven't thought about this issue much before, so I might be speaking out of ignorance, but here's why I still prefer the conditional solution. It seems like many conditionals could be replaced by `try/except` clauses (probably all of them if you allow `assert` statement use), so we have to draw the line somewhere. In this particular instance, I see the purpose of the new code as: "if xdpyinfo isn't available, use xrandr". My suggestion to use an `if` involving `command -v` instead of the `try/except` was meant in part to more clearly reflects that purpose -- it takes a bit more effort to infer that the `try/except` is meant to act as a conditional for a particular circumstance.

Another hesitation I have with widespread adoption of `try/except` is that it exposes developers to potentially catching otherwise informative exceptions that were not intended to be caught. For example, maybe there is problem with the specific use of `run_subprocess` here, or we will introduce one in a future edit -- if the error happens to manifest as an `OSError` or `AttributeError`, it may go unnoticed because of the `try/except`. Limiting the types of caught exceptions helps, but doesn't eliminate that issue. The negative effects of this here could be partially ameliorated by moving the `x_dpi` and `return` lines to an `else` clause of the `try/except`, but they wouldn't totally go away.

All that being said, if the other `vispy` devs @almarklein @lcampagn @rossant want us to move more toward EAFP, I can live with it :)

`xrandr` may well have to run through a `try/except`, if what you're really trying to detect is that the program exited abnormally. In that case, it is best to keep only the expected offending line(s) should be in the `try`, the other code should go in the `else` clause. Because there are two lines in the `try/except`, though, I can't actually tell from the code what specific errors you're trying to catch -- my guess is that the `OSError` is for the `run_subprocess` and the `AttributeError` is for the `re.search` failure...?