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