Example #1
0
/* Set up RANDR extension                          */
void randr_init(xcb_connection_t * conn,xcb_screen_t * screen)
{
  const xcb_query_extension_reply_t *extension;

        
    extension = xcb_get_extension_data(conn, &xcb_randr_id);
    if (!extension->present)
    {
        PDEBUG("No RANDR extension.\n");
        return;
    }
    else
    {
        randr_get(conn,screen);
    }

    randrbase = extension->first_event;
    PDEBUG("randrbase is %d.\n", randrbase);
        
    xcb_randr_select_input(conn, screen->root,
                           XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
                           XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
                           XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
                           XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);

    
}
/**
 * Select if the ScreenChangeNotify events  will be sent.
 * @param window The window.
 * @param on     1 to enable, 0 to disable.
 * @return       1 on success, 0 otherwise.
 *
 * If @p on value is @c 1, ScreenChangeNotify events
 * will be sent when the screen configuration changes, either from
 * this protocol extension, or due to detected external screen
 * configuration changes. ScreenChangeNotify may also be sent when
 * this request executes if the screen configuration has changed since
 * the client connected, to avoid race conditions.
 * @ingroup Ecore_X_RandR_Group
 */
EAPI int
ecore_x_randr_events_select(Ecore_X_Window window,
                            int            on)
{
#ifdef ECORE_XCB_RANDR
     xcb_randr_select_input(_ecore_xcb_conn, window,
                            on ? XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE : 0);
     return 1;
#else
   return 0;
#endif /* ECORE_XCB_RANDR */
}
Example #3
0
bool ScreenManager::configureRandR(xcb_connection_t *conn)
{
    const xcb_query_extension_reply_t *ext = xcb_get_extension_data(conn, &xcb_randr_id);
    if (!ext->present) {
        return false;
    }
    xcb_randr_query_version_reply_t *ver =
        xcb_randr_query_version_reply(
            conn, xcb_randr_query_version(conn, 1, 1), 0);
    if (!ver) {
        return false;
    }
    _randrBase = ext->first_event;
    xcb_randr_select_input(conn, _rootWindow,
        XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
       XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
       XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
       XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);
    xcb_flush(conn);
    return true;
}
Example #4
0
void event_handle(xcb_generic_event_t *event)
{
    uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event);

    if(response_type == 0)
    {
        /* This is an error, not a event */
        xerror((xcb_generic_error_t *) event);
        return;
    }

    switch(response_type)
    {
#define EVENT(type, callback) case type: callback((void *) event); return
        EVENT(XCB_BUTTON_PRESS, event_handle_button);
        EVENT(XCB_BUTTON_RELEASE, event_handle_button);
        EVENT(XCB_CONFIGURE_REQUEST, event_handle_configurerequest);
        EVENT(XCB_CONFIGURE_NOTIFY, event_handle_configurenotify);
        EVENT(XCB_DESTROY_NOTIFY, event_handle_destroynotify);
        EVENT(XCB_ENTER_NOTIFY, event_handle_enternotify);
        EVENT(XCB_CLIENT_MESSAGE, event_handle_clientmessage);
        EVENT(XCB_EXPOSE, event_handle_expose);
        EVENT(XCB_FOCUS_IN, event_handle_focusin);
        EVENT(XCB_KEY_PRESS, event_handle_key);
        EVENT(XCB_KEY_RELEASE, event_handle_key);
        EVENT(XCB_LEAVE_NOTIFY, event_handle_leavenotify);
        EVENT(XCB_MAPPING_NOTIFY, event_handle_mappingnotify);
        EVENT(XCB_MAP_REQUEST, event_handle_maprequest);
        EVENT(XCB_MOTION_NOTIFY, event_handle_motionnotify);
        EVENT(XCB_PROPERTY_NOTIFY, property_handle_propertynotify);
        EVENT(XCB_REPARENT_NOTIFY, event_handle_reparentnotify);
        EVENT(XCB_UNMAP_NOTIFY, event_handle_unmapnotify);
        EVENT(XCB_SELECTION_CLEAR, event_handle_selectionclear);
#undef EVENT
    }

    static uint8_t randr_screen_change_notify = 0;
    static uint8_t randr_output_change_notify = 0;
    static uint8_t shape_notify = 0;
    static uint8_t xkb_notify = 0;

    if(randr_screen_change_notify == 0 || randr_output_change_notify == 0)
    {
        /* check for randr extension */
        const xcb_query_extension_reply_t *randr_query;
        randr_query = xcb_get_extension_data(globalconf.connection, &xcb_randr_id);
        if(randr_query->present) {
            xcb_randr_select_input(globalconf.connection, globalconf.screen->root, XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE);
            randr_screen_change_notify = randr_query->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY;
            randr_output_change_notify = randr_query->first_event + XCB_RANDR_NOTIFY;
        }
    }

    if(shape_notify == 0)
    {
        /* check for shape extension */
        const xcb_query_extension_reply_t *shape_query;
        shape_query = xcb_get_extension_data(globalconf.connection, &xcb_shape_id);
        if(shape_query->present)
            shape_notify = shape_query->first_event + XCB_SHAPE_NOTIFY;
    }

    if(xkb_notify == 0)
    {
        /* check for xkb extension */
        const xcb_query_extension_reply_t *xkb_query;
        xkb_query = xcb_get_extension_data(globalconf.connection, &xcb_xkb_id);
        if(xkb_query->present)
            xkb_notify = xkb_query->first_event;
    }

    if (response_type == randr_screen_change_notify)
        event_handle_randr_screen_change_notify((void *) event);
    if (response_type == randr_output_change_notify)
        event_handle_randr_output_change_notify((void *) event);
    if (response_type == shape_notify)
        event_handle_shape_notify((void *) event);
    if (response_type == xkb_notify)
        event_handle_xkb_notify((void *) event);
}
Example #5
0
static gboolean
_eventd_nd_xcb_start(EventdNdBackendContext *self, const gchar *target)
{
    gint r;
    gchar *h;
    gint d;

    r = xcb_parse_display(target, &h, &d, NULL);
    if ( r == 0 )
        return FALSE;
    free(h);

    const xcb_query_extension_reply_t *extension_query;
    gint screen;

    self->source = g_water_xcb_source_new(NULL, target, &screen, _eventd_nd_xcb_events_callback, self, NULL);
    if ( self->source == NULL )
    {
        g_warning("Couldn't initialize X connection for '%s'", target);
        return FALSE;
    }

    self->xcb_connection = g_water_xcb_source_get_connection(self->source);
    self->screen_number = screen;
    self->screen = xcb_aux_get_screen(self->xcb_connection, screen);

    self->bubbles = g_hash_table_new(NULL, NULL);

    if ( self->follow_focus != EVENTD_ND_XCB_FOLLOW_FOCUS_NONE )
    {
        guint32 mask[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
        xcb_change_window_attributes(self->xcb_connection, self->screen->root, XCB_CW_EVENT_MASK, mask);
    }

    xcb_intern_atom_cookie_t *ac;
    ac = xcb_ewmh_init_atoms(self->xcb_connection, &self->ewmh);
    xcb_ewmh_init_atoms_replies(&self->ewmh, ac, NULL);

    extension_query = xcb_get_extension_data(self->xcb_connection, &xcb_randr_id);
    if ( ! extension_query->present )
        g_warning("No RandR extension");
    else
    {
        self->randr = TRUE;
        self->randr_event_base = extension_query->first_event;
        xcb_randr_select_input(self->xcb_connection, self->screen->root,
                XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
                XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
                XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
                XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);
    }

    self->custom_map = _eventd_nd_xcb_get_colormap(self);

    if ( self->custom_map )
    {
        /* We have a 32bit color map, try to support compositing */
        xcb_get_selection_owner_cookie_t oc;
        xcb_window_t owner;
        oc = xcb_ewmh_get_wm_cm_owner(&self->ewmh, self->screen_number);
        self->compositing = xcb_ewmh_get_wm_cm_owner_reply(&self->ewmh, oc, &owner, NULL) && ( owner != XCB_WINDOW_NONE );

        extension_query = xcb_get_extension_data(self->xcb_connection, &xcb_xfixes_id);
        if ( ! extension_query->present )
            g_warning("No XFixes extension");
        else
        {
            xcb_xfixes_query_version_cookie_t vc;
            xcb_xfixes_query_version_reply_t *r;
            vc = xcb_xfixes_query_version(self->xcb_connection, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
            r = xcb_xfixes_query_version_reply(self->xcb_connection, vc, NULL);
            if ( r == NULL )
                g_warning("Cannot get XFixes version");
            else
            {
                self->xfixes = TRUE;
                self->xfixes_event_base = extension_query->first_event;
                xcb_xfixes_select_selection_input_checked(self->xcb_connection, self->screen->root,
                    self->ewmh._NET_WM_CM_Sn[self->screen_number],
                    XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
                    XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
                    XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE);
            }
        }
    }

    extension_query = xcb_get_extension_data(self->xcb_connection, &xcb_shape_id);
    if ( ! extension_query->present )
        g_warning("No Shape extension");
    else
        self->shape = TRUE;

    xcb_flush(self->xcb_connection);
    _eventd_nd_xcb_check_geometry(self);

    return TRUE;
}
Example #6
0
QT_BEGIN_NAMESPACE

QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
                       xcb_randr_get_output_info_reply_t *output, QString outputName, int number)
    : QXcbObject(connection)
    , m_screen(scr)
    , m_crtc(output ? output->crtc : 0)
    , m_outputName(outputName)
    , m_sizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
    , m_virtualSize(scr->width_in_pixels, scr->height_in_pixels)
    , m_virtualSizeMillimeters(scr->width_in_millimeters, scr->height_in_millimeters)
    , m_orientation(Qt::PrimaryOrientation)
    , m_number(number)
    , m_refreshRate(60)
    , m_forcedDpi(-1)
{
    if (connection->hasXRandr())
        xcb_randr_select_input(xcb_connection(), screen()->root, true);

    updateGeometry(output ? output->timestamp : 0);
    updateRefreshRate();

    // On VNC, it can be that physical size is unknown while
    // virtual size is known (probably back-calculated from DPI and resolution)
    if (m_sizeMillimeters.isEmpty())
        m_sizeMillimeters = m_virtualSizeMillimeters;
    if (m_geometry.isEmpty())
        m_geometry = QRect(QPoint(), m_virtualSize);
    if (m_availableGeometry.isEmpty())
        m_availableGeometry = QRect(QPoint(), m_virtualSize);

    readXResources();


#ifdef Q_XCB_DEBUG
    qDebug();
    qDebug("Screen output %s of xcb screen %d:", m_outputName.toUtf8().constData(), m_number);
    qDebug("  width..........: %lf", m_sizeMillimeters.width());
    qDebug("  height.........: %lf", m_sizeMillimeters.height());
    qDebug("  geometry.......: %d x %d +%d +%d", m_geometry.width(), m_geometry.height(), m_geometry.x(), m_geometry.y());
    qDebug("  virtual width..: %lf", m_virtualSizeMillimeters.width());
    qDebug("  virtual height.: %lf", m_virtualSizeMillimeters.height());
    qDebug("  virtual geom...: %d x %d", m_virtualSize.width(), m_virtualSize.height());
    qDebug("  avail virt geom: %d x %d +%d +%d", m_availableGeometry.width(), m_availableGeometry.height(), m_availableGeometry.x(), m_availableGeometry.y());
    qDebug("  depth..........: %d", screen()->root_depth);
    qDebug("  white pixel....: %x", screen()->white_pixel);
    qDebug("  black pixel....: %x", screen()->black_pixel);
    qDebug("  refresh rate...: %d", m_refreshRate);
    qDebug("  root ID........: %x", screen()->root);
#endif

    const quint32 mask = XCB_CW_EVENT_MASK;
    const quint32 values[] = {
        // XCB_CW_EVENT_MASK
        XCB_EVENT_MASK_ENTER_WINDOW
        | XCB_EVENT_MASK_LEAVE_WINDOW
        | XCB_EVENT_MASK_PROPERTY_CHANGE
    };

    xcb_change_window_attributes(xcb_connection(), screen()->root, mask, values);

    xcb_get_property_reply_t *reply =
        xcb_get_property_reply(xcb_connection(),
            xcb_get_property_unchecked(xcb_connection(), false, screen()->root,
                             atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK),
                             XCB_ATOM_WINDOW, 0, 1024), NULL);

    if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) {
        xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply));

        if (windowManager != XCB_WINDOW_NONE) {
            xcb_get_property_reply_t *windowManagerReply =
                xcb_get_property_reply(xcb_connection(),
                    xcb_get_property_unchecked(xcb_connection(), false, windowManager,
                                     atom(QXcbAtom::_NET_WM_NAME),
                                     atom(QXcbAtom::UTF8_STRING), 0, 1024), NULL);
            if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) {
                m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply));
#ifdef Q_XCB_DEBUG
                qDebug("  window manager.: %s", qPrintable(m_windowManagerName));
                qDebug();
#endif
            }

            free(windowManagerReply);
        }
    }
    free(reply);

    const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id);
    if (!sync_reply || !sync_reply->present)
        m_syncRequestSupported = false;
    else
        m_syncRequestSupported = m_windowManagerName != QLatin1String("KWin");

    m_clientLeader = xcb_generate_id(xcb_connection());
    Q_XCB_CALL2(xcb_create_window(xcb_connection(),
                                  XCB_COPY_FROM_PARENT,
                                  m_clientLeader,
                                  screen()->root,
                                  0, 0, 1, 1,
                                  0,
                                  XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                  screen()->root_visual,
                                  0, 0), connection);

    Q_XCB_CALL2(xcb_change_property(xcb_connection(),
                                    XCB_PROP_MODE_REPLACE,
                                    m_clientLeader,
                                    atom(QXcbAtom::WM_CLIENT_LEADER),
                                    XCB_ATOM_WINDOW,
                                    32,
                                    1,
                                    &m_clientLeader), connection);

    xcb_depth_iterator_t depth_iterator =
        xcb_screen_allowed_depths_iterator(screen());

    while (depth_iterator.rem) {
        xcb_depth_t *depth = depth_iterator.data;
        xcb_visualtype_iterator_t visualtype_iterator =
            xcb_depth_visuals_iterator(depth);

        while (visualtype_iterator.rem) {
            xcb_visualtype_t *visualtype = visualtype_iterator.data;
            m_visuals.insert(visualtype->visual_id, *visualtype);
            xcb_visualtype_next(&visualtype_iterator);
        }

        xcb_depth_next(&depth_iterator);
    }

    m_cursor = new QXcbCursor(connection, this);
}
Example #7
0
void Extensions::init()
{
    xcb_connection_t *c = connection();
    xcb_prefetch_extension_data(c, &xcb_shape_id);
    xcb_prefetch_extension_data(c, &xcb_randr_id);
    xcb_prefetch_extension_data(c, &xcb_damage_id);
    xcb_prefetch_extension_data(c, &xcb_composite_id);
    xcb_prefetch_extension_data(c, &xcb_xfixes_id);
    xcb_prefetch_extension_data(c, &xcb_render_id);
    xcb_prefetch_extension_data(c, &xcb_sync_id);

    m_shape.name     = QByteArray("SHAPE");
    m_randr.name     = QByteArray("RANDR");
    m_damage.name    = QByteArray("DAMAGE");
    m_composite.name = QByteArray("Composite");
    m_fixes.name     = QByteArray("XFIXES");
    m_render.name    = QByteArray("RENDER");
    m_sync.name      = QByteArray("SYNC");

    extensionQueryReply(xcb_get_extension_data(c, &xcb_shape_id), &m_shape);
    extensionQueryReply(xcb_get_extension_data(c, &xcb_randr_id), &m_randr);
    extensionQueryReply(xcb_get_extension_data(c, &xcb_damage_id), &m_damage);
    extensionQueryReply(xcb_get_extension_data(c, &xcb_composite_id), &m_composite);
    extensionQueryReply(xcb_get_extension_data(c, &xcb_xfixes_id), &m_fixes);
    extensionQueryReply(xcb_get_extension_data(c, &xcb_render_id), &m_render);
    extensionQueryReply(xcb_get_extension_data(c, &xcb_sync_id), &m_sync);

    // extension specific queries
    xcb_shape_query_version_cookie_t shapeVersion;
    xcb_randr_query_version_cookie_t randrVersion;
    xcb_damage_query_version_cookie_t damageVersion;
    xcb_composite_query_version_cookie_t compositeVersion;
    xcb_xfixes_query_version_cookie_t xfixesVersion;
    xcb_render_query_version_cookie_t renderVersion;
    xcb_sync_initialize_cookie_t syncVersion;
    if (m_shape.present) {
        shapeVersion = xcb_shape_query_version_unchecked(c);
    }
    if (m_randr.present) {
        randrVersion = xcb_randr_query_version_unchecked(c, RANDR_MAX_MAJOR, RANDR_MAX_MINOR);
        xcb_randr_select_input(connection(), rootWindow(), XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
    }
    if (m_damage.present) {
        damageVersion = xcb_damage_query_version_unchecked(c, DAMAGE_MAX_MAJOR, DAMAGE_MIN_MAJOR);
    }
    if (m_composite.present) {
        compositeVersion = xcb_composite_query_version_unchecked(c, COMPOSITE_MAX_MAJOR, COMPOSITE_MAX_MINOR);
    }
    if (m_fixes.present) {
        xfixesVersion = xcb_xfixes_query_version_unchecked(c, XFIXES_MAX_MAJOR, XFIXES_MAX_MINOR);
    }
    if (m_render.present) {
        renderVersion = xcb_render_query_version_unchecked(c, RENDER_MAX_MAJOR, RENDER_MAX_MINOR);
    }
    if (m_sync.present) {
        syncVersion = xcb_sync_initialize(c, SYNC_MAX_MAJOR, SYNC_MAX_MINOR);
    }
    // handle replies
    if (m_shape.present) {
        initVersion<xcb_shape_query_version_reply_t>(shapeVersion, &xcb_shape_query_version_reply, &m_shape);
    }
    if (m_randr.present) {
        initVersion<xcb_randr_query_version_reply_t>(randrVersion, &xcb_randr_query_version_reply, &m_randr);
    }
    if (m_damage.present) {
        initVersion<xcb_damage_query_version_reply_t>(damageVersion, &xcb_damage_query_version_reply, &m_damage);
    }
    if (m_composite.present) {
        initVersion<xcb_composite_query_version_reply_t>(compositeVersion, &xcb_composite_query_version_reply, &m_composite);
    }
    if (m_fixes.present) {
        initVersion<xcb_xfixes_query_version_reply_t>(xfixesVersion, &xcb_xfixes_query_version_reply, &m_fixes);
    }
    if (m_render.present) {
        initVersion<xcb_render_query_version_reply_t>(renderVersion, &xcb_render_query_version_reply, &m_render);
    }
    if (m_sync.present) {
        initVersion<xcb_sync_initialize_reply_t>(syncVersion, &xcb_sync_initialize_reply, &m_sync);
    }
    qDebug() << "Extensions: shape: 0x" << QString::number(m_shape.version, 16)
                 << " composite: 0x" << QString::number(m_composite.version, 16)
                 << " render: 0x" << QString::number(m_render.version, 16)
                 << " fixes: 0x" << QString::number(m_fixes.version, 16)
                 << " randr: 0x" << QString::number(m_randr.version, 16)
                 << " sync: 0x" << QString::number(m_sync.version, 16)
                 << " damage: 0x " << QString::number(m_damage.version, 16) << endl;
}
Example #8
0
static void init_xcb()
{
    const xcb_query_extension_reply_t *qer;
    const xcb_setup_t *setup;
    xcb_screen_t *screen;
    xcb_screen_iterator_t screen_iter;
    xcb_drawable_t win;
    guint num_screens;
    guint i;
    xcb_generic_error_t *err = NULL;

    /* Open xcb connection */
    conn = xcb_connect(gdk_get_display_arg_name(), NULL);
    if (xcb_connection_has_error(conn)) {
        g_error("Failed to connect to display\n");
        exit(EXIT_FAILURE);
    }

    /* query the version to prevent error 16 when setting config */
    xcb_randr_query_version_unchecked(conn, 1, 5);

    qer = xcb_get_extension_data(conn, &xcb_randr_id);
    if (!qer || !qer->present) {
        g_error("RandR extension missing\n");
        exit(EXIT_FAILURE);
    }
    randr_base = qer->first_event;

    xcb_source = g_xcb_source_new_for_connection(NULL, conn);
    g_xcb_source_set_event_callback(xcb_source, on_xcb_event, NULL);

    /* get the screens */
    setup = xcb_get_setup(conn);
    screen_iter = xcb_setup_roots_iterator(setup);

    num_screens = setup->roots_len;

    /* Set up space for cookies */
    xcb_randr_get_screen_info_cookie_t get_screen_info_cookies[num_screens];

    for (i = 0; i < num_screens; i++) {
        /* Get root window */
        screen = screen_iter.data;
        win = screen->root;

        /* Register for screen change events */
        xcb_randr_select_input(conn, win, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);

        /* Get screen info */
        get_screen_info_cookies[i] =
            xcb_randr_get_screen_info_unchecked(conn, win);

        xcb_screen_next(&screen_iter);
    }
    /* TODO: detect adding and removal of screens */

    xcb_flush(conn);

    /* Get screen info replies */
    for (i = 0; i < num_screens; i++) {
        xcb_randr_get_screen_info_reply_t *reply =
            xcb_randr_get_screen_info_reply(conn,
                    get_screen_info_cookies[i], &err);
        if (err) {
            g_warning("Error getting info for screen %u\n", i);
            err = NULL;
            continue;
        }

        add_screen(reply);
        free(reply);
    }
    xcb_flush(conn);
}
Example #9
0
int main() {

	uint8_t xrandr;
	struct pollfd poll_fd;
	fd_set set;
	int fd;
	int retval;
	int timeout;

	setlocale (LC_ALL, "");
//	bindtextdomain (PACKAGE, LOCALEDIR);
//	textdomain (PACKAGE);

	printf("TabletWM version 0.25\n");

	init_tabletwm();

	uint32_t v[]={XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY|XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT};
	xcb_change_window_attributes(conn,scr->root,XCB_CW_EVENT_MASK,v);
	support_capture_key(XCB_MOD_MASK_CONTROL,23); // Ctrl+TAB
	support_capture_key(XCB_MOD_MASK_1,23); // Alt+TAB
	support_capture_key(XCB_MOD_MASK_1,70); // Alt+F4
	support_capture_key(XCB_MOD_MASK_ANY,135); // MENU key (between the right WINDOWS key and the right Ctrl key)
	support_capture_key(XCB_MOD_MASK_ANY,124); // POWER key
	//xcb_grab_key(conn,0,scr->root,XCB_MOD_MASK_ANY,XCB_GRAB_ANY,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC);

#ifdef DEBUG
	support_capture_key(XCB_MOD_MASK_1,71); // Alt+F5 for VALGRIND tests
#endif

	/* detect changes in screen size with xrandr */
	xcb_randr_query_version_reply_t *r=xcb_randr_query_version_reply(conn,xcb_randr_query_version(conn,1,1),0);
	if (r) {
		xcb_randr_select_input(conn,scr->root,XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);

		const xcb_query_extension_reply_t *r2=xcb_get_extension_data(conn,&xcb_randr_id);
		xrandr=r2->first_event;
	}
	free(r);

	xcb_flush(conn);
	xcb_generic_event_t *e;
	
	keep_running=1;
	
	support_launch_manager();
	fd = xcb_get_file_descriptor(conn);
	while(keep_running) {
		poll_fd.fd=fd;
		poll_fd.events=POLLIN;
		poll_fd.revents=0;
		if (key_win.possition!=0) {
			retval = poll(&poll_fd,1,2000); // refresh every two seconds if the bar is visible
		} else {
			retval = poll(&poll_fd,1,-1); // just wait for an event when the bar is not visible
		}
		if (retval==0) {
			menuwin_expose(NULL); // each 10 seconds of inactivity, refresh the user bar to keep the clock and indicators updated
			continue;
		}
		while(e=xcb_poll_for_event(conn)) {
			uint8_t r=e->response_type&~0x80;
		
			if (r>=xrandr) {
				printf("XRandR\n");
				switch(r-xrandr) {
					case(XCB_RANDR_SCREEN_CHANGE_NOTIFY):
						action_xrandr_screen_change_notify(e);
					break;
					default:
						printf("XRandR unknown: %d\n",r-xrandr);
					break;
				}
			} else {
				switch(r) {
					case(XCB_KEY_RELEASE):
						action_key(e);
					break;
					case (XCB_CREATE_NOTIFY):
						//xcb_create_notify_event_t *ee=(xcb_create_notify_event_t *)e;
					break;
					case(XCB_UNMAP_NOTIFY):
						action_unmap_notify(e);
					break;
					case(XCB_DESTROY_NOTIFY):
						action_destroy_notify(e);
					break;
					case(XCB_MAP_REQUEST):
						action_map_request(e);
					break;
					case(XCB_MAP_NOTIFY):
					case(XCB_MAPPING_NOTIFY):
						support_send_dock_up(NULL,NULL); // ensure that the dock is always on top
					break;
					case(XCB_CONFIGURE_NOTIFY):
						action_configure_notify(e);
					break;
					case(XCB_CONFIGURE_REQUEST):
						action_configure_request(e);
					break;
					case(XCB_CIRCULATE_REQUEST):
						//xcb_circulate_request_event_t *ee=(xcb_circulate_request_event_t *)e;
					break;
					case(XCB_EXPOSE):
						action_expose(e);
					break;
					case(XCB_ENTER_NOTIFY):
						action_mouse_enter(e);
					break;
					case(XCB_LEAVE_NOTIFY):
						action_mouse_leave(e);
					break;
					case(XCB_BUTTON_RELEASE):
						action_mouse_click(e);
					break;
					case(0): {
						xcb_generic_error_t *ee=(xcb_generic_error_t *)e;
						printf("error event type %d\n",ee->error_code);
					}
					break;
					default:
						printf("unhandled event type %d\n",e->response_type);
					break;
				}
			}
			free(e);
		}
	}
	destroy_tabletwm();
	xcb_disconnect(conn);
	return(0);
}