fixed build on windows
[gph-gfx] / test_x11.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <X11/Xlib.h>
4 #include <X11/Xutil.h>
5 #include <X11/keysym.h>
6 #include "gphgfx.h"
7
8 static void redraw(void);
9 static void reshape(int x, int y);
10 static void keydown(int key, int x, int y);
11 static void keyup(int key, int x, int y);
12 static void button(int bn, int st, int x, int y);
13 static void motion(int x, int y);
14
15 static int create_window(const char *title, int width, int height);
16 static void handle_event(XEvent *ev);
17 static KeySym translate_keysym(KeySym sym);
18 static void set_window_title(const char *title);
19
20 static Display *dpy;
21 static int scr;
22 static Window win, root;
23 static Atom xa_wm_proto, xa_wm_del_win;
24 static int quit, mapped, win_width, win_height, modstate;
25 static GC gc;
26
27 int main(int argc, char **argv)
28 {
29         if(!(dpy = XOpenDisplay(0))) {
30                 fprintf(stderr, "failed to connect to the X server\n");
31                 return 1;
32         }
33         xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", False);
34         xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
35
36         scr = DefaultScreen(dpy);
37         root = RootWindow(dpy, scr);
38
39         if(create_window("gph-gfx test", 800, 600) == -1) {
40                 return 1;
41         }
42
43         if(ggfx_init("test", GGFX_INIT_DEBUG) == -1) {
44                 return 1;
45         }
46
47         for(;;) {
48                 while(XPending(dpy)) {
49                         XEvent ev;
50                         XNextEvent(dpy, &ev);
51                         handle_event(&ev);
52                         if(quit) goto end;
53                 }
54                 redraw();
55         }
56 end:
57
58         ggfx_shutdown();
59         XFreeGC(dpy, gc);
60         XCloseDisplay(dpy);
61         return 0;
62 }
63
64
65 static void redraw(void)
66 {
67         XSetForeground(dpy, gc, 0xff00);
68         XClearWindow(dpy, win);
69         usleep(10000);
70 }
71
72 static void reshape(int x, int y)
73 {
74         printf("reshape %dx%d\n", x, y);
75 }
76
77 static void keydown(int key, int x, int y)
78 {
79         switch(key) {
80         case 27:
81                 quit = 1;
82                 break;
83         }
84 }
85
86 static void keyup(int key, int x, int y)
87 {
88 }
89
90 static void button(int bn, int st, int x, int y)
91 {
92 }
93
94 static void motion(int x, int y)
95 {
96 }
97
98 static int create_window(const char *title, int width, int height)
99 {
100         XSetWindowAttributes xattr = {0};
101         XVisualInfo vinf;
102         unsigned int xattr_mask;
103
104         if(!XMatchVisualInfo(dpy, scr, 24, TrueColor, &vinf)) {
105                 fprintf(stderr, "failed to find appropriate visual\n");
106                 return -1;
107         }
108
109         xattr.background_pixel = BlackPixel(dpy, scr);
110         xattr.colormap = XCreateColormap(dpy, root, vinf.visual, AllocNone);
111         xattr_mask = CWBackPixel | CWColormap | CWBackPixmap | CWBorderPixel;
112         if(!(win = XCreateWindow(dpy, root, 0, 0, width, height, 0, vinf.depth,
113                                         InputOutput, vinf.visual, xattr_mask, &xattr))) {
114                 fprintf(stderr, "Failed to create window\n");
115                 return -1;
116         }
117
118         XSelectInput(dpy, win, ExposureMask | StructureNotifyMask | KeyPressMask |
119                         KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask);
120
121         set_window_title(title);
122         XSetWMProtocols(dpy, win, &xa_wm_del_win, 1);
123         XMapWindow(dpy, win);
124
125         gc = XCreateGC(dpy, win, 0, 0);
126         return 0;
127 }
128
129
130 static KeySym translate_keysym(KeySym sym)
131 {
132         switch(sym) {
133         case XK_Escape:
134                 return 27;
135         case XK_BackSpace:
136                 return '\b';
137         case XK_Linefeed:
138                 return '\r';
139         case XK_Return:
140                 return '\n';
141         case XK_Delete:
142                 return 127;
143         case XK_Tab:
144                 return '\t';
145         default:
146                 break;
147         }
148         return sym;
149 }
150
151 static void handle_event(XEvent *ev)
152 {
153         KeySym sym;
154
155         switch(ev->type) {
156         case MapNotify:
157                 mapped = 1;
158                 break;
159         case UnmapNotify:
160                 mapped = 0;
161                 break;
162         case ConfigureNotify:
163                 if(ev->xconfigure.width != win_width || ev->xconfigure.height != win_height) {
164                         win_width = ev->xconfigure.width;
165                         win_height = ev->xconfigure.height;
166                         reshape(ev->xconfigure.width, ev->xconfigure.height);
167                 }
168                 break;
169
170         case ClientMessage:
171                 if(ev->xclient.message_type == xa_wm_proto) {
172                         if(ev->xclient.data.l[0] == xa_wm_del_win) {
173                                 quit = 1;
174                         }
175                 }
176                 break;
177
178         case Expose:
179                 /*upd_pending = 1;*/
180                 break;
181
182         case KeyPress:
183         case KeyRelease:
184                 modstate = ev->xkey.state & (ShiftMask | ControlMask | Mod1Mask);
185                 if(!(sym = XLookupKeysym(&ev->xkey, 0))) {
186                         break;
187                 }
188                 sym = translate_keysym(sym);
189                 if(ev->type == KeyPress) {
190                         keydown(sym, ev->xkey.x, ev->xkey.y);
191                 } else {
192                         keyup(sym, ev->xkey.x, ev->xkey.y);
193                 }
194                 break;
195
196         case ButtonPress:
197         case ButtonRelease:
198                 modstate = ev->xbutton.state & (ShiftMask | ControlMask | Mod1Mask);
199                 button(ev->xbutton.button - Button1, ev->type == ButtonPress,
200                                 ev->xbutton.x, ev->xbutton.y);
201                 break;
202
203         case MotionNotify:
204                 motion(ev->xmotion.x, ev->xmotion.y);
205                 break;
206
207         default:
208                 break;
209         }
210 }
211
212 static void set_window_title(const char *title)
213 {
214         XTextProperty tprop;
215         if(!XStringListToTextProperty((char**)&title, 1, &tprop)) {
216                 return;
217         }
218         XSetWMName(dpy, win, &tprop);
219         XFree(tprop.value);
220 }