summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
authorKevin Walzer <kw@codebykevin.com>2015-04-09 02:00:49 (GMT)
committerKevin Walzer <kw@codebykevin.com>2015-04-09 02:00:49 (GMT)
commit69e749839382af95c02bdb100c49402eb6b926ae (patch)
treee0d98826c7a37d1a2c4e79ce3376a5f0054ec088 /macosx
parent9f2f06f947fdb1bc1d9c47da80db1ec6728b32a2 (diff)
downloadtk-69e749839382af95c02bdb100c49402eb6b926ae.zip
tk-69e749839382af95c02bdb100c49402eb6b926ae.tar.gz
tk-69e749839382af95c02bdb100c49402eb6b926ae.tar.bz2
Re-working of internal Cocoa widget drawing routines, especially when resizing; fix rendering of scrollbar when resized or clipped; cleanup of button metrics; thanks to Marc Culler for extensive patches
Diffstat (limited to 'macosx')
-rw-r--r--macosx/tkMacOSXButton.c21
-rw-r--r--macosx/tkMacOSXDraw.c86
-rw-r--r--macosx/tkMacOSXInt.h2
-rw-r--r--macosx/tkMacOSXMouseEvent.c6
-rw-r--r--macosx/tkMacOSXNotify.c27
-rw-r--r--macosx/tkMacOSXScrlbr.c84
-rw-r--r--macosx/tkMacOSXSubwindows.c59
-rw-r--r--macosx/tkMacOSXWindowEvent.c101
8 files changed, 266 insertions, 120 deletions
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/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c
index 95f0021..8c0a2e6 100644
--- a/macosx/tkMacOSXMouseEvent.c
+++ b/macosx/tkMacOSXMouseEvent.c
@@ -104,12 +104,6 @@ enum {
return theEvent; /* Give up. No window for this event. */
}
- /*
- MacDrawable *macWin = (MacDrawable *) window;
- NSView *view = TkMacOSXDrawableView(macWin);
- local = [view convertPoint:local fromView:nil];
- local.y = NSHeight([view bounds]) - local.y;
- */
TkWindow *winPtr = (TkWindow *) tkwin;
local.x -= winPtr->wmInfoPtr->xInParent;
local.y -= winPtr->wmInfoPtr->yInParent;
diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c
index 8b9745d..1d4c6c5 100644
--- a/macosx/tkMacOSXNotify.c
+++ b/macosx/tkMacOSXNotify.c
@@ -50,18 +50,18 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
@end
@implementation TKApplication(TKNotify)
-/* Redisplay all of our windows, then call super. */
+/* Call super then redisplay all of our windows. */
- (NSEvent *) nextEventMatchingMask: (NSUInteger) mask
untilDate: (NSDate *) expiration inMode: (NSString *) mode
dequeue: (BOOL) deqFlag
{
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
- [NSApp makeWindowsPerform:@selector(tkDisplayIfNeeded) inOrder:NO];
- [pool drain];
NSEvent *event = [super nextEventMatchingMask:mask
untilDate:expiration
inMode:mode
dequeue:deqFlag];
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ [NSApp makeWindowsPerform:@selector(tkDisplayIfNeeded) inOrder:NO];
+ [pool drain];
return event;
}
@@ -226,7 +226,7 @@ TkMacOSXEventsSetupProc(
untilDate:[NSDate distantPast]
inMode:GetRunLoopMode(TkMacOSXGetModalSession())
dequeue:NO];
- if (currentEvent) {
+ if (currentEvent && currentEvent.type > 0) {
Tcl_SetMaxBlockTime(&zeroBlockTime);
}
}
@@ -254,19 +254,30 @@ TkMacOSXEventsCheckProc(
ClientData clientData,
int flags)
{
- if (flags & TCL_WINDOW_EVENTS &&
- ![[NSRunLoop currentRunLoop] currentMode]) {
+ NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
+ if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
+
NSEvent *currentEvent = nil;
+ NSEvent *testEvent = nil;
NSModalSession modalSession;
do {
modalSession = TkMacOSXGetModalSession();
+ testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:GetRunLoopMode(modalSession)
+ dequeue:NO];
+ /* We must not steal any events during LiveResize. */
+ if (testEvent && [[testEvent window] inLiveResize]) {
+ break;
+ }
+
currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:GetRunLoopMode(modalSession)
dequeue:YES];
if (!currentEvent) {
- break; /* No more events. */
+ break; /* No events are available. */
}
NSAutoreleasePool *pool = [NSAutoreleasePool new];
/* Generate Xevents. */
diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c
index bdb76af..37178ed 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);
-
/*
*----------------------------------------------------------------------
*
@@ -136,27 +136,26 @@ TkpDisplayScrollbar(
{
register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
register Tk_Window tkwin = scrollPtr->tkwin;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkMacOSXDrawingContext dc;
+ scrollPtr->flags &= ~REDRAW_PENDING;
- if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
return;
}
- TkWindow *winPtr = (TkWindow *) tkwin;
MacDrawable *macWin = (MacDrawable *) winPtr->window;
- TkMacOSXDrawingContext dc;
NSView *view = TkMacOSXDrawableView(macWin);
+ if (!view ||
+ macWin->flags & TK_DO_NOT_DRAW ||
+ !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
+ return;
+ }
+
CGFloat viewHeight = [view bounds].size.height;
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)) {
- return;
- }
-
CGContextConcatCTM(dc.context, t);
/*Draw Unix-style scroll trough to provide rect for native scrollbar.*/
@@ -173,7 +172,6 @@ TkpDisplayScrollbar(
(Pixmap) macWin);
}
-
Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
scrollPtr->highlightWidth, scrollPtr->highlightWidth,
Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
@@ -186,15 +184,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 +259,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 +365,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 +398,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 +418,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 +437,6 @@ static void
UpdateControlValues(
TkScrollbar *scrollPtr) /* Scrollbar data struct. */
{
-
Tk_Window tkwin = scrollPtr->tkwin;
MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
double dViewSize;
@@ -462,8 +466,10 @@ UpdateControlValues(
*/
info.bounds = contrlRect;
- if (!scrollPtr->vertical) {
- info.attributes |= kThemeTrackHorizontal;
+ if (scrollPtr->vertical) {
+ info.attributes &= ~kThemeTrackHorizontal;
+ } else {
+ info.attributes |= kThemeTrackHorizontal;
}
/*
@@ -484,7 +490,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..15e86ca 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;
@@ -804,6 +805,15 @@ ExposeRestrictProc(
? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}
+/*Restrict event processing to ConfigureNotify events.*/
+static Tk_RestrictAction
+ConfigureRestrictProc(
+ ClientData arg,
+ XEvent *eventPtr)
+{
+ return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
+}
+
@implementation TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect
@@ -829,11 +839,12 @@ ExposeRestrictProc(
HIShapeUnionWithRect(drawShape, &r);
}
if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
- [self generateExposeEvents:drawShape];
+ [self generateExposeEvents:(HIShapeRef)drawShape];
} else {
[self performSelectorOnMainThread:@selector(generateExposeEvents:)
withObject:(id)drawShape waitUntilDone:NO
modes:[NSArray arrayWithObjects:NSRunLoopCommonModes,
+
NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode,
nil]];
}
@@ -844,25 +855,37 @@ 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;
+ ClientData oldArg;
+ Tk_RestrictProc *oldProc;
+
+ /* Resize the NSView */
+ [super setFrameSize: newsize];
- /* Resize the Tk Window to the requested size.*/
+ /* 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);
+ oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg);
+ while ( Tk_DoOneEvent(TK_X_EVENTS|TK_DONT_WAIT) ) {}
+ Tk_RestrictEvents(oldProc, oldArg, &oldArg);
- /* Then resize the NSView to the actual window size*/
- newsize.width = (CGFloat)Tk_Width(tkwin);
- newsize.height = (CGFloat)Tk_Height(tkwin);
- [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)) {}
+ /* 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];
}
@@ -878,49 +901,48 @@ ExposeRestrictProc(
{
HIRect bounds = NSRectToCGRect([self bounds]);
HIShapeRef shape = HIShapeCreateWithRect(&bounds);
+ [super viewDidEndLiveResize];
[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 +958,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));