📄 transparent.c
字号:
# ifdef HAVE_MENUBAR if (None != r->menuBar.win && r->Options & Opt_transparent_menubar) XSetWindowBackgroundPixmap (r->Xdisplay, r->menuBar.win, ParentRelative);# endif if (r->Options & Opt_transparent_tabbar) XSetWindowBackgroundPixmap (r->Xdisplay, r->tabBar.win, ParentRelative); XSelectInput(r->Xdisplay, XROOT, PropertyChangeMask); rxvt_check_our_parents (r); } /* Clear all windows */ XClearWindow (r->Xdisplay, r->TermWin.parent);# ifdef HAVE_SCROLLBARS rxvt_scrollbar_update (r, 0);# endif# ifdef HAVE_MENUBAR rxvt_menubar_expose (r);# endif rxvt_tabbar_expose (r, NULL); rxvt_scr_clear (r, ATAB(r)); rxvt_scr_touch (r, ATAB(r), True);}/* refreshRootBGVars(r) {{{2 * * Refresh our information about the root pixmap and it's geometry etc. This * should be called every time the desktop changes. *//* EXTPROTO */voidrefreshRootBGVars(rxvt_t *r ){ unsigned long nitems, bytes_after; Atom atype; int aformat; unsigned char *prop = NULL; r->h->allowedxerror = 1; r->h->xerror_return = Success; /* Get new root pixmap ID in h->rootPixmap*/ if ( r->h->xa[XA_XROOTPMAPID] != None && XGetWindowProperty( r->Xdisplay, XROOT, r->h->xa[XA_XROOTPMAPID], 0L, 1L, False, XA_PIXMAP, &atype, &aformat, &nitems, &bytes_after, &prop) == Success && prop != NULL ) { int u_rootx, u_rooty; /* u_ variables are unused */ unsigned u_bw, u_depth; Window u_cr; r->h->rootPixmap = *( (Pixmap *) prop ); r->h->bgGrabbed = False; XFree( prop); /* Get root pixmap geometry */ XGetGeometry( r->Xdisplay, r->h->rootPixmap, &u_cr, &u_rootx, &u_rooty, &r->h->rpWidth, &r->h->rpHeight, &u_bw, &u_depth); } else /* Failed. */ r->h->rootPixmap = None; r->h->allowedxerror = 0; if( r->h->xerror_return != Success ) /* Set by xerror handler */ r->h->rootPixmap = None; DBG_MSG( 1, (stderr, "Got %snull root pixmap %lx\n", r->h->rootPixmap == None ? "" : "non-", r->h->rootPixmap));}/* {{{2 rxvt_check_our_parents(r) * * Check our parents are still who we think they are. Do transparency updates if * required. *//* EXTPROTO */intrxvt_check_our_parents(rxvt_t *r){ int have_changed = 0, rootdepth; XWindowAttributes wattr, wrootattr; Window u_cr; /* * We dont' really have to check our parents if we're not transparent :) */ if (!(r->Options & Opt_transparent)) return have_changed; DBG_MSG(2, (stderr, "rxvt_check_our_parent ()\n")); /* * Don't try transparency if window depth is not the same as the root depth. */ XGetWindowAttributes(r->Xdisplay, XROOT, &wrootattr); rootdepth = wrootattr.depth; XGetWindowAttributes(r->Xdisplay, r->TermWin.parent, &wattr); if (rootdepth != wattr.depth ) { /* * Oops. We can't be transparent (or pixmap_transparent). */ assert (-1 != LTAB(r)); /* should't happen */ DBG_MSG( 1, (stderr, "Bad depth, transparency failed: (%u, %u)\n", rootdepth, wattr.depth)); rxvt_print_error( "Root window has different depth. Disabling transparency"); r->h->am_pixmap_trans = 0; r->Options &= ~( Opt_forceTransparent | Opt_transparent ); return tempDisableTransparent( r ); } /* * r->szHint should contain the correct location of this window if we got * here from a configure notify event. If we got here from reparent_notify, * then we need to set it ourselves to offset WM decorations */ XTranslateCoordinates( r->Xdisplay, r->TermWin.parent, XROOT, 0, 0, &r->szHint.x, &r->szHint.y, &u_cr); /* * Don't try refreshing our background if we're completely off screen. */ if ( r->szHint.x + r->szHint.width <= 0 || r->szHint.x >= (int) wrootattr.width || r->szHint.y + r->szHint.height <= 0 || r->szHint.y >= (int) wrootattr.height ) return 0; XSync(r->Xdisplay, False); r->h->allowedxerror = 1; r->h->xerror_return = Success; /* * Use "do" instead of "if" so we can break out if transparency updates * don't need to be performed. */ do /* while( 0 ) */ { /* * Copy XROOT pixmap transparency */ int retvt = 0; if( r->h->rootPixmap == None ) { have_changed = tempDisableTransparent( r); break; } retvt = resetParentPixmap( r, wrootattr.width, wrootattr.height, wrootattr.depth); if (retvt ) { /* All good. */ r->h->bgGrabbed = True; r->h->prevPos.x = r->szHint.x; r->h->prevPos.y = r->szHint.y; r->h->prevPos.width = r->szHint.width; r->h->prevPos.height = r->szHint.height; have_changed = 1; r->h->am_transparent = 1; r->h->am_pixmap_trans = 0; expose_transparent_subwin( r ); DBG_MSG( 1, ( stderr, "Enabled XROOT pseudo-transparency\n")); } else have_changed = tempDisableTransparent( r); } while( 0 ); /* * Disable transparency if something went wrong above. */ r->h->allowedxerror = 0; if( r->h->xerror_return != Success && r->h->am_transparent ) /* Only call if we're still transparent (otherwise we might call * tempDisableTransparent twice). */ have_changed = tempDisableTransparent( r ); /* * 2006-01-07 gi1242: This code doesn't work too well. The problem is that * if the user sets the desktop with say xsetroot, and we recieve an expose * event, then we only refresh part of our window. This causes really ugly * effects. */ if( !r->h->am_transparent && (r->Options & Opt_forceTransparent) ) { /* * Try "transparent transparency" legacy code. */ Window root, oldp, *list; unsigned int i, n; /* * Make the frame window set by the window manager that have the root * background. Some window managers put multiple nested frame windows for * each client, so we have to take care about that. */ DBG_MSG(1,(stderr, "Transparent Seeking to %08lx\n", XROOT)); for (i = 1; i < PARENT_NUMBER; i++) { /* * Check if any of our "parents" have changed. */ oldp = r->TermWin.parenttree[i]; XQueryTree(r->Xdisplay, r->TermWin.parenttree[i - 1], &root, &r->TermWin.parenttree[i], &list, &n); XFree(list); DBG_MSG( 1, (stderr, "Transparent Parent[%d] = %08lx\n", i, r->TermWin.parenttree[i] ) ); if (r->TermWin.parenttree[i] == XROOT) { if (oldp != None) have_changed = 1; break; } if (oldp != r->TermWin.parenttree[i]) have_changed = 1; } n = 0; /* * Now set background of all windows in this tree to ParentRelative. */ for (; n < (unsigned int)i; n++) { /* * Make sure we don't have any input only (or different depth) * windows. */ XGetWindowAttributes(r->Xdisplay, r->TermWin.parenttree[n], &wattr); DBG_MSG(1, (stderr, "Transparent Checking Parent[%d]: %s\n", n, (wattr.depth == rootdepth && wattr.class != InputOnly) ? "OK" : "FAIL")); if (wattr.depth != rootdepth || wattr.class == InputOnly) { n = PARENT_NUMBER + 1; break; } } if (n > PARENT_NUMBER) { /* * Bummer. We got an inputonly (or bad depth) window. Fail. */ DBG_MSG(1,(stderr, "Transparent Turning off\n")); if( r->h->am_pixmap_trans ) { r->h->am_pixmap_trans = 0; r->h->want_full_refresh = 1; have_changed = 1; XSetWindowBackground(r->Xdisplay, r->TermWin.parent, r->h->global_bg); expose_transparent_subwin( r ); } } else { /* wait (an arbitrary period) for the WM to do its thing * needed for fvwm2.2.2 (and before?). */#if 0# ifdef HAVE_NANOSLEEP struct timespec rqt; rqt.tv_sec = 1; rqt.tv_nsec = 0; nanosleep(&rqt, NULL);# else sleep(1); # endif#endif DBG_MSG(1,(stderr, "Transparent Turning on (%d parents). Geometry %ux%u+%d+%d\n", i - 1, r->szHint.width, r->szHint.height, r->szHint.x, r->szHint.y)); for (n = 0; n < i; n ++) XSetWindowBackgroundPixmap(r->Xdisplay, r->TermWin.parenttree[n], ParentRelative); r->h->am_pixmap_trans = 1; have_changed = 1; expose_transparent_subwin( r ); } /* * Set the tail portion of our tree to None for future calls */ for (; i < PARENT_NUMBER; i++) r->TermWin.parenttree[i] = None; } DBG_MSG( 1, (stderr, "am_transparent: %hhu am_pixmap_trans: %hhu have_changed %d\n", r->h->am_transparent, r->h->am_pixmap_trans, have_changed)); return have_changed;}/* {{{2 Obsolete stuff */#if 0/* INTPROTO */static XImage*get_parent_ximage (rxvt_t* r, unsigned int rootw, unsigned int rooth, unsigned int depth, int* nx, int* ny){ int sx = r->szHint.x, sy = r->szHint.y; unsigned int nw = r->szHint.width, nh = r->szHint.height; /* * On ConfigureNotify events, r->szHint is updated to the correct position * of the window, so we can safely use values in it (without having to call * XTranslateCoordinates). */#if 0 Window cr; XTranslateCoordinates(r->Xdisplay, r->TermWin.parent, XROOT, 0, 0, &sx, &sy, &cr);#endif#if DEBUG_LEVEL if( sx + nw <= 0 || sx >= (int) rootw || sy + nh <= 0 || sy >= (int) rooth) { DBG_MSG( 1, (stderr, "Possible error: grabbing offscreen (%d, %d, %u, %u)\n", sx, sy, nw, nh)); }#endif *nx = *ny = 0; if (sx < 0) { nw += sx; *nx = -sx; sx = 0; } if (sy < 0) { nh += sy; *ny = -sy; sy = 0; } MIN_IT(nw, (unsigned int) (rootw - sx)); MIN_IT(nh, (unsigned int) (rooth - sy)); DBG_MSG(1, (stderr, "XGetImage (%d, %d, %d, %d)\n", sx, sy, nw, nh)); if( r->h->rpWidth < rootw || r->h->rpHeight < rooth ) { /* * Must tile the root background on the window. */ XImage *image; Pixmap tiledPmap; GC gc; XGCValues values; values.ts_x_origin = -sx; values.ts_y_origin = -sy; values.fill_style = FillTiled; values.tile = r->h->rootPixmap; gc = XCreateGC( r->Xdisplay, r->TermWin.parent, GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin | GCTile, &values); tiledPmap = XCreatePixmap( r->Xdisplay, r->TermWin.parent, nw, nh, depth); XFillRectangle( r->Xdisplay, tiledPmap, gc, 0, 0, nw, nh); image = XGetImage( r->Xdisplay, tiledPmap, 0, 0, nw, nh, AllPlanes, ZPixmap); XFreePixmap( r->Xdisplay, tiledPmap); XFreeGC( r->Xdisplay, gc); return image; } else return (XGetImage(r->Xdisplay, r->h->rootPixmap, sx, sy, nw, nh, AllPlanes, ZPixmap));}/* INTPROTO */static intreset_parent_pixmap (rxvt_t* r, XImage* image, int nx, int ny){ Pixmap pixmap; GC gc;#ifdef TINTING_SUPPORT if (ISSET_PIXCOLOR (r->h, Color_tint) && r->h->rs[Rs_shade]) { XColor xcol; xcol.pixel = r->PixColors[Color_tint]; XQueryColor (r->Xdisplay, XCMAP, &xcol); shade_ximage (r, image, r->TermWin.shade, xcol.red, xcol.green, xcol.blue); }#endif pixmap = XCreatePixmap(r->Xdisplay, r->TermWin.parent, r->szHint.width, r->szHint.height, (unsigned int) image->depth); if (None == pixmap) return 0; /* XXX: Unnecessary XCreateGC */ gc = XCreateGC (r->Xdisplay, r->TermWin.parent, 0UL, 0); if (None != gc) { XPutImage(r->Xdisplay, pixmap, gc, image, 0, 0, /* src x and y */ nx, ny, /* dst x and y */ (unsigned int) image->width, (unsigned int) image->height); XFreeGC(r->Xdisplay, gc); } DBG_MSG(2, (stderr, "reset background image for parent\n")); /* Reset background of TermWin!!! */ XSetWindowBackgroundPixmap (r->Xdisplay, r->TermWin.parent, pixmap); /* * If we just became transparent, then make all child terminals transparent. */ if( !r->h->am_transparent && !r->h->am_pixmap_trans ) { int i; for (i = 0; i <= LTAB(r); i ++) { XSetWindowBackgroundPixmap (r->Xdisplay, PVTS(r, i)->vt, ParentRelative); } } /* * pixmap hogs up a few MB of space depending on how large your screen is. * After we called XSetWindowBackgroundPixmap, we no longer need this. */ XFreePixmap( r->Xdisplay, pixmap); /* * Caller must set xerror_return before and after calling this function. */ return r->h->xerror_return == Success;}#endif /*}}}2*/#endif /* TRANSPARENT *//* {{{1 Background image + Transparent functions */#if defined(BACKGROUND_IMAGE) || defined(TRANSPARENT)/* {{{2 rxvt_refresh_bg_image( r, page, imediate) *//* EXTPROTO */voidrxvt_refresh_bg_image (rxvt_t* r, int page, Bool imediate){ DBG_MSG( 1, (stderr, "rxvt_refresh_bg_image\n"));# ifdef TRANSPARENT if (r->Options & Opt_transparent) { if( imediate || !r->h->bgRefreshInterval ) { /* reset background NOW */ rxvt_check_our_parents (r); rxvt_scr_clear (r, page); rxvt_scr_touch (r, page, imediate); } else { /* Generate a timeout to refresh the bg image. TODO lastCNotify * should be called something else */ gettimeofday( &r->h->lastCNotify, NULL); r->h->bgGrabbed = False; /* So timeout will force refresh */ } } else# endif /* TRANSPARENT */ {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -