ca6dbb95018d91fa416360a542fe32edc1c0ac33
[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
21 #include <assert.h>
22 #include <X11/Xutil.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 GLWindow::~GLWindow()
27 {
28         delete backend;
29         if (window)
30                 XDestroyWindow(display, window);
31         XCloseDisplay(display);
32 }
33
34 void GLWindow::create(unsigned int width, unsigned int height)
35 {
36         assert(!window);
37         // get visual from backend
38         XVisualInfo vinfo_template;
39         vinfo_template.visualid = backend->initialize(display);
40         int num_vinfo;
41         XVisualInfo *vi = XGetVisualInfo(display, VisualIDMask, &vinfo_template, &num_vinfo);
42         assert(num_vinfo == 1 && vi != NULL);
43         // set winattrs
44         XSetWindowAttributes winAttr;
45         winAttr.colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone);
46         winAttr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;                                                 
47         winAttr.border_pixel = 0;
48         // create window
49         printf("Initial window size: %dx%d\n", width, height);
50         // create a window in window mode
51         window = XCreateWindow(display, RootWindow(display, vi->screen),
52                 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
53                 CWBorderPixel | CWColormap | CWEventMask, &winAttr);
54         /* handle wm_delete_events */
55         Atom wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", True);
56         XMapRaised(display, window);
57         XSetWMProtocols(display, window, &wmDelete, 1);
58         // done
59         this->fullscreen = false;
60         this->width = width;
61         this->height = height;
62         backend->createContext(window);
63         initGL();
64         resizeGL(width, height);
65 }
66
67 void GLWindow::close()
68 {
69         if (!window) return;
70         XEvent ev;
71         memset(&ev, 0, sizeof (ev));
72         ev.xclient.type = ClientMessage;
73         ev.xclient.window = window;
74         ev.xclient.message_type = XInternAtom(display, "WM_PROTOCOLS", true);
75         ev.xclient.format = 32;
76         ev.xclient.data.l[0] = XInternAtom(display, "WM_DELETE_WINDOW", false);
77         ev.xclient.data.l[1] = CurrentTime;
78         XSendEvent(display, window, False, NoEventMask, &ev);
79 }
80
81 void GLWindow::setFullscreen(bool fullscreen)
82 {
83         assert(window);
84         // set fullscreen property
85         XEvent e;
86         e.xclient.type         = ClientMessage;
87         e.xclient.window       = window;
88         e.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", true);
89         e.xclient.format = 32;
90         e.xclient.data.l[0] = 2;    // _NET_WM_STATE_TOGGLE
91         e.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", fullscreen);
92         e.xclient.data.l[2] = 0;    // no second property to toggle
93         e.xclient.data.l[3] = 1;
94         e.xclient.data.l[4] = 0;
95         XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &e);
96 }
97
98 void GLWindow::exec()
99 {
100         while (true)                            
101         {                                        
102                 /* handle the events in the queue */ 
103                 while (XPending(display) > 0)        
104                 {
105                         XEvent event;
106                         XNextEvent(display, &event);     
107                         switch (event.type)              
108                         {
109                                 case Expose:
110                                         renderGL();
111                                         break;
112                                 case ConfigureNotify:
113                                         if (event.xconfigure.width != this->width || event.xconfigure.height != this->height) {
114                                                 printf("Window resized to: %dx%d\n", event.xconfigure.width, event.xconfigure.height);
115                                                 this->width = event.xconfigure.width;
116                                                 this->height = event.xconfigure.height;
117                                                 resizeGL(this->width, this->height);
118                                         }
119                                         break;
120                                 case KeyPress:
121                                         handleKeyPress(XLookupKeysym(&event.xkey, 0));
122                                         break;
123                                 case ClientMessage:
124                                         if (strcmp(XGetAtomName(display, event.xclient.message_type), "WM_PROTOCOLS") == 0 &&
125                                                 strcmp(XGetAtomName(display, event.xclient.data.l[0]), "WM_DELETE_WINDOW") == 0)
126                                         {
127                                                 return;
128                                         }
129                                         break;
130                                 default:
131                                         break;
132                         }
133                 }
134                 renderGL();
135         }
136 }