| /* |
| * X11DRV clipping functions |
| * |
| * Copyright 1998 Huw Davies |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include "config.h" |
| |
| #include "ts_xlib.h" |
| |
| #include <stdio.h> |
| |
| #include "gdi.h" |
| #include "x11drv.h" |
| #include "region.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(x11drv); |
| |
| /*********************************************************************** |
| * X11DRV_SetDeviceClipping |
| * Copy RECT32s to a temporary buffer of XRectangles and call |
| * TSXSetClipRectangles(). |
| * |
| * Could write using GetRegionData but this would be slower. |
| */ |
| void X11DRV_SetDeviceClipping( X11DRV_PDEVICE *physDev, HRGN hrgn ) |
| { |
| XRectangle *pXrect; |
| |
| RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(hrgn, REGION_MAGIC); |
| if (!obj) |
| { |
| ERR("Rgn is 0. Please report this.\n"); |
| return; |
| } |
| |
| if (obj->rgn->numRects > 0) |
| { |
| XRectangle *pXr; |
| RECT *pRect = obj->rgn->rects; |
| RECT *pEndRect = obj->rgn->rects + obj->rgn->numRects; |
| |
| pXrect = HeapAlloc( GetProcessHeap(), 0, |
| sizeof(*pXrect) * obj->rgn->numRects ); |
| if(!pXrect) |
| { |
| WARN("Can't alloc buffer\n"); |
| GDI_ReleaseObj( hrgn ); |
| return; |
| } |
| |
| for(pXr = pXrect; pRect < pEndRect; pRect++, pXr++) |
| { |
| pXr->x = pRect->left; |
| pXr->y = pRect->top; |
| pXr->width = pRect->right - pRect->left; |
| pXr->height = pRect->bottom - pRect->top; |
| } |
| } |
| else |
| pXrect = NULL; |
| |
| TSXSetClipRectangles( gdi_display, physDev->gc, 0, 0, |
| pXrect, obj->rgn->numRects, YXBanded ); |
| |
| if(pXrect) |
| HeapFree( GetProcessHeap(), 0, pXrect ); |
| |
| GDI_ReleaseObj( hrgn ); |
| } |
| |
| |
| /*********************************************************************** |
| * X11DRV_SetDrawable |
| * |
| * Set the drawable, clipping mode and origin for a DC. |
| */ |
| void X11DRV_SetDrawable( HDC hdc, Drawable drawable, int mode, int org_x, int org_y ) |
| { |
| DC *dc = DC_GetDCPtr( hdc ); |
| if (dc) |
| { |
| X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev; |
| /* |
| * This function change the coordinate system (DCOrgX,DCOrgY) |
| * values. When it moves the origin, other data like the current clipping |
| * region will not be moved to that new origin. In the case of DCs that are class |
| * or window DCs that clipping region might be a valid value from a previous use |
| * of the DC and changing the origin of the DC without moving the clip region |
| * results in a clip region that is not placed properly in the DC. |
| * This code will save the dc origin, let the SetDrawable |
| * modify the origin and reset the clipping. When the clipping is set, |
| * it is moved according to the new DC origin. |
| */ |
| if (dc->hClipRgn) OffsetRgn( dc->hClipRgn, org_x - dc->DCOrgX, org_y - dc->DCOrgY ); |
| dc->DCOrgX = org_x; |
| dc->DCOrgY = org_y; |
| physDev->drawable = drawable; |
| TSXSetSubwindowMode( gdi_display, physDev->gc, mode ); |
| if(physDev->xrender) |
| X11DRV_XRender_UpdateDrawable( physDev ); |
| GDI_ReleaseObj( hdc ); |
| } |
| } |
| |
| |
| /*********************************************************************** |
| * X11DRV_StartGraphicsExposures |
| * |
| * Set the DC in graphics exposures mode |
| */ |
| void X11DRV_StartGraphicsExposures( HDC hdc ) |
| { |
| DC *dc = DC_GetDCPtr( hdc ); |
| if (dc) |
| { |
| X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev; |
| TSXSetGraphicsExposures( gdi_display, physDev->gc, True ); |
| physDev->exposures = 0; |
| GDI_ReleaseObj( hdc ); |
| } |
| } |
| |
| |
| /*********************************************************************** |
| * X11DRV_EndGraphicsExposures |
| * |
| * End the graphics exposures mode and process the events |
| */ |
| void X11DRV_EndGraphicsExposures( HDC hdc, HRGN hrgn ) |
| { |
| HRGN tmp = 0; |
| DC *dc = DC_GetDCPtr( hdc ); |
| |
| if (dc) |
| { |
| XEvent event; |
| X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev; |
| |
| SetRectRgn( hrgn, 0, 0, 0, 0 ); |
| wine_tsx11_lock(); |
| XSetGraphicsExposures( gdi_display, physDev->gc, False ); |
| if (physDev->exposures) |
| { |
| XSync( gdi_display, False ); |
| for (;;) |
| { |
| XWindowEvent( gdi_display, physDev->drawable, ~0, &event ); |
| if (event.type == NoExpose) break; |
| if (event.type == GraphicsExpose) |
| { |
| int x = event.xgraphicsexpose.x - dc->DCOrgX; |
| int y = event.xgraphicsexpose.y - dc->DCOrgY; |
| |
| TRACE( "got %d,%d %dx%d count %d\n", |
| x, y, event.xgraphicsexpose.width, event.xgraphicsexpose.height, |
| event.xgraphicsexpose.count ); |
| |
| if (!tmp) tmp = CreateRectRgn( 0, 0, 0, 0 ); |
| SetRectRgn( tmp, x, y, |
| x + event.xgraphicsexpose.width, |
| y + event.xgraphicsexpose.height ); |
| CombineRgn( hrgn, hrgn, tmp, RGN_OR ); |
| if (!event.xgraphicsexpose.count) break; |
| } |
| else |
| { |
| ERR( "got unexpected event %d\n", event.type ); |
| break; |
| } |
| if (tmp) DeleteObject( tmp ); |
| } |
| } |
| wine_tsx11_unlock(); |
| GDI_ReleaseObj( hdc ); |
| } |
| } |
| |