summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorculler <culler>2018-11-06 21:21:50 (GMT)
committerculler <culler>2018-11-06 21:21:50 (GMT)
commit1cd3199254c47a7fd9e308663776b9e540d527c2 (patch)
tree448e2c1f7ba55253f13ed714dcecd4aa83e77417
parentc5205ce3fbef20b6a3e78118e6ccfea8c05e0dd7 (diff)
downloadtk-1cd3199254c47a7fd9e308663776b9e540d527c2.zip
tk-1cd3199254c47a7fd9e308663776b9e540d527c2.tar.gz
tk-1cd3199254c47a7fd9e308663776b9e540d527c2.tar.bz2
Came up with a scheme for making test images behave the way that the
tests assume they do.
-rw-r--r--generic/tkTest.c48
-rw-r--r--macosx/tkMacOSXDraw.c21
-rw-r--r--macosx/tkMacOSXEvent.c20
-rw-r--r--macosx/tkMacOSXInit.c7
-rw-r--r--macosx/tkMacOSXInt.h3
-rw-r--r--macosx/tkMacOSXPrivate.h2
-rw-r--r--macosx/tkMacOSXTest.c23
-rw-r--r--macosx/tkMacOSXWindowEvent.c27
8 files changed, 83 insertions, 68 deletions
diff --git a/generic/tkTest.c b/generic/tkTest.c
index e95d274..5609391 100644
--- a/generic/tkTest.c
+++ b/generic/tkTest.c
@@ -31,9 +31,9 @@
#if defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"
#include "tkScrollbar.h"
-#define APP_IS_DRAWING (TkTestAppIsDrawing())
+#define SIMULATE_DRAWING TkTestSimulateDrawing(true);
#else
-#define APP_IS_DRAWING 1
+#define SIMULATE_DRAWING
#endif
#ifdef __UNIX__
@@ -1554,26 +1554,34 @@ ImageDisplay(
char buffer[200 + TCL_INTEGER_SPACE * 6];
/*
- * On macOS the fake drawing below will not take place when this
- * displayProc is run as an idle task. That is because the idle task will
- * not have a valid graphics context available. Instead, the window will
- * be marked as needing redisplay and will get redrawn in the next call to
- * its contentView's drawRect method. We only record the display
- * information when the actual drawing takes place to avoid duplicate
- * records which would cause some image tests to fail.
+ * The purpose of the test image type is to track the calls to an image
+ * display proc and record the parameters passed in each call. On macOS
+ * these tests will fail because of the asynchronous drawing. The low
+ * level graphics calls below which are supposed to draw a rectangle will
+ * not draw anything to the screen because the idle task will not be
+ * processed inside of the drawRect method and hence will not be able to
+ * obtain a valid graphics context. Instead, the window will be marked as
+ * needing display, and will be redrawn during a future asynchronous call
+ * to drawRect. This will generate an other call to this display proc,
+ * and the recorded data will show extra calls, causing the test to fail.
+ * To avoid this, we can set the [NSApp simulateDrawing] flag, which will
+ * cause all low level drawing routines to return immediately and not
+ * schedule the window for drawing later. This flag is cleared by the
+ * next call to XSync, which is called by the update command.
*/
- if (APP_IS_DRAWING) {
- sprintf(buffer, "%s display %d %d %d %d",
- instPtr->masterPtr->imageName, imageX, imageY, width, height);
- Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
- buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
- if (width > (instPtr->masterPtr->width - imageX)) {
- width = instPtr->masterPtr->width - imageX;
- }
- if (height > (instPtr->masterPtr->height - imageY)) {
- height = instPtr->masterPtr->height - imageY;
- }
+
+ sprintf(buffer, "%s display %d %d %d %d",
+ instPtr->masterPtr->imageName, imageX, imageY, width, height);
+ Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
+ buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+ if (width > (instPtr->masterPtr->width - imageX)) {
+ width = instPtr->masterPtr->width - imageX;
+ }
+ if (height > (instPtr->masterPtr->height - imageY)) {
+ height = instPtr->masterPtr->height - imageY;
}
+
+ SIMULATE_DRAWING
XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
(unsigned) (width-1), (unsigned) (height-1));
XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index 94e8778..42c9059 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -1448,7 +1448,7 @@ TkMacOSXSetUpGraphicsPort(
*----------------------------------------------------------------------
*/
-int
+Bool
TkMacOSXSetupDrawingContext(
Drawable d,
GC gc,
@@ -1462,16 +1462,26 @@ TkMacOSXSetupDrawingContext(
CGRect clipBounds;
/*
+ * If we are simulating drawing for tests, just return false.
+ */
+
+ if ([NSApp simulateDrawing]) {
+ return false;
+ }
+
+ /*
* If the drawable is not a pixmap and it has an associated
- * NSWindow then we are drawing to a window.
+ * NSWindow then we know we are drawing to a window.
*/
+
if (!(macDraw->flags & TK_IS_PIXMAP)) {
win = TkMacOSXDrawableWindow(d);
}
-
+
/*
* Check that we have a non-empty clipping region.
*/
+
dc.clipRgn = TkMacOSXGetClipRgn(d);
ClipToGC(d, gc, &dc.clipRgn);
if (dc.clipRgn && HIShapeIsEmpty(dc.clipRgn)) {
@@ -1484,12 +1494,14 @@ TkMacOSXSetupDrawingContext(
* are drawing to a window then we can get one from the
* window.
*/
+
dc.context = TkMacOSXGetCGContextForDrawable(d);
if (dc.context) {
dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
} else if (win) {
NSView *view = TkMacOSXDrawableView(macDraw);
if (view) {
+
/*
* We can only draw into the view when the current CGContext is
* valid and belongs to the view. Validity can only be guaranteed
@@ -1501,6 +1513,7 @@ TkMacOSXSetupDrawingContext(
* then we mark our view as needing display and return failure.
* It should get drawn in a later call to drawRect.
*/
+
if (view != [NSView focusView]) {
[view setNeedsDisplay:YES];
canDraw = false;
@@ -1520,9 +1533,11 @@ TkMacOSXSetupDrawingContext(
Tcl_Panic("TkMacOSXSetupDrawingContext(): "
"no context to draw into !");
}
+
/*
* Configure the drawing context.
*/
+
if (dc.context) {
CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
.ty = dc.portBounds.size.height};
diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c
index 676344c..798c73c 100644
--- a/macosx/tkMacOSXEvent.c
+++ b/macosx/tkMacOSXEvent.c
@@ -136,22 +136,16 @@ enum {
MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
- NSModalSession modalSession = TkMacOSXGetModalSession();
- NSEvent *syncEvent;
NSArray *macWindows = [NSApp orderedWindows];
+ if ([NSApp simulateDrawing]) {
+ [NSApp setSimulateDrawing:NO];
+ return;
+ }
for (NSWindow *w in macWindows) {
- if (TkMacOSXGetXWindow(w)) {
- [w displayIfNeeded];
- syncEvent = [NSApp
- nextEventMatchingMask:NSApplicationDefinedMask
- untilDate:[NSDate distantPast]
- inMode:GetRunLoopMode(modalSession)
- dequeue:YES];
- [NSApp discardEventsMatchingMask:NSApplicationDefinedMask
- beforeEvent:syncEvent];
- }
+ if (TkMacOSXGetXWindow(w)) {
+ [w displayIfNeeded];
+ }
}
-
}
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index 10ef87e..8e9c600 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -47,6 +47,7 @@ static char scriptPath[PATH_MAX + 1] = "";
@synthesize poolLock = _poolLock;
@synthesize macMinorVersion = _macMinorVersion;
@synthesize isDrawing = _isDrawing;
+@synthesize simulateDrawing = _simulateDrawing;
@end
/*
@@ -162,13 +163,14 @@ static char scriptPath[PATH_MAX + 1] = "";
systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
minorVersion = systemVersion.minorVersion;
#endif
- [NSApp setMacMinorVersion: minorVersion];
+ [NSApp setMacMinorVersion: minorVersion];
/*
* We are not drawing yet.
*/
- [NSApp setIsDrawing: NO];
+ [NSApp setIsDrawing:NO];
+ [NSApp setSimulateDrawing:NO];
/*
* Be our own delegate.
@@ -178,6 +180,7 @@ static char scriptPath[PATH_MAX + 1] = "";
/*
* Make sure we are allowed to open windows.
*/
+
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
/*
diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h
index 6108383..f04d9dc 100644
--- a/macosx/tkMacOSXInt.h
+++ b/macosx/tkMacOSXInt.h
@@ -200,7 +200,8 @@ MODULE_SCOPE void TkpReleaseRegion(TkRegion r);
MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
MODULE_SCOPE Bool TkpAppIsDrawing(void);
MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin);
-MODULE_SCOPE NSString* GetRunLoopMode(NSModalSession modalSession);
+MODULE_SCOPE void TkTestSimulateDrawing(Bool);
+
/*
* Include the stubbed internal platform-specific API.
*/
diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h
index f5924e5..5eef949 100644
--- a/macosx/tkMacOSXPrivate.h
+++ b/macosx/tkMacOSXPrivate.h
@@ -266,11 +266,13 @@ VISIBILITY_HIDDEN
int _poolLock;
int _macMinorVersion;
Bool _isDrawing;
+ Bool _simulateDrawing;
#endif
}
@property int poolLock;
@property int macMinorVersion;
@property Bool isDrawing;
+@property Bool simulateDrawing;
@end
@interface TKApplication(TKInit)
diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c
index 92c925c..5576c44 100644
--- a/macosx/tkMacOSXTest.c
+++ b/macosx/tkMacOSXTest.c
@@ -82,25 +82,28 @@ DebuggerObjCmd(
/*
*----------------------------------------------------------------------
*
- * TkTestAppIsDrawing --
+ * TkTestSimulateDrawing --
+ *
+ * A test widget display procedure which records calls can use this to
+ * avoid duplicate calls which would occur due to fact that no valid
+ * graphics context is available to the idle task which is running the
+ * display proc. Note that no actual drawing to the screen will take
+ * place when this flag is set. This is just a wrapper for the NSApp
+ * property.
*
- * A widget display procedure can call this to determine whether it
- * is being run inside of the drawRect method. This is needed for
- * some tests, especially of the Text widget, which record data in
- * a global Tcl variable and assume that display procedures will be
- * run in a predictable sequence as Tcl idle tasks.
*
* Results:
- * True only while running the drawRect method of a TKContentView;
+ * Calls to low level drawing routines will return without actually
+ * drawing anything to the screen.
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
-MODULE_SCOPE Bool
-TkTestAppIsDrawing(void) {
- return [NSApp isDrawing];
+MODULE_SCOPE void
+TkTestSimulateDrawing(Bool yesno) {
+ [NSApp setSimulateDrawing:yesno];
}
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index f69ee0c..724a9af 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -832,14 +832,19 @@ ConfigureRestrictProc(
Tk_PathName(winPtr));
#endif
+ if ([NSApp simulateDrawing]) {
+ return;
+ }
+
/*
- * We do not allow recursive calls to drawRect. Only log this
- * in 10.14 and higher, where it should not happen.
+ * We do not allow recursive calls to drawRect.
*/
- if ([NSApp isDrawing] && [NSApp macMinorVersion] > 13) {
+
+ if ([NSApp isDrawing]) {
TKLog(@"WARNING: a recursive call to drawRect was aborted.");
return;
}
+
[NSApp setIsDrawing: YES];
[self getRectsBeingDrawn:&rectsBeingDrawn count:&rectsBeingDrawnCount];
@@ -861,22 +866,6 @@ ConfigureRestrictProc(
CFRelease(drawShape);
[NSApp setIsDrawing: NO];
- /*
- * To make it possible to wait for this method, we post an application
- * defined event when all drawing has been done.
- */
- NSEvent* drawEvent = [NSEvent otherEventWithType:NSApplicationDefined
- location:NSMakePoint(0,0)
- modifierFlags:0
- timestamp:0
- windowNumber:[[self window] windowNumber]
- context:nil
- subtype:1
- data1:0
- data2:0
- ];
- [NSApp postEvent:drawEvent atStart:YES];
-
#ifdef TK_MAC_DEBUG_DRAWING
fprintf(stderr, "drawRect: done.\n");
#endif