1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief X11 utilities.
22 *//*--------------------------------------------------------------------*/
25 #include "gluRenderConfig.hpp"
28 #include <X11/Xutil.h>
35 EventState::EventState (void)
40 EventState::~EventState (void)
44 void EventState::setQuitFlag (bool quit)
46 de::ScopedLock lock(m_mutex);
50 bool EventState::getQuitFlag (void)
52 de::ScopedLock lock(m_mutex);
56 DisplayBase::DisplayBase (EventState& platform)
57 : m_eventState (platform)
61 DisplayBase::~DisplayBase (void)
65 WindowBase::WindowBase ()
70 WindowBase::~WindowBase (void)
74 XlibDisplay::XlibDisplay (EventState& eventState, const char* name)
75 : DisplayBase (eventState)
77 m_display = XOpenDisplay((char*)name); // Won't modify argument string.
79 throw ResourceError("Failed to open display", name, __FILE__, __LINE__);
81 m_deleteAtom = XInternAtom(m_display, "WM_DELETE_WINDOW", False);
84 XlibDisplay::~XlibDisplay (void)
86 XCloseDisplay(m_display);
89 void XlibDisplay::processEvents (void)
93 while (XPending(m_display))
95 XNextEvent(m_display, &event);
97 // \todo [2010-10-27 pyry] Handle ConfigureNotify?
98 if (event.type == ClientMessage && (unsigned)event.xclient.data.l[0] == m_deleteAtom)
99 m_eventState.setQuitFlag(true);
103 bool XlibDisplay::getVisualInfo (VisualID visualID, XVisualInfo& dst)
106 query.visualid = visualID;
108 XVisualInfo* response = XGetVisualInfo(m_display, VisualIDMask, &query, &numVisuals);
111 if (response != DE_NULL)
113 if (numVisuals > 0) // should be 1, but you never know...
124 ::Visual* XlibDisplay::getVisual (VisualID visualID)
128 if (getVisualInfo(visualID, info))
134 XlibWindow::XlibWindow (XlibDisplay& display, int width, int height, ::Visual* visual)
136 , m_display (display)
140 XSetWindowAttributes swa;
141 ::Display* const dpy = m_display.getXDisplay();
142 ::Window root = DefaultRootWindow(dpy);
143 unsigned long mask = CWBorderPixel | CWEventMask;
145 // If redirect is enabled, window size can't be guaranteed and it is up to
146 // the window manager to decide whether to honor sizing requests. However,
147 // overriding that causes window to appear as an overlay, which causes
148 // other issues, so this is disabled by default.
149 const bool overrideRedirect = false;
151 if (overrideRedirect)
153 mask |= CWOverrideRedirect;
154 swa.override_redirect = true;
157 if (visual == DE_NULL)
158 visual = CopyFromParent;
161 XVisualInfo info = XVisualInfo();
162 bool succ = display.getVisualInfo(XVisualIDFromVisual(visual), info);
164 TCU_CHECK_INTERNAL(succ);
166 root = RootWindow(dpy, info.screen);
167 m_colormap = XCreateColormap(dpy, root, visual, AllocNone);
168 swa.colormap = m_colormap;
172 swa.border_pixel = 0;
173 swa.event_mask = ExposureMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask;
175 if (width == glu::RenderConfig::DONT_CARE)
176 width = DEFAULT_WINDOW_WIDTH;
177 if (height == glu::RenderConfig::DONT_CARE)
178 height = DEFAULT_WINDOW_HEIGHT;
180 m_window = XCreateWindow(dpy, root, 0, 0, width, height, 0,
181 CopyFromParent, InputOutput, visual, mask, &swa);
184 Atom deleteAtom = m_display.getDeleteAtom();
185 XSetWMProtocols(dpy, m_window, &deleteAtom, 1);
189 void XlibWindow::setVisibility (bool visible)
191 ::Display* dpy = m_display.getXDisplay();
192 int eventType = None;
195 if (visible == m_visible)
200 XMapWindow(dpy, m_window);
201 eventType = MapNotify;
205 XUnmapWindow(dpy, m_window);
206 eventType = UnmapNotify;
209 // We are only interested about exposure/structure notify events, not user input
210 XSelectInput(dpy, m_window, ExposureMask | StructureNotifyMask);
214 XNextEvent(dpy, &event);
215 } while (event.type != eventType);
220 void XlibWindow::getDimensions (int* width, int* height) const
224 unsigned width_, height_, borderWidth, depth;
226 XGetGeometry(m_display.getXDisplay(), m_window, &root, &x, &y, &width_, &height_, &borderWidth, &depth);
227 if (width != DE_NULL)
228 *width = static_cast<int>(width_);
229 if (height != DE_NULL)
230 *height = static_cast<int>(height_);
233 void XlibWindow::setDimensions (int width, int height)
235 const unsigned int mask = CWWidth | CWHeight;
236 XWindowChanges changes;
237 ::Display* dpy = m_display.getXDisplay();
239 changes.width = width;
240 changes.height = height;
241 XConfigureWindow(dpy, m_window, mask, &changes);
246 XNextEvent(dpy, &myevent);
247 if (myevent.type == ConfigureNotify)
252 void XlibWindow::processEvents (void)
254 // A bit of a hack, since we don't really handle all the events.
255 m_display.processEvents();
258 XlibWindow::~XlibWindow (void)
260 XDestroyWindow(m_display.getXDisplay(), m_window);
261 if (m_colormap != None)
262 XFreeColormap(m_display.getXDisplay(), m_colormap);