summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorculler <culler>2018-11-05 16:03:56 (GMT)
committerculler <culler>2018-11-05 16:03:56 (GMT)
commit31f82fb5b5ae52d1893a87e7a5a83c0e9eae2f58 (patch)
tree55a223472c4e168f0c0b29d3aa178a70c75b629f
parentb236ac696bc5e78bb9aa87505d01d388b1b8cb07 (diff)
downloadtk-31f82fb5b5ae52d1893a87e7a5a83c0e9eae2f58.zip
tk-31f82fb5b5ae52d1893a87e7a5a83c0e9eae2f58.tar.gz
tk-31f82fb5b5ae52d1893a87e7a5a83c0e9eae2f58.tar.bz2
Make XSync, and hence update, be synchronous so test results are consistent. Fix duplicate
reports of calls to the test image displayProc.
-rw-r--r--generic/tkTest.c32
-rw-r--r--macosx/tkMacOSXConstants.h2
-rw-r--r--macosx/tkMacOSXEvent.c25
-rw-r--r--macosx/tkMacOSXInt.h2
-rw-r--r--macosx/tkMacOSXNotify.c2
-rw-r--r--macosx/tkMacOSXTest.c26
-rw-r--r--macosx/tkMacOSXWindowEvent.c19
7 files changed, 89 insertions, 19 deletions
diff --git a/generic/tkTest.c b/generic/tkTest.c
index 2dbd877..e95d274 100644
--- a/generic/tkTest.c
+++ b/generic/tkTest.c
@@ -31,6 +31,9 @@
#if defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"
#include "tkScrollbar.h"
+#define APP_IS_DRAWING (TkTestAppIsDrawing())
+#else
+#define APP_IS_DRAWING 1
#endif
#ifdef __UNIX__
@@ -1550,15 +1553,26 @@ ImageDisplay(
TImageInstance *instPtr = (TImageInstance *) clientData;
char buffer[200 + TCL_INTEGER_SPACE * 6];
- 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;
+ /*
+ * 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.
+ */
+ 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;
+ }
}
XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
(unsigned) (width-1), (unsigned) (height-1));
diff --git a/macosx/tkMacOSXConstants.h b/macosx/tkMacOSXConstants.h
index b160083..dbe533c 100644
--- a/macosx/tkMacOSXConstants.h
+++ b/macosx/tkMacOSXConstants.h
@@ -40,6 +40,7 @@
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
#define NSAppKitDefined NSEventTypeAppKitDefined
+#define NSApplicationDefined NSEventTypeApplicationDefined
#define NSApplicationActivatedEventType NSEventSubtypeApplicationActivated
#define NSApplicationDeactivatedEventType NSEventSubtypeApplicationDeactivated
#define NSWindowExposedEventType NSEventSubtypeWindowExposed
@@ -92,6 +93,7 @@
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
#define NSShiftKeyMask NSEventModifierFlagShift
#define NSAnyEventMask NSEventMaskAny
+#define NSApplicationDefinedEventMask NSEventMaskApplicationDefined
#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground
#define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow
#define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel
diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c
index 25c0bea..36167cb 100644
--- a/macosx/tkMacOSXEvent.c
+++ b/macosx/tkMacOSXEvent.c
@@ -112,11 +112,16 @@ enum {
*
* TkMacOSXFlushWindows --
*
- * This routine is a stub called by XSync, which is called during
- * the Tk update command. It calls displayIfNeeded on all visible
- * windows. This is necessary in order to insure that update will
- * run all of the display procedures which have been registered as
- * idle tasks. The test suite assumes that this is the case.
+ * This routine is a stub called by XSync, which is called during the Tk
+ * update command. The language specification does not require that the
+ * update command be synchronous but many of the tests assume that is the
+ * case. It is not naturally the case on macOS since many idle tasks are
+ * run inside of the drawRect method of a window's contentView, and that
+ * method will not be called until after this function returns. To make
+ * the tests work, we attempt to force this to be synchronous by waiting
+ * until drawRect has been called for each window. The mechanism we use
+ * for this is to have drawRect post an ApplicationDefined NSEvent on the
+ * AppKit event queue when it finishes drawing, and wait for it here.
*
* Results:
* None.
@@ -131,11 +136,19 @@ enum {
MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
+ NSModalSession modalSession = TkMacOSXGetModalSession();
+ NSEvent *syncEvent;
NSArray *macWindows = [NSApp orderedWindows];
-
for (NSWindow *w in macWindows) {
if (TkMacOSXGetXWindow(w)) {
[w displayIfNeeded];
+ syncEvent = [NSApp
+ nextEventMatchingMask:NSApplicationDefinedEventMask
+ untilDate:[NSDate distantPast]
+ inMode:GetRunLoopMode(modalSession)
+ dequeue:YES];
+ [NSApp discardEventsMatchingMask:NSApplicationDefinedEventMask
+ beforeEvent:syncEvent];
}
}
diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h
index 09fbed3..6108383 100644
--- a/macosx/tkMacOSXInt.h
+++ b/macosx/tkMacOSXInt.h
@@ -200,7 +200,7 @@ 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);
/*
* Include the stubbed internal platform-specific API.
*/
diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c
index e276926..7cbd248 100644
--- a/macosx/tkMacOSXNotify.c
+++ b/macosx/tkMacOSXNotify.c
@@ -169,7 +169,7 @@ void DebugPrintQueue(void)
*----------------------------------------------------------------------
*/
-static NSString *
+NSString *
GetRunLoopMode(NSModalSession modalSession)
{
NSString *runLoopMode = nil;
diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c
index 1882ce6..92c925c 100644
--- a/macosx/tkMacOSXTest.c
+++ b/macosx/tkMacOSXTest.c
@@ -80,6 +80,32 @@ DebuggerObjCmd(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * TkTestAppIsDrawing --
+ *
+ * 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;
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+MODULE_SCOPE Bool
+TkTestAppIsDrawing(void) {
+ return [NSApp isDrawing];
+}
+
+
+
+/*
* Local Variables:
* mode: objc
* c-basic-offset: 4
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index 19e4ba2..f69ee0c 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -861,6 +861,22 @@ 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
@@ -981,8 +997,7 @@ ConfigureRestrictProc(
*
* Fortunately, Tk schedules all drawing to be done while Tcl is idle.
* So we can do the drawing by processing all of the idle events that
- * were created when the expose events were processed. Unfortunately
- * this does not work in macOS 10.13.
+ * were created when the expose events were processed.
*/
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
}