64d007575bf2e9dc6310e057c27a0fdecc5849f9
[gltest.git] / glwindow.cpp
1 /* gltest - small OpenGL tearing test program
2  * Copyright (C) 2012-2013 Ralf Jung <post@ralfj.de>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "glwindow.h"
20 #include "glutil.h"
21
22 #include <assert.h>
23 #include <X11/Xutil.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 GLWindow::~GLWindow()
28 {
29         delete backend;
30         if (window)
31                 XDestroyWindow(display, window);
32         XCloseDisplay(display);
33 }
34
35 void GLWindow::create(unsigned int width, unsigned int height)
36 {
37         assert(!window);
38         // get visual from backend
39         XVisualInfo vinfo_template;
40         vinfo_template.visualid = backend->initialize(display);
41         int num_vinfo;
42         XVisualInfo *vi = XGetVisualInfo(display, VisualIDMask, &vinfo_template, &num_vinfo);
43         assert(num_vinfo == 1 && vi != NULL);
44         // set winattrs
45         XSetWindowAttributes winAttr;
46         winAttr.colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone);
47         winAttr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;                                                 
48         winAttr.border_pixel = 0;
49         // create window
50         printf("Initial window size: %dx%d\n", width, height);
51         // create a window in window mode
52         window = XCreateWindow(display, RootWindow(display, vi->screen),
53                 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
54                 CWBorderPixel | CWColormap | CWEventMask, &winAttr);
55         /* handle wm_delete_events */
56         Atom wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", True);
57         XMapRaised(display, window);
58         XSetWMProtocols(display, window, &wmDelete, 1);
59         // done
60         this->fullscreen = false;
61         this->width = width;
62         this->height = height;
63         backend->createContext(window);
64         printf("Using GL version: %s\n", glGetString(GL_VERSION));
65         initGL();
66         resizeGL(width, height);
67 }
68
69 void GLWindow::close()
70 {
71         if (!window) return;
72         XEvent ev;
73         memset(&ev, 0, sizeof (ev));
74         ev.xclient.type = ClientMessage;
75         ev.xclient.window = window;
76         ev.xclient.message_type = XInternAtom(display, "WM_PROTOCOLS", true);
77         ev.xclient.format = 32;
78         ev.xclient.data.l[0] = XInternAtom(display, "WM_DELETE_WINDOW", false);
79         ev.xclient.data.l[1] = CurrentTime;
80         XSendEvent(display, window, False, NoEventMask, &ev);
81 }
82
83 void GLWindow::setFullscreen(bool fullscreen)
84 {
85         assert(window);
86         // set fullscreen property
87         XEvent e;
88         e.xclient.type         = ClientMessage;
89         e.xclient.window       = window;
90         e.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", true);
91         e.xclient.format = 32;
92         e.xclient.data.l[0] = 2;    // _NET_WM_STATE_TOGGLE
93         e.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", fullscreen);
94         e.xclient.data.l[2] = 0;    // no second property to toggle
95         e.xclient.data.l[3] = 1;
96         e.xclient.data.l[4] = 0;
97         XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &e);
98 }
99
100 void GLWindow::exec()
101 {
102         while (true)                            
103         {                                        
104                 /* handle the events in the queue */ 
105                 while (XPending(display) > 0)        
106                 {
107                         XEvent event;
108                         XNextEvent(display, &event);     
109                         switch (event.type)              
110                         {
111                                 case Expose:
112                                         renderGL();
113                                         break;
114                                 case ConfigureNotify:
115                                         if (event.xconfigure.width != this->width || event.xconfigure.height != this->height) {
116                                                 printf("Window resized to: %dx%d\n", event.xconfigure.width, event.xconfigure.height);
117                                                 this->width = event.xconfigure.width;
118                                                 this->height = event.xconfigure.height;
119                                                 resizeGL(this->width, this->height);
120                                         }
121                                         break;
122                                 case KeyPress:
123                                         handleKeyPress(XLookupKeysym(&event.xkey, 0));
124                                         break;
125                                 case ClientMessage:
126                                         if (strcmp(XGetAtomName(display, event.xclient.message_type), "WM_PROTOCOLS") == 0 &&
127                                                 strcmp(XGetAtomName(display, event.xclient.data.l[0]), "WM_DELETE_WINDOW") == 0)
128                                         {
129                                                 return;
130                                         }
131                                         break;
132                                 default:
133                                         break;
134                         }
135                 }
136                 renderGL();
137         }
138 }