1/* 2 * Copyright (C) 2010 LunarG Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: 23 * Chia-I Wu <olv@lunarg.com> 24 */ 25 26#include <X11/Xlib.h> 27#include <X11/Xutil.h> 28#include <X11/keysym.h> 29 30#include "eglutint.h" 31 32void 33_eglutNativeInitDisplay(void) 34{ 35 _eglut->native_dpy = XOpenDisplay(_eglut->display_name); 36 if (!_eglut->native_dpy) 37 _eglutFatal("failed to initialize native display"); 38 39 _eglut->surface_type = EGL_WINDOW_BIT; 40} 41 42void 43_eglutNativeFiniDisplay(void) 44{ 45 XCloseDisplay(_eglut->native_dpy); 46} 47 48void 49_eglutNativeInitWindow(struct eglut_window *win, const char *title, 50 int x, int y, int w, int h) 51{ 52 XVisualInfo *visInfo, visTemplate; 53 int num_visuals; 54 Window root, xwin; 55 XSetWindowAttributes attr; 56 unsigned long mask; 57 EGLint vid; 58 59 if (!eglGetConfigAttrib(_eglut->dpy, 60 win->config, EGL_NATIVE_VISUAL_ID, &vid)) 61 _eglutFatal("failed to get visual id"); 62 63 /* The X window visual must match the EGL config */ 64 visTemplate.visualid = vid; 65 visInfo = XGetVisualInfo(_eglut->native_dpy, 66 VisualIDMask, &visTemplate, &num_visuals); 67 if (!visInfo) 68 _eglutFatal("failed to get an visual of id 0x%x", vid); 69 70 root = RootWindow(_eglut->native_dpy, DefaultScreen(_eglut->native_dpy)); 71 72 /* window attributes */ 73 attr.background_pixel = 0; 74 attr.border_pixel = 0; 75 attr.colormap = XCreateColormap(_eglut->native_dpy, 76 root, visInfo->visual, AllocNone); 77 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 78 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 79 80 xwin = XCreateWindow(_eglut->native_dpy, root, x, y, w, h, 81 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr); 82 if (!xwin) 83 _eglutFatal("failed to create a window"); 84 85 XFree(visInfo); 86 87 /* set hints and properties */ 88 { 89 XSizeHints sizehints; 90 sizehints.x = x; 91 sizehints.y = y; 92 sizehints.width = w; 93 sizehints.height = h; 94 sizehints.flags = USSize | USPosition; 95 XSetNormalHints(_eglut->native_dpy, xwin, &sizehints); 96 XSetStandardProperties(_eglut->native_dpy, xwin, 97 title, title, None, (char **) NULL, 0, &sizehints); 98 } 99 100 XMapWindow(_eglut->native_dpy, xwin); 101 102 win->native.u.window = xwin; 103 win->native.width = w; 104 win->native.height = h; 105} 106 107void 108_eglutNativeFiniWindow(struct eglut_window *win) 109{ 110 XDestroyWindow(_eglut->native_dpy, win->native.u.window); 111} 112 113static int 114lookup_keysym(KeySym sym) 115{ 116 int special; 117 118 switch (sym) { 119 case XK_F1: 120 special = EGLUT_KEY_F1; 121 break; 122 case XK_F2: 123 special = EGLUT_KEY_F2; 124 break; 125 case XK_F3: 126 special = EGLUT_KEY_F3; 127 break; 128 case XK_F4: 129 special = EGLUT_KEY_F4; 130 break; 131 case XK_F5: 132 special = EGLUT_KEY_F5; 133 break; 134 case XK_F6: 135 special = EGLUT_KEY_F6; 136 break; 137 case XK_F7: 138 special = EGLUT_KEY_F7; 139 break; 140 case XK_F8: 141 special = EGLUT_KEY_F8; 142 break; 143 case XK_F9: 144 special = EGLUT_KEY_F9; 145 break; 146 case XK_F10: 147 special = EGLUT_KEY_F10; 148 break; 149 case XK_F11: 150 special = EGLUT_KEY_F11; 151 break; 152 case XK_F12: 153 special = EGLUT_KEY_F12; 154 break; 155 case XK_KP_Left: 156 case XK_Left: 157 special = EGLUT_KEY_LEFT; 158 break; 159 case XK_KP_Up: 160 case XK_Up: 161 special = EGLUT_KEY_UP; 162 break; 163 case XK_KP_Right: 164 case XK_Right: 165 special = EGLUT_KEY_RIGHT; 166 break; 167 case XK_KP_Down: 168 case XK_Down: 169 special = EGLUT_KEY_DOWN; 170 break; 171 default: 172 special = -1; 173 break; 174 } 175 176 return special; 177} 178 179static void 180next_event(struct eglut_window *win) 181{ 182 int redraw = 0; 183 XEvent event; 184 185 if (!XPending(_eglut->native_dpy)) { 186 /* there is an idle callback */ 187 if (_eglut->idle_cb) { 188 _eglut->idle_cb(); 189 return; 190 } 191 192 /* the app requests re-display */ 193 if (_eglut->redisplay) 194 return; 195 } 196 197 /* block for next event */ 198 XNextEvent(_eglut->native_dpy, &event); 199 200 switch (event.type) { 201 case Expose: 202 redraw = 1; 203 break; 204 case ConfigureNotify: 205 win->native.width = event.xconfigure.width; 206 win->native.height = event.xconfigure.height; 207 if (win->reshape_cb) 208 win->reshape_cb(win->native.width, win->native.height); 209 break; 210 case KeyPress: 211 { 212 char buffer[1]; 213 KeySym sym; 214 int r; 215 216 r = XLookupString(&event.xkey, 217 buffer, sizeof(buffer), &sym, NULL); 218 if (r && win->keyboard_cb) { 219 win->keyboard_cb(buffer[0]); 220 } 221 else if (!r && win->special_cb) { 222 r = lookup_keysym(sym); 223 if (r >= 0) 224 win->special_cb(r); 225 } 226 } 227 redraw = 1; 228 break; 229 default: 230 ; /*no-op*/ 231 } 232 233 _eglut->redisplay = redraw; 234} 235 236void 237_eglutNativeEventLoop(void) 238{ 239 while (1) { 240 struct eglut_window *win = _eglut->current; 241 242 next_event(win); 243 244 if (_eglut->redisplay) { 245 _eglut->redisplay = 0; 246 247 if (win->display_cb) 248 win->display_cb(); 249 eglSwapBuffers(_eglut->dpy, win->surface); 250 } 251 } 252} 253