WindowPixmapInterface::Ptr PrivateCompositeWindow::getPixmap () { Pixmap pixmap = XCompositeNameWindowPixmap (screen->dpy (), ROOTPARENT (window)); WindowPixmapInterface::Ptr p (new X11WindowPixmap (screen->dpy (), pixmap)); return p; }
void window_set_mapped(Window id, bool mapped) { window_t *window = window_get(id); if (window == NULL) return; window->mapped = mapped; if (mapped == TRUE) { XRenderPictFormat *format; XRenderPictureAttributes pa; format = XRenderFindVisualFormat(conn, visual); pa.subwindow_mode = IncludeInferiors; if (window->picture != None) XRenderFreePicture(conn, window->picture); if (window->pixmap != None) XFreePixmap(conn, window->pixmap); window->pixmap = XCompositeNameWindowPixmap(conn, id); window->picture = XRenderCreatePicture(conn, window->pixmap, format, CPSubwindowMode, &pa); XDamageCreate(conn, window->pixmap, XDamageReportNonEmpty); window_list_remove(id); window_list_append(id); } }
void add(Window w) { XWindowAttributes attr; int i; if (w == root || w == overlay || w == canvas-1) return; debug("[AddWindow] Adding window 0x%x\n", w); if (workspace == NULL) { workspace = malloc(sizeof(Client) * MAX_CLIENTS); memset(workspace, 0, sizeof(Client) * MAX_CLIENTS); } for (i=0; i<MAX_CLIENTS && workspace[i].window != 0; i++) if (workspace[i].window == 0) break; unsigned int v; int target; GLuint texture; GLXFBConfig fbc = choose_fbconfig(); Pixmap pixmap = XCompositeNameWindowPixmap(dpy, w); debug("Got pixmap 0x%x for 0x%x\n", pixmap, w); XGetWindowAttributes(dpy, w, &attr); if (attr.depth == 32) pixmap_attr[1] = GLX_TEXTURE_FORMAT_RGBA_EXT; else pixmap_attr[1] = GLX_TEXTURE_FORMAT_RGB_EXT; GLXPixmap glxpixmap = glXCreatePixmap(dpy, fbc, pixmap, pixmap_attr); debug("Got glxpixmap 0x%x for 0x%x\n", glxpixmap, pixmap); check_gl(__LINE__); glXQueryDrawable(dpy, glxpixmap, GLX_WIDTH, &v); check_gl(__LINE__); debug("GLX is %d width\n", v); glXQueryDrawable(dpy, glxpixmap, GLX_HEIGHT, &v); check_gl(__LINE__); debug("GLX is %d height\n", v); glXQueryDrawableProc(dpy, glxpixmap, GLX_TEXTURE_TARGET_EXT, &target); check_gl(__LINE__); debug("GLX is 0x%x\n", target); glGenTextures(1, &texture); check_gl(__LINE__); switch (target) { case GLX_TEXTURE_2D_EXT: warn("GLX_TEXTURE_2D_EXT requested but we don't support that yet\n"); target = GL_TEXTURE_2D; break; case GLX_TEXTURE_RECTANGLE_EXT: target = GL_TEXTURE_RECTANGLE_ARB; break; default: die(ERR_INVALID_TEXTURE, "Invalid target: 0x%x\n", target); } info("Window 0x%x has glx = %x, target 0x%x and texture %d\n", w, glxpixmap, target, texture); workspace[i].window = w; workspace[i].glxpixmap = glxpixmap; workspace[i].target = target; workspace[i].texture = texture; XGetWindowAttributes(dpy, w, &(workspace[i].geom)); }
void compzillaWindow::Resized (PRInt32 x, PRInt32 y, PRInt32 width, PRInt32 height, PRInt32 border) { if (width != mAttr.width || height != mAttr.height || border != mAttr.border_width || mAttr.override_redirect) { if (mIsRedirected) { ReleaseWindow (); mPixmap = XCompositeNameWindowPixmap (mDisplay, mWindow); if (mPixmap == None) return; for (PRUint32 i = mContentNodes.Count() - 1; i != PRUint32(-1); --i) { nsIDOMHTMLCanvasElement *aContent = mContentNodes.ObjectAt (i); aContent->SetWidth (width); aContent->SetHeight (height); } Damaged (NULL); } } mAttr.x = x; mAttr.y = y; mAttr.width = width; mAttr.height = height; mAttr.border_width = border; }
static gboolean on_ref_mapped(GtkWidget *widget, GdkEvent *event, gpointer user_data) { g_debug("%s", __func__); if (!back_pixmap) { g_assert(gtk_widget_is_visible(ref)); GdkWindow* gdkwin = gtk_widget_get_window(ref); back_pixmap = XCompositeNameWindowPixmap(display, GDK_WINDOW_XID(gdkwin)); glx_pm = glXCreatePixmap(display, bestFbc, back_pixmap, pixmap_attribs); } return FALSE; }
cairo_surface_t* RedirectedXCompositeWindow::cairoSurfaceForWidget(GtkWidget* widget) { if (!m_needsNewPixmapAfterResize && m_surface) return m_surface.get(); m_needsNewPixmapAfterResize = false; // It's important that the new pixmap be created with the same Display pointer as the target // widget or else drawing speed can be 100x slower. Display* newPixmapDisplay = GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(widget)); Pixmap newPixmap = XCompositeNameWindowPixmap(newPixmapDisplay, m_window); if (!newPixmap) { cleanupPixmapAndPixmapSurface(); return 0; } XWindowAttributes windowAttributes; if (!XGetWindowAttributes(newPixmapDisplay, m_window, &windowAttributes)) { cleanupPixmapAndPixmapSurface(); XFreePixmap(newPixmapDisplay, newPixmap); return 0; } RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_xlib_surface_create(newPixmapDisplay, newPixmap, windowAttributes.visual, m_size.width(), m_size.height())); // Nvidia drivers seem to prepare their redirected window pixmap asynchronously, so for a few fractions // of a second after each resize, while doing continuous resizing (which constantly destroys and creates // pixmap window-backings), the pixmap memory is uninitialized. To work around this issue, paint the old // pixmap to the new one to properly initialize it. if (m_surface) { RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get())); cairo_set_source_rgb(cr.get(), 1, 1, 1); cairo_paint(cr.get()); cairo_set_source_surface(cr.get(), m_surface.get(), 0, 0); cairo_paint(cr.get()); } cleanupPixmapAndPixmapSurface(); m_pixmap = newPixmap; m_surface = newSurface; return m_surface.get(); }
static void update_pixmap (MetaSurfaceActorX11 *self) { MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); MetaDisplay *display = priv->display; Display *xdisplay = meta_display_get_xdisplay (display); if (priv->size_changed) { detach_pixmap (self); priv->size_changed = FALSE; } if (priv->pixmap == None) { Pixmap new_pixmap; Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window); meta_error_trap_push (display); new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow); if (meta_error_trap_pop_with_return (display) != Success) { /* Probably a BadMatch if the window isn't viewable; we could * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync * to avoid this, but there's no reason to take two round trips * when one will do. (We need that Sync if we want to handle failures * for any reason other than !viewable. That's unlikely, but maybe * we'll BadAlloc or something.) */ new_pixmap = None; } if (new_pixmap == None) { meta_verbose ("Unable to get named pixmap for %s\n", meta_window_get_description (priv->window)); return; } set_pixmap (self, new_pixmap); } }
cairo_surface_t* RedirectedXCompositeWindow::surface() { // This should never be called with an empty size (not in Accelerated Compositing mode). ASSERT(!m_size.isEmpty()); if (!m_needsNewPixmapAfterResize && m_surface) return m_surface.get(); m_needsNewPixmapAfterResize = false; Pixmap newPixmap = XCompositeNameWindowPixmap(m_display, m_window); if (!newPixmap) { cleanupPixmapAndPixmapSurface(); return nullptr; } XWindowAttributes windowAttributes; if (!XGetWindowAttributes(m_display, m_window, &windowAttributes)) { cleanupPixmapAndPixmapSurface(); XFreePixmap(m_display, newPixmap); return nullptr; } RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_xlib_surface_create(m_display, newPixmap, windowAttributes.visual, m_size.width(), m_size.height())); // Nvidia drivers seem to prepare their redirected window pixmap asynchronously, so for a few fractions // of a second after each resize, while doing continuous resizing (which constantly destroys and creates // pixmap window-backings), the pixmap memory is uninitialized. To work around this issue, paint the old // pixmap to the new one to properly initialize it. if (m_surface) { RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get())); cairo_set_source_rgb(cr.get(), 1, 1, 1); cairo_paint(cr.get()); cairo_set_source_surface(cr.get(), m_surface.get(), 0, 0); cairo_paint(cr.get()); } cleanupPixmapAndPixmapSurface(); m_pixmap = newPixmap; m_surface = newSurface; return m_surface.get(); }
void MTexturePixmapPrivate::saveBackingStore() { if (item->propertyCache()->isVirtual()) { TFP.bind(item->windowPixmap()); return; } if ((item->propertyCache()->is_valid && !item->propertyCache()->isMapped()) || item->propertyCache()->isInputOnly() || !window) return; if (TFP.drawable) XFreePixmap(QX11Info::display(), TFP.drawable); // Pixmap is already freed. No sense to bind it to texture if (item->isClosing() || item->window() < QX11Info::appRootWindow()) return; Drawable pixmap = XCompositeNameWindowPixmap(QX11Info::display(), item->window()); TFP.bind(pixmap); }
void createPixmap(uint32_t winId) { XWindowAttributes attr; XGetWindowAttributes(m_display, winId, &attr); XRenderPictFormat* format = XRenderFindVisualFormat(m_display, attr.visual); m_hasAlpha = (format->type == PictTypeDirect && format->direct.alphaMask); m_size = IntSize(attr.width, attr.height); int numberOfConfigs; GLXFBConfig* configs = glXChooseFBConfig(m_display, XDefaultScreen(m_display), glxSpec, &numberOfConfigs); m_xPixmap = XCompositeNameWindowPixmap(m_display, winId); m_glxPixmap = glXCreatePixmap(m_display, *configs, m_xPixmap, glxAttributes); uint inverted = 0; glXQueryDrawable(m_display, m_glxPixmap, GLX_Y_INVERTED_EXT, &inverted); m_textureIsYInverted = !!inverted; XFree(configs); }
void RedirectedXCompositeWindow::createNewPixampAndPixampSurface() { // This should never be called with an empty size (not in Accelerated Compositing mode). ASSERT(!m_size.isEmpty()); XUniquePixmap newPixmap(XCompositeNameWindowPixmap(m_display, m_window.get())); if (!newPixmap) { cleanupPixmapAndPixmapSurface(); return; } XWindowAttributes windowAttributes; if (!XGetWindowAttributes(m_display, m_window.get(), &windowAttributes)) { cleanupPixmapAndPixmapSurface(); return; } RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_xlib_surface_create(m_display, newPixmap.get(), windowAttributes.visual, m_size.width(), m_size.height())); cairoSurfaceSetDeviceScale(newSurface.get(), m_webPage.deviceScaleFactor(), m_webPage.deviceScaleFactor()); RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get())); if (!m_webPage.drawsBackground()) cairo_set_operator(cr.get(), CAIRO_OPERATOR_CLEAR); else setSourceRGBAFromColor(cr.get(), m_webPage.backgroundColor()); cairo_paint(cr.get()); // Nvidia drivers seem to prepare their redirected window pixmap asynchronously, so for a few fractions // of a second after each resize, while doing continuous resizing (which constantly destroys and creates // pixmap window-backings), the pixmap memory is uninitialized. To work around this issue, paint the old // pixmap to the new one to properly initialize it. if (m_surface) { cairo_set_operator(cr.get(), CAIRO_OPERATOR_OVER); cairo_set_source_surface(cr.get(), m_surface.get(), 0, 0); cairo_paint(cr.get()); } cleanupPixmapAndPixmapSurface(); m_pixmap = WTFMove(newPixmap); m_surface = WTFMove(newSurface); }
static gboolean on_ref_configure(GtkWidget *widget, GdkEvent *event, gpointer user_data) { g_debug("%s", __func__); GdkEventConfigure *gec = (GdkEventConfigure*)event; g_width = gec->width; g_height = gec->height; gtk_window_resize(GTK_WINDOW(top), g_width, g_height); if (!gtk_widget_get_mapped(ref)) return TRUE; if (back_pixmap) { glXDestroyPixmap(display, glx_pm); XFreePixmap(display, back_pixmap); GdkWindow* gdkwin = gtk_widget_get_window(ref); back_pixmap = XCompositeNameWindowPixmap(display, GDK_WINDOW_XID(gdkwin)); glx_pm = glXCreatePixmap(display, bestFbc, back_pixmap, pixmap_attribs); } return TRUE; }
void compzillaWindow::BindWindow () { RedirectWindow (); if (!mPixmap) { XGrabServer (mDisplay); UpdateAttributes (); if (mAttr.map_state == IsViewable) { // Set up persistent offscreen window contents pixmap. mPixmap = XCompositeNameWindowPixmap (mDisplay, mWindow); if (mPixmap == None) { ERROR ("XCompositeNameWindowPixmap failed for window %p\n", mWindow); } } XUngrabServer (mDisplay); } }
void createPixmap(uint32_t winId) { XWindowAttributes attr; XGetWindowAttributes(m_display, winId, &attr); XRenderPictFormat* format = XRenderFindVisualFormat(m_display, attr.visual); m_hasAlpha = (format->type == PictTypeDirect && format->direct.alphaMask); int numberOfConfigs; GLXFBConfig* configs = glXChooseFBConfig(m_display, XDefaultScreen(m_display), glxSpec, &numberOfConfigs); // If origin window has alpha then find config with alpha. GLXFBConfig& config = m_hasAlpha ? findFBConfigWithAlpha(configs, numberOfConfigs) : configs[0]; m_xPixmap = XCompositeNameWindowPixmap(m_display, winId); m_glxPixmap = glXCreatePixmap(m_display, config, m_xPixmap, glxAttributes); uint inverted = 0; glXQueryDrawable(m_display, m_glxPixmap, GLX_Y_INVERTED_EXT, &inverted); m_textureIsYInverted = !!inverted; XFree(configs); }
void SceneXrender::selfCheckSetup() { KXErrorHandler err; QImage img( selfCheckWidth(), selfCheckHeight(), QImage::Format_RGB32 ); img.setPixel( 0, 0, QColor( Qt::red ).rgb()); img.setPixel( 1, 0, QColor( Qt::green ).rgb()); img.setPixel( 2, 0, QColor( Qt::blue ).rgb()); img.setPixel( 0, 1, QColor( Qt::white ).rgb()); img.setPixel( 1, 1, QColor( Qt::black ).rgb()); img.setPixel( 2, 1, QColor( Qt::white ).rgb()); QPixmap pix = QPixmap::fromImage( img ); foreach( const QPoint& p, selfCheckPoints()) { XSetWindowAttributes wa; wa.override_redirect = True; ::Window window = XCreateWindow( display(), rootWindow(), 0, 0, selfCheckWidth(), selfCheckHeight(), 0, QX11Info::appDepth(), CopyFromParent, CopyFromParent, CWOverrideRedirect, &wa ); XSetWindowBackgroundPixmap( display(), window, pix.handle()); XClearWindow( display(), window ); XMapWindow( display(), window ); // move the window one down to where the result will be rendered too, just in case // the render would fail completely and eventual check would try to read this window's contents XMoveWindow( display(), window, p.x() + 1, p.y()); XCompositeRedirectWindow( display(), window, CompositeRedirectAutomatic ); Pixmap wpix = XCompositeNameWindowPixmap( display(), window ); XWindowAttributes attrs; XGetWindowAttributes( display(), window, &attrs ); XRenderPictFormat* format = XRenderFindVisualFormat( display(), attrs.visual ); Picture pic = XRenderCreatePicture( display(), wpix, format, 0, 0 ); QRect rect( p.x(), p.y(), selfCheckWidth(), selfCheckHeight()); XRenderComposite( display(), PictOpSrc, pic, None, buffer, 0, 0, 0, 0, rect.x(), rect.y(), rect.width(), rect.height()); XRenderFreePicture( display(), pic ); XFreePixmap( display(), wpix ); XDestroyWindow( display(), window ); }
void XCompositeEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer) { XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer); Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window()); QVector<EGLint> eglConfigSpec = eglbuildSpec(); EGLint matching = 0; EGLConfig config; bool matched = eglChooseConfig(mEglDisplay,eglConfigSpec.constData(),&config,1,&matching); if (!matched || !matching) { qWarning("Could not retrieve a suitable EGL config"); return; } QVector<EGLint> attribList; attribList.append(EGL_TEXTURE_FORMAT); attribList.append(EGL_TEXTURE_RGBA); attribList.append(EGL_TEXTURE_TARGET); attribList.append(EGL_TEXTURE_2D); attribList.append(EGL_NONE); EGLSurface surface = eglCreatePixmapSurface(mEglDisplay,config,pixmap,attribList.constData()); if (surface == EGL_NO_SURFACE) { qDebug() << "Failed to create eglsurface" << pixmap << compositorBuffer->window(); } compositorBuffer->setInvertedY(true); if (!eglBindTexImage(mEglDisplay,surface,EGL_BACK_BUFFER)) { qDebug() << "Failed to bind"; } // eglDestroySurface(mEglDisplay,surface); }
GLboolean stubIsWindowVisible(WindowInfo *win) { #if defined(WINDOWS) # ifdef VBOX_WITH_WDDM if (stub.bRunningUnderWDDM) return win->mapped; # endif return GL_TRUE; #elif defined(Darwin) return GL_TRUE; #elif defined(GLX) Display *dpy = stubGetWindowDisplay(win); if (dpy) { XWindowAttributes attr; XLOCK(dpy); XGetWindowAttributes(dpy, win->drawable, &attr); XUNLOCK(dpy); if (attr.map_state == IsUnmapped) { return GL_FALSE; } # if 1 return GL_TRUE; # else if (attr.override_redirect) { return GL_TRUE; } if (!stub.bXExtensionsChecked) { stubCheckXExtensions(win); } if (!stub.bHaveXComposite) { return GL_TRUE; } else { Pixmap p; crLockMutex(&stub.mutex); XLOCK(dpy); XSync(dpy, false); oldErrorHandler = XSetErrorHandler(errorHandler); /*@todo this will create new pixmap for window every call*/ p = XCompositeNameWindowPixmap(dpy, win->drawable); XSync(dpy, false); XSetErrorHandler(oldErrorHandler); XUNLOCK(dpy); switch (lastXError) { case Success: XFreePixmap(dpy, p); crUnlockMutex(&stub.mutex); return GL_FALSE; break; case BadMatch: /*Window isn't redirected*/ lastXError = Success; break; default: crWarning("Unexpected XError %i", (int)lastXError); lastXError = Success; } crUnlockMutex(&stub.mutex); return GL_TRUE; } # endif } else { /* probably created by crWindowCreate() */ return win->mapped; } #endif }
int xcomposite_get_widow_contents() { int ret = 0; int ver, rev, eventB, baseB; int x, y; Pixmap pxm = 0; window_struct params; if(create_window(¶ms, "Test Window")) { ret = -1; goto cleanup; } if(!XCompositeQueryExtension(params.display, &eventB, &baseB)) { BLTS_ERROR("XCompositeQueryExtension failed\n"); ret = -1; goto cleanup; } if(!XCompositeQueryVersion(params.display, &ver, &rev)) { BLTS_ERROR("XCompositeQueryVersion failed\n"); ret = -1; goto cleanup; } BLTS_DEBUG("XComposite Extension version %i.%i\n", ver, rev); /* Redirect window to off-screen storage (the window might be already redirected when using composite window manager) */ XCompositeRedirectWindow(params.display, params.window, 0); /* Draw rectangle pattern */ for(x = 0; x < params.window_attributes.width; x+=20) { for(y = 0; y < params.window_attributes.height; y+=20) { XFillRectangle(params.display, params.window, params.gc, x, y, 10, 10); } } XFlush(params.display); sleep(1); /* Get pixmap of window contents */ pxm = XCompositeNameWindowPixmap(params.display, params.window); XCompositeUnredirectWindow(params.display, params.window, 0); /* Copy the pixmap over the window (you should see white/black stripes * after this) */ for(y = 0; y < params.window_attributes.height; y++) { XCopyArea(params.display, pxm, params.window, params.gc, 0, 0, params.window_attributes.width, params.window_attributes.height, 0, y ); } XFlush(params.display); sleep(1); cleanup: if(params.display && pxm) { XFreePixmap(params.display, pxm); } close_window(¶ms); return ret; }
/** * clutter_x11_texture_pixmap_sync_window: * @texture: the texture to bind * * Resets the texture's pixmap from its window, perhaps in response to the * pixmap's invalidation as the window changed size. * * Since: 0.8 **/ void clutter_x11_texture_pixmap_sync_window (ClutterX11TexturePixmap *texture) { ClutterX11TexturePixmapPrivate *priv; Pixmap pixmap; g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture)); priv = texture->priv; if (priv->destroyed) return; if (!clutter_x11_has_composite_extension()) { clutter_x11_texture_pixmap_set_pixmap (texture, priv->window); return; } if (priv->window) { XWindowAttributes attr; Display *dpy = clutter_x11_get_default_display (); gboolean mapped, notify_x, notify_y, notify_override_redirect; /* We may get a BadMatch error here if the window is not mapped. * If so, ignore it - pixmap should be set to None in that case anyway */ XSync (dpy, FALSE); clutter_x11_trap_x_errors (); XGetWindowAttributes (dpy, priv->window, &attr); mapped = attr.map_state == IsViewable; if (mapped) pixmap = XCompositeNameWindowPixmap (dpy, priv->window); else pixmap = None; XSync (dpy, FALSE); if (clutter_x11_untrap_x_errors() && pixmap!=None) g_warning("%s: Got X error but pixmap is still set", __FUNCTION__); notify_x = attr.x != priv->window_x; notify_y = attr.y != priv->window_y; notify_override_redirect = attr.override_redirect != priv->override_redirect; priv->window_x = attr.x; priv->window_y = attr.y; priv->override_redirect = attr.override_redirect; g_object_ref (texture); /* guard against unparent */ if (pixmap) { clutter_x11_texture_pixmap_set_pixmap (texture, pixmap); priv->owns_pixmap = TRUE; } clutter_x11_texture_pixmap_set_mapped (texture, mapped); /* could do more clever things with a signal, i guess.. */ if (notify_override_redirect) g_object_notify (G_OBJECT (texture), "window-override-redirect"); if (notify_x) g_object_notify (G_OBJECT (texture), "window-x"); if (notify_y) g_object_notify (G_OBJECT (texture), "window-y"); g_object_unref (texture); } }
void XCompcapMain::updateSettings(obs_data_t *settings) { PLock lock(&p->lock); XErrorLock xlock; ObsGsContextHolder obsctx; blog(LOG_DEBUG, "Settings updating"); Window prevWin = p->win; xcc_cleanup(p); if (settings) { const char *windowName = obs_data_get_string(settings, "capture_window"); p->windowName = windowName; p->win = getWindowFromString(windowName); p->cut_top = obs_data_get_int(settings, "cut_top"); p->cut_left = obs_data_get_int(settings, "cut_left"); p->cut_right = obs_data_get_int(settings, "cut_right"); p->cut_bot = obs_data_get_int(settings, "cut_bot"); p->lockX = obs_data_get_bool(settings, "lock_x"); p->swapRedBlue = obs_data_get_bool(settings, "swap_redblue"); p->show_cursor = obs_data_get_bool(settings, "show_cursor"); p->include_border = obs_data_get_bool(settings, "include_border"); p->exclude_alpha = obs_data_get_bool(settings, "exclude_alpha"); } else { p->win = prevWin; } xlock.resetError(); if (p->win) XCompositeRedirectWindow(xdisp, p->win, CompositeRedirectAutomatic); if (xlock.gotError()) { blog(LOG_ERROR, "XCompositeRedirectWindow failed: %s", xlock.getErrorText().c_str()); return; } if (p->win) XSelectInput(xdisp, p->win, StructureNotifyMask | ExposureMask); XSync(xdisp, 0); XWindowAttributes attr; if (!p->win || !XGetWindowAttributes(xdisp, p->win, &attr)) { p->win = 0; p->width = 0; p->height = 0; return; } if (p->win && p->cursor && p->show_cursor) { Window child; int x, y; XTranslateCoordinates(xdisp, p->win, attr.root, 0, 0, &x, &y, &child); xcursor_offset(p->cursor, x, y); } gs_color_format cf = GS_RGBA; if (p->exclude_alpha) { cf = GS_BGRX; } p->border = attr.border_width; if (p->include_border) { p->width = attr.width + p->border * 2; p->height = attr.height + p->border * 2; } else { p->width = attr.width; p->height = attr.height; } if (p->cut_top + p->cut_bot < (int)p->height) { p->cur_cut_top = p->cut_top; p->cur_cut_bot = p->cut_bot; } else { p->cur_cut_top = 0; p->cur_cut_bot = 0; } if (p->cut_left + p->cut_right < (int)p->width) { p->cur_cut_left = p->cut_left; p->cur_cut_right = p->cut_right; } else { p->cur_cut_left = 0; p->cur_cut_right = 0; } if (p->tex) gs_texture_destroy(p->tex); uint8_t *texData = new uint8_t[width() * height() * 4]; memset(texData, 0, width() * height() * 4); const uint8_t* texDataArr[] = { texData, 0 }; p->tex = gs_texture_create(width(), height(), cf, 1, texDataArr, 0); delete[] texData; if (p->swapRedBlue) { GLuint tex = *(GLuint*)gs_texture_get_obj(p->tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glBindTexture(GL_TEXTURE_2D, 0); } const int attrs[] = { GLX_BIND_TO_TEXTURE_RGBA_EXT, GL_TRUE, GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, GLX_DOUBLEBUFFER, GL_FALSE, None }; int nelem = 0; GLXFBConfig* configs = glXChooseFBConfig(xdisp, XCompcap::getRootWindowScreen(attr.root), attrs, &nelem); if (nelem <= 0) { blog(LOG_ERROR, "no matching fb config found"); p->win = 0; p->height = 0; p->width = 0; return; } glXGetFBConfigAttrib(xdisp, configs[0], GLX_Y_INVERTED_EXT, &nelem); p->inverted = nelem != 0; xlock.resetError(); p->pixmap = XCompositeNameWindowPixmap(xdisp, p->win); if (xlock.gotError()) { blog(LOG_ERROR, "XCompositeNameWindowPixmap failed: %s", xlock.getErrorText().c_str()); p->pixmap = 0; XFree(configs); return; } const int attribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, None }; p->glxpixmap = glXCreatePixmap(xdisp, configs[0], p->pixmap, attribs); if (xlock.gotError()) { blog(LOG_ERROR, "glXCreatePixmap failed: %s", xlock.getErrorText().c_str()); XFreePixmap(xdisp, p->pixmap); XFree(configs); p->pixmap = 0; p->glxpixmap = 0; return; } XFree(configs); p->gltex = gs_texture_create(p->width, p->height, cf, 1, 0, GS_GL_DUMMYTEX); GLuint gltex = *(GLuint*)gs_texture_get_obj(p->gltex); glBindTexture(GL_TEXTURE_2D, gltex); glXBindTexImageEXT(xdisp, p->glxpixmap, GLX_FRONT_LEFT_EXT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); }
QPixmap X11Support::getWindowPixmap(unsigned long window) { return QPixmap::fromX11Pixmap(XCompositeNameWindowPixmap(QX11Info::display(), window)); }
void X11EmbedContainer::paintEvent(QPaintEvent *event) { Q_UNUSED(event); if (!d->updatesEnabled) { return; } if (!d->picture) { FdoSelectionManager::painter()->updateContainer(this); return; } QPainter p(this); // Paint the background // Translate the painter to ensure the background brush is aligned with the // rest of the panel p.translate(-x(), -y()); p.eraseRect(0, 0, x() + width(), y() + height()); p.translate(x(), y()); // Taking a detour via a QPixmap is unfortunately the only way we can get // the window contents into Qt's backing store. QPixmap pixmap(size()); if (pixmap.paintEngine()->type() != QPaintEngine::X11) { // If we're using the raster or OpenGL graphics systems, a QPixmap isn't an X pixmap, // so we have to get the window contents into a QImage and then draw that. Display *dpy = x11Info().display(); // XXX We really should keep a cached copy of the image client side, and only // update it in response to a damage event. Pixmap pixmap = XCompositeNameWindowPixmap(dpy, clientWinId()); // Extract XImage from pixmap, trying to cope with different behaviors. // There are two possible sizes: // #1: width() x height(), which is 24 x 24 in our situation // #2: d->attr.width x d->attr.height // // - Mumble 1.2.3 returns a correct image when asked for an image of // size #1 , but returns a 22 x 22 cropped icon when asked for an image // of size #2. // // - Pidgin 2.7.9 returns a NULL image when asked for an image of size // #1 but returns a correct 16 x 16 image when asked for an image of // size #2. XImage *ximage = XGetImage(dpy, pixmap, 0, 0, width(), height(), AllPlanes, ZPixmap); if (!ximage) { int ximageWidth = qMin(d->attr.width, width()); int ximageHeight = qMin(d->attr.height, height()); ximage = XGetImage(dpy, pixmap, 0, 0, ximageWidth, ximageHeight, AllPlanes, ZPixmap); } XFreePixmap(dpy, pixmap); if (!ximage) { //UQ_WARNING << "Failed to get an XImage from X11 window with XID=" << clientWinId(); return; } // This is safe to do since we only composite ARGB32 windows, and PictStandardARGB32 // matches QImage::Format_ARGB32_Premultiplied. QImage image((const uchar*)ximage->data, ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_ARGB32_Premultiplied); p.drawImage((width() - image.width()) / 2, (height() - image.height()) / 2, image); XDestroyImage(ximage); } else { pixmap.fill(Qt::transparent); XRenderComposite(x11Info().display(), PictOpSrc, d->picture, None, pixmap.x11PictureHandle(), 0, 0, 0, 0, 0, 0, width(), height()); p.drawPixmap(0, 0, pixmap); } }
// ----------------------------------------------------------------------------- // Internal stuff // ----------------------------------------------------------------------------- static void create_texture(riftwm_t *wm, riftwin_t *win) { XWindowAttributes attr; // Retrieve properties if (!XGetWindowAttributes(wm->dpy, win->window, &attr)) { riftwm_error(wm, "Cannot retrieve window attributes"); } win->width = attr.width; win->height = attr.height; if (attr.map_state != IsViewable) { return; } // Free old resources if (win->glx_pixmap) { glBindTexture(GL_TEXTURE_2D, win->texture); wm->glXReleaseTexImageEXT(wm->dpy, win->glx_pixmap, GLX_FRONT_LEFT_EXT); glBindTexture(GL_TEXTURE_2D, 0); glXDestroyPixmap(wm->dpy, win->glx_pixmap); win->glx_pixmap = 0; } if (win->pixmap) { XFreePixmap(wm->dpy, win->pixmap); win->pixmap = 0; } if (!win->texture) { glGenTextures(1, &win->texture); } // Retrieve the pixmap from the XComposite win->pixmap = XCompositeNameWindowPixmap(wm->dpy, win->window); // Create a backing OpenGL pixmap const int ATTR[] = { GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, None }; if (!(win->glx_pixmap = glXCreatePixmap(wm->dpy, wm->fb_config[1].config, win->pixmap, ATTR))) { riftwm_error(wm, "Cannot create GLX pixmap"); } // Create the texture glBindTexture(GL_TEXTURE_2D, win->texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); wm->glXBindTexImageEXT(wm->dpy, win->glx_pixmap, GLX_FRONT_LEFT_EXT, NULL); glBindTexture(GL_TEXTURE_2D, 0); win->dirty = 0; }
static DFBResult x11AllocateKey( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceBuffer *buffer, const char *key, u64 handle, CoreSurfaceAllocation *allocation, void *alloc_data ) { CoreSurface *surface; x11AllocationData *alloc = alloc_data; x11PoolLocalData *local = pool_local; DFBX11 *x11 = local->x11; D_DEBUG_AT( X11_Surfaces, "%s( %s, 0x%08llx )\n", __FUNCTION__, key, (unsigned long long) handle ); D_DEBUG_AT( X11_Surfaces, " -> allocation: %s\n", ToString_CoreSurfaceAllocation( allocation ) ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); surface = buffer->surface; D_MAGIC_ASSERT( surface, CoreSurface ); if (!strcmp( key, "Pixmap/X11" )) { D_DEBUG_AT( X11_Surfaces, " -> Pixmap/X11\n" ); alloc->type = X11_ALLOC_PIXMAP; } else if (!strcmp( key, "Window/X11" )) { D_DEBUG_AT( X11_Surfaces, " -> Window/X11\n" ); alloc->type = X11_ALLOC_WINDOW; } else { D_BUG( "unexpected key '%s'", key ); return DFB_BUG; } dfb_surface_calc_buffer_size( surface, 8, 8, &alloc->pitch, &allocation->size ); // alloc->depth = DefaultDepthOfScreen( x11->screenptr ); // alloc->visual = DefaultVisualOfScreen( x11->screenptr ); alloc->visual = x11->visuals[DFB_PIXELFORMAT_INDEX(buffer->format)]; alloc->depth = DFB_COLOR_BITS_PER_PIXEL( buffer->format ) + DFB_ALPHA_BITS_PER_PIXEL( buffer->format ); if (alloc->depth == DefaultDepthOfScreen( x11->screenptr )) alloc->visual = DefaultVisualOfScreen( x11->screenptr ); D_DEBUG_AT( X11_Surfaces, " -> visual %p (id %lu), depth %d\n", alloc->visual, alloc->visual->visualid, alloc->depth ); if (handle) { switch (alloc->type) { case X11_ALLOC_PIXMAP: XLockDisplay( x11->display ); alloc->xid = (unsigned long) handle; x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> pixmap 0x%08lx\n", (long) alloc->xid ); XUnlockDisplay( x11->display ); D_INFO( "X11/Windows: Import Pixmap 0x%08lx\n", alloc->xid ); break; case X11_ALLOC_WINDOW: { XLockDisplay( x11->display ); alloc->window = (unsigned long) handle; x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> window 0x%08lx\n", (long) alloc->window ); XCompositeRedirectWindow( x11->display, alloc->window, CompositeRedirectManual ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> redirected\n" ); alloc->xid = XCompositeNameWindowPixmap( x11->display, alloc->window ); // alloc->xid = alloc->window; x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> pixmap 0x%08lx\n", (long) alloc->xid ); XUnmapWindow( x11->display, alloc->window ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> unmapped\n" ); XUnlockDisplay( x11->display ); D_INFO( "X11/Windows: Import Window 0x%08lx with Pixmap handle 0x%08lx\n", alloc->window, alloc->xid ); break; } default: D_BUG( "unexpected allocation type %d\n", alloc->type ); return DFB_BUG; } } else { // alloc->type = X11_ALLOC_PIXMAP; switch (alloc->type) { case X11_ALLOC_PIXMAP: XLockDisplay( x11->display ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> creating pixmap...\n" ); alloc->xid = XCreatePixmap( x11->display, DefaultRootWindow(x11->display), allocation->config.size.w, allocation->config.size.h, alloc->depth ); x11->Sync( x11 ); XSync( x11->display, False ); D_DEBUG_AT( X11_Surfaces, " -> pixmap 0x%08lx\n", (long) alloc->xid ); XUnlockDisplay( x11->display ); D_INFO( "X11/Windows: New Pixmap 0x%08lx\n", alloc->xid ); alloc->created = true; break; case X11_ALLOC_WINDOW: { Window w = (Window) (long) buffer->surface->data; XSetWindowAttributes attr; attr.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask | KeyReleaseMask | ExposureMask | StructureNotifyMask; attr.background_pixmap = 0; XLockDisplay( x11->display ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> creating window...\n" ); alloc->window = w?:XCreateWindow( x11->display, DefaultRootWindow(x11->display), 600, 200, allocation->config.size.w, allocation->config.size.h, 0, alloc->depth, InputOutput, alloc->visual, CWEventMask, &attr ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> window 0x%08lx\n", (long) alloc->window ); buffer->surface->data = (void*) (long) alloc->window; XMapRaised( x11->display, alloc->window ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> raised\n" ); XCompositeRedirectWindow( x11->display, alloc->window, CompositeRedirectManual ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> redirected\n" ); alloc->xid = XCompositeNameWindowPixmap( x11->display, alloc->window ); // alloc->xid = alloc->window; x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> pixmap 0x%08lx\n", (long) alloc->xid ); XUnmapWindow( x11->display, alloc->window ); x11->Sync( x11 ); D_DEBUG_AT( X11_Surfaces, " -> unmapped\n" ); XUnlockDisplay( x11->display ); D_INFO( "X11/Windows: New Window 0x%08lx with Pixmap handle 0x%08lx\n", alloc->window, alloc->xid ); alloc->created = !w; break; } default: D_BUG( "unexpected allocation type %d\n", alloc->type ); return DFB_BUG; } } alloc->gc = XCreateGC( x11->display, alloc->xid, 0, NULL ); allocation->offset = alloc->type; return DFB_OK; }
ClientWin * clientwin_create(MainWin *mw, Window client) { session_t *ps = mw->ps; ClientWin *cw = allocchk(malloc(sizeof(ClientWin))); { static const ClientWin CLIENTWT_DEF = CLIENTWT_INIT; memcpy(cw, &CLIENTWT_DEF, sizeof(ClientWin)); } XWindowAttributes attr; cw->mainwin = mw; cw->wid_client = client; if (ps->o.includeFrame) cw->src.window = wm_find_frame(ps, client); if (!cw->src.window) cw->src.window = client; cw->mini.format = mw->format; { XSetWindowAttributes sattr = { .border_pixel = 0, .background_pixel = 0, .colormap = mw->colormap, .event_mask = ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ExposureMask | FocusChangeMask, .override_redirect = ps->o.lazyTrans, }; cw->mini.window = XCreateWindow(ps->dpy, (ps->o.lazyTrans ? ps->root : mw->window), 0, 0, 1, 1, 0, mw->depth, InputOutput, mw->visual, CWColormap | CWBackPixel | CWBorderPixel | CWEventMask | CWOverrideRedirect, &sattr); } if (!cw->mini.window) goto clientwin_create_err; { static const char *PREFIX = "mini window of "; const int len = strlen(PREFIX) + 20; char *str = allocchk(malloc(len)); snprintf(str, len, "%s%#010lx", PREFIX, cw->src.window); wm_wid_set_info(cw->mainwin->ps, cw->mini.window, str, None); free(str); } // Listen to events on the window. We don't want to miss any changes so // this is to be done as early as possible XSelectInput(cw->mainwin->ps->dpy, cw->src.window, SubstructureNotifyMask | StructureNotifyMask); XGetWindowAttributes(ps->dpy, client, &attr); if (IsViewable != attr.map_state) goto clientwin_create_err; clientwin_update(cw); // Get window pixmap if (ps->o.useNameWindowPixmap) { XCompositeRedirectWindow(ps->dpy, cw->src.window, CompositeRedirectAutomatic); cw->redirected = true; cw->cpixmap = XCompositeNameWindowPixmap(ps->dpy, cw->src.window); } // Create window picture { Drawable draw = cw->cpixmap; if (!draw) draw = cw->src.window; XRenderPictureAttributes pa = { .subwindow_mode = IncludeInferiors }; cw->origin = XRenderCreatePicture(cw->mainwin->ps->dpy, draw, cw->src.format, CPSubwindowMode, &pa); } if (!cw->origin) goto clientwin_create_err; XRenderSetPictureFilter(cw->mainwin->ps->dpy, cw->origin, FilterBest, 0, 0); return cw; clientwin_create_err: if (cw) clientwin_destroy(cw, False); return NULL; } void clientwin_update(ClientWin *cw) { Window tmpwin; XWindowAttributes wattr; XGetWindowAttributes(cw->mainwin->ps->dpy, cw->src.window, &wattr); XTranslateCoordinates(cw->mainwin->ps->dpy, cw->src.window, wattr.root, -wattr.border_width, -wattr.border_width, &cw->src.x, &cw->src.y, &tmpwin); cw->src.width = wattr.width; cw->src.height = wattr.height; cw->src.format = XRenderFindVisualFormat(cw->mainwin->ps->dpy, wattr.visual); cw->mini.x = cw->mini.y = 0; cw->mini.width = cw->mini.height = 1; }