vulkan_test2

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