eqemu

view src/main.cc @ 2:48dce4ee4850

the fake device is working
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 15 Jul 2014 14:37:51 +0300
parents 374d91dd2996
children 3d3656360a82
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <sys/select.h>
7 #include <GL/glew.h>
8 #include <X11/Xlib.h>
9 #include <GL/glx.h>
10 #include "dev.h"
12 static bool init();
13 static void cleanup();
14 static void display();
15 static void keyb(int key, bool pressed);
16 static void mouse(int bn, bool pressed, int x, int y);
17 static void motion(int x, int y);
19 static Window create_window(const char *title, int xsz, int ysz);
20 static void process_events();
21 static int translate_keysym(KeySym sym);
23 static int proc_args(int argc, char **argv);
25 static Display *dpy;
26 static Window win;
27 static GLXContext ctx;
28 static Atom xa_wm_prot, xa_wm_del_win;
30 static int win_width, win_height;
32 static bool redisplay_pending;
33 static bool win_mapped;
35 static int fakefd = -1;
36 static char *fake_devpath;
38 int main(int argc, char **argv)
39 {
40 if(proc_args(argc, argv) == -1) {
41 return 1;
42 }
43 if(!init()) {
44 return 1;
45 }
46 atexit(cleanup);
48 int xfd = ConnectionNumber(dpy);
50 for(;;) {
51 fd_set rd;
52 FD_ZERO(&rd);
54 FD_SET(xfd, &rd);
55 FD_SET(fakefd, &rd);
57 int maxfd = xfd > fakefd ? xfd : fakefd;
59 while(select(maxfd + 1, &rd, 0, 0, 0) == -1 && errno == EINTR);
61 if(FD_ISSET(xfd, &rd)) {
62 process_events();
63 }
64 if(FD_ISSET(fakefd, &rd)) {
65 proc_dev_input();
66 }
68 if(redisplay_pending) {
69 display();
70 redisplay_pending = false;
71 }
72 }
73 return 0;
74 }
76 static bool init()
77 {
78 if(fake_devpath) {
79 if((fakefd = start_dev(fake_devpath)) == -1) {
80 return false;
81 }
82 }
84 if(!(dpy = XOpenDisplay(0))) {
85 fprintf(stderr, "failed to connect to the X server!\n");
86 return false;
87 }
89 if(!(win = create_window("dummy equeue device", 800, 600))) {
90 return false;
91 }
93 return true;
94 }
96 static void cleanup()
97 {
98 stop_dev();
100 if(!dpy) return;
102 if(win) {
103 XDestroyWindow(dpy, win);
104 }
105 XCloseDisplay(dpy);
106 }
108 static void display()
109 {
110 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
112 glMatrixMode(GL_MODELVIEW);
113 glLoadIdentity();
115 glXSwapBuffers(dpy, win);
116 assert(glGetError() == GL_NO_ERROR);
117 }
119 static void reshape(int x, int y)
120 {
121 glViewport(0, 0, x, y);
123 glMatrixMode(GL_PROJECTION);
124 glLoadIdentity();
125 gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
126 }
128 static void keyb(int key, bool pressed)
129 {
130 if(pressed) {
131 switch(key) {
132 case 27:
133 exit(0);
134 }
135 }
136 }
138 static void mouse(int bn, bool pressed, int x, int y)
139 {
140 }
142 static void motion(int x, int y)
143 {
144 }
146 static Window create_window(const char *title, int xsz, int ysz)
147 {
148 int scr = DefaultScreen(dpy);
149 Window root = RootWindow(dpy, scr);
151 int glxattr[] = {
152 GLX_RGBA,
153 GLX_RED_SIZE, 8,
154 GLX_GREEN_SIZE, 8,
155 GLX_BLUE_SIZE, 8,
156 GLX_DEPTH_SIZE, 24,
157 GLX_DOUBLEBUFFER,
158 #if defined(GLX_VERSION_1_4) || defined(GLX_ARB_multisample)
159 GLX_SAMPLE_BUFFERS_ARB, 1,
160 GLX_SAMPLES_ARB, 1,
161 #endif
162 None
163 };
165 XVisualInfo *vis = glXChooseVisual(dpy, scr, glxattr);
166 if(!vis) {
167 fprintf(stderr, "failed to find a suitable visual\n");
168 return 0;
169 }
171 if(!(ctx = glXCreateContext(dpy, vis, 0, True))) {
172 fprintf(stderr, "failed to create OpenGL context\n");
173 XFree(vis);
174 return -1;
175 }
177 XSetWindowAttributes xattr;
178 xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, scr);
179 xattr.colormap = XCreateColormap(dpy, root, vis->visual, AllocNone);
180 unsigned int xattr_mask = CWColormap | CWBackPixel | CWBorderPixel;
182 Window win = XCreateWindow(dpy, root, 0, 0, xsz, ysz, 0, vis->depth, InputOutput,
183 vis->visual, xattr_mask, &xattr);
184 if(!win) {
185 fprintf(stderr, "failed to create window\n");
186 glXDestroyContext(dpy, ctx);
187 XFree(vis);
188 return -1;
189 }
190 XFree(vis);
192 unsigned int evmask = StructureNotifyMask | VisibilityChangeMask | ExposureMask |
193 KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
194 ButtonMotionMask | PointerMotionMask;
195 XSelectInput(dpy, win, evmask);
197 xa_wm_prot = XInternAtom(dpy, "WM_PROTOCOLS", False);
198 xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
199 XSetWMProtocols(dpy, win, &xa_wm_del_win, 1);
201 XClassHint hint;
202 hint.res_name = hint.res_class = (char*)"equeue_win";
203 XSetClassHint(dpy, win, &hint);
205 XTextProperty wm_name;
206 XStringListToTextProperty((char**)&title, 1, &wm_name);
207 XSetWMName(dpy, win, &wm_name);
208 XSetWMIconName(dpy, win, &wm_name);
209 XFree(wm_name.value);
211 XMapWindow(dpy, win);
212 glXMakeCurrent(dpy, win, ctx);
214 return win;
215 }
217 static void process_events()
218 {
219 XEvent ev;
221 while(XPending(dpy)) {
222 XNextEvent(dpy, &ev);
223 switch(ev.type) {
224 case MapNotify:
225 win_mapped = true;
226 break;
228 case UnmapNotify:
229 win_mapped = false;
230 break;
232 case Expose:
233 if(win_mapped && ev.xexpose.count == 0) {
234 redisplay_pending = 1;
235 }
236 break;
238 case MotionNotify:
239 motion(ev.xmotion.x, ev.xmotion.y);
240 break;
242 case ButtonPress:
243 mouse(ev.xbutton.button - 1, true, ev.xbutton.x, ev.xbutton.y);
244 break;
246 case ButtonRelease:
247 mouse(ev.xbutton.button - 1, false, ev.xbutton.x, ev.xbutton.y);
248 break;
250 case KeyPress:
251 {
252 KeySym sym = XLookupKeysym(&ev.xkey, 0);
253 keyb(translate_keysym(sym), true);
254 }
255 break;
257 case KeyRelease:
258 {
259 KeySym sym = XLookupKeysym(&ev.xkey, 0);
260 keyb(translate_keysym(sym), false);
261 }
262 break;
264 case ConfigureNotify:
265 {
266 int xsz = ev.xconfigure.width;
267 int ysz = ev.xconfigure.height;
269 if(xsz != win_width || ysz != win_height) {
270 win_width = xsz;
271 win_height = ysz;
272 reshape(xsz, ysz);
273 }
274 }
275 break;
277 case ClientMessage:
278 if(ev.xclient.message_type == xa_wm_prot) {
279 if((Atom)ev.xclient.data.l[0] == xa_wm_del_win) {
280 exit(0);
281 }
282 }
283 break;
285 default:
286 break;
287 }
289 }
290 }
292 static int translate_keysym(KeySym sym)
293 {
294 switch(sym) {
295 case XK_BackSpace:
296 return '\b';
297 case XK_Tab:
298 return '\t';
299 case XK_Linefeed:
300 return '\r';
301 case XK_Return:
302 return '\n';
303 case XK_Escape:
304 return 27;
305 default:
306 break;
307 }
308 return (int)sym;
309 }
311 static int proc_args(int argc, char **argv)
312 {
313 for(int i=1; i<argc; i++) {
314 if(argv[i][0] == '-') {
315 fprintf(stderr, "unexpected option: %s\n", argv[i]);
316 return -1;
318 } else {
319 if(fake_devpath) {
320 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
321 return -1;
322 }
323 fake_devpath = argv[i];
324 }
325 }
326 if(!fake_devpath) {
327 fprintf(stderr, "no device path specified, running standalone\n");
328 }
329 return 0;
330 }