EAPI void ecore_x_composite_redirect_window(Ecore_X_Window win, Ecore_X_Composite_Update_Type type) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!_composite_avail) return; #ifdef ECORE_XCB_COMPOSITE uint8_t update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; switch (type) { case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC: update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; break; case ECORE_X_COMPOSITE_UPDATE_MANUAL: update = XCB_COMPOSITE_REDIRECT_MANUAL; break; } xcb_composite_redirect_window(_ecore_xcb_conn, win, update); // ecore_x_flush(); #endif }
// === EmbedWindow() === uint LXCB::EmbedWindow(WId win, WId container){ if(DEBUG){ qDebug() << "XCB: EmbedWindow()"; } //This returns the damage control ID number (or 0 for a failure) if(win==0 || container==0){ return 0; } //qDebug() << "Embed Window:" << win << container; //Initialize any atoms that will be needed xcb_intern_atom_cookie_t ecookie = xcb_intern_atom_unchecked(QX11Info::connection(), 0, 7, "_XEMBED"); xcb_intern_atom_reply_t *ereply = xcb_intern_atom_reply(QX11Info::connection(), ecookie, NULL); if(ereply==0){ return 0; } //unable to initialize the atom xcb_atom_t emb = ereply->atom; free(ereply); //done with this structure //Reparent the window into the container xcb_reparent_window(QX11Info::connection(), win, container, 0, 0); xcb_map_window(QX11Info::connection(), win); //Now send the embed event to the app //qDebug() << " - send _XEMBED event"; xcb_client_message_event_t event; event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; event.window = win; event.type = emb; //_XEMBED event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY event.data.data32[2] = 0; event.data.data32[3] = container; //WID of the container event.data.data32[4] = 0; xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); //Now setup any redirects and return //qDebug() << " - select Input"; //XSelectInput(disp, win, StructureNotifyMask); //Notify of structure changes //uint32_t val[] = {XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY}; //xcb_change_window_attributes(QX11Info::connection(), win, XCB_CW_EVENT_MASK, val); this->SelectInput(win); //qDebug() << " - Composite Redirect"; xcb_composite_redirect_window(QX11Info::connection(), win, XCB_COMPOSITE_REDIRECT_MANUAL); //Now map the window (will be a transparent child of the container) xcb_map_window(QX11Info::connection(), win); //Now create/register the damage handler xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer xcb_damage_create(QX11Info::connection(), dmgID, win, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); //qDebug() << " - Done"; return ( (uint) dmgID ); }
void setup_screen() { window = xcb_generate_id(c); xcb_create_window(c, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, 800, 600, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, (uint32_t[]){ screen->white_pixel, XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE }); xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, WM_PROTOCOLS, XCB_ATOM_ATOM, 32, 1, (uint32_t[]){ WM_DELETE_WINDOW }); xcb_composite_redirect_window(c, window, XCB_COMPOSITE_REDIRECT_AUTOMATIC); xcb_map_window(c, window); xcb_flush(c); }
/** * Probes and initializes. */ static int Open (vlc_object_t *obj) { demux_t *demux = (demux_t *)obj; demux_sys_t *p_sys = malloc (sizeof (*p_sys)); if (p_sys == NULL) return VLC_ENOMEM; demux->p_sys = p_sys; /* Connect to X server */ char *display = var_InheritString (obj, "x11-display"); int snum; xcb_connection_t *conn = xcb_connect (display, &snum); free (display); if (xcb_connection_has_error (conn)) { free (p_sys); return VLC_EGENERIC; } p_sys->conn = conn; /* Find configured screen */ if (!strcmp (demux->psz_access, "screen")) { const xcb_setup_t *setup = xcb_get_setup (conn); const xcb_screen_t *scr = NULL; for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup); i.rem > 0; xcb_screen_next (&i)) { if (snum == 0) { scr = i.data; break; } snum--; } if (scr == NULL) { msg_Err (obj, "bad X11 screen number"); goto error; } p_sys->window = scr->root; } else /* Determine capture window */ if (!strcmp (demux->psz_access, "window")) { char *end; unsigned long ul = strtoul (demux->psz_location, &end, 0); if (*end || ul > 0xffffffff) { msg_Err (obj, "bad X11 drawable %s", demux->psz_location); goto error; } p_sys->window = ul; xcb_composite_query_version_reply_t *r = xcb_composite_query_version_reply (conn, xcb_composite_query_version (conn, 0, 4), NULL); if (r == NULL || r->minor_version < 2) { msg_Err (obj, "X Composite extension not available"); free (r); goto error; } msg_Dbg (obj, "using Composite extension v%"PRIu32".%"PRIu32, r->major_version, r->minor_version); free (r); xcb_composite_redirect_window (conn, p_sys->window, XCB_COMPOSITE_REDIRECT_AUTOMATIC); } else goto error; /* Window properties */ p_sys->pixmap = xcb_generate_id (conn); p_sys->w = var_InheritInteger (obj, "screen-width"); p_sys->h = var_InheritInteger (obj, "screen-height"); if (p_sys->w != 0 || p_sys->h != 0) p_sys->follow_mouse = var_InheritBool (obj, "screen-follow-mouse"); else /* Following mouse is meaningless if width&height are dynamic. */ p_sys->follow_mouse = false; if (!p_sys->follow_mouse) /* X and Y are meaningless if following mouse */ { p_sys->x = var_InheritInteger (obj, "screen-left"); p_sys->y = var_InheritInteger (obj, "screen-top"); } /* Initializes format */ p_sys->rate = var_InheritFloat (obj, "screen-fps"); if (!p_sys->rate) goto error; p_sys->interval = (float)CLOCK_FREQ / p_sys->rate; if (!p_sys->interval) goto error; var_Create (obj, "screen-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT); p_sys->cur_w = 0; p_sys->cur_h = 0; p_sys->es = NULL; p_sys->pts = VLC_TS_INVALID; if (vlc_timer_create (&p_sys->timer, Demux, demux)) goto error; vlc_timer_schedule (p_sys->timer, false, 1, p_sys->interval); /* Initializes demux */ demux->pf_demux = NULL; demux->pf_control = Control; return VLC_SUCCESS; error: xcb_disconnect (p_sys->conn); free (p_sys); return VLC_EGENERIC; }
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); }