Move new lxsession with built-in settings daemon to trunk.
[lxde/lxsession.git] / lxsession / xevent.c
1 /*
2 * xevent.c
3 *
4 * Copyright 2009 PCMan <pcman.tw@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include "xevent.h"
23
24 #include <string.h>
25
26 #include <X11/X.h>
27 #include <X11/Xproto.h>
28 #include <X11/Xlib.h>
29 #include <X11/Xatom.h>
30
31 #include "lxsession.h"
32 #include "settings-daemon.h"
33
34 Display* dpy = NULL;
35
36 static Atom CMD_ATOM; /* for private client message */
37 static GSource* source = NULL; /* main loop event source for X11 events */
38
39 typedef struct _X11Source
40 {
41 GSource source;
42 GPollFD poll_fd;
43 }X11Source;
44
45 static gboolean x11_event_prepare(GSource *source, gint *timeout);
46 static gboolean x11_event_check(GSource *source);
47 static gboolean x11_event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data);
48
49 static GSourceFuncs event_funcs =
50 {
51 x11_event_prepare,
52 x11_event_check,
53 x11_event_dispatch,
54 NULL
55 };
56
57 void send_internal_command( int cmd )
58 {
59 Window root = DefaultRootWindow(dpy);
60 XEvent ev;
61
62 memset(&ev, 0, sizeof(ev) );
63 ev.xclient.type = ClientMessage;
64 ev.xclient.window = root;
65 ev.xclient.message_type = CMD_ATOM;
66 ev.xclient.format = 8;
67
68 ev.xclient.data.l[0] = cmd;
69
70 XSendEvent(dpy, root, False,
71 SubstructureRedirectMask|SubstructureNotifyMask, &ev);
72 XSync(dpy, False);
73 }
74
75 gboolean xevent_init()
76 {
77 X11Source* xsource;
78 int fd;
79
80 dpy = XOpenDisplay( g_getenv("DISPLAY") );
81 if( ! dpy )
82 return FALSE;
83
84 /* according to the spec, private Atoms should prefix their names with _. */
85 CMD_ATOM = XInternAtom( dpy, "_LXSESSION", False );
86
87 fd = ConnectionNumber(dpy); /* fd of XDisplay connection */
88 if( G_UNLIKELY(fd == -1) )
89 return FALSE;
90
91 /* set up main loop event source for XDisplay */
92 source = g_source_new (&event_funcs, sizeof(X11Source));
93 xsource = (X11Source*)source;
94 xsource->poll_fd.fd = fd;
95 xsource->poll_fd.events = G_IO_IN;
96
97 g_source_add_poll(source, &xsource->poll_fd);
98 g_source_set_can_recurse(source, TRUE);
99 g_source_attach(source, NULL);
100
101 return TRUE;
102 }
103
104 gboolean single_instance_check()
105 {
106 /* NOTE: this is a hack to do single instance */
107 XGrabServer( dpy );
108 if( XGetSelectionOwner( dpy, CMD_ATOM ) )
109 {
110 XUngrabServer( dpy );
111 XCloseDisplay( dpy );
112 return FALSE;
113 }
114 XSetSelectionOwner( dpy, CMD_ATOM, DefaultRootWindow( dpy ), CurrentTime );
115 XUngrabServer( dpy );
116 return TRUE;
117 }
118
119 gboolean x11_event_prepare(GSource *source, gint *timeout)
120 {
121 *timeout = -1;
122 return XPending(dpy) ? TRUE : FALSE;
123 }
124
125 gboolean x11_event_check(GSource *source)
126 {
127 X11Source *xsource = (X11Source*)source;
128 if(xsource->poll_fd.revents & G_IO_IN)
129 return XPending(dpy) ? TRUE : FALSE;
130 return FALSE;
131 }
132
133 gboolean x11_event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
134 {
135 while( XPending(dpy) )
136 {
137 XEvent evt;
138 XNextEvent( dpy, &evt );
139 if( evt.type == ClientMessage )
140 {
141 if(evt.xproperty.atom == CMD_ATOM)
142 {
143 int cmd = evt.xclient.data.b[0];
144 switch( cmd )
145 {
146 case LXS_RELOAD: /* reload all settings */
147 settings_deamon_reload();
148 break;
149 case LXS_EXIT:
150 lxsession_quit();
151 break;
152 }
153 }
154 }
155 else if( evt.type == SelectionClear )
156 {
157 settings_manager_selection_clear( &evt );
158 }
159 }
160 return TRUE;
161 }
162
163 void xevent_finalize()
164 {
165 if(source)
166 {
167 g_source_destroy(source);
168 g_source_unref(source);
169 }
170
171 XGrabServer( dpy );
172 XSetSelectionOwner( dpy, CMD_ATOM, DefaultRootWindow( dpy ), None );
173 XUngrabServer( dpy );
174
175 XCloseDisplay( dpy );
176 }
177