<commit_before>/**
 * @file
 *
 * @brief Plugin which acts as proxy and calls other plugins written in python
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#ifndef SWIG_TYPE_TABLE
#error Build system error, SWIG_TYPE_TABLE is not defined
#endif

#include <Python.h>

#ifndef HAVE_KDBCONFIG
#include <kdbconfig.h>
#endif
#include <kdbhelper.h>
#include SWIG_RUNTIME
#include "python.hpp"

#include <key.hpp>
#include <keyset.hpp>
#include <libgen.h>
#include <mutex>

using namespace ckdb;
#include <kdberrors.h>

#define PYTHON_PLUGIN_NAME_STR2(x) ELEKTRA_QUOTE (x)
#define PYTHON_PLUGIN_NAME_STR PYTHON_PLUGIN_NAME_STR2 (PYTHON_PLUGIN_NAME)

static PyObject * Python_fromSWIG (ckdb::Key * key)
{
	swig_type_info * ti = SWIG_TypeQuery ("kdb::Key *");
	if (key == nullptr || ti == nullptr) return Py_None;
	return SWIG_NewPointerObj (new kdb::Key (key), ti, 0);
}

static PyObject * Python_fromSWIG (ckdb::KeySet * keyset)
{
	swig_type_info * ti = SWIG_TypeQuery ("kdb::KeySet *");
	if (keyset == nullptr || ti == nullptr) return Py_None;
	return SWIG_NewPointerObj (new kdb::KeySet (keyset), ti, 0);
}

class Python_LockSwap
{
public:
	Python_LockSwap (PyThreadState * newstate)
	{
		gstate = PyGILState_Ensure ();
		tstate = PyThreadState_Swap (newstate);
	}

	~Python_LockSwap ()
	{
		PyThreadState_Swap (tstate);
		PyGILState_Release (gstate);
	}

private:
	PyGILState_STATE gstate;
	PyThreadState * tstate;
};

typedef struct
{
	PyThreadState * tstate;
	PyObject * instance;
	int printError;
	int shutdown;
} moduleData;

static int Python_AppendToSysPath (const char * path)
{
	if (path == nullptr) return 0;

	PyObject * sysPath = PySys_GetObject ((char *)"path");
	PyObject * pyPath = PyUnicode_FromString (path);
	PyList_Append (sysPath, pyPath);
	Py_DECREF (pyPath);
	return 1;
}

static PyObject * Python_CallFunction (PyObject * object, PyObject * args)
{
	if (!PyCallable_Check (object)) return nullptr;

	PyObject * res = PyObject_CallObject (object, args ? args : PyTuple_New (0));
	Py_XINCREF (res);
	return res;
}

static int Python_CallFunction_Int (moduleData * data, PyObject * object, PyObject * args, ckdb::Key * errorKey)
{
	int ret = -1;
	PyObject * res = Python_CallFunction (object, args);
	if (!res)
	{
		ELEKTRA_SET_ERROR (111, errorKey, "Error while calling python function");
		if (data->printError) PyErr_Print ();
	}
	else
	{
#if PY_MAJOR_VERSION >= 3
		if (!PyLong_Check (res))
#else
		if (!PyInt_Check (res))
#endif
			ELEKTRA_SET_ERROR (111, errorKey, "Return value is no integer");
		else
			ret = PyLong_AsLong (res);
	}

	Py_XDECREF (res);
	return ret;
}

static int Python_CallFunction_Helper1 (moduleData * data, const char * funcName, ckdb::Key * errorKey)
{
	int ret = 0;
	Python_LockSwap pylock (data->tstate);
	PyObject * func = PyObject_GetAttrString (data->instance, funcName);
	if (func)
	{
		PyObject * arg0 = Python_fromSWIG (errorKey);
		PyObject * args = Py_BuildValue ("(O)", arg0);
		ret = Python_CallFunction_Int (data, func, args, errorKey);
		Py_DECREF (arg0);
		Py_DECREF (args);
		Py_DECREF (func);
	}
	return ret;
}

static int Python_CallFunction_Helper2 (moduleData * data, const char * funcName, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	int ret = 0;
	Python_LockSwap pylock (data->tstate);
	PyObject * func = PyObject_GetAttrString (data->instance, funcName);
	if (func)
	{
		PyObject * arg0 = Python_fromSWIG (returned);
		PyObject * arg1 = Python_fromSWIG (parentKey);
		PyObject * args = Py_BuildValue ("(OO)", arg0, arg1);
		ret = Python_CallFunction_Int (data, func, args, parentKey);
		Py_DECREF (arg0);
		Py_DECREF (arg1);
		Py_DECREF (args);
		Py_DECREF (func);
	}
	return ret;
}

static std::mutex mutex;
static unsigned open_cnt = 0;

static void Python_Shutdown (moduleData * data)
{
	/* destroy python if plugin isn't used anymore */
	if (Py_IsInitialized ())
	{
		if (data->tstate)
		{
			Python_LockSwap pylock (data->tstate);

			/* clean up references */
			Py_XDECREF (data->instance);
			data->instance = nullptr;

			/* destroy sub interpreter */
			Py_EndInterpreter (data->tstate);
		}
		mutex.lock ();
		if (open_cnt && !--open_cnt && data->shutdown) // order matters!
			Py_Finalize ();
		mutex.unlock ();
	}
}

extern "C" {
int PYTHON_PLUGIN_FUNCTION (Open) (ckdb::Plugin * handle, ckdb::Key * errorKey)
{
	KeySet * config = elektraPluginGetConfig (handle);

	Key * script = ksLookupByName (config, "/script", 0);
	if (script == nullptr || !strlen (keyString (script)))
	{
		if (ksLookupByName (config, "/module", 0) != nullptr)
		{
			return 0; // by convention: success if /module exists
		}
		ELEKTRA_SET_ERROR (111, errorKey, "No python script set");
		return -1;
	}

	/* create module data */
	auto data = new moduleData;
	data->tstate = nullptr;
	data->instance = nullptr;
	data->printError = (ksLookupByName (config, "/print", 0) != nullptr);
	/* shutdown flag is integer by design. This way users can set the
	 * expected behaviour without worring about default values
	 */
	data->shutdown = (ksLookupByName (config, "/shutdown", 0) && !!strcmp (keyString (ksLookupByName (config, "/shutdown", 0)), "0"));

	{
		/* initialize python interpreter if necessary */
		mutex.lock ();
		if (!Py_IsInitialized ())
		{
			Py_Initialize ();
			if (!Py_IsInitialized ())
			{
				mutex.unlock ();
				goto error;
			}
			open_cnt++;
		}
		else if (open_cnt) // we have initialized python before
			open_cnt++;
		mutex.unlock ();

		/* init threads */
		PyEval_InitThreads ();

		/* acquire GIL */
		Python_LockSwap pylock (nullptr);

		/* create a new sub-interpreter */
		data->tstate = Py_NewInterpreter ();
		if (data->tstate == nullptr)
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Unable to create sub intepreter");
			goto error;
		}
		PyThreadState_Swap (data->tstate);

		/* import kdb */
		PyObject * kdbModule = PyImport_ImportModule ("kdb");
		if (kdbModule == nullptr)
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Unable to import kdb module");
			goto error_print;
		}
		Py_XDECREF (kdbModule);

		/* extend sys path */
		char * tmpScript = elektraStrDup (keyString (script));
		const char * dname = dirname (tmpScript);
		if (!Python_AppendToSysPath (dname))
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Unable to extend sys.path");
			elektraFree (tmpScript);
			goto error;
		}
		elektraFree (tmpScript);

		/* import module/script */
		tmpScript = elektraStrDup (keyString (script));
		char * bname = basename (tmpScript);
		size_t bname_len = strlen (bname);
		if (bname_len >= 4 && strcmp (bname + bname_len - 3, ".py") == 0) bname[bname_len - 3] = '\0';

		PyObject * pModule = PyImport_ImportModule (bname);
		if (pModule == nullptr)
		{
			ELEKTRA_SET_ERRORF (111, errorKey, "Unable to import python script %s", keyString (script));
			elektraFree (tmpScript);
			goto error_print;
		}
		elektraFree (tmpScript);

		/* get class */
		PyObject * klass = PyObject_GetAttrString (pModule, "ElektraPlugin");
		Py_DECREF (pModule);
		if (klass == nullptr)
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Module doesn't provide a ElektraPlugin class");
			goto error_print;
		}

		/* create instance of class */
		PyObject * inst_args = Py_BuildValue ("()");
		PyObject * inst = PyEval_CallObject (klass, inst_args);
		Py_DECREF (klass);
		Py_DECREF (inst_args);
		if (inst == nullptr)
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Unable to create instance of ElektraPlugin");
			goto error_print;
		}
		data->instance = inst;
	}

	/* store module data after everything is set up */
	elektraPluginSetData (handle, data);

	/* call python function */
	return Python_CallFunction_Helper2 (data, "open", config, errorKey);

error_print:
	if (data->printError) PyErr_Print ();
error:
	/* destroy python */
	Python_Shutdown (data);
	delete data;
	return -1;
}

int PYTHON_PLUGIN_FUNCTION (Close) (ckdb::Plugin * handle, ckdb::Key * errorKey)
{
	moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
	if (data == nullptr) return 0;

	int ret = Python_CallFunction_Helper1 (data, "close", errorKey);

	/* destroy python */
	Python_Shutdown (data);
	delete data;
	return ret;
}

int PYTHON_PLUGIN_FUNCTION (Get) (ckdb::Plugin * handle, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
#define _MODULE_CONFIG_PATH "system/elektra/modules/" PYTHON_PLUGIN_NAME_STR
	if (!strcmp (keyName (parentKey), _MODULE_CONFIG_PATH))
	{
		KeySet * n;
		ksAppend (returned,
			  n = ksNew (30, keyNew (_MODULE_CONFIG_PATH, KEY_VALUE, "python interpreter waits for your orders", KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports", KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/get", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Get), KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/set", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Set), KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/error", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Error), KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/open", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Open), KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/close", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Close), KEY_END),
#include ELEKTRA_README (PYTHON_PLUGIN_NAME)
				     keyNew (_MODULE_CONFIG_PATH "/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END));
		ksDel (n);
	}

	moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
	if (data != nullptr) return Python_CallFunction_Helper2 (data, "get", returned, parentKey);
	return 0;
}

int PYTHON_PLUGIN_FUNCTION (Set) (ckdb::Plugin * handle, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
	if (data != nullptr) return Python_CallFunction_Helper2 (data, "set", returned, parentKey);
	return 0;
}

int PYTHON_PLUGIN_FUNCTION (Error) (ckdb::Plugin * handle, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
	if (data != nullptr) return Python_CallFunction_Helper2 (data, "error", returned, parentKey);
	return 0;
}

ckdb::Plugin * PYTHON_PLUGIN_EXPORT (PYTHON_PLUGIN_NAME)
{
	// clang-format off
	return elektraPluginExport(PYTHON_PLUGIN_NAME_STR,
		ELEKTRA_PLUGIN_OPEN,  &PYTHON_PLUGIN_FUNCTION(Open),
		ELEKTRA_PLUGIN_CLOSE, &PYTHON_PLUGIN_FUNCTION(Close),
		ELEKTRA_PLUGIN_GET,   &PYTHON_PLUGIN_FUNCTION(Get),
		ELEKTRA_PLUGIN_SET,   &PYTHON_PLUGIN_FUNCTION(Set),
		ELEKTRA_PLUGIN_ERROR, &PYTHON_PLUGIN_FUNCTION(Error),
		ELEKTRA_PLUGIN_END);
}
}
<commit_msg>python: fix typo<commit_after>/**
 * @file
 *
 * @brief Plugin which acts as proxy and calls other plugins written in python
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#ifndef SWIG_TYPE_TABLE
#error Build system error, SWIG_TYPE_TABLE is not defined
#endif

#include <Python.h>

#ifndef HAVE_KDBCONFIG
#include <kdbconfig.h>
#endif
#include <kdbhelper.h>
#include SWIG_RUNTIME
#include "python.hpp"

#include <key.hpp>
#include <keyset.hpp>
#include <libgen.h>
#include <mutex>

using namespace ckdb;
#include <kdberrors.h>

#define PYTHON_PLUGIN_NAME_STR2(x) ELEKTRA_QUOTE (x)
#define PYTHON_PLUGIN_NAME_STR PYTHON_PLUGIN_NAME_STR2 (PYTHON_PLUGIN_NAME)

static PyObject * Python_fromSWIG (ckdb::Key * key)
{
	swig_type_info * ti = SWIG_TypeQuery ("kdb::Key *");
	if (key == nullptr || ti == nullptr) return Py_None;
	return SWIG_NewPointerObj (new kdb::Key (key), ti, 0);
}

static PyObject * Python_fromSWIG (ckdb::KeySet * keyset)
{
	swig_type_info * ti = SWIG_TypeQuery ("kdb::KeySet *");
	if (keyset == nullptr || ti == nullptr) return Py_None;
	return SWIG_NewPointerObj (new kdb::KeySet (keyset), ti, 0);
}

class Python_LockSwap
{
public:
	Python_LockSwap (PyThreadState * newstate)
	{
		gstate = PyGILState_Ensure ();
		tstate = PyThreadState_Swap (newstate);
	}

	~Python_LockSwap ()
	{
		PyThreadState_Swap (tstate);
		PyGILState_Release (gstate);
	}

private:
	PyGILState_STATE gstate;
	PyThreadState * tstate;
};

typedef struct
{
	PyThreadState * tstate;
	PyObject * instance;
	int printError;
	int shutdown;
} moduleData;

static int Python_AppendToSysPath (const char * path)
{
	if (path == nullptr) return 0;

	PyObject * sysPath = PySys_GetObject ((char *)"path");
	PyObject * pyPath = PyUnicode_FromString (path);
	PyList_Append (sysPath, pyPath);
	Py_DECREF (pyPath);
	return 1;
}

static PyObject * Python_CallFunction (PyObject * object, PyObject * args)
{
	if (!PyCallable_Check (object)) return nullptr;

	PyObject * res = PyObject_CallObject (object, args ? args : PyTuple_New (0));
	Py_XINCREF (res);
	return res;
}

static int Python_CallFunction_Int (moduleData * data, PyObject * object, PyObject * args, ckdb::Key * errorKey)
{
	int ret = -1;
	PyObject * res = Python_CallFunction (object, args);
	if (!res)
	{
		ELEKTRA_SET_ERROR (111, errorKey, "Error while calling python function");
		if (data->printError) PyErr_Print ();
	}
	else
	{
#if PY_MAJOR_VERSION >= 3
		if (!PyLong_Check (res))
#else
		if (!PyInt_Check (res))
#endif
			ELEKTRA_SET_ERROR (111, errorKey, "Return value is no integer");
		else
			ret = PyLong_AsLong (res);
	}

	Py_XDECREF (res);
	return ret;
}

static int Python_CallFunction_Helper1 (moduleData * data, const char * funcName, ckdb::Key * errorKey)
{
	int ret = 0;
	Python_LockSwap pylock (data->tstate);
	PyObject * func = PyObject_GetAttrString (data->instance, funcName);
	if (func)
	{
		PyObject * arg0 = Python_fromSWIG (errorKey);
		PyObject * args = Py_BuildValue ("(O)", arg0);
		ret = Python_CallFunction_Int (data, func, args, errorKey);
		Py_DECREF (arg0);
		Py_DECREF (args);
		Py_DECREF (func);
	}
	return ret;
}

static int Python_CallFunction_Helper2 (moduleData * data, const char * funcName, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	int ret = 0;
	Python_LockSwap pylock (data->tstate);
	PyObject * func = PyObject_GetAttrString (data->instance, funcName);
	if (func)
	{
		PyObject * arg0 = Python_fromSWIG (returned);
		PyObject * arg1 = Python_fromSWIG (parentKey);
		PyObject * args = Py_BuildValue ("(OO)", arg0, arg1);
		ret = Python_CallFunction_Int (data, func, args, parentKey);
		Py_DECREF (arg0);
		Py_DECREF (arg1);
		Py_DECREF (args);
		Py_DECREF (func);
	}
	return ret;
}

static std::mutex mutex;
static unsigned open_cnt = 0;

static void Python_Shutdown (moduleData * data)
{
	/* destroy python if plugin isn't used anymore */
	if (Py_IsInitialized ())
	{
		if (data->tstate)
		{
			Python_LockSwap pylock (data->tstate);

			/* clean up references */
			Py_XDECREF (data->instance);
			data->instance = nullptr;

			/* destroy sub interpreter */
			Py_EndInterpreter (data->tstate);
		}
		mutex.lock ();
		if (open_cnt && !--open_cnt && data->shutdown) // order matters!
			Py_Finalize ();
		mutex.unlock ();
	}
}

extern "C" {
int PYTHON_PLUGIN_FUNCTION (Open) (ckdb::Plugin * handle, ckdb::Key * errorKey)
{
	KeySet * config = elektraPluginGetConfig (handle);

	Key * script = ksLookupByName (config, "/script", 0);
	if (script == nullptr || !strlen (keyString (script)))
	{
		if (ksLookupByName (config, "/module", 0) != nullptr)
		{
			return 0; // by convention: success if /module exists
		}
		ELEKTRA_SET_ERROR (111, errorKey, "No python script set");
		return -1;
	}

	/* create module data */
	auto data = new moduleData;
	data->tstate = nullptr;
	data->instance = nullptr;
	data->printError = (ksLookupByName (config, "/print", 0) != nullptr);
	/* shutdown flag is integer by design. This way users can set the
	 * expected behaviour without worring about default values
	 */
	data->shutdown = (ksLookupByName (config, "/shutdown", 0) && !!strcmp (keyString (ksLookupByName (config, "/shutdown", 0)), "0"));

	{
		/* initialize python interpreter if necessary */
		mutex.lock ();
		if (!Py_IsInitialized ())
		{
			Py_Initialize ();
			if (!Py_IsInitialized ())
			{
				mutex.unlock ();
				goto error;
			}
			open_cnt++;
		}
		else if (open_cnt) // we have initialized python before
			open_cnt++;
		mutex.unlock ();

		/* init threads */
		PyEval_InitThreads ();

		/* acquire GIL */
		Python_LockSwap pylock (nullptr);

		/* create a new sub-interpreter */
		data->tstate = Py_NewInterpreter ();
		if (data->tstate == nullptr)
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Unable to create sub interpreter");
			goto error;
		}
		PyThreadState_Swap (data->tstate);

		/* import kdb */
		PyObject * kdbModule = PyImport_ImportModule ("kdb");
		if (kdbModule == nullptr)
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Unable to import kdb module");
			goto error_print;
		}
		Py_XDECREF (kdbModule);

		/* extend sys path */
		char * tmpScript = elektraStrDup (keyString (script));
		const char * dname = dirname (tmpScript);
		if (!Python_AppendToSysPath (dname))
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Unable to extend sys.path");
			elektraFree (tmpScript);
			goto error;
		}
		elektraFree (tmpScript);

		/* import module/script */
		tmpScript = elektraStrDup (keyString (script));
		char * bname = basename (tmpScript);
		size_t bname_len = strlen (bname);
		if (bname_len >= 4 && strcmp (bname + bname_len - 3, ".py") == 0) bname[bname_len - 3] = '\0';

		PyObject * pModule = PyImport_ImportModule (bname);
		if (pModule == nullptr)
		{
			ELEKTRA_SET_ERRORF (111, errorKey, "Unable to import python script %s", keyString (script));
			elektraFree (tmpScript);
			goto error_print;
		}
		elektraFree (tmpScript);

		/* get class */
		PyObject * klass = PyObject_GetAttrString (pModule, "ElektraPlugin");
		Py_DECREF (pModule);
		if (klass == nullptr)
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Module doesn't provide a ElektraPlugin class");
			goto error_print;
		}

		/* create instance of class */
		PyObject * inst_args = Py_BuildValue ("()");
		PyObject * inst = PyEval_CallObject (klass, inst_args);
		Py_DECREF (klass);
		Py_DECREF (inst_args);
		if (inst == nullptr)
		{
			ELEKTRA_SET_ERROR (111, errorKey, "Unable to create instance of ElektraPlugin");
			goto error_print;
		}
		data->instance = inst;
	}

	/* store module data after everything is set up */
	elektraPluginSetData (handle, data);

	/* call python function */
	return Python_CallFunction_Helper2 (data, "open", config, errorKey);

error_print:
	if (data->printError) PyErr_Print ();
error:
	/* destroy python */
	Python_Shutdown (data);
	delete data;
	return -1;
}

int PYTHON_PLUGIN_FUNCTION (Close) (ckdb::Plugin * handle, ckdb::Key * errorKey)
{
	moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
	if (data == nullptr) return 0;

	int ret = Python_CallFunction_Helper1 (data, "close", errorKey);

	/* destroy python */
	Python_Shutdown (data);
	delete data;
	return ret;
}

int PYTHON_PLUGIN_FUNCTION (Get) (ckdb::Plugin * handle, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
#define _MODULE_CONFIG_PATH "system/elektra/modules/" PYTHON_PLUGIN_NAME_STR
	if (!strcmp (keyName (parentKey), _MODULE_CONFIG_PATH))
	{
		KeySet * n;
		ksAppend (returned,
			  n = ksNew (30, keyNew (_MODULE_CONFIG_PATH, KEY_VALUE, "python interpreter waits for your orders", KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports", KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/get", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Get), KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/set", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Set), KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/error", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Error), KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/open", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Open), KEY_END),
				     keyNew (_MODULE_CONFIG_PATH "/exports/close", KEY_FUNC, PYTHON_PLUGIN_FUNCTION (Close), KEY_END),
#include ELEKTRA_README (PYTHON_PLUGIN_NAME)
				     keyNew (_MODULE_CONFIG_PATH "/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END));
		ksDel (n);
	}

	moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
	if (data != nullptr) return Python_CallFunction_Helper2 (data, "get", returned, parentKey);
	return 0;
}

int PYTHON_PLUGIN_FUNCTION (Set) (ckdb::Plugin * handle, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
	if (data != nullptr) return Python_CallFunction_Helper2 (data, "set", returned, parentKey);
	return 0;
}

int PYTHON_PLUGIN_FUNCTION (Error) (ckdb::Plugin * handle, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	moduleData * data = static_cast<moduleData *> (elektraPluginGetData (handle));
	if (data != nullptr) return Python_CallFunction_Helper2 (data, "error", returned, parentKey);
	return 0;
}

ckdb::Plugin * PYTHON_PLUGIN_EXPORT (PYTHON_PLUGIN_NAME)
{
	// clang-format off
	return elektraPluginExport(PYTHON_PLUGIN_NAME_STR,
		ELEKTRA_PLUGIN_OPEN,  &PYTHON_PLUGIN_FUNCTION(Open),
		ELEKTRA_PLUGIN_CLOSE, &PYTHON_PLUGIN_FUNCTION(Close),
		ELEKTRA_PLUGIN_GET,   &PYTHON_PLUGIN_FUNCTION(Get),
		ELEKTRA_PLUGIN_SET,   &PYTHON_PLUGIN_FUNCTION(Set),
		ELEKTRA_PLUGIN_ERROR, &PYTHON_PLUGIN_FUNCTION(Error),
		ELEKTRA_PLUGIN_END);
}
}
<|endoftext|>


<commit_before>#include <cassert>
#include <cstdio>
#include <iostream>
#include <map>

#include "Blur.h"
#include "Sharpen.h"
#include "Sobel.h"

#define METHOD_REFERENCE  (1<<1)
#define METHOD_HALIDE_CPU (1<<2)
#define METHOD_HALIDE_GPU (1<<3)
#define METHOD_OPENCL     (1<<4)

using namespace improsa;
using namespace std;

void printUsage();
int updateStatus(const char *format, va_list args);

map<string, Filter*> m_filters =
{
  {"blur",    new Blur()},
  {"sharpen", new Sharpen()},
  {"sobel",   new Sobel()},
};

map<string, unsigned int> m_methods =
{
  {"reference",  METHOD_REFERENCE},
  {"halide_cpu", METHOD_HALIDE_CPU},
  {"halide_gpu", METHOD_HALIDE_GPU},
  {"opencl",     METHOD_OPENCL},
};

int main(int argc, char *argv[])
{
  size_t size = 0;
  Filter *filter = NULL;
  unsigned int method = 0;

  // Parse arguments
  for (int i = 1; i < argc; i++)
  {
    if (m_filters.find(argv[i]) != m_filters.end())
    {
      filter = m_filters[argv[i]];
    }
    else if (m_methods.find(argv[i]) != m_methods.end())
    {
      method = m_methods[argv[i]];
    }
    else
    {
      char *next;
      size_t sz = strtoul(argv[i], &next, 10);
      if (strlen(next) > 0 || size != 0 || sz == 0)
      {
        cout << "Invalid argument '" << argv[i] << "'" << endl;
        printUsage();
        exit(1);
      }
      size = sz;
    }
  }
  if (size == 0 || filter == NULL || method == 0)
  {
    printUsage();
    exit(1);
  }

  // Allocate input/output images
  Image input = {new unsigned char[size*size*4], size, size};
  Image output = {new unsigned char[size*size*4], size, size};

  // Initialize input image with random data
  for (int y = 0; y < size; y++)
  {
    for (int x = 0; x < size; x++)
    {
      setPixel(input, x, y, 0, rand()/RAND_MAX);
      setPixel(input, x, y, 1, rand()/RAND_MAX);
      setPixel(input, x, y, 2, rand()/RAND_MAX);
      setPixel(input, x, y, 3, 255);
    }
  }

  // Run filter
  Filter::Params params = {{0,0}};
  filter->setStatusCallback(updateStatus);
  switch (method)
  {
    case METHOD_REFERENCE:
      filter->runReference(input, output);
      break;
    case METHOD_HALIDE_CPU:
      filter->runHalideCPU(input, output, params);
      break;
    case METHOD_HALIDE_GPU:
      filter->runHalideGPU(input, output, params);
      break;
    case METHOD_OPENCL:
      filter->runOpenCL(input, output, params);
      break;
    default:
      assert(false && "Invalid method.");
  }

  return 0;
}

void printUsage()
{
  cout << endl << "Usage: improsa SIZE FILTER METHOD" << endl;

  cout << endl << "Where FILTER is one of:" << endl;
  map<string, Filter*>::iterator fItr;
  for (fItr = m_filters.begin(); fItr != m_filters.end(); fItr++)
  {
    cout << "\t" << fItr->first << endl;
  }

  cout << endl << "Where METHOD is one of:" << endl;
  map<string, unsigned int>::iterator mItr;
  for (mItr = m_methods.begin(); mItr != m_methods.end(); mItr++)
  {
    cout << "\t" << mItr->first << endl;
  }

  cout << endl;
}

int updateStatus(const char *format, va_list args)
{
  vprintf(format, args);
  printf("\n");
  return 0;
}
<commit_msg>Included cstring for strlen().<commit_after>#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>

#include "Blur.h"
#include "Sharpen.h"
#include "Sobel.h"

#define METHOD_REFERENCE  (1<<1)
#define METHOD_HALIDE_CPU (1<<2)
#define METHOD_HALIDE_GPU (1<<3)
#define METHOD_OPENCL     (1<<4)

using namespace improsa;
using namespace std;

void printUsage();
int updateStatus(const char *format, va_list args);

map<string, Filter*> m_filters =
{
  {"blur",    new Blur()},
  {"sharpen", new Sharpen()},
  {"sobel",   new Sobel()},
};

map<string, unsigned int> m_methods =
{
  {"reference",  METHOD_REFERENCE},
  {"halide_cpu", METHOD_HALIDE_CPU},
  {"halide_gpu", METHOD_HALIDE_GPU},
  {"opencl",     METHOD_OPENCL},
};

int main(int argc, char *argv[])
{
  size_t size = 0;
  Filter *filter = NULL;
  unsigned int method = 0;

  // Parse arguments
  for (int i = 1; i < argc; i++)
  {
    if (m_filters.find(argv[i]) != m_filters.end())
    {
      filter = m_filters[argv[i]];
    }
    else if (m_methods.find(argv[i]) != m_methods.end())
    {
      method = m_methods[argv[i]];
    }
    else
    {
      char *next;
      size_t sz = strtoul(argv[i], &next, 10);
      if (strlen(next) > 0 || size != 0 || sz == 0)
      {
        cout << "Invalid argument '" << argv[i] << "'" << endl;
        printUsage();
        exit(1);
      }
      size = sz;
    }
  }
  if (size == 0 || filter == NULL || method == 0)
  {
    printUsage();
    exit(1);
  }

  // Allocate input/output images
  Image input = {new unsigned char[size*size*4], size, size};
  Image output = {new unsigned char[size*size*4], size, size};

  // Initialize input image with random data
  for (int y = 0; y < size; y++)
  {
    for (int x = 0; x < size; x++)
    {
      setPixel(input, x, y, 0, rand()/RAND_MAX);
      setPixel(input, x, y, 1, rand()/RAND_MAX);
      setPixel(input, x, y, 2, rand()/RAND_MAX);
      setPixel(input, x, y, 3, 255);
    }
  }

  // Run filter
  Filter::Params params = {{0,0}};
  filter->setStatusCallback(updateStatus);
  switch (method)
  {
    case METHOD_REFERENCE:
      filter->runReference(input, output);
      break;
    case METHOD_HALIDE_CPU:
      filter->runHalideCPU(input, output, params);
      break;
    case METHOD_HALIDE_GPU:
      filter->runHalideGPU(input, output, params);
      break;
    case METHOD_OPENCL:
      filter->runOpenCL(input, output, params);
      break;
    default:
      assert(false && "Invalid method.");
  }

  return 0;
}

void printUsage()
{
  cout << endl << "Usage: improsa SIZE FILTER METHOD" << endl;

  cout << endl << "Where FILTER is one of:" << endl;
  map<string, Filter*>::iterator fItr;
  for (fItr = m_filters.begin(); fItr != m_filters.end(); fItr++)
  {
    cout << "\t" << fItr->first << endl;
  }

  cout << endl << "Where METHOD is one of:" << endl;
  map<string, unsigned int>::iterator mItr;
  for (mItr = m_methods.begin(); mItr != m_methods.end(); mItr++)
  {
    cout << "\t" << mItr->first << endl;
  }

  cout << endl;
}

int updateStatus(const char *format, va_list args)
{
  vprintf(format, args);
  printf("\n");
  return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** This file is part of QtCompositor**
**
** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
**
** Contact:  Nokia Corporation qt-info@nokia.com
**
** You may use this file under the terms of the BSD license as follows:
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**
** Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
**
** Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
**
** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/

#include "wlsurface.h"

#include "../waylandsurface.h"

#include "wlcompositor.h"
#include "wlshmbuffer.h"

#include <QtCore/QDebug>

#include <wayland-server.h>

#include <linux/input.h>

#ifdef QT_COMPOSITOR_WAYLAND_GL
#include "../graphicshardwareintegration.cpp"
#include <QtGui/QPlatformGLContext>
#endif

namespace Wayland {

class SurfacePrivate
{
public:
    SurfacePrivate(struct wl_client *client, Compositor *compositor)
        : client(client)
        , compositor(compositor)
    {
        type = WaylandSurface::Invalid;
#ifdef QT_COMPOSITOR_WAYLAND_GL
        texture_id = 0;
#endif
    }

    WaylandSurface::Type type;
    QRect rect;
    struct wl_client *client;
    Compositor *compositor;
    WaylandSurface *qtSurface;

    ShmBuffer *shm_buffer;
#ifdef QT_COMPOSITOR_WAYLAND_GL
    GLuint texture_id;
#endif
};

void surface_destroy(struct wl_client *client, struct wl_surface *surface)
{
    wl_resource_destroy(&surface->resource, client);
}

void surface_attach(struct wl_client *client, struct wl_surface *surface,
                    struct wl_buffer *buffer, int x, int y)
{
    Q_UNUSED(client);
    Q_UNUSED(x);
    Q_UNUSED(y);

    if (buffer->attach) {
        wayland_cast<Surface *>(surface)->attachShm(wayland_cast<ShmBuffer *>(buffer));
    }
#ifdef QT_COMPOSITOR_WAYLAND_GL
    else {
        wayland_cast<Surface *>(surface)->attachHWBuffer(buffer);
    }
#endif //QT_COMPOSITOR_WAYLAND_EGL
}

void surface_map_toplevel(struct wl_client *client,
                          struct wl_surface *surface)
{
    Q_UNUSED(client);
    printf("surface_map_toplevel: %p, %p", client, surface);

    wayland_cast<Surface *>(surface)->mapTopLevel();
}

void surface_map_transient(struct wl_client *client,
                      struct wl_surface *surface,
                      struct wl_surface *parent,
                      int x,
                      int y,
                      uint32_t flags)
{
    Q_UNUSED(client);
    Q_UNUSED(surface);
    Q_UNUSED(parent);
    Q_UNUSED(x);
    Q_UNUSED(y);
    Q_UNUSED(flags);
    printf("surface_map_transient: %p, %p", client, surface);
}

void surface_map_fullscreen(struct wl_client *client,
                       struct wl_surface *surface)
{
    Q_UNUSED(client);
    Q_UNUSED(surface);
    printf("surface_map_fullscreen: %p, %p", client, surface);
}

void surface_damage(struct wl_client *client, struct wl_surface *surface,
                    int32_t x, int32_t y, int32_t width, int32_t height)
{
    Q_UNUSED(client);
    wayland_cast<Surface *>(surface)->damage(QRect(x, y, width, height));
}

Surface::Surface(struct wl_client *client, Compositor *compositor)
    : d_ptr(new SurfacePrivate(client,compositor))
{
    base()->client = client;
    wl_list_init(&base()->destroy_listener_list);
    d_ptr->qtSurface = new WaylandSurface(this);

}

Surface::~Surface()
{
    Q_D(Surface);
    d->compositor->surfaceDestroyed(this);
    delete d->qtSurface;
}

WaylandSurface::Type Surface::type() const
{
    Q_D(const Surface);
    return d->type;
}

void Surface::damage(const QRect &rect)
{
    Q_D(Surface);
    emit d->qtSurface->damaged(rect);
}

QImage Surface::image() const
{
    Q_D(const Surface);
    if (d->type == WaylandSurface::Shm) {
        return d->shm_buffer->image();
    }
    return QImage();
}

#ifdef QT_COMPOSITOR_WAYLAND_GL

void Surface::attachHWBuffer(struct wl_buffer *buffer)
{
    Q_D(Surface);
    d->type = WaylandSurface::Texture;

    //make current for the topLevel. We could have used the eglContext,
    //but then we would need to handle eglSurfaces as well.
    d->compositor->topLevelWidget()->platformWindow()->glContext()->makeCurrent();

    glDeleteTextures(1,&d->texture_id);

    d->texture_id = d->compositor->graphicsHWIntegration()->createTextureFromBuffer(buffer);
    emit d->qtSurface->mapped(QRect(QPoint(), QSize(buffer->width, buffer->height)));
}

GLuint Surface::textureId() const
{
    Q_D(const Surface);
    return d->texture_id;
}
#endif // QT_COMPOSITOR_WAYLAND_GL

void Surface::attachShm(Wayland::ShmBuffer *shm_buffer)
{
    Q_D(Surface);
    d->shm_buffer = shm_buffer;
    d->type = WaylandSurface::Shm;
    emit d->qtSurface->mapped(QRect(QPoint(), shm_buffer->size()));
}

void Surface::mapTopLevel()
{
    Q_D(Surface);
    d->rect = QRect(0, 0, 200, 200);
}

WaylandSurface * Surface::handle() const
{
    Q_D(const Surface);
    return d->qtSurface;
}

uint32_t toWaylandButton(Qt::MouseButton button)
{
    switch (button) {
    case Qt::LeftButton:
        return BTN_LEFT;
    case Qt::RightButton:
        return BTN_RIGHT;
    default:
        return BTN_MIDDLE;
    }
}

void Surface::sendMousePressEvent(int x, int y, Qt::MouseButton button)
{
    Q_D(Surface);
    if (d->client) {
        uint32_t time = d->compositor->currentTimeMsecs();
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
                             WL_INPUT_DEVICE_BUTTON, time, toWaylandButton(button), 1);
    }
    sendMouseMoveEvent(x, y);
}

void Surface::sendMouseReleaseEvent(int x, int y, Qt::MouseButton button)
{
    Q_D(Surface);
    if (d->client)
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
                             WL_INPUT_DEVICE_BUTTON, d->compositor->currentTimeMsecs(), toWaylandButton(button), 0);
    sendMouseMoveEvent(x, y);
}

void Surface::sendMouseMoveEvent(int x, int y)
{
    Q_D(Surface);
    if (d->client) {
        uint32_t time = d->compositor->currentTimeMsecs();
        wl_input_device_set_pointer_focus(d->compositor->defaultInputDevice(),
            base(), time, x, y, x, y);
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
             WL_INPUT_DEVICE_MOTION, time, x, y, x, y);
    }
}

void Surface::sendKeyPressEvent(uint code)
{
    Q_D(Surface);
    if (d->compositor->defaultInputDevice()->keyboard_focus != NULL) {
        uint32_t time = d->compositor->currentTimeMsecs();
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
                             WL_INPUT_DEVICE_KEY, time, code - 8, 1);
    }

}

void Surface::sendKeyReleaseEvent(uint code)
{
    Q_D(Surface);
    if (d->compositor->defaultInputDevice()->keyboard_focus != NULL) {
        uint32_t time = d->compositor->currentTimeMsecs();
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
                             WL_INPUT_DEVICE_KEY, time, code - 8, 0);
    }
}

void Surface::setInputFocus()
{
    Q_D(Surface);
    ulong time = d->compositor->currentTimeMsecs();

    wl_input_device_set_keyboard_focus(d->compositor->defaultInputDevice(), base(), time);
    wl_input_device_set_pointer_focus(d->compositor->defaultInputDevice(), base(), time, 0, 0, 0, 0);
}

}
<commit_msg>Fixed wrong coordinates sent for button press events.<commit_after>/****************************************************************************
**
** This file is part of QtCompositor**
**
** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
**
** Contact:  Nokia Corporation qt-info@nokia.com
**
** You may use this file under the terms of the BSD license as follows:
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**
** Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
**
** Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
**
** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/

#include "wlsurface.h"

#include "../waylandsurface.h"

#include "wlcompositor.h"
#include "wlshmbuffer.h"

#include <QtCore/QDebug>

#include <wayland-server.h>

#include <linux/input.h>

#ifdef QT_COMPOSITOR_WAYLAND_GL
#include "../graphicshardwareintegration.cpp"
#include <QtGui/QPlatformGLContext>
#endif

namespace Wayland {

class SurfacePrivate
{
public:
    SurfacePrivate(struct wl_client *client, Compositor *compositor)
        : client(client)
        , compositor(compositor)
    {
        type = WaylandSurface::Invalid;
#ifdef QT_COMPOSITOR_WAYLAND_GL
        texture_id = 0;
#endif
    }

    WaylandSurface::Type type;
    QRect rect;
    struct wl_client *client;
    Compositor *compositor;
    WaylandSurface *qtSurface;

    ShmBuffer *shm_buffer;
#ifdef QT_COMPOSITOR_WAYLAND_GL
    GLuint texture_id;
#endif
};

void surface_destroy(struct wl_client *client, struct wl_surface *surface)
{
    wl_resource_destroy(&surface->resource, client);
}

void surface_attach(struct wl_client *client, struct wl_surface *surface,
                    struct wl_buffer *buffer, int x, int y)
{
    Q_UNUSED(client);
    Q_UNUSED(x);
    Q_UNUSED(y);

    if (buffer->attach) {
        wayland_cast<Surface *>(surface)->attachShm(wayland_cast<ShmBuffer *>(buffer));
    }
#ifdef QT_COMPOSITOR_WAYLAND_GL
    else {
        wayland_cast<Surface *>(surface)->attachHWBuffer(buffer);
    }
#endif //QT_COMPOSITOR_WAYLAND_EGL
}

void surface_map_toplevel(struct wl_client *client,
                          struct wl_surface *surface)
{
    Q_UNUSED(client);
    printf("surface_map_toplevel: %p, %p", client, surface);

    wayland_cast<Surface *>(surface)->mapTopLevel();
}

void surface_map_transient(struct wl_client *client,
                      struct wl_surface *surface,
                      struct wl_surface *parent,
                      int x,
                      int y,
                      uint32_t flags)
{
    Q_UNUSED(client);
    Q_UNUSED(surface);
    Q_UNUSED(parent);
    Q_UNUSED(x);
    Q_UNUSED(y);
    Q_UNUSED(flags);
    printf("surface_map_transient: %p, %p", client, surface);
}

void surface_map_fullscreen(struct wl_client *client,
                       struct wl_surface *surface)
{
    Q_UNUSED(client);
    Q_UNUSED(surface);
    printf("surface_map_fullscreen: %p, %p", client, surface);
}

void surface_damage(struct wl_client *client, struct wl_surface *surface,
                    int32_t x, int32_t y, int32_t width, int32_t height)
{
    Q_UNUSED(client);
    wayland_cast<Surface *>(surface)->damage(QRect(x, y, width, height));
}

Surface::Surface(struct wl_client *client, Compositor *compositor)
    : d_ptr(new SurfacePrivate(client,compositor))
{
    base()->client = client;
    wl_list_init(&base()->destroy_listener_list);
    d_ptr->qtSurface = new WaylandSurface(this);

}

Surface::~Surface()
{
    Q_D(Surface);
    d->compositor->surfaceDestroyed(this);
    delete d->qtSurface;
}

WaylandSurface::Type Surface::type() const
{
    Q_D(const Surface);
    return d->type;
}

void Surface::damage(const QRect &rect)
{
    Q_D(Surface);
    emit d->qtSurface->damaged(rect);
}

QImage Surface::image() const
{
    Q_D(const Surface);
    if (d->type == WaylandSurface::Shm) {
        return d->shm_buffer->image();
    }
    return QImage();
}

#ifdef QT_COMPOSITOR_WAYLAND_GL

void Surface::attachHWBuffer(struct wl_buffer *buffer)
{
    Q_D(Surface);
    d->type = WaylandSurface::Texture;

    //make current for the topLevel. We could have used the eglContext,
    //but then we would need to handle eglSurfaces as well.
    d->compositor->topLevelWidget()->platformWindow()->glContext()->makeCurrent();

    glDeleteTextures(1,&d->texture_id);

    d->texture_id = d->compositor->graphicsHWIntegration()->createTextureFromBuffer(buffer);
    emit d->qtSurface->mapped(QRect(QPoint(), QSize(buffer->width, buffer->height)));
}

GLuint Surface::textureId() const
{
    Q_D(const Surface);
    return d->texture_id;
}
#endif // QT_COMPOSITOR_WAYLAND_GL

void Surface::attachShm(Wayland::ShmBuffer *shm_buffer)
{
    Q_D(Surface);
    d->shm_buffer = shm_buffer;
    d->type = WaylandSurface::Shm;
    emit d->qtSurface->mapped(QRect(QPoint(), shm_buffer->size()));
}

void Surface::mapTopLevel()
{
    Q_D(Surface);
    d->rect = QRect(0, 0, 200, 200);
}

WaylandSurface * Surface::handle() const
{
    Q_D(const Surface);
    return d->qtSurface;
}

uint32_t toWaylandButton(Qt::MouseButton button)
{
    switch (button) {
    case Qt::LeftButton:
        return BTN_LEFT;
    case Qt::RightButton:
        return BTN_RIGHT;
    default:
        return BTN_MIDDLE;
    }
}

void Surface::sendMousePressEvent(int x, int y, Qt::MouseButton button)
{
    Q_D(Surface);
    sendMouseMoveEvent(x, y);
    if (d->client) {
        uint32_t time = d->compositor->currentTimeMsecs();
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
                             WL_INPUT_DEVICE_BUTTON, time, toWaylandButton(button), 1);
    }
}

void Surface::sendMouseReleaseEvent(int x, int y, Qt::MouseButton button)
{
    Q_D(Surface);
    sendMouseMoveEvent(x, y);
    if (d->client) {
        uint32_t time = d->compositor->currentTimeMsecs();
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
                             WL_INPUT_DEVICE_BUTTON, time, toWaylandButton(button), 0);
    }
}

void Surface::sendMouseMoveEvent(int x, int y)
{
    Q_D(Surface);
    if (d->client) {
        uint32_t time = d->compositor->currentTimeMsecs();
        wl_input_device_set_pointer_focus(d->compositor->defaultInputDevice(),
            base(), time, x, y, x, y);
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
             WL_INPUT_DEVICE_MOTION, time, x, y, x, y);
    }
}

void Surface::sendKeyPressEvent(uint code)
{
    Q_D(Surface);
    if (d->compositor->defaultInputDevice()->keyboard_focus != NULL) {
        uint32_t time = d->compositor->currentTimeMsecs();
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
                             WL_INPUT_DEVICE_KEY, time, code - 8, 1);
    }

}

void Surface::sendKeyReleaseEvent(uint code)
{
    Q_D(Surface);
    if (d->compositor->defaultInputDevice()->keyboard_focus != NULL) {
        uint32_t time = d->compositor->currentTimeMsecs();
        wl_client_post_event(d->client, &d->compositor->defaultInputDevice()->object,
                             WL_INPUT_DEVICE_KEY, time, code - 8, 0);
    }
}

void Surface::setInputFocus()
{
    Q_D(Surface);
    ulong time = d->compositor->currentTimeMsecs();

    wl_input_device_set_keyboard_focus(d->compositor->defaultInputDevice(), base(), time);
    wl_input_device_set_pointer_focus(d->compositor->defaultInputDevice(), base(), time, 0, 0, 0, 0);
}

}
<|endoftext|>


<commit_before>/**
 * Render Pipeline C++
 *
 * Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
 * Copyright (c) 2016-2017 Center of Human-centered Interaction for Coexistence.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#pragma once

#include <boost/any.hpp>

#include "render_pipeline/rpcore/rpobject.hpp"
#include "render_pipeline/rpcore/stage_manager.hpp"
#include "rplibs/yaml.hpp"

namespace rpcore {

// ************************************************************************************************
/** This is the base setting type, all setting types derive from this. */
class BaseType : public RPObject
{
public:
    BaseType(YAML::Node& data);
    virtual ~BaseType() {}

    virtual std::string get_value_as_string() const = 0;
    const boost::any& get_value() const { return _value; }

    virtual void set_value(const YAML::Node& value) = 0;

    virtual void add_defines(const std::string& plugin_id,
        const std::string& setting_id, StageManager::DefinesType& defines) const;

    const std::string& get_type() const { return _type; }
    const std::string& get_label() const { return _label; }
    const std::string& get_description() const { return _description; }
    bool is_runtime() const { return _runtime; }
    bool is_shader_runtime() const { return _shader_runtime; }

protected:
    boost::any _value;
    std::string _type;
    std::string _label;
    std::string _description;
    bool _runtime;
    bool _shader_runtime;
    std::unordered_map<std::string, std::string> _display_conditions;
};

// ************************************************************************************************
/**
 * This setting stores a single type including a minimum and maximum value.
 * It is shared between integer and floating point types.
 */
template <class T>
class TemplatedType : public BaseType
{
public:
    TemplatedType(YAML::Node& data);

    std::string get_value_as_string() const override;
    void set_value(const YAML::Node& value) override;
    virtual void set_value(T value);

protected:
    const std::string _template_type;
    T _default;
    T _minval;
    T _maxval;
};

template <class T>
TemplatedType<T>::TemplatedType(YAML::Node& data): BaseType(data), _template_type(typeid(T).name())
{
    _default = data["default"].as<T>();
    data.remove("default");
    _value = _default;

    const std::vector<T>& setting_range = data["range"].as<std::vector<T>>();
    _minval = setting_range[0];
    _maxval = setting_range[1];
    data.remove("range");
}

template <class T>
std::string TemplatedType<T>::get_value_as_string() const
{
    return std::to_string(boost::any_cast<T>(_value));
}

template <class T>
void TemplatedType<T>::set_value(const YAML::Node& value)
{
    set_value(value.as<T>());
}

template <class T>
void TemplatedType<T>::set_value(T value)
{
    if (_minval <= value && value <= _maxval)
        _value = value;
    else
        error(std::string("Invalid value: ") + std::to_string(value));
}

// ************************************************************************************************
/** Template instantiation of TemplatedType using int. */
using IntType = TemplatedType<int>;

/** Template instantiation of TemplatedType using float. */
using FloatType = TemplatedType<float>;

// ************************************************************************************************
/** Type for any power of two resolution. */
class PowerOfTwoType : public IntType
{
public:
    PowerOfTwoType(YAML::Node& data);

    void set_value(int value) final;
};

inline PowerOfTwoType::PowerOfTwoType(YAML::Node& data): IntType(data)
{
}

inline void PowerOfTwoType::set_value(int value)
{
    if (_minval <= value && value <= _maxval)
    {
        // check if value is power of two.
        if (value && !(value & (value - 1)))
            _value = value;
        else
            error("Not a power of two: " + std::to_string(value));
    }
    else
    {
        error("Invalid value: " + std::to_string(value));
    }
}

// ************************************************************************************************
/** Boolean setting type. */
class BoolType : public BaseType
{
public:
    BoolType(YAML::Node& data);

    std::string get_value_as_string() const final;
    void set_value(const YAML::Node& value) final;
    void set_value(bool value) { _value = value; }

private:
    bool _default;
};

// ************************************************************************************************
/** Enumeration setting type. */
class EnumType : public BaseType
{
public:
    EnumType(YAML::Node& data);

    std::string get_value_as_string() const final;
    void set_value(const YAML::Node& value) final;
    void set_value(const std::string& value);
    void add_defines(const std::string& plugin_id,
        const std::string& setting_id, StageManager::DefinesType& defines) const final;

private:
    std::vector<std::string> _values;
    std::string _default;
};

// ************************************************************************************************
/** Type for any 2D or 3D sample sequence. */
class SampleSequenceType : public BaseType
{
public:
    static const std::vector<int> POISSON_2D_SIZES;
    static const std::vector<int> POISSON_3D_SIZES;
    static const std::vector<int> HALTON_SIZES;

    SampleSequenceType(YAML::Node& data);

    std::string get_value_as_string() const final;
    void set_value(const YAML::Node& value) final;
    void set_value(const std::string& value);

    std::vector<std::string> get_sequences() const;

private:
    int dimension_;
    std::string default_;
};

inline std::string SampleSequenceType::get_value_as_string() const
{
    return boost::any_cast<const std::string&>(_value);
}

inline void SampleSequenceType::set_value(const std::string& value)
{
    const auto& sequences = get_sequences();
    if (std::find(sequences.begin(), sequences.end(), value) == sequences.end())
    {
        error("Value '" + value + "' is not a valid sequence!");
        return;
    }
    _value = value;
}

// ************************************************************************************************
/** Path type to specify paths to files. */
class PathType : public BaseType
{
public:
    PathType(YAML::Node& data);

    std::string get_value_as_string() const final;
    void set_value(const YAML::Node& value) final;
    void set_value(const std::string& value);
    void add_defines(const std::string& plugin_id,
        const std::string& setting_id, StageManager::DefinesType& defines) const final;

private:
    std::string _default;
    std::string _file_type;
    std::string _base_path;
};

inline std::string PathType::get_value_as_string() const
{
    return boost::any_cast<const std::string&>(_value);
}

inline void PathType::set_value(const std::string& value)
{
    _value = value;
}

// ************************************************************************************************
/**
 * Constructs a new setting from a given dataset. This method will automatically
 * instantiate a new class matching the type of the given dataset. It will fill
 * all values provided by the dataset and then return the created instance.
 */
std::shared_ptr<BaseType> make_setting_from_data(YAML::Node& data);

}
<commit_msg>Remove unused memeber data to remove RTTI<commit_after>/**
 * Render Pipeline C++
 *
 * Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
 * Copyright (c) 2016-2017 Center of Human-centered Interaction for Coexistence.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#pragma once

#include <boost/any.hpp>

#include "render_pipeline/rpcore/rpobject.hpp"
#include "render_pipeline/rpcore/stage_manager.hpp"
#include "rplibs/yaml.hpp"

namespace rpcore {

// ************************************************************************************************
/** This is the base setting type, all setting types derive from this. */
class BaseType : public RPObject
{
public:
    BaseType(YAML::Node& data);
    virtual ~BaseType() {}

    virtual std::string get_value_as_string() const = 0;
    const boost::any& get_value() const { return _value; }

    virtual void set_value(const YAML::Node& value) = 0;

    virtual void add_defines(const std::string& plugin_id,
        const std::string& setting_id, StageManager::DefinesType& defines) const;

    const std::string& get_type() const { return _type; }
    const std::string& get_label() const { return _label; }
    const std::string& get_description() const { return _description; }
    bool is_runtime() const { return _runtime; }
    bool is_shader_runtime() const { return _shader_runtime; }

protected:
    boost::any _value;
    std::string _type;
    std::string _label;
    std::string _description;
    bool _runtime;
    bool _shader_runtime;
    std::unordered_map<std::string, std::string> _display_conditions;
};

// ************************************************************************************************
/**
 * This setting stores a single type including a minimum and maximum value.
 * It is shared between integer and floating point types.
 */
template <class T>
class TemplatedType : public BaseType
{
public:
    TemplatedType(YAML::Node& data);

    std::string get_value_as_string() const override;
    void set_value(const YAML::Node& value) override;
    virtual void set_value(T value);

protected:
    T _default;
    T _minval;
    T _maxval;
};

template <class T>
TemplatedType<T>::TemplatedType(YAML::Node& data): BaseType(data)
{
    _default = data["default"].as<T>();
    data.remove("default");
    _value = _default;

    const std::vector<T>& setting_range = data["range"].as<std::vector<T>>();
    _minval = setting_range[0];
    _maxval = setting_range[1];
    data.remove("range");
}

template <class T>
std::string TemplatedType<T>::get_value_as_string() const
{
    return std::to_string(boost::any_cast<T>(_value));
}

template <class T>
void TemplatedType<T>::set_value(const YAML::Node& value)
{
    set_value(value.as<T>());
}

template <class T>
void TemplatedType<T>::set_value(T value)
{
    if (_minval <= value && value <= _maxval)
        _value = value;
    else
        error(std::string("Invalid value: ") + std::to_string(value));
}

// ************************************************************************************************
/** Template instantiation of TemplatedType using int. */
using IntType = TemplatedType<int>;

/** Template instantiation of TemplatedType using float. */
using FloatType = TemplatedType<float>;

// ************************************************************************************************
/** Type for any power of two resolution. */
class PowerOfTwoType : public IntType
{
public:
    PowerOfTwoType(YAML::Node& data);

    void set_value(int value) final;
};

inline PowerOfTwoType::PowerOfTwoType(YAML::Node& data): IntType(data)
{
}

inline void PowerOfTwoType::set_value(int value)
{
    if (_minval <= value && value <= _maxval)
    {
        // check if value is power of two.
        if (value && !(value & (value - 1)))
            _value = value;
        else
            error("Not a power of two: " + std::to_string(value));
    }
    else
    {
        error("Invalid value: " + std::to_string(value));
    }
}

// ************************************************************************************************
/** Boolean setting type. */
class BoolType : public BaseType
{
public:
    BoolType(YAML::Node& data);

    std::string get_value_as_string() const final;
    void set_value(const YAML::Node& value) final;
    void set_value(bool value) { _value = value; }

private:
    bool _default;
};

// ************************************************************************************************
/** Enumeration setting type. */
class EnumType : public BaseType
{
public:
    EnumType(YAML::Node& data);

    std::string get_value_as_string() const final;
    void set_value(const YAML::Node& value) final;
    void set_value(const std::string& value);
    void add_defines(const std::string& plugin_id,
        const std::string& setting_id, StageManager::DefinesType& defines) const final;

private:
    std::vector<std::string> _values;
    std::string _default;
};

// ************************************************************************************************
/** Type for any 2D or 3D sample sequence. */
class SampleSequenceType : public BaseType
{
public:
    static const std::vector<int> POISSON_2D_SIZES;
    static const std::vector<int> POISSON_3D_SIZES;
    static const std::vector<int> HALTON_SIZES;

    SampleSequenceType(YAML::Node& data);

    std::string get_value_as_string() const final;
    void set_value(const YAML::Node& value) final;
    void set_value(const std::string& value);

    std::vector<std::string> get_sequences() const;

private:
    int dimension_;
    std::string default_;
};

inline std::string SampleSequenceType::get_value_as_string() const
{
    return boost::any_cast<const std::string&>(_value);
}

inline void SampleSequenceType::set_value(const std::string& value)
{
    const auto& sequences = get_sequences();
    if (std::find(sequences.begin(), sequences.end(), value) == sequences.end())
    {
        error("Value '" + value + "' is not a valid sequence!");
        return;
    }
    _value = value;
}

// ************************************************************************************************
/** Path type to specify paths to files. */
class PathType : public BaseType
{
public:
    PathType(YAML::Node& data);

    std::string get_value_as_string() const final;
    void set_value(const YAML::Node& value) final;
    void set_value(const std::string& value);
    void add_defines(const std::string& plugin_id,
        const std::string& setting_id, StageManager::DefinesType& defines) const final;

private:
    std::string _default;
    std::string _file_type;
    std::string _base_path;
};

inline std::string PathType::get_value_as_string() const
{
    return boost::any_cast<const std::string&>(_value);
}

inline void PathType::set_value(const std::string& value)
{
    _value = value;
}

// ************************************************************************************************
/**
 * Constructs a new setting from a given dataset. This method will automatically
 * instantiate a new class matching the type of the given dataset. It will fill
 * all values provided by the dataset and then return the created instance.
 */
std::shared_ptr<BaseType> make_setting_from_data(YAML::Node& data);

}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/glue/webaccessibility.h"

#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityCache.h"
#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityObject.h"
#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityRole.h"
#include "third_party/WebKit/WebKit/chromium/public/WebAttribute.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocumentType.h"
#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNamedNodeMap.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"

using WebKit::WebAccessibilityCache;
using WebKit::WebAccessibilityRole;
using WebKit::WebAccessibilityObject;

namespace webkit_glue {

// Provides a conversion between the WebKit::WebAccessibilityRole and a role
// supported on the Browser side. Listed alphabetically by the
// WebAccessibilityRole (except for default role).
WebAccessibility::Role ConvertRole(WebKit::WebAccessibilityRole role) {
  switch (role) {
    case WebKit::WebAccessibilityRoleAnnotation:
      return WebAccessibility::ROLE_ANNOTATION;
    case WebKit::WebAccessibilityRoleApplication:
      return WebAccessibility::ROLE_APPLICATION;
    case WebKit::WebAccessibilityRoleApplicationAlert:
      return WebAccessibility::ROLE_ALERT;
    case WebKit::WebAccessibilityRoleApplicationAlertDialog:
      return WebAccessibility::ROLE_ALERT_DIALOG;
    case WebKit::WebAccessibilityRoleApplicationDialog:
      return WebAccessibility::ROLE_DIALOG;
    case WebKit::WebAccessibilityRoleApplicationLog:
      return WebAccessibility::ROLE_LOG;
    case WebKit::WebAccessibilityRoleApplicationMarquee:
      return WebAccessibility::ROLE_MARQUEE;
    case WebKit::WebAccessibilityRoleApplicationStatus:
      return WebAccessibility::ROLE_STATUS;
    case WebKit::WebAccessibilityRoleApplicationTimer:
      return WebAccessibility::ROLE_TIMER;
    case WebKit::WebAccessibilityRoleBrowser:
      return WebAccessibility::ROLE_BROWSER;
    case WebKit::WebAccessibilityRoleBusyIndicator:
      return WebAccessibility::ROLE_BUSY_INDICATOR;
    case WebKit::WebAccessibilityRoleButton:
      return WebAccessibility::ROLE_BUTTON;
    case WebKit::WebAccessibilityRoleCell:
      return WebAccessibility::ROLE_CELL;
    case WebKit::WebAccessibilityRoleCheckBox:
      return WebAccessibility::ROLE_CHECKBOX;
    case WebKit::WebAccessibilityRoleColorWell:
      return WebAccessibility::ROLE_COLOR_WELL;
    case WebKit::WebAccessibilityRoleColumn:
      return WebAccessibility::ROLE_COLUMN;
    case WebKit::WebAccessibilityRoleColumnHeader:
      return WebAccessibility::ROLE_COLUMN_HEADER;
    case WebKit::WebAccessibilityRoleComboBox:
      return WebAccessibility::ROLE_COMBO_BOX;
    case WebKit::WebAccessibilityRoleDefinitionListDefinition:
      return WebAccessibility::ROLE_DEFINITION_LIST_DEFINITION;
    case WebKit::WebAccessibilityRoleDefinitionListTerm:
      return WebAccessibility::ROLE_DEFINITION_LIST_TERM;
    case WebKit::WebAccessibilityRoleDirectory:
      return WebAccessibility::ROLE_DIRECTORY;
    case WebKit::WebAccessibilityRoleDisclosureTriangle:
      return WebAccessibility::ROLE_DISCLOSURE_TRIANGLE;
    case WebKit::WebAccessibilityRoleDocument:
      return WebAccessibility::ROLE_DOCUMENT;
    case WebKit::WebAccessibilityRoleDocumentArticle:
      return WebAccessibility::ROLE_ARTICLE;
    case WebKit::WebAccessibilityRoleDocumentMath:
      return WebAccessibility::ROLE_MATH;
    case WebKit::WebAccessibilityRoleDocumentNote:
      return WebAccessibility::ROLE_NOTE;
    case WebKit::WebAccessibilityRoleDocumentRegion:
      return WebAccessibility::ROLE_REGION;
    case WebKit::WebAccessibilityRoleDrawer:
      return WebAccessibility::ROLE_DRAWER;
    case WebKit::WebAccessibilityRoleEditableText:
      return WebAccessibility::ROLE_EDITABLE_TEXT;
    case WebKit::WebAccessibilityRoleGrid:
      return WebAccessibility::ROLE_GRID;
    case WebKit::WebAccessibilityRoleGroup:
      return WebAccessibility::ROLE_GROUP;
    case WebKit::WebAccessibilityRoleGrowArea:
      return WebAccessibility::ROLE_GROW_AREA;
    case WebKit::WebAccessibilityRoleHeading:
      return WebAccessibility::ROLE_HEADING;
    case WebKit::WebAccessibilityRoleHelpTag:
      return WebAccessibility::ROLE_HELP_TAG;
    case WebKit::WebAccessibilityRoleIgnored:
      return WebAccessibility::ROLE_IGNORED;
    case WebKit::WebAccessibilityRoleImage:
      return WebAccessibility::ROLE_IMAGE;
    case WebKit::WebAccessibilityRoleImageMap:
      return WebAccessibility::ROLE_IMAGE_MAP;
    case WebKit::WebAccessibilityRoleImageMapLink:
      return WebAccessibility::ROLE_IMAGE_MAP_LINK;
    case WebKit::WebAccessibilityRoleIncrementor:
      return WebAccessibility::ROLE_INCREMENTOR;
    case WebKit::WebAccessibilityRoleLandmarkApplication:
      return WebAccessibility::ROLE_LANDMARK_APPLICATION;
    case WebKit::WebAccessibilityRoleLandmarkBanner:
      return WebAccessibility::ROLE_LANDMARK_BANNER;
    case WebKit::WebAccessibilityRoleLandmarkComplementary:
      return WebAccessibility::ROLE_LANDMARK_COMPLEMENTARY;
    case WebKit::WebAccessibilityRoleLandmarkContentInfo:
      return WebAccessibility::ROLE_LANDMARK_CONTENTINFO;
    case WebKit::WebAccessibilityRoleLandmarkMain:
      return WebAccessibility::ROLE_LANDMARK_MAIN;
    case WebKit::WebAccessibilityRoleLandmarkNavigation:
      return WebAccessibility::ROLE_LANDMARK_NAVIGATION;
    case WebKit::WebAccessibilityRoleLandmarkSearch:
      return WebAccessibility::ROLE_LANDMARK_SEARCH;
    case WebKit::WebAccessibilityRoleLink:
      return WebAccessibility::ROLE_LINK;
    case WebKit::WebAccessibilityRoleList:
      return WebAccessibility::ROLE_LIST;
    case WebKit::WebAccessibilityRoleListBox:
      return WebAccessibility::ROLE_LISTBOX;
    case WebKit::WebAccessibilityRoleListBoxOption:
      return WebAccessibility::ROLE_LISTBOX_OPTION;
    case WebKit::WebAccessibilityRoleListItem:
      return WebAccessibility::ROLE_LIST_ITEM;
    case WebKit::WebAccessibilityRoleListMarker:
      return WebAccessibility::ROLE_LIST_MARKER;
    case WebKit::WebAccessibilityRoleMatte:
      return WebAccessibility::ROLE_MATTE;
    case WebKit::WebAccessibilityRoleMenu:
      return WebAccessibility::ROLE_MENU;
    case WebKit::WebAccessibilityRoleMenuBar:
      return WebAccessibility::ROLE_MENU_BAR;
    case WebKit::WebAccessibilityRoleMenuButton:
      return WebAccessibility::ROLE_MENU_BUTTON;
    case WebKit::WebAccessibilityRoleMenuItem:
      return WebAccessibility::ROLE_MENU_ITEM;
    case WebKit::WebAccessibilityRoleMenuListOption:
      return WebAccessibility::ROLE_MENU_LIST_OPTION;
    case WebKit::WebAccessibilityRoleMenuListPopup:
      return WebAccessibility::ROLE_MENU_LIST_POPUP;
    case WebKit::WebAccessibilityRoleOutline:
      return WebAccessibility::ROLE_OUTLINE;
    case WebKit::WebAccessibilityRolePopUpButton:
      return WebAccessibility::ROLE_POPUP_BUTTON;
    case WebKit::WebAccessibilityRoleProgressIndicator:
      return WebAccessibility::ROLE_PROGRESS_INDICATOR;
    case WebKit::WebAccessibilityRoleRadioButton:
      return WebAccessibility::ROLE_RADIO_BUTTON;
    case WebKit::WebAccessibilityRoleRadioGroup:
      return WebAccessibility::ROLE_RADIO_GROUP;
    case WebKit::WebAccessibilityRoleRow:
      return WebAccessibility::ROLE_ROW;
    case WebKit::WebAccessibilityRoleRowHeader:
      return WebAccessibility::ROLE_ROW_HEADER;
    case WebKit::WebAccessibilityRoleRuler:
      return WebAccessibility::ROLE_RULER;
    case WebKit::WebAccessibilityRoleRulerMarker:
      return WebAccessibility::ROLE_RULER_MARKER;
    case WebKit::WebAccessibilityRoleScrollArea:
      return WebAccessibility::ROLE_SCROLLAREA;
    case WebKit::WebAccessibilityRoleScrollBar:
      return WebAccessibility::ROLE_SCROLLBAR;
    case WebKit::WebAccessibilityRoleSheet:
      return WebAccessibility::ROLE_SHEET;
    case WebKit::WebAccessibilityRoleSlider:
      return WebAccessibility::ROLE_SLIDER;
    case WebKit::WebAccessibilityRoleSliderThumb:
      return WebAccessibility::ROLE_SLIDER_THUMB;
    case WebKit::WebAccessibilityRoleSplitGroup:
      return WebAccessibility::ROLE_SPLIT_GROUP;
    case WebKit::WebAccessibilityRoleSplitter:
      return WebAccessibility::ROLE_SPLITTER;
    case WebKit::WebAccessibilityRoleStaticText:
      return WebAccessibility::ROLE_STATIC_TEXT;
    case WebKit::WebAccessibilityRoleSystemWide:
      return WebAccessibility::ROLE_SYSTEM_WIDE;
    case WebKit::WebAccessibilityRoleTab:
      return WebAccessibility::ROLE_TAB;
    case WebKit::WebAccessibilityRoleTabGroup:
      return WebAccessibility::ROLE_TAB_GROUP;
    case WebKit::WebAccessibilityRoleTabList:
      return WebAccessibility::ROLE_TAB_LIST;
    case WebKit::WebAccessibilityRoleTabPanel:
      return WebAccessibility::ROLE_TAB_PANEL;
    case WebKit::WebAccessibilityRoleTable:
      return WebAccessibility::ROLE_TABLE;
    case WebKit::WebAccessibilityRoleTableHeaderContainer:
      return WebAccessibility::ROLE_TABLE_HEADER_CONTAINER;
    case WebKit::WebAccessibilityRoleTextArea:
      return WebAccessibility::ROLE_TEXTAREA;
    case WebKit::WebAccessibilityRoleTextField:
      return WebAccessibility::ROLE_TEXT_FIELD;
    case WebKit::WebAccessibilityRoleToolbar:
      return WebAccessibility::ROLE_TOOLBAR;
    case WebKit::WebAccessibilityRoleTreeGrid:
      return WebAccessibility::ROLE_TREE_GRID;
    case WebKit::WebAccessibilityRoleTreeItemRole:
      return WebAccessibility::ROLE_TREE_ITEM;
    case WebKit::WebAccessibilityRoleTreeRole:
      return WebAccessibility::ROLE_TREE;
    case WebKit::WebAccessibilityRoleUserInterfaceTooltip:
      return WebAccessibility::ROLE_TOOLTIP;
    case WebKit::WebAccessibilityRoleValueIndicator:
      return WebAccessibility::ROLE_VALUE_INDICATOR;
    case WebKit::WebAccessibilityRoleWebArea:
      return WebAccessibility::ROLE_WEB_AREA;
    case WebKit::WebAccessibilityRoleWebCoreLink:
      return WebAccessibility::ROLE_WEBCORE_LINK;
    case WebKit::WebAccessibilityRoleWindow:
      return WebAccessibility::ROLE_WINDOW;

    default:
      return WebAccessibility::ROLE_UNKNOWN;
  }
}

uint32 ConvertState(const WebAccessibilityObject& o) {
  uint32 state = 0;
  if (o.isChecked())
    state |= (1 << WebAccessibility::STATE_CHECKED);

  if (o.canSetFocusAttribute())
    state |= (1 << WebAccessibility::STATE_FOCUSABLE);

  if (o.isFocused())
    state |= (1 << WebAccessibility::STATE_FOCUSED);

  if (o.isHovered())
    state |= (1 << WebAccessibility::STATE_HOTTRACKED);

  if (o.isIndeterminate())
    state |= (1 << WebAccessibility::STATE_INDETERMINATE);

  if (o.isAnchor())
    state |= (1 << WebAccessibility::STATE_LINKED);

  if (o.isMultiSelectable())
    state |= (1 << WebAccessibility::STATE_MULTISELECTABLE);

  if (o.isOffScreen())
    state |= (1 << WebAccessibility::STATE_OFFSCREEN);

  if (o.isPressed())
    state |= (1 << WebAccessibility::STATE_PRESSED);

  if (o.isPasswordField())
    state |= (1 << WebAccessibility::STATE_PROTECTED);

  if (o.isReadOnly())
    state |= (1 << WebAccessibility::STATE_READONLY);

  if (o.isVisited())
    state |= (1 << WebAccessibility::STATE_TRAVERSED);

  if (!o.isEnabled())
    state |= (1 << WebAccessibility::STATE_UNAVAILABLE);

  return state;
}

WebAccessibility::WebAccessibility()
    : id(-1),
      role(ROLE_NONE),
      state(-1) {
}

WebAccessibility::WebAccessibility(const WebKit::WebAccessibilityObject& src,
                                   WebKit::WebAccessibilityCache* cache) {
  Init(src, cache);
}

WebAccessibility::~WebAccessibility() {
}

void WebAccessibility::Init(const WebKit::WebAccessibilityObject& src,
                            WebKit::WebAccessibilityCache* cache) {
  name = src.title();
  value = src.stringValue();
  role = ConvertRole(src.roleValue());
  state = ConvertState(src);
  location = src.boundingBoxRect();

  if (src.actionVerb().length())
    attributes[ATTR_ACTION] = src.actionVerb();
  if (src.accessibilityDescription().length())
    attributes[ATTR_DESCRIPTION] = src.accessibilityDescription();
  if (src.helpText().length())
    attributes[ATTR_HELP] = src.helpText();
  if (src.keyboardShortcut().length())
    attributes[ATTR_SHORTCUT] = src.keyboardShortcut();
  if (src.hasComputedStyle())
    attributes[ATTR_DISPLAY] = src.computedStyleDisplay();

  WebKit::WebNode node = src.node();

  if (!node.isNull() && node.isElementNode()) {
    WebKit::WebElement element = node.to<WebKit::WebElement>();
    attributes[ATTR_HTML_TAG] = element.tagName();
    for (unsigned i = 0; i < element.attributes().length(); i++) {
      html_attributes.push_back(
          std::pair<string16, string16>(
              element.attributes().attributeItem(i).localName(),
              element.attributes().attributeItem(i).value()));
    }
  }

  if (role == WebAccessibility::ROLE_DOCUMENT ||
      role == WebAccessibility::ROLE_WEB_AREA) {
    WebKit::WebDocument document = src.document();
    attributes[ATTR_DOC_TITLE] = document.title();
    attributes[ATTR_DOC_URL] = document.frame()->url().spec().utf16();
    if (document.isXHTMLDocument())
      attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/xhtml");
    else
      attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/html");

    WebKit::WebDocumentType doctype = document.doctype();
    if (!doctype.isNull())
      attributes[ATTR_DOC_DOCTYPE] = doctype.name();
  }

  // Add the source object to the cache and store its id.
  id = cache->addOrGetId(src);

  // Recursively create children.
  int child_count = src.childCount();
  children.resize(child_count);
  for (int i = 0; i < child_count; i++) {
    children[i].Init(src.childAt(i), cache);
  }
}

}  // namespace webkit_glue
<commit_msg>Don't add invalid webkit accessibility objects to the renderer accessibility tree.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/glue/webaccessibility.h"

#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityCache.h"
#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityObject.h"
#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityRole.h"
#include "third_party/WebKit/WebKit/chromium/public/WebAttribute.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocumentType.h"
#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNamedNodeMap.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"

using WebKit::WebAccessibilityCache;
using WebKit::WebAccessibilityRole;
using WebKit::WebAccessibilityObject;

namespace webkit_glue {

// Provides a conversion between the WebKit::WebAccessibilityRole and a role
// supported on the Browser side. Listed alphabetically by the
// WebAccessibilityRole (except for default role).
WebAccessibility::Role ConvertRole(WebKit::WebAccessibilityRole role) {
  switch (role) {
    case WebKit::WebAccessibilityRoleAnnotation:
      return WebAccessibility::ROLE_ANNOTATION;
    case WebKit::WebAccessibilityRoleApplication:
      return WebAccessibility::ROLE_APPLICATION;
    case WebKit::WebAccessibilityRoleApplicationAlert:
      return WebAccessibility::ROLE_ALERT;
    case WebKit::WebAccessibilityRoleApplicationAlertDialog:
      return WebAccessibility::ROLE_ALERT_DIALOG;
    case WebKit::WebAccessibilityRoleApplicationDialog:
      return WebAccessibility::ROLE_DIALOG;
    case WebKit::WebAccessibilityRoleApplicationLog:
      return WebAccessibility::ROLE_LOG;
    case WebKit::WebAccessibilityRoleApplicationMarquee:
      return WebAccessibility::ROLE_MARQUEE;
    case WebKit::WebAccessibilityRoleApplicationStatus:
      return WebAccessibility::ROLE_STATUS;
    case WebKit::WebAccessibilityRoleApplicationTimer:
      return WebAccessibility::ROLE_TIMER;
    case WebKit::WebAccessibilityRoleBrowser:
      return WebAccessibility::ROLE_BROWSER;
    case WebKit::WebAccessibilityRoleBusyIndicator:
      return WebAccessibility::ROLE_BUSY_INDICATOR;
    case WebKit::WebAccessibilityRoleButton:
      return WebAccessibility::ROLE_BUTTON;
    case WebKit::WebAccessibilityRoleCell:
      return WebAccessibility::ROLE_CELL;
    case WebKit::WebAccessibilityRoleCheckBox:
      return WebAccessibility::ROLE_CHECKBOX;
    case WebKit::WebAccessibilityRoleColorWell:
      return WebAccessibility::ROLE_COLOR_WELL;
    case WebKit::WebAccessibilityRoleColumn:
      return WebAccessibility::ROLE_COLUMN;
    case WebKit::WebAccessibilityRoleColumnHeader:
      return WebAccessibility::ROLE_COLUMN_HEADER;
    case WebKit::WebAccessibilityRoleComboBox:
      return WebAccessibility::ROLE_COMBO_BOX;
    case WebKit::WebAccessibilityRoleDefinitionListDefinition:
      return WebAccessibility::ROLE_DEFINITION_LIST_DEFINITION;
    case WebKit::WebAccessibilityRoleDefinitionListTerm:
      return WebAccessibility::ROLE_DEFINITION_LIST_TERM;
    case WebKit::WebAccessibilityRoleDirectory:
      return WebAccessibility::ROLE_DIRECTORY;
    case WebKit::WebAccessibilityRoleDisclosureTriangle:
      return WebAccessibility::ROLE_DISCLOSURE_TRIANGLE;
    case WebKit::WebAccessibilityRoleDocument:
      return WebAccessibility::ROLE_DOCUMENT;
    case WebKit::WebAccessibilityRoleDocumentArticle:
      return WebAccessibility::ROLE_ARTICLE;
    case WebKit::WebAccessibilityRoleDocumentMath:
      return WebAccessibility::ROLE_MATH;
    case WebKit::WebAccessibilityRoleDocumentNote:
      return WebAccessibility::ROLE_NOTE;
    case WebKit::WebAccessibilityRoleDocumentRegion:
      return WebAccessibility::ROLE_REGION;
    case WebKit::WebAccessibilityRoleDrawer:
      return WebAccessibility::ROLE_DRAWER;
    case WebKit::WebAccessibilityRoleEditableText:
      return WebAccessibility::ROLE_EDITABLE_TEXT;
    case WebKit::WebAccessibilityRoleGrid:
      return WebAccessibility::ROLE_GRID;
    case WebKit::WebAccessibilityRoleGroup:
      return WebAccessibility::ROLE_GROUP;
    case WebKit::WebAccessibilityRoleGrowArea:
      return WebAccessibility::ROLE_GROW_AREA;
    case WebKit::WebAccessibilityRoleHeading:
      return WebAccessibility::ROLE_HEADING;
    case WebKit::WebAccessibilityRoleHelpTag:
      return WebAccessibility::ROLE_HELP_TAG;
    case WebKit::WebAccessibilityRoleIgnored:
      return WebAccessibility::ROLE_IGNORED;
    case WebKit::WebAccessibilityRoleImage:
      return WebAccessibility::ROLE_IMAGE;
    case WebKit::WebAccessibilityRoleImageMap:
      return WebAccessibility::ROLE_IMAGE_MAP;
    case WebKit::WebAccessibilityRoleImageMapLink:
      return WebAccessibility::ROLE_IMAGE_MAP_LINK;
    case WebKit::WebAccessibilityRoleIncrementor:
      return WebAccessibility::ROLE_INCREMENTOR;
    case WebKit::WebAccessibilityRoleLandmarkApplication:
      return WebAccessibility::ROLE_LANDMARK_APPLICATION;
    case WebKit::WebAccessibilityRoleLandmarkBanner:
      return WebAccessibility::ROLE_LANDMARK_BANNER;
    case WebKit::WebAccessibilityRoleLandmarkComplementary:
      return WebAccessibility::ROLE_LANDMARK_COMPLEMENTARY;
    case WebKit::WebAccessibilityRoleLandmarkContentInfo:
      return WebAccessibility::ROLE_LANDMARK_CONTENTINFO;
    case WebKit::WebAccessibilityRoleLandmarkMain:
      return WebAccessibility::ROLE_LANDMARK_MAIN;
    case WebKit::WebAccessibilityRoleLandmarkNavigation:
      return WebAccessibility::ROLE_LANDMARK_NAVIGATION;
    case WebKit::WebAccessibilityRoleLandmarkSearch:
      return WebAccessibility::ROLE_LANDMARK_SEARCH;
    case WebKit::WebAccessibilityRoleLink:
      return WebAccessibility::ROLE_LINK;
    case WebKit::WebAccessibilityRoleList:
      return WebAccessibility::ROLE_LIST;
    case WebKit::WebAccessibilityRoleListBox:
      return WebAccessibility::ROLE_LISTBOX;
    case WebKit::WebAccessibilityRoleListBoxOption:
      return WebAccessibility::ROLE_LISTBOX_OPTION;
    case WebKit::WebAccessibilityRoleListItem:
      return WebAccessibility::ROLE_LIST_ITEM;
    case WebKit::WebAccessibilityRoleListMarker:
      return WebAccessibility::ROLE_LIST_MARKER;
    case WebKit::WebAccessibilityRoleMatte:
      return WebAccessibility::ROLE_MATTE;
    case WebKit::WebAccessibilityRoleMenu:
      return WebAccessibility::ROLE_MENU;
    case WebKit::WebAccessibilityRoleMenuBar:
      return WebAccessibility::ROLE_MENU_BAR;
    case WebKit::WebAccessibilityRoleMenuButton:
      return WebAccessibility::ROLE_MENU_BUTTON;
    case WebKit::WebAccessibilityRoleMenuItem:
      return WebAccessibility::ROLE_MENU_ITEM;
    case WebKit::WebAccessibilityRoleMenuListOption:
      return WebAccessibility::ROLE_MENU_LIST_OPTION;
    case WebKit::WebAccessibilityRoleMenuListPopup:
      return WebAccessibility::ROLE_MENU_LIST_POPUP;
    case WebKit::WebAccessibilityRoleOutline:
      return WebAccessibility::ROLE_OUTLINE;
    case WebKit::WebAccessibilityRolePopUpButton:
      return WebAccessibility::ROLE_POPUP_BUTTON;
    case WebKit::WebAccessibilityRoleProgressIndicator:
      return WebAccessibility::ROLE_PROGRESS_INDICATOR;
    case WebKit::WebAccessibilityRoleRadioButton:
      return WebAccessibility::ROLE_RADIO_BUTTON;
    case WebKit::WebAccessibilityRoleRadioGroup:
      return WebAccessibility::ROLE_RADIO_GROUP;
    case WebKit::WebAccessibilityRoleRow:
      return WebAccessibility::ROLE_ROW;
    case WebKit::WebAccessibilityRoleRowHeader:
      return WebAccessibility::ROLE_ROW_HEADER;
    case WebKit::WebAccessibilityRoleRuler:
      return WebAccessibility::ROLE_RULER;
    case WebKit::WebAccessibilityRoleRulerMarker:
      return WebAccessibility::ROLE_RULER_MARKER;
    case WebKit::WebAccessibilityRoleScrollArea:
      return WebAccessibility::ROLE_SCROLLAREA;
    case WebKit::WebAccessibilityRoleScrollBar:
      return WebAccessibility::ROLE_SCROLLBAR;
    case WebKit::WebAccessibilityRoleSheet:
      return WebAccessibility::ROLE_SHEET;
    case WebKit::WebAccessibilityRoleSlider:
      return WebAccessibility::ROLE_SLIDER;
    case WebKit::WebAccessibilityRoleSliderThumb:
      return WebAccessibility::ROLE_SLIDER_THUMB;
    case WebKit::WebAccessibilityRoleSplitGroup:
      return WebAccessibility::ROLE_SPLIT_GROUP;
    case WebKit::WebAccessibilityRoleSplitter:
      return WebAccessibility::ROLE_SPLITTER;
    case WebKit::WebAccessibilityRoleStaticText:
      return WebAccessibility::ROLE_STATIC_TEXT;
    case WebKit::WebAccessibilityRoleSystemWide:
      return WebAccessibility::ROLE_SYSTEM_WIDE;
    case WebKit::WebAccessibilityRoleTab:
      return WebAccessibility::ROLE_TAB;
    case WebKit::WebAccessibilityRoleTabGroup:
      return WebAccessibility::ROLE_TAB_GROUP;
    case WebKit::WebAccessibilityRoleTabList:
      return WebAccessibility::ROLE_TAB_LIST;
    case WebKit::WebAccessibilityRoleTabPanel:
      return WebAccessibility::ROLE_TAB_PANEL;
    case WebKit::WebAccessibilityRoleTable:
      return WebAccessibility::ROLE_TABLE;
    case WebKit::WebAccessibilityRoleTableHeaderContainer:
      return WebAccessibility::ROLE_TABLE_HEADER_CONTAINER;
    case WebKit::WebAccessibilityRoleTextArea:
      return WebAccessibility::ROLE_TEXTAREA;
    case WebKit::WebAccessibilityRoleTextField:
      return WebAccessibility::ROLE_TEXT_FIELD;
    case WebKit::WebAccessibilityRoleToolbar:
      return WebAccessibility::ROLE_TOOLBAR;
    case WebKit::WebAccessibilityRoleTreeGrid:
      return WebAccessibility::ROLE_TREE_GRID;
    case WebKit::WebAccessibilityRoleTreeItemRole:
      return WebAccessibility::ROLE_TREE_ITEM;
    case WebKit::WebAccessibilityRoleTreeRole:
      return WebAccessibility::ROLE_TREE;
    case WebKit::WebAccessibilityRoleUserInterfaceTooltip:
      return WebAccessibility::ROLE_TOOLTIP;
    case WebKit::WebAccessibilityRoleValueIndicator:
      return WebAccessibility::ROLE_VALUE_INDICATOR;
    case WebKit::WebAccessibilityRoleWebArea:
      return WebAccessibility::ROLE_WEB_AREA;
    case WebKit::WebAccessibilityRoleWebCoreLink:
      return WebAccessibility::ROLE_WEBCORE_LINK;
    case WebKit::WebAccessibilityRoleWindow:
      return WebAccessibility::ROLE_WINDOW;

    default:
      return WebAccessibility::ROLE_UNKNOWN;
  }
}

uint32 ConvertState(const WebAccessibilityObject& o) {
  uint32 state = 0;
  if (o.isChecked())
    state |= (1 << WebAccessibility::STATE_CHECKED);

  if (o.canSetFocusAttribute())
    state |= (1 << WebAccessibility::STATE_FOCUSABLE);

  if (o.isFocused())
    state |= (1 << WebAccessibility::STATE_FOCUSED);

  if (o.isHovered())
    state |= (1 << WebAccessibility::STATE_HOTTRACKED);

  if (o.isIndeterminate())
    state |= (1 << WebAccessibility::STATE_INDETERMINATE);

  if (o.isAnchor())
    state |= (1 << WebAccessibility::STATE_LINKED);

  if (o.isMultiSelectable())
    state |= (1 << WebAccessibility::STATE_MULTISELECTABLE);

  if (o.isOffScreen())
    state |= (1 << WebAccessibility::STATE_OFFSCREEN);

  if (o.isPressed())
    state |= (1 << WebAccessibility::STATE_PRESSED);

  if (o.isPasswordField())
    state |= (1 << WebAccessibility::STATE_PROTECTED);

  if (o.isReadOnly())
    state |= (1 << WebAccessibility::STATE_READONLY);

  if (o.isVisited())
    state |= (1 << WebAccessibility::STATE_TRAVERSED);

  if (!o.isEnabled())
    state |= (1 << WebAccessibility::STATE_UNAVAILABLE);

  return state;
}

WebAccessibility::WebAccessibility()
    : id(-1),
      role(ROLE_NONE),
      state(-1) {
}

WebAccessibility::WebAccessibility(const WebKit::WebAccessibilityObject& src,
                                   WebKit::WebAccessibilityCache* cache) {
  Init(src, cache);
}

WebAccessibility::~WebAccessibility() {
}

void WebAccessibility::Init(const WebKit::WebAccessibilityObject& src,
                            WebKit::WebAccessibilityCache* cache) {
  name = src.title();
  value = src.stringValue();
  role = ConvertRole(src.roleValue());
  state = ConvertState(src);
  location = src.boundingBoxRect();

  if (src.actionVerb().length())
    attributes[ATTR_ACTION] = src.actionVerb();
  if (src.accessibilityDescription().length())
    attributes[ATTR_DESCRIPTION] = src.accessibilityDescription();
  if (src.helpText().length())
    attributes[ATTR_HELP] = src.helpText();
  if (src.keyboardShortcut().length())
    attributes[ATTR_SHORTCUT] = src.keyboardShortcut();
  if (src.hasComputedStyle())
    attributes[ATTR_DISPLAY] = src.computedStyleDisplay();

  WebKit::WebNode node = src.node();

  if (!node.isNull() && node.isElementNode()) {
    WebKit::WebElement element = node.to<WebKit::WebElement>();
    attributes[ATTR_HTML_TAG] = element.tagName();
    for (unsigned i = 0; i < element.attributes().length(); i++) {
      html_attributes.push_back(
          std::pair<string16, string16>(
              element.attributes().attributeItem(i).localName(),
              element.attributes().attributeItem(i).value()));
    }
  }

  if (role == WebAccessibility::ROLE_DOCUMENT ||
      role == WebAccessibility::ROLE_WEB_AREA) {
    WebKit::WebDocument document = src.document();
    attributes[ATTR_DOC_TITLE] = document.title();
    attributes[ATTR_DOC_URL] = document.frame()->url().spec().utf16();
    if (document.isXHTMLDocument())
      attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/xhtml");
    else
      attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/html");

    WebKit::WebDocumentType doctype = document.doctype();
    if (!doctype.isNull())
      attributes[ATTR_DOC_DOCTYPE] = doctype.name();
  }

  // Add the source object to the cache and store its id.
  id = cache->addOrGetId(src);

  // Recursively create children.
  int child_count = src.childCount();
  for (int i = 0; i < child_count; i++) {
    WebAccessibilityObject child = src.childAt(i);

    // The child may be invalid due to issues in webkit accessibility code.
    // Don't add children are invalid thus preventing a crash.
    // https://bugs.webkit.org/show_bug.cgi?id=44149
    // TODO(ctguil): We may want to remove this check as webkit stabilizes.
    if (child.isValid())
      children.push_back(WebAccessibility(child, cache));
  }
}

}  // namespace webkit_glue
<|endoftext|>


<commit_before>/***************************************************************************
 *  algo/sort_file.cpp
 *
 *  Part of the STXXL. See http://stxxl.sourceforge.net
 *
 *  Copyright (C) 2002-2003 Roman Dementiev <dementiev@mpi-sb.mpg.de>
 *  Copyright (C) 2009 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt)
 **************************************************************************/

//! \example algo/sort_file.cpp
//! This example imports a file into an \c stxxl::vector without copying its
//! content and then sorts it using stxxl::sort / stxxl::ksort / ...

#include <stxxl/io>
#include <stxxl/mng>
#include <stxxl/ksort>
#include <stxxl/sort>
#include <stxxl/stable_ksort>
#include <stxxl/vector>

struct my_type
{
    typedef unsigned key_type;

    key_type _key;
    char _data[128 - sizeof(key_type)];
    key_type key() const
    {
        return _key;
    }

    my_type() { }
    my_type(key_type __key) : _key(__key) { }

    static my_type min_value()
    {
        return my_type((std::numeric_limits<key_type>::min)());
    }
    static my_type max_value()
    {
        return my_type((std::numeric_limits<key_type>::max)());
    }
};

inline bool operator < (const my_type & a, const my_type & b)
{
    return a.key() < b.key();
}

inline bool operator == (const my_type & a, const my_type & b)
{
    return a.key() == b.key();
}

struct Cmp
{
    bool operator () (const my_type & a, const my_type & b) const
    {
        return a < b;
    }
    static my_type min_value()
    {
        return my_type::min_value();
    }
    static my_type max_value()
    {
        return my_type::max_value();
    }
};

std::ostream & operator << (std::ostream & o, const my_type & obj)
{
    o << obj._key;
    return o;
}

int main(int argc, char ** argv)
{
    if (argc < 3)
    {
        std::cout << "Usage: " << argv[0] << " action file" << std::endl;
        std::cout << "       where action is one of generate, sort, ksort, stable_sort, stable_ksort" << std::endl;
        return -1;
    }

    if (strcasecmp(argv[1], "generate") == 0) {
        const my_type::key_type max_key = 1 * 1024 * 1024;
        const unsigned int block_size = 1 * 1024 * 1024;
        const unsigned int records_in_block = block_size / sizeof(my_type);
        stxxl::syscall_file f(argv[2], stxxl::file::CREAT | stxxl::file::RDWR);
        my_type * array = (my_type *)stxxl::aligned_alloc<BLOCK_ALIGN>(block_size);
        memset(array, 0, block_size);

        my_type::key_type cur_key = max_key;
        for (unsigned i = 0; i < max_key / records_in_block; i++)
        {
            for (unsigned j = 0; j < records_in_block; j++)
                array[j]._key = cur_key--;

            stxxl::request_ptr req = f.awrite((void *)array, stxxl::int64(i) * block_size, block_size, stxxl::default_completion_handler());
            req->wait();
        }
        stxxl::aligned_dealloc<BLOCK_ALIGN>(array);
    } else {
        stxxl::syscall_file f(argv[2], stxxl::file::DIRECT | stxxl::file::RDWR);
        unsigned memory_to_use = 50 * 1024 * 1024;
        typedef stxxl::vector<my_type> vector_type;
        vector_type v(&f);

        /*
        STXXL_MSG("Printing...");
        for(stxxl::int64 i=0; i < v.size(); i++)
            STXXL_MSG(v[i].key());
         */

        STXXL_MSG("Checking order...");
        STXXL_MSG((stxxl::is_sorted(v.begin(), v.end()) ? "OK" : "WRONG"));

        STXXL_MSG("Sorting...");
        if (strcasecmp(argv[1], "sort") == 0) {
            stxxl::sort(v.begin(), v.end(), Cmp(), memory_to_use);
        /* stable_sort is not yet implemented
        } else if (strcasecmp(argv[1], "stable_sort") == 0) {
            stxxl::stable_sort(v.begin(), v.end(), memory_to_use);
        */
        } else if (strcasecmp(argv[1], "ksort") == 0) {
            stxxl::ksort(v.begin(), v.end(), memory_to_use);
        } else if (strcasecmp(argv[1], "stable_ksort") == 0) {
            stxxl::stable_ksort(v.begin(), v.end(), memory_to_use);
        } else {
            STXXL_MSG("Not implemented: " << argv[1]);
        }

        STXXL_MSG("Checking order...");
        STXXL_MSG((stxxl::is_sorted(v.begin(), v.end()) ? "OK" : "WRONG"));
    }

    return 0;
}

// vim: et:ts=4:sw=4
<commit_msg>adjust sort_file for mcstl usage<commit_after>/***************************************************************************
 *  algo/sort_file.cpp
 *
 *  Part of the STXXL. See http://stxxl.sourceforge.net
 *
 *  Copyright (C) 2002-2003 Roman Dementiev <dementiev@mpi-sb.mpg.de>
 *  Copyright (C) 2009 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt)
 **************************************************************************/

//! \example algo/sort_file.cpp
//! This example imports a file into an \c stxxl::vector without copying its
//! content and then sorts it using stxxl::sort / stxxl::ksort / ...

#include <stxxl/io>
#include <stxxl/mng>
#include <stxxl/ksort>
#include <stxxl/sort>
#include <stxxl/stable_ksort>
#include <stxxl/vector>

struct my_type
{
    typedef unsigned key_type;

    key_type _key;
    char _data[128 - sizeof(key_type)];
    key_type key() const
    {
        return _key;
    }

    my_type() { }
    my_type(key_type __key) : _key(__key) { }

    static my_type min_value()
    {
        return my_type((std::numeric_limits<key_type>::min)());
    }
    static my_type max_value()
    {
        return my_type((std::numeric_limits<key_type>::max)());
    }
};

inline bool operator < (const my_type & a, const my_type & b)
{
    return a.key() < b.key();
}

inline bool operator == (const my_type & a, const my_type & b)
{
    return a.key() == b.key();
}

struct Cmp
{
    typedef my_type first_argument_type;
    typedef my_type second_argument_type;
    typedef bool result_type;
    bool operator () (const my_type & a, const my_type & b) const
    {
        return a < b;
    }
    static my_type min_value()
    {
        return my_type::min_value();
    }
    static my_type max_value()
    {
        return my_type::max_value();
    }
};

std::ostream & operator << (std::ostream & o, const my_type & obj)
{
    o << obj._key;
    return o;
}

int main(int argc, char ** argv)
{
    if (argc < 3)
    {
        std::cout << "Usage: " << argv[0] << " action file" << std::endl;
        std::cout << "       where action is one of generate, sort, ksort, stable_sort, stable_ksort" << std::endl;
        return -1;
    }

    if (strcasecmp(argv[1], "generate") == 0) {
        const my_type::key_type max_key = 1 * 1024 * 1024;
        const unsigned int block_size = 1 * 1024 * 1024;
        const unsigned int records_in_block = block_size / sizeof(my_type);
        stxxl::syscall_file f(argv[2], stxxl::file::CREAT | stxxl::file::RDWR);
        my_type * array = (my_type *)stxxl::aligned_alloc<BLOCK_ALIGN>(block_size);
        memset(array, 0, block_size);

        my_type::key_type cur_key = max_key;
        for (unsigned i = 0; i < max_key / records_in_block; i++)
        {
            for (unsigned j = 0; j < records_in_block; j++)
                array[j]._key = cur_key--;

            stxxl::request_ptr req = f.awrite((void *)array, stxxl::int64(i) * block_size, block_size, stxxl::default_completion_handler());
            req->wait();
        }
        stxxl::aligned_dealloc<BLOCK_ALIGN>(array);
    } else {
        stxxl::syscall_file f(argv[2], stxxl::file::DIRECT | stxxl::file::RDWR);
        unsigned memory_to_use = 50 * 1024 * 1024;
        typedef stxxl::vector<my_type> vector_type;
        vector_type v(&f);

        /*
        STXXL_MSG("Printing...");
        for(stxxl::int64 i=0; i < v.size(); i++)
            STXXL_MSG(v[i].key());
         */

        STXXL_MSG("Checking order...");
        STXXL_MSG((stxxl::is_sorted(v.begin(), v.end()) ? "OK" : "WRONG"));

        STXXL_MSG("Sorting...");
        if (strcasecmp(argv[1], "sort") == 0) {
            stxxl::sort(v.begin(), v.end(), Cmp(), memory_to_use);
        /* stable_sort is not yet implemented
        } else if (strcasecmp(argv[1], "stable_sort") == 0) {
            stxxl::stable_sort(v.begin(), v.end(), memory_to_use);
        */
        } else if (strcasecmp(argv[1], "ksort") == 0) {
            stxxl::ksort(v.begin(), v.end(), memory_to_use);
        } else if (strcasecmp(argv[1], "stable_ksort") == 0) {
            stxxl::stable_ksort(v.begin(), v.end(), memory_to_use);
        } else {
            STXXL_MSG("Not implemented: " << argv[1]);
        }

        STXXL_MSG("Checking order...");
        STXXL_MSG((stxxl::is_sorted(v.begin(), v.end()) ? "OK" : "WRONG"));
    }

    return 0;
}

// vim: et:ts=4:sw=4
<|endoftext|>