/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief X11 utilities.
 *//*--------------------------------------------------------------------*/

#include "tcuLnxX11.hpp"
#include "gluRenderConfig.hpp"
#include "deMemory.h"

#include <X11/Xutil.h>

namespace tcu
{
namespace lnx
{
namespace x11
{

DisplayBase::DisplayBase (EventState& platform)
	: m_eventState	(platform)
{
}

DisplayBase::~DisplayBase (void)
{
}

WindowBase::WindowBase ()
	: m_visible	(false)
{
}

WindowBase::~WindowBase (void)
{
}

XlibDisplay::DisplayState XlibDisplay::s_displayState = XlibDisplay::DISPLAY_STATE_UNKNOWN;

bool XlibDisplay::hasDisplay (const char* name)
{
	if (s_displayState == DISPLAY_STATE_UNKNOWN)
	{
		XInitThreads();
		Display *display = XOpenDisplay((char*)name);
		if (display)
		{
			s_displayState = DISPLAY_STATE_AVAILABLE;
			XCloseDisplay(display);
		} else
			s_displayState = DISPLAY_STATE_UNAVAILABLE;
	}
	return s_displayState == DISPLAY_STATE_AVAILABLE ? true : false;
}

XlibDisplay::XlibDisplay (EventState& eventState, const char* name)
	: DisplayBase	(eventState)
{
	// From man:XinitThreads(3):
	//
	//     The XInitThreads function initializes Xlib support for concurrent
	//     threads.  This function must be the first Xlib function
	//     a multi-threaded program calls, and it must complete before any other
	//     Xlib call is made.
	DE_CHECK_RUNTIME_ERR(XInitThreads() != 0);
	m_display = XOpenDisplay((char*)name); // Won't modify argument string.
	if (!m_display)
		throw ResourceError("Failed to open display", name, __FILE__, __LINE__);

	m_deleteAtom	= XInternAtom(m_display, "WM_DELETE_WINDOW", False);
}

XlibDisplay::~XlibDisplay (void)
{
	XCloseDisplay(m_display);
}

void XlibDisplay::processEvent (XEvent& event)
{
	switch (event.type)
	{
		case ClientMessage:
			if ((unsigned)event.xclient.data.l[0] == m_deleteAtom)
				m_eventState.setQuitFlag(true);
			break;
		// note: ConfigureNotify for window is handled in setDimensions()
		default:
			break;
	}
}

void XlibDisplay::processEvents (void)
{
	XEvent	event;

	while (XPending(m_display))
	{
		XNextEvent(m_display, &event);
		processEvent(event);
	}
}

bool XlibDisplay::getVisualInfo (VisualID visualID, XVisualInfo& dst)
{
	XVisualInfo		query;
	query.visualid = visualID;
	int				numVisuals	= 0;
	XVisualInfo*	response	= XGetVisualInfo(m_display, VisualIDMask, &query, &numVisuals);
	bool			succ		= false;

	if (response != DE_NULL)
	{
		if (numVisuals > 0) // should be 1, but you never know...
		{
			dst = response[0];
			succ = true;
		}
		XFree(response);
	}

	return succ;
}

::Visual* XlibDisplay::getVisual (VisualID visualID)
{
	XVisualInfo		info;

	if (getVisualInfo(visualID, info))
		return info.visual;

	return DE_NULL;
}

XlibWindow::XlibWindow (XlibDisplay& display, int width, int height, ::Visual* visual)
	: WindowBase	()
	, m_display		(display)
	, m_colormap	(None)
	, m_window		(None)
{
	XSetWindowAttributes	swa;
	::Display* const		dpy					= m_display.getXDisplay();
	::Window				root				= DefaultRootWindow(dpy);
	unsigned long			mask				= CWBorderPixel | CWEventMask;

	// If redirect is enabled, window size can't be guaranteed and it is up to
	// the window manager to decide whether to honor sizing requests. However,
	// overriding that causes window to appear as an overlay, which causes
	// other issues, so this is disabled by default.
	const bool				overrideRedirect	= false;

	int depth = CopyFromParent;

	if (overrideRedirect)
	{
		mask |= CWOverrideRedirect;
		swa.override_redirect = true;
	}

	if (visual == DE_NULL)
		visual = CopyFromParent;
	else
	{
		XVisualInfo	info	= XVisualInfo();
		bool		succ	= display.getVisualInfo(XVisualIDFromVisual(visual), info);

		TCU_CHECK_INTERNAL(succ);

		root				= RootWindow(dpy, info.screen);
		m_colormap			= XCreateColormap(dpy, root, visual, AllocNone);
		swa.colormap		= m_colormap;
		mask |= CWColormap;

		depth = info.depth;
	}

	swa.border_pixel	= 0;
	swa.event_mask		= ExposureMask|KeyPressMask|KeyReleaseMask|StructureNotifyMask;

	if (width == glu::RenderConfig::DONT_CARE)
		width = DEFAULT_WINDOW_WIDTH;
	if (height == glu::RenderConfig::DONT_CARE)
		height = DEFAULT_WINDOW_HEIGHT;

	m_window = XCreateWindow(dpy, root, 0, 0, width, height, 0,
							 depth, InputOutput, visual, mask, &swa);
	TCU_CHECK(m_window);

	/* Prevent the window from stealing input, since our windows are
	 * non-interactive.
	 */
	XWMHints *hints = XAllocWMHints();
	hints->flags |= InputHint;
	hints->input = False;
	XSetWMHints(dpy, m_window, hints);
	XFree(hints);

	Atom deleteAtom = m_display.getDeleteAtom();
	XSetWMProtocols(dpy, m_window, &deleteAtom, 1);
	XSync(dpy,false);
}

void XlibWindow::setVisibility (bool visible)
{
	::Display*	dpy			= m_display.getXDisplay();
	int			eventType	= None;
	XEvent		event;

	if (visible == m_visible)
		return;

	if (visible)
	{
		XMapWindow(dpy, m_window);
		eventType = MapNotify;
	}
	else
	{
		XUnmapWindow(dpy, m_window);
		eventType = UnmapNotify;
	}

	// We are only interested about exposure/structure notify events, not user input
	XSelectInput(dpy, m_window, ExposureMask | StructureNotifyMask);

	do
	{
		XWindowEvent(dpy, m_window, ExposureMask | StructureNotifyMask, &event);
	} while (event.type != eventType);

	m_visible = visible;
}

void XlibWindow::getDimensions (int* width, int* height) const
{
	int x, y;
	::Window root;
	unsigned width_, height_, borderWidth, depth;

	XGetGeometry(m_display.getXDisplay(), m_window, &root, &x, &y, &width_, &height_, &borderWidth, &depth);
	if (width != DE_NULL)
		*width = static_cast<int>(width_);
	if (height != DE_NULL)
		*height = static_cast<int>(height_);
}

void XlibWindow::setDimensions (int width, int height)
{
	const unsigned int	mask		= CWWidth | CWHeight;
	XWindowChanges		changes;
	::Display*			dpy			= m_display.getXDisplay();
	XEvent				myevent;
	changes.width	= width;
	changes.height	= height;
	XConfigureWindow(dpy, m_window, mask, &changes);
	XFlush(dpy);

	for(;;)
	{
		XNextEvent(dpy, &myevent);
		if (myevent.type == ConfigureNotify) {
			XConfigureEvent e = myevent.xconfigure;
			if (e.width == width && e.height == height)
				break;
		}
		else
			m_display.processEvent(myevent);
	}
}

void XlibWindow::processEvents (void)
{
	// A bit of a hack, since we don't really handle all the events.
	m_display.processEvents();
}

XlibWindow::~XlibWindow (void)
{
	XDestroyWindow(m_display.getXDisplay(), m_window);
	if (m_colormap != None)
		XFreeColormap(m_display.getXDisplay(), m_colormap);
}

} // x11
} // lnx
} // tcu
