eqemu

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