5c62d4b15012b421632617efae8fbfade7cc56d2
[debian/lxdm.git] / src / xconn.c
1 #include <unistd.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <glib.h>
6
7 #ifdef LXDM_XCONN_XLIB
8 #include <X11/Xlib.h>
9 #include <X11/XKBlib.h>
10 #include <setjmp.h>
11 #endif
12
13 #ifdef LXDM_XCONN_XCB
14 #include <xcb/xcb.h>
15 #include <xcb/xproto.h>
16 #endif
17
18 #ifdef LXDM_XCONN_XLIB
19
20 typedef Display *xconn_t;
21
22 static int CatchErrors(Display *dpy, XErrorEvent *ev)
23 {
24 return 0;
25 }
26
27 static jmp_buf XErrEnv;
28 static int CatchIOErrors(Display *dpy)
29 {
30 close(ConnectionNumber(dpy));
31 longjmp(XErrEnv,1);
32 return 0;
33 }
34
35 xconn_t xconn_open(const char *display)
36 {
37 return XOpenDisplay(display);
38 }
39
40 void xconn_close(xconn_t c)
41 {
42 if(!c) return;
43 XSetErrorHandler(CatchErrors);
44 XSetIOErrorHandler(CatchIOErrors);
45 if(!setjmp(XErrEnv))
46 XCloseDisplay(c);
47 XSetErrorHandler(NULL);
48 XSetIOErrorHandler(NULL);
49 }
50
51 void xconn_clean(xconn_t c)
52 {
53 Window dummy, parent;
54 Window *children;
55 unsigned int nchildren;
56 unsigned int i;
57 Window Root;
58
59 if(!c) return;
60
61 XSetErrorHandler(CatchErrors);
62 XSetIOErrorHandler(CatchIOErrors);
63
64 Root = DefaultRootWindow(c);
65
66 nchildren = 0;
67 if(!setjmp(XErrEnv))
68 XQueryTree(c, Root, &dummy, &parent, &children, &nchildren);
69 else
70 goto out;
71 for( i = 0; i < nchildren; i++ )
72 {
73 if(!setjmp(XErrEnv))
74 XKillClient(c, children[i]);
75 }
76 XFree((char *)children);
77 if(!setjmp(XErrEnv))
78 XSync(c, 0);
79 out:
80 XSetErrorHandler(NULL);
81 XSetIOErrorHandler(NULL);
82 }
83
84 #endif
85
86 #ifdef LXDM_XCONN_XCB
87
88 typedef struct{
89 guint id;
90 xcb_connection_t *c;
91 }*xconn_t;
92
93 typedef struct _XConnSource
94 {
95 GSource source;
96 GPollFD poll;
97 }XConnSource;
98
99 typedef gboolean (*XConnFunc)(gpointer data,xcb_generic_event_t *event);
100
101 static gboolean xconn_prepare (GSource *source,gint *timeout)
102 {
103 *timeout=-1;
104 return FALSE;
105 }
106
107 static gboolean xconn_check(GSource *source)
108 {
109 XConnSource *s=(XConnSource*)source;
110 if((s->poll.revents & G_IO_IN))
111 return TRUE;
112 return FALSE;
113 }
114
115 static gboolean xconn_dispatch (GSource *source,GSourceFunc callback,gpointer user_data)
116 {
117 xconn_t c=user_data;
118 xcb_generic_event_t *event;
119 while((event=xcb_poll_for_event(c->c))!=NULL)
120 {
121 ((XConnFunc)callback)(user_data,event);
122 free(event);
123 }
124 return TRUE;
125 }
126
127 static GSourceFuncs xconn_funcs =
128 {
129 xconn_prepare,
130 xconn_check,
131 xconn_dispatch,
132 NULL
133 };
134
135 static gboolean xconn_func(gpointer data,xcb_generic_event_t *event)
136 {
137 return TRUE;
138 }
139
140
141 xconn_t xconn_open(const char *display)
142 {
143 XConnSource *s;
144 xcb_connection_t *dpy;
145 xconn_t c;
146 int fd;
147 dpy=xcb_connect(display,0);
148 /* is error in setup stage, there is memory leak at xcb */
149 if(!dpy || xcb_connection_has_error(dpy))
150 return NULL;
151 c=malloc(sizeof(*c));
152 c->c=dpy;
153 fd=xcb_get_file_descriptor(dpy);
154 s=(XConnSource*)g_source_new(&xconn_funcs,sizeof(XConnSource));
155 g_source_set_callback((GSource*)s,(GSourceFunc)xconn_func,c,NULL);
156
157 s->poll.fd=fd;
158 s->poll.events=G_IO_IN;
159 g_source_add_poll((GSource*)s,&s->poll);
160 c->id=g_source_attach((GSource*)s,NULL);
161 return c;
162 }
163
164 void xconn_close(xconn_t c)
165 {
166 if(!c) return;
167 g_source_remove(c->id);
168 /* hack, clear the xcb has_error, so we can free it any way */
169 if(xcb_connection_has_error(c->c) && *(int*)c->c==1)
170 *(int*)c->c=0;
171 xcb_disconnect(c->c);
172 free(c);
173 }
174
175 #if 0
176 static xcb_window_t xconn_get_root(xconn_t c)
177 {
178 const xcb_setup_t *setup;
179 setup=xcb_get_setup(c->c);
180 xcb_screen_iterator_t iter = xcb_setup_roots_iterator (setup);
181 xcb_screen_t *screen = iter.data;
182 return screen->root;
183 }
184 #endif
185
186 void xconn_clean(xconn_t c)
187 {
188 #if 0
189 xcb_query_tree_cookie_t wintree;
190 xcb_query_tree_reply_t *rep;
191 xcb_window_t *children;
192 xcb_window_t root;
193 int i,len;
194 if(!c) return;
195 root=xconn_get_root(c);
196 wintree = xcb_query_tree(c->c, root);
197 rep = xcb_query_tree_reply(c->c, wintree, 0);
198 if(!rep) return;
199 len = xcb_query_tree_children_length(rep);
200 children = xcb_query_tree_children(rep);
201 for(i=0;i<len;i++)
202 xcb_kill_client(c->c,children[i]);
203 free(rep);
204 xcb_flush(c->c);
205 #endif
206 }
207
208 #endif
209