summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Walzer <kw@codebykevin.com>2015-04-07 01:12:45 (GMT)
committerKevin Walzer <kw@codebykevin.com>2015-04-07 01:12:45 (GMT)
commitccdac05dbacc3b62fc27a65c11c8bd1188daddf4 (patch)
tree95547ff6225666daa34552c1afc7ff7d112cc5a5
parente450f5762837d46e9c72791b8af7361838364291 (diff)
downloadtk-ccdac05dbacc3b62fc27a65c11c8bd1188daddf4.zip
tk-ccdac05dbacc3b62fc27a65c11c8bd1188daddf4.tar.gz
tk-ccdac05dbacc3b62fc27a65c11c8bd1188daddf4.tar.bz2
Further cleanup of scrolling, drawing, resize in Cocoa; thanks to Marc Culler for patches
-rw-r--r--generic/tkCanvas.c13
-rw-r--r--generic/tkInt.decls3
-rw-r--r--generic/tkIntPlatDecls.h5
-rw-r--r--generic/tkTextDisp.c30
-rw-r--r--macosx/tkMacOSXButton.c21
-rw-r--r--macosx/tkMacOSXDraw.c86
-rw-r--r--macosx/tkMacOSXInt.h2
-rw-r--r--macosx/tkMacOSXScrlbr.c59
-rw-r--r--macosx/tkMacOSXSubwindows.c59
-rw-r--r--macosx/tkMacOSXWindowEvent.c90
10 files changed, 253 insertions, 115 deletions
diff --git a/generic/tkCanvas.c b/generic/tkCanvas.c
index 8e14852..9c4d60a 100644
--- a/generic/tkCanvas.c
+++ b/generic/tkCanvas.c
@@ -2447,6 +2447,19 @@ DisplayCanvas(
goto done;
}
+#ifdef MAC_OSX_TK
+ /*
+ * If drawing is disabled, all we need to do is
+ * clear the REDRAW_PENDING flag.
+ */
+ TkWindow *winPtr = (TkWindow *)(canvasPtr->tkwin);
+ MacDrawable *macWin = winPtr->privatePtr;
+ if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){
+ canvasPtr->flags &= ~REDRAW_PENDING;
+ return;
+ }
+#endif
+
/*
* Choose a new current item if that is needed (this could cause event
* handlers to be invoked).
diff --git a/generic/tkInt.decls b/generic/tkInt.decls
index ebbadba..8924d68 100644
--- a/generic/tkInt.decls
+++ b/generic/tkInt.decls
@@ -1017,6 +1017,9 @@ declare 50 aqua {
declare 51 aqua {
void TkGenWMDestroyEvent(Tk_Window tkwin)
}
+declare 52 aqua {
+ TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag);
+}
# removed duplicate from tkPlat table (tk.decls)
#declare 52 aqua {
diff --git a/generic/tkIntPlatDecls.h b/generic/tkIntPlatDecls.h
index 3a2a8aa..3a4bdac 100644
--- a/generic/tkIntPlatDecls.h
+++ b/generic/tkIntPlatDecls.h
@@ -250,7 +250,8 @@ EXTERN int TkGenerateButtonEvent(int x, int y, Window window,
unsigned int state);
/* 51 */
EXTERN void TkGenWMDestroyEvent(Tk_Window tkwin);
-/* Slot 52 is reserved */
+/* 52 */
+EXTERN void TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag);
/* 53 */
EXTERN unsigned long TkpGetMS(void);
/* 54 */
@@ -395,7 +396,7 @@ typedef struct TkIntPlatStubs {
Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */
void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */
- void (*reserved52)(void);
+ void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */
unsigned long (*tkpGetMS) (void); /* 53 */
void * (*tkMacOSXDrawable) (Drawable drawable); /* 54 */
int (*tkpScanWindowId) (Tcl_Interp *interp, const char *string, Window *idPtr); /* 55 */
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index 95ea935..c3bcd5e 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -3948,7 +3948,6 @@ DisplayText(
* warnings. */
Tcl_Interp *interp;
-
if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
/*
* The widget has been deleted. Don't do anything.
@@ -3957,6 +3956,19 @@ DisplayText(
return;
}
+#ifdef MAC_OSX_TK
+ /*
+ * If drawing is disabled, all we need to do is
+ * clear the REDRAW_PENDING flag.
+ */
+ TkWindow *winPtr = (TkWindow *)(textPtr->tkwin);
+ MacDrawable *macWin = winPtr->privatePtr;
+ if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){
+ dInfoPtr->flags &= ~REDRAW_PENDING;
+ return;
+ }
+#endif
+
interp = textPtr->interp;
Tcl_Preserve(interp);
@@ -3964,14 +3976,6 @@ DisplayText(
Tcl_SetVar2(interp, "tk_textRelayout", NULL, "", TCL_GLOBAL_ONLY);
}
- if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
- /*
- * The widget has been deleted. Don't do anything.
- */
-
- goto end;
- }
-
if (!Tk_IsMapped(textPtr->tkwin) || (dInfoPtr->maxX <= dInfoPtr->x)
|| (dInfoPtr->maxY <= dInfoPtr->y)) {
UpdateDisplayInfo(textPtr);
@@ -3983,14 +3987,6 @@ DisplayText(
Tcl_SetVar2(interp, "tk_textRedraw", NULL, "", TCL_GLOBAL_ONLY);
}
- if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
- /*
- * The widget has been deleted. Don't do anything.
- */
-
- goto end;
- }
-
/*
* Choose a new current item if that is needed (this could cause event
* handlers to be invoked, hence the preserve/release calls and the loop,
diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c
index 725c211..59d394e 100644
--- a/macosx/tkMacOSXButton.c
+++ b/macosx/tkMacOSXButton.c
@@ -30,10 +30,10 @@
* Default insets for controls
*/
-#define DEF_INSET_LEFT 2
-#define DEF_INSET_RIGHT 2
-#define DEF_INSET_TOP 2
-#define DEF_INSET_BOTTOM 4
+#define DEF_INSET_LEFT 12
+#define DEF_INSET_RIGHT 12
+#define DEF_INSET_TOP 1
+#define DEF_INSET_BOTTOM 1
/*
* Some defines used to control what type of control is drawn.
@@ -318,8 +318,8 @@ TkpComputeButtonGeometry(
Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength,
butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
- txtWidth = butPtr->textWidth;
- txtHeight = butPtr->textHeight;
+ txtWidth = butPtr->textWidth + DEF_INSET_LEFT + DEF_INSET_RIGHT;
+ txtHeight = butPtr->textHeight + DEF_INSET_BOTTOM + DEF_INSET_TOP;
charWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
Tk_GetFontMetrics(butPtr->tkfont, &fm);
haveText = (txtWidth != 0 && txtHeight != 0);
@@ -647,7 +647,7 @@ DrawButtonImageAndText(
butPtr->textHeight, &x, &y);
x += butPtr->indicatorSpace;
Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout,
- x, y, 0, -1);
+ x, y - DEF_INSET_BOTTOM, 0, -1);
}
/*
@@ -807,9 +807,12 @@ TkMacOSXDrawButton(
hiinfo.animation.time.start = hiinfo.animation.time.current;
}
- HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, &contHIRec);
+ HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal,
+ &contHIRec);
+
TkMacOSXRestoreDrawingContext(&dc);
- ButtonContentDrawCB(&contHIRec, mbPtr->btnkind, &mbPtr->drawinfo, (MacButton *)mbPtr, 32, true);
+ ButtonContentDrawCB(&contHIRec, mbPtr->btnkind, &mbPtr->drawinfo,
+ (MacButton *)mbPtr, 32, true);
} else {
if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index 328f905..0f6d2f0 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -222,7 +222,8 @@ XCopyArea(
}
if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
- TkMacOSXDbgMsg("Failed to setup drawing context.");
+ return;
+ /*TkMacOSXDbgMsg("Failed to setup drawing context.");*/
}
if ( dc.context ) {
@@ -243,6 +244,8 @@ XCopyArea(
CGRectMake(src_x, src_y, width, height),
CGRectMake(dest_x, dest_y, width, height));
CFRelease(img);
+
+
} else {
TkMacOSXDbgMsg("Failed to construct CGImage.");
}
@@ -652,9 +655,9 @@ GetCGContextForDrawable(
CGColorSpaceRef colorspace = NULL;
CGBitmapInfo bitmapInfo =
#ifdef __LITTLE_ENDIAN__
- kCGBitmapByteOrder32Host;
+ kCGBitmapByteOrder32Host;
#else
- kCGBitmapByteOrderDefault;
+ kCGBitmapByteOrderDefault;
#endif
char *data;
CGRect bounds = CGRectMake(0, 0, macDraw->size.width,
@@ -731,6 +734,7 @@ DrawCGImage(
}
}
dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff);
+
if (CGImageIsMask(image)) {
/*CGContextSaveGState(context);*/
if (macDraw->flags & TK_IS_BW_PIXMAP) {
@@ -765,8 +769,8 @@ DrawCGImage(
dstBounds.size.width, dstBounds.size.height);
#else /* TK_MAC_DEBUG_IMAGE_DRAWING */
CGContextSaveGState(context);
- CGContextTranslateCTM(context,
- 0, dstBounds.origin.y + CGRectGetMaxY(dstBounds));
+ CGContextTranslateCTM(context, 0,
+ dstBounds.origin.y + CGRectGetMaxY(dstBounds));
CGContextScaleCTM(context, 1, -1);
CGContextDrawImage(context, dstBounds, image);
CGContextRestoreGState(context);
@@ -1478,10 +1482,9 @@ TkScrollWindow(
MacDrawable *macDraw = (MacDrawable *) drawable;
NSView *view = TkMacOSXDrawableView(macDraw);
CGRect srcRect, dstRect;
- HIShapeRef dmgRgn = NULL, extraRgn;
+ HIShapeRef dmgRgn = NULL, extraRgn = NULL;
NSRect bounds, visRect, scrollSrc, scrollDst;
- int result;
-
+ int result = 0;
if ( view ) {
/* Get the scroll area in NSView coordinates (origin at bottom left). */
@@ -1491,36 +1494,79 @@ TkScrollWindow(
bounds.size.height - height - (macDraw->yOff + y),
width, height);
scrollDst = NSOffsetRect(scrollSrc, dx, -dy);
+
/* Limit scrolling to the window content area. */
visRect = [view visibleRect];
scrollSrc = NSIntersectionRect(scrollSrc, visRect);
scrollDst = NSIntersectionRect(scrollDst, visRect);
-
if ( !NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst) ) {
/*
* Mark the difference between source and destination as damaged.
- * This region is described in the Tk coordinate system.
+ * This region is described in NSView coordinates (y=0 at the bottom)
+ * and converted to Tk coordinates later.
*/
- srcRect = CGRectMake(x, y, width, height);
- dstRect = CGRectOffset(srcRect, dx, dy);
+ srcRect = CGRectMake(x, y, width, height);
+ dstRect = CGRectOffset(srcRect, dx, dy);
+
+ /* Expand the rectangles slightly to avoid degeneracies. */
+ srcRect.origin.y -= 1;
+ srcRect.size.height += 2;
+ dstRect.origin.y += 1;
+ dstRect.size.height -= 2;
+
+ /* Compute the damage. */
dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
extraRgn = HIShapeCreateWithRect(&dstRect);
ChkErr(HIShapeDifference, dmgRgn, extraRgn, (HIMutableShapeRef) dmgRgn);
- CFRelease(extraRgn);
+ result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
+
+ /* Convert to Tk coordinates. */
+ TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
+ if (extraRgn) {
+ CFRelease(extraRgn);
+ }
/* Scroll the rectangle. */
[view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)];
+
+ /* Shift the Tk children which meet the source rectangle. */
+ TkWindow *winPtr = (TkWindow *)tkwin;
+ TkWindow *childPtr;
+ CGRect childBounds;
+ for (childPtr = winPtr->childList; childPtr != NULL; childPtr = childPtr->nextPtr) {
+ if (Tk_IsMapped(childPtr) && !Tk_IsTopLevel(childPtr)) {
+ TkMacOSXWinCGBounds(childPtr, &childBounds);
+ if (CGRectIntersectsRect(srcRect, childBounds)) {
+ MacDrawable *macChild = childPtr->privatePtr;
+ if (macChild) {
+ macChild->yOff += dy;
+ macChild->xOff += dx;
+ childPtr->changes.y = macChild->yOff;
+ childPtr->changes.x = macChild->xOff;
+ }
+ }
+ }
+ }
+
+ /* Queue up Expose events for the damage region. */
+ int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
+ [view generateExposeEvents:dmgRgn childrenOnly:1];
+ Tcl_SetServiceMode(oldMode);
+
+ /* Belt and suspenders: make the AppKit request a redraw
+ when it gets control again. */
+ [view setNeedsDisplay:YES];
}
+ } else {
+ dmgRgn = HIShapeCreateEmpty();
+ TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
}
- if ( dmgRgn == NULL ) {
- dmgRgn = HIShapeCreateEmpty();
+ if (dmgRgn) {
+ CFRelease(dmgRgn);
}
- TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
- result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
- CFRelease(dmgRgn);
return result;
}
@@ -1855,6 +1901,7 @@ TkpClipDrawableToRect(
CFRelease(macDraw->drawRgn);
macDraw->drawRgn = NULL;
}
+
if (width >= 0 && height >= 0) {
CGRect clipRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff,
width, height);
@@ -2002,7 +2049,7 @@ TkpDrawHighlightBorder (
* TkpDrawFrame --
*
* This procedure draws the rectangular frame area. If the user
- * has request themeing, it draws with a the background theme.
+ * has requested themeing, it draws with the background theme.
*
* Results:
* None.
@@ -2032,6 +2079,7 @@ TkpDrawFrame(
border = themedBorder;
}
}
+
Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
border, highlightWidth, highlightWidth,
Tk_Width(tkwin) - 2 * highlightWidth,
diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h
index 249d5cf..6971e26 100644
--- a/macosx/tkMacOSXInt.h
+++ b/macosx/tkMacOSXInt.h
@@ -86,7 +86,7 @@ typedef struct TkWindowPrivate MacDrawable;
#define TK_FOCUSED_VIEW 0x10
#define TK_IS_PIXMAP 0x20
#define TK_IS_BW_PIXMAP 0x40
-
+#define TK_DO_NOT_DRAW 0x80
/*
* I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags
* This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the
diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c
index bdb76af..4d4949f 100644
--- a/macosx/tkMacOSXScrlbr.c
+++ b/macosx/tkMacOSXScrlbr.c
@@ -26,6 +26,7 @@
#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum))
#endif /* __LP64__ */
+#define MOUNTAIN_LION_STYLE (NSAppKitVersionNumber < 1138)
/*
* Declaration of Mac specific scrollbar structure.
@@ -80,7 +81,6 @@ static void ScrollbarEventProc(ClientData clientData, XEvent *eventPtr);
static int ScrollbarPress(TkScrollbar *scrollPtr, XEvent *eventPtr);
static void UpdateControlValues(TkScrollbar *scrollPtr);
-
/*
*----------------------------------------------------------------------
*
@@ -137,7 +137,6 @@ TkpDisplayScrollbar(
register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
register Tk_Window tkwin = scrollPtr->tkwin;
-
if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
return;
}
@@ -150,7 +149,6 @@ TkpDisplayScrollbar(
CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
.ty = viewHeight};
-
scrollPtr->flags &= ~REDRAW_PENDING;
if (!scrollPtr->tkwin || !Tk_IsMapped(tkwin) || !view ||
!TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
@@ -173,7 +171,6 @@ TkpDisplayScrollbar(
(Pixmap) macWin);
}
-
Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
scrollPtr->highlightWidth, scrollPtr->highlightWidth,
Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
@@ -186,15 +183,11 @@ TkpDisplayScrollbar(
/*Update values and draw in native rect.*/
UpdateControlValues(scrollPtr);
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
- if (scrollPtr->vertical) {
- HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal);
- } else {
+ if (MOUNTAIN_LION_STYLE) {
HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationInverted);
+ } else {
+ HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal);
}
-#else
- HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal);
-#endif
TkMacOSXRestoreDrawingContext(&dc);
scrollPtr->flags &= ~REDRAW_PENDING;
@@ -265,11 +258,12 @@ TkpComputeScrollbarGeometry(
if (scrollPtr->sliderLast > fieldLength) {
scrollPtr->sliderLast = fieldLength;
}
- scrollPtr->sliderFirst += scrollPtr->inset +
+ if (!(MOUNTAIN_LION_STYLE)) {
+ scrollPtr->sliderFirst += scrollPtr->inset +
metrics[variant].topArrowHeight;
- scrollPtr->sliderLast += scrollPtr->inset +
+ scrollPtr->sliderLast += scrollPtr->inset +
metrics[variant].bottomArrowHeight;
-
+ }
/*
* Register the desired geometry for the window (leave enough space
* for the two arrows plus a minimum-size slider, plus border around
@@ -370,21 +364,29 @@ TkpScrollbarPosition(
int x, int y) /* Coordinates within scrollPtr's window. */
{
- /*Using code from tkUnixScrlbr.c because Unix scroll bindings are driving the display at the script level. All the Mac scrollbar has to do is re-draw itself.*/
+ /*
+ * Using code from tkUnixScrlbr.c because Unix scroll bindings are
+ * driving the display at the script level. All the Mac scrollbar
+ * has to do is re-draw itself.
+ */
- int length, width, tmp;
+ int length, fieldlength, width, tmp;
register const int inset = scrollPtr->inset;
+ register const int arrowSize = scrollPtr->arrowLength + inset;
if (scrollPtr->vertical) {
length = Tk_Height(scrollPtr->tkwin);
+ fieldlength = length - 2 * arrowSize;
width = Tk_Width(scrollPtr->tkwin);
} else {
tmp = x;
x = y;
y = tmp;
length = Tk_Width(scrollPtr->tkwin);
+ fieldlength = length - 2 * arrowSize;
width = Tk_Height(scrollPtr->tkwin);
}
+ fieldlength = fieldlength < 0 ? 0 : fieldlength;
if (x<inset || x>=width-inset || y<inset || y>=length-inset) {
return OUTSIDE;
@@ -395,19 +397,19 @@ TkpScrollbarPosition(
* TkpDisplayScrollbar. Be sure to keep the two consistent.
*/
- if (y < inset + scrollPtr->arrowLength) {
- return TOP_ARROW;
- }
if (y < scrollPtr->sliderFirst) {
return TOP_GAP;
}
if (y < scrollPtr->sliderLast) {
return SLIDER;
}
- if (y >= length - (scrollPtr->arrowLength + inset)) {
- return BOTTOM_ARROW;
+ if (y < fieldlength){
+ return BOTTOM_GAP;
+ }
+ if (y < fieldlength + arrowSize) {
+ return TOP_ARROW;
}
- return BOTTOM_GAP;
+ return BOTTOM_ARROW;
}
/*
@@ -415,9 +417,11 @@ TkpScrollbarPosition(
*
* UpdateControlValues --
*
- * This procedure updates the Macintosh scrollbar control to display the
- * values defined by the Tk scrollbar. This is the key interface to the Mac-native * scrollbar; the Unix bindings drive scrolling in the Tk window and all the Mac
- * scrollbar has to do is redraw itself.
+ * This procedure updates the Macintosh scrollbar control to
+ * display the values defined by the Tk scrollbar. This is the
+ * key interface to the Mac-native * scrollbar; the Unix bindings
+ * drive scrolling in the Tk window and all the Mac scrollbar has
+ * to do is redraw itself.
*
* Results:
* None.
@@ -432,7 +436,6 @@ static void
UpdateControlValues(
TkScrollbar *scrollPtr) /* Scrollbar data struct. */
{
-
Tk_Window tkwin = scrollPtr->tkwin;
MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
double dViewSize;
@@ -484,7 +487,11 @@ UpdateControlValues(
factor - dViewSize;
info.trackInfo.scrollbar.viewsize = dViewSize;
if (scrollPtr->vertical) {
+ if (MOUNTAIN_LION_STYLE) {
+ info.value = factor * scrollPtr->firstFraction;
+ } else {
info.value = info.max - factor * scrollPtr->firstFraction;
+ }
} else {
info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction;
}
diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c
index 869f717..2a88422 100644
--- a/macosx/tkMacOSXSubwindows.c
+++ b/macosx/tkMacOSXSubwindows.c
@@ -657,6 +657,65 @@ XConfigureWindow(
/*
*----------------------------------------------------------------------
*
+ * TkMacOSXSetDrawingEnabled --
+ *
+ * This function sets the TK_DO_NOT_DRAW flag for a given window and
+ * all of its children.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The clipping regions for the window and its children are cleared.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetDrawingEnabled(
+ TkWindow *winPtr,
+ int flag)
+{
+ TkWindow *childPtr;
+ MacDrawable *macWin = winPtr->privatePtr;
+
+ if (macWin) {
+ if (flag ) {
+ macWin->flags &= ~TK_DO_NOT_DRAW;
+ } else {
+ macWin->flags |= TK_DO_NOT_DRAW;
+ }
+ }
+
+ /*
+ * Set the flag for all children & their descendants, excluding
+ * Toplevels. (??? Do we need to exclude Toplevels?)
+ */
+
+ childPtr = winPtr->childList;
+ while (childPtr) {
+ if (!Tk_IsTopLevel(childPtr)) {
+ TkMacOSXSetDrawingEnabled(childPtr, flag);
+ }
+ childPtr = childPtr->nextPtr;
+ }
+
+ /*
+ * If the window is a container, set the flag for its embedded window.
+ */
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+
+ if (childPtr) {
+ TkMacOSXSetDrawingEnabled(childPtr, flag);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkMacOSXUpdateClipRgn --
*
* This function updates the clipping regions for a given window and all of
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index 2e7c041..35f9f1c 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -29,7 +29,7 @@
* Declaration of functions used only in this file
*/
-static int GenerateUpdates(HIMutableShapeRef updateRgn,
+static int GenerateUpdates(HIShapeRef updateRgn,
CGRect *updateBounds, TkWindow *winPtr);
static int GenerateActivateEvents(TkWindow *winPtr,
int activeFlag);
@@ -315,7 +315,7 @@ extern BOOL opaqueTag;
static int
GenerateUpdates(
- HIMutableShapeRef updateRgn,
+ HIShapeRef updateRgn,
CGRect *updateBounds,
TkWindow *winPtr)
{
@@ -782,7 +782,8 @@ Tk_MacOSXIsAppInFront(void)
@interface TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect;
-- (void) generateExposeEvents: (HIMutableShapeRef) shape;
+- (void) generateExposeEvents: (HIShapeRef) shape;
+- (void) generateExposeEvents: (HIShapeRef) shape childrenOnly: (int) childrenOnly;
- (void) viewDidEndLiveResize;
- (void) tkToolbarButton: (id) sender;
- (BOOL) isOpaque;
@@ -792,6 +793,8 @@ Tk_MacOSXIsAppInFront(void)
@end
@implementation TKContentView
+NSDate *_resizeStart;
+NSTimeInterval _resizeDuration;
@end
/*Restrict event processing to Expose events.*/
@@ -829,7 +832,7 @@ ExposeRestrictProc(
HIShapeUnionWithRect(drawShape, &r);
}
if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
- [self generateExposeEvents:drawShape];
+ [self generateExposeEvents:(HIShapeRef)drawShape];
} else {
[self performSelectorOnMainThread:@selector(generateExposeEvents:)
withObject:(id)drawShape waitUntilDone:NO
@@ -844,25 +847,33 @@ ExposeRestrictProc(
-(void) setFrameSize: (NSSize)newsize
{
if ( [self inLiveResize] ) {
- NSWindow *window = [self window];
- TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ NSWindow *w = [self window];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
unsigned int width = (unsigned int)newsize.width;
unsigned int height=(unsigned int)newsize.height;
- /* Resize the Tk Window to the requested size.*/
- TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,
- TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
-
- /* Then resize the NSView to the actual window size*/
- newsize.width = (CGFloat)Tk_Width(tkwin);
- newsize.height = (CGFloat)Tk_Height(tkwin);
+ /* Resize the NSView */
[super setFrameSize: newsize];
- /* Process all pending events to update the window. */
- while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
+ /* Disable drawing until the window has been completely configured.*/
+ TkMacOSXSetDrawingEnabled(winPtr, 0);
+ /* Generate and handle a ConfigureNotify event for the new size.*/
+ TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,
+ TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
+ while ( Tk_DoOneEvent(TK_X_EVENTS|TK_DONT_WAIT) ) {}
+
+ /* Now that Tk has configured all subwindows we can create the clip regions. */
+ TkMacOSXSetDrawingEnabled(winPtr, 1);
+ TkMacOSXInvalClipRgns(tkwin);
+ TkMacOSXUpdateClipRgn(winPtr);
+
+ /* Finally, generate and process expose events to redraw the window. */
+ HIRect bounds = NSRectToCGRect([self bounds]);
+ HIShapeRef shape = HIShapeCreateWithRect(&bounds);
+ [self generateExposeEvents: shape];
+ while ( Tk_DoOneEvent(TK_ALL_EVENTS|TK_DONT_WAIT) ) {}
} else {
[super setFrameSize: newsize];
}
@@ -881,46 +892,44 @@ ExposeRestrictProc(
[self generateExposeEvents: shape];
}
-/*Core function of this class, generates expose events for redrawing.*/
-- (void) generateExposeEvents: (HIMutableShapeRef) shape
+/* Core method of this class: generates expose events for redrawing.
+ * Whereas drawRect is intended to be called only from the Appkit event
+ * loop, this can be called from Tk. If the Tcl_ServiceMode is set to
+ * TCL_SERVICE_ALL then the expose events will be immediately removed
+ * from the Tcl event loop and processed. Typically, they should be queued,
+ * however.
+ */
+- (void) generateExposeEvents: (HIShapeRef) shape
+{
+ [self generateExposeEvents:shape childrenOnly:0];
+}
+
+- (void) generateExposeEvents: (HIShapeRef) shape
+ childrenOnly: (int) childrenOnly
{
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
unsigned long serial;
CGRect updateBounds;
+ int updatesNeeded;
if (!winPtr) {
return;
}
+ /* Generate Tk Expose events. */
HIShapeGetBounds(shape, &updateBounds);
+ /* All of these events will share the same serial number. */
serial = LastKnownRequestProcessed(Tk_Display(winPtr));
- if (GenerateUpdates(shape, &updateBounds, winPtr) &&
- ![[NSRunLoop currentRunLoop] currentMode] &&
- Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
- /*
- * Ensure there are no pending idle-time redraws that could
- * prevent the just posted Expose events from generating
- * new redraws.
- */
-
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
-
- /*
- * For smoother drawing, process Expose events and resulting
- * redraws immediately instead of at idle time.
- */
-
- ClientData oldArg;
+ updatesNeeded = GenerateUpdates(shape, &updateBounds, winPtr);
+
+ /* Process the Expose events if the service mode is TCL_SERVICE_ALL */
+ if (updatesNeeded && Tcl_GetServiceMode() == TCL_SERVICE_ALL) {
+ ClientData oldArg;
Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc,
UINT2PTR(serial), &oldArg);
-
while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
-
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
-
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
}
-
}
/*
@@ -936,7 +945,6 @@ ExposeRestrictProc(
int x, y;
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
Tk_Window tkwin = (Tk_Window) winPtr;
-
bzero(&event, sizeof(XVirtualEvent));
event.type = VirtualEvent;
event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));