Пример #1
0
static void
_eventd_nd_xcb_surface_draw(EventdNdSurface *self)
{
    xcb_clear_area(self->context->xcb_connection, TRUE, self->window, 0, 0, 0, 0);
    self->context->nd->notification_draw(self->notification, self->surface, self->context->compositing);
    xcb_flush(self->context->xcb_connection);
}
Пример #2
0
/*
 * Calls draw_image on a new pixmap and swaps that with the current pixmap
 *
 */
void redraw_screen(void) {

    /* avoid drawing if monitor state is not on */
    if (dpms_capable) {
        xcb_dpms_info_reply_t *dpms_info =
            xcb_dpms_info_reply(conn,xcb_dpms_info(conn), NULL);
        if (dpms_info) {
            /* monitor is off when DPMS state is enabled and power level is not
             * DPMS_MODE_ON */
            uint8_t monitor_off = dpms_info->state
                && dpms_info->power_level != XCB_DPMS_DPMS_MODE_ON;
            free(dpms_info);
            if (monitor_off)
                return;
        }
    }

    xcb_pixmap_t bg_pixmap = draw_image(last_resolution);
    xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){ bg_pixmap });
    /* XXX: Possible optimization: Only update the area in the middle of the
     * screen instead of the whole screen. */
    xcb_clear_area(conn, 0, win, 0, 0, last_resolution[0], last_resolution[1]);
    xcb_free_pixmap(conn, bg_pixmap);
    xcb_flush(conn);
}
/*
 * Calls draw_image on a new pixmap and swaps that with the current pixmap
 *
 */
void redraw_screen(void) {
    xcb_pixmap_t bg_pixmap = draw_image(last_resolution);
    xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){bg_pixmap});
    /* XXX: Possible optimization: Only update the area in the middle of the
     * screen instead of the whole screen. */
    xcb_clear_area(conn, 0, win, 0, 0, last_resolution[0], last_resolution[1]);
    xcb_free_pixmap(conn, bg_pixmap);
    xcb_flush(conn);
}
void QXcbNativeInterface::clearRegion(const QWindow *qwindow, const QRect& rect)
{
    if (const QPlatformWindow *platformWindow = qwindow->handle()) {
        const QXcbWindow *qxwindow = static_cast<const QXcbWindow *>(platformWindow);
        xcb_connection_t *xcb_conn = qxwindow->xcb_connection();

        xcb_clear_area(xcb_conn, false, qxwindow->xcb_window(), rect.x(), rect.y(), rect.width(), rect.height());
    }
}
Пример #5
0
SNIProxy::SNIProxy(xcb_window_t wid, QObject* parent):
    QObject(parent),
    //Work round a bug in our SNIWatcher with multiple SNIs per connection.
    //there is an undocumented feature that you can register an SNI by path, however it doesn't detect an object on a service being removed, only the entire service closing
    //instead lets use one DBus connection per SNI
    m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("XembedSniProxy%1").arg(s_serviceCount++))),
    m_windowId(wid)
{
    //create new SNI
    new StatusNotifierItemAdaptor(this);
    m_dbus.registerObject(QStringLiteral("/StatusNotifierItem"), this);

    auto statusNotifierWatcher = new org::kde::StatusNotifierWatcher(QStringLiteral(SNI_WATCHER_SERVICE_NAME), QStringLiteral(SNI_WATCHER_PATH), QDBusConnection::sessionBus(), this);
    auto reply = statusNotifierWatcher->RegisterStatusNotifierItem(m_dbus.baseService());
    reply.waitForFinished();
    if (reply.isError()) {
        qCWarning(SNIPROXY) << "could not register SNI:" << reply.error().message();
    }

    auto c = QX11Info::connection();

    auto cookie = xcb_get_geometry(c, m_windowId);
    QScopedPointer<xcb_get_geometry_reply_t> clientGeom(xcb_get_geometry_reply(c, cookie, Q_NULLPTR));

    //create a container window
    auto screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
    m_containerWid = xcb_generate_id(c);
    uint32_t             values[2];
    auto mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT;
    values[0] = screen->black_pixel; //draw a solid background so the embeded icon doesn't get garbage in it
    values[1] = true; //bypass wM
    xcb_create_window (c,                          /* connection    */
                    XCB_COPY_FROM_PARENT,          /* depth         */
                     m_containerWid,               /* window Id     */
                     screen->root,                 /* parent window */
                     -500, 0,                       /* x, y          */
                     s_embedSize, s_embedSize,     /* width, height */
                     0,                           /* border_width  */
                     XCB_WINDOW_CLASS_INPUT_OUTPUT,/* class         */
                     screen->root_visual,          /* visual        */
                     mask, values);                /* masks         */

    /*
        We need the window to exist and be mapped otherwise the child won't render it's contents

        We also need it to exist in the right place to get the clicks working as GTK will check sendEvent locations to see if our window is in the right place. So even though our contents are drawn via compositing we still put this window in the right place

        We can't composite it away anything parented owned by the root window (apparently)
        Stack Under works in the non composited case, but it doesn't seem to work in kwin's composited case (probably need set relevant NETWM hint)

        As a last resort set opacity to 0 just to make sure this container never appears
    */

#ifndef VISUAL_DEBUG
    const uint32_t stackBelowData[] = {XCB_STACK_MODE_BELOW};
    xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackBelowData);

    NETWinInfo wm(c, m_containerWid, screen->root, 0);
    wm.setOpacity(0);
#endif

    xcb_flush(c);

    xcb_map_window(c, m_containerWid);

    xcb_reparent_window(c, wid,
                        m_containerWid,
                        0, 0);

    /*
     * Render the embedded window offscreen
     */
    xcb_composite_redirect_window(c, wid, XCB_COMPOSITE_REDIRECT_MANUAL);


    /* we grab the window, but also make sure it's automatically reparented back
     * to the root window if we should die.
    */
    xcb_change_save_set(c, XCB_SET_MODE_INSERT, wid);

    //tell client we're embedding it
    xembed_message_send(wid, XEMBED_EMBEDDED_NOTIFY, m_containerWid, 0, 0);

    //move window we're embedding
    const uint32_t windowMoveConfigVals[2] = { 0, 0 };

    xcb_configure_window(c, wid,
                             XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
                             windowMoveConfigVals);


    //if the window is a clearly stupid size resize to be something sensible
    //this is needed as chormium and such when resized just fill the icon with transparent space and only draw in the middle
    //however spotify does need this as by default the window size is 900px wide.
    //use an artbitrary heuristic to make sure icons are always sensible
    if (clientGeom->width < 12 || clientGeom->width > s_embedSize ||
        clientGeom->height < 12 || clientGeom->height > s_embedSize)
    {
        const uint32_t windowMoveConfigVals[2] = { s_embedSize, s_embedSize };
        xcb_configure_window(c, wid,
                                XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
                                windowMoveConfigVals);
    }

    //show the embedded window otherwise nothing happens
    xcb_map_window(c, wid);

    xcb_clear_area(c, 0, wid, 0, 0, qMin(clientGeom->width, s_embedSize), qMin(clientGeom->height, s_embedSize));

    xcb_flush(c);

    //there's no damage event for the first paint, and sometimes it's not drawn immediately
    //not ideal, but it works better than nothing
    //test with xchat before changing
    QTimer::singleShot(500, this, &SNIProxy::update);
}