From acc2acbb288f8a715cce7905093615b3a7fcbc47 Mon Sep 17 00:00:00 2001 From: das Date: Fri, 12 Oct 2007 03:14:47 +0000 Subject: * macosx/tkMacOSXDraw.c: replace all (internal) use of QD region * macosx/tkMacOSXSubwindows.c: API by HIShape API, with conversion to * macosx/tkMacOSXWindowEvent.c QD regions only when required by legacy * macosx/tkMacOSXPrivate.h: Carbon or Tk API. * macosx/tkMacOSXRegion.c: * macosx/tkMacOSXDebug.c: * macosx/tkMacOSXDebug.h: * macosx/tkMacOSXInt.h: replace MacDrawable's QD RgnHandles * macosx/tkMacOSXEmbed.c: clipRgn, aboveClipRgn & drawRgn by * macosx/tkMacOSXMenu.c: HIShapeRefs visRgn & aboveVisRgn and * macosx/tkMacOSXSubwindows.c: CGRect drawRect. * macosx/tkMacOSXWindowEvent.c: remove use of QD port vis rgn in window * macosx/tkMacOSXSubwindows.c: update rgn calculation, manually excise * macosx/tkMacOSXWm.c: growbox from toplevel clip rgn instead. * macosx/tkMacOSXDraw.c: replace use of QD port clip rgn by new * macosx/tkMacOSXPrivate.h: clipRgn fld in TkMacOSXDrawingContext; handle QD/CG drawing mismatches in XCopyArea, XCopyPlane and TkPutImage; cleanup/speedup CGContext setup in TkMacOSXSetupDrawingContext(). * macosx/tkMacOSXDraw.c: change TkMacOSXSetupDrawingContext() to * macosx/tkMacOSXEntry.c: return boolean indicating whether * macosx/tkMacOSXFont.c: drawing is allowed (and was setup) or * macosx/tkMacOSXMenu.c: not (e.g. when clipRgn is empty). * macosx/ttkMacOSXTheme.c: * macosx/tkMacOSXSubwindows.c: signal that drawable is a pixmap via * macosx/tkMacOSXInt.h: new explicit TK_IS_PIXMAP flag instead of a NULL cligRgn field. * macosx/tkMacOSXRegion.c: add wrappers for missing/buggy HIShape * macosx/tkMacOSXPrivate.h: API, and private helpers to operate on HIShapeRefs & convert to/from TkRegion. * macosx/tkMacOSXRegion.c: add Tkp{Retain,Release}Region() API for * macosx/tkMacOSXInt.h: TkRegion. --- ChangeLog | 51 ++++ macosx/tkMacOSXDebug.c | 17 +- macosx/tkMacOSXDebug.h | 4 +- macosx/tkMacOSXDraw.c | 638 ++++++++++++++++++++++++++----------------- macosx/tkMacOSXEmbed.c | 16 +- macosx/tkMacOSXEntry.c | 10 +- macosx/tkMacOSXFont.c | 8 +- macosx/tkMacOSXInt.h | 11 +- macosx/tkMacOSXMenu.c | 24 +- macosx/tkMacOSXPrivate.h | 36 ++- macosx/tkMacOSXRegion.c | 408 +++++++++++++++++++++++++-- macosx/tkMacOSXSubwindows.c | 195 +++++++++---- macosx/tkMacOSXWindowEvent.c | 107 +++++--- macosx/tkMacOSXWm.c | 3 +- macosx/ttkMacOSXTheme.c | 4 +- 15 files changed, 1101 insertions(+), 431 deletions(-) diff --git a/ChangeLog b/ChangeLog index e405bf3..a937ad5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,54 @@ +2007-10-12 Daniel Steffen + + * macosx/tkMacOSXDraw.c: replace all (internal) use of QD region + * macosx/tkMacOSXSubwindows.c: API by HIShape API, with conversion to + * macosx/tkMacOSXWindowEvent.c QD regions only when required by legacy + * macosx/tkMacOSXPrivate.h: Carbon or Tk API. + * macosx/tkMacOSXRegion.c: + * macosx/tkMacOSXDebug.c: + * macosx/tkMacOSXDebug.h: + + * macosx/tkMacOSXInt.h: replace MacDrawable's QD RgnHandles + * macosx/tkMacOSXEmbed.c: clipRgn, aboveClipRgn & drawRgn by + * macosx/tkMacOSXMenu.c: HIShapeRefs visRgn & aboveVisRgn and + * macosx/tkMacOSXSubwindows.c: CGRect drawRect. + + * macosx/tkMacOSXWindowEvent.c: remove use of QD port vis rgn in window + * macosx/tkMacOSXSubwindows.c: update rgn calculation, manually excise + * macosx/tkMacOSXWm.c: growbox from toplevel clip rgn instead. + + * macosx/tkMacOSXDraw.c: replace use of QD port clip rgn by new + * macosx/tkMacOSXPrivate.h: clipRgn fld in TkMacOSXDrawingContext; + handle QD/CG drawing mismatches in + XCopyArea, XCopyPlane and TkPutImage; + cleanup/speedup CGContext setup in + TkMacOSXSetupDrawingContext(). + + * macosx/tkMacOSXDraw.c: change TkMacOSXSetupDrawingContext() to + * macosx/tkMacOSXEntry.c: return boolean indicating whether + * macosx/tkMacOSXFont.c: drawing is allowed (and was setup) or + * macosx/tkMacOSXMenu.c: not (e.g. when clipRgn is empty). + * macosx/ttkMacOSXTheme.c: + + * macosx/tkMacOSXSubwindows.c: signal that drawable is a pixmap via + * macosx/tkMacOSXInt.h: new explicit TK_IS_PIXMAP flag instead + of a NULL cligRgn field. + + * macosx/tkMacOSXRegion.c: add wrappers for missing/buggy HIShape + * macosx/tkMacOSXPrivate.h: API, and private helpers to operate on + HIShapeRefs & convert to/from TkRegion. + + * macosx/tkMacOSXRegion.c: add Tkp{Retain,Release}Region() API for + * macosx/tkMacOSXInt.h: TkRegion. + + * xlib/xgc.c: factor out alloc/free of GC clip_mask; + * macosx/tkMacOSXXStubs.c: manage clip rgn lifetime with new + Tkp{Retain,Release}Region(). + + * macosx/tkMacOSXButton.c: delay picParams setup until needed. + + * generic/tkTextDisp.c (CharUndisplayProc): fix textDisp.test crash. + 2007-10-11 David Gravereaux * win/winMain.c: Replaced incorrect comments in main() to descibe diff --git a/macosx/tkMacOSXDebug.c b/macosx/tkMacOSXDebug.c index bceddab..b9ff3fa 100644 --- a/macosx/tkMacOSXDebug.c +++ b/macosx/tkMacOSXDebug.c @@ -54,7 +54,7 @@ * software in accordance with the terms specified in this * license. * - * RCS: @(#) $Id: tkMacOSXDebug.c,v 1.14 2007/06/29 03:20:00 das Exp $ + * RCS: @(#) $Id: tkMacOSXDebug.c,v 1.15 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -456,19 +456,28 @@ TkMacOSXMouseTrackingResultToAscii(MouseTrackingResult r, char * buf) MODULE_SCOPE void TkMacOSXDebugFlashRegion( Drawable d, - RgnHandle rgn) + HIShapeRef rgn) { TkMacOSXInitNamedDebugSymbol(HIToolbox, int, QDDebugFlashRegion, CGrafPtr port, RgnHandle region); - if (d && rgn && QDDebugFlashRegion && !EmptyRgn(rgn)) { + CFShow(rgn); + if (d && rgn && QDDebugFlashRegion && !HIShapeIsEmpty(rgn)) { CGrafPtr port = TkMacOSXGetDrawablePort(d); if (port) { + static RgnHandle qdRgn = NULL; + + if (!qdRgn) { + qdRgn = NewRgn(); + } + ChkErr(HIShapeGetAsQDRgn, rgn, qdRgn); + /* * Carbon-internal region flashing SPI (c.f. Technote 2124) */ - QDDebugFlashRegion(port, rgn); + QDDebugFlashRegion(port, qdRgn); + SetEmptyRgn(qdRgn); } } } diff --git a/macosx/tkMacOSXDebug.h b/macosx/tkMacOSXDebug.h index 7ef4834..be4a6a7 100644 --- a/macosx/tkMacOSXDebug.h +++ b/macosx/tkMacOSXDebug.h @@ -54,7 +54,7 @@ * software in accordance with the terms specified in this * license. * - * RCS: @(#) $Id: tkMacOSXDebug.h,v 1.12 2007/06/29 03:20:00 das Exp $ + * RCS: @(#) $Id: tkMacOSXDebug.h,v 1.13 2007/10/12 03:14:48 das Exp $ */ #ifndef _TKMACDEBUG @@ -82,7 +82,7 @@ MODULE_SCOPE char* TkMacOSXMenuMessageToAscii(int msg, char * s); MODULE_SCOPE char* TkMacOSXMouseTrackingResultToAscii(MouseTrackingResult r, char * buf ); #endif -MODULE_SCOPE void TkMacOSXDebugFlashRegion(Drawable d, RgnHandle rgn); +MODULE_SCOPE void TkMacOSXDebugFlashRegion(Drawable d, HIShapeRef rgn); MODULE_SCOPE void* TkMacOSXGetNamedDebugSymbol(const char* module, const char* symbol); diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 53e1996..06b09fb 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.29 2007/07/09 08:30:22 das Exp $ + * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.30 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -53,7 +53,7 @@ static int useThemedFrame = 0; * Prototypes for functions used only in this file. */ -static void ClipToGC(Drawable d, GC gc, CGrafPtr port, RgnHandle clipRgn); +static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr); static void NoQDClip(CGrafPtr port); @@ -161,32 +161,50 @@ XCopyArea( display->request++; if (!width || !height) { - TkMacOSXDbgMsg("Drawing of emtpy area requested"); + /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */ return; } - if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) { - Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; + { CGrafPtr srcPort; - const BitMap *srcBit, *dstBit; - RGBColor black = {0, 0, 0}, white = {0xffff, 0xffff, 0xffff}; srcPort = TkMacOSXGetDrawablePort(src); - srcBit = GetPortBitMapForCopyBits(srcPort); - dstBit = GetPortBitMapForCopyBits(dc.port); - SetRect(srcPtr, srcDraw->xOff + src_x, srcDraw->yOff + src_y, - srcDraw->xOff + src_x + width, srcDraw->yOff + src_y + height); - if (tkPictureIsOpen) { - dstPtr = srcPtr; + if (srcPort) { + Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; + const BitMap *srcBit, *dstBit; + RGBColor black = {0, 0, 0}, white = {0xffff, 0xffff, 0xffff}; + + if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) { + return; + } + if (dc.context) { + TkMacOSXDbgMsg("Ignored CG drawing of QD drawable"); + goto end; + } + if (!dc.port) { + TkMacOSXDbgMsg("Invalid destination drawable"); + goto end; + } + srcBit = GetPortBitMapForCopyBits(srcPort); + dstBit = GetPortBitMapForCopyBits(dc.port); + SetRect(srcPtr, srcDraw->xOff + src_x, srcDraw->yOff + src_y, + srcDraw->xOff + src_x + width, + srcDraw->yOff + src_y + height); + if (tkPictureIsOpen) { + dstPtr = srcPtr; + } else { + SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, + dstDraw->xOff + dest_x + width, + dstDraw->yOff + dest_y + height); + } + RGBForeColor(&black); + RGBBackColor(&white); + CopyBits(srcBit, dstBit, srcPtr, dstPtr, srcCopy, NULL); +end: + TkMacOSXRestoreDrawingContext(&dc); } else { - SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, - dstDraw->xOff + dest_x + width, - dstDraw->yOff + dest_y + height); + TkMacOSXDbgMsg("Invalid source drawable"); } - RGBForeColor(&black); - RGBBackColor(&white); - CopyBits(srcBit, dstBit, srcPtr, dstPtr, srcCopy, NULL); } - TkMacOSXRestoreDrawingContext(&dc); } /* @@ -227,61 +245,80 @@ XCopyPlane( display->request++; if (!width || !height) { - TkMacOSXDbgMsg("Drawing of emtpy area requested"); + /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */ return; } if (plane != 1) { Tcl_Panic("Unexpected plane specified for XCopyPlane"); } - if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) { - Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; + { CGrafPtr srcPort; - const BitMap *srcBit, *dstBit; - TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; srcPort = TkMacOSXGetDrawablePort(src); - srcBit = GetPortBitMapForCopyBits(srcPort); - dstBit = GetPortBitMapForCopyBits(dc.port); - SetRect(srcPtr, srcDraw->xOff + src_x, srcDraw->yOff + src_y, - srcDraw->xOff + src_x + width, srcDraw->yOff + src_y + height); - if (tkPictureIsOpen) { - dstPtr = srcPtr; - } else { - SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, - dstDraw->xOff + dest_x + width, - dstDraw->yOff + dest_y + height); - } - TkMacOSXSetColorInPort(gc->foreground, 1, NULL, dc.port); - if (!clipPtr || clipPtr->type == TKP_CLIP_REGION) { - /* - * Opaque bitmaps. - */ + if (srcPort) { + Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; + const BitMap *srcBit, *dstBit; + TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; - TkMacOSXSetColorInPort(gc->background, 0, NULL, dc.port); - CopyBits(srcBit, dstBit, srcPtr, dstPtr, srcCopy, NULL); - } else if (clipPtr->type == TKP_CLIP_PIXMAP) { - if (clipPtr->value.pixmap == src) { - /* - * Transparent bitmaps. If it's color we ignore the forecolor. - */ - short tmode = GetPixDepth(GetPortPixMap(srcPort)) == 1 ? - srcOr : transparent; - - CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL); + if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) { + return; + } + if (dc.context) { + TkMacOSXDbgMsg("Ignored CG drawing of QD drawable"); + goto end; + } + if (!dc.port) { + TkMacOSXDbgMsg("Invalid destination drawable"); + goto end; + } + srcBit = GetPortBitMapForCopyBits(srcPort); + dstBit = GetPortBitMapForCopyBits(dc.port); + SetRect(srcPtr, srcDraw->xOff + src_x, srcDraw->yOff + src_y, + srcDraw->xOff + src_x + width, + srcDraw->yOff + src_y + height); + if (tkPictureIsOpen) { + dstPtr = srcPtr; } else { + SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, + dstDraw->xOff + dest_x + width, + dstDraw->yOff + dest_y + height); + } + TkMacOSXSetColorInPort(gc->foreground, 1, NULL, dc.port); + if (!clipPtr || clipPtr->type == TKP_CLIP_REGION) { /* - * Two arbitrary bitmaps. + * Opaque bitmaps. */ - CGrafPtr mskPort = TkMacOSXGetDrawablePort(clipPtr->value.pixmap); - const BitMap *mskBit = GetPortBitMapForCopyBits(mskPort); + TkMacOSXSetColorInPort(gc->background, 0, NULL, dc.port); + CopyBits(srcBit, dstBit, srcPtr, dstPtr, srcCopy, NULL); + } else if (clipPtr->type == TKP_CLIP_PIXMAP) { + if (clipPtr->value.pixmap == src) { + /* + * Transparent bitmaps. If it's color ignore the forecolor. + */ + short tmode = GetPixDepth(GetPortPixMap(srcPort)) == 1 ? + srcOr : transparent; - CopyDeepMask(srcBit, mskBit, dstBit, srcPtr, srcPtr, dstPtr, - srcCopy, NULL); + CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL); + } else { + /* + * Two arbitrary bitmaps. + */ + + CGrafPtr mskPort = TkMacOSXGetDrawablePort( + clipPtr->value.pixmap); + const BitMap *mskBit = GetPortBitMapForCopyBits(mskPort); + + CopyDeepMask(srcBit, mskBit, dstBit, srcPtr, srcPtr, + dstPtr, srcCopy, NULL); + } } +end: + TkMacOSXRestoreDrawingContext(&dc); + } else { + TkMacOSXDbgMsg("Invalid source drawable"); } } - TkMacOSXRestoreDrawingContext(&dc); } /* @@ -321,14 +358,19 @@ TkPutImage( display->request++; if (!TkMacOSXSetupDrawingContext(d, gc, 0, &dc)) { + return; + } + if (dc.context) { + TkMacOSXDbgMsg("Ignored CG drawing of XImage"); + } else { Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; const BitMap *dstBit; RGBColor black = {0, 0, 0}, white = {0xffff, 0xffff, 0xffff}; int i, j; char *newData = NULL; char *dataPtr, *newPtr, *oldPtr; - int rowBytes = image->bytes_per_line; - int slices, sliceRowBytes, lastSliceRowBytes, sliceWidth, lastSliceWidth; + int rowBytes = image->bytes_per_line, sliceRowBytes, lastSliceRowBytes; + int slices, sliceWidth, lastSliceWidth; dstBit = GetPortBitMapForCopyBits(dc.port); SetRect(srcPtr, src_x, src_y, src_x + width, src_y + height); @@ -346,8 +388,9 @@ TkPutImage( * Image from XGetImage, copy from containing GWorld directly. */ - CopyBits(GetPortBitMapForCopyBits(TkMacOSXGetDrawablePort((Drawable) - image->obdata)), dstBit, srcPtr, dstPtr, srcCopy, NULL); + CopyBits(GetPortBitMapForCopyBits(TkMacOSXGetDrawablePort( + (Drawable)image->obdata)), dstBit, + srcPtr, dstPtr, srcCopy, NULL); } else if (image->depth == 1) { /* * BW image @@ -527,7 +570,10 @@ XDrawLines( } display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { double prevx, prevy; double o = (lw % 2) ? .5 : 0; @@ -597,7 +643,10 @@ XDrawSegments( int i, lw = gc->line_width; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { double o = (lw % 2) ? .5 : 0; for (i = 0; i < nsegments; i++) { @@ -658,7 +707,10 @@ XFillPolygon( int i; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { double prevx, prevy; double o = (gc->line_width % 2) ? .5 : 0; @@ -733,7 +785,10 @@ XDrawRectangle( } display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0; @@ -796,7 +851,10 @@ XDrawRectangles( int i, lw = gc->line_width; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0; @@ -856,7 +914,10 @@ XFillRectangles( int i; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) { @@ -919,7 +980,10 @@ XDrawArc( } display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0; @@ -1001,7 +1065,10 @@ XDrawArcs( int i, lw = gc->line_width; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0; @@ -1094,7 +1161,10 @@ XFillArc( } display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0, u = 0; @@ -1208,7 +1278,10 @@ XFillArcs( int i, lw = gc->line_width; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0, u = 0; @@ -1354,7 +1427,7 @@ TkScrollWindow( Boolean portChanged; Rect scrollRect; int result; - RgnHandle rgn = (RgnHandle) damageRgn; + HIShapeRef dmgRgn; /* * Due to the implementation below the behavior may be differnt @@ -1383,8 +1456,9 @@ TkScrollWindow( destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); + TkMacOSXCheckTmpQdRgnEmpty(); portChanged = QDSwapPort(destPort, &savePort); - ScrollRect(&scrollRect, dx, dy, rgn); + ScrollRect(&scrollRect, dx, dy, tkMacOSXtmpQdRgn); if (portChanged) { QDSwapPort(savePort, NULL); } @@ -1396,7 +1470,11 @@ TkScrollWindow( * created. */ - result = EmptyRgn(rgn) ? 0 : 1; + dmgRgn = HIShapeCreateWithQDRgn(tkMacOSXtmpQdRgn); + SetEmptyRgn(tkMacOSXtmpQdRgn); + TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn); + result = HIShapeIsEmpty(dmgRgn) ? 0 : 1; + CFRelease(dmgRgn); return result; } @@ -1454,7 +1532,9 @@ TkMacOSXSetUpGraphicsPort( * Set up a drawing context for the given drawable and GC. * * Results: - * Boolean indicating whether to use CG drawing. + * Boolean indicating whether it is ok to draw; if false, drawing + * context was not setup, so do not attempt to draw and do not call + * TkMacOSXRestoreDrawingContext(). * * Side effects: * None. @@ -1467,149 +1547,152 @@ TkMacOSXSetupDrawingContext( Drawable d, GC gc, int useCG, /* advisory only ! */ - TkMacOSXDrawingContext *dc) + TkMacOSXDrawingContext *dcPtr) { MacDrawable *macDraw = ((MacDrawable*)d); - CGContextRef context = macDraw->context; - CGrafPtr port; - Rect portBounds; - - dc->saveState = NULL; - dc->saveClip = NULL; - dc->penPat = NULL; - dc->portChanged = false; - port = TkMacOSXGetDrawablePort(d); - if (port) { - GetPortBounds(port, &portBounds); - dc->saveClip = NewRgn(); - GetPortClipRegion(port, dc->saveClip); - if (tkPictureIsOpen) { - NoQDClip(port); - } else { - TkMacOSXSetUpClippingRgn(d); + int dontDraw = 0; + TkMacOSXDrawingContext dc = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, + {SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX}, false}; + + if (tkPictureIsOpen) { + if (useCG) { + TkMacOSXDbgMsg("Ignored CG Drawing with QD Picture open"); + dontDraw = 1; } + } else { + dc.clipRgn = TkMacOSXGetClipRgn(d); + } + if (!dontDraw) { + ClipToGC(d, gc, &dc.clipRgn); + dontDraw = dc.clipRgn ? HIShapeIsEmpty(dc.clipRgn) : 0; } - if (context && useCG) { - if (!port) { + if (dontDraw) { + if (dc.clipRgn) { + CFRelease(dc.clipRgn); + dc.clipRgn = NULL; + } + goto end; + } + dc.port = TkMacOSXGetDrawablePort(d); + if (dc.port) { + GetPortBounds(dc.port, &dc.portBounds); + } + dc.context = macDraw->context; + if (dc.context && useCG) { + if (!dc.port) { TK_IF_MAC_OS_X_API (3, CGContextGetClipBoundingBox, - CGRect r = CGContextGetClipBoundingBox(context); + CGRect r = CGContextGetClipBoundingBox(dc.context); - SetRect(&portBounds, r.origin.x + macDraw->xOff, + SetRect(&dc.portBounds, r.origin.x + macDraw->xOff, r.origin.y + macDraw->yOff, r.origin.x + r.size.width + macDraw->xOff, r.origin.y + r.size.height + macDraw->yOff); ) TK_ENDIF } - CGContextSaveGState(context); - dc->saveState = (void*)1; - port = NULL; - } else if (port) { - dc->portChanged = QDSwapPort(port, &(dc->savePort)); - if (useCG && ChkErr(QDBeginCGContext, port, &context) == noErr) { - SyncCGContextOriginWithPort(context, port); + CGContextSaveGState(dc.context); + dc.saveState = (void*)1; + dc.port = NULL; + } else if (dc.port) { + dc.portChanged = QDSwapPort(dc.port, &dc.savePort); + if (useCG && ChkErr(QDBeginCGContext, dc.port, &dc.context) == noErr) { + SyncCGContextOriginWithPort(dc.context, dc.port); } else { - context = NULL; - useCG = 0; + dc.context = NULL; } } else { Tcl_Panic("TkMacOSXSetupDrawingContext(): " "no port or context to draw into !"); } - if (useCG) { - if (tkPictureIsOpen) { - TkMacOSXDbgMsg("Ignored CG Drawing with QD Picture open"); - } else if (context) { - TkMacOSXCheckTmpQdRgnEmpty(); - RectRgn(tkMacOSXtmpQdRgn, &portBounds); - if (port) { - SectRegionWithPortClipRegion(port, tkMacOSXtmpQdRgn); - SectRegionWithPortVisibleRegion(port, tkMacOSXtmpQdRgn); - } else if (macDraw->flags & TK_CLIPPED_DRAW) { - OffsetRgn(macDraw->drawRgn, macDraw->xOff, macDraw->yOff); - SectRgn(macDraw->clipRgn, macDraw->drawRgn, tkMacOSXtmpQdRgn); - OffsetRgn(macDraw->drawRgn, -macDraw->xOff, -macDraw->yOff); + if (dc.context) { + CGContextConcatCTM(dc.context, CGAffineTransformMake(1.0, 0.0, 0.0, + -1.0, 0.0, dc.portBounds.bottom - dc.portBounds.top)); + if (dc.clipRgn) { +#ifdef TK_MAC_DEBUG_DRAWING + CGContextSaveGState(dc.context); + ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); + CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.2); + CGContextEOFillPath(dc.context); + CGContextRestoreGState(dc.context); +#endif /* TK_MAC_DEBUG_DRAWING */ + ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); + CGContextEOClip(dc.context); + } + if (gc) { + static const CGLineCap cgCap[] = { + [CapNotLast] = kCGLineCapButt, + [CapButt] = kCGLineCapButt, + [CapRound] = kCGLineCapRound, + [CapProjecting] = kCGLineCapSquare, + }; + static const CGLineJoin cgJoin[] = { + [JoinMiter] = kCGLineJoinMiter, + [JoinRound] = kCGLineJoinRound, + [JoinBevel] = kCGLineJoinBevel, + }; + bool shouldAntialias; + double w = gc->line_width; + + TkMacOSXSetColorInContext(gc->foreground, dc.context); + if (dc.port) { + CGContextSetPatternPhase(dc.context, CGSizeMake( + dc.portBounds.right - dc.portBounds.left, + dc.portBounds.bottom - dc.portBounds.top)); } - ClipToGC(d, gc, NULL, tkMacOSXtmpQdRgn); - ClipCGContextToRegion(context, &portBounds, tkMacOSXtmpQdRgn); - SetEmptyRgn(tkMacOSXtmpQdRgn); - CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0, - -1.0, 0.0, portBounds.bottom - portBounds.top)); - if (gc) { - double w = gc->line_width; - - TkMacOSXSetColorInContext(gc->foreground, context); - if (port) { - CGContextSetPatternPhase(context, - CGSizeMake(portBounds.right - portBounds.left, - portBounds.bottom - portBounds.top)); - } - if(gc->function != GXcopy) { - TkMacOSXDbgMsg("Logical functions other than GXcopy are " - "not supported for CG drawing!"); - } - /* When should we antialias? */ - if (notAA(gc->line_width)) { - /* Make non-antialiased CG drawing look more like X11 */ - w -= (gc->line_width ? NON_AA_CG_OFFSET : 0); - CGContextSetShouldAntialias(context, 0); - } else { - CGContextSetShouldAntialias(context, 1); - } - CGContextSetLineWidth(context, w); - if (gc->line_style != LineSolid) { - int num = 0; - char *p = &(gc->dashes); - double dashOffset = gc->dash_offset; - float lengths[10]; - - while (p[num] != '\0' && num < 10) { - lengths[num] = p[num]; - num++; - } - CGContextSetLineDash(context, dashOffset, lengths, num); - } - if (gc->cap_style == CapButt) { - /* - * What about CapNotLast, CapProjecting? - */ - - CGContextSetLineCap(context, kCGLineCapButt); - } else if (gc->cap_style == CapRound) { - CGContextSetLineCap(context, kCGLineCapRound); - } else if (gc->cap_style == CapProjecting) { - CGContextSetLineCap(context, kCGLineCapSquare); - } - if (gc->join_style == JoinMiter) { - CGContextSetLineJoin(context, kCGLineJoinMiter); - } else if (gc->join_style == JoinRound) { - CGContextSetLineJoin(context, kCGLineJoinRound); - } else if (gc->join_style == JoinBevel) { - CGContextSetLineJoin(context, kCGLineJoinBevel); + if(gc->function != GXcopy) { + TkMacOSXDbgMsg("Logical functions other than GXcopy are " + "not supported for CG drawing!"); + } + /* When should we antialias? */ + shouldAntialias = !notAA(gc->line_width); + if (!shouldAntialias) { + /* Make non-antialiased CG drawing look more like X11 */ + w -= (gc->line_width ? NON_AA_CG_OFFSET : 0); + } + CGContextSetShouldAntialias(dc.context, shouldAntialias); + CGContextSetLineWidth(dc.context, w); + if (gc->line_style != LineSolid) { + int num = 0; + char *p = &(gc->dashes); + double dashOffset = gc->dash_offset; + float lengths[10]; + + while (p[num] != '\0' && num < 10) { + lengths[num] = p[num]; + num++; } + CGContextSetLineDash(dc.context, dashOffset, lengths, num); } - } - } else { - if (port) { - PixPatHandle savePat = penPat; - - ChkErr(GetThemeDrawingState, &(dc->saveState)); - penPat = NULL; - TkMacOSXSetUpGraphicsPort(gc, port); - dc->penPat = penPat; - penPat = savePat; - if (gc) { - TkMacOSXCheckTmpQdRgnEmpty(); - ClipToGC(d, gc, port, tkMacOSXtmpQdRgn); + if ((unsigned)gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) { + CGContextSetLineCap(dc.context, + cgCap[(unsigned)gc->cap_style]); } - if (!tkPictureIsOpen) { - ShowPen(); + if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) { + CGContextSetLineJoin(dc.context, + cgJoin[(unsigned)gc->join_style]); } } + } else if (dc.port) { + PixPatHandle savePat = penPat; + + ChkErr(GetThemeDrawingState, &dc.saveState); + penPat = NULL; + TkMacOSXSetUpGraphicsPort(gc, dc.port); + dc.penPat = penPat; + penPat = savePat; + dc.saveClip = NewRgn(); + GetPortClipRegion(dc.port, dc.saveClip); + if (dc.clipRgn) { + ChkErr(HIShapeSetQDClip, dc.clipRgn, dc.port); + } else { + NoQDClip(dc.port); + } + if (!tkPictureIsOpen) { + ShowPen(); + } } - dc->portBounds = portBounds; - dc->port = port; - dc->context = context; - return useCG; +end: + *dcPtr = dc; + return !dontDraw; } /* @@ -1629,87 +1712,130 @@ TkMacOSXSetupDrawingContext( */ void -TkMacOSXRestoreDrawingContext(TkMacOSXDrawingContext *dc) +TkMacOSXRestoreDrawingContext( + TkMacOSXDrawingContext *dcPtr) { - if (dc->context) { - CGContextSynchronize(dc->context); - if (dc->saveState) { - CGContextRestoreGState(dc->context); + if (dcPtr->context) { + CGContextSynchronize(dcPtr->context); + if (dcPtr->saveState) { + CGContextRestoreGState(dcPtr->context); } - if (dc->port) { - ChkErr(QDEndCGContext, dc->port, &(dc->context)); + if (dcPtr->port) { + ChkErr(QDEndCGContext, dcPtr->port, &(dcPtr->context)); } - } else if (dc->port) { + } else if (dcPtr->port) { if (!tkPictureIsOpen) { HidePen(); } PenNormal(); - if (dc->saveClip) { - SetPortClipRegion(dc->port, dc->saveClip); - DisposeRgn(dc->saveClip); + if (dcPtr->saveClip) { + SetPortClipRegion(dcPtr->port, dcPtr->saveClip); + DisposeRgn(dcPtr->saveClip); } - if (dc->penPat) { - DisposePixPat(dc->penPat); + if (dcPtr->penPat) { + DisposePixPat(dcPtr->penPat); } - if (dc->saveState) { - ChkErr(SetThemeDrawingState, dc->saveState, true); + if (dcPtr->saveState) { + ChkErr(SetThemeDrawingState, dcPtr->saveState, true); } } - if (dc->portChanged) { - QDSwapPort(dc->savePort, NULL); + if (dcPtr->clipRgn) { + CFRelease(dcPtr->clipRgn); + } + if (dcPtr->portChanged) { + QDSwapPort(dcPtr->savePort, NULL); } #ifdef TK_MAC_DEBUG - bzero(dc, sizeof(dc)); + bzero(dcPtr, sizeof(dcPtr)); #endif /* TK_MAC_DEBUG */ } /* *---------------------------------------------------------------------- * - * TkMacOSXSetUpClippingRgn -- + * TkMacOSXGetClipRgn -- * - * Set up the clipping region so that drawing only occurs on the - * specified X subwindow. + * Get the clipping region needed to restrict drawing to the given + * drawable. * * Results: - * None. + * Clipping region. If non-NULL, CFRelease it when done. * * Side effects: - * The clipping region in the current port is changed. + * None. * *---------------------------------------------------------------------- */ -void -TkMacOSXSetUpClippingRgn( - Drawable drawable) /* Drawable to update. */ +HIShapeRef +TkMacOSXGetClipRgn( + Drawable drawable) /* Drawable. */ { MacDrawable *macDraw = (MacDrawable *) drawable; - CGrafPtr port = TkMacOSXGetDrawablePort(drawable); + HIShapeRef clipRgn = NULL; + CGRect r; if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) { TkMacOSXUpdateClipRgn(macDraw->winPtr); #ifdef TK_MAC_DEBUG_DRAWING - TkMacOSXDbgMsg("%s clipRgn ", macDraw->winPtr->pathName); - TkMacOSXDebugFlashRegion(drawable, macDraw->clipRgn); + TkMacOSXDbgMsg("%s visRgn ", macDraw->winPtr->pathName); + TkMacOSXDebugFlashRegion(drawable, macDraw->visRgn); #endif /* TK_MAC_DEBUG_DRAWING */ } - if (macDraw->clipRgn) { + if (macDraw->flags & TK_CLIPPED_DRAW) { + r = CGRectOffset(macDraw->drawRect, macDraw->xOff, macDraw->yOff); + } + if (macDraw->visRgn) { if (macDraw->flags & TK_CLIPPED_DRAW) { - TkMacOSXCheckTmpQdRgnEmpty(); - OffsetRgn(macDraw->drawRgn, macDraw->xOff, macDraw->yOff); - SectRgn(macDraw->clipRgn, macDraw->drawRgn, tkMacOSXtmpQdRgn); - OffsetRgn(macDraw->drawRgn, -macDraw->xOff, -macDraw->yOff); - SetPortClipRegion(port, tkMacOSXtmpQdRgn); - SetEmptyRgn(tkMacOSXtmpQdRgn); + HIShapeRef rgn = HIShapeCreateWithRect(&r); + + clipRgn = HIShapeCreateIntersection(macDraw->visRgn, rgn); + CFRelease(rgn); } else { - SetPortClipRegion(port, macDraw->clipRgn); + clipRgn = HIShapeCreateCopy(macDraw->visRgn); } } else if (macDraw->flags & TK_CLIPPED_DRAW) { - OffsetRgn(macDraw->drawRgn, macDraw->xOff, macDraw->yOff); - SetPortClipRegion(port, macDraw->drawRgn); - OffsetRgn(macDraw->drawRgn, -macDraw->xOff, -macDraw->yOff); + clipRgn = HIShapeCreateWithRect(&r); + } +#ifdef TK_MAC_DEBUG_DRAWING + TkMacOSXDbgMsg("%s clipRgn ", macDraw->winPtr->pathName); + TkMacOSXDebugFlashRegion(drawable, clipRgn); +#endif /* TK_MAC_DEBUG_DRAWING */ + + return clipRgn; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXSetUpClippingRgn -- + * + * Set up the clipping region so that drawing only occurs on the + * specified X subwindow. + * + * Results: + * None. + * + * Side effects: + * The clipping region in the current port is changed. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXSetUpClippingRgn( + Drawable drawable) /* Drawable to update. */ +{ + CGrafPtr port = TkMacOSXGetDrawablePort(drawable); + + if (port) { + HIShapeRef clipRgn = TkMacOSXGetClipRgn(drawable); + + if (clipRgn) { + ChkErr(HIShapeSetQDClip, clipRgn, port); + CFRelease(clipRgn); + } } } @@ -1739,14 +1865,12 @@ TkpClipDrawableToRect( { MacDrawable *macDraw = (MacDrawable *) d; - if (macDraw->drawRgn) { - if (width < 0 && height < 0) { - SetEmptyRgn(macDraw->drawRgn); - macDraw->flags &= ~TK_CLIPPED_DRAW; - } else { - SetRectRgn(macDraw->drawRgn, x, y, x + width, y + height); - macDraw->flags |= TK_CLIPPED_DRAW; - } + if (width < 0 && height < 0) { + macDraw->drawRect = CGRectNull; + macDraw->flags &= ~TK_CLIPPED_DRAW; + } else { + macDraw->drawRect = CGRectMake(x, y, width, height); + macDraw->flags |= TK_CLIPPED_DRAW; } } @@ -1755,8 +1879,7 @@ TkpClipDrawableToRect( * * ClipToGC -- * - * Helper function to intersect the given port's clip region (or if - * port is NULL, the given clipRgn) with gc clip region. + * Helper function to intersect given region with gc clip region. * * Results: * None. @@ -1771,29 +1894,28 @@ static void ClipToGC( Drawable d, GC gc, - CGrafPtr port, /* can be NULL */ - RgnHandle clipRgn) /* tmp region or if port == NULL, region to intersect */ + HIShapeRef *clipRgnPtr) /* must point to initialized variable */ { if (gc && gc->clip_mask && ((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) { - RgnHandle gcClipRgn = (RgnHandle) - ((TkpClipMask*)gc->clip_mask)->value.region; + TkRegion gcClip = ((TkpClipMask*)gc->clip_mask)->value.region; int xOffset = ((MacDrawable *) d)->xOff + gc->clip_x_origin; int yOffset = ((MacDrawable *) d)->yOff + gc->clip_y_origin; + HIShapeRef clipRgn = *clipRgnPtr, gcClipRgn; if (!tkPictureIsOpen) { - OffsetRgn(gcClipRgn, xOffset, yOffset); + TkMacOSXOffsetRegion(gcClip, xOffset, yOffset); } - if (port) { - GetPortClipRegion(port, clipRgn); - } - SectRgn(clipRgn, gcClipRgn, clipRgn); - if (port) { - SetPortClipRegion(port, clipRgn); - SetEmptyRgn(clipRgn); + gcClipRgn = TkMacOSXGetNativeRegion(gcClip); + if (clipRgn) { + *clipRgnPtr = HIShapeCreateIntersection(gcClipRgn, clipRgn); + CFRelease(clipRgn); + } else { + *clipRgnPtr = HIShapeCreateCopy(gcClipRgn); } + CFRelease(gcClipRgn); if (!tkPictureIsOpen) { - OffsetRgn(gcClipRgn, -xOffset, -yOffset); + TkMacOSXOffsetRegion(gcClip, -xOffset, -yOffset); } } } diff --git a/macosx/tkMacOSXEmbed.c b/macosx/tkMacOSXEmbed.c index 5a0e786..8219c8e 100644 --- a/macosx/tkMacOSXEmbed.c +++ b/macosx/tkMacOSXEmbed.c @@ -15,7 +15,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXEmbed.c,v 1.13 2007/06/03 13:44:39 das Exp $ + * RCS: @(#) $Id: tkMacOSXEmbed.c,v 1.14 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXInt.h" @@ -148,12 +148,11 @@ TkpMakeWindow( } macWin->winPtr = winPtr; winPtr->privatePtr = macWin; - macWin->clipRgn = NewRgn(); - macWin->aboveClipRgn = NewRgn(); - macWin->drawRgn = NewRgn(); + macWin->visRgn = NULL; + macWin->aboveVisRgn = NULL; + macWin->drawRect = CGRectNull; macWin->referenceCount = 0; macWin->flags = TK_CLIP_INVALID; - macWin->grafPtr = NULL; macWin->context = NULL; if (Tk_IsTopLevel(macWin->winPtr)) { @@ -299,10 +298,9 @@ TkpUseWindow( macWin->grafPtr = NULL; macWin->context = NULL; - - macWin->clipRgn = NewRgn(); - macWin->aboveClipRgn = NewRgn(); - macWin->drawRgn = NewRgn(); + macWin->visRgn = NULL; + macWin->aboveVisRgn = NULL; + macWin->drawRect = CGRectNull; macWin->referenceCount = 0; macWin->flags = TK_CLIP_INVALID; macWin->toplevel = macWin; diff --git a/macosx/tkMacOSXEntry.c b/macosx/tkMacOSXEntry.c index 3485ae4..848904d 100644 --- a/macosx/tkMacOSXEntry.c +++ b/macosx/tkMacOSXEntry.c @@ -53,7 +53,7 @@ * software in accordance with the terms specified in this * license. * - * RCS: @(#) $Id: tkMacOSXEntry.c,v 1.12 2007/06/29 03:20:01 das Exp $ + * RCS: @(#) $Id: tkMacOSXEntry.c,v 1.13 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -197,7 +197,9 @@ TkpDrawEntryBorderAndFocus(Entry *entryPtr, Drawable d, int isSpinbox) } else { drawState = kThemeStateActive; } - TkMacOSXSetupDrawingContext(d, NULL, 0, &dc); + if (!TkMacOSXSetupDrawingContext(d, NULL, 0, &dc)) { + return 0; + } DrawThemeEditTextFrame(&bounds, drawState); if (entryPtr->flags & GOT_FOCUS) { /* @@ -307,7 +309,9 @@ TkpDrawSpinboxButtons(Spinbox *sbPtr, Drawable d) rects[0].height = Tk_Height(tkwin); XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1); - TkMacOSXSetupDrawingContext(d, NULL, 0, &dc); + if (!TkMacOSXSetupDrawingContext(d, NULL, 0, &dc)) { + return 0; + } ChkErr(DrawThemeButton, &inBounds, inKind, &inNewInfo, inPrevInfo, inEraseProc, inLabelProc, inUserData); TkMacOSXRestoreDrawingContext(&dc); diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index fdd522a..c744ac8 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -35,7 +35,7 @@ * that such fonts can not be used for controls, because controls * definitely require a family id (this assertion needs testing). * - * RCS: @(#) $Id: tkMacOSXFont.c,v 1.28 2007/06/29 03:20:01 das Exp $ + * RCS: @(#) $Id: tkMacOSXFont.c,v 1.29 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -1054,8 +1054,10 @@ TkpDrawCharsInContext( Tcl_DString runString; #endif - TkMacOSXSetupDrawingContext(drawable, gc, tkMacOSXUseCGDrawing, - &drawingContext); + if (!TkMacOSXSetupDrawingContext(drawable, gc, tkMacOSXUseCGDrawing, + &drawingContext)) { + return; + } #if 0 /* diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index 9396902..458e003 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXInt.h,v 1.29 2007/08/23 10:44:57 das Exp $ + * RCS: @(#) $Id: tkMacOSXInt.h,v 1.30 2007/10/12 03:14:48 das Exp $ */ #ifndef _TKMACINT @@ -39,9 +39,9 @@ struct TkWindowPrivate { ControlRef rootControl; int xOff; /* X offset from toplevel window */ int yOff; /* Y offset from toplevel window */ - RgnHandle clipRgn; /* Visible region of window */ - RgnHandle aboveClipRgn; /* Visible region of window & its children */ - RgnHandle drawRgn; /* Clipped drawing region */ + HIShapeRef visRgn; /* Visible region of window */ + HIShapeRef aboveVisRgn; /* Visible region of window & its children */ + CGRect drawRect; /* Clipped drawing rect */ int referenceCount; /* Don't delete toplevel until children are * gone. */ struct TkWindowPrivate *toplevel; @@ -71,6 +71,7 @@ typedef struct TkMacOSXWindowList { #define TK_HOST_EXISTS 0x04 #define TK_DRAWN_UNDER_MENU 0x08 #define TK_CLIPPED_DRAW 0x10 +#define TK_IS_PIXMAP 0x20 /* * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags @@ -165,6 +166,8 @@ MODULE_SCOPE int XSetClipRectangles(Display *d, GC gc, int clip_x_origin, #endif MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x, int y, int width, int height); +MODULE_SCOPE void TkpRetainRegion(TkRegion r); +MODULE_SCOPE void TkpReleaseRegion(TkRegion r); /* * Include the stubbed internal platform-specific API. diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index 35672b7..ef069f8 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXMenu.c,v 1.42 2007/06/29 03:20:01 das Exp $ + * RCS: @(#) $Id: tkMacOSXMenu.c,v 1.43 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -343,10 +343,11 @@ DrawThemeText( cmdKeyBaseline); bounds = &adjustedBounds; } - TkMacOSXSetupDrawingContext(d, gc, 1, &dc); - ChkErr(DrawThemeTextBox, string, font, drawState, false, bounds, just, - dc.context); - TkMacOSXRestoreDrawingContext(&dc); + if (TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) { + ChkErr(DrawThemeTextBox, string, font, drawState, false, bounds, just, + dc.context); + TkMacOSXRestoreDrawingContext(&dc); + } } /* @@ -2702,9 +2703,10 @@ DrawMenuSeparator( r.left = x; r.bottom = y + height; r.right = x + width; - TkMacOSXSetupDrawingContext(d, gc, 1, &dc); - ChkErr(DrawThemeMenuSeparator, &r); - TkMacOSXRestoreDrawingContext(&dc); + if (TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) { + ChkErr(DrawThemeMenuSeparator, &r); + TkMacOSXRestoreDrawingContext(&dc); + } } #ifdef USE_TK_MDEF @@ -3983,9 +3985,9 @@ TkpMenuInit(void) macMDEFDrawable.winPtr = NULL; macMDEFDrawable.xOff = 0; macMDEFDrawable.yOff = 0; - macMDEFDrawable.clipRgn = NULL; - macMDEFDrawable.aboveClipRgn = NULL; - macMDEFDrawable.drawRgn = NewRgn(); + macMDEFDrawable.visRgn = NULL; + macMDEFDrawable.aboveVisRgn = NULL; + macMDEFDrawable.drawRect = CGRectNull; macMDEFDrawable.referenceCount = 0; macMDEFDrawable.toplevel = NULL; macMDEFDrawable.flags = 0; diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 1861c16..3951e52 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXPrivate.h,v 1.2 2007/08/23 10:44:57 das Exp $ + * RCS: @(#) $Id: tkMacOSXPrivate.h,v 1.3 2007/10/12 03:14:48 das Exp $ */ #ifndef _TKMACPRIV @@ -252,6 +252,7 @@ typedef struct TkMacOSXDrawingContext { CGrafPtr port, savePort; ThemeDrawingState saveState; RgnHandle saveClip; + HIShapeRef clipRgn; PixPatHandle penPat; Rect portBounds; Boolean portChanged; @@ -265,6 +266,33 @@ MODULE_SCOPE RgnHandle tkMacOSXtmpQdRgn; MODULE_SCOPE int tkMacOSXUseCGDrawing; /* + * Prototypes for TkMacOSXRegion.c. + */ + +#if 0 +MODULE_SCOPE void TkMacOSXEmtpyRegion(TkRegion r); +MODULE_SCOPE int TkMacOSXIsEmptyRegion(TkRegion r); +#endif +MODULE_SCOPE HIShapeRef TkMacOSXGetNativeRegion(TkRegion r); +MODULE_SCOPE void TkMacOSXSetWithNativeRegion(TkRegion r, HIShapeRef rgn); +MODULE_SCOPE void TkMacOSXOffsetRegion(TkRegion r, short dx, short dy); +MODULE_SCOPE HIShapeRef TkMacOSXHIShapeCreateEmpty(void); +MODULE_SCOPE HIMutableShapeRef TkMacOSXHIShapeCreateMutableWithRect( + const CGRect *inRect); +MODULE_SCOPE OSStatus TkMacOSXHIShapeSetWithShape( + HIMutableShapeRef inDestShape, HIShapeRef inSrcShape); +#if 0 +MODULE_SCOPE OSStatus TkMacOSXHIShapeSetWithRect(HIMutableShapeRef inShape, + const CGRect *inRect); +#endif +MODULE_SCOPE OSStatus TkMacOSHIShapeDifferenceWithRect( + HIMutableShapeRef inShape, const CGRect *inRect); +MODULE_SCOPE OSStatus TkMacOSHIShapeUnionWithRect(HIMutableShapeRef inShape, + const CGRect *inRect); +MODULE_SCOPE OSStatus TkMacOSHIShapeUnion(HIShapeRef inShape1, + HIShapeRef inShape2, HIMutableShapeRef outResult); + +/* * Prototypes of TkAqua internal procs. */ @@ -285,8 +313,8 @@ MODULE_SCOPE int TkMacOSXIsWindowZoomed(TkWindow *winPtr); MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window); MODULE_SCOPE EventModifiers TkMacOSXModifierState(void); MODULE_SCOPE int TkMacOSXSetupDrawingContext(Drawable d, GC gc, int useCG, - TkMacOSXDrawingContext *dc); -MODULE_SCOPE void TkMacOSXRestoreDrawingContext(TkMacOSXDrawingContext *dc); + TkMacOSXDrawingContext *dcPtr); +MODULE_SCOPE void TkMacOSXRestoreDrawingContext(TkMacOSXDrawingContext *dcPtr); MODULE_SCOPE void TkMacOSXSetColorInPort(unsigned long pixel, int fg, PixPatHandle penPat, CGrafPtr port); MODULE_SCOPE void TkMacOSXSetColorInContext(unsigned long pixel, @@ -303,5 +331,7 @@ MODULE_SCOPE int TkMacOSXMakeFullscreen(TkWindow *winPtr, WindowRef window, MODULE_SCOPE void TkMacOSXEnterExitFullscreen(TkWindow *winPtr, int active); MODULE_SCOPE void TkMacOSXBringWindowForward(WindowRef wRef); MODULE_SCOPE WindowRef TkMacOSXDrawableWindow(Drawable drawable); +MODULE_SCOPE void TkMacOSXWinCGBounds(TkWindow *winPtr, CGRect *bounds); +MODULE_SCOPE HIShapeRef TkMacOSXGetClipRgn(Drawable drawable); #endif /* _TKMACPRIV */ diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c index e2252da..f839a15 100644 --- a/macosx/tkMacOSXRegion.c +++ b/macosx/tkMacOSXRegion.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXRegion.c,v 1.9 2007/06/29 03:20:02 das Exp $ + * RCS: @(#) $Id: tkMacOSXRegion.c,v 1.10 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -36,7 +36,7 @@ TkRegion TkCreateRegion(void) { - return (TkRegion) NewRgn(); + return (TkRegion) HIShapeCreateMutable(); } /* @@ -60,7 +60,9 @@ void TkDestroyRegion( TkRegion r) { - DisposeRgn((RgnHandle) r); + if (r) { + CFRelease(r); + } } /* @@ -86,7 +88,8 @@ TkIntersectRegion( TkRegion srb, TkRegion dr_return) { - SectRgn((RgnHandle) sra, (RgnHandle) srb, (RgnHandle) dr_return); + ChkErr(HIShapeIntersect, (HIShapeRef) sra, (HIShapeRef) srb, + (HIMutableShapeRef) dr_return); } /* @@ -112,7 +115,8 @@ TkSubtractRegion( TkRegion srb, TkRegion dr_return) { - DiffRgn((RgnHandle) sra, (RgnHandle) srb, (RgnHandle) dr_return); + ChkErr(HIShapeDifference, (HIShapeRef) sra, (HIShapeRef) srb, + (HIMutableShapeRef) dr_return); } /* @@ -139,12 +143,19 @@ TkUnionRectWithRegion( TkRegion src_region, TkRegion dest_region_return) { - TkMacOSXCheckTmpQdRgnEmpty(); - SetRectRgn(tkMacOSXtmpQdRgn, rectangle->x, rectangle->y, - rectangle->x + rectangle->width, rectangle->y + rectangle->height); - UnionRgn((RgnHandle) src_region, tkMacOSXtmpQdRgn, - (RgnHandle) dest_region_return); - SetEmptyRgn(tkMacOSXtmpQdRgn); + const CGRect r = CGRectMake(rectangle->x, rectangle->y, + rectangle->width, rectangle->height); + + if (src_region == dest_region_return) { + ChkErr(TkMacOSHIShapeUnionWithRect, + (HIMutableShapeRef) dest_region_return, &r); + } else { + HIShapeRef rectRgn = HIShapeCreateWithRect(&r); + + ChkErr(TkMacOSHIShapeUnion, rectRgn, (HIShapeRef) src_region, + (HIMutableShapeRef) dest_region_return); + CFRelease(rectRgn); + } } /* @@ -156,7 +167,8 @@ TkUnionRectWithRegion( * XRectInRegion. See X window documentation for more details. * * Results: - * Returns one of: RectangleOut, RectangleIn, RectanglePart. + * Returns RectanglePart or RectangleOut. Note that this is not a + * complete implementation since it doesn't test for RectangleIn. * * Side effects: * None. @@ -173,18 +185,40 @@ TkRectInRegion( unsigned int height) { int result; + const CGRect r = CGRectMake(x, y, width, height); - TkMacOSXCheckTmpQdRgnEmpty(); - SetRectRgn(tkMacOSXtmpQdRgn, x, y, x + width, y + height); - SectRgn((RgnHandle) region, tkMacOSXtmpQdRgn, tkMacOSXtmpQdRgn); - if (EmptyRgn(tkMacOSXtmpQdRgn)) { - result = RectangleOut; - } else if (EqualRgn((RgnHandle) region, tkMacOSXtmpQdRgn)) { - result = RectangleIn; - } else { - result = RectanglePart; - } - SetEmptyRgn(tkMacOSXtmpQdRgn); + TK_IF_MAC_OS_X_API (4, HIShapeIntersectsRect, + result = HIShapeIntersectsRect((HIShapeRef) region, &r) ? + RectanglePart : RectangleOut; + ) TK_ELSE_MAC_OS_X (4, + HIShapeRef rectRgn = HIShapeCreateWithRect(&r); + HIShapeRef sectRgn = HIShapeCreateIntersection((HIShapeRef) region, + rectRgn); + +#if 1 + result = !HIShapeIsEmpty(sectRgn) ? RectanglePart : RectangleOut; +#else + /* + * More expensive full implementation that tests for RectangleIn, + * unused by Tk at present. + */ + + if (!HIShapeIsEmpty(sectRgn)) { + HIShapeRef diffRgn = HIShapeCreateDifference(rectRgn, sectRgn); + + if (HIShapeIsEmpty(diffRgn)) { + result = RectangleIn; + } else { + result = RectanglePart; + } + CFRelease(diffRgn); + } else { + result = RectangleOut; + } +#endif + CFRelease(sectRgn); + CFRelease(rectRgn); + ) TK_ENDIF return result; } @@ -210,13 +244,13 @@ TkClipBox( TkRegion r, XRectangle* rect_return) { - Rect rect; - - GetRegionBounds((RgnHandle) r,&rect); - rect_return->x = rect.left; - rect_return->y = rect.top; - rect_return->width = rect.right-rect.left; - rect_return->height = rect.bottom-rect.top; + CGRect rect; + + HIShapeGetBounds((HIShapeRef) r, &rect); + rect_return->x = rect.origin.x; + rect_return->y = rect.origin.y; + rect_return->width = rect.size.width; + rect_return->height = rect.size.height; } /* @@ -278,3 +312,317 @@ TkpBuildRegionFromAlphaData( dataPtr += lineStride; } } + +/* + *---------------------------------------------------------------------- + * + * TkpRetainRegion -- + * + * Increases reference count of region. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpRetainRegion( + TkRegion r) +{ + CFRetain(r); +} + +/* + *---------------------------------------------------------------------- + * + * TkpReleaseRegion -- + * + * Decreases reference count of region. + * + * Results: + * None. + * + * Side effects: + * May free memory. + * + *---------------------------------------------------------------------- + */ + +void +TkpReleaseRegion( + TkRegion r) +{ + CFRelease(r); +} +#if 0 + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXEmtpyRegion -- + * + * Set region to emtpy. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXEmtpyRegion( + TkRegion r) +{ + ChkErr(HIShapeSetEmpty, (HIMutableShapeRef) r); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXIsEmptyRegion -- + * + * Return native region for given tk region. + * + * Results: + * 1 if empty, 0 otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXIsEmptyRegion( + TkRegion r) +{ + return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0; +} +#endif + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetNativeRegion -- + * + * Return native region for given tk region. + * + * Results: + * Native region, CFRelease when done. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +HIShapeRef +TkMacOSXGetNativeRegion( + TkRegion r) +{ + return (HIShapeRef) CFRetain(r); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXSetWithNativeRegion -- + * + * Set region to the native region. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXSetWithNativeRegion( + TkRegion r, + HIShapeRef rgn) +{ + ChkErr(TkMacOSXHIShapeSetWithShape, (HIMutableShapeRef) r, rgn); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXOffsetRegion -- + * + * Offsets region by given distances. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXOffsetRegion( + TkRegion r, + short dx, + short dy) +{ + ChkErr(HIShapeOffset, (HIMutableShapeRef) r, dx, dy); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXHIShapeCreateEmpty, TkMacOSXHIShapeCreateMutableWithRect, + * TkMacOSXHIShapeSetWithShape, TkMacOSXHIShapeSetWithRect, + * TkMacOSHIShapeDifferenceWithRect, TkMacOSHIShapeUnionWithRect, + * TkMacOSHIShapeUnion -- + * + * Wrapper functions for missing/buggy HIShape API + * + *---------------------------------------------------------------------- + */ + +HIShapeRef +TkMacOSXHIShapeCreateEmpty(void) +{ + HIShapeRef result; + + TK_IF_MAC_OS_X_API (4, HIShapeCreateEmpty, + result = HIShapeCreateEmpty(); + ) TK_ELSE_MAC_OS_X (4, + static HIShapeRef emptyRgn = NULL; + + if (!emptyRgn) { + HIMutableShapeRef rgn = HIShapeCreateMutable(); + + emptyRgn = HIShapeCreateCopy(rgn); + CFRelease(rgn); + } + result = HIShapeCreateCopy(emptyRgn); + ) TK_ENDIF + + return result; +} + +HIMutableShapeRef +TkMacOSXHIShapeCreateMutableWithRect( + const CGRect *inRect) +{ + HIMutableShapeRef result; + + TK_IF_MAC_OS_X_API (5, HIShapeCreateMutableWithRect, + result = HIShapeCreateMutableWithRect(inRect); + ) TK_ELSE_MAC_OS_X (5, + HIShapeRef rgn = HIShapeCreateWithRect(inRect); + + result = HIShapeCreateMutableCopy(rgn); + CFRelease(rgn); + ) TK_ENDIF + + return result; +} + +OSStatus +TkMacOSXHIShapeSetWithShape( + HIMutableShapeRef inDestShape, + HIShapeRef inSrcShape) +{ + OSStatus result; + + TK_IF_MAC_OS_X_API (5, HIShapeSetWithShape, + result = HIShapeSetWithShape(inDestShape, inSrcShape); + ) TK_ELSE_MAC_OS_X (5, + result = HIShapeSetEmpty(inDestShape); + if (result == noErr) { + result = HIShapeDifference(inSrcShape, inDestShape, inDestShape); + } + ) TK_ENDIF + + return result; +} + +#if 0 +OSStatus +TkMacOSXHIShapeSetWithRect( + HIMutableShapeRef inShape, + const CGRect *inRect) +{ + OSStatus result; + HIShapeRef rgn = HIShapeCreateWithRect(inRect); + + result = TkMacOSXHIShapeSetWithShape(inShape, rgn); + CFRelease(rgn); + + return result; +} +#endif + +OSStatus +TkMacOSHIShapeDifferenceWithRect( + HIMutableShapeRef inShape, + const CGRect *inRect) +{ + OSStatus result; + HIShapeRef rgn = HIShapeCreateWithRect(inRect); + + result = HIShapeDifference(inShape, rgn, inShape); + CFRelease(rgn); + + return result; +} + +OSStatus +TkMacOSHIShapeUnionWithRect( + HIMutableShapeRef inShape, + const CGRect *inRect) +{ + OSStatus result; + + TK_IF_MAC_OS_X_API (5, HIShapeUnionWithRect, + result = HIShapeUnionWithRect(inShape, inRect); + ) TK_ELSE_MAC_OS_X (5, + HIShapeRef rgn = HIShapeCreateWithRect(inRect); + + result = TkMacOSHIShapeUnion(rgn, inShape, inShape); + CFRelease(rgn); + ) TK_ENDIF + + return result; +} + +OSStatus +TkMacOSHIShapeUnion( + HIShapeRef inShape1, + HIShapeRef inShape2, + HIMutableShapeRef outResult) +{ + OSStatus result; + + TK_IF_HI_TOOLBOX (4, + result = HIShapeUnion(inShape1, inShape2, outResult); + ) TK_ELSE_HI_TOOLBOX (4, + /* Workaround HIShapeUnion bug in 10.3 and earlier */ + HIShapeRef rgn = HIShapeCreateCopy(outResult); + + result = HIShapeUnion(inShape1, inShape2, (HIMutableShapeRef) rgn); + if (result == noErr) { + result = HIShapeSetEmpty(outResult); + if (result == noErr) { + result = HIShapeDifference(rgn, outResult, outResult); + } + } + CFRelease(rgn); + ) TK_ENDIF + + return result; +} diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 46d299d..6810519 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.23 2007/06/29 03:20:02 das Exp $ + * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.24 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -90,9 +90,12 @@ XDestroyWindow( } } } - DisposeRgn(macWin->clipRgn); - DisposeRgn(macWin->aboveClipRgn); - DisposeRgn(macWin->drawRgn); + if (macWin->visRgn) { + CFRelease(macWin->visRgn); + } + if (macWin->aboveVisRgn) { + CFRelease(macWin->aboveVisRgn); + } /* * Delete the Mac window and remove it from the windowTable. @@ -140,9 +143,12 @@ XDestroyWindow( if (macWin->winPtr->parentPtr != NULL) { TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr); } - DisposeRgn(macWin->clipRgn); - DisposeRgn(macWin->aboveClipRgn); - DisposeRgn(macWin->drawRgn); + if (macWin->visRgn) { + CFRelease(macWin->visRgn); + } + if (macWin->aboveVisRgn) { + CFRelease(macWin->aboveVisRgn); + } if (macWin->toplevel->referenceCount == 0) { ckfree((char *) macWin->toplevel); @@ -690,15 +696,16 @@ TkMacOSXUpdateClipRgn( TkWindow *win2Ptr; if (Tk_IsMapped(winPtr)) { - Rect bounds; - RgnHandle rgn = macWin->aboveClipRgn; + int rgnChanged = 0; + CGRect bounds; + HIMutableShapeRef rgn; /* * Start with a region defined by the window bounds. */ - TkMacOSXWinBounds(winPtr, &bounds); - RectRgn(rgn, &bounds); + TkMacOSXWinCGBounds(winPtr, &bounds); + rgn = TkMacOSXHIShapeCreateMutableWithRect(&bounds); /* * Clip away the area of any windows that may obscure this @@ -715,9 +722,9 @@ TkMacOSXUpdateClipRgn( if (!Tk_IsTopLevel(winPtr)) { TkMacOSXUpdateClipRgn(winPtr->parentPtr); - TkMacOSXCheckTmpQdRgnEmpty(); if (winPtr->parentPtr) { - SectRgn(rgn, winPtr->parentPtr->privatePtr->aboveClipRgn, + ChkErr(HIShapeIntersect, + winPtr->parentPtr->privatePtr->aboveVisRgn, rgn, rgn); } win2Ptr = winPtr; @@ -725,46 +732,62 @@ TkMacOSXUpdateClipRgn( if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) { continue; } - TkMacOSXWinBounds(win2Ptr, &bounds); - RectRgn(tkMacOSXtmpQdRgn, &bounds); - DiffRgn(rgn, tkMacOSXtmpQdRgn, rgn); + TkMacOSXWinCGBounds(win2Ptr, &bounds); + ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds); } } else if (Tk_IsEmbedded(winPtr)) { win2Ptr = TkpGetOtherWindow(winPtr); if (win2Ptr) { TkMacOSXUpdateClipRgn(win2Ptr); - TkMacOSXCheckTmpQdRgnEmpty(); - SectRgn(rgn, win2Ptr->privatePtr->aboveClipRgn, rgn); + ChkErr(HIShapeIntersect, + win2Ptr->privatePtr->aboveVisRgn, rgn, rgn); } else if (tkMacOSXEmbedHandler != NULL) { + HIShapeRef visRgn; + TkMacOSXCheckTmpQdRgnEmpty(); tkMacOSXEmbedHandler->getClipProc((Tk_Window) winPtr, tkMacOSXtmpQdRgn); - SectRgn(rgn, tkMacOSXtmpQdRgn, rgn); + visRgn = HIShapeCreateWithQDRgn(tkMacOSXtmpQdRgn); + SetEmptyRgn(tkMacOSXtmpQdRgn); + ChkErr(HIShapeIntersect, visRgn, rgn, rgn); } /* * TODO: Here we should handle out of process embedding. */ + } else if (winPtr->wmInfoPtr->attributes & + kWindowResizableAttribute) { + HIViewRef growBoxView; + OSErr err = HIViewFindByID(HIViewGetRoot( + TkMacOSXDrawableWindow(winPtr->window)), + kHIViewWindowGrowBoxID, &growBoxView); + + if (err == noErr) { + ChkErr(HIViewGetFrame, growBoxView, &bounds); + bounds = CGRectOffset(bounds, + -winPtr->wmInfoPtr->xInParent, + -winPtr->wmInfoPtr->yInParent); + ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds); + } } + macWin->aboveVisRgn = HIShapeCreateCopy(rgn); /* - * The final clip region is the aboveClip region (or visible + * The final clip region is the aboveVis region (or visible * region) minus all the children of this window. * If the window is a container, we must also subtract the region * of the embedded window. */ - rgn = macWin->clipRgn; - CopyRgn(macWin->aboveClipRgn, rgn); win2Ptr = winPtr->childList; while (win2Ptr) { if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) { win2Ptr = win2Ptr->nextPtr; continue; } - TkMacOSXWinBounds(win2Ptr, &bounds); - RectRgn(tkMacOSXtmpQdRgn, &bounds); - DiffRgn(rgn, tkMacOSXtmpQdRgn, rgn); + TkMacOSXWinCGBounds(win2Ptr, &bounds); + ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds); + rgnChanged = 1; win2Ptr = win2Ptr->nextPtr; } @@ -772,9 +795,9 @@ TkMacOSXUpdateClipRgn( win2Ptr = TkpGetOtherWindow(winPtr); if (win2Ptr) { if (Tk_IsMapped(win2Ptr)) { - TkMacOSXWinBounds(win2Ptr, &bounds); - RectRgn(tkMacOSXtmpQdRgn, &bounds); - DiffRgn(rgn, tkMacOSXtmpQdRgn, rgn); + TkMacOSXWinCGBounds(win2Ptr, &bounds); + ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds); + rgnChanged = 1; } } @@ -782,7 +805,16 @@ TkMacOSXUpdateClipRgn( * TODO: Here we should handle out of process embedding. */ } - SetEmptyRgn(tkMacOSXtmpQdRgn); + if (rgnChanged) { + HIShapeRef diffRgn = HIShapeCreateDifference( + macWin->aboveVisRgn, rgn); + + if (!HIShapeIsEmpty(diffRgn)) { + macWin->visRgn = HIShapeCreateCopy(rgn); + } + CFRelease(diffRgn); + } + CFRelease(rgn); } else { /* * An unmapped window has empty clip regions to prevent any @@ -798,13 +830,15 @@ TkMacOSXUpdateClipRgn( TkMacOSXUpdateClipRgn(win2Ptr); } } - SetEmptyRgn(macWin->aboveClipRgn); - SetEmptyRgn(macWin->clipRgn); + macWin->aboveVisRgn = TkMacOSXHIShapeCreateEmpty(); + } + if (!macWin->visRgn) { + macWin->visRgn = HIShapeCreateCopy(macWin->aboveVisRgn); } macWin->flags &= ~TK_CLIP_INVALID; #ifdef TK_MAC_DEBUG_CLIP_REGIONS - TkMacOSXDebugFlashRegion((Drawable) macWin, macWin->clipRgn); + TkMacOSXDebugFlashRegion((Drawable) macWin, macWin->visRgn); #endif /* TK_MAC_DEBUG_CLIP_REGIONS */ } } @@ -830,10 +864,16 @@ RgnHandle TkMacOSXVisableClipRgn( TkWindow *winPtr) { + static RgnHandle visQdRgn = NULL; + + if (visQdRgn == NULL) { + visQdRgn = NewRgn(); + } if (winPtr->privatePtr->flags & TK_CLIP_INVALID) { TkMacOSXUpdateClipRgn(winPtr); } - return winPtr->privatePtr->clipRgn; + ChkErr(HIShapeGetAsQDRgn, winPtr->privatePtr->visRgn, visQdRgn); + return visQdRgn; } /* @@ -860,15 +900,18 @@ TkMacOSXInvalidateWindow( * TK_PARENT_WINDOW */ { WindowRef windowRef; - RgnHandle rgn; + HIShapeRef rgn; windowRef = TkMacOSXDrawableWindow((Drawable)macWin); if (macWin->flags & TK_CLIP_INVALID) { TkMacOSXUpdateClipRgn(macWin->winPtr); } - rgn = (flag == TK_WINDOW_ONLY) ? macWin->clipRgn : macWin->aboveClipRgn; - if (!EmptyRgn(rgn)) { - InvalWindowRgn(windowRef, rgn); + rgn = (flag == TK_WINDOW_ONLY) ? macWin->visRgn : macWin->aboveVisRgn; + if (!HIShapeIsEmpty(rgn)) { + TkMacOSXCheckTmpQdRgnEmpty(); + ChkErr(HIShapeGetAsQDRgn, rgn, tkMacOSXtmpQdRgn); + InvalWindowRgn(windowRef, tkMacOSXtmpQdRgn); + SetEmptyRgn(tkMacOSXtmpQdRgn); } #ifdef TK_MAC_DEBUG_CLIP_REGIONS TkMacOSXDebugFlashRegion((Drawable) macWin, rgn); @@ -898,7 +941,7 @@ TkMacOSXDrawableWindow( MacDrawable *macWin = (MacDrawable *) drawable; WindowRef result = NULL; - if (!macWin || !macWin->clipRgn) { + if (!macWin || macWin->flags & TK_IS_PIXMAP) { result = NULL; } else { result = GetWindowFromPort(TkMacOSXGetDrawablePort(drawable)); @@ -930,8 +973,7 @@ TkMacOSXGetDrawablePort( CGrafPtr resultPort = NULL; if (macWin) { - resultPort = macWin->grafPtr; - if (macWin->toplevel && macWin->clipRgn) { + if (macWin->toplevel) { /* * If the Drawable is in an embedded window, use the Port of its * container. @@ -957,7 +999,7 @@ TkMacOSXGetDrawablePort( (Tk_Window) macWin->winPtr); } - if (resultPort == NULL) { + if (!resultPort) { /* * FIXME: So far as I can tell, the only time that this * happens is when we are tearing down an embedded child @@ -973,6 +1015,8 @@ TkMacOSXGetDrawablePort( } else { resultPort = macWin->toplevel->grafPtr; } + } else { + resultPort = macWin->grafPtr; } } @@ -1062,8 +1106,14 @@ TkMacOSXInvalClipRgns( } macWin->flags |= TK_CLIP_INVALID; - SetEmptyRgn(macWin->aboveClipRgn); - SetEmptyRgn(macWin->clipRgn); + if (macWin->visRgn) { + CFRelease(macWin->visRgn); + macWin->visRgn = NULL; + } + if (macWin->aboveVisRgn) { + CFRelease(macWin->aboveVisRgn); + macWin->aboveVisRgn = NULL; + } /* * Invalidate clip regions for all children & @@ -1127,6 +1177,36 @@ TkMacOSXWinBounds( /* *---------------------------------------------------------------------- * + * TkMacOSXWinCGBounds -- + * + * Given a Tk window this function determines the windows + * bounds in relation to the Macintosh window's coordinate + * system. This is also the same coordinate system as the + * Tk toplevel window in which this window is contained. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXWinCGBounds( + TkWindow *winPtr, + CGRect *bounds) +{ + bounds->origin.x = winPtr->privatePtr->xOff; + bounds->origin.y = winPtr->privatePtr->yOff; + bounds->size.width = winPtr->changes.width; + bounds->size.height = winPtr->changes.height; +} + +/* + *---------------------------------------------------------------------- + * * UpdateOffsets -- * * Updates the X & Y offsets of the given TkWindow from the @@ -1207,9 +1287,6 @@ Tk_GetPixmap( int height, int depth) /* Bits per pixel for pixmap. */ { - QDErr err; - GWorldPtr gWorld; - Rect bounds = {0, 0, height, width}; MacDrawable *macPix; if (display != NULL) { @@ -1219,24 +1296,30 @@ Tk_GetPixmap( macPix->winPtr = NULL; macPix->xOff = 0; macPix->yOff = 0; - macPix->clipRgn = NULL; - macPix->aboveClipRgn = NULL; - macPix->drawRgn = NULL; + macPix->visRgn = NULL; + macPix->aboveVisRgn = NULL; + macPix->drawRect = CGRectNull; macPix->referenceCount = 0; macPix->toplevel = NULL; - macPix->flags = 0; + macPix->flags = TK_IS_PIXMAP; macPix->grafPtr = NULL; macPix->context = NULL; + { + OSStatus err; + GWorldPtr gWorld; + Rect bounds = {0, 0, height, width}; - err = ChkErr(NewGWorld, &gWorld, depth == 1 ? 1 : 0, &bounds, NULL, NULL, 0 + err = ChkErr(NewGWorld, &gWorld, depth == 1 ? 1 : 0, &bounds, NULL, + NULL, 0 #ifdef __LITTLE_ENDIAN__ - | kNativeEndianPixMap + | kNativeEndianPixMap #endif - ); - if (err != noErr) { - Tcl_Panic("Out of memory: NewGWorld failed in Tk_GetPixmap"); + ); + if (err != noErr) { + Tcl_Panic("Out of memory: NewGWorld failed in Tk_GetPixmap"); + } + macPix->grafPtr = gWorld; } - macPix->grafPtr = gWorld; return (Pixmap) macPix; } diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 20b79f3..78e428f 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -54,7 +54,7 @@ * software in accordance with the terms specified in this * license. * - * RCS: @(#) $Id: tkMacOSXWindowEvent.c,v 1.28 2007/07/09 08:31:55 das Exp $ + * RCS: @(#) $Id: tkMacOSXWindowEvent.c,v 1.29 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -73,10 +73,10 @@ */ static int GenerateUpdateEvent(Window window); -static int GenerateUpdates(RgnHandle updateRgn, Rect *updateBounds, +static int GenerateUpdates(HIMutableShapeRef updateRgn, CGRect *updateBounds, TkWindow *winPtr); static int GenerateActivateEvents(Window window, int activeFlag); -static void ClearPort(CGrafPtr port, RgnHandle updateRgn); +static void ClearPort(CGrafPtr port, HIShapeRef updateRgn); /* @@ -430,12 +430,14 @@ TkMacOSXProcessWindowEvent( static int GenerateUpdateEvent(Window window) { - CGrafPtr destPort; WindowRef macWindow; TkDisplay *dispPtr; TkWindow *winPtr; int result = 0; - Rect updateBounds, bounds; + CGRect updateBounds; + HIShapeRef rgn; + HIMutableShapeRef updateRgn; + int dx, dy; dispPtr = TkGetDisplayList(); winPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, window); @@ -443,24 +445,37 @@ GenerateUpdateEvent(Window window) if (winPtr ==NULL ){ return result; } - TkMacOSXCheckTmpQdRgnEmpty(); - destPort = TkMacOSXGetDrawablePort(window); - macWindow = GetWindowFromPort(destPort); - ChkErr(GetWindowRegion, macWindow, kWindowUpdateRgn, tkMacOSXtmpQdRgn); - ChkErr(GetWindowBounds, macWindow, kWindowContentRgn, &bounds); - OffsetRgn(tkMacOSXtmpQdRgn, -bounds.left, -bounds.top); - SectRegionWithPortVisibleRegion(destPort, tkMacOSXtmpQdRgn); - GetRegionBounds(tkMacOSXtmpQdRgn, &updateBounds); + macWindow = TkMacOSXDrawableWindow(window); + TK_IF_MAC_OS_X_API (5, HIWindowCopyShape, + ChkErr(HIWindowCopyShape, macWindow, kWindowUpdateRgn, + kHICoordSpaceWindow, &rgn); + dx = -winPtr->wmInfoPtr->xInParent; + dy = -winPtr->wmInfoPtr->yInParent; + ) TK_ELSE_MAC_OS_X (5, + Rect bounds; + + TkMacOSXCheckTmpQdRgnEmpty(); + ChkErr(GetWindowRegion, macWindow, kWindowUpdateRgn, tkMacOSXtmpQdRgn); + rgn = HIShapeCreateWithQDRgn(tkMacOSXtmpQdRgn); + SetEmptyRgn(tkMacOSXtmpQdRgn); + ChkErr(GetWindowBounds, macWindow, kWindowContentRgn, &bounds); + dx = -bounds.left; + dy = -bounds.top; + ) TK_ENDIF + updateRgn = HIShapeCreateMutableCopy(rgn); + CFRelease(rgn); + ChkErr(HIShapeOffset, updateRgn, dx, dy); + HIShapeGetBounds(updateRgn, &updateBounds); #ifdef TK_MAC_DEBUG_CLIP_REGIONS - TkMacOSXDebugFlashRegion(window, tkMacOSXtmpQdRgn); + TkMacOSXDebugFlashRegion(window, updateRgn); #endif /* TK_MAC_DEBUG_CLIP_REGIONS */ BeginUpdate(macWindow); if (winPtr->wmInfoPtr->flags & WM_TRANSPARENT) { - ClearPort(destPort, tkMacOSXtmpQdRgn); + ClearPort(TkMacOSXGetDrawablePort(window), updateRgn); } - result = GenerateUpdates(tkMacOSXtmpQdRgn, &updateBounds, winPtr); + result = GenerateUpdates(updateRgn, &updateBounds, winPtr); EndUpdate(macWindow); - SetEmptyRgn(tkMacOSXtmpQdRgn); + CFRelease(updateRgn); if (result) { /* * Ensure there are no pending idle-time redraws that could prevent @@ -493,50 +508,51 @@ GenerateUpdateEvent(Window window) static int GenerateUpdates( - RgnHandle updateRgn, - Rect *updateBounds, + HIMutableShapeRef updateRgn, + CGRect *updateBounds, TkWindow *winPtr) { TkWindow *childPtr; XEvent event; - Rect bounds, damageBounds; - static RgnHandle damageRgn = NULL; - - TkMacOSXWinBounds(winPtr, &bounds); - if (bounds.top > updateBounds->bottom || - updateBounds->top > bounds.bottom || - bounds.left > updateBounds->right || - updateBounds->left > bounds.right) { - return 0; - } - if (!RectInRgn(&bounds, updateRgn)) { + CGRect bounds, damageBounds; + HIShapeRef boundsRgn, damageRgn; + + TkMacOSXWinCGBounds(winPtr, &bounds); + if (!CGRectIntersectsRect(bounds, *updateBounds)) { return 0; } + TK_IF_MAC_OS_X_API (4, HIShapeIntersectsRect, + if (!HIShapeIntersectsRect(updateRgn, &bounds)) { + return 0; + } + ) TK_ENDIF /* * Compute the bounding box of the area that the damage occured in. */ - if (damageRgn == NULL) { - damageRgn = NewRgn(); + boundsRgn = HIShapeCreateWithRect(&bounds); + damageRgn = HIShapeCreateIntersection(updateRgn, boundsRgn); + if (HIShapeIsEmpty(damageRgn)) { + CFRelease(damageRgn); + CFRelease(boundsRgn); + return 0; } - RectRgn(damageRgn, &bounds); - SectRgn(damageRgn, updateRgn, damageRgn); - GetRegionBounds(damageRgn, &damageBounds); - RectRgn(damageRgn, &bounds); - UnionRgn(damageRgn, updateRgn, updateRgn); - GetRegionBounds(updateRgn, updateBounds); - SetEmptyRgn(damageRgn); + HIShapeGetBounds(damageRgn, &damageBounds); + ChkErr(TkMacOSHIShapeUnion, boundsRgn, updateRgn, updateRgn); + HIShapeGetBounds(updateRgn, updateBounds); + CFRelease(damageRgn); + CFRelease(boundsRgn); event.xany.serial = Tk_Display(winPtr)->request; event.xany.send_event = false; event.xany.window = Tk_WindowId(winPtr); event.xany.display = Tk_Display(winPtr); event.type = Expose; - event.xexpose.x = damageBounds.left - bounds.left; - event.xexpose.y = damageBounds.top - bounds.top; - event.xexpose.width = damageBounds.right - damageBounds.left; - event.xexpose.height = damageBounds.bottom - damageBounds.top; + event.xexpose.x = damageBounds.origin.x - bounds.origin.x; + event.xexpose.y = damageBounds.origin.y - bounds.origin.y; + event.xexpose.width = damageBounds.size.width; + event.xexpose.height = damageBounds.size.height; event.xexpose.count = 0; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); @@ -945,7 +961,7 @@ Tk_MacOSXIsAppInFront(void) static void ClearPort( CGrafPtr port, - RgnHandle updateRgn) + HIShapeRef updateRgn) { CGContextRef context; Rect bounds; @@ -957,7 +973,8 @@ ClearPort( CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, bounds.bottom - bounds.top)); if (updateRgn) { - ClipCGContextToRegion(context, &bounds, updateRgn); + ChkErr(HIShapeReplacePathInCGContext, updateRgn, context); + CGContextEOClip(context); } rect = CGRectMake(0, 0, bounds.right, bounds.bottom); CGContextClearRect(context, rect); diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index de2f46b..c51509c 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXWm.c,v 1.56 2007/10/11 14:13:41 das Exp $ + * RCS: @(#) $Id: tkMacOSXWm.c,v 1.57 2007/10/12 03:14:48 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -5864,6 +5864,7 @@ ApplyWindowClassAttributeChanges( ChkErr(HIGrowBoxViewSetTransparent, growBoxView, true); } } + TkMacOSXInvalClipRgns((Tk_Window) winPtr); TkMacOSXInvalidateWindow((MacDrawable *)(winPtr->window), TK_PARENT_WINDOW); } diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 2606264..6294a5a 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -27,7 +27,7 @@ * top-level window, not to the Tk_Window. BoxToRect() * accounts for this. * - * RCS: @(#) $Id: ttkMacOSXTheme.c,v 1.8 2007/06/29 03:20:02 das Exp $ + * RCS: @(#) $Id: ttkMacOSXTheme.c,v 1.9 2007/10/12 03:14:49 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -35,7 +35,7 @@ #define BEGIN_DRAWING(d) { \ TkMacOSXDrawingContext dc; \ - TkMacOSXSetupDrawingContext((d), NULL, 0, &dc); + if (!TkMacOSXSetupDrawingContext((d), NULL, 0, &dc)) {return;} #define END_DRAWING \ TkMacOSXRestoreDrawingContext(&dc); } -- cgit v0.12