eqemu
view src/main.cc @ 1:374d91dd2996
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 15 Jul 2014 05:44:26 +0300 |
parents | 01fb0dee8a92 |
children | 48dce4ee4850 |
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 Display *dpy;
24 static Window win;
25 static GLXContext ctx;
26 static Atom xa_wm_prot, xa_wm_del_win;
28 static int win_width, win_height;
30 static bool redisplay_pending;
31 static bool win_mapped;
33 int main()
34 {
35 if(!init()) {
36 fprintf(stderr, "X11/OpenGL initialization failed\n");
37 return 1;
38 }
39 atexit(cleanup);
41 int xfd = ConnectionNumber(dpy);
43 for(;;) {
44 fd_set rd;
45 FD_ZERO(&rd);
47 FD_SET(xfd, &rd);
49 while(select(xfd + 1, &rd, 0, 0, 0) == -1 && errno == EINTR);
51 if(FD_ISSET(xfd, &rd)) {
52 process_events();
53 }
55 if(redisplay_pending) {
56 display();
57 redisplay_pending = false;
58 }
59 }
60 return 0;
61 }
63 static bool init()
64 {
65 start_dev();
67 if(!(dpy = XOpenDisplay(0))) {
68 fprintf(stderr, "failed to connect to the X server!\n");
69 return false;
70 }
72 if(!(win = create_window("dummy equeue device", 800, 600))) {
73 return false;
74 }
76 return true;
77 }
79 static void cleanup()
80 {
81 stop_dev();
83 if(!dpy) return;
85 if(win) {
86 XDestroyWindow(dpy, win);
87 }
88 XCloseDisplay(dpy);
89 }
91 static void display()
92 {
93 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
95 glMatrixMode(GL_MODELVIEW);
96 glLoadIdentity();
98 glXSwapBuffers(dpy, win);
99 assert(glGetError() == GL_NO_ERROR);
100 }
102 static void reshape(int x, int y)
103 {
104 glViewport(0, 0, x, y);
106 glMatrixMode(GL_PROJECTION);
107 glLoadIdentity();
108 gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
109 }
111 static void keyb(int key, bool pressed)
112 {
113 if(pressed) {
114 switch(key) {
115 case 27:
116 exit(0);
117 }
118 }
119 }
121 static void mouse(int bn, bool pressed, int x, int y)
122 {
123 }
125 static void motion(int x, int y)
126 {
127 }
129 static Window create_window(const char *title, int xsz, int ysz)
130 {
131 int scr = DefaultScreen(dpy);
132 Window root = RootWindow(dpy, scr);
134 int glxattr[] = {
135 GLX_RGBA,
136 GLX_RED_SIZE, 8,
137 GLX_GREEN_SIZE, 8,
138 GLX_BLUE_SIZE, 8,
139 GLX_DEPTH_SIZE, 24,
140 GLX_DOUBLEBUFFER,
141 #if defined(GLX_VERSION_1_4) || defined(GLX_ARB_multisample)
142 GLX_SAMPLE_BUFFERS_ARB, 1,
143 GLX_SAMPLES_ARB, 1,
144 #endif
145 None
146 };
148 XVisualInfo *vis = glXChooseVisual(dpy, scr, glxattr);
149 if(!vis) {
150 fprintf(stderr, "failed to find a suitable visual\n");
151 return 0;
152 }
154 if(!(ctx = glXCreateContext(dpy, vis, 0, True))) {
155 fprintf(stderr, "failed to create OpenGL context\n");
156 XFree(vis);
157 return -1;
158 }
160 XSetWindowAttributes xattr;
161 xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, scr);
162 xattr.colormap = XCreateColormap(dpy, root, vis->visual, AllocNone);
163 unsigned int xattr_mask = CWColormap | CWBackPixel | CWBorderPixel;
165 Window win = XCreateWindow(dpy, root, 0, 0, xsz, ysz, 0, vis->depth, InputOutput,
166 vis->visual, xattr_mask, &xattr);
167 if(!win) {
168 fprintf(stderr, "failed to create window\n");
169 glXDestroyContext(dpy, ctx);
170 XFree(vis);
171 return -1;
172 }
173 XFree(vis);
175 unsigned int evmask = StructureNotifyMask | VisibilityChangeMask | ExposureMask |
176 KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
177 ButtonMotionMask | PointerMotionMask;
178 XSelectInput(dpy, win, evmask);
180 xa_wm_prot = XInternAtom(dpy, "WM_PROTOCOLS", False);
181 xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
182 XSetWMProtocols(dpy, win, &xa_wm_del_win, 1);
184 XClassHint hint;
185 hint.res_name = hint.res_class = (char*)"equeue_win";
186 XSetClassHint(dpy, win, &hint);
188 XTextProperty wm_name;
189 XStringListToTextProperty((char**)&title, 1, &wm_name);
190 XSetWMName(dpy, win, &wm_name);
191 XSetWMIconName(dpy, win, &wm_name);
192 XFree(wm_name.value);
194 XMapWindow(dpy, win);
195 glXMakeCurrent(dpy, win, ctx);
197 return win;
198 }
200 static void process_events()
201 {
202 XEvent ev;
204 while(XPending(dpy)) {
205 XNextEvent(dpy, &ev);
206 switch(ev.type) {
207 case MapNotify:
208 win_mapped = true;
209 break;
211 case UnmapNotify:
212 win_mapped = false;
213 break;
215 case Expose:
216 if(win_mapped && ev.xexpose.count == 0) {
217 redisplay_pending = 1;
218 }
219 break;
221 case MotionNotify:
222 motion(ev.xmotion.x, ev.xmotion.y);
223 break;
225 case ButtonPress:
226 mouse(ev.xbutton.button - 1, true, ev.xbutton.x, ev.xbutton.y);
227 break;
229 case ButtonRelease:
230 mouse(ev.xbutton.button - 1, false, ev.xbutton.x, ev.xbutton.y);
231 break;
233 case KeyPress:
234 {
235 KeySym sym = XLookupKeysym(&ev.xkey, 0);
236 keyb(translate_keysym(sym), true);
237 }
238 break;
240 case KeyRelease:
241 {
242 KeySym sym = XLookupKeysym(&ev.xkey, 0);
243 keyb(translate_keysym(sym), false);
244 }
245 break;
247 case ConfigureNotify:
248 {
249 int xsz = ev.xconfigure.width;
250 int ysz = ev.xconfigure.height;
252 if(xsz != win_width || ysz != win_height) {
253 win_width = xsz;
254 win_height = ysz;
255 reshape(xsz, ysz);
256 }
257 }
258 break;
260 case ClientMessage:
261 if(ev.xclient.message_type == xa_wm_prot) {
262 if((Atom)ev.xclient.data.l[0] == xa_wm_del_win) {
263 exit(0);
264 }
265 }
266 break;
268 default:
269 break;
270 }
272 }
273 }
275 static int translate_keysym(KeySym sym)
276 {
277 switch(sym) {
278 case XK_BackSpace:
279 return '\b';
280 case XK_Tab:
281 return '\t';
282 case XK_Linefeed:
283 return '\r';
284 case XK_Return:
285 return '\n';
286 case XK_Escape:
287 return 27;
288 default:
289 break;
290 }
291 return (int)sym;
292 }