text:
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/QDebug>

#include "qxcbconnection.h"
#include "qxcbkeyboard.h"
#include "qxcbscreen.h"
#include "qxcbwindow.h"
#include "qxcbclipboard.h"
#include "qxcbdrag.h"
#include "qxcbwmsupport.h"
#include "qxcbnativeinterface.h"
#include "qxcbintegration.h"
#include "qxcbsystemtraytracker.h"

#include <QSocketNotifier>
#include <QAbstractEventDispatcher>
#include <QTimer>
#include <QByteArray>

#include <algorithm>

#include <dlfcn.h>
#include <stdio.h>
#include <errno.h>
#include <xcb/shm.h>
#include <xcb/sync.h>
#include <xcb/xfixes.h>

#ifdef XCB_USE_XLIB
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <X11/Xlibint.h>
#endif

#if defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO)
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XI2proto.h>
#endif

#ifdef XCB_USE_RENDER
#include <xcb/render.h>
#endif

#if defined(XCB_HAS_XCB_GLX)
#include <xcb/glx.h>
#endif

#ifdef XCB_USE_EGL //don't pull in eglext prototypes
#include <EGL/egl.h>
#endif

QT_BEGIN_NAMESPACE

#ifdef XCB_USE_XLIB
static const char * const xcbConnectionErrors[] = {
    "No error", /* Error 0 */
    "I/O error", /* XCB_CONN_ERROR */
    "Unsupported extension used", /* XCB_CONN_CLOSED_EXT_NOTSUPPORTED */
    "Out of memory", /* XCB_CONN_CLOSED_MEM_INSUFFICIENT */
    "Maximum allowed requested length exceeded", /* XCB_CONN_CLOSED_REQ_LEN_EXCEED */
    "Failed to parse display string", /* XCB_CONN_CLOSED_PARSE_ERR */
    "No such screen on display", /* XCB_CONN_CLOSED_INVALID_SCREEN */
    "Error during FD passing" /* XCB_CONN_CLOSED_FDPASSING_FAILED */
};

static int nullErrorHandler(Display *, XErrorEvent *)
{
    return 0;
}

static int ioErrorHandler(Display *dpy)
{
    xcb_connection_t *conn = XGetXCBConnection(dpy);
    if (conn != NULL) {
        /* Print a message with a textual description of the error */
        int code = xcb_connection_has_error(conn);
        const char *str = "Unknown error";
        int arrayLength = sizeof(xcbConnectionErrors) / sizeof(xcbConnectionErrors[0]);
        if (code >= 0 && code < arrayLength)
            str = xcbConnectionErrors[code];

        qWarning("The X11 connection broke: %s (code %d)", str, code);
    }
    return _XDefaultIOError(dpy);
}
#endif

QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens,
    int screenNumber, xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output)
{
    QString name;
    if (output)
        name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output),
                xcb_randr_get_output_info_name_length(output));
    else {
        QByteArray displayName = m_displayName;
        int dotPos = displayName.lastIndexOf('.');
        if (dotPos != -1)
            displayName.truncate(dotPos);
        name = displayName + QLatin1Char('.') + QString::number(screenNumber);
    }
    foreach (QXcbScreen* scr, m_screens)
        if (scr->name() == name && scr->root() == xcbScreen->root)
            return scr;
    QXcbScreen *ret = new QXcbScreen(this, xcbScreen, output, name, screenNumber);
    newScreens << ret;
    return ret;
}

/*!
    \brief Synchronizes the screen list, adds new screens, removes deleted ones
*/
void QXcbConnection::updateScreens()
{
    xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
    int screenNumber = 0;       // index of this QScreen in QGuiApplication::screens()
    int xcbScreenNumber = 0;    // screen number in the xcb sense
    QSet<QXcbScreen *> activeScreens;
    QList<QXcbScreen *> newScreens;
    QXcbScreen* primaryScreen = NULL;
    while (it.rem) {
        // Each "screen" in xcb terminology is a virtual desktop,
        // potentially a collection of separate juxtaposed monitors.
        // But we want a separate QScreen for each output (e.g. DVI-I-1, VGA-1, etc.)
        // which will become virtual siblings.
        xcb_screen_t *xcbScreen = it.data;
        QList<QPlatformScreen *> siblings;
        int outputCount = 0;
        if (has_randr_extension) {
            xcb_generic_error_t *error = NULL;
            xcb_randr_get_output_primary_cookie_t primaryCookie =
                xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root);
            xcb_randr_get_screen_resources_cookie_t resourcesCookie =
                xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root);
            xcb_randr_get_output_primary_reply_t *primary =
                    xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error);
            if (!primary || error) {
                qWarning("QXcbConnection: Failed to get the primary output of the screen");
                free(error);
            } else {
                xcb_randr_get_screen_resources_reply_t *resources =
                        xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error);
                if (!resources || error) {
                    qWarning("QXcbConnection: Failed to get the screen resources");
                    free(error);
                } else {
                    xcb_timestamp_t timestamp = resources->config_timestamp;
                    outputCount = xcb_randr_get_screen_resources_outputs_length(resources);
                    xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources);

                    for (int i = 0; i < outputCount; i++) {
                        xcb_randr_get_output_info_reply_t *output =
                                xcb_randr_get_output_info_reply(xcb_connection(),
                                    xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL);
                        if (output == NULL)
                            continue;

#ifdef Q_XCB_DEBUG
                        QString outputName = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output),
                                                               xcb_randr_get_output_info_name_length(output));
#endif

                        if (output->crtc == XCB_NONE) {
#ifdef Q_XCB_DEBUG
                            qDebug("Screen output %s is not connected", qPrintable(outputName));
#endif
                            continue;
                        }

                        QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen, output);
                        siblings << screen;
                        activeScreens << screen;
                        ++screenNumber;
                        // There can be multiple outputs per screen, use either
                        // the first or an exact match.  An exact match isn't
                        // always available if primary->output is XCB_NONE
                        // or currently disconnected output.
                        if (m_primaryScreen == xcbScreenNumber) {
                            if (!primaryScreen || (primary && outputs[i] == primary->output)) {
                                primaryScreen = screen;
                                siblings.prepend(siblings.takeLast());
#ifdef Q_XCB_DEBUG
                                qDebug("Primary output is %d: %s", primary->output, qPrintable(outputName));
#endif
                            }
                        }
                        free(output);
                    }
                }
                free(resources);
            }
            free(primary);
        }
        // If there's no randr extension, or there was some error above, or the screen
        // doesn't have outputs for some other reason (e.g. on VNC or ssh -X), just assume there is one screen.
        if (outputCount == 0) {
#ifdef Q_XCB_DEBUG
                qDebug("Found a screen with zero outputs");
#endif
            QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen);
            siblings << screen;
            activeScreens << screen;
            if (!primaryScreen)
                primaryScreen = screen;
            ++screenNumber;
        }
        foreach (QPlatformScreen* s, siblings)
            ((QXcbScreen*)s)->setVirtualSiblings(siblings);
        xcb_screen_next(&it);
        ++xcbScreenNumber;
    } // for each xcb screen

    // Now activeScreens is the complete set of screens which are active at this time.
    // Delete any existing screens which are not in activeScreens
    for (int i = m_screens.count() - 1; i >= 0; --i) {
        if (!activeScreens.contains(m_screens[i])) {
            delete m_screens[i];
            m_screens.removeAt(i);
        }
    }

    // Add any new screens, and make sure the primary screen comes first
    // since it is used by QGuiApplication::primaryScreen()
    foreach (QXcbScreen* screen, newScreens) {
        if (screen == primaryScreen)
            m_screens.prepend(screen);
        else
            m_screens.append(screen);
    }

    // Now that they are in the right order, emit the added signals for new screens only
    foreach (QXcbScreen* screen, m_screens)
        if (newScreens.contains(screen))
            ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->screenAdded(screen);
}

QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName)
    : m_connection(0)
    , m_canGrabServer(canGrabServer)
    , m_primaryScreen(0)
    , m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
    , m_nativeInterface(nativeInterface)
#ifdef XCB_USE_XINPUT2_MAEMO
    , m_xinputData(0)
#endif
    , xfixes_first_event(0)
    , xrandr_first_event(0)
    , xkb_first_event(0)
    , has_glx_extension(false)
    , has_shape_extension(false)
    , has_randr_extension(false)
    , has_input_shape(false)
    , has_touch_without_mouse_emulation(false)
    , has_xkb(false)
    , debug_xinput_devices(false)
    , debug_xinput(false)
    , m_buttons(0)
    , m_focusWindow(0)
    , m_systemTrayTracker(0)
{
#ifdef XCB_USE_EGL
    EGLNativeDisplayType dpy = EGL_DEFAULT_DISPLAY;
#elif defined(XCB_USE_XLIB)
    Display *dpy;
#endif
#ifdef XCB_USE_XLIB
    dpy = XOpenDisplay(m_displayName.constData());
    if (dpy) {
        m_primaryScreen = DefaultScreen(dpy);
        m_connection = XGetXCBConnection(dpy);
        XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
        XSetErrorHandler(nullErrorHandler);
        XSetIOErrorHandler(ioErrorHandler);
        m_xlib_display = dpy;
    }
#else
    m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreen);
#endif //XCB_USE_XLIB

    if (!m_connection || xcb_connection_has_error(m_connection))
        qFatal("QXcbConnection: Could not connect to display %s", m_displayName.constData());

#ifdef XCB_USE_EGL
    EGLDisplay eglDisplay = eglGetDisplay(dpy);
    m_egl_display = eglDisplay;
    EGLint major, minor;
    m_has_egl = eglInitialize(eglDisplay, &major, &minor);
#endif //XCB_USE_EGL

    m_reader = new QXcbEventReader(this);
    m_reader->start();

    xcb_extension_t *extensions[] = {
        &xcb_shm_id, &xcb_xfixes_id, &xcb_randr_id, &xcb_shape_id, &xcb_sync_id,
#ifndef QT_NO_XKB
        &xcb_xkb_id,
#endif
#ifdef XCB_USE_RENDER
        &xcb_render_id,
#endif
#ifdef XCB_HAS_XCB_GLX
        &xcb_glx_id,
#endif
        0
    };

    for (xcb_extension_t **ext_it = extensions; *ext_it; ++ext_it)
        xcb_prefetch_extension_data (m_connection, *ext_it);

    m_setup = xcb_get_setup(xcb_connection());

    initializeAllAtoms();

    m_time = XCB_CURRENT_TIME;
    m_netWmUserTime = XCB_CURRENT_TIME;

    initializeXRandr();
    updateScreens();

    initializeGLX();
    initializeXFixes();
    initializeXRender();
    m_xi2Enabled = false;
#ifdef XCB_USE_XINPUT2_MAEMO
    initializeXInput2Maemo();
#elif defined(XCB_USE_XINPUT2)
    initializeXInput2();
#endif
    initializeXShape();
    initializeXKB();

    m_wmSupport.reset(new QXcbWMSupport(this));
    m_keyboard = new QXcbKeyboard(this);
#ifndef QT_NO_CLIPBOARD
    m_clipboard = new QXcbClipboard(this);
#endif
#ifndef QT_NO_DRAGANDDROP
    m_drag = new QXcbDrag(this);
#endif

    m_startupId = qgetenv("DESKTOP_STARTUP_ID");
    if (!m_startupId.isNull())
        qunsetenv("DESKTOP_STARTUP_ID");

    sync();
}

QXcbConnection::~QXcbConnection()
{
#ifndef QT_NO_CLIPBOARD
    delete m_clipboard;
#endif
#ifndef QT_NO_DRAGANDDROP
    delete m_drag;
#endif

#ifdef XCB_USE_XINPUT2_MAEMO
    finalizeXInput2Maemo();
#elif defined(XCB_USE_XINPUT2)
    finalizeXInput2();
#endif

    if (m_reader->isRunning()) {
        sendConnectionEvent(QXcbAtom::_QT_CLOSE_CONNECTION);
        m_reader->wait();
    }

    delete m_reader;

    // Delete screens in reverse order to avoid crash in case of multiple screens
    while (!m_screens.isEmpty())
        delete m_screens.takeLast();

#ifdef XCB_USE_EGL
    if (m_has_egl)
        eglTerminate(m_egl_display);
#endif //XCB_USE_EGL

#ifdef XCB_USE_XLIB
    XCloseDisplay((Display *)m_xlib_display);
#else
    xcb_disconnect(xcb_connection());
#endif

    delete m_keyboard;
}

void QXcbConnection::addWindowEventListener(xcb_window_t id, QXcbWindowEventListener *eventListener)
{
    m_mapper.insert(id, eventListener);
}

void QXcbConnection::removeWindowEventListener(xcb_window_t id)
{
    m_mapper.remove(id);
}

QXcbWindowEventListener *QXcbConnection::windowEventListenerFromId(xcb_window_t id)
{
    return m_mapper.value(id, 0);
}

QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id)
{
    QXcbWindowEventListener *listener = m_mapper.value(id, 0);
    if (listener)
        return listener->toWindow();
    return 0;
}

#define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \
{ \
    event_t *e = (event_t *)event; \
    if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember))  { \
        handled = eventListener->handleGenericEvent(event, &result); \
        if (!handled) \
            eventListener->handler(e); \
    } \
} \
break;

#define HANDLE_KEYBOARD_EVENT(event_t, handler) \
{ \
    event_t *e = (event_t *)event; \
    if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \
        handled = eventListener->handleGenericEvent(event, &result); \
        if (!handled) \
            m_keyboard->handler(m_focusWindow ? m_focusWindow : eventListener, e); \
    } \
} \
break;

//#define XCB_EVENT_DEBUG

void printXcbEvent(const char *message, xcb_generic_event_t *event)
{
#ifdef XCB_EVENT_DEBUG
#define PRINT_XCB_EVENT(ev) \
    case ev: \
        qDebug("QXcbConnection: %s: %d - %s - sequence: %d", message, int(ev), #ev, event->sequence); \
        break;

    switch (event->response_type & ~0x80) {
    PRINT_XCB_EVENT(XCB_KEY_PRESS);
    PRINT_XCB_EVENT(XCB_KEY_RELEASE);
    PRINT_XCB_EVENT(XCB_BUTTON_PRESS);
    PRINT_XCB_EVENT(XCB_BUTTON_RELEASE);
    PRINT_XCB_EVENT(XCB_MOTION_NOTIFY);
    PRINT_XCB_EVENT(XCB_ENTER_NOTIFY);
    PRINT_XCB_EVENT(XCB_LEAVE_NOTIFY);
    PRINT_XCB_EVENT(XCB_FOCUS_IN);
    PRINT_XCB_EVENT(XCB_FOCUS_OUT);
    PRINT_XCB_EVENT(XCB_KEYMAP_NOTIFY);
    PRINT_XCB_EVENT(XCB_EXPOSE);
    PRINT_XCB_EVENT(XCB_GRAPHICS_EXPOSURE);
    PRINT_XCB_EVENT(XCB_VISIBILITY_NOTIFY);
    PRINT_XCB_EVENT(XCB_CREATE_NOTIFY);
    PRINT_XCB_EVENT(XCB_DESTROY_NOTIFY);
    PRINT_XCB_EVENT(XCB_UNMAP_NOTIFY);
    PRINT_XCB_EVENT(XCB_MAP_NOTIFY);
    PRINT_XCB_EVENT(XCB_MAP_REQUEST);
    PRINT_XCB_EVENT(XCB_REPARENT_NOTIFY);
    PRINT_XCB_EVENT(XCB_CONFIGURE_NOTIFY);
    PRINT_XCB_EVENT(XCB_CONFIGURE_REQUEST);
    PRINT_XCB_EVENT(XCB_GRAVITY_NOTIFY);
    PRINT_XCB_EVENT(XCB_RESIZE_REQUEST);
    PRINT_XCB_EVENT(XCB_CIRCULATE_NOTIFY);
    PRINT_XCB_EVENT(XCB_CIRCULATE_REQUEST);
    PRINT_XCB_EVENT(XCB_PROPERTY_NOTIFY);
    PRINT_XCB_EVENT(XCB_SELECTION_CLEAR);
    PRINT_XCB_EVENT(XCB_SELECTION_REQUEST);
    PRINT_XCB_EVENT(XCB_SELECTION_NOTIFY);
    PRINT_XCB_EVENT(XCB_COLORMAP_NOTIFY);
    PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE);
    default:
        qDebug("QXcbConnection: %s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence));
    }
#else
    Q_UNUSED(message);
    Q_UNUSED(event);
#endif
}

const char *xcb_errors[] =
{
    "Success",
    "BadRequest",
    "BadValue",
    "BadWindow",
    "BadPixmap",
    "BadAtom",
    "BadCursor",
    "BadFont",
    "BadMatch",
    "BadDrawable",
    "BadAccess",
    "BadAlloc",
    "BadColor",
    "BadGC",
    "BadIDChoice",
    "BadName",
    "BadLength",
    "BadImplementation",
    "Unknown"
};

const char *xcb_protocol_request_codes[] =
{
    "Null",
    "CreateWindow",
    "ChangeWindowAttributes",
    "GetWindowAttributes",
    "DestroyWindow",
    "DestroySubwindows",
    "ChangeSaveSet",
    "ReparentWindow",
    "MapWindow",
    "MapSubwindows",
    "UnmapWindow",
    "UnmapSubwindows",
    "ConfigureWindow",
    "CirculateWindow",
    "GetGeometry",
    "QueryTree",
    "InternAtom",
    "GetAtomName",
    "ChangeProperty",
    "DeleteProperty",
    "GetProperty",
    "ListProperties",
    "SetSelectionOwner",
    "GetSelectionOwner",
    "ConvertSelection",
    "SendEvent",
    "GrabPointer",
    "UngrabPointer",
    "GrabButton",
    "UngrabButton",
    "ChangeActivePointerGrab",
    "GrabKeyboard",
    "UngrabKeyboard",
    "GrabKey",
    "UngrabKey",
    "AllowEvents",
    "GrabServer",
    "UngrabServer",
    "QueryPointer",
    "GetMotionEvents",
    "TranslateCoords",
    "WarpPointer",
    "SetInputFocus",
    "GetInputFocus",
    "QueryKeymap",
    "OpenFont",
    "CloseFont",
    "QueryFont",
    "QueryTextExtents",
    "ListFonts",
    "ListFontsWithInfo",
    "SetFontPath",
    "GetFontPath",
    "CreatePixmap",
    "FreePixmap",
    "CreateGC",
    "ChangeGC",
    "CopyGC",
    "SetDashes",
    "SetClipRectangles",
    "FreeGC",
    "ClearArea",
    "CopyArea",
    "CopyPlane",
    "PolyPoint",
    "PolyLine",
    "PolySegment",
    "PolyRectangle",
    "PolyArc",
    "FillPoly",
    "PolyFillRectangle",
    "PolyFillArc",
    "PutImage",
    "GetImage",
    "PolyText8",
    "PolyText16",
    "ImageText8",
    "ImageText16",
    "CreateColormap",
    "FreeColormap",
    "CopyColormapAndFree",
    "InstallColormap",
    "UninstallColormap",
    "ListInstalledColormaps",
    "AllocColor",
    "AllocNamedColor",
    "AllocColorCells",
    "AllocColorPlanes",
    "FreeColors",
    "StoreColors",
    "StoreNamedColor",
    "QueryColors",
    "LookupColor",
    "CreateCursor",
    "CreateGlyphCursor",
    "FreeCursor",
    "RecolorCursor",
    "QueryBestSize",
    "QueryExtension",
    "ListExtensions",
    "ChangeKeyboardMapping",
    "GetKeyboardMapping",
    "ChangeKeyboardControl",
    "GetKeyboardControl",
    "Bell",
    "ChangePointerControl",
    "GetPointerControl",
    "SetScreenSaver",
    "GetScreenSaver",
    "ChangeHosts",
    "ListHosts",
    "SetAccessControl",
    "SetCloseDownMode",
    "KillClient",
    "RotateProperties",
    "ForceScreenSaver",
    "SetPointerMapping",
    "GetPointerMapping",
    "SetModifierMapping",
    "GetModifierMapping",
    "Unknown"
};

#ifdef Q_XCB_DEBUG
void QXcbConnection::log(const char *file, int line, int sequence)
{
    QMutexLocker locker(&m_callLogMutex);
    CallInfo info;
    info.sequence = sequence;
    info.file = file;
    info.line = line;
    m_callLog << info;
}
#endif

void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
{
    long result = 0;
    QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
    if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), error, &result))
        return;

    uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
    uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);

    qWarning("QXcbConnection: XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
           int(error->error_code), xcb_errors[clamped_error_code],
           int(error->sequence), int(error->resource_id),
           int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
           int(error->minor_code));
#ifdef Q_XCB_DEBUG
    QMutexLocker locker(&m_callLogMutex);
    int i = 0;
    for (; i < m_callLog.size(); ++i) {
        if (m_callLog.at(i).sequence == error->sequence) {
            qDebug("Caused by: %s:%d", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
            break;
        } else if (m_callLog.at(i).sequence > error->sequence) {
            qDebug("Caused some time before: %s:%d", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
            if (i > 0)
                qDebug("and after: %s:%d", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line);
            break;
        }
    }
    if (i == m_callLog.size() && !m_callLog.isEmpty())
        qDebug("Caused some time after: %s:%d", qPrintable(m_callLog.first().file), m_callLog.first().line);
#endif
}

static Qt::MouseButtons translateMouseButtons(int s)
{
    Qt::MouseButtons ret = 0;
    if (s & XCB_BUTTON_MASK_1)
        ret |= Qt::LeftButton;
    if (s & XCB_BUTTON_MASK_2)
        ret |= Qt::MidButton;
    if (s & XCB_BUTTON_MASK_3)
        ret |= Qt::RightButton;
    return ret;
}

static Qt::MouseButton translateMouseButton(xcb_button_t s)
{
    switch (s) {
    case 1: return Qt::LeftButton;
    case 2: return Qt::MidButton;
    case 3: return Qt::RightButton;
    // Button values 4-7 were already handled as Wheel events, and won't occur here.
    case 8: return Qt::BackButton;      // Also known as Qt::ExtraButton1
    case 9: return Qt::ForwardButton;   // Also known as Qt::ExtraButton2
    case 10: return Qt::ExtraButton3;
    case 11: return Qt::ExtraButton4;
    case 12: return Qt::ExtraButton5;
    case 13: return Qt::ExtraButton6;
    case 14: return Qt::ExtraButton7;
    case 15: return Qt::ExtraButton8;
    case 16: return Qt::ExtraButton9;
    case 17: return Qt::ExtraButton10;
    case 18: return Qt::ExtraButton11;
    case 19: return Qt::ExtraButton12;
    case 20: return Qt::ExtraButton13;
    case 21: return Qt::ExtraButton14;
    case 22: return Qt::ExtraButton15;
    case 23: return Qt::ExtraButton16;
    case 24: return Qt::ExtraButton17;
    case 25: return Qt::ExtraButton18;
    case 26: return Qt::ExtraButton19;
    case 27: return Qt::ExtraButton20;
    case 28: return Qt::ExtraButton21;
    case 29: return Qt::ExtraButton22;
    case 30: return Qt::ExtraButton23;
    case 31: return Qt::ExtraButton24;
    default: return Qt::NoButton;
    }
}

void QXcbConnection::handleButtonPress(xcb_generic_event_t *ev)
{
    xcb_button_press_event_t *event = (xcb_button_press_event_t *)ev;

    // the event explicitly contains the state of the three first buttons,
    // the rest we need to manage ourselves
    m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state);
    m_buttons |= translateMouseButton(event->detail);
    if (Q_UNLIKELY(debug_xinput))
        qDebug("xcb: pressed mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons));
}

void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev)
{
    xcb_button_release_event_t *event = (xcb_button_release_event_t *)ev;

    // the event explicitly contains the state of the three first buttons,
    // the rest we need to manage ourselves
    m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state);
    m_buttons &= ~translateMouseButton(event->detail);
    if (Q_UNLIKELY(debug_xinput))
        qDebug("xcb: released mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons));
}

#ifndef QT_NO_XKB
namespace {
    typedef union {
        /* All XKB events share these fields. */
        struct {
            uint8_t response_type;
            uint8_t xkbType;
            uint16_t sequence;
            xcb_timestamp_t time;
            uint8_t deviceID;
        } any;
        xcb_xkb_new_keyboard_notify_event_t new_keyboard_notify;
        xcb_xkb_map_notify_event_t map_notify;
        xcb_xkb_state_notify_event_t state_notify;
    } _xkb_event;
}
#endif

void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
{
#ifdef Q_XCB_DEBUG
    {
        QMutexLocker locker(&m_callLogMutex);
        int i = 0;
        for (; i < m_callLog.size(); ++i)
            if (m_callLog.at(i).sequence >= event->sequence)
                break;
        m_callLog.remove(0, i);
    }
#endif

    long result = 0;
    QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
    bool handled = dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), event, &result);

    uint response_type = event->response_type & ~0x80;

    if (!handled) {
        switch (response_type) {
        case XCB_EXPOSE:
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
        case XCB_BUTTON_PRESS:
            m_keyboard->updateXKBStateFromCore(((xcb_button_press_event_t *)event)->state);
            handleButtonPress(event);
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
        case XCB_BUTTON_RELEASE:
            m_keyboard->updateXKBStateFromCore(((xcb_button_release_event_t *)event)->state);
            handleButtonRelease(event);
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
        case XCB_MOTION_NOTIFY:
            if (Q_UNLIKELY(debug_xinput)) {
                xcb_motion_notify_event_t *mev = (xcb_motion_notify_event_t *)event;
                qDebug("xcb: moved mouse to %4d, %4d; button state %X", mev->event_x, mev->event_y, static_cast<unsigned int>(m_buttons));
            }
            m_keyboard->updateXKBStateFromCore(((xcb_motion_notify_event_t *)event)->state);
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
        case XCB_CONFIGURE_NOTIFY:
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
        case XCB_MAP_NOTIFY:
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent);
        case XCB_UNMAP_NOTIFY:
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent);
        case XCB_DESTROY_NOTIFY:
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_destroy_notify_event_t, event, handleDestroyNotifyEvent);
        case XCB_CLIENT_MESSAGE:
            handleClientMessageEvent((xcb_client_message_event_t *)event);
            break;
        case XCB_ENTER_NOTIFY:
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
        case XCB_LEAVE_NOTIFY:
            m_keyboard->updateXKBStateFromCore(((xcb_leave_notify_event_t *)event)->state);
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
        case XCB_FOCUS_IN:
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent);
        case XCB_FOCUS_OUT:
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
        case XCB_KEY_PRESS:
            m_keyboard->updateXKBStateFromCore(((xcb_key_press_event_t *)event)->state);
            HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
        case XCB_KEY_RELEASE:
            m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state);
            HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
        case XCB_MAPPING_NOTIFY:
            m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
            break;
        case XCB_SELECTION_REQUEST:
        {
            xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event;
#ifndef QT_NO_DRAGANDDROP
            if (sr->selection == atom(QXcbAtom::XdndSelection))
                m_drag->handleSelectionRequest(sr);
            else
#endif
            {
#ifndef QT_NO_CLIPBOARD
                m_clipboard->handleSelectionRequest(sr);
#endif
            }
            break;
        }
        case XCB_SELECTION_CLEAR:
            setTime(((xcb_selection_clear_event_t *)event)->time);
#ifndef QT_NO_CLIPBOARD
            m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event);
#endif
            handled = true;
            break;
        case XCB_SELECTION_NOTIFY:
            setTime(((xcb_selection_notify_event_t *)event)->time);
            handled = false;
            break;
        case XCB_PROPERTY_NOTIFY:
            HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
            break;
#ifdef XCB_USE_XINPUT2_MAEMO
        case GenericEvent:
            handleGenericEventMaemo((xcb_ge_event_t*)event);
            break;
#elif defined(XCB_USE_XINPUT2)
        case GenericEvent:
            if (m_xi2Enabled)
                xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event));
            break;
#endif
        default:
            handled = false;
            break;
        }
    }

    if (!handled) {
        if (response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) {
            setTime(((xcb_xfixes_selection_notify_event_t *)event)->timestamp);
#ifndef QT_NO_CLIPBOARD
            m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event);
#endif
            handled = true;
        } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
            updateScreens();
            xcb_randr_screen_change_notify_event_t *change_event = (xcb_randr_screen_change_notify_event_t *)event;
            foreach (QXcbScreen *s, m_screens) {
                if (s->root() == change_event->root ) {
                    s->handleScreenChange(change_event);
                    s->updateRefreshRate();
                }
            }
            handled = true;
#ifndef QT_NO_XKB
        } else if (response_type == xkb_first_event) { // https://bugs.freedesktop.org/show_bug.cgi?id=51295
            _xkb_event *xkb_event = reinterpret_cast<_xkb_event *>(event);
            if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) {
                switch (xkb_event->any.xkbType) {
                    // XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap
                    // updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent recompilations.
                    case XCB_XKB_STATE_NOTIFY:
                        m_keyboard->updateXKBState(&xkb_event->state_notify);
                        handled = true;
                        break;
                    case XCB_XKB_MAP_NOTIFY:
                        m_keyboard->handleMappingNotifyEvent(&xkb_event->map_notify);
                        handled = true;
                        break;
                    case XCB_XKB_NEW_KEYBOARD_NOTIFY: {
                        xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify;
                        if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
                            m_keyboard->updateKeymap();
                        break;
                    }
                    default:
                        break;
                }
            }
#endif
        }
    }

#ifdef XCB_USE_XLIB
    if (!handled) {
        // Check if a custom XEvent constructor was registered in xlib for this event type, and call it discarding the constructed XEvent if any.
        // XESetWireToEvent might be used by libraries to intercept messages from the X server e.g. the OpenGL lib waiting for DRI2 events.
        Display *xdisplay = (Display *)m_xlib_display;
        XLockDisplay(xdisplay);
        Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, response_type, 0);
        if (proc) {
            XESetWireToEvent(xdisplay, response_type, proc);
            XEvent dummy;
            event->sequence = LastKnownRequestProcessed(m_xlib_display);
            proc(xdisplay, &dummy, (xEvent*)event);
        }
        XUnlockDisplay(xdisplay);
    }
#endif

    if (handled)
        printXcbEvent("Handled XCB event", event);
    else
        printXcbEvent("Unhandled XCB event", event);
}

void QXcbConnection::addPeekFunc(PeekFunc f)
{
    m_peekFuncs.append(f);
}

QXcbEventReader::QXcbEventReader(QXcbConnection *connection)
    : m_connection(connection)
    , m_xcb_poll_for_queued_event(0)
{
#ifdef RTLD_DEFAULT
    m_xcb_poll_for_queued_event = (XcbPollForQueuedEventFunctionPointer)dlsym(RTLD_DEFAULT, "xcb_poll_for_queued_event");
#endif

#ifdef Q_XCB_DEBUG
    if (m_xcb_poll_for_queued_event)
        qDebug("Using threaded event reader with xcb_poll_for_queued_event");
#endif
}

void QXcbEventReader::start()
{
    if (m_xcb_poll_for_queued_event) {
        connect(this, SIGNAL(eventPending()), m_connection, SLOT(processXcbEvents()), Qt::QueuedConnection);
        connect(this, SIGNAL(finished()), m_connection, SLOT(processXcbEvents()));
        QThread::start();
    } else {
        // Must be done after we have an event-dispatcher. By posting a method invocation
        // we are sure that by the time the method is called we have an event-dispatcher.
        QMetaObject::invokeMethod(this, "registerForEvents", Qt::QueuedConnection);
    }
}

void QXcbEventReader::registerForEvents()
{
    QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection->xcb_connection()), QSocketNotifier::Read, this);
    connect(notifier, SIGNAL(activated(int)), m_connection, SLOT(processXcbEvents()));

    QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
    connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(processXcbEvents()));
    connect(dispatcher, SIGNAL(awake()), m_connection, SLOT(processXcbEvents()));
}

void QXcbEventReader::run()
{
    xcb_generic_event_t *event;
    while (m_connection && (event = xcb_wait_for_event(m_connection->xcb_connection()))) {
        m_mutex.lock();
        addEvent(event);
        while (m_connection && (event = m_xcb_poll_for_queued_event(m_connection->xcb_connection())))
            addEvent(event);
        m_mutex.unlock();
        emit eventPending();
    }

    m_mutex.lock();
    for (int i = 0; i < m_events.size(); ++i)
        free(m_events.at(i));
    m_events.clear();
    m_mutex.unlock();
}

void QXcbEventReader::addEvent(xcb_generic_event_t *event)
{
    if ((event->response_type & ~0x80) == XCB_CLIENT_MESSAGE
        && ((xcb_client_message_event_t *)event)->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION))
        m_connection = 0;
    m_events << event;
}

QXcbEventArray *QXcbEventReader::lock()
{
    m_mutex.lock();
    if (!m_xcb_poll_for_queued_event) {
        while (xcb_generic_event_t *event = xcb_poll_for_event(m_connection->xcb_connection()))
            m_events << event;
    }
    return &m_events;
}

void QXcbEventReader::unlock()
{
    m_mutex.unlock();
}

void QXcbConnection::setFocusWindow(QXcbWindow *w)
{
    m_focusWindow = w;
}

void QXcbConnection::grabServer()
{
    if (m_canGrabServer)
        xcb_grab_server(m_connection);
}

void QXcbConnection::ungrabServer()
{
    if (m_canGrabServer)
        xcb_ungrab_server(m_connection);
}

void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
{
    xcb_client_message_event_t event;
    memset(&event, 0, sizeof(event));

    const xcb_window_t eventListener = xcb_generate_id(m_connection);
    Q_XCB_CALL(xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
                                 eventListener, m_screens.at(0)->root(),
                                 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
                                 m_screens.at(0)->screen()->root_visual, 0, 0));

    event.response_type = XCB_CLIENT_MESSAGE;
    event.format = 32;
    event.sequence = 0;
    event.window = eventListener;
    event.type = atom(a);
    event.data.data32[0] = id;

    Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
    Q_XCB_CALL(xcb_destroy_window(m_connection, eventListener));
    xcb_flush(xcb_connection());
}

namespace
{
    class PropertyNotifyEvent {
    public:
        PropertyNotifyEvent(xcb_window_t win, xcb_atom_t property)
            : window(win), type(XCB_PROPERTY_NOTIFY), atom(property) {}
        xcb_window_t window;
        int type;
        xcb_atom_t atom;
        bool checkEvent(xcb_generic_event_t *event) const {
            if (!event)
                return false;
            if ((event->response_type & ~0x80) != type) {
                return false;
            } else {
                xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
                if ((pn->window == window) && (pn->atom == atom))
                    return true;
            }
            return false;
        }
    };
}

xcb_timestamp_t QXcbConnection::getTimestamp()
{
    // send a dummy event to myself to get the timestamp from X server.
    xcb_window_t root_win = rootWindow();
    xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, root_win, atom(QXcbAtom::CLIP_TEMPORARY),
                        XCB_ATOM_INTEGER, 32, 0, NULL);

    connection()->flush();
    PropertyNotifyEvent checker(root_win, atom(QXcbAtom::CLIP_TEMPORARY));

    xcb_generic_event_t *event = 0;
    // lets keep this inside a loop to avoid a possible race condition, where
    // reader thread has not yet had the time to acquire the mutex in order
    // to add the new set of events to its event queue
    while (!event) {
        connection()->sync();
        event = checkEvent(checker);
    }

    xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
    xcb_timestamp_t timestamp = pn->time;
    free(event);

    xcb_delete_property(xcb_connection(), root_win, atom(QXcbAtom::CLIP_TEMPORARY));

    return timestamp;
}

xcb_window_t QXcbConnection::rootWindow()
{
    return screens().at(primaryScreen())->root();
}

void QXcbConnection::processXcbEvents()
{
    int connection_error = xcb_connection_has_error(xcb_connection());
    if (connection_error) {
        qWarning("The X11 connection broke (error %d). Did the X11 server die?", connection_error);
        exit(1);
    }

    QXcbEventArray *eventqueue = m_reader->lock();

    for(int i = 0; i < eventqueue->size(); ++i) {
        xcb_generic_event_t *event = eventqueue->at(i);
        if (!event)
            continue;
        QScopedPointer<xcb_generic_event_t, QScopedPointerPodDeleter> eventGuard(event);
        (*eventqueue)[i] = 0;

        uint response_type = event->response_type & ~0x80;

        if (!response_type) {
            handleXcbError((xcb_generic_error_t *)event);
        } else {
            if (response_type == XCB_MOTION_NOTIFY) {
                // compress multiple motion notify events in a row
                // to avoid swamping the event queue
                xcb_generic_event_t *next = eventqueue->value(i+1, 0);
                if (next && (next->response_type & ~0x80) == XCB_MOTION_NOTIFY)
                    continue;
            }

            if (response_type == XCB_CONFIGURE_NOTIFY) {
                // compress multiple configure notify events for the same window
                bool found = false;
                for (int j = i; j < eventqueue->size(); ++j) {
                    xcb_generic_event_t *other = eventqueue->at(j);
                    if (other && (other->response_type & ~0x80) == XCB_CONFIGURE_NOTIFY
                        && ((xcb_configure_notify_event_t *)other)->event == ((xcb_configure_notify_event_t *)event)->event)
                    {
                        found = true;
                        break;
                    }
                }
                if (found)
                    continue;
            }

            bool accepted = false;
            if (clipboard()->processIncr())
                clipboard()->incrTransactionPeeker(event, accepted);
            if (accepted)
                continue;

            QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
            while (it != m_peekFuncs.end()) {
                // These callbacks return true if the event is what they were
                // waiting for, remove them from the list in that case.
                if ((*it)(this, event))
                    it = m_peekFuncs.erase(it);
                else
                    ++it;
            }
            m_reader->unlock();
            handleXcbEvent(event);
            m_reader->lock();
        }
    }

    eventqueue->clear();

    m_reader->unlock();

    // Indicate with a null event that the event the callbacks are waiting for
    // is not in the queue currently.
    Q_FOREACH (PeekFunc f, m_peekFuncs)
        f(this, 0);
    m_peekFuncs.clear();

    xcb_flush(xcb_connection());
}

void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t *event)
{
    if (event->format != 32)
        return;

#ifndef QT_NO_DRAGANDDROP
    if (event->type == atom(QXcbAtom::XdndStatus)) {
        drag()->handleStatus(event);
    } else if (event->type == atom(QXcbAtom::XdndFinished)) {
        drag()->handleFinished(event);
    }
#endif
    if (m_systemTrayTracker && event->type == atom(QXcbAtom::MANAGER))
        m_systemTrayTracker->notifyManagerClientMessageEvent(event);

    QXcbWindow *window = platformWindowFromId(event->window);
    if (!window)
        return;

    window->handleClientMessageEvent(event);
}

xcb_generic_event_t *QXcbConnection::checkEvent(int type)
{
    QXcbEventArray *eventqueue = m_reader->lock();

    for (int i = 0; i < eventqueue->size(); ++i) {
        xcb_generic_event_t *event = eventqueue->at(i);
        if (event && event->response_type == type) {
            (*eventqueue)[i] = 0;
            m_reader->unlock();
            return event;
        }
    }

    m_reader->unlock();

    return 0;
}

static const char * xcb_atomnames = {
    // window-manager <-> client protocols
    "WM_PROTOCOLS\0"
    "WM_DELETE_WINDOW\0"
    "WM_TAKE_FOCUS\0"
    "_NET_WM_PING\0"
    "_NET_WM_CONTEXT_HELP\0"
    "_NET_WM_SYNC_REQUEST\0"
    "_NET_WM_SYNC_REQUEST_COUNTER\0"
    "MANAGER\0"
    "_NET_SYSTEM_TRAY_OPCODE\0"

    // ICCCM window state
    "WM_STATE\0"
    "WM_CHANGE_STATE\0"
    "WM_CLASS\0"

    // Session management
    "WM_CLIENT_LEADER\0"
    "WM_WINDOW_ROLE\0"
    "SM_CLIENT_ID\0"

    // Clipboard
    "CLIPBOARD\0"
    "INCR\0"
    "TARGETS\0"
    "MULTIPLE\0"
    "TIMESTAMP\0"
    "SAVE_TARGETS\0"
    "CLIP_TEMPORARY\0"
    "_QT_SELECTION\0"
    "_QT_CLIPBOARD_SENTINEL\0"
    "_QT_SELECTION_SENTINEL\0"
    "CLIPBOARD_MANAGER\0"

    "RESOURCE_MANAGER\0"

    "_XSETROOT_ID\0"

    "_QT_SCROLL_DONE\0"
    "_QT_INPUT_ENCODING\0"

    "_QT_CLOSE_CONNECTION\0"

    "_MOTIF_WM_HINTS\0"

    "DTWM_IS_RUNNING\0"
    "ENLIGHTENMENT_DESKTOP\0"
    "_DT_SAVE_MODE\0"
    "_SGI_DESKS_MANAGER\0"

    // EWMH (aka NETWM)
    "_NET_SUPPORTED\0"
    "_NET_VIRTUAL_ROOTS\0"
    "_NET_WORKAREA\0"

    "_NET_MOVERESIZE_WINDOW\0"
    "_NET_WM_MOVERESIZE\0"

    "_NET_WM_NAME\0"
    "_NET_WM_ICON_NAME\0"
    "_NET_WM_ICON\0"

    "_NET_WM_PID\0"

    "_NET_WM_WINDOW_OPACITY\0"

    "_NET_WM_STATE\0"
    "_NET_WM_STATE_ABOVE\0"
    "_NET_WM_STATE_BELOW\0"
    "_NET_WM_STATE_FULLSCREEN\0"
    "_NET_WM_STATE_MAXIMIZED_HORZ\0"
    "_NET_WM_STATE_MAXIMIZED_VERT\0"
    "_NET_WM_STATE_MODAL\0"
    "_NET_WM_STATE_STAYS_ON_TOP\0"
    "_NET_WM_STATE_DEMANDS_ATTENTION\0"

    "_NET_WM_USER_TIME\0"
    "_NET_WM_USER_TIME_WINDOW\0"
    "_NET_WM_FULL_PLACEMENT\0"

    "_NET_WM_WINDOW_TYPE\0"
    "_NET_WM_WINDOW_TYPE_DESKTOP\0"
    "_NET_WM_WINDOW_TYPE_DOCK\0"
    "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
    "_NET_WM_WINDOW_TYPE_MENU\0"
    "_NET_WM_WINDOW_TYPE_UTILITY\0"
    "_NET_WM_WINDOW_TYPE_SPLASH\0"
    "_NET_WM_WINDOW_TYPE_DIALOG\0"
    "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
    "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
    "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
    "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
    "_NET_WM_WINDOW_TYPE_COMBO\0"
    "_NET_WM_WINDOW_TYPE_DND\0"
    "_NET_WM_WINDOW_TYPE_NORMAL\0"
    "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"

    "_KDE_NET_WM_FRAME_STRUT\0"

    "_NET_STARTUP_INFO\0"
    "_NET_STARTUP_INFO_BEGIN\0"

    "_NET_SUPPORTING_WM_CHECK\0"

    "_NET_WM_CM_S0\0"

    "_NET_SYSTEM_TRAY_VISUAL\0"

    "_NET_ACTIVE_WINDOW\0"

    // Property formats
    "TEXT\0"
    "UTF8_STRING\0"
    "CARDINAL\0"

    // xdnd
    "XdndEnter\0"
    "XdndPosition\0"
    "XdndStatus\0"
    "XdndLeave\0"
    "XdndDrop\0"
    "XdndFinished\0"
    "XdndTypeList\0"
    "XdndActionList\0"

    "XdndSelection\0"

    "XdndAware\0"
    "XdndProxy\0"

    "XdndActionCopy\0"
    "XdndActionLink\0"
    "XdndActionMove\0"
    "XdndActionPrivate\0"

    // Motif DND
    "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
    "_MOTIF_DRAG_INITIATOR_INFO\0"
    "_MOTIF_DRAG_RECEIVER_INFO\0"
    "_MOTIF_DRAG_WINDOW\0"
    "_MOTIF_DRAG_TARGETS\0"

    "XmTRANSFER_SUCCESS\0"
    "XmTRANSFER_FAILURE\0"

    // Xkb
    "_XKB_RULES_NAMES\0"

    // XEMBED
    "_XEMBED\0"
    "_XEMBED_INFO\0"

    // XInput2
    "Button Left\0"
    "Button Middle\0"
    "Button Right\0"
    "Button Wheel Up\0"
    "Button Wheel Down\0"
    "Button Horiz Wheel Left\0"
    "Button Horiz Wheel Right\0"
    "Abs MT Position X\0"
    "Abs MT Position Y\0"
    "Abs MT Touch Major\0"
    "Abs MT Touch Minor\0"
    "Abs MT Pressure\0"
    "Abs MT Tracking ID\0"
    "Max Contacts\0"
    "Rel X\0"
    "Rel Y\0"
    // XInput2 tablet
    "Abs X\0"
    "Abs Y\0"
    "Abs Pressure\0"
    "Abs Tilt X\0"
    "Abs Tilt Y\0"
    "Abs Wheel\0"
    "Abs Distance\0"
    "Wacom Serial IDs\0"
    "INTEGER\0"
    "Rel Horiz Wheel\0"
    "Rel Vert Wheel\0"
    "Rel Horiz Scroll\0"
    "Rel Vert Scroll\0"
#if XCB_USE_MAEMO_WINDOW_PROPERTIES
    "_MEEGOTOUCH_ORIENTATION_ANGLE\0"
#endif
    "_XSETTINGS_SETTINGS\0"
    "_COMPIZ_DECOR_PENDING\0"
    "_COMPIZ_DECOR_REQUEST\0"
    "_COMPIZ_DECOR_DELETE_PIXMAP\0" // \0\0 terminates loop.
};

QXcbAtom::Atom QXcbConnection::qatom(xcb_atom_t xatom) const
{
    return static_cast<QXcbAtom::Atom>(std::find(m_allAtoms, m_allAtoms + QXcbAtom::NAtoms, xatom) - m_allAtoms);
}

void QXcbConnection::initializeAllAtoms() {
    const char *names[QXcbAtom::NAtoms];
    const char *ptr = xcb_atomnames;

    int i = 0;
    while (*ptr) {
        names[i++] = ptr;
        while (*ptr)
            ++ptr;
        ++ptr;
    }

    Q_ASSERT(i == QXcbAtom::NPredefinedAtoms);

    QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
    settings_atom_name += m_displayName;
    names[i++] = settings_atom_name;

    xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];

    Q_ASSERT(i == QXcbAtom::NAtoms);
    for (i = 0; i < QXcbAtom::NAtoms; ++i)
        cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]);

    for (i = 0; i < QXcbAtom::NAtoms; ++i) {
        xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0);
        m_allAtoms[i] = reply->atom;
        free(reply);
    }
}

xcb_atom_t QXcbConnection::internAtom(const char *name)
{
    if (!name || *name == 0)
        return XCB_NONE;

    xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection(), false, strlen(name), name);
    xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookie, 0);
    int atom = reply->atom;
    free(reply);
    return atom;
}

QByteArray QXcbConnection::atomName(xcb_atom_t atom)
{
    if (!atom)
        return QByteArray();

    xcb_generic_error_t *error = 0;
    xcb_get_atom_name_cookie_t cookie = Q_XCB_CALL(xcb_get_atom_name(xcb_connection(), atom));
    xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(xcb_connection(), cookie, &error);
    if (error) {
        qWarning() << "QXcbConnection::atomName: bad Atom" << atom;
        free(error);
    }
    if (reply) {
        QByteArray result(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
        free(reply);
        return result;
    }
    return QByteArray();
}

const xcb_format_t *QXcbConnection::formatForDepth(uint8_t depth) const
{
    xcb_format_iterator_t iterator =
        xcb_setup_pixmap_formats_iterator(m_setup);

    while (iterator.rem) {
        xcb_format_t *format = iterator.data;
        if (format->depth == depth)
            return format;
        xcb_format_next(&iterator);
    }

    return 0;
}

void QXcbConnection::sync()
{
    // from xcb_aux_sync
    xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection()));
    free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
}

void QXcbConnection::initializeXFixes()
{
    xcb_generic_error_t *error = 0;
    const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id);
    if (!reply || !reply->present)
        return;

    xfixes_first_event = reply->first_event;
    xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
                                                                                XCB_XFIXES_MAJOR_VERSION,
                                                                                XCB_XFIXES_MINOR_VERSION);
    xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
                                                                                xfixes_query_cookie, &error);
    if (!xfixes_query || error || xfixes_query->major_version < 2) {
        qWarning("QXcbConnection: Failed to initialize XFixes");
        free(error);
        xfixes_first_event = 0;
    }
    free(xfixes_query);
}

void QXcbConnection::initializeXRender()
{
#ifdef XCB_USE_RENDER
    const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_render_id);
    if (!reply || !reply->present)
        return;

    xcb_generic_error_t *error = 0;
    xcb_render_query_version_cookie_t xrender_query_cookie = xcb_render_query_version(m_connection,
                                                                                XCB_RENDER_MAJOR_VERSION,
                                                                                XCB_RENDER_MINOR_VERSION);
    xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection,
                                                                                xrender_query_cookie, &error);
    if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
        qWarning("QXcbConnection: Failed to initialize XRender");
        free(error);
    }
    free(xrender_query);
#endif
}

void QXcbConnection::initializeGLX()
{
#ifdef XCB_HAS_XCB_GLX
    const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_glx_id);
    if (!reply || !reply->present)
        return;

    has_glx_extension = true;

    xcb_generic_error_t *error = 0;
    xcb_glx_query_version_cookie_t xglx_query_cookie = xcb_glx_query_version(m_connection,
                                                                             XCB_GLX_MAJOR_VERSION,
                                                                             XCB_GLX_MINOR_VERSION);
    xcb_glx_query_version_reply_t *xglx_query = xcb_glx_query_version_reply(m_connection,
                                                                            xglx_query_cookie, &error);
    if (!xglx_query || error) {
        qWarning("QXcbConnection: Failed to initialize GLX");
        free(error);
        has_glx_extension = false;
    }
    free(xglx_query);
#else
    // no way to check, assume GLX is present
    has_glx_extension = true;
#endif
}

void QXcbConnection::initializeXRandr()
{
    const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_randr_id);
    if (!reply || !reply->present)
        return;

    xrandr_first_event = reply->first_event;

    xcb_generic_error_t *error = 0;
    xcb_randr_query_version_cookie_t xrandr_query_cookie = xcb_randr_query_version(m_connection,
                                                                                XCB_RANDR_MAJOR_VERSION,
                                                                                XCB_RANDR_MINOR_VERSION);

    has_randr_extension = true;

    xcb_randr_query_version_reply_t *xrandr_query = xcb_randr_query_version_reply(m_connection,
                                                                                xrandr_query_cookie, &error);
    if (!xrandr_query || error || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) {
        qWarning("QXcbConnection: Failed to initialize XRandr");
        free(error);
        has_randr_extension = false;
    }
    free(xrandr_query);
}

void QXcbConnection::initializeXShape()
{
    const xcb_query_extension_reply_t *xshape_reply = xcb_get_extension_data(m_connection, &xcb_shape_id);
    if (!xshape_reply || !xshape_reply->present)
        return;

    has_shape_extension = true;
    xcb_shape_query_version_cookie_t cookie = xcb_shape_query_version(m_connection);
    xcb_shape_query_version_reply_t *shape_query = xcb_shape_query_version_reply(m_connection,
                                                                                cookie, NULL);
    if (!shape_query) {
        qWarning("QXcbConnection: Failed to initialize SHAPE extension");
    } else if (shape_query->major_version > 1 || (shape_query->major_version == 1 && shape_query->minor_version >= 1)) {
        // The input shape is the only thing added in SHAPE 1.1
        has_input_shape = true;
    }
    free(shape_query);
}

void QXcbConnection::initializeXKB()
{
#ifndef QT_NO_XKB
    const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xkb_id);
    if (!reply || !reply->present) {
        qWarning() << "Qt: XKEYBOARD extension not present on the X server.";
        xkb_first_event = 0;
        return;
    }
    xkb_first_event = reply->first_event;

    xcb_connection_t *c = connection()->xcb_connection();
    xcb_xkb_use_extension_cookie_t xkb_query_cookie;
    xcb_xkb_use_extension_reply_t *xkb_query;

    xkb_query_cookie = xcb_xkb_use_extension(c, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
    xkb_query = xcb_xkb_use_extension_reply(c, xkb_query_cookie, 0);

    if (!xkb_query) {
        qWarning("Qt: Failed to initialize XKB extension");
        return;
    } else if (!xkb_query->supported) {
        qWarning("Qt: Unsupported XKB version (We want %d %d, but X server has %d %d)",
                 XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION,
                 xkb_query->serverMajor, xkb_query->serverMinor);
        free(xkb_query);
        return;
    }

    has_xkb = true;
    free(xkb_query);

    const uint16_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES |
        XCB_XKB_MAP_PART_KEY_SYMS |
        XCB_XKB_MAP_PART_MODIFIER_MAP |
        XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
        XCB_XKB_MAP_PART_KEY_ACTIONS |
        XCB_XKB_MAP_PART_KEY_BEHAVIORS |
        XCB_XKB_MAP_PART_VIRTUAL_MODS |
        XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);

    const uint16_t required_events = (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
        XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
        XCB_XKB_EVENT_TYPE_STATE_NOTIFY);

    // XKB events are reported to all interested clients without regard
    // to the current keyboard input focus or grab state
    xcb_void_cookie_t select = xcb_xkb_select_events_checked(c,
                       XCB_XKB_ID_USE_CORE_KBD,
                       required_events,
                       0,
                       required_events,
                       required_map_parts,
                       required_map_parts,
                       0);

    xcb_generic_error_t *error = xcb_request_check(c, select);
    if (error) {
        free(error);
        qWarning() << "Qt: failed to select notify events from xcb-xkb";
        return;
    }
#endif
}

#if defined(XCB_USE_EGL)
bool QXcbConnection::hasEgl() const
{
    return m_has_egl;
}
#endif // defined(XCB_USE_EGL)

#if defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO)
static int xi2ValuatorOffset(unsigned char *maskPtr, int maskLen, int number)
{
    int offset = 0;
    for (int i = 0; i < maskLen; i++) {
        if (number < 8) {
            if ((maskPtr[i] & (1 << number)) == 0)
                return -1;
        }
        for (int j = 0; j < 8; j++) {
            if (j == number)
                return offset;
            if (maskPtr[i] & (1 << j))
                offset++;
        }
        number -= 8;
    }
    return -1;
}

bool QXcbConnection::xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value)
{
    xXIDeviceEvent *xideviceevent = static_cast<xXIDeviceEvent *>(event);
    unsigned char *buttonsMaskAddr = (unsigned char*)&xideviceevent[1];
    unsigned char *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4;
    FP3232 *valuatorsValuesAddr = (FP3232*)(valuatorsMaskAddr + xideviceevent->valuators_len * 4);

    int valuatorOffset = xi2ValuatorOffset(valuatorsMaskAddr, xideviceevent->valuators_len, valuatorNum);
    if (valuatorOffset < 0)
        return false;

    *value = valuatorsValuesAddr[valuatorOffset].integral;
    *value += ((double)valuatorsValuesAddr[valuatorOffset].frac / (1 << 16) / (1 << 16));
    return true;
}

// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
// - "pad0" became "extension"
// - "pad1" and "pad" became "pad0"
// New and old version of this struct share the following fields:
// NOTE: API might change again in the next release of xcb in which case this comment will
// need to be updated to reflect the reality.
typedef struct qt_xcb_ge_event_t {
    uint8_t  response_type;
    uint8_t  extension;
    uint16_t sequence;
    uint32_t length;
    uint16_t event_type;
} qt_xcb_ge_event_t;

bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *ev, int opCode)
{
    qt_xcb_ge_event_t *event = (qt_xcb_ge_event_t *)ev;
    // xGenericEvent has "extension" on the second byte, the same is true for xcb_ge_event_t starting from
    // the xcb version 1.9.3, prior to that it was called "pad0".
    if (event->extension == opCode) {
        // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
        // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
        // Move this data back to have the same layout in memory as it was on the wire
        // and allow casting, overwriting the full_sequence field.
        memmove((char*) event + 32, (char*) event + 36, event->length * 4);
        return true;
    }
    return false;
}
#endif // defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO)

QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker()
{
    if (!m_systemTrayTracker) {
        if ( (m_systemTrayTracker = QXcbSystemTrayTracker::create(this)) ) {
            connect(m_systemTrayTracker, SIGNAL(systemTrayWindowChanged(QScreen*)),
                    QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)));
        }
    }
    return m_systemTrayTracker;
}

QXcbConnectionGrabber::QXcbConnectionGrabber(QXcbConnection *connection)
    :m_connection(connection)
{
    connection->grabServer();
}

QXcbConnectionGrabber::~QXcbConnectionGrabber()
{
    if (m_connection)
        m_connection->ungrabServer();
}

void QXcbConnectionGrabber::release()
{
    if (m_connection) {
        m_connection->ungrabServer();
        m_connection = 0;
    }
}

QT_END_NAMESPACE


text:
package org.apache.hadoop.hbase.client;

import static org.apache.hadoop.hbase.TableName.META_TABLE_NAME;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import org.apache.hadoop.hbase.AsyncMetaTableAccessor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.NoSuchProcedureException;
import org.apache.hadoop.hbase.master.RegionState;
import org.apache.hadoop.hbase.master.ServerManager;
import org.apache.hadoop.hbase.master.assignment.AssignmentManager;
import org.apache.hadoop.hbase.master.assignment.RegionStates;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.regionserver.Region;
import org.apache.hadoop.hbase.testclassification.ClientTests;
import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.JVMClusterUtil;
import org.apache.hadoop.hbase.util.Threads;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

/**
 * Class to test asynchronous region admin operations.
 */
@RunWith(Parameterized.class)
@Category({ LargeTests.class, ClientTests.class })
public class TestAsyncRegionAdminApi extends TestAsyncAdminBase {

  @Test
  public void testGetRegionLocation() throws Exception {
    RawAsyncHBaseAdmin rawAdmin = (RawAsyncHBaseAdmin) ASYNC_CONN.getAdmin();
    TEST_UTIL.createMultiRegionTable(tableName, HConstants.CATALOG_FAMILY);
    AsyncTableRegionLocator locator = ASYNC_CONN.getRegionLocator(tableName);
    HRegionLocation regionLocation = locator.getRegionLocation(Bytes.toBytes("mmm")).get();
    RegionInfo region = regionLocation.getRegionInfo();
    byte[] regionName = regionLocation.getRegionInfo().getRegionName();
    HRegionLocation location = rawAdmin.getRegionLocation(regionName).get();
    assertTrue(Bytes.equals(regionName, location.getRegionInfo().getRegionName()));
    location = rawAdmin.getRegionLocation(region.getEncodedNameAsBytes()).get();
    assertTrue(Bytes.equals(regionName, location.getRegionInfo().getRegionName()));
  }

  @Test
  public void testAssignRegionAndUnassignRegion() throws Exception {
    createTableWithDefaultConf(tableName);

    // assign region.
    HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
    AssignmentManager am = master.getAssignmentManager();
    RegionInfo hri = am.getRegionStates().getRegionsOfTable(tableName).get(0);

    // assert region on server
    RegionStates regionStates = am.getRegionStates();
    ServerName serverName = regionStates.getRegionServerOfRegion(hri);
    TEST_UTIL.assertRegionOnServer(hri, serverName, 200);
    assertTrue(regionStates.getRegionState(hri).isOpened());

    // Region is assigned now. Let's assign it again.
    // Master should not abort, and region should stay assigned.
    admin.assign(hri.getRegionName()).get();
    try {
      am.waitForAssignment(hri);
      fail("Expected NoSuchProcedureException");
    } catch (NoSuchProcedureException e) {
      // Expected
    }
    assertTrue(regionStates.getRegionState(hri).isOpened());

    // unassign region
    admin.unassign(hri.getRegionName(), true).get();
    try {
      am.waitForAssignment(hri);
      fail("Expected NoSuchProcedureException");
    } catch (NoSuchProcedureException e) {
      // Expected
    }
    assertTrue(regionStates.getRegionState(hri).isClosed());
  }

  RegionInfo createTableAndGetOneRegion(final TableName tableName)
      throws IOException, InterruptedException, ExecutionException {
    TableDescriptor desc =
        TableDescriptorBuilder.newBuilder(tableName)
            .addColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY)).build();
    admin.createTable(desc, Bytes.toBytes("A"), Bytes.toBytes("Z"), 5).get();

    // wait till the table is assigned
    HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
    long timeoutTime = System.currentTimeMillis() + 3000;
    while (true) {
      List<RegionInfo> regions =
          master.getAssignmentManager().getRegionStates().getRegionsOfTable(tableName);
      if (regions.size() > 3) {
        return regions.get(2);
      }
      long now = System.currentTimeMillis();
      if (now > timeoutTime) {
        fail("Could not find an online region");
      }
      Thread.sleep(10);
    }
  }

  @Ignore @Test
  // Turning off this tests in AMv2. Doesn't make sense.Offlining means something
  // different now.
  // You can't 'offline' a region unless you know what you are doing
  // Will cause the Master to tell the regionserver to shut itself down because
  // regionserver is reporting the state as OPEN.
  public void testOfflineRegion() throws Exception {
    RegionInfo hri = createTableAndGetOneRegion(tableName);

    RegionStates regionStates =
        TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStates();
    admin.offline(hri.getRegionName()).get();

    long timeoutTime = System.currentTimeMillis() + 3000;
    while (true) {
      if (regionStates.getRegionByStateOfTable(tableName).get(RegionState.State.OFFLINE)
          .stream().anyMatch(r -> RegionInfo.COMPARATOR.compare(r, hri) == 0)) break;
      long now = System.currentTimeMillis();
      if (now > timeoutTime) {
        fail("Failed to offline the region in time");
        break;
      }
      Thread.sleep(10);
    }
    RegionState regionState = regionStates.getRegionState(hri);
    assertTrue(regionState.isOffline());
  }

  @Test
  public void testGetRegionByStateOfTable() throws Exception {
    RegionInfo hri = createTableAndGetOneRegion(tableName);

    RegionStates regionStates =
        TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStates();
    assertTrue(regionStates.getRegionByStateOfTable(tableName).get(RegionState.State.OPEN)
        .stream().anyMatch(r -> RegionInfo.COMPARATOR.compare(r, hri) == 0));
    assertFalse(regionStates.getRegionByStateOfTable(TableName.valueOf("I_am_the_phantom"))
        .get(RegionState.State.OPEN).stream().anyMatch(r -> RegionInfo.COMPARATOR.compare(r, hri) == 0));
  }

  @Test
  public void testMoveRegion() throws Exception {
    admin.setBalancerOn(false).join();

    RegionInfo hri = createTableAndGetOneRegion(tableName);
    RawAsyncHBaseAdmin rawAdmin = (RawAsyncHBaseAdmin) ASYNC_CONN.getAdmin();
    ServerName serverName = rawAdmin.getRegionLocation(hri.getRegionName()).get().getServerName();

    HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
    ServerManager serverManager = master.getServerManager();
    ServerName destServerName = null;
    List<JVMClusterUtil.RegionServerThread> regionServers =
        TEST_UTIL.getHBaseCluster().getLiveRegionServerThreads();
    for (JVMClusterUtil.RegionServerThread regionServer : regionServers) {
      HRegionServer destServer = regionServer.getRegionServer();
      destServerName = destServer.getServerName();
      if (!destServerName.equals(serverName) && serverManager.isServerOnline(destServerName)) {
        break;
      }
    }

    assertTrue(destServerName != null && !destServerName.equals(serverName));
    admin.move(hri.getRegionName(), Optional.of(destServerName)).get();

    long timeoutTime = System.currentTimeMillis() + 30000;
    while (true) {
      ServerName sn = rawAdmin.getRegionLocation(hri.getRegionName()).get().getServerName();
      if (sn != null && sn.equals(destServerName)) {
        break;
      }
      long now = System.currentTimeMillis();
      if (now > timeoutTime) {
        fail("Failed to move the region in time: " + hri);
      }
      Thread.sleep(100);
    }
    admin.setBalancerOn(true).join();
  }

  @Test
  public void testGetOnlineRegions() throws Exception {
    createTableAndGetOneRegion(tableName);
    AtomicInteger regionServerCount = new AtomicInteger(0);
    TEST_UTIL
        .getHBaseCluster()
        .getLiveRegionServerThreads()
        .stream()
        .map(rsThread -> rsThread.getRegionServer())
        .forEach(
          rs -> {
            ServerName serverName = rs.getServerName();
            try {
              Assert.assertEquals(admin.getOnlineRegions(serverName).get().size(), rs
                  .getRegions().size());
            } catch (Exception e) {
              fail("admin.getOnlineRegions() method throws a exception: " + e.getMessage());
            }
            regionServerCount.incrementAndGet();
          });
    Assert.assertEquals(regionServerCount.get(), 2);
  }

  @Test
  public void testFlushTableAndRegion() throws Exception {
    RegionInfo hri = createTableAndGetOneRegion(tableName);
    ServerName serverName =
        TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStates()
            .getRegionServerOfRegion(hri);
    HRegionServer regionServer =
        TEST_UTIL.getHBaseCluster().getLiveRegionServerThreads().stream()
            .map(rsThread -> rsThread.getRegionServer())
            .filter(rs -> rs.getServerName().equals(serverName)).findFirst().get();

    // write a put into the specific region
    ASYNC_CONN.getRawTable(tableName)
        .put(new Put(hri.getStartKey()).addColumn(FAMILY, FAMILY_0, Bytes.toBytes("value-1")))
        .join();
    Assert.assertTrue(regionServer.getOnlineRegion(hri.getRegionName()).getMemStoreSize() > 0);
    // flush region and wait flush operation finished.
    LOG.info("flushing region: " + Bytes.toStringBinary(hri.getRegionName()));
    admin.flushRegion(hri.getRegionName()).get();
    LOG.info("blocking until flush is complete: " + Bytes.toStringBinary(hri.getRegionName()));
    Threads.sleepWithoutInterrupt(500);
    while (regionServer.getOnlineRegion(hri.getRegionName()).getMemStoreSize() > 0) {
      Threads.sleep(50);
    }
    // check the memstore.
    Assert.assertEquals(regionServer.getOnlineRegion(hri.getRegionName()).getMemStoreSize(), 0);

    // write another put into the specific region
    ASYNC_CONN.getRawTable(tableName)
        .put(new Put(hri.getStartKey()).addColumn(FAMILY, FAMILY_0, Bytes.toBytes("value-2")))
        .join();
    Assert.assertTrue(regionServer.getOnlineRegion(hri.getRegionName()).getMemStoreSize() > 0);
    admin.flush(tableName).get();
    Threads.sleepWithoutInterrupt(500);
    while (regionServer.getOnlineRegion(hri.getRegionName()).getMemStoreSize() > 0) {
      Threads.sleep(50);
    }
    // check the memstore.
    Assert.assertEquals(regionServer.getOnlineRegion(hri.getRegionName()).getMemStoreSize(), 0);
  }

  @Test
  public void testSplitSwitch() throws Exception {
    createTableWithDefaultConf(tableName);
    byte[][] families = { FAMILY };
    final int rows = 10000;
    loadData(tableName, families, rows);

    RawAsyncTable metaTable = ASYNC_CONN.getRawTable(META_TABLE_NAME);
    List<HRegionLocation> regionLocations =
        AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, Optional.of(tableName)).get();
    int originalCount = regionLocations.size();

    initSplitMergeSwitch();
    assertTrue(admin.setSplitOn(false).get());
    try {
      admin.split(tableName, Bytes.toBytes(rows / 2)).join();
    } catch (Exception e){
      //Expected
    }
    int count = admin.getTableRegions(tableName).get().size();
    assertTrue(originalCount == count);

    assertFalse(admin.setSplitOn(true).get());
    admin.split(tableName).join();
    while ((count = admin.getTableRegions(tableName).get().size()) == originalCount) {
      Threads.sleep(100);
    }
    assertTrue(originalCount < count);
  }

  @Test
  @Ignore
  // It was ignored in TestSplitOrMergeStatus, too
  public void testMergeSwitch() throws Exception {
    createTableWithDefaultConf(tableName);
    byte[][] families = { FAMILY };
    loadData(tableName, families, 1000);

    RawAsyncTable metaTable = ASYNC_CONN.getRawTable(META_TABLE_NAME);
    List<HRegionLocation> regionLocations =
        AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, Optional.of(tableName)).get();
    int originalCount = regionLocations.size();

    initSplitMergeSwitch();
    admin.split(tableName).join();
    int postSplitCount = originalCount;
    while ((postSplitCount = admin.getTableRegions(tableName).get().size()) == originalCount) {
      Threads.sleep(100);
    }
    assertTrue("originalCount=" + originalCount + ", postSplitCount=" + postSplitCount,
      originalCount != postSplitCount);

    // Merge switch is off so merge should NOT succeed.
    assertTrue(admin.setMergeOn(false).get());
    List<RegionInfo> regions = admin.getTableRegions(tableName).get();
    assertTrue(regions.size() > 1);
    admin.mergeRegions(regions.get(0).getRegionName(), regions.get(1).getRegionName(), true).join();
    int count = admin.getTableRegions(tableName).get().size();
    assertTrue("postSplitCount=" + postSplitCount + ", count=" + count, postSplitCount == count);

    // Merge switch is on so merge should succeed.
    assertFalse(admin.setMergeOn(true).get());
    admin.mergeRegions(regions.get(0).getRegionName(), regions.get(1).getRegionName(), true).join();
    count = admin.getTableRegions(tableName).get().size();
    assertTrue((postSplitCount / 2) == count);
  }

  private void initSplitMergeSwitch() throws Exception {
    if (!admin.isSplitOn().get()) {
      admin.setSplitOn(true).get();
    }
    if (!admin.isMergeOn().get()) {
      admin.setMergeOn(true).get();
    }
    assertTrue(admin.isSplitOn().get());
    assertTrue(admin.isMergeOn().get());
  }

  @Test
  public void testMergeRegions() throws Exception {
    byte[][] splitRows = new byte[][] { Bytes.toBytes("3"), Bytes.toBytes("6") };
    createTableWithDefaultConf(tableName, Optional.of(splitRows));

    RawAsyncTable metaTable = ASYNC_CONN.getRawTable(META_TABLE_NAME);
    List<HRegionLocation> regionLocations =
        AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, Optional.of(tableName)).get();
    RegionInfo regionA;
    RegionInfo regionB;

    // merge with full name
    assertEquals(3, regionLocations.size());
    regionA = regionLocations.get(0).getRegionInfo();
    regionB = regionLocations.get(1).getRegionInfo();
    admin.mergeRegions(regionA.getRegionName(), regionB.getRegionName(), false).get();

    regionLocations =
        AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, Optional.of(tableName)).get();
    assertEquals(2, regionLocations.size());
    // merge with encoded name
    regionA = regionLocations.get(0).getRegionInfo();
    regionB = regionLocations.get(1).getRegionInfo();
    admin.mergeRegions(regionA.getRegionName(), regionB.getRegionName(), false).get();

    regionLocations =
        AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, Optional.of(tableName)).get();
    assertEquals(1, regionLocations.size());
  }

  @Test
  public void testSplitTable() throws Exception {
    initSplitMergeSwitch();
    splitTest(TableName.valueOf("testSplitTable"), 3000, false, null);
    splitTest(TableName.valueOf("testSplitTableWithSplitPoint"), 3000, false, Bytes.toBytes("3"));
    splitTest(TableName.valueOf("testSplitTableRegion"), 3000, true, null);
    splitTest(TableName.valueOf("testSplitTableRegionWithSplitPoint2"), 3000, true, Bytes.toBytes("3"));
  }

  private void
      splitTest(TableName tableName, int rowCount, boolean isSplitRegion, byte[] splitPoint)
          throws Exception {
    // create table
    createTableWithDefaultConf(tableName);

    RawAsyncTable metaTable = ASYNC_CONN.getRawTable(META_TABLE_NAME);
    List<HRegionLocation> regionLocations =
        AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, Optional.of(tableName)).get();
    assertEquals(1, regionLocations.size());

    RawAsyncTable table = ASYNC_CONN.getRawTable(tableName);
    List<Put> puts = new ArrayList<>();
    for (int i = 0; i < rowCount; i++) {
      Put put = new Put(Bytes.toBytes(i));
      put.addColumn(FAMILY, null, Bytes.toBytes("value" + i));
      puts.add(put);
    }
    table.putAll(puts).join();

    if (isSplitRegion) {
      admin.splitRegion(regionLocations.get(0).getRegionInfo().getRegionName(),
        Optional.ofNullable(splitPoint)).get();
    } else {
      if (splitPoint == null) {
        admin.split(tableName).get();
      } else {
        admin.split(tableName, splitPoint).get();
      }
    }

    int count = 0;
    for (int i = 0; i < 45; i++) {
      try {
        regionLocations =
            AsyncMetaTableAccessor.getTableHRegionLocations(metaTable, Optional.of(tableName))
                .get();
        count = regionLocations.size();
        if (count >= 2) {
          break;
        }
        Thread.sleep(1000L);
      } catch (Exception e) {
        LOG.error(e);
      }
    }
    assertEquals(count, 2);
  }

  @Test
  public void testCompactRegionServer() throws Exception {
    byte[][] families = { Bytes.toBytes("f1"), Bytes.toBytes("f2"), Bytes.toBytes("f3") };
    createTableWithDefaultConf(tableName, Optional.empty(), families);
    loadData(tableName, families, 3000, 8);

    List<HRegionServer> rsList =
        TEST_UTIL.getHBaseCluster().getLiveRegionServerThreads().stream()
            .map(rsThread -> rsThread.getRegionServer()).collect(Collectors.toList());
    List<Region> regions = new ArrayList<>();
    rsList.forEach(rs -> regions.addAll(rs.getRegions(tableName)));
    Assert.assertEquals(regions.size(), 1);
    int countBefore = countStoreFilesInFamilies(regions, families);
    Assert.assertTrue(countBefore > 0);

    // Minor compaction for all region servers.
    for (HRegionServer rs : rsList)
      admin.compactRegionServer(rs.getServerName()).get();
    Thread.sleep(5000);
    int countAfterMinorCompaction = countStoreFilesInFamilies(regions, families);
    Assert.assertTrue(countAfterMinorCompaction < countBefore);

    // Major compaction for all region servers.
    for (HRegionServer rs : rsList)
      admin.majorCompactRegionServer(rs.getServerName()).get();
    Thread.sleep(5000);
    int countAfterMajorCompaction = countStoreFilesInFamilies(regions, families);
    Assert.assertEquals(countAfterMajorCompaction, 3);
  }

  @Test
  public void testCompact() throws Exception {
    compactionTest(TableName.valueOf("testCompact1"), 8, CompactionState.MAJOR, false);
    compactionTest(TableName.valueOf("testCompact2"), 15, CompactionState.MINOR, false);
    compactionTest(TableName.valueOf("testCompact3"), 8, CompactionState.MAJOR, true);
    compactionTest(TableName.valueOf("testCompact4"), 15, CompactionState.MINOR, true);
  }

  private void compactionTest(final TableName tableName, final int flushes,
      final CompactionState expectedState, boolean singleFamily) throws Exception {
    // Create a table with regions
    byte[] family = Bytes.toBytes("family");
    byte[][] families =
        { family, Bytes.add(family, Bytes.toBytes("2")), Bytes.add(family, Bytes.toBytes("3")) };
    createTableWithDefaultConf(tableName, Optional.empty(), families);
    loadData(tableName, families, 3000, flushes);

    List<Region> regions = new ArrayList<>();
    TEST_UTIL
        .getHBaseCluster()
        .getLiveRegionServerThreads()
        .forEach(rsThread -> regions.addAll(rsThread.getRegionServer().getRegions(tableName)));
    Assert.assertEquals(regions.size(), 1);

    int countBefore = countStoreFilesInFamilies(regions, families);
    int countBeforeSingleFamily = countStoreFilesInFamily(regions, family);
    assertTrue(countBefore > 0); // there should be some data files
    if (expectedState == CompactionState.MINOR) {
      if (singleFamily) {
        admin.compact(tableName, Optional.of(family)).get();
      } else {
        admin.compact(tableName, Optional.empty()).get();
      }
    } else {
      if (singleFamily) {
        admin.majorCompact(tableName, Optional.of(family)).get();
      } else {
        admin.majorCompact(tableName, Optional.empty()).get();
      }
    }

    long curt = System.currentTimeMillis();
    long waitTime = 5000;
    long endt = curt + waitTime;
    CompactionState state = admin.getCompactionState(tableName).get();
    while (state == CompactionState.NONE && curt < endt) {
      Thread.sleep(10);
      state = admin.getCompactionState(tableName).get();
      curt = System.currentTimeMillis();
    }
    // Now, should have the right compaction state,
    // otherwise, the compaction should have already been done
    if (expectedState != state) {
      for (Region region : regions) {
        state = CompactionState.valueOf(region.getCompactionState().toString());
        assertEquals(CompactionState.NONE, state);
      }
    } else {
      // Wait until the compaction is done
      state = admin.getCompactionState(tableName).get();
      while (state != CompactionState.NONE && curt < endt) {
        Thread.sleep(10);
        state = admin.getCompactionState(tableName).get();
      }
      // Now, compaction should be done.
      assertEquals(CompactionState.NONE, state);
    }

    int countAfter = countStoreFilesInFamilies(regions, families);
    int countAfterSingleFamily = countStoreFilesInFamily(regions, family);
    assertTrue(countAfter < countBefore);
    if (!singleFamily) {
      if (expectedState == CompactionState.MAJOR) assertTrue(families.length == countAfter);
      else assertTrue(families.length < countAfter);
    } else {
      int singleFamDiff = countBeforeSingleFamily - countAfterSingleFamily;
      // assert only change was to single column family
      assertTrue(singleFamDiff == (countBefore - countAfter));
      if (expectedState == CompactionState.MAJOR) {
        assertTrue(1 == countAfterSingleFamily);
      } else {
        assertTrue(1 < countAfterSingleFamily);
      }
    }
  }

  private static int countStoreFilesInFamily(List<Region> regions, final byte[] family) {
    return countStoreFilesInFamilies(regions, new byte[][] { family });
  }

  private static int countStoreFilesInFamilies(List<Region> regions, final byte[][] families) {
    int count = 0;
    for (Region region : regions) {
      count += region.getStoreFileList(families).size();
    }
    return count;
  }

  private static void loadData(final TableName tableName, final byte[][] families, final int rows)
      throws IOException {
    loadData(tableName, families, rows, 1);
  }

  private static void loadData(final TableName tableName, final byte[][] families, final int rows,
      final int flushes) throws IOException {
    RawAsyncTable table = ASYNC_CONN.getRawTable(tableName);
    List<Put> puts = new ArrayList<>(rows);
    byte[] qualifier = Bytes.toBytes("val");
    for (int i = 0; i < flushes; i++) {
      for (int k = 0; k < rows; k++) {
        byte[] row = Bytes.add(Bytes.toBytes(k), Bytes.toBytes(i));
        Put p = new Put(row);
        for (int j = 0; j < families.length; ++j) {
          p.addColumn(families[j], qualifier, row);
        }
        puts.add(p);
      }
      table.putAll(puts).join();
      TEST_UTIL.flush();
      puts.clear();
    }
  }
}

redpajama_set_name: RedPajamaGithub


text:
// Copyright (c) DNN Software. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace DotNetNuke.Web.Mvc.Helpers
{
    public static class HtmlEditorExtensions
    {
        public static MvcHtmlString EditorFor<TModel, TValue>(this DnnHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
        {
            var htmlHelper = html.HtmlHelper as HtmlHelper<TModel>;
            return htmlHelper.EditorFor(expression);
        }

        public static MvcHtmlString EditorFor<TModel, TValue>(this DnnHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object additionalViewData)
        {
            var htmlHelper = html.HtmlHelper as HtmlHelper<TModel>;
            return htmlHelper.EditorFor(expression, additionalViewData);
        }

        public static MvcHtmlString EditorFor<TModel, TValue>(this DnnHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string templateName)
        {
            var htmlHelper = html.HtmlHelper as HtmlHelper<TModel>;
            return htmlHelper.EditorFor(expression, templateName);
        }

        public static MvcHtmlString EditorFor<TModel, TValue>(this DnnHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string templateName, object additionalViewData)
        {
            var htmlHelper = html.HtmlHelper as HtmlHelper<TModel>;
            return htmlHelper.EditorFor(expression, templateName, additionalViewData);
        }

        public static MvcHtmlString EditorFor<TModel, TValue>(this DnnHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string templateName, string htmlFieldName)
        {
            var htmlHelper = html.HtmlHelper as HtmlHelper<TModel>;
            return htmlHelper.EditorFor(expression, templateName, htmlFieldName);
        }

        public static MvcHtmlString EditorFor<TModel, TValue>(this DnnHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string templateName, string htmlFieldName, object additionalViewData)
        {
            var htmlHelper = html.HtmlHelper as HtmlHelper<TModel>;
            return htmlHelper.EditorFor(expression, templateName, htmlFieldName, additionalViewData);
        }
    }
}


text:
title: Getting Unity to construct an instance with the default constructor
categories: .Net
tags: Unity
date: 2010-03-26 16:51:19 +10:00
---

I wasted a lot of time this afternoon trying to get some Unity configuration to work.

One of the issues I had was that I wanted to inject a concrete type that didn't have an interface. This turned about to be simple as Unity natively supports it. You just don't need to define a mapTo attribute on the type element. The issue that hit me was that Unity was not invoking the constructor that I was expecting. My type that has the following constructors:

<!--more-->

```csharp
public class Settings
{
    public Settings()
        : this(ConfigurationStoreFactory.Create())
    {
    }

    public Settings(IConfigurationStore store)
    {
    }
}
```

In my attempt to wire this up, my Unity configuration contained the following definition:

```xml
<type type="Neovolve.Jabiru.Server.Business.Settings, Neovolve.Jabiru.Server.Business">
</type>
```

Unity was not able to create an instance of Settings with this configuration. The reason was that Unity was calling the constructor with an interface definition rather than the default constructor. This is not what I expected given that I was not defining any constructor configuration for the type.

The following configuration must be used in order for Unity to invoke the default constructor.

```xml
<type type="Neovolve.Jabiru.Server.Business.Settings, Neovolve.Jabiru.Server.Business">
    <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,
                            Microsoft.Practices.Unity.Configuration">
    <constructor>
    </constructor>
    </typeConfig>
</type>
```

This is completely counter-intuitive, but that's life.


text:
package org.apache.jackrabbit.oak.security.authorization.permission;

import java.util.Collection;

import org.apache.jackrabbit.oak.api.Root;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * The permission store is used to store and provide access control permissions for principals. It is responsible to
 * load and store the permissions in an optimal form in the repository and must not cache them.
 */
interface PermissionStore {

    long DYNAMIC_ALL_BITS = -1;

    /**
     * Loads the permission entries for the given principal and path. If no
     * entries can be found for the given principal or path, {@code null} is returned.
     *
     * @param principalName name of the principal
     * @param path access controlled path.
     * @return the given {@code entries}, a new collection or {@code null}
     */
    @Nullable
    Collection<PermissionEntry> load(@NotNull String principalName, @NotNull String path);

    @NotNull
    PrincipalPermissionEntries load(@NotNull String principalName);

    @NotNull
    NumEntries getNumEntries(@NotNull String principalName, long max);

    void flush(@NotNull Root root);

}


text:
struct PrimeSieveOptions
{
  std::deque<uint64_t> n;
  int flags;
  int sieveSize;
  int threads;
  bool quiet;
  bool nthPrime;
  PrimeSieveOptions() :
    flags(0),
    sieveSize(0),
    threads(0),
    quiet(false),
    nthPrime(false)
  { }
};

PrimeSieveOptions parseOptions(int, char**);

#endif


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<TITLE>
KeyspaceDefinition (astyanax 1.0.3 API)
</TITLE>

<META NAME="date" CONTENT="2012-05-24">

<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../stylesheet.css" TITLE="Style">

      Overview
      Package
    Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

  All Classes

  SUMMARY: NESTED | FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD

com.netflix.astyanax.ddl

Interface KeyspaceDefinition

All Known Implementing Classes:
ThriftKeyspaceDefinitionImpl

public interface KeyspaceDefinition

Method Summary

 KeyspaceDefinition
addColumnFamily(ColumnFamilyDefinition cfDef)

 KeyspaceDefinition
addStrategyOption(String name,
                  String value)

 ColumnFamilyDefinition
getColumnFamily(String columnFamily)

 List<ColumnFamilyDefinition>
getColumnFamilyList()

 String
getName()

 String
getStrategyClass()

 Map<String,String>
getStrategyOptions()

 KeyspaceDefinition
setName(String name)

 KeyspaceDefinition
setStrategyClass(String strategyClass)

 KeyspaceDefinition
setStrategyOptions(Map<String,String> options)

Method Detail

setName

KeyspaceDefinition setName(String name)

getName

String getName()

setStrategyClass

KeyspaceDefinition setStrategyClass(String strategyClass)

getStrategyClass

String getStrategyClass()

setStrategyOptions

KeyspaceDefinition setStrategyOptions(Map<String,String> options)

addStrategyOption

KeyspaceDefinition addStrategyOption(String name,
                                     String value)

getStrategyOptions

Map<String,String> getStrategyOptions()

addColumnFamily

KeyspaceDefinition addColumnFamily(ColumnFamilyDefinition cfDef)

getColumnFamilyList

List<ColumnFamilyDefinition> getColumnFamilyList()

getColumnFamily

ColumnFamilyDefinition getColumnFamily(String columnFamily)

      Overview
      Package
    Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

  All Classes

  SUMMARY: NESTED | FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD

Copyright © 2012. All Rights Reserved.


text:
namespace metaforce {

CScriptRipple::CScriptRipple(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& vec,
                             bool active, float f1)
: CEntity(uid, info, active, name), x34_magnitude(f1 >= 0.f ? f1 : 0.5f), x38_center(vec) {}

void CScriptRipple::Accept(IVisitor& visitor) { visitor.Visit(this); }

void CScriptRipple::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
  if (msg != EScriptObjectMessage::Play) {
    CEntity::AcceptScriptMsg(msg, uid, mgr);
    return;
  }

  if (!GetActive()) {
    return;
  }

  for (const SConnection& conn : x20_conns) {
    if (conn.x0_state != EScriptObjectState::Active || conn.x4_msg != EScriptObjectMessage::Next) {
      continue;
    }

    const auto search = mgr.GetIdListForScript(conn.x8_objId);
    for (auto it = search.first; it != search.second; ++it) {
      if (const TCastToPtr<CScriptWater> water = mgr.ObjectById(it->second)) {
        water->GetFluidPlane().AddRipple(x34_magnitude, GetUniqueId(), x38_center, *water, mgr);
      }
    }
  }

}
} // namespace metaforce


text:
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;

namespace {

class JavaArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
  JavaArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
      : SyntheticChildrenFrontEnd(*valobj_sp) {
    if (valobj_sp)
      Update();
  }

  size_t CalculateNumChildren() override {
    ValueObjectSP valobj = GetDereferencedValueObject();
    if (!valobj)
      return 0;

    CompilerType type = valobj->GetCompilerType();
    uint32_t size = JavaASTContext::CalculateArraySize(type, *valobj);
    if (size == UINT32_MAX)
      return 0;
    return size;
  }

  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
    ValueObjectSP valobj = GetDereferencedValueObject();
    if (!valobj)
      return nullptr;

    ProcessSP process_sp = valobj->GetProcessSP();
    if (!process_sp)
      return nullptr;

    CompilerType type = valobj->GetCompilerType();
    CompilerType element_type = type.GetArrayElementType();
    lldb::addr_t address =
        valobj->GetAddressOf() +
        JavaASTContext::CalculateArrayElementOffset(type, idx);

    Status error;
    size_t byte_size = element_type.GetByteSize(nullptr);
    DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
    size_t bytes_read = process_sp->ReadMemory(address, buffer_sp->GetBytes(),
                                               byte_size, error);
    if (error.Fail() || byte_size != bytes_read)
      return nullptr;

    StreamString name;
    name.Printf("[%" PRIu64 "]", (uint64_t)idx);
    DataExtractor data(buffer_sp, process_sp->GetByteOrder(),
                       process_sp->GetAddressByteSize());
    return CreateValueObjectFromData(
        name.GetString(), data, valobj->GetExecutionContextRef(), element_type);
  }

  bool Update() override { return false; }

  bool MightHaveChildren() override { return true; }

  size_t GetIndexOfChildWithName(const ConstString &name) override {
    return ExtractIndexFromString(name.GetCString());
  }

private:
  ValueObjectSP GetDereferencedValueObject() {
    if (!m_backend.IsPointerOrReferenceType())
      return m_backend.GetSP();

    Status error;
    return m_backend.Dereference(error);
  }
};

} // end of anonymous namespace

bool lldb_private::formatters::JavaStringSummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) {
  if (valobj.IsPointerOrReferenceType()) {
    Status error;
    ValueObjectSP deref = valobj.Dereference(error);
    if (error.Fail())
      return false;
    return JavaStringSummaryProvider(*deref, stream, opts);
  }

  ProcessSP process_sp = valobj.GetProcessSP();
  if (!process_sp)
    return false;

  ConstString data_name("value");
  ConstString length_name("count");

  ValueObjectSP length_sp = valobj.GetChildMemberWithName(length_name, true);
  ValueObjectSP data_sp = valobj.GetChildMemberWithName(data_name, true);
  if (!data_sp || !length_sp)
    return false;

  bool success = false;
  uint64_t length = length_sp->GetValueAsUnsigned(0, &success);
  if (!success)
    return false;

  if (length == 0) {
    stream.Printf("\"\"");
    return true;
  }
  lldb::addr_t valobj_addr = data_sp->GetAddressOf();

  StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
  options.SetLocation(valobj_addr);
  options.SetProcessSP(process_sp);
  options.SetStream(&stream);
  options.SetSourceSize(length);
  options.SetNeedsZeroTermination(false);
  options.SetLanguage(eLanguageTypeJava);

  if (StringPrinter::ReadStringAndDumpToStream<
          StringPrinter::StringElementType::UTF16>(options))
    return true;

  stream.Printf("Summary Unavailable");
  return true;
}

bool lldb_private::formatters::JavaArraySummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
  if (valobj.IsPointerOrReferenceType()) {
    Status error;
    ValueObjectSP deref = valobj.Dereference(error);
    if (error.Fail())
      return false;
    return JavaArraySummaryProvider(*deref, stream, options);
  }

  CompilerType type = valobj.GetCompilerType();
  uint32_t size = JavaASTContext::CalculateArraySize(type, valobj);
  if (size == UINT32_MAX)
    return false;
  stream.Printf("[%u]{...}", size);
  return true;
}

SyntheticChildrenFrontEnd *
lldb_private::formatters::JavaArraySyntheticFrontEndCreator(
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
  return valobj_sp ? new JavaArraySyntheticFrontEnd(valobj_sp) : nullptr;
}


text:
/**
 * @module ember-declarative/ed-container/mixin
 *
 * mixin for main declaration container class, whose template
 * yields for declarations and then renders implementation.
 *
 */

import Ember from 'ember';

export default Ember.Mixin.create({

  declarations: Ember.computed({
    get(){ return Ember.A(); }, set(k, v){ return v; }}),
  register: null,

  registerDeclaration(declaration) {
    let declarations = this.get('declarations');
    declarations.pushObject(declaration);
  },

});


text:
<!-- TODO: Something useful here -->
<div>{{ results }}</div>


text:
package mods.alice.infiniteorb.tileentity;

import mods.alice.infiniteorb.EnergyType;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;

public abstract class TileEntityGenerator extends TileEntity
{
	public int outputAmount;
	public int outputPerTick;
	public int outputTick;
	protected int tickToNextOut;

	public static TileEntity createTile(World world, EnergyType type)
	{
		TileEntity tile;

		switch(type)
		{
		case EU:
			tile = new TileEntityGeneratorEU();
			break;
		case MJ:
			tile = new TileEntityGeneratorMJ();
			break;
		default:
			tile = null;
			break;
		}

		if(tile != null)
		{
			tile.setWorldObj(world);
		}

		return tile;
	}

	public abstract void updateParameters();

	public abstract void updateParameters(int outAmount, int outPerTick, int outTick);

	@Override
	public Packet getDescriptionPacket()
	{
		NBTTagCompound tag;

		tag = new NBTTagCompound();
		writeToNBT(tag);

		return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 1, tag);
	}

	@Override
	public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt)
	{
		if((pkt.func_148856_c() == xCoord) && (pkt.func_148855_d() == yCoord) && (pkt.func_148854_e() == zCoord) && (pkt.func_148853_f() == 1))
		{
			NBTTagCompound tag = pkt.func_148857_g();
			if(tag != null)
			{
				try
				{
					readFromNBT(tag);
				}
				catch(Exception e)
				{
				}
			}
		}
	}

	@Override
	public void readFromNBT(NBTTagCompound tag)
	{
		super.readFromNBT(tag);

		outputAmount = tag.getInteger("PowerTotal");
		outputPerTick = tag.getInteger("PowerPerTick");
		outputTick = tag.getInteger("Tick");
		tickToNextOut = tag.getInteger("WaitCount");

		updateParameters();
	}

	@Override
	public void writeToNBT(NBTTagCompound tag)
	{
		super.writeToNBT(tag);

		tag.setInteger("PowerTotal", outputAmount);
		tag.setInteger("PowerPerTick", outputPerTick);
		tag.setInteger("Tick", outputTick);
		tag.setInteger("WaitCount", tickToNextOut);
	}
}