initial commit
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 18 Dec 2021 12:02:46 +0000 (14:02 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 18 Dec 2021 12:02:46 +0000 (14:02 +0200)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
src/app.c [new file with mode: 0644]
src/app.h [new file with mode: 0644]
src/main_x11.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..59e7bce
--- /dev/null
@@ -0,0 +1,4 @@
+*.o
+*.swp
+*.d
+vkray
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..b9931ac
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,25 @@
+src = $(wildcard src/*.c)
+obj = $(src:.c=.o)
+dep = $(src:.c=.d)
+bin = vkray
+
+sdr = $(wildcard sdr/*.glsl)
+spirv = $(sdr:.glsl=.spv)
+
+CFLAGS = -pedantic -Wall -g -MMD
+LDFLAGS = -lvulkan -lX11
+
+$(bin): $(obj) $(spirv)
+       $(CC) -o $@ $(obj) $(LDFLAGS)
+
+%.spv: %.v.glsl
+       glslangValidator -o $@ -S vert -V $<
+
+%.spv: %.p.glsl
+       glslangValidator -o $@ -S frag -V $<
+
+-include $(dep)
+
+.PHONY: clean
+clean:
+       rm -f $(src) $(obj) $(spirv)
diff --git a/src/app.c b/src/app.c
new file mode 100644 (file)
index 0000000..9be52ca
--- /dev/null
+++ b/src/app.c
@@ -0,0 +1,38 @@
+#include "app.h"
+
+int app_init(void)
+{
+       return 0;
+}
+
+void app_cleanup(void)
+{
+}
+
+
+void app_display(void)
+{
+}
+
+void app_reshape(int x, int y)
+{
+}
+
+void app_keyboard(int key, int press)
+{
+       if(!press) return;
+
+       switch(key) {
+       case 27:
+               app_quit();
+               break;
+       }
+}
+
+void app_mouse(int bn, int press, int x, int y)
+{
+}
+
+void app_motion(int x, int y)
+{
+}
diff --git a/src/app.h b/src/app.h
new file mode 100644 (file)
index 0000000..4f891e7
--- /dev/null
+++ b/src/app.h
@@ -0,0 +1,22 @@
+#ifndef APP_H_
+#define APP_H_
+
+enum {
+       KEY_DEL = 127,
+       KEY_HOME, KEY_END,
+       KEY_PGUP, KEY_PGDOWN
+};
+
+int app_init(void);
+void app_cleanup(void);
+
+void app_display(void);
+void app_reshape(int x, int y);
+void app_keyboard(int key, int press);
+void app_mouse(int bn, int press, int x, int y);
+void app_motion(int x, int y);
+
+void app_quit(void);
+void app_swap_buffers(void);
+
+#endif /* APP_H_ */
diff --git a/src/main_x11.c b/src/main_x11.c
new file mode 100644 (file)
index 0000000..54f4df6
--- /dev/null
@@ -0,0 +1,166 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "app.h"
+
+static Window create_window(const char *title, int xsz, int ysz);
+static void handle_event(XEvent *ev);
+static int translate_keysym(KeySym sym);
+
+static Display *dpy;
+static Window win, root_win;
+static int xscr;
+static Atom xa_wm_proto, xa_wm_del_win;
+static int reshape_pending, quit;
+static int win_width, win_height, win_mapped;
+
+int main(int argc, char **argv)
+{
+       XEvent ev;
+
+       if(!(dpy = XOpenDisplay(0))) {
+               fprintf(stderr, "failed to connect to the X server\n");
+               return 1;
+       }
+       xscr = DefaultScreen(dpy);
+       root_win = RootWindow(dpy, xscr);
+       xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", False);
+       xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+
+       if(!(win = create_window("vkray", 1280, 800))) {
+               return 1;
+       }
+
+       for(;;) {
+               while(XPending(dpy)) {
+                       XNextEvent(dpy, &ev);
+                       handle_event(&ev);
+                       if(quit) goto end;
+               }
+
+               if(reshape_pending) {
+                       app_reshape(win_width, win_height);
+               }
+               app_display();
+       }
+
+end:
+       XDestroyWindow(dpy, win);
+       XCloseDisplay(dpy);
+       return 0;
+}
+
+void app_quit(void)
+{
+       quit = 1;
+}
+
+void app_swap_buffers(void)
+{
+}
+
+static Window create_window(const char *title, int xsz, int ysz)
+{
+       Window win;
+       XVisualInfo vinf;
+       XTextProperty txprop;
+       XSetWindowAttributes xattr;
+
+       if(!XMatchVisualInfo(dpy, xscr, 24, TrueColor, &vinf)) {
+               fprintf(stderr, "no suitable visual found\n");
+               return 0;
+       }
+
+       xattr.background_pixel = BlackPixel(dpy, xscr);
+       xattr.colormap = XCreateColormap(dpy, root_win, vinf.visual, AllocNone);
+
+       if(!(win = XCreateWindow(dpy, root_win, 0, 0, xsz, ysz, 0, 24, InputOutput,
+                                       vinf.visual, CWBackPixel | CWColormap, &xattr))) {
+               fprintf(stderr, "failed to create window\n");
+               return 0;
+       }
+
+       XSelectInput(dpy, win, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
+                       ButtonMotionMask | ExposureMask | StructureNotifyMask);
+
+       XSetWMProtocols(dpy, win, &xa_wm_del_win, 1);
+
+       if(XStringListToTextProperty((char**)&title, 1, &txprop)) {
+               XSetWMName(dpy, win, &txprop);
+               XSetWMIconName(dpy, win, &txprop);
+               XFree(txprop.value);
+       }
+
+       XMapWindow(dpy, win);
+
+       reshape_pending = 1;
+       return win;
+}
+
+static void handle_event(XEvent *ev)
+{
+       KeySym sym;
+       int key;
+
+       switch(ev->type) {
+       case MapNotify:
+               win_mapped = 1;
+               break;
+       case UnmapNotify:
+               win_mapped = 0;
+               break;
+
+       case ConfigureNotify:
+               if(ev->xconfigure.width != win_width || ev->xconfigure.height != win_height) {
+                       win_width = ev->xconfigure.width;
+                       win_height = ev->xconfigure.height;
+                       reshape_pending = 1;
+               }
+               break;
+
+       case KeyPress:
+       case KeyRelease:
+               if((sym = XLookupKeysym(&ev->xkey, 0)) && (key = translate_keysym(sym))) {
+                       app_keyboard(key, ev->type == KeyPress);
+               }
+               break;
+
+       case ButtonPress:
+       case ButtonRelease:
+               app_mouse(ev->xbutton.button - Button1, ev->type == ButtonPress, ev->xbutton.x, ev->xbutton.y);
+               break;
+
+       case ClientMessage:
+               if(ev->xclient.message_type == xa_wm_proto) {
+                       if(ev->xclient.data.l[0] == xa_wm_del_win) {
+                               quit = 1;
+                       }
+               }
+               break;
+
+       default:
+               break;
+       }
+}
+
+static int translate_keysym(KeySym sym)
+{
+       if(sym < 128) return sym;
+
+       switch(sym) {
+       case XK_Escape: return 27;
+       case XK_Tab: return '\t';
+       case XK_Return: return '\n';
+       case XK_BackSpace: return '\b';
+       case XK_Delete: return KEY_DEL;
+       case XK_Home: return KEY_HOME;
+       case XK_End: return KEY_END;
+       case XK_Page_Up: return KEY_PGUP;
+       case XK_Page_Down: return KEY_PGDOWN;
+       default:
+               break;
+       }
+
+       return 0;
+}