foo
[vkray] / src / main_x11.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <X11/Xlib.h>
4 #include <X11/Xutil.h>
5 #include "app.h"
6
7 static Window create_window(const char *title, int xsz, int ysz);
8 static void handle_event(XEvent *ev);
9 static int translate_keysym(KeySym sym);
10
11 static Display *dpy;
12 static Window win, root_win;
13 static int xscr;
14 static Atom xa_wm_proto, xa_wm_del_win;
15 static int reshape_pending, quit;
16 static int win_width, win_height, win_mapped;
17
18 int main(int argc, char **argv)
19 {
20         XEvent ev;
21
22         if(!(dpy = XOpenDisplay(0))) {
23                 fprintf(stderr, "failed to connect to the X server\n");
24                 return 1;
25         }
26         xscr = DefaultScreen(dpy);
27         root_win = RootWindow(dpy, xscr);
28         xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", False);
29         xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
30
31         if(!(win = create_window("vkray", 1280, 800))) {
32                 return 1;
33         }
34
35         if(app_init() == -1) {
36                 goto end;
37         }
38
39         for(;;) {
40                 while(XPending(dpy)) {
41                         XNextEvent(dpy, &ev);
42                         handle_event(&ev);
43                         if(quit) goto end;
44                 }
45
46                 if(reshape_pending) {
47                         app_reshape(win_width, win_height);
48                 }
49                 app_display();
50         }
51
52 end:
53         app_cleanup();
54         XDestroyWindow(dpy, win);
55         XCloseDisplay(dpy);
56         return 0;
57 }
58
59 void app_quit(void)
60 {
61         quit = 1;
62 }
63
64 void app_swap_buffers(void)
65 {
66 }
67
68 static Window create_window(const char *title, int xsz, int ysz)
69 {
70         Window win;
71         XVisualInfo vinf;
72         XTextProperty txprop;
73         XSetWindowAttributes xattr;
74
75         if(!XMatchVisualInfo(dpy, xscr, 24, TrueColor, &vinf)) {
76                 fprintf(stderr, "no suitable visual found\n");
77                 return 0;
78         }
79
80         xattr.background_pixel = BlackPixel(dpy, xscr);
81         xattr.colormap = XCreateColormap(dpy, root_win, vinf.visual, AllocNone);
82
83         if(!(win = XCreateWindow(dpy, root_win, 0, 0, xsz, ysz, 0, 24, InputOutput,
84                                         vinf.visual, CWBackPixel | CWColormap, &xattr))) {
85                 fprintf(stderr, "failed to create window\n");
86                 return 0;
87         }
88
89         XSelectInput(dpy, win, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
90                         ButtonMotionMask | ExposureMask | StructureNotifyMask);
91
92         XSetWMProtocols(dpy, win, &xa_wm_del_win, 1);
93
94         if(XStringListToTextProperty((char**)&title, 1, &txprop)) {
95                 XSetWMName(dpy, win, &txprop);
96                 XSetWMIconName(dpy, win, &txprop);
97                 XFree(txprop.value);
98         }
99
100         XMapWindow(dpy, win);
101
102         reshape_pending = 1;
103         return win;
104 }
105
106 static void handle_event(XEvent *ev)
107 {
108         KeySym sym;
109         int key;
110
111         switch(ev->type) {
112         case MapNotify:
113                 win_mapped = 1;
114                 break;
115         case UnmapNotify:
116                 win_mapped = 0;
117                 break;
118
119         case ConfigureNotify:
120                 if(ev->xconfigure.width != win_width || ev->xconfigure.height != win_height) {
121                         win_width = ev->xconfigure.width;
122                         win_height = ev->xconfigure.height;
123                         reshape_pending = 1;
124                 }
125                 break;
126
127         case KeyPress:
128         case KeyRelease:
129                 if((sym = XLookupKeysym(&ev->xkey, 0)) && (key = translate_keysym(sym))) {
130                         app_keyboard(key, ev->type == KeyPress);
131                 }
132                 break;
133
134         case ButtonPress:
135         case ButtonRelease:
136                 app_mouse(ev->xbutton.button - Button1, ev->type == ButtonPress, ev->xbutton.x, ev->xbutton.y);
137                 break;
138
139         case ClientMessage:
140                 if(ev->xclient.message_type == xa_wm_proto) {
141                         if(ev->xclient.data.l[0] == xa_wm_del_win) {
142                                 quit = 1;
143                         }
144                 }
145                 break;
146
147         default:
148                 break;
149         }
150 }
151
152 static int translate_keysym(KeySym sym)
153 {
154         if(sym < 128) return sym;
155
156         switch(sym) {
157         case XK_Escape: return 27;
158         case XK_Tab: return '\t';
159         case XK_Return: return '\n';
160         case XK_BackSpace: return '\b';
161         case XK_Delete: return KEY_DEL;
162         case XK_Home: return KEY_HOME;
163         case XK_End: return KEY_END;
164         case XK_Page_Up: return KEY_PGUP;
165         case XK_Page_Down: return KEY_PGDOWN;
166         default:
167                 break;
168         }
169
170         return 0;
171 }