/* $Id$ */ /* Copyright (c) 2006-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 "common.h" /* GWindow */ /* private */ /* types */ struct _GWindow { GWidget * gwidget; /* GWindow */ char * title; bool decorated; bool fullscreen; bool resizable; int width; int height; /* not portable */ Window window; GLXContext context; }; /* prototypes */ static void _gwindow_hide(GWindow * gwindow); static void _gwindow_show(GWindow * gwindow); /* public */ /* functions */ /* gwindow_new */ GWindow * gwindow_new(void) { Display * display; XVisualInfo * visual; GWindow * gwindow; XSetWindowAttributes attr; Atom a; if((gwindow = malloc(sizeof(*gwindow))) == NULL) return NULL; /* FIXME report */ if((gwindow->gwidget = gwidget_new()) == NULL) { free(gwindow); return NULL; } gwidget_set_self(gwindow->gwidget, gwindow); gwidget_set_handler(gwindow->gwidget, GWIDGET_HANDLER_HIDE, _gwindow_hide); gwidget_set_handler(gwindow->gwidget, GWIDGET_HANDLER_SHOW, _gwindow_show); gwindow->title = NULL; gwindow->decorated = true; gwindow->fullscreen = false; gwindow->resizable = true; gwindow->width = -1; gwindow->height = -1; display = gtoolkit_get_display(); visual = gtoolkit_get_visual(); attr.colormap = gtoolkit_get_colormap(); attr.border_pixel = 0; attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask; gwindow->window = XCreateWindow(display, RootWindow(display, visual->screen), 0, 0, (gwindow->width > 0) ? gwindow->width : 200, (gwindow->height > 0) ? gwindow->height : 200, 0, visual->depth, InputOutput, visual->visual, CWBorderPixel | CWColormap | CWEventMask, &attr); gwindow->context = glXCreateContext(display, visual, 0, GL_TRUE); a = XInternAtom(display, "WM_DELETE_WINDOW", True); XSetWMProtocols(display, gwindow->window, &a, 1); gtoolkit_register_window(gwindow); return gwindow; } /* gwindow_delete */ void gwindow_delete(GWindow * gwindow) { gtoolkit_deregister_window(gwindow); glXDestroyContext(gtoolkit_get_display(), gwindow->context); free(gwindow->title); free(gwindow); } /* accessors */ /* gwindow_get_decorated */ bool gwindow_get_decorated(GWindow * gwindow) { return gwindow->decorated; } /* gwindow_get_modal */ bool gwindow_get_modal(GWindow * gwindow) { return false; } /* gwindow_get_resizable */ bool gwindow_get_resizable(GWindow * gwindow) { return gwindow->resizable; } /* gwindow_get_size */ void gwindow_get_size(GWindow * gwindow, int * width, int * height) { if(width != NULL) *width = gwindow->width; if(height != NULL) *height = gwindow->height; } /* gwindow_get_title */ char const * gwindow_get_title(GWindow * gwindow) { return gwindow->title; } /* gwindow_get_window */ Window gwindow_get_window(GWindow * gwindow) { return gwindow->window; } /* gwindow_set_resizable */ void gwindow_set_resizable(GWindow * gwindow, bool resizable) { /* FIXME really implement */ gwindow->resizable = resizable; } /* gwindow_set_title */ void gwindow_set_title(GWindow * gwindow, char const * title) { Display * display; display = gtoolkit_get_display(); free(gwindow->title); title = (title != NULL) ? title : "(untitled)"; /* XXX ignore errors */ gwindow->title = strdup(title); if(!gwindow->fullscreen) XSetStandardProperties(display, gwindow->window, title, title, None, NULL, 0, NULL); } /* useful */ /* gwindow_event_configure */ void gwindow_event_configure(GWindow * gwindow, XConfigureEvent * event) { unsigned int width; unsigned int height; if(event->width == gwindow->width && event->height == gwindow->height) return; if((gwindow->width = event->width) < 0) width = 0; if((gwindow->height = event->height) < 1) height = 1; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); } /* gwindow_event_expose */ void gwindow_event_expose(GWindow * gwindow, XExposeEvent * event) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); /* FIXME redraw the window */ glXSwapBuffers(event->display, gwindow->window); } /* gwindow_move */ void gwindow_move(GWindow * gwindow, int x, int y) { /* XXX may fail */ XMoveWindow(gtoolkit_get_display(), gwindow->window, x, y); } /* gwindow_present */ void gwindow_present(GWindow * gwindow) { XMapRaised(gtoolkit_get_display(), gwindow->window); } /* gwindow_resize */ void gwindow_resize(GWindow * gwindow, int width, int height) { /* XXX may fail */ XResizeWindow(gtoolkit_get_display(), gwindow->window, (width > 0) ? width : 1, (height > 0) ? height : 1); } /* private */ /* functions */ /* gwindow_hide */ static void _gwindow_hide(GWindow * gwindow) { XUnmapWindow(gtoolkit_get_display(), gwindow->window); } /* gwindow_show */ static void _gwindow_show(GWindow * gwindow) /* FIXME accept flags (focus...) */ { Display * display; display = gtoolkit_get_display(); XMapWindow(display, gwindow->window); glXMakeCurrent(display, gwindow->window, gwindow->context); }