13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Tester Core
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ----------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief X11 utilities.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuX11.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderConfig.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <X11/Xutil.h>
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace tcu
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace x11
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DEFAULT_WINDOW_WIDTH	= 400,
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DEFAULT_WINDOW_HEIGHT	= 300
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko PoyryEventState::EventState (void)
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_quit(false)
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryEventState::~EventState (void)
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid EventState::setQuitFlag (bool quit)
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::ScopedLock lock(m_mutex);
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_quit = quit;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool EventState::getQuitFlag (void)
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::ScopedLock lock(m_mutex);
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_quit;
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
623c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDisplay::Display (EventState& eventState, const char* name)
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_eventState	(eventState)
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_display		(DE_NULL)
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_deleteAtom	(DE_NULL)
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_display = XOpenDisplay((char*)name); // Won't modify argument string.
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_display)
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw ResourceError("Failed to open display", name, __FILE__, __LINE__);
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_deleteAtom	= XInternAtom(m_display, "WM_DELETE_WINDOW", False);
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDisplay::~Display (void)
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XCloseDisplay(m_display);
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Display::processEvents (void)
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XEvent	event;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (XPending(m_display))
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XNextEvent(m_display, &event);
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \todo [2010-10-27 pyry] Handle ConfigureNotify?
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (event.type == ClientMessage && (unsigned)event.xclient.data.l[0] == m_deleteAtom)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_eventState.setQuitFlag(true);
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool Display::getVisualInfo (VisualID visualID, XVisualInfo& dst)
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XVisualInfo		query;
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	query.visualid = visualID;
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numVisuals	= 0;
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XVisualInfo*	response	= XGetVisualInfo(m_display, VisualIDMask, &query, &numVisuals);
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool			succ		= false;
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (response != DE_NULL)
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (numVisuals > 0) // should be 1, but you never know...
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst = response[0];
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			succ = true;
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XFree(response);
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return succ;
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry::Visual* Display::getVisual (VisualID visualID)
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XVisualInfo		info;
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (getVisualInfo(visualID, info))
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return info.visual;
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_NULL;
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryWindow::Window (Display& display, int width, int height, ::Visual* visual)
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_display		(display)
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_colormap	(None)
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_window		(None)
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_visible		(false)
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XSetWindowAttributes	swa;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	::Display*				dpy	= m_display.getXDisplay();
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	::Window				root = DefaultRootWindow(dpy);
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	unsigned long			mask = CWBorderPixel | CWEventMask;
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (visual == DE_NULL)
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		visual = CopyFromParent;
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XVisualInfo	info	= XVisualInfo();
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool		succ	= display.getVisualInfo(XVisualIDFromVisual(visual), info);
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_CHECK_INTERNAL(succ);
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		root				= RootWindow(dpy, info.screen);
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_colormap			= XCreateColormap(dpy, root, visual, AllocNone);
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		swa.colormap		= m_colormap;
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		mask |= CWColormap;
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	swa.border_pixel	= 0;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	swa.event_mask		= ExposureMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask;
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mask |= CWOverrideRedirect;
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	swa.override_redirect = true;
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (width == glu::RenderConfig::DONT_CARE)
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		width = DEFAULT_WINDOW_WIDTH;
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (height == glu::RenderConfig::DONT_CARE)
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		height = DEFAULT_WINDOW_HEIGHT;
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_window = XCreateWindow(dpy, root, 0, 0, width, height, 0,
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 CopyFromParent, InputOutput, visual, mask, &swa);
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(m_window);
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Atom deleteAtom = m_display.getDeleteAtom();
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XSetWMProtocols(dpy, m_window, &deleteAtom, 1);
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Window::setVisibility (bool visible)
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	::Display*	dpy			= m_display.getXDisplay();
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			eventType	= None;
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XEvent		event;
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (visible == m_visible)
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (visible)
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XMapWindow(dpy, m_window);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		eventType = MapNotify;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XUnmapWindow(dpy, m_window);
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		eventType = UnmapNotify;
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// We are only interested about exposure/structure notify events, not user input
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XSelectInput(dpy, m_window, ExposureMask | StructureNotifyMask);
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	do
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XNextEvent(dpy, &event);
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} while (event.type != eventType);
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_visible = visible;
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Window::getDimensions (int* width, int* height) const
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int x, y;
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	::Window root;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	unsigned width_, height_, borderWidth, depth;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XGetGeometry(m_display.getXDisplay(), m_window, &root, &x, &y, &width_, &height_, &borderWidth, &depth);
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (width != DE_NULL)
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*width = static_cast<int>(width_);
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (height != DE_NULL)
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*height = static_cast<int>(height_);
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Window::setDimensions (int width, int height)
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const unsigned int	mask = CWWidth | CWHeight;
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XWindowChanges		changes;
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	changes.width		= width;
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	changes.height		= height;
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XConfigureWindow(m_display.getXDisplay(), m_window, mask, &changes);
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Window::processEvents (void)
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// A bit of a hack, since we don't really handle all the events.
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_display.processEvents();
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2303c827367444ee418f129b2c238299f49d3264554Jarkko PoyryWindow::~Window (void)
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	XDestroyWindow(m_display.getXDisplay(), m_window);
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_colormap != None)
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		XFreeColormap(m_display.getXDisplay(), m_colormap);
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // x11
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // tcu
239