0

I'm working on a small server program that takes data received from the network and performs various actions. One of these actions is to open a connection with the X server running on the system and simulate key presses. This is fine when my server is started from a terminal inside X, but I want my program to start as a system service with the system boots and then communicate with X when requested by the clients.

The basic problem I have is that a call to XOpenDisplay(NULL) in a process that was not started from inside X fails. As far as I understand, I can't get open an X display from outside of X so the best workaround I can think of is to write a separate program that is started when a user logs in to X that waits for a signal or message from the server and then performs the requested action. It is perfectly okay to assume that the server can send an error back to the client if this helper program isn't running or has failed for some reason.

So question: Is what I described above the best (albeit messy) solution, or is there a better way? Is there, in fact, a way to open an X display from outside of X? Thanks!

shanet
  • 7,246
  • 3
  • 34
  • 46
  • @jweyrich Gah, when I was playing around with the DISPLAY envvar, I was assigning it, then running my program, but forgetting `export` and assumed something else was wrong. That does work, but it still means I to assume the display is actually `:0:`. – shanet Oct 19 '12 at 21:51

2 Answers2

3

Being "inside of X" is just a matter of having the DISPLAY environment variable set. You can do this from anywhere.

If the X server in question is being run for a different user, you may need to also deal with authentication tokens such as Xauthority tickets.

However -- for the use case you describe, I'd strongly recommend running your own X server process, independent of the system's actual display hardware. This could be Xvnc if you want to connect to inspect interactively, or a simple headless implementation, or Xvfb if you need no display buffer at all. This approach will also prevent your software from needing to restart when users log in and out, which would otherwise be the case.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • You're right about the `DISPLAY` envvar, but I don't want to hardcode the display as, say, `:0:`. I looked into `Xvfb`, but maybe I should explain a little more. My goal is to simulate media key presses to play/pause a media player that is running in an X process that a user started (so as not to work with only a specific media player). As far as I understand, creating a new X process would be sending these simulated key presses to nothing. – shanet Oct 19 '12 at 21:55
  • 1
    @shanet If you create your own X server, such as `Xvnc`, you can tell it which `DISPLAY` to use. – Charles Duffy Oct 19 '12 at 22:47
  • 1
    @shanet Which media player is this, by the way? The better ones have control socket mechanisms which don't have any dependency or requirement on receiving keypresses; it might be more appropriate to use something better fit-to-purpose. – Charles Duffy Oct 19 '12 at 22:49
  • I'm not very familiar with X so I'm trying to make sense of all this; assuming I used Xvnc, I could just go ahead and use `XOpenDisplay` like I already am? I'm currently using Clementine, but I changed media players somewhat often which is why I'm trying to build a solution that is independent of the player since all I need is simple play/pause/next commands. – shanet Oct 20 '12 at 19:09
  • 1
    @shanet Yes, Xvnc acts as a normal X server from the perspective of the clients; the same calls will work as for any other. – Charles Duffy Oct 21 '12 at 00:54
1

It is possible to connect to an X display from any process running on the machine - you need the DISPLAY variable set to indicate which X session you want to connect to, and may need the correct XAuthority token.

However, this would be considered the "messy" solution for your case, since you'd need to essentially guess the display number and work around the authorization issue. You'd also have to handle the case where the X server hasn't started yet when your daemon starts, or when the X server gets restarted while your daemon is running (the X client library isn't really designed to handle the case of the X server going away and coming back again).

The "clean" solution is actually the one you've suggested as a workaround - a client running within the X session that connects to your daemon over a UNIX domain socket or similar.

caf
  • 233,326
  • 40
  • 323
  • 462
  • That's a good point about not knowing the `DISPLAY` to use. I suppose I could make a config file for my program and default the display to `:0` if not specified otherwise.If I have my program set as a service (in `/etc/init.d`) is it fair to assume that it will be started with sufficient privileges to communicate with any X session? – shanet Oct 19 '12 at 22:06
  • 1
    @shanet: No - it depends on the way X is configured, but typically you need a "magic cookie" value or key which is stored in the `.Xauthority` file in the logged-on user's home directory. – caf Oct 19 '12 at 23:18