Merge branch '7.8'
[mesa.git] / progs / egl / eglut / eglut_x11.c
1 #include <X11/Xlib.h>
2 #include <X11/Xutil.h>
3 #include <X11/keysym.h>
4
5 #include "eglutint.h"
6
7 void
8 _eglutNativeInitDisplay(void)
9 {
10 _eglut->native_dpy = XOpenDisplay(_eglut->display_name);
11 if (!_eglut->native_dpy)
12 _eglutFatal("failed to initialize native display");
13
14 _eglut->surface_type = EGL_WINDOW_BIT;
15 }
16
17 void
18 _eglutNativeFiniDisplay(void)
19 {
20 XCloseDisplay(_eglut->native_dpy);
21 }
22
23 void
24 _eglutNativeInitWindow(struct eglut_window *win, const char *title,
25 int x, int y, int w, int h)
26 {
27 XVisualInfo *visInfo, visTemplate;
28 int num_visuals;
29 Window root, xwin;
30 XSetWindowAttributes attr;
31 unsigned long mask;
32 EGLint vid;
33
34 if (!eglGetConfigAttrib(_eglut->dpy,
35 win->config, EGL_NATIVE_VISUAL_ID, &vid))
36 _eglutFatal("failed to get visual id");
37
38 /* The X window visual must match the EGL config */
39 visTemplate.visualid = vid;
40 visInfo = XGetVisualInfo(_eglut->native_dpy,
41 VisualIDMask, &visTemplate, &num_visuals);
42 if (!visInfo)
43 _eglutFatal("failed to get an visual of id 0x%x", vid);
44
45 root = RootWindow(_eglut->native_dpy, DefaultScreen(_eglut->native_dpy));
46
47 /* window attributes */
48 attr.background_pixel = 0;
49 attr.border_pixel = 0;
50 attr.colormap = XCreateColormap(_eglut->native_dpy,
51 root, visInfo->visual, AllocNone);
52 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
53 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
54
55 xwin = XCreateWindow(_eglut->native_dpy, root, x, y, w, h,
56 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr);
57 if (!xwin)
58 _eglutFatal("failed to create a window");
59
60 XFree(visInfo);
61
62 /* set hints and properties */
63 {
64 XSizeHints sizehints;
65 sizehints.x = x;
66 sizehints.y = y;
67 sizehints.width = w;
68 sizehints.height = h;
69 sizehints.flags = USSize | USPosition;
70 XSetNormalHints(_eglut->native_dpy, xwin, &sizehints);
71 XSetStandardProperties(_eglut->native_dpy, xwin,
72 title, title, None, (char **) NULL, 0, &sizehints);
73 }
74
75 XMapWindow(_eglut->native_dpy, xwin);
76
77 win->native.u.window = xwin;
78 win->native.width = w;
79 win->native.height = h;
80 }
81
82 void
83 _eglutNativeFiniWindow(struct eglut_window *win)
84 {
85 XDestroyWindow(_eglut->native_dpy, win->native.u.window);
86 }
87
88 static int
89 lookup_keysym(KeySym sym)
90 {
91 int special;
92
93 switch (sym) {
94 case XK_F1:
95 special = EGLUT_KEY_F1;
96 break;
97 case XK_F2:
98 special = EGLUT_KEY_F2;
99 break;
100 case XK_F3:
101 special = EGLUT_KEY_F3;
102 break;
103 case XK_F4:
104 special = EGLUT_KEY_F4;
105 break;
106 case XK_F5:
107 special = EGLUT_KEY_F5;
108 break;
109 case XK_F6:
110 special = EGLUT_KEY_F6;
111 break;
112 case XK_F7:
113 special = EGLUT_KEY_F7;
114 break;
115 case XK_F8:
116 special = EGLUT_KEY_F8;
117 break;
118 case XK_F9:
119 special = EGLUT_KEY_F9;
120 break;
121 case XK_F10:
122 special = EGLUT_KEY_F10;
123 break;
124 case XK_F11:
125 special = EGLUT_KEY_F11;
126 break;
127 case XK_F12:
128 special = EGLUT_KEY_F12;
129 break;
130 case XK_KP_Left:
131 case XK_Left:
132 special = EGLUT_KEY_LEFT;
133 break;
134 case XK_KP_Up:
135 case XK_Up:
136 special = EGLUT_KEY_UP;
137 break;
138 case XK_KP_Right:
139 case XK_Right:
140 special = EGLUT_KEY_RIGHT;
141 break;
142 case XK_KP_Down:
143 case XK_Down:
144 special = EGLUT_KEY_DOWN;
145 break;
146 default:
147 special = -1;
148 break;
149 }
150
151 return special;
152 }
153
154 static void
155 next_event(struct eglut_window *win)
156 {
157 int redraw = 0;
158 XEvent event;
159
160 if (!XPending(_eglut->native_dpy)) {
161 if (_eglut->idle_cb)
162 _eglut->idle_cb();
163 return;
164 }
165
166 XNextEvent(_eglut->native_dpy, &event);
167
168 switch (event.type) {
169 case Expose:
170 redraw = 1;
171 break;
172 case ConfigureNotify:
173 win->native.width = event.xconfigure.width;
174 win->native.height = event.xconfigure.height;
175 if (win->reshape_cb)
176 win->reshape_cb(win->native.width, win->native.height);
177 break;
178 case KeyPress:
179 {
180 char buffer[1];
181 KeySym sym;
182 int r;
183
184 r = XLookupString(&event.xkey,
185 buffer, sizeof(buffer), &sym, NULL);
186 if (r && win->keyboard_cb) {
187 win->keyboard_cb(buffer[0]);
188 }
189 else if (!r && win->special_cb) {
190 r = lookup_keysym(sym);
191 if (r >= 0)
192 win->special_cb(r);
193 }
194 }
195 redraw = 1;
196 break;
197 default:
198 ; /*no-op*/
199 }
200
201 _eglut->redisplay = redraw;
202 }
203
204 void
205 _eglutNativeEventLoop(void)
206 {
207 while (1) {
208 struct eglut_window *win = _eglut->current;
209
210 next_event(win);
211
212 if (_eglut->redisplay) {
213 _eglut->redisplay = 0;
214
215 if (win->display_cb)
216 win->display_cb();
217 eglSwapBuffers(_eglut->dpy, win->surface);
218 }
219 }
220 }