diff options
author | Hoe Hao Cheng <haochengho12907@gmail.com> | 2023-03-25 22:06:51 +0800 |
---|---|---|
committer | Erik Faye-Lund <erik.faye-lund@collabora.com> | 2023-04-04 19:56:58 +0000 |
commit | 4b5cc75a1e6f164e825bcd1472bff0854f5cb2fd (patch) | |
tree | 3dc4d14d0f90671ae03834fb42c7fc580256907b | |
parent | 609db1ba91cf5f338d3ba87cf0a002e4c787ca8b (diff) | |
download | mesa-demos-4b5cc75a1e6f164e825bcd1472bff0854f5cb2fd.tar.gz |
eglut/wsi: introduce X11 WSI
Similar to the Wayland commit - renaming, making things static, and adding
a new x11_wsi_interface() function.
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
-rw-r--r-- | src/egl/eglut/wsi/x11.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/src/egl/eglut/wsi/x11.c b/src/egl/eglut/wsi/x11.c new file mode 100644 index 00000000..2c65c026 --- /dev/null +++ b/src/egl/eglut/wsi/x11.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> + +#include "eglutint.h" +#include "wsi.h" + +static void +init_display(void) +{ + _eglut->native_dpy = XOpenDisplay(_eglut->display_name); + if (!_eglut->native_dpy) + _eglutFatal("failed to initialize native display"); + + _eglut->surface_type = EGL_WINDOW_BIT; +} + +static void +fini_display(void) +{ + XCloseDisplay(_eglut->native_dpy); +} + +static void +init_window(struct eglut_window *win, const char *title, + int x, int y, int w, int h) +{ + XVisualInfo *visInfo, visTemplate; + int num_visuals; + Window root, xwin; + XSetWindowAttributes attr; + unsigned long mask; + EGLint vid; + + if (!eglGetConfigAttrib(_eglut->dpy, + win->config, EGL_NATIVE_VISUAL_ID, &vid)) + _eglutFatal("failed to get visual id"); + + /* The X window visual must match the EGL config */ + visTemplate.visualid = vid; + visInfo = XGetVisualInfo(_eglut->native_dpy, + VisualIDMask, &visTemplate, &num_visuals); + if (!visInfo) + _eglutFatal("failed to get an visual of id 0x%x", vid); + + root = RootWindow(_eglut->native_dpy, DefaultScreen(_eglut->native_dpy)); + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap(_eglut->native_dpy, + root, visInfo->visual, AllocNone); + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + xwin = XCreateWindow(_eglut->native_dpy, root, x, y, w, h, + 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr); + if (!xwin) + _eglutFatal("failed to create a window"); + + XFree(visInfo); + + /* set hints and properties */ + { + XSizeHints sizehints; + sizehints.x = x; + sizehints.y = y; + sizehints.width = w; + sizehints.height = h; + sizehints.flags = USSize | USPosition; + XSetNormalHints(_eglut->native_dpy, xwin, &sizehints); + XSetStandardProperties(_eglut->native_dpy, xwin, + title, title, None, (char **) NULL, 0, &sizehints); + } + + XMapWindow(_eglut->native_dpy, xwin); + + win->native.u.window = xwin; + win->native.width = w; + win->native.height = h; +} + +static void +fini_window(struct eglut_window *win) +{ + XDestroyWindow(_eglut->native_dpy, win->native.u.window); +} + +static int +lookup_keysym(KeySym sym) +{ + int special; + + switch (sym) { + case XK_F1: + special = EGLUT_KEY_F1; + break; + case XK_F2: + special = EGLUT_KEY_F2; + break; + case XK_F3: + special = EGLUT_KEY_F3; + break; + case XK_F4: + special = EGLUT_KEY_F4; + break; + case XK_F5: + special = EGLUT_KEY_F5; + break; + case XK_F6: + special = EGLUT_KEY_F6; + break; + case XK_F7: + special = EGLUT_KEY_F7; + break; + case XK_F8: + special = EGLUT_KEY_F8; + break; + case XK_F9: + special = EGLUT_KEY_F9; + break; + case XK_F10: + special = EGLUT_KEY_F10; + break; + case XK_F11: + special = EGLUT_KEY_F11; + break; + case XK_F12: + special = EGLUT_KEY_F12; + break; + case XK_KP_Left: + case XK_Left: + special = EGLUT_KEY_LEFT; + break; + case XK_KP_Up: + case XK_Up: + special = EGLUT_KEY_UP; + break; + case XK_KP_Right: + case XK_Right: + special = EGLUT_KEY_RIGHT; + break; + case XK_KP_Down: + case XK_Down: + special = EGLUT_KEY_DOWN; + break; + default: + special = -1; + break; + } + + return special; +} + +static void +next_event(struct eglut_window *win) +{ + int redraw = 0; + XEvent event; + + if (!XPending(_eglut->native_dpy)) { + /* there is an idle callback */ + if (_eglut->idle_cb) { + _eglut->idle_cb(); + return; + } + + /* the app requests re-display */ + if (_eglut->redisplay) + return; + } + + /* block for next event */ + XNextEvent(_eglut->native_dpy, &event); + + switch (event.type) { + case Expose: + redraw = 1; + break; + case ConfigureNotify: + win->native.width = event.xconfigure.width; + win->native.height = event.xconfigure.height; + if (win->reshape_cb) + win->reshape_cb(win->native.width, win->native.height); + break; + case KeyPress: + { + char buffer[1]; + KeySym sym; + int r; + + r = XLookupString(&event.xkey, + buffer, sizeof(buffer), &sym, NULL); + if (r && win->keyboard_cb) { + win->keyboard_cb(buffer[0]); + } + else if (!r && win->special_cb) { + r = lookup_keysym(sym); + if (r >= 0) + win->special_cb(r); + } + } + redraw = 1; + break; + default: + ; /*no-op*/ + } + + _eglut->redisplay = redraw; +} + +static void +event_loop(void) +{ + while (1) { + struct eglut_window *win = _eglut->current; + + next_event(win); + + if (_eglut->redisplay) { + _eglut->redisplay = 0; + + if (win->display_cb) + win->display_cb(); + eglSwapBuffers(_eglut->dpy, win->surface); + } + } +} + +struct eglut_wsi_interface +x11_wsi_interface(void) +{ + return (struct eglut_wsi_interface) { + .init_display = init_display, + .fini_display = fini_display, + .init_window = init_window, + .fini_window = fini_window, + .event_loop = event_loop, + }; +} |