Initial checkin of luaxcb
[luaxcb.git] / lxcb.c
blobb7d35d8aa4364d674cc5ac771864cd9110b57290
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <lua5.1/lua.h>
4 #include <lua5.1/lauxlib.h>
6 #include <xcb/xcb.h>
8 #define MT_DISPLAY "XCB.display"
11 extern void push_ERROR(lua_State *L, xcb_generic_error_t *e);
13 typedef void (*eventFunc)(lua_State *L, xcb_generic_event_t *);
14 eventFunc push_event[256] = { NULL };
16 void RegisterEvent(int index, eventFunc func)
18 push_event[index] = func;
21 static void PushEvent(lua_State *L, xcb_generic_event_t *event)
23 lua_newtable(L);
24 lua_pushinteger(L, event->response_type);
25 lua_setfield(L, -2, "response_type");
26 lua_pushinteger(L, event->sequence);
27 lua_setfield(L, -2, "sequence");
28 lua_pushinteger(L, event->full_sequence);
29 lua_setfield(L, -2, "full_sequence");
31 if (push_event[event->response_type])
32 push_event[event->response_type](L, event);
35 static int Connect(lua_State *L)
37 xcb_connection_t *c;
38 int screen;
39 const char *name = NULL;
41 if (!lua_isnil(L, 1))
42 name = lua_tostring(L, 1);
43 c = xcb_connect(name, &screen);
44 if (!c)
45 return 0;
47 lua_newuserdata(L, sizeof(xcb_connection_t *));
48 ((xcb_connection_t **)lua_touserdata(L, -1))[0] = c;
49 luaL_getmetatable(L, MT_DISPLAY);
50 lua_setmetatable(L, -2);
52 lua_newtable(L);
53 lua_setfenv(L, -2);
55 lua_pushinteger(L, screen);
56 return 2;
59 static int gc_connection(lua_State *L)
61 xcb_connection_t *c;
62 c = ((xcb_connection_t **)luaL_checkudata(L, 1, MT_DISPLAY))[0];
64 lua_getfenv(L, 1);
65 lua_getfield(L, -1, "closed");
66 if (!lua_toboolean(L, -1))
67 xcb_disconnect(c);
69 return 0;
72 static int Disconnect(lua_State *L)
74 xcb_connection_t *c;
75 c = ((xcb_connection_t **)luaL_checkudata(L, 1, MT_DISPLAY))[0];
77 lua_getfenv(L, 1);
78 lua_getfield(L, -1, "closed");
79 if (lua_toboolean(L, -1))
80 luaL_error(L, "Error: already disconnected");
82 lua_pushboolean(L, 1);
83 lua_setfield(L, -3, "closed");
85 xcb_disconnect(c);
86 return 0;
89 static int Flush(lua_State *L)
91 xcb_connection_t *c;
92 c = ((xcb_connection_t **)luaL_checkudata(L, 1, MT_DISPLAY))[0];
94 lua_pushinteger(L, xcb_flush(c));
95 return 1;
98 static int GenerateID(lua_State *L)
100 lua_pushinteger(L, xcb_generate_id(((xcb_connection_t **)luaL_checkudata(L, 1, MT_DISPLAY))[0]));
102 return 1;
106 extern void push_Setup(lua_State *L, const xcb_setup_t *x); //Temporary until I get headers sorted out
108 static int GetSetup(lua_State *L)
110 xcb_connection_t *c;
111 c = ((xcb_connection_t **)luaL_checkudata(L, 1, MT_DISPLAY))[0];
113 lua_getfenv(L, 1);
114 lua_getfield(L, -1, "closed");
115 if (lua_toboolean(L, -1))
116 luaL_error(L, "Error: already disconnected");
118 push_Setup(L, xcb_get_setup(c));
119 return 1;
122 static int PollForEvent(lua_State *L)
124 xcb_connection_t *c;
125 xcb_generic_event_t *e;
127 c = ((xcb_connection_t **)luaL_checkudata(L, 1, MT_DISPLAY))[0];
129 lua_getfenv(L, 1);
130 lua_getfield(L, -1, "closed");
131 if (lua_toboolean(L, -1))
132 luaL_error(L, "Error: already disconnected");
134 e = xcb_poll_for_event(c);
135 if (!e)
136 lua_pushnil(L);
137 else if (!e->response_type)
138 push_ERROR(L, (xcb_generic_error_t *)e);
139 else
140 PushEvent(L, e);
142 if (e)
143 free(e);
145 return 1;
148 static int WaitForEvent(lua_State *L)
150 xcb_connection_t *c;
151 xcb_generic_event_t *e;
153 c = ((xcb_connection_t **)luaL_checkudata(L, 1, MT_DISPLAY))[0];
155 lua_getfenv(L, 1);
156 lua_getfield(L, -1, "closed");
157 if (lua_toboolean(L, -1))
158 luaL_error(L, "Error: already disconnected");
160 e = xcb_wait_for_event(c);
161 if (!e)
162 lua_pushnil(L);
163 else if (!e->response_type)
164 push_ERROR(L, (xcb_generic_error_t *)e);
165 else
166 PushEvent(L, e);
168 if (e)
169 free(e);
171 return 1;
174 static int HasError(lua_State *L)
176 xcb_connection_t *c;
177 c = ((xcb_connection_t **)luaL_checkudata(L, 1, MT_DISPLAY))[0];
179 lua_getfenv(L, 1);
180 lua_getfield(L, -1, "closed");
181 if (lua_toboolean(L, -1))
182 luaL_error(L, "Error: already disconnected");
184 lua_pushboolean(L, xcb_connection_has_error(c));
185 return 1;
190 static luaL_Reg lxcb[] = {
191 { "connect", Connect },
192 { NULL, NULL }
195 static luaL_Reg display_m[] = {
196 { "__gc", gc_connection },
197 { "disconnect", Disconnect },
198 { "flush", Flush },
199 { "generate_id", GenerateID },
200 { "get_setup", GetSetup },
201 { "poll_for_event", PollForEvent },
202 { "wait_for_event", WaitForEvent },
203 { "has_error", HasError },
204 /* TODO:
205 { "connect_to_display_with_auth_info", ConnectToDisplayWithAuthInfo },
206 { "connect_to_fd", ConnectToFD },
207 { "get_file_descriptor", GetFileDescriptor },
208 { "get_maximum_request_length", GetMaximumRequestLength },
209 { "parse_display", ParseDisplay },
210 { "prefetch_extension_data", PrefetchExtensionData },
211 { "prefetch_maximum_request_length", PrefetchMaximumRequestLength },
212 { "query_extension_reply", QueryExtensionReply },
213 { "request_check", RequestCheck },
215 { NULL, NULL }
218 #ifdef _MSC_VER
219 #define DLLEXPORT __declspec(dllexport)
220 #else
221 /* Must be gcc if not MSC */
222 #define DLLEXPORT __attribute__((visibility("default")))
223 #endif
225 extern void init_xproto(lua_State *L); // Temporary, until I get headers sorted.
227 DLLEXPORT int luaopen_lxcb(lua_State *L)
229 luaL_register(L, "lxcb", lxcb);
231 luaL_newmetatable(L, MT_DISPLAY);
232 lua_pushvalue(L, -1);
233 lua_setfield(L, -2, "__index");
234 luaL_register(L, NULL, display_m);
236 init_xproto(L);
237 lua_pop(L, 1);
239 return 1;