static void clonePreparePaintScreen(CompScreen * s, int msSinceLastPaint) { int i; CLONE_SCREEN(s); if (cs->grab) { if (cs->grabIndex) { cs->offset -= msSinceLastPaint * 0.005f; if (cs->offset < 0.0f) cs->offset = 0.0f; } else { cs->offset += msSinceLastPaint * 0.005f; if (cs->offset >= 1.0f) cs->offset = 1.0f; } } UNWRAP(cs, s, preparePaintScreen); (*s->preparePaintScreen) (s, msSinceLastPaint); WRAP(cs, s, preparePaintScreen, clonePreparePaintScreen); for (i = 0; i < cs->nClone; i++) { CompOutput *src = &s->outputDev[cs->clone[i].src]; CompOutput *dst = &s->outputDev[cs->clone[i].dst]; int dx, dy; dx = dst->region.extents.x1 - src->region.extents.x1; dy = dst->region.extents.y1 - src->region.extents.y1; if (s->damageMask & COMP_SCREEN_DAMAGE_REGION_MASK) { if (src->width != dst->width || src->height != dst->height) { XSubtractRegion(&dst->region, &emptyRegion, cs->clone[i].region); XUnionRegion(s->damage, cs->clone[i].region, s->damage); XSubtractRegion(&src->region, &emptyRegion, cs->clone[i].region); } else { XSubtractRegion(s->damage, &dst->region, cs->clone[i].region); XOffsetRegion(cs->clone[i].region, dx, dy); XUnionRegion(s->damage, cs->clone[i].region, s->damage); XSubtractRegion(s->damage, &src->region, cs->clone[i].region); XOffsetRegion(cs->clone[i].region, -dx, -dy); } } else { XSubtractRegion(&src->region, &emptyRegion, cs->clone[i].region); } } }
static void minSetShade (CompWindow *w, int shade) { REGION rect; int h = w->attrib.height + w->attrib.border_width * 2; MIN_WINDOW (w); EMPTY_REGION (w->region); rect.rects = &rect.extents; rect.numRects = rect.size = 1; w->height = shade; rect.extents.x1 = 0; rect.extents.y1 = h - shade; rect.extents.x2 = w->width; rect.extents.y2 = h; XIntersectRegion (mw->region, &rect, w->region); XOffsetRegion (w->region, w->attrib.x, w->attrib.y - (h - shade)); w->matrix = w->texture->matrix; w->matrix.x0 -= (w->attrib.x * w->matrix.xx); w->matrix.y0 -= ((w->attrib.y - (h - shade)) * w->matrix.yy); (*w->screen->windowResizeNotify) (w, 0, 0, 0, 0); }
Bool apc_region_combine( Handle self, Handle other_region, int rgnop) { PRegionSysData r2; int d; Bool ok = true; r2 = GET_REGION(other_region); if ( rgnop == rgnopCopy ) { if ( REGION ) XDestroyRegion( REGION ); REGION = XCreateRegion(); XUnionRegion( REGION, r2->region, REGION); HEIGHT = r2-> height; return true; } d = HEIGHT - r2-> height; if ( d > 0 ) XOffsetRegion( r2-> region, 0, d); else XOffsetRegion( REGION, 0, -d); switch (rgnop) { case rgnopIntersect: XIntersectRegion( REGION, r2->region, REGION); break; case rgnopUnion: XUnionRegion( REGION, r2->region, REGION); break; case rgnopXor: XXorRegion( REGION, r2->region, REGION); break; case rgnopDiff: XSubtractRegion( REGION, r2->region, REGION); break; default: ok = false; } if ( d > 0 ) XOffsetRegion( r2-> region, 0, -d); else HEIGHT = r2-> height; return ok; }
// Offset region by dx,dy FXRegion& FXRegion::offset(FXint dx,FXint dy){ #ifdef WIN32 OffsetRgn((HRGN)region,dx,dy); #else XOffsetRegion((Region)region,dx,dy); #endif return *this; }
Bool apc_gp_set_region( Handle self, Handle rgn) { DEFXX; Region region; PRegionSysData r; if ( PObject( self)-> options. optInDrawInfo) return false; if ( !XF_IN_PAINT(XX)) return false; if (rgn == nilHandle) { Rect r; r. left = 0; r. bottom = 0; r. right = XX-> size. x - 1; r. top = XX-> size. y - 1; return apc_gp_set_clip_rect( self, r); } r = GET_REGION(rgn); XClipBox( r-> region, &XX-> clip_rect); XX-> clip_rect. y += XX-> size. y - r-> height; XX-> clip_mask_extent. x = XX-> clip_rect. width; XX-> clip_mask_extent. y = XX-> clip_rect. height; if ( XX-> clip_rect. width == 0 || XX-> clip_rect. height == 0) { Rect r; r. left = -1; r. bottom = -1; r. right = -1; r. top = -1; return apc_gp_set_clip_rect( self, r); } region = XCreateRegion(); XUnionRegion( region, r-> region, region); /* offset region if drawable is buffered */ XOffsetRegion( region, XX-> btransform. x, XX-> size.y - r-> height - XX-> btransform. y); /* otherwise ( and only otherwise ), and if there's a X11 clipping, intersect the region with it. X11 clipping must not mix with the buffer clipping */ if (( !XX-> udrawable || XX-> udrawable == XX-> gdrawable) && XX-> paint_region) XIntersectRegion( region, XX-> paint_region, region); XSetRegion( DISP, XX-> gc, region); if ( XX-> flags. kill_current_region) XDestroyRegion( XX-> current_region); XX-> flags. kill_current_region = 1; XX-> current_region = region; XX-> flags. xft_clip = 0; #ifdef USE_XFT if ( XX-> xft_drawable) prima_xft_update_region( self); #endif #ifdef HAVE_X11_EXTENSIONS_XRENDER_H if ( XX-> argb_picture ) XRenderSetPictureClipRegion(DISP, XX->argb_picture, region); #endif return true; }
bool wxRegion::DoOffset( wxCoord x, wxCoord y ) { wxCHECK_MSG( m_refData, false, wxS("invalid region") ); AllocExclusive(); XOffsetRegion( M_REGIONDATA->m_region, x, y ); return true; }
static PyObject * region_OffsetRegion(PaxRegionObject *self, PyObject *args) { int dx, dy; if (!PyArg_ParseTuple(args, "ii", &dx, &dy)) return NULL; XOffsetRegion(self->region, dx, dy); Py_INCREF(Py_None); return Py_None; }
EAPI void ecore_x_xregion_translate(Ecore_X_XRegion *region, int x, int y) { LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!region) return; /* return value not used */ XOffsetRegion((Region)region, x, y); } /* ecore_x_xregion_translate */
/* lpStruct - pointer to POINT */ DWORD DrvRegionsOffSetRegion(LPARAM dwParm1, LPARAM dwParm2, LPVOID lpStruct) { LPPOINT lppt; if (!(lppt = (LPPOINT)lpStruct)) return (DWORD)ERROR; XOffsetRegion((Region)dwParm1, lppt->x, lppt->y); return (DWORD)COMPLEXREGION; }
bool wxRegion::DoOffset( wxCoord x, wxCoord y ) { if (!m_refData) return false; AllocExclusive(); XOffsetRegion( M_REGIONDATA->m_region, x, y ); return true; }
bool wxRegion::Offset( wxCoord x, wxCoord y ) { #if 0 if (!m_refData) return FALSE; AllocExclusive(); XOffsetRegion( M_REGIONDATA->m_region, x, y ); #endif return TRUE; }
void X11Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc, int ySrc, int xDest, int yDest, int width, int height ) { const X11Graphics& rGraph = (X11Graphics&)rGraphics; // check and adapt to source if needed if( !checkBoundaries( 0, 0, rGraph.getWidth(), rGraph.getHeight(), xSrc, ySrc, width, height ) ) { msg_Err( getIntf(), "nothing to draw from graphics source" ); return; } // check destination if( !checkBoundaries( 0, 0, m_width, m_height, xDest, yDest, width, height ) ) { msg_Err( getIntf(), "out of reach destination! pls, debug your skin" ); return; } // Source drawable Drawable src = rGraph.getDrawable(); // Create the mask for transparency Region voidMask = XCreateRegion(); XRectangle rect; rect.x = xSrc; rect.y = ySrc; rect.width = width; rect.height = height; Region clipMask = XCreateRegion(); XUnionRectWithRegion( &rect, voidMask, clipMask ); Region mask = XCreateRegion(); XIntersectRegion( rGraph.getMask(), clipMask, mask ); XDestroyRegion( clipMask ); XDestroyRegion( voidMask ); XOffsetRegion( mask, xDest - xSrc, yDest - ySrc ); // Copy the pixmap XSetRegion( XDISPLAY, m_gc, mask ); XCopyArea( XDISPLAY, src, m_pixmap, m_gc, xSrc, ySrc, width, height, xDest, yDest ); // Add the source mask to the mask of the graphics Region newMask = XCreateRegion(); XUnionRegion( m_mask, mask, newMask ); XDestroyRegion( mask ); XDestroyRegion( m_mask ); m_mask = newMask; }
/* * Kreslenà */ static void expose(XExposeEvent *event) { Region region, region1, region2; XRectangle rect; if(event->count > 0) return; /* Kreslit jen po poslednà události v øadì */ XDrawArc(display, topwin, my_gc, 20, 20, topwin_w - 40, topwin_h - 40, 0, 360 * 64); region = XCreateRegion(); region1 = XCreateRegion(); region2 = XCreateRegion(); rect.x = rect.y = 0; rect.width = 100; rect.height = topwin_w - 60; XUnionRectWithRegion(&rect, region, region1); rect.width = 20; rect.height = 10; XUnionRectWithRegion(&rect, region2, region); XOffsetRegion(region, 50, 100); XSubtractRegion(region1, region, region2); XDestroyRegion(region); region = XCreateRegion(); rect.width = 100; rect.height = 30; XUnionRectWithRegion(&rect, region, region1); XOffsetRegion(region1, (int)topwin_w - 120, -30 + ((int)topwin_h - 40) / 2); XUnionRegion(region1, region2, region); XSetRegion(display, my_gc, region); XDestroyRegion(region); XDestroyRegion(region1); XDestroyRegion(region2); XSetClipOrigin(display, my_gc, 20, 20); XFillArc(display, topwin, my_gc, 20, 20, topwin_w - 40, topwin_h - 40, 0, 360 * 64); XSetClipMask(display, my_gc, None); /* Zru¹it oøezávánà */ }
void X11Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc, int ySrc, int xDest, int yDest, int width, int height ) { if( width == -1 ) { width = rGraphics.getWidth(); } if( height == -1 ) { height = rGraphics.getHeight(); } // Source drawable Drawable src = ((X11Graphics&)rGraphics).getDrawable(); // Create the mask for transparency Region voidMask = XCreateRegion(); XRectangle rect; rect.x = xSrc; rect.y = ySrc; rect.width = width; rect.height = height; Region clipMask = XCreateRegion(); XUnionRectWithRegion( &rect, voidMask, clipMask ); Region mask = XCreateRegion(); XIntersectRegion( ((X11Graphics&)rGraphics).getMask(), clipMask, mask ); XDestroyRegion( clipMask ); XDestroyRegion( voidMask ); XOffsetRegion( mask, xDest - xSrc, yDest - ySrc ); // Copy the pixmap XSetRegion( XDISPLAY, m_gc, mask ); XCopyArea( XDISPLAY, src, m_pixmap, m_gc, xSrc, ySrc, width, height, xDest, yDest ); // Add the source mask to the mask of the graphics Region newMask = XCreateRegion(); XUnionRegion( m_mask, mask, newMask ); XDestroyRegion( mask ); XDestroyRegion( m_mask ); m_mask = newMask; }
Bool apc_gp_set_clip_rect( Handle self, Rect clipRect) { DEFXX; Region region; XRectangle r; if ( !XF_IN_PAINT(XX)) return false; SORT( clipRect. left, clipRect. right); SORT( clipRect. bottom, clipRect. top); r. x = clipRect. left; r. y = REVERT( clipRect. top); r. width = clipRect. right - clipRect. left+1; r. height = clipRect. top - clipRect. bottom+1; XX-> clip_rect = r; XX-> clip_mask_extent. x = r. width; XX-> clip_mask_extent. y = r. height; region = XCreateRegion(); XUnionRectWithRegion( &r, region, region); if ( XX-> paint_region) XIntersectRegion( region, XX-> paint_region, region); if ( XX-> btransform. x != 0 || XX-> btransform. y != 0) { XOffsetRegion( region, XX-> btransform. x, -XX-> btransform. y); } XSetRegion( DISP, XX-> gc, region); if ( XX-> flags. kill_current_region) XDestroyRegion( XX-> current_region); XX-> flags. kill_current_region = 1; XX-> current_region = region; XX-> flags. xft_clip = 0; #ifdef USE_XFT if ( XX-> xft_drawable) prima_xft_update_region( self); #endif #ifdef HAVE_X11_EXTENSIONS_XRENDER_H if ( XX-> argb_picture ) XRenderSetPictureClipRegion(DISP, XX->argb_picture, region); #endif return true; }
Bool apc_gp_get_region( Handle self, Handle rgn) { DEFXX; GC gc; XGCValues gcv; int w, h; Pixmap pixmap; XImage * i; Image pi; Region rgn2; if ( !XF_IN_PAINT(XX)) return false; if ( !rgn) return XX-> clip_mask_extent. x != 0 && XX-> clip_mask_extent. y != 0; if ( XX-> clip_mask_extent. x == 0 || XX-> clip_mask_extent. y == 0) return false; w = XX-> clip_mask_extent. x; h = XX-> clip_mask_extent. y; pixmap = XCreatePixmap( DISP, guts.root, w, h, XF_LAYERED(XX) ? guts. argb_depth : ( XT_IS_BITMAP(XX) ? 1 : guts. depth ) ); XCHECKPOINT; gcv. graphics_exposures = false; gcv. fill_style = FillSolid; gcv. foreground = 0; gcv. clip_y_origin = -XX-> clip_rect. y + XX-> btransform. y; gcv. clip_x_origin = -XX-> clip_rect. x - XX-> btransform. x; XCHECKPOINT; gc = XCreateGC( DISP, pixmap, GCGraphicsExposures|GCFillStyle|GCForeground|GCClipXOrigin|GCClipYOrigin, &gcv); XFillRectangle( DISP, pixmap, gc, 0, 0, w, h); XSetForeground( DISP, gc, 1 ); XCopyGC( DISP, XX->gc, GCClipMask, gc); XFillRectangle( DISP, pixmap, gc, 0, 0, w, h); XFreeGC( DISP, gc); XCHECKPOINT; i = XGetImage( DISP, pixmap, 0, 0, w, h, 1, XYPixmap); XFreePixmap( DISP, pixmap); if ( !i ) { warn("Cannot query image"); return false; } img_fill_dummy( &pi, w, h, imBW | imGrayScale, NULL, NULL); if ( !( pi.data = malloc(pi.lineSize * h))) { XDestroyImage( i); warn("Not enough memory"); return false; } prima_copy_xybitmap( pi.data, (Byte*)i-> data, w, h, pi.lineSize, i-> bytes_per_line); XDestroyImage( i); rgn2 = prima_region_create((Handle) &pi); free(pi.data); if ( GET_REGION(rgn)-> region ) XDestroyRegion( GET_REGION(rgn)-> region ); if ( rgn2 ) { XOffsetRegion( rgn2, XX-> clip_rect.x, 0); GET_REGION(rgn)-> height = XX-> size.y - XX-> clip_rect.y; GET_REGION(rgn)-> region = rgn2; } else { GET_REGION(rgn)-> height = 0; GET_REGION(rgn)-> region = XCreateRegion(); } return true; }
void X11Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc, int ySrc, int xDest, int yDest, int width, int height, bool blend ) { // Get the bitmap size if necessary if( width == -1 ) { width = rBitmap.getWidth(); } else if( width > rBitmap.getWidth() ) { msg_Dbg( getIntf(), "bitmap width too small (%i)", rBitmap.getWidth() ); width = rBitmap.getWidth(); } if( height == -1 ) { height = rBitmap.getHeight(); } else if( height > rBitmap.getHeight() ) { msg_Dbg( getIntf(), "bitmap height too small (%i)", rBitmap.getHeight() ); height = rBitmap.getHeight(); } // Nothing to draw if width or height is null if( width == 0 || height == 0 ) { return; } // Safety check for debugging purpose if( xDest + width > m_width || yDest + height > m_height ) { msg_Dbg( getIntf(), "bitmap too large" ); return; } // Get a buffer on the image data uint8_t *pBmpData = rBitmap.getData(); if( pBmpData == NULL ) { // Nothing to draw return; } // Get the image from the pixmap XImage *pImage = XGetImage( XDISPLAY, m_pixmap, xDest, yDest, width, height, AllPlanes, ZPixmap ); if( pImage == NULL ) { msg_Dbg( getIntf(), "XGetImage returned NULL" ); return; } char *pData = pImage->data; // Get the padding of this image int pad = pImage->bitmap_pad >> 3; int shift = ( pad - ( (width * XPIXELSIZE) % pad ) ) % pad; // Mask for transparency Region mask = XCreateRegion(); // Get a pointer on the right X11Display::makePixel method X11Display::MakePixelFunc_t makePixelFunc = ( blend ? m_rDisplay.getBlendPixel() : m_rDisplay.getPutPixel() ); // Skip the first lines of the image pBmpData += 4 * ySrc * rBitmap.getWidth(); // Copy the bitmap on the image and compute the mask for( int y = 0; y < height; y++ ) { // Skip uninteresting bytes at the beginning of the line pBmpData += 4 * xSrc; // Flag to say whether the previous pixel on the line was visible bool wasVisible = false; // Beginning of the current visible segment on the line int visibleSegmentStart = 0; for( int x = 0; x < width; x++ ) { uint8_t b = *(pBmpData++); uint8_t g = *(pBmpData++); uint8_t r = *(pBmpData++); uint8_t a = *(pBmpData++); // Draw the pixel (m_rDisplay.*makePixelFunc)( (uint8_t*)pData, r, g, b, a ); pData += XPIXELSIZE; if( a > 0 ) { // Pixel is visible if( ! wasVisible ) { // Beginning of a visible segment visibleSegmentStart = x; } wasVisible = true; } else { // Pixel is transparent if( wasVisible ) { // End of a visible segment: add it to the mask addHSegmentInRegion( mask, visibleSegmentStart, x, y ); } wasVisible = false; } } if( wasVisible ) { // End of a visible segment: add it to the mask addHSegmentInRegion( mask, visibleSegmentStart, width, y ); } pData += shift; // Skip uninteresting bytes at the end of the line pBmpData += 4 * (rBitmap.getWidth() - width - xSrc); } // Apply the mask to the graphics context XOffsetRegion( mask, xDest, yDest ); XSetRegion( XDISPLAY, m_gc, mask ); // Copy the image on the pixmap XPutImage( XDISPLAY, m_pixmap, m_gc, pImage, 0, 0, xDest, yDest, width, height); XDestroyImage( pImage ); // Add the bitmap mask to the global graphics mask Region newMask = XCreateRegion(); XUnionRegion( mask, m_mask, newMask ); XDestroyRegion( m_mask ); m_mask = newMask; XDestroyRegion( mask ); }
void meta_draw_window_decoration (decor_t *d) { Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); cairo_surface_t *surface; Picture src; MetaButtonState button_states [META_BUTTON_TYPE_LAST]; MetaButtonLayout button_layout; MetaFrameGeometry fgeom; MetaFrameFlags flags; MetaFrameType frame_type; MetaTheme *theme; GtkStyleContext *context; cairo_t *cr; gint i; GdkRectangle clip; Region top_region = NULL; Region bottom_region = NULL; Region left_region = NULL; Region right_region = NULL; gdouble meta_active_opacity, meta_inactive_opacity; gboolean meta_active_shade_opacity, meta_inactive_shade_opacity; g_object_get (settings, "metacity-active-opacity", &meta_active_opacity, NULL); g_object_get (settings, "metacity-inactive-opacity", &meta_inactive_opacity, NULL); g_object_get (settings, "metacity-active-shade-opacity", &meta_active_shade_opacity, NULL); g_object_get (settings, "metacity-inactive-shade-opacity", &meta_inactive_shade_opacity, NULL); double alpha = (d->active) ? meta_active_opacity : meta_inactive_opacity; gboolean shade_alpha = (d->active) ? meta_active_shade_opacity : meta_inactive_shade_opacity; MetaFrameStyle *frame_style; GtkWidget *style_window; GdkRGBA bg_rgba; if (!d->surface || !d->picture) return; if (decoration_alpha == 1.0) alpha = 1.0; if (cairo_xlib_surface_get_depth (d->surface) == 32) { context = gtk_widget_get_style_context (d->frame->style_window_rgba); style_window = d->frame->style_window_rgba; } else { context = gtk_widget_get_style_context (d->frame->style_window_rgb); style_window = d->frame->style_window_rgb; } cr = cairo_create (d->buffer_surface ? d->buffer_surface : d->surface); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); theme = meta_theme_get_current (); frame_type = meta_frame_type_from_string (d->frame->type); if (frame_type == META_FRAME_TYPE_LAST) frame_type = META_FRAME_TYPE_NORMAL; meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, frame_type, &clip); if ((d->prop_xid || !d->buffer_surface) && !d->frame_window) draw_shadow_background (d, cr, d->shadow, d->context); for (i = 0; i < META_BUTTON_TYPE_LAST; ++i) button_states[i] = meta_button_state_for_button_type (d, i); frame_style = meta_theme_get_frame_style (theme, frame_type, flags); gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg_rgba); bg_rgba.alpha = 1.0; if (frame_style->window_background_color) { meta_color_spec_render (frame_style->window_background_color, gtk_widget_get_style_context (style_window), &bg_rgba); bg_rgba.alpha = frame_style->window_background_alpha / 255.0; } /* Draw something that will be almost invisible to user. This is hacky way * to fix invisible decorations. */ cairo_set_source_rgba (cr, 0, 0, 0, 0.01); cairo_rectangle (cr, 0, 0, 1, 1); cairo_fill (cr); /* ------------ */ cairo_destroy (cr); if (d->frame_window) surface = create_surface (clip.width, clip.height, d->frame->style_window_rgb); else surface = create_surface (clip.width, clip.height, d->frame->style_window_rgba); cr = cairo_create (surface); gdk_cairo_set_source_rgba (cr, &bg_rgba); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); src = XRenderCreatePicture (xdisplay, cairo_xlib_surface_get_drawable (surface), get_format_for_surface (d, surface), 0, NULL); cairo_paint (cr); meta_theme_draw_frame (theme, style_window, cr, frame_type, flags, clip.width - fgeom.left_width - fgeom.right_width, clip.height - fgeom.top_height - fgeom.bottom_height, d->layout, d->frame->text_height, &button_layout, button_states, d->icon_pixbuf, NULL); if (fgeom.top_height) { top_region = meta_get_top_border_region (&fgeom, clip.width); decor_blend_border_picture (xdisplay, d->context, src, 0, 0, d->picture, &d->border_layout, BORDER_TOP, top_region, alpha * 0xffff, shade_alpha, 0); } if (fgeom.bottom_height) { bottom_region = meta_get_bottom_border_region (&fgeom, clip.width); decor_blend_border_picture (xdisplay, d->context, src, 0, clip.height - fgeom.bottom_height, d->picture, &d->border_layout, BORDER_BOTTOM, bottom_region, alpha * 0xffff, shade_alpha, 0); } if (fgeom.left_width) { left_region = meta_get_left_border_region (&fgeom, clip.height); decor_blend_border_picture (xdisplay, d->context, src, 0, fgeom.top_height, d->picture, &d->border_layout, BORDER_LEFT, left_region, alpha * 0xffff, shade_alpha, 0); } if (fgeom.right_width) { right_region = meta_get_right_border_region (&fgeom, clip.height); decor_blend_border_picture (xdisplay, d->context, src, clip.width - fgeom.right_width, fgeom.top_height, d->picture, &d->border_layout, BORDER_RIGHT, right_region, alpha * 0xffff, shade_alpha, 0); } cairo_destroy (cr); cairo_surface_destroy (surface); XRenderFreePicture (xdisplay, src); copy_to_front_buffer (d); if (d->frame_window) { GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window); GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface (d->surface, 0, 0, d->width, d->height); gtk_image_set_from_pixbuf (GTK_IMAGE (d->decor_image), pixbuf); g_object_unref (pixbuf); gtk_window_resize (GTK_WINDOW (d->decor_window), d->width, d->height); gdk_window_move (gdk_frame_window, d->context->left_corner_space - 1, d->context->top_corner_space - 1); gdk_window_lower (gdk_frame_window); } if (d->prop_xid) { /* translate from frame to client window space */ if (top_region) XOffsetRegion (top_region, -fgeom.left_width, -fgeom.top_height); if (bottom_region) XOffsetRegion (bottom_region, -fgeom.left_width, 0); if (left_region) XOffsetRegion (left_region, -fgeom.left_width, 0); decor_update_meta_window_property (d, theme, flags, top_region, bottom_region, left_region, right_region); d->prop_xid = 0; } if (top_region) XDestroyRegion (top_region); if (bottom_region) XDestroyRegion (bottom_region); if (left_region) XDestroyRegion (left_region); if (right_region) XDestroyRegion (right_region); }
/* * groupHandleButtonReleaseEvent * */ static void groupHandleButtonReleaseEvent (CompScreen *s, XEvent *event) { GroupSelection *group; int vx, vy; Region newRegion; Bool inserted = FALSE; Bool wasInTabBar = FALSE; GROUP_SCREEN (s); if (event->xbutton.button != 1) return; if (!gs->draggedSlot) return; if (!gs->dragged) { groupChangeTab (gs->draggedSlot, RotateUncertain); gs->draggedSlot = NULL; if (gs->grabState == ScreenGrabTabDrag) groupGrabScreen (s, ScreenGrabNone); return; } GROUP_WINDOW (gs->draggedSlot->window); newRegion = XCreateRegion (); if (!newRegion) return; XUnionRegion (newRegion, gs->draggedSlot->region, newRegion); groupGetDrawOffsetForSlot (gs->draggedSlot, &vx, &vy); XOffsetRegion (newRegion, vx, vy); for (group = gs->groups; group; group = group->next) { Bool inTabBar; Region clip, buf; GroupTabBarSlot *slot; if (!group->tabBar || !HAS_TOP_WIN (group)) continue; /* create clipping region */ clip = groupGetClippingRegion (TOP_TAB (group)); if (!clip) continue; buf = XCreateRegion (); if (!buf) { XDestroyRegion (clip); continue; } XIntersectRegion (newRegion, group->tabBar->region, buf); XSubtractRegion (buf, clip, buf); XDestroyRegion (clip); inTabBar = !XEmptyRegion (buf); XDestroyRegion (buf); if (!inTabBar) continue; wasInTabBar = TRUE; for (slot = group->tabBar->slots; slot; slot = slot->next) { GroupTabBarSlot *tmpDraggedSlot; GroupSelection *tmpGroup; Region slotRegion, buf; XRectangle rect; Bool inSlot; if (slot == gs->draggedSlot) continue; slotRegion = XCreateRegion (); if (!slotRegion) continue; if (slot->prev && slot->prev != gs->draggedSlot) { rect.x = slot->prev->region->extents.x2; } else if (slot->prev && slot->prev == gs->draggedSlot && gs->draggedSlot->prev) { rect.x = gs->draggedSlot->prev->region->extents.x2; } else rect.x = group->tabBar->region->extents.x1; rect.y = slot->region->extents.y1; if (slot->next && slot->next != gs->draggedSlot) { rect.width = slot->next->region->extents.x1 - rect.x; } else if (slot->next && slot->next == gs->draggedSlot && gs->draggedSlot->next) { rect.width = gs->draggedSlot->next->region->extents.x1 - rect.x; } else rect.width = group->tabBar->region->extents.x2; rect.height = slot->region->extents.y2 - slot->region->extents.y1; XUnionRectWithRegion (&rect, slotRegion, slotRegion); buf = XCreateRegion (); if (!buf) continue; XIntersectRegion (newRegion, slotRegion, buf); inSlot = !XEmptyRegion (buf); XDestroyRegion (buf); XDestroyRegion (slotRegion); if (!inSlot) continue; tmpDraggedSlot = gs->draggedSlot; if (group != gw->group) { CompWindow *w = gs->draggedSlot->window; GroupSelection *tmpGroup = gw->group; int oldPosX = WIN_CENTER_X (w); int oldPosY = WIN_CENTER_Y (w); /* if the dragged window is not the top tab, move it onscreen */ if (tmpGroup->topTab && !IS_TOP_TAB (w, tmpGroup)) { CompWindow *tw = TOP_TAB (tmpGroup); oldPosX = WIN_CENTER_X (tw) + gw->mainTabOffset.x; oldPosY = WIN_CENTER_Y (tw) + gw->mainTabOffset.y; groupSetWindowVisibility (w, TRUE); } /* Change the group. */ groupDeleteGroupWindow (gs->draggedSlot->window); groupAddWindowToGroup (gs->draggedSlot->window, group, 0); /* we saved the original center position in oldPosX/Y before - now we should apply that to the new main tab offset */ if (HAS_TOP_WIN (group)) { CompWindow *tw = TOP_TAB (group); gw->mainTabOffset.x = oldPosX - WIN_CENTER_X (tw); gw->mainTabOffset.y = oldPosY - WIN_CENTER_Y (tw); } } else groupUnhookTabBarSlot (group->tabBar, gs->draggedSlot, TRUE); gs->draggedSlot = NULL; gs->dragged = FALSE; inserted = TRUE; if ((tmpDraggedSlot->region->extents.x1 + tmpDraggedSlot->region->extents.x2 + (2 * vx)) / 2 > (slot->region->extents.x1 + slot->region->extents.x2) / 2) { groupInsertTabBarSlotAfter (group->tabBar, tmpDraggedSlot, slot); } else groupInsertTabBarSlotBefore (group->tabBar, tmpDraggedSlot, slot); groupDamageTabBarRegion (group); /* Hide tab-bars. */ for (tmpGroup = gs->groups; tmpGroup; tmpGroup = tmpGroup->next) { if (group == tmpGroup) groupTabSetVisibility (tmpGroup, TRUE, 0); else groupTabSetVisibility (tmpGroup, FALSE, PERMANENT); } break; } if (inserted) break; } XDestroyRegion (newRegion); if (!inserted) { CompWindow *draggedSlotWindow = gs->draggedSlot->window; GroupSelection *tmpGroup; for (tmpGroup = gs->groups; tmpGroup; tmpGroup = tmpGroup->next) groupTabSetVisibility (tmpGroup, FALSE, PERMANENT); gs->draggedSlot = NULL; gs->dragged = FALSE; const BananaValue * option_dnd_ungroup_window = bananaGetOption (bananaIndex, "dnd_ungroup_window", s->screenNum); if (option_dnd_ungroup_window->b && !wasInTabBar) { groupRemoveWindowFromGroup (draggedSlotWindow); } else if (gw->group && gw->group->topTab) { groupRecalcTabBarPos (gw->group, (gw->group->tabBar->region->extents.x1 + gw->group->tabBar->region->extents.x2) / 2, gw->group->tabBar->region->extents.x1, gw->group->tabBar->region->extents.x2); } /* to remove the painted slot */ damageScreen (s); } if (gs->grabState == ScreenGrabTabDrag) groupGrabScreen (s, ScreenGrabNone); if (gs->dragHoverTimeoutHandle) { compRemoveTimeout (gs->dragHoverTimeoutHandle); gs->dragHoverTimeoutHandle = 0; } }
static void groupHandleMotionEvent (CompScreen *s, int xRoot, int yRoot) { GROUP_SCREEN (s); if (gs->grabState == ScreenGrabTabDrag) { int dx, dy; int vx, vy; REGION reg; Region draggedRegion = gs->draggedSlot->region; reg.rects = ®.extents; reg.numRects = 1; dx = xRoot - gs->prevX; dy = yRoot - gs->prevY; if (gs->dragged || abs (dx) > RADIUS || abs (dy) > RADIUS) { gs->prevX = xRoot; gs->prevY = yRoot; if (!gs->dragged) { GroupSelection *group; BoxRec *box; GROUP_WINDOW (gs->draggedSlot->window); gs->dragged = TRUE; for (group = gs->groups; group; group = group->next) groupTabSetVisibility (group, TRUE, PERMANENT); box = &gw->group->tabBar->region->extents; groupRecalcTabBarPos (gw->group, (box->x1 + box->x2) / 2, box->x1, box->x2); } groupGetDrawOffsetForSlot (gs->draggedSlot, &vx, &vy); reg.extents.x1 = draggedRegion->extents.x1 + vx; reg.extents.y1 = draggedRegion->extents.y1 + vy; reg.extents.x2 = draggedRegion->extents.x2 + vx; reg.extents.y2 = draggedRegion->extents.y2 + vy; damageScreenRegion (s, ®); XOffsetRegion (gs->draggedSlot->region, dx, dy); gs->draggedSlot->springX = (gs->draggedSlot->region->extents.x1 + gs->draggedSlot->region->extents.x2) / 2; reg.extents.x1 = draggedRegion->extents.x1 + vx; reg.extents.y1 = draggedRegion->extents.y1 + vy; reg.extents.x2 = draggedRegion->extents.x2 + vx; reg.extents.y2 = draggedRegion->extents.y2 + vy; damageScreenRegion (s, ®); } } else if (gs->grabState == ScreenGrabSelect) { groupDamageSelectionRect (s, xRoot, yRoot); } }
/* * groupWindowMoveNotify * */ void groupWindowMoveNotify (CompWindow *w, int dx, int dy, Bool immediate) { CompScreen *s = w->screen; Bool viewportChange; int i; GROUP_SCREEN (s); GROUP_DISPLAY (&display); GROUP_WINDOW (w); UNWRAP (gs, s, windowMoveNotify); (*s->windowMoveNotify)(w, dx, dy, immediate); WRAP (gs, s, windowMoveNotify, groupWindowMoveNotify); if (gw->glowQuads) groupComputeGlowQuads (w, &gs->glowTexture.matrix); if (!gw->group || gs->queued) return; /* FIXME: we need a reliable, 100% safe way to detect window moves caused by viewport changes here */ viewportChange = ((dx && !(dx % w->screen->width)) || (dy && !(dy % w->screen->height))); if (viewportChange && (gw->animateState & IS_ANIMATED)) { gw->destination.x += dx; gw->destination.y += dy; } if (gw->group->tabBar && IS_TOP_TAB (w, gw->group)) { GroupTabBarSlot *slot; GroupTabBar *bar = gw->group->tabBar; bar->rightSpringX += dx; bar->leftSpringX += dx; groupMoveTabBarRegion (gw->group, dx, dy, TRUE); for (slot = bar->slots; slot; slot = slot->next) { XOffsetRegion (slot->region, dx, dy); slot->springX += dx; } } const BananaValue * option_move_all = bananaGetOption (bananaIndex, "move_all", s->screenNum); if (!option_move_all->b || gd->ignoreMode || (gw->group->tabbingState != NoTabbing) || (gw->group->grabWindow != w->id) || !(gw->group->grabMask & CompWindowGrabMoveMask)) { return; } for (i = 0; i < gw->group->nWins; i++) { CompWindow *cw = gw->group->windows[i]; if (!cw) continue; if (cw->id == w->id) continue; GROUP_WINDOW (cw); if (cw->state & MAXIMIZE_STATE) { if (viewportChange) groupEnqueueMoveNotify (cw, -dx, -dy, immediate, TRUE); } else if (!viewportChange) { gw->needsPosSync = TRUE; groupEnqueueMoveNotify (cw, dx, dy, immediate, FALSE); } } }
Bool groupDamageWindowRect (CompWindow *w, Bool initial, BoxPtr rect) { Bool status; CompScreen *s = w->screen; GROUP_SCREEN (s); GROUP_WINDOW (w); UNWRAP (gs, s, damageWindowRect); status = (*s->damageWindowRect)(w, initial, rect); WRAP (gs, s, damageWindowRect, groupDamageWindowRect); if (initial) { const BananaValue * option_autotab_create = bananaGetOption (bananaIndex, "autotab_create", s->screenNum); if (option_autotab_create->b && groupIsGroupWindow (w)) { if (!gw->group && (gw->windowState == WindowNormal)) { /* First check if this window should be added to an * existing group */ GroupSelection *g = NULL; int i; for (i = 0; i <= gs->autotabCount - 1; i++) { if (matchEval (&gs->autotab[i], w)) { Bool foundGroup = FALSE; GroupSelection *tg; for (tg = gs->groups; tg; tg = tg->next) { int i; for (i = 0; i <= tg->nWins - 1; i++) { if (matchEval (&gs->autotab[i], tg->windows[i])) { foundGroup = TRUE; g = tg; break; } } if (foundGroup) break; } if (foundGroup) break; } } if (g) { groupAddWindowToGroup (w, g, 0); //groupTabGroup (w); } else { groupAddWindowToGroup (w, NULL, 0); //groupTabGroup (w); } } } if (gw->group) { if (gw->windowState == WindowMinimized) { const BananaValue * option_minimize_all = bananaGetOption (bananaIndex, "minimize_all", s->screenNum); if (option_minimize_all->b) groupMinimizeWindows (w, gw->group, FALSE); } else if (gw->windowState == WindowShaded) { const BananaValue * option_shade_all = bananaGetOption (bananaIndex, "shade_all", s->screenNum); if (option_shade_all->b) groupShadeWindows (w, gw->group, FALSE); } } gw->windowState = WindowNormal; } if (gw->resizeGeometry) { BoxRec box; groupGetStretchRectangle (w, &box, NULL, NULL); groupDamagePaintRectangle (s, &box); } if (gw->slot) { int vx, vy; Region reg; groupGetDrawOffsetForSlot (gw->slot, &vx, &vy); if (vx || vy) { reg = XCreateRegion (); XUnionRegion (reg, gw->slot->region, reg); XOffsetRegion (reg, vx, vy); } else reg = gw->slot->region; damageScreenRegion (s, reg); if (vx || vy) XDestroyRegion (reg); } return status; }
Bool apc_region_offset( Handle self, int dx, int dy) { XOffsetRegion(REGION, dx, -dy); return true; }
static Bool minDamageWindowRect (CompWindow *w, Bool initial, BoxPtr rect) { Bool status = FALSE; MIN_SCREEN (w->screen); MIN_WINDOW (w); if (mw->ignoreDamage) return TRUE; if (initial) { if (mw->state == IconicState) { mw->state = NormalState; if (!w->invisible && w->iconGeometrySet && matchEval (&ms->match, w)) { if (!mw->adjust) { mw->adjust = TRUE; ms->moreAdjust = TRUE; mw->tx = w->iconGeometry.x - w->serverX; mw->ty = w->iconGeometry.y - w->serverY; mw->xScale = (float) w->iconGeometry.width / w->width; mw->yScale = (float) w->iconGeometry.height / w->height; addWindowDamage (w); } } } else if (mw->region && mw->shade < w->height) { if (ms->shadeStep && !w->invisible) { XSubtractRegion (w->region, &emptyRegion, mw->region); XOffsetRegion (mw->region, -w->attrib.x, -w->attrib.y); /* bind pixmap here so we have something to unshade with */ if (!w->texture->pixmap && !w->bindFailed) bindWindow (w); ms->moreAdjust = TRUE; } else { mw->shade = MAXSHORT; } } mw->newState = NormalState; } else if (mw->adjust) { damageTransformedWindowRect (w, mw->xScale, mw->yScale, mw->tx, mw->ty, rect); status = TRUE; } UNWRAP (ms, w->screen, damageWindowRect); status |= (*w->screen->damageWindowRect) (w, initial, rect); WRAP (ms, w->screen, damageWindowRect, minDamageWindowRect); return status; }
static void minHandleEvent (XEvent *event) { CompWindow *w; MIN_DISPLAY (&display); switch (event->type) { case MapNotify: w = findWindowAtDisplay (event->xmap.window); if (w) { MIN_WINDOW (w); if (mw->adjust) mw->state = mw->newState; if (mw->region) w->height = 0; mw->ignoreDamage = TRUE; while (mw->unmapCnt) { unmapWindow (w); mw->unmapCnt--; } mw->ignoreDamage = FALSE; } break; case UnmapNotify: w = findWindowAtDisplay (event->xunmap.window); if (w) { MIN_SCREEN (w->screen); if (w->pendingUnmaps && onCurrentDesktop (w)) /* Normal -> Iconic */ { MIN_WINDOW (w); if (w->shaded) { if (!mw->region) mw->region = XCreateRegion (); if (mw->region && ms->shadeStep) { XSubtractRegion (w->region, &emptyRegion, mw->region); XOffsetRegion (mw->region, -w->attrib.x, w->attrib.height + w->attrib.border_width * 2 - w->height - w->attrib.y); mw->shade = w->height; mw->adjust = FALSE; ms->moreAdjust = TRUE; mw->unmapCnt++; w->unmapRefCnt++; addWindowDamage (w); } } else if (!w->invisible && matchEval (&ms->match, w)) { if (w->iconGeometrySet) { mw->newState = IconicState; mw->xScale = w->paint.xScale; mw->yScale = w->paint.yScale; mw->tx = w->attrib.x - w->serverX; mw->ty = w->attrib.y - w->serverY; if (mw->region) { XDestroyRegion (mw->region); mw->region = NULL; } mw->shade = MAXSHORT; mw->adjust = TRUE; ms->moreAdjust = TRUE; mw->unmapCnt++; w->unmapRefCnt++; addWindowDamage (w); } } } else /* X -> Withdrawn */ { MIN_WINDOW (w); if (mw->adjust) { mw->adjust = FALSE; mw->xScale = mw->yScale = 1.0f; mw->tx = mw->ty = 0.0f; mw->xVelocity = mw->yVelocity = 0.0f; mw->xScaleVelocity = mw->yScaleVelocity = 1.0f; mw->shade = MAXSHORT; if (mw->region) { XDestroyRegion (mw->region); mw->region = NULL; } } mw->state = NormalState; } } default: break; } UNWRAP (md, &display, handleEvent); (*display.handleEvent) (event); WRAP (md, &display, handleEvent, minHandleEvent); switch (event->type) { case MapRequest: w = findWindowAtDisplay (event->xmaprequest.window); if (w && w->hints && w->hints->initial_state == IconicState) { MIN_WINDOW (w); mw->newState = mw->state = IconicState; } break; default: break; } }
void CompRegion::translate (int dx, int dy) { priv->makeReal (); XOffsetRegion (handle (), dx, dy); }
/* This function currently always performs occlusion detection to minimize paint regions. OpenGL precision requirements are no good enough to guarantee that the results from using occlusion detection is the same as without. It's likely not possible to see any difference with most hardware but occlusion detection in the transformed screen case should be made optional for those who do see a difference. */ static void paintOutputRegion (CompScreen *screen, const CompTransform *transform, Region region, CompOutput *output, unsigned int mask) { static Region tmpRegion = NULL; CompWindow *w; CompCursor *c; int count, windowMask, odMask, i; CompWindow *fullscreenWindow = NULL; CompWalker walk; Bool status; Bool withOffset = FALSE; CompTransform vTransform; int offX, offY; Region clip = region; int dontcare; if (!tmpRegion) { tmpRegion = XCreateRegion (); if (!tmpRegion) return; } if (mask & PAINT_SCREEN_TRANSFORMED_MASK) { windowMask = PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK; count = 1; } else { windowMask = 0; count = 0; } XSubtractRegion (region, &emptyRegion, tmpRegion); (*screen->initWindowWalker) (screen, &walk); if (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK)) { /* detect occlusions */ for (w = (*walk.last) (screen); w; w = (*walk.prev) (w)) { if (w->destroyed) continue; if (!w->shaded) { if (w->attrib.map_state != IsViewable || !w->damaged) continue; } /* copy region */ XSubtractRegion (tmpRegion, &emptyRegion, w->clip); odMask = PAINT_WINDOW_OCCLUSION_DETECTION_MASK; if ((screen->windowOffsetX != 0 || screen->windowOffsetY != 0) && !windowOnAllViewports (w)) { withOffset = TRUE; getWindowMovementForOffset (w, screen->windowOffsetX, screen->windowOffsetY, &offX, &offY); vTransform = *transform; matrixTranslate (&vTransform, offX, offY, 0); XOffsetRegion (w->clip, -offX, -offY); odMask |= PAINT_WINDOW_WITH_OFFSET_MASK; status = (*screen->paintWindow) (w, &w->paint, &vTransform, tmpRegion, odMask); } else { withOffset = FALSE; status = (*screen->paintWindow) (w, &w->paint, transform, tmpRegion, odMask); } if (status) { if (withOffset) { XOffsetRegion (w->region, offX, offY); XSubtractRegion (tmpRegion, w->region, tmpRegion); XOffsetRegion (w->region, -offX, -offY); } else XSubtractRegion (tmpRegion, w->region, tmpRegion); /* unredirect top most fullscreen windows. */ /* if the fullscreen window is mate-screensaver and we're on nvidia we want to always unredirect even if this option is disabled to work around LP #160264 */ if (count == 0 && (screen->opt[COMP_SCREEN_OPTION_UNREDIRECT_FS].value.b || (w->resName && !strcmp(w->resName, "mate-screensaver") && XQueryExtension (screen->display->display, "NV-GLX", &dontcare, &dontcare, &dontcare)))) { if (XEqualRegion (w->region, &screen->region) && !REGION_NOT_EMPTY (tmpRegion)) { fullscreenWindow = w; } else { for (i = 0; i < screen->nOutputDev; i++) if (XEqualRegion (w->region, &screen->outputDev[i].region)) fullscreenWindow = w; } } } if (!w->invisible) count++; } } if (fullscreenWindow) unredirectWindow (fullscreenWindow); if (!(mask & PAINT_SCREEN_NO_BACKGROUND_MASK)) paintBackground (screen, tmpRegion, (mask & PAINT_SCREEN_TRANSFORMED_MASK)); /* paint all windows from bottom to top */ for (w = (*walk.first) (screen); w; w = (*walk.next) (w)) { if (w->destroyed) continue; if (w == fullscreenWindow) continue; if (!w->shaded) { if (w->attrib.map_state != IsViewable || !w->damaged) continue; } if (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK)) clip = w->clip; if ((screen->windowOffsetX != 0 || screen->windowOffsetY != 0) && !windowOnAllViewports (w)) { getWindowMovementForOffset (w, screen->windowOffsetX, screen->windowOffsetY, &offX, &offY); vTransform = *transform; matrixTranslate (&vTransform, offX, offY, 0); (*screen->paintWindow) (w, &w->paint, &vTransform, clip, windowMask | PAINT_WINDOW_WITH_OFFSET_MASK); } else { (*screen->paintWindow) (w, &w->paint, transform, clip, windowMask); } } if (walk.fini) (*walk.fini) (screen, &walk); /* paint cursors */ for (c = screen->cursors; c; c = c->next) (*screen->paintCursor) (c, transform, tmpRegion, 0); }
void X11Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc, int ySrc, int xDest, int yDest, int width, int height, bool blend ) { // check and adapt to source if needed if( !checkBoundaries( 0, 0, rBitmap.getWidth(), rBitmap.getHeight(), xSrc, ySrc, width, height ) ) { msg_Err( getIntf(), "empty source! pls, debug your skin" ); return; } // check destination if( !checkBoundaries( 0, 0, m_width, m_height, xDest, yDest, width, height ) ) { msg_Err( getIntf(), "out of reach destination! pls, debug your skin" ); return; } // Get a buffer on the image data uint8_t *pBmpData = rBitmap.getData(); if( pBmpData == NULL ) { // Nothing to draw return; } // Force pending XCopyArea to be sent to the X Server // before issuing an XGetImage. XSync( XDISPLAY, False ); // Get the image from the pixmap XImage *pImage = XGetImage( XDISPLAY, m_pixmap, xDest, yDest, width, height, AllPlanes, ZPixmap ); if( pImage == NULL ) { msg_Dbg( getIntf(), "XGetImage returned NULL" ); return; } char *pData = pImage->data; // Get the padding of this image int pad = pImage->bitmap_pad >> 3; int shift = ( pad - ( (width * XPIXELSIZE) % pad ) ) % pad; // Mask for transparency Region mask = XCreateRegion(); // Get a pointer on the right X11Display::makePixel method X11Display::MakePixelFunc_t makePixelFunc = ( blend ? m_rDisplay.getBlendPixel() : m_rDisplay.getPutPixel() ); // Skip the first lines of the image pBmpData += 4 * ySrc * rBitmap.getWidth(); // Copy the bitmap on the image and compute the mask for( int y = 0; y < height; y++ ) { // Skip uninteresting bytes at the beginning of the line pBmpData += 4 * xSrc; // Flag to say whether the previous pixel on the line was visible bool wasVisible = false; // Beginning of the current visible segment on the line int visibleSegmentStart = 0; for( int x = 0; x < width; x++ ) { uint8_t b = *(pBmpData++); uint8_t g = *(pBmpData++); uint8_t r = *(pBmpData++); uint8_t a = *(pBmpData++); // Draw the pixel (m_rDisplay.*makePixelFunc)( (uint8_t*)pData, r, g, b, a ); pData += XPIXELSIZE; if( a > 0 ) { // Pixel is visible if( ! wasVisible ) { // Beginning of a visible segment visibleSegmentStart = x; } wasVisible = true; } else { // Pixel is transparent if( wasVisible ) { // End of a visible segment: add it to the mask addHSegmentInRegion( mask, visibleSegmentStart, x, y ); } wasVisible = false; } } if( wasVisible ) { // End of a visible segment: add it to the mask addHSegmentInRegion( mask, visibleSegmentStart, width, y ); } pData += shift; // Skip uninteresting bytes at the end of the line pBmpData += 4 * (rBitmap.getWidth() - width - xSrc); } // Apply the mask to the graphics context XOffsetRegion( mask, xDest, yDest ); XSetRegion( XDISPLAY, m_gc, mask ); // Copy the image on the pixmap XPutImage( XDISPLAY, m_pixmap, m_gc, pImage, 0, 0, xDest, yDest, width, height); XDestroyImage( pImage ); // Add the bitmap mask to the global graphics mask Region newMask = XCreateRegion(); XUnionRegion( mask, m_mask, newMask ); XDestroyRegion( m_mask ); m_mask = newMask; XDestroyRegion( mask ); }