/* $Id$ */ /* Copyright (c) 2004-2020 Pierre Pronchery */ /* This file is part of DeforaOS Graphics GToolkit */ /* All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "GToolkit/GWindow.h" #include "common.h" /* GToolkit */ /* private */ /* types */ typedef struct _GToolkit { int init; /* main loop */ unsigned int loop; GWindow ** windows; size_t windows_cnt; /* not portable */ Display * display; int screen; XVisualInfo * visual; Colormap colormap; } GToolkit; /* variables */ static GToolkit _gt; /* prototypes */ /* accessors */ static GWindow * _gtoolkit_get_gwindow(Window window); /* useful */ static int _gtoolkit_error(char const * message, int ret); /* public */ /* functions */ /* accessors */ Colormap gtoolkit_get_colormap(void) { return _gt.colormap; } /* gtoolkit_get_display */ Display * gtoolkit_get_display(void) { return _gt.display; } /* gtoolkit_get_visual */ XVisualInfo * gtoolkit_get_visual(void) { return _gt.visual; } /* useful */ /* gtoolkit_register_window */ void gtoolkit_deregister_window(GWindow * gwindow) { size_t i; /* FIXME free memory if possible */ for(i = 0; i < _gt.windows_cnt; i++) if(_gt.windows[i] == gwindow) { _gt.windows[i] = NULL; return; } } /* gtoolkit_init */ int gtoolkit_init(void) { int attrd[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, None }; int attrs[] = { GLX_RGBA, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, None }; if(_gt.init != 0) return 0; if((_gt.display = XOpenDisplay(NULL)) == NULL) return _gtoolkit_error("Could not open display", 1); _gt.screen = DefaultScreen(_gt.display); if((_gt.visual = glXChooseVisual(_gt.display, _gt.screen, attrd)) == NULL) _gt.visual = glXChooseVisual(_gt.display, _gt.screen, attrs); if(_gt.visual == NULL) return _gtoolkit_error("Could not choose visual", 1); _gt.colormap = XCreateColormap(_gt.display, RootWindow(_gt.display, _gt.screen), _gt.visual->visual, AllocNone); _gt.loop = 0; _gt.init = 1; return 0; } /* gtoolkit_main */ static void _main_event(void); static void _main_event_configure(XConfigureEvent * event); static void _main_event_expose(XExposeEvent * event); void gtoolkit_main(void) { size_t i; for(_gt.loop++; _gt.loop >= 1;) while(XPending(_gt.display) > 0) _main_event(); for(i = 0; i < _gt.windows_cnt; i++) if(_gt.windows[i] != NULL) gwindow_delete(_gt.windows[i]); XCloseDisplay(_gt.display); memset(&_gt, 0, sizeof(_gt)); } static void _main_event(void) { XEvent event; XNextEvent(_gt.display, &event); switch(event.type) { case ConfigureNotify: _main_event_configure(&event.xconfigure); break; case Expose: _main_event_expose(&event.xexpose); break; case ClientMessage: case KeyPress: case KeyRelease: default: #ifdef DEBUG fprintf(stderr, "DEBUG: %s() Event %d\n", __func__, event.type); #endif break; } } static void _main_event_configure(XConfigureEvent * event) { GWindow * gwindow; if((gwindow = _gtoolkit_get_gwindow(event->window)) == NULL) return; gwindow_event_configure(gwindow, event); } static void _main_event_expose(XExposeEvent * event) { GWindow * gwindow; if((gwindow = _gtoolkit_get_gwindow(event->window)) == NULL) return; gwindow_event_expose(gwindow, event); } /* gtoolkit_main_quit */ void gtoolkit_main_quit(void) { if(_gt.init == 0) return; if(_gt.loop > 0) _gt.loop--; } /* gtoolkit_register_window */ void gtoolkit_register_window(GWindow * gwindow) { GWindow ** p; /* FIXME look for an empty spot first */ if((p = realloc(_gt.windows, sizeof(*p) * _gt.windows_cnt + 1)) == NULL) /* XXX ignore errors */ return; _gt.windows = p; _gt.windows[_gt.windows_cnt++] = gwindow; } /* private */ /* accessors */ /* gtoolkit_get_gwindow */ static GWindow * _gtoolkit_get_gwindow(Window window) { size_t i; for(i = 0; i < _gt.windows_cnt; i++) if(_gt.windows[i] != NULL && gwindow_get_window(_gt.windows[i]) == window) return _gt.windows[i]; /* XXX report error */ return NULL; } /* useful */ /* gtoolkit_error */ static int _gtoolkit_error(char const * message, int ret) { fprintf(stderr, "%s%s\n", "GToolkit: ", message); return ret; }