132001f49Smrg/* 232001f49Smrg * Copyright (C) 2010 LunarG Inc. 332001f49Smrg * 432001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a 532001f49Smrg * copy of this software and associated documentation files (the "Software"), 632001f49Smrg * to deal in the Software without restriction, including without limitation 732001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 832001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the 932001f49Smrg * Software is furnished to do so, subject to the following conditions: 1032001f49Smrg * 1132001f49Smrg * The above copyright notice and this permission notice shall be included 1232001f49Smrg * in all copies or substantial portions of the Software. 1332001f49Smrg * 1432001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1532001f49Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1632001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1732001f49Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1832001f49Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1932001f49Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2032001f49Smrg * DEALINGS IN THE SOFTWARE. 2132001f49Smrg * 2232001f49Smrg * Authors: 2332001f49Smrg * Chia-I Wu <olv@lunarg.com> 2432001f49Smrg */ 2532001f49Smrg 2632001f49Smrg#include <X11/Xlib.h> 2732001f49Smrg#include <X11/Xutil.h> 2832001f49Smrg#include <X11/keysym.h> 2932001f49Smrg 3032001f49Smrg#include "eglutint.h" 3132001f49Smrg 3232001f49Smrgvoid 3332001f49Smrg_eglutNativeInitDisplay(void) 3432001f49Smrg{ 3532001f49Smrg _eglut->native_dpy = XOpenDisplay(_eglut->display_name); 3632001f49Smrg if (!_eglut->native_dpy) 3732001f49Smrg _eglutFatal("failed to initialize native display"); 3832001f49Smrg 3932001f49Smrg _eglut->surface_type = EGL_WINDOW_BIT; 4032001f49Smrg} 4132001f49Smrg 4232001f49Smrgvoid 4332001f49Smrg_eglutNativeFiniDisplay(void) 4432001f49Smrg{ 4532001f49Smrg XCloseDisplay(_eglut->native_dpy); 4632001f49Smrg} 4732001f49Smrg 4832001f49Smrgvoid 4932001f49Smrg_eglutNativeInitWindow(struct eglut_window *win, const char *title, 5032001f49Smrg int x, int y, int w, int h) 5132001f49Smrg{ 5232001f49Smrg XVisualInfo *visInfo, visTemplate; 5332001f49Smrg int num_visuals; 5432001f49Smrg Window root, xwin; 5532001f49Smrg XSetWindowAttributes attr; 5632001f49Smrg unsigned long mask; 5732001f49Smrg EGLint vid; 5832001f49Smrg 5932001f49Smrg if (!eglGetConfigAttrib(_eglut->dpy, 6032001f49Smrg win->config, EGL_NATIVE_VISUAL_ID, &vid)) 6132001f49Smrg _eglutFatal("failed to get visual id"); 6232001f49Smrg 6332001f49Smrg /* The X window visual must match the EGL config */ 6432001f49Smrg visTemplate.visualid = vid; 6532001f49Smrg visInfo = XGetVisualInfo(_eglut->native_dpy, 6632001f49Smrg VisualIDMask, &visTemplate, &num_visuals); 6732001f49Smrg if (!visInfo) 6832001f49Smrg _eglutFatal("failed to get an visual of id 0x%x", vid); 6932001f49Smrg 7032001f49Smrg root = RootWindow(_eglut->native_dpy, DefaultScreen(_eglut->native_dpy)); 7132001f49Smrg 7232001f49Smrg /* window attributes */ 7332001f49Smrg attr.background_pixel = 0; 7432001f49Smrg attr.border_pixel = 0; 7532001f49Smrg attr.colormap = XCreateColormap(_eglut->native_dpy, 7632001f49Smrg root, visInfo->visual, AllocNone); 7732001f49Smrg attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 7832001f49Smrg mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 7932001f49Smrg 8032001f49Smrg xwin = XCreateWindow(_eglut->native_dpy, root, x, y, w, h, 8132001f49Smrg 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr); 8232001f49Smrg if (!xwin) 8332001f49Smrg _eglutFatal("failed to create a window"); 8432001f49Smrg 8532001f49Smrg XFree(visInfo); 8632001f49Smrg 8732001f49Smrg /* set hints and properties */ 8832001f49Smrg { 8932001f49Smrg XSizeHints sizehints; 9032001f49Smrg sizehints.x = x; 9132001f49Smrg sizehints.y = y; 9232001f49Smrg sizehints.width = w; 9332001f49Smrg sizehints.height = h; 9432001f49Smrg sizehints.flags = USSize | USPosition; 9532001f49Smrg XSetNormalHints(_eglut->native_dpy, xwin, &sizehints); 9632001f49Smrg XSetStandardProperties(_eglut->native_dpy, xwin, 9732001f49Smrg title, title, None, (char **) NULL, 0, &sizehints); 9832001f49Smrg } 9932001f49Smrg 10032001f49Smrg XMapWindow(_eglut->native_dpy, xwin); 10132001f49Smrg 10232001f49Smrg win->native.u.window = xwin; 10332001f49Smrg win->native.width = w; 10432001f49Smrg win->native.height = h; 10532001f49Smrg} 10632001f49Smrg 10732001f49Smrgvoid 10832001f49Smrg_eglutNativeFiniWindow(struct eglut_window *win) 10932001f49Smrg{ 11032001f49Smrg XDestroyWindow(_eglut->native_dpy, win->native.u.window); 11132001f49Smrg} 11232001f49Smrg 11332001f49Smrgstatic int 11432001f49Smrglookup_keysym(KeySym sym) 11532001f49Smrg{ 11632001f49Smrg int special; 11732001f49Smrg 11832001f49Smrg switch (sym) { 11932001f49Smrg case XK_F1: 12032001f49Smrg special = EGLUT_KEY_F1; 12132001f49Smrg break; 12232001f49Smrg case XK_F2: 12332001f49Smrg special = EGLUT_KEY_F2; 12432001f49Smrg break; 12532001f49Smrg case XK_F3: 12632001f49Smrg special = EGLUT_KEY_F3; 12732001f49Smrg break; 12832001f49Smrg case XK_F4: 12932001f49Smrg special = EGLUT_KEY_F4; 13032001f49Smrg break; 13132001f49Smrg case XK_F5: 13232001f49Smrg special = EGLUT_KEY_F5; 13332001f49Smrg break; 13432001f49Smrg case XK_F6: 13532001f49Smrg special = EGLUT_KEY_F6; 13632001f49Smrg break; 13732001f49Smrg case XK_F7: 13832001f49Smrg special = EGLUT_KEY_F7; 13932001f49Smrg break; 14032001f49Smrg case XK_F8: 14132001f49Smrg special = EGLUT_KEY_F8; 14232001f49Smrg break; 14332001f49Smrg case XK_F9: 14432001f49Smrg special = EGLUT_KEY_F9; 14532001f49Smrg break; 14632001f49Smrg case XK_F10: 14732001f49Smrg special = EGLUT_KEY_F10; 14832001f49Smrg break; 14932001f49Smrg case XK_F11: 15032001f49Smrg special = EGLUT_KEY_F11; 15132001f49Smrg break; 15232001f49Smrg case XK_F12: 15332001f49Smrg special = EGLUT_KEY_F12; 15432001f49Smrg break; 15532001f49Smrg case XK_KP_Left: 15632001f49Smrg case XK_Left: 15732001f49Smrg special = EGLUT_KEY_LEFT; 15832001f49Smrg break; 15932001f49Smrg case XK_KP_Up: 16032001f49Smrg case XK_Up: 16132001f49Smrg special = EGLUT_KEY_UP; 16232001f49Smrg break; 16332001f49Smrg case XK_KP_Right: 16432001f49Smrg case XK_Right: 16532001f49Smrg special = EGLUT_KEY_RIGHT; 16632001f49Smrg break; 16732001f49Smrg case XK_KP_Down: 16832001f49Smrg case XK_Down: 16932001f49Smrg special = EGLUT_KEY_DOWN; 17032001f49Smrg break; 17132001f49Smrg default: 17232001f49Smrg special = -1; 17332001f49Smrg break; 17432001f49Smrg } 17532001f49Smrg 17632001f49Smrg return special; 17732001f49Smrg} 17832001f49Smrg 17932001f49Smrgstatic void 18032001f49Smrgnext_event(struct eglut_window *win) 18132001f49Smrg{ 18232001f49Smrg int redraw = 0; 18332001f49Smrg XEvent event; 18432001f49Smrg 18532001f49Smrg if (!XPending(_eglut->native_dpy)) { 18632001f49Smrg /* there is an idle callback */ 18732001f49Smrg if (_eglut->idle_cb) { 18832001f49Smrg _eglut->idle_cb(); 18932001f49Smrg return; 19032001f49Smrg } 19132001f49Smrg 19232001f49Smrg /* the app requests re-display */ 19332001f49Smrg if (_eglut->redisplay) 19432001f49Smrg return; 19532001f49Smrg } 19632001f49Smrg 19732001f49Smrg /* block for next event */ 19832001f49Smrg XNextEvent(_eglut->native_dpy, &event); 19932001f49Smrg 20032001f49Smrg switch (event.type) { 20132001f49Smrg case Expose: 20232001f49Smrg redraw = 1; 20332001f49Smrg break; 20432001f49Smrg case ConfigureNotify: 20532001f49Smrg win->native.width = event.xconfigure.width; 20632001f49Smrg win->native.height = event.xconfigure.height; 20732001f49Smrg if (win->reshape_cb) 20832001f49Smrg win->reshape_cb(win->native.width, win->native.height); 20932001f49Smrg break; 21032001f49Smrg case KeyPress: 21132001f49Smrg { 21232001f49Smrg char buffer[1]; 21332001f49Smrg KeySym sym; 21432001f49Smrg int r; 21532001f49Smrg 21632001f49Smrg r = XLookupString(&event.xkey, 21732001f49Smrg buffer, sizeof(buffer), &sym, NULL); 21832001f49Smrg if (r && win->keyboard_cb) { 21932001f49Smrg win->keyboard_cb(buffer[0]); 22032001f49Smrg } 22132001f49Smrg else if (!r && win->special_cb) { 22232001f49Smrg r = lookup_keysym(sym); 22332001f49Smrg if (r >= 0) 22432001f49Smrg win->special_cb(r); 22532001f49Smrg } 22632001f49Smrg } 22732001f49Smrg redraw = 1; 22832001f49Smrg break; 22932001f49Smrg default: 23032001f49Smrg ; /*no-op*/ 23132001f49Smrg } 23232001f49Smrg 23332001f49Smrg _eglut->redisplay = redraw; 23432001f49Smrg} 23532001f49Smrg 23632001f49Smrgvoid 23732001f49Smrg_eglutNativeEventLoop(void) 23832001f49Smrg{ 23932001f49Smrg while (1) { 24032001f49Smrg struct eglut_window *win = _eglut->current; 24132001f49Smrg 24232001f49Smrg next_event(win); 24332001f49Smrg 24432001f49Smrg if (_eglut->redisplay) { 24532001f49Smrg _eglut->redisplay = 0; 24632001f49Smrg 24732001f49Smrg if (win->display_cb) 24832001f49Smrg win->display_cb(); 24932001f49Smrg eglSwapBuffers(_eglut->dpy, win->surface); 25032001f49Smrg } 25132001f49Smrg } 25232001f49Smrg} 253