vulkan_test2

view src/wsys_x11.c @ 4:c31c4115d44a

test 2, open window, create queue, etc ...
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 22 Sep 2017 15:26:29 +0300
parents
children cec4b0e7fce8
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <X11/Xlib.h>
4 #include <X11/Xutil.h>
5 #include "wsys.h"
6 #include "vku.h"
8 struct callbacks {
9 void (*display)(void);
10 void (*reshape)(int, int);
11 void (*keyboard)(int, int);
12 void (*mouse)(int, int, int, int);
13 void (*motion)(int, int);
14 void (*passive)(int, int);
15 };
17 enum {
18 QUIT = 1,
19 RESHAPE = 2,
20 REDISPLAY = 4
21 };
23 static void proc_event(XEvent *ev);
25 static Display *dpy;
26 static Window win;
27 static Atom xa_wm_delete;
28 static int win_width, win_height;
29 static int win_mapped;
30 static unsigned int evmask = StructureNotifyMask | ExposureMask;
31 static unsigned int pending;
32 static struct callbacks cb;
34 int wsys_create_window(int xsz, int ysz)
35 {
36 int i, scr, num_visuals;
37 Window root_win;
38 Visual *vis = 0;
39 XSetWindowAttributes xattr;
40 unsigned int xattr_mask;
41 XVisualInfo *vinf, vinf_match;
43 if(!(dpy = XOpenDisplay(0))) {
44 fprintf(stderr, "failed to open connection to the X server\n");
45 return -1;
46 }
47 scr = DefaultScreen(dpy);
48 root_win = RootWindow(dpy, scr);
50 xa_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
52 vinf_match.screen = scr;
53 vinf_match.depth = 24;
54 vinf_match.class = TrueColor;
56 if(!(vinf = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask | VisualClassMask, &vinf_match, &num_visuals))) {
57 fprintf(stderr, "failed to retrieve matching visuals\n");
58 XCloseDisplay(dpy);
59 return -1;
60 }
62 for(i=0; i<num_visuals; i++) {
63 if(vku_xlib_usable_visual(dpy, vinf[i].visualid)) {
64 vis = vinf[i].visual;
65 break;
66 }
67 }
68 if(!vis) {
69 fprintf(stderr, "failed to find approprate visual\n");
70 XFree(vinf);
71 XCloseDisplay(dpy);
72 return -1;
73 }
75 xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, scr);
76 xattr.colormap = XCreateColormap(dpy, root_win, vis, AllocNone);
77 xattr_mask = CWBackPixel | CWBorderPixel | CWColormap;
79 if(!(win = XCreateWindow(dpy, root_win, 0, 0, xsz, ysz, 0, 24, InputOutput, vis, xattr_mask, &xattr))) {
80 fprintf(stderr, "failed to create X window\n");
81 XFree(vinf);
82 XCloseDisplay(dpy);
83 return -1;
84 }
85 XFree(vinf);
87 XSelectInput(dpy, win, evmask);
88 XSetWMProtocols(dpy, win, &xa_wm_delete, 1);
90 wsys_set_window_title("X11 window");
91 XMapWindow(dpy, win);
93 win_width = xsz;
94 win_height = ysz;
95 pending = RESHAPE | REDISPLAY;
97 return 0;
98 }
100 void wsys_destroy_window(void)
101 {
102 if(dpy) {
103 if(win) {
104 XDestroyWindow(dpy, win);
105 win = 0;
106 }
107 XCloseDisplay(dpy);
108 dpy = 0;
109 }
110 }
112 void wsys_get_window_size(int *xsz, int *ysz)
113 {
114 *xsz = win_width;
115 *ysz = win_height;
116 }
118 void wsys_set_window_title(const char *title)
119 {
120 XTextProperty text;
121 XStringListToTextProperty((char**)&title, 1, &text);
122 XSetWMName(dpy, win, &text);
123 XSetWMIconName(dpy, win, &text);
124 XFree(text.value);
125 }
127 void wsys_display_callback(void (*func)(void))
128 {
129 cb.display = func;
130 }
132 void wsys_reshape_callback(void (*func)(int, int))
133 {
134 cb.reshape = func;
135 }
137 void wsys_keyboard_callback(void (*func)(int, int))
138 {
139 cb.keyboard = func;
140 if(func) {
141 evmask |= KeyPressMask | KeyReleaseMask;
142 } else {
143 evmask &= ~(KeyPressMask | KeyReleaseMask);
144 }
145 if(win) {
146 XSelectInput(dpy, win, evmask);
147 }
148 }
150 void wsys_mouse_callback(void (*func)(int, int, int, int))
151 {
152 cb.mouse = func;
153 if(func) {
154 evmask |= ButtonPressMask | ButtonReleaseMask;
155 } else {
156 evmask &= ~(ButtonPressMask | ButtonReleaseMask);
157 }
158 if(win) {
159 XSelectInput(dpy, win, evmask);
160 }
161 }
163 void wsys_motion_callback(void (*func)(int, int))
164 {
165 cb.motion = func;
166 if(func) {
167 evmask |= ButtonMotionMask;
168 } else {
169 evmask &= ~ButtonMotionMask;
170 }
171 if(win) {
172 XSelectInput(dpy, win, evmask);
173 }
174 }
176 void wsys_passive_motion_callback(void (*func)(int, int))
177 {
178 cb.passive = func;
179 if(func) {
180 evmask |= PointerMotionMask;
181 } else {
182 evmask &= ~PointerMotionMask;
183 }
184 if(win) {
185 XSelectInput(dpy, win, evmask);
186 }
187 }
189 void wsys_swap_buffers(void)
190 {
191 /* TODO */
192 }
194 void wsys_redisplay(void)
195 {
196 pending |= REDISPLAY;
197 }
199 void wsys_quit(void)
200 {
201 pending |= QUIT;
202 }
204 int wsys_process_events(int mode)
205 {
206 XEvent xev;
208 if(pending & RESHAPE) {
209 if(cb.reshape) {
210 cb.reshape(win_width, win_height);
211 }
212 pending &= ~RESHAPE;
213 }
215 if(mode == WSYS_BLOCKING) {
216 XNextEvent(dpy, &xev);
217 proc_event(&xev);
218 if(pending & QUIT) return -1;
219 }
221 while(XPending(dpy)) {
222 XNextEvent(dpy, &xev);
223 proc_event(&xev);
224 if(pending & QUIT) return -1;
225 }
227 if(pending & REDISPLAY && win_mapped) {
228 pending &= ~REDISPLAY;
229 if(cb.display) {
230 cb.display();
231 }
232 }
233 return 0;
234 }
236 static void proc_event(XEvent *ev)
237 {
238 switch(ev->type) {
239 case MapNotify:
240 win_mapped = 1;
241 break;
243 case UnmapNotify:
244 win_mapped = 0;
245 break;
247 case ClientMessage:
248 if(ev->xclient.data.l[0] == xa_wm_delete) {
249 pending |= QUIT;
250 }
251 break;
253 case ConfigureNotify:
254 if(ev->xconfigure.width != win_width || ev->xconfigure.height != win_height) {
255 win_width = ev->xconfigure.width;
256 win_height = ev->xconfigure.height;
257 pending |= RESHAPE;
258 }
259 break;
261 case Expose:
262 if(ev->xexpose.count == 0) {
263 pending |= REDISPLAY;
264 }
265 break;
267 case KeyPress:
268 case KeyRelease:
269 if(cb.keyboard) {
270 KeySym sym;
271 char str[16];
272 XLookupString(&ev->xkey, str, sizeof str, &sym, 0);
273 cb.keyboard(sym & 0xff, ev->type == KeyPress ? 1 : 0);
274 }
275 break;
277 case ButtonPress:
278 case ButtonRelease:
279 if(cb.mouse) {
280 int bn = ev->xbutton.button - Button1;
281 int pressed = ev->type == ButtonPress ? 1 : 0;
282 cb.mouse(bn, pressed, ev->xbutton.x, ev->xbutton.y);
283 }
284 break;
286 case MotionNotify:
287 if(ev->xmotion.state & 0x1f00) {
288 if(cb.motion) {
289 cb.motion(ev->xmotion.x, ev->xmotion.y);
290 }
291 } else {
292 if(cb.passive) {
293 cb.passive(ev->xmotion.x, ev->xmotion.y);
294 }
295 }
296 break;
297 }
298 }