diff options
78 files changed, 2210 insertions, 1417 deletions
@@ -1,6 +1,6 @@ A NOTE ON THE CHANGELOG: Starting in early 2011, Tk source code has been under the management of -fossil, hosted at http://core.tcl.tk/tk/ . Fossil presents a "Timeline" +fossil, hosted at http://core.tcl-lang.org/tk/ . Fossil presents a "Timeline" view of changes made that is superior in every way to a hand edited log file. Because of this, many Tk developers are now out of the habit of maintaining this log file. You may still find useful things in it, but the Timeline is @@ -1,5 +1,5 @@ README: Tk - This is the Tk 8.6.8 source distribution. + This is the Tk 8.6.9 source distribution. http://sourceforge.net/projects/tcl/files/Tcl/ You can get any source release of Tk from the URL above. @@ -12,7 +12,7 @@ toolkit implemented with the Tcl scripting language. For details on features, incompatibilities, and potential problems with this release, see the Tcl/Tk 8.6 Web page at - http://www.tcl.tk/software/tcltk/8.6.html + http://www.tcl-lang.org/software/tcltk/8.6.html or refer to the "changes" file in this directory, which contains a historical record of all changes to Tk. @@ -21,11 +21,11 @@ Tk is maintained, enhanced, and distributed freely by the Tcl community. Source code development and tracking of bug reports and feature requests takes place at: - http://core.tcl.tk/tk/ + http://core.tcl-lang.org/tk/ with the Tcl Developer Xchange at: - http://www.tcl.tk/ + http://www.tcl-lang.org/ Tk is a freely available open source package. You can do virtually anything you like with it, such as modifying it, redistributing it, @@ -7495,3 +7495,77 @@ Tk Cocoa 2.0: More drawing internals refinements (culler,walzer) 2017-12-18 (bug)[b77626] Make [tk busy -cursor] silent no-op on macOS (vogel) --- Released 8.6.8, December 22, 2017 --- http://core.tcl.tk/tk/ for details + +2017-12-31 (bug)[aa7679] crash using window after master destroyed (vogel) + +2017-12-31 (bug)[6525e1] encoding leak in tkMacOSXProcessFiles (werner) + +2018-01-07 (bug)[925262] New option -state for ttk::scale (vogel) + +2018-01-07 (bug)[fa8de7] Crash [ttk::checkbutton .x -variable {}] (werner) + +2018-01-16 (bug)[382712] Crash in [event generate . <KeyPress>] (werner) + +2018-01-19 (bug)[657c38] Crash in menu destroy with checkbutton entry (werner) + +2018-01-25 (bug)[de156e] Deny PRIMARY selection access in safe interps (nash) + +2018-01-28 (bug)[b68710] Fixes in [text] bindings (nash) + +2018-01-28 (bug)[e20d5c] Stop failures of textTag-18.1 (vogel) + +2018-02-04 (bug)[5d991b] Fortify var traces against deleted vars (vogel) + +2018-02-10 (bug)[1821174] Stop RenderBadPicture X error (werner) + +2018-02-11 (bug)[502e74] Stop X errors on untrusted connections (werner) + +2018-03-07 (bug)[71b131] Regression in Tk_DrawChars() (werner,cramer) + +2018-04-03 (bug)[59fccb] menu flaws when empty menubar clicked (vogel,mcdonald) + +2018-04-28 (bug)[7423f9] improved legacy support for [tk_setPalette] (bll) + +2018-04-30 (bug)[6d5042] enable [tk inactive] on Mac OSX (culler) + +2018-05-03 (bug)[75d38f] fix touchpad scroll of listbox on win notebook (vogel) + +2018-06-16 (bug)[de01e2] Crash in [$text replace] (vogel) + +2018-07-04 (bug)[6ca257] Fix [wm resizable] on Mac OSX (culler) + +2018-07-04 (bug)[135696] Crash in [wm transient] (culler) + +2018-07-04 (bug)[309b42] Improve ttk high-contrast-mode support (lemburg,vogel) + +2018-07-17 (bug)[1088825] fix frame-2.17,3.9,3.10 on Mac (vogel) + +2018-07-27 (bug)[fabed1] GIF photo support for "deferred clear code" (vogel) + +2018-08-08 (feature) Modern full-screen support on Mac OSX (walzer) + +2018-08-12 (bug)[1875c1] scrollbar on Mac OSX (walzer) + +2018-08-14 (bug)[1ba71a] KeyRelease events on Mac OSX(walzer) + +2018-09-02 (bug)[3441086] error message in layout-2 (vogel) + +2018-09-07 (bug)[05bd7f] vista theme for combobox (vogel) + +2018-09-08 (bug)[382712] crash in KeyPress event handling (vogel,werner) + +2018-09-08 (bug)[6fcaaa] insertion cursor visibility in ttk::entry (nemethi) + +2018-09-30 (bug)[822923] cascade menu indicator color (mcdonald) + +2018-10-06 (bug)[9658bc] borderwidth calculations on menu items (vogel) + +2018-10-17 (bug)[ca403f] treeview border drawing (vogel) + +2018-10-17 (bug)[4b555a] hang in [$text search -all] (vogel,danckaert) + +2018-10-30 (new platform) port to system changes in Mac OSX 10.14 (culler) + +2018-11-04 (bug)[6b22d4] [treeview] binding fix (ohagan) + +- Released 8.6.9, November 16, 2018 - http://core.tcl-lang.org/tk/ for details - diff --git a/doc/CanvTkwin.3 b/doc/CanvTkwin.3 index d53c5b1..3534989 100644 --- a/doc/CanvTkwin.3 +++ b/doc/CanvTkwin.3 @@ -144,7 +144,7 @@ like this: .PP .CS static const Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc, - Tk_CanvasTagsPrintProc, (ClientData) NULL + Tk_CanvasTagsPrintProc, NULL }; static const Tk_ConfigSpec configSpecs[] = { diff --git a/doc/ParseArgv.3 b/doc/ParseArgv.3 index 3a9bd49..7749d92 100644 --- a/doc/ParseArgv.3 +++ b/doc/ParseArgv.3 @@ -314,14 +314,14 @@ Boolean exec = FALSE; Tk_ArgvInfo argTable[] = { {"\-X", TK_ARGV_CONSTANT, (char *) 1, (char *) &debugFlag, "Turn on debugging printfs"}, - {"\-N", TK_ARGV_INT, (char *) NULL, (char *) &numReps, + {"\-N", TK_ARGV_INT, NULL, (char *) &numReps, "Number of repetitions"}, - {"\-of", TK_ARGV_STRING, (char *) NULL, (char *) &fileName, + {"\-of", TK_ARGV_STRING, NULL, (char *) &fileName, "Name of file for output"}, - {"x", TK_ARGV_REST, (char *) NULL, (char *) &exec, + {"x", TK_ARGV_REST, NULL, (char *) &exec, "File to exec, followed by any arguments (must be last argument)."}, - {(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL, - (char *) NULL} + {NULL, TK_ARGV_END, NULL, NULL, + NULL} }; main(argc, argv) diff --git a/doc/event.n b/doc/event.n index 4478b92..9ab48e5 100644 --- a/doc/event.n +++ b/doc/event.n @@ -339,7 +339,9 @@ This is sent to a text widget when the selection in the widget is changed. .TP \fB<<ThemeChanged>>\fR -This is sent to a text widget when the ttk (Tile) theme changed. +This is sent to all widgets when the ttk theme changed. The ttk +widgets listen to this event and redisplay themselves when it fires. +The legacy widgets ignore this event. .TP \fB<<TraverseIn>>\fR This is sent to a widget when the focus enters the widget because of a diff --git a/doc/ttk_label.n b/doc/ttk_label.n index aae95e6..1e30592 100644 --- a/doc/ttk_label.n +++ b/doc/ttk_label.n @@ -49,9 +49,6 @@ Specifies the 3-D effect desired for the widget border. Valid values are \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR, \fBsolid\fR, and \fBsunken\fR. -.OP \-text text Text -Specifies a text string to be displayed inside the widget -(unless overridden by \fB\-textvariable\fR). .OP \-wraplength wrapLength WrapLength Specifies the maximum line length (in pixels). If this option is less than or equal to zero, diff --git a/generic/tk.h b/generic/tk.h index 87150e9..c94882c 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -75,10 +75,10 @@ extern "C" { #define TK_MAJOR_VERSION 8 #define TK_MINOR_VERSION 6 #define TK_RELEASE_LEVEL TCL_FINAL_RELEASE -#define TK_RELEASE_SERIAL 8 +#define TK_RELEASE_SERIAL 9 #define TK_VERSION "8.6" -#define TK_PATCH_LEVEL "8.6.8" +#define TK_PATCH_LEVEL "8.6.9" /* * A special definition used to allow this header file to be included from @@ -1174,7 +1174,7 @@ typedef struct Tk_TSOffset { } Tk_TSOffset; /* - * Bit fields in Tk_Offset->flags: + * Bit fields in Tk_TSOffset->flags: */ #define TK_OFFSET_INDEX 1 diff --git a/generic/tkButton.c b/generic/tkButton.c index fc2c7ec..7760359 100644 --- a/generic/tkButton.c +++ b/generic/tkButton.c @@ -879,7 +879,13 @@ ButtonWidgetObjCmd( Tcl_CancelIdleCall(TkpDisplayButton, butPtr); XFlush(butPtr->display); + #ifndef MAC_OSX_TK + /* + * On the mac you can not sleep in a display proc, and the + * flash command doesn't do anything anyway. + */ Tcl_Sleep(50); + #endif } } break; diff --git a/generic/tkImgPhInstance.c b/generic/tkImgPhInstance.c index ec9ee04..0daca2f 100644 --- a/generic/tkImgPhInstance.c +++ b/generic/tkImgPhInstance.c @@ -19,6 +19,9 @@ */ #include "tkImgPhoto.h" +#ifdef MAC_OSX_TK +#define TKPUTIMAGE_CAN_BLEND +#endif /* * Declaration for internal Xlib function used here: @@ -30,8 +33,10 @@ extern int _XInitImageFuncPtrs(XImage *image); * Forward declarations */ +#ifndef TKPUTIMAGE_CAN_BLEND static void BlendComplexAlpha(XImage *bgImg, PhotoInstance *iPtr, int xOffset, int yOffset, int width, int height); +#endif static int IsValidPalette(PhotoInstance *instancePtr, const char *palette); static int CountBits(pixel mask); @@ -409,7 +414,7 @@ TkImgPhotoGet( * *---------------------------------------------------------------------- */ - +#ifndef TKPUTIMAGE_CAN_BLEND #ifndef _WIN32 #define GetRValue(rgb) (UCHAR(((rgb) & red_mask) >> red_shift)) #define GetGValue(rgb) (UCHAR(((rgb) & green_mask) >> green_shift)) @@ -418,13 +423,6 @@ TkImgPhotoGet( (UCHAR(r) << red_shift) | \ (UCHAR(g) << green_shift) | \ (UCHAR(b) << blue_shift) )) -#ifdef MAC_OSX_TK -#define RGBA(r, g, b, a) ((unsigned)( \ - (UCHAR(r) << red_shift) | \ - (UCHAR(g) << green_shift) | \ - (UCHAR(b) << blue_shift) | \ - (UCHAR(a) << alpha_shift) )) -#endif #define RGB15(r, g, b) ((unsigned)( \ (((r) * red_mask / 255) & red_mask) | \ (((g) * green_mask / 255) & green_mask) | \ @@ -443,16 +441,7 @@ BlendComplexAlpha( unsigned long pixel; unsigned char r, g, b, alpha, unalpha, *masterPtr; unsigned char *alphaAr = iPtr->masterPtr->pix32; -#if defined(MAC_OSX_TK) - /* Background "pixels" are actually 2^pp x 2^pp blocks of subpixels. Each - * block gets blended with the color of one image pixel. Since we iterate - * over the background subpixels, we reset the width and height to the - * subpixel dimensions of the background image we are using. - */ - int pp = bgImg->pixelpower; - width = width << pp; - height = height << pp; -#endif + /* * This blending is an integer version of the Source-Over compositing rule * (see Porter&Duff, "Compositing Digital Images", proceedings of SIGGRAPH @@ -492,13 +481,6 @@ BlendComplexAlpha( while ((0x0001 & (blue_mask >> blue_shift)) == 0) { blue_shift++; } -#ifdef MAC_OSX_TK - unsigned long alpha_mask = visual->alpha_mask; - unsigned long alpha_shift = 0; - while ((0x0001 & (alpha_mask >> alpha_shift)) == 0) { - alpha_shift++; - } -#endif #endif /* !_WIN32 */ /* @@ -507,7 +489,7 @@ BlendComplexAlpha( * optimized. */ -#if !(defined(_WIN32) || defined(MAC_OSX_TK)) +#if !defined(_WIN32) if (bgImg->depth < 24) { unsigned char red_mlen, green_mlen, blue_mlen; @@ -555,19 +537,12 @@ BlendComplexAlpha( } return; } -#endif /* !_WIN32 && !MAC_OSX_TK */ +#endif /* !_WIN32 */ for (y = 0; y < height; y++) { -# if !defined(MAC_OSX_TK) line = (y + yOffset) * iPtr->masterPtr->width; for (x = 0; x < width; x++) { masterPtr = alphaAr + ((line + x + xOffset) * 4); -#else - /* Repeat each image row and column 2^pp times. */ - line = ((y>>pp) + yOffset) * iPtr->masterPtr->width; - for (x = 0; x < width; x++) { - masterPtr = alphaAr + ((line + (x>>pp) + xOffset) * 4); -#endif alpha = masterPtr[3]; /* @@ -599,16 +574,13 @@ BlendComplexAlpha( g = ALPHA_BLEND(ga, g, alpha, unalpha); b = ALPHA_BLEND(ba, b, alpha, unalpha); } -#ifndef MAC_OSX_TK XPutPixel(bgImg, x, y, RGB(r, g, b)); -#else - XPutPixel(bgImg, x, y, RGBA(r, g, b, alpha)); -#endif } } } #undef ALPHA_BLEND } +#endif /* TKPUTIMAGE_CAN_BLEND */ /* *---------------------------------------------------------------------- @@ -640,8 +612,10 @@ TkImgPhotoDisplay( * to imageX and imageY. */ { PhotoInstance *instancePtr = clientData; +#ifndef TKPUTIMAGE_CAN_BLEND XVisualInfo visInfo = instancePtr->visualInfo; - +#endif + /* * If there's no pixmap, it means that an error occurred while creating * the image instance so it can't be displayed. @@ -651,6 +625,24 @@ TkImgPhotoDisplay( return; } +#ifdef TKPUTIMAGE_CAN_BLEND + /* + * If TkPutImage can handle RGBA Ximages directly there is + * no need to call XGetImage or to do the Porter-Duff compositing by hand. + */ + + unsigned char *rgbaPixels = instancePtr->masterPtr->pix32; + XImage *photo = XCreateImage(display, NULL, 32, ZPixmap, 0, (char*)rgbaPixels, + (unsigned int)instancePtr->width, + (unsigned int)instancePtr->height, + 0, (unsigned int)(4 * instancePtr->width)); + TkPutImage(NULL, 0, display, drawable, instancePtr->gc, + photo, imageX, imageY, drawableX, drawableY, + (unsigned int) width, (unsigned int) height); + photo->data = NULL; + XDestroyImage(photo); +#else + if ((instancePtr->masterPtr->flags & COMPLEX_ALPHA) && visInfo.depth >= 15 && (visInfo.class == DirectColor || visInfo.class == TrueColor)) { @@ -709,6 +701,7 @@ TkImgPhotoDisplay( XSetClipOrigin(display, instancePtr->gc, 0, 0); } XFlush(display); +#endif } /* diff --git a/generic/tkInt.decls b/generic/tkInt.decls index a13d8d7..d0b7678 100644 --- a/generic/tkInt.decls +++ b/generic/tkInt.decls @@ -983,9 +983,9 @@ declare 38 aqua { declare 39 aqua { void TkSetWMName(TkWindow *winPtr, Tk_Uid titleUid) } -declare 40 aqua { - void TkSuspendClipboard(void) -} +# +# Slot 40 unused (WAS: TkSuspendClipboard) +# declare 41 aqua { int TkMacOSXZoomToplevel(void *whichWindow, short zoomPart) } diff --git a/generic/tkIntPlatDecls.h b/generic/tkIntPlatDecls.h index e48e803..ded5ac5 100644 --- a/generic/tkIntPlatDecls.h +++ b/generic/tkIntPlatDecls.h @@ -224,8 +224,7 @@ EXTERN void TkMacOSXWindowOffset(void *wRef, int *xOffset, EXTERN int TkSetMacColor(unsigned long pixel, void *macColor); /* 39 */ EXTERN void TkSetWMName(TkWindow *winPtr, Tk_Uid titleUid); -/* 40 */ -EXTERN void TkSuspendClipboard(void); +/* Slot 40 is reserved */ /* 41 */ EXTERN int TkMacOSXZoomToplevel(void *whichWindow, short zoomPart); @@ -384,7 +383,7 @@ typedef struct TkIntPlatStubs { void (*tkMacOSXWindowOffset) (void *wRef, int *xOffset, int *yOffset); /* 37 */ int (*tkSetMacColor) (unsigned long pixel, void *macColor); /* 38 */ void (*tkSetWMName) (TkWindow *winPtr, Tk_Uid titleUid); /* 39 */ - void (*tkSuspendClipboard) (void); /* 40 */ + void (*reserved40)(void); int (*tkMacOSXZoomToplevel) (void *whichWindow, short zoomPart); /* 41 */ Tk_Window (*tk_TopCoordsToWindow) (Tk_Window tkwin, int rootX, int rootY, int *newX, int *newY); /* 42 */ MacDrawable * (*tkMacOSXContainerId) (TkWindow *winPtr); /* 43 */ @@ -599,8 +598,7 @@ extern const TkIntPlatStubs *tkIntPlatStubsPtr; (tkIntPlatStubsPtr->tkSetMacColor) /* 38 */ #define TkSetWMName \ (tkIntPlatStubsPtr->tkSetWMName) /* 39 */ -#define TkSuspendClipboard \ - (tkIntPlatStubsPtr->tkSuspendClipboard) /* 40 */ +/* Slot 40 is reserved */ #define TkMacOSXZoomToplevel \ (tkIntPlatStubsPtr->tkMacOSXZoomToplevel) /* 41 */ #define Tk_TopCoordsToWindow \ diff --git a/generic/tkMenuDraw.c b/generic/tkMenuDraw.c index 1abe1c4..3f492db 100644 --- a/generic/tkMenuDraw.c +++ b/generic/tkMenuDraw.c @@ -624,7 +624,6 @@ DisplayMenu( int width; int borderWidth; Tk_3DBorder border; - int activeBorderWidth; int relief; @@ -636,8 +635,6 @@ DisplayMenu( Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, &borderWidth); border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); - Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, - menuPtr->activeBorderWidthPtr, &activeBorderWidth); if (menuPtr->menuType == MENUBAR) { Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, borderWidth, @@ -668,28 +665,16 @@ DisplayMenu( } mePtr->entryFlags &= ~ENTRY_NEEDS_REDISPLAY; - if (menuPtr->menuType == MENUBAR) { - width = mePtr->width; - } else { - if (mePtr->entryFlags & ENTRY_LAST_COLUMN) { - width = Tk_Width(menuPtr->tkwin) - mePtr->x - - activeBorderWidth; - } else { - width = mePtr->width + borderWidth; - } - } TkpDrawMenuEntry(mePtr, Tk_WindowId(menuPtr->tkwin), tkfont, - &menuMetrics, mePtr->x, mePtr->y, width, + &menuMetrics, mePtr->x, mePtr->y, mePtr->width, mePtr->height, strictMotif, 1); if ((index > 0) && (menuPtr->menuType != MENUBAR) && mePtr->columnBreak) { mePtr = menuPtr->entries[index - 1]; Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, - mePtr->x, mePtr->y + mePtr->height, - mePtr->width, - Tk_Height(tkwin) - mePtr->y - mePtr->height - - activeBorderWidth, 0, - TK_RELIEF_FLAT); + mePtr->x, mePtr->y + mePtr->height, mePtr->width, + Tk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth, + 0, TK_RELIEF_FLAT); } } @@ -698,19 +683,18 @@ DisplayMenu( if (menuPtr->numEntries == 0) { x = y = borderWidth; - width = Tk_Width(tkwin) - 2 * activeBorderWidth; - height = Tk_Height(tkwin) - 2 * activeBorderWidth; + width = Tk_Width(tkwin) - 2 * borderWidth; + height = Tk_Height(tkwin) - 2 * borderWidth; } else { mePtr = menuPtr->entries[menuPtr->numEntries - 1]; Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, mePtr->x, mePtr->y + mePtr->height, mePtr->width, - Tk_Height(tkwin) - mePtr->y - mePtr->height - - activeBorderWidth, 0, - TK_RELIEF_FLAT); + Tk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth, + 0, TK_RELIEF_FLAT); x = mePtr->x + mePtr->width; y = mePtr->y + mePtr->height; - width = Tk_Width(tkwin) - x - activeBorderWidth; - height = Tk_Height(tkwin) - y - activeBorderWidth; + width = Tk_Width(tkwin) - x - borderWidth; + height = Tk_Height(tkwin) - y - borderWidth; } Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, x, y, width, height, 0, TK_RELIEF_FLAT); diff --git a/generic/tkOption.c b/generic/tkOption.c index 24e7fb3..545a9b9 100644 --- a/generic/tkOption.c +++ b/generic/tkOption.c @@ -996,6 +996,9 @@ AddFromString( while ((*src == ' ') || (*src == '\t')) { src++; } + if (*src == '\\' && (src[1] == '\t' || src[1] == ' ')) { + src++; + } if (*src == '\0') { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "missing value on line %d", lineNum)); @@ -1025,7 +1028,7 @@ AddFromString( src += 2; *dst++ = '\n'; continue; - } else if (src[1] == '\t' || src[1] == ' ' || src[1] == '\\') { + } else if (src[1] == '\\') { ++src; } else if (src[1] >= '0' && src[1] <= '3' && src[2] >= '0' && src[2] <= '9' && src[3] >= '0' && src[3] <= '9') { diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index 9411c26..7e02302 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -547,7 +547,7 @@ static const TkIntPlatStubs tkIntPlatStubs = { TkMacOSXWindowOffset, /* 37 */ TkSetMacColor, /* 38 */ TkSetWMName, /* 39 */ - TkSuspendClipboard, /* 40 */ + 0, /* 40 */ TkMacOSXZoomToplevel, /* 41 */ Tk_TopCoordsToWindow, /* 42 */ TkMacOSXContainerId, /* 43 */ diff --git a/generic/tkTest.c b/generic/tkTest.c index 1fa461e..6712017 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 0 #endif #ifdef __UNIX__ @@ -168,7 +171,7 @@ static int TestmenubarObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); #endif -#if defined(_WIN32) || defined(MAC_OSX_TK) +#if defined(_WIN32) static int TestmetricsObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); @@ -266,17 +269,17 @@ Tktest_Init( Tcl_CreateObjCommand(interp, "testtext", TkpTesttextCmd, (ClientData) Tk_MainWindow(interp), NULL); -#if defined(_WIN32) || defined(MAC_OSX_TK) +#if defined(_WIN32) Tcl_CreateObjCommand(interp, "testmetrics", TestmetricsObjCmd, (ClientData) Tk_MainWindow(interp), NULL); -#elif !defined(__CYGWIN__) +#elif !defined(__CYGWIN__) && !defined(MAC_OSX_TK) Tcl_CreateObjCommand(interp, "testmenubar", TestmenubarObjCmd, (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testsend", TkpTestsendCmd, (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testwrapper", TestwrapperObjCmd, (ClientData) Tk_MainWindow(interp), NULL); -#endif /* _WIN32 || MAC_OSX_TK */ +#endif /* _WIN32 */ /* * Create test image type. @@ -1550,16 +1553,36 @@ ImageDisplay( TImageInstance *instPtr = (TImageInstance *) clientData; char buffer[200 + TCL_INTEGER_SPACE * 6]; + /* + * 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. + */ + 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 (!APP_IS_DRAWING) { + 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)); XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY, @@ -1764,7 +1787,7 @@ TestmenubarObjCmd( *---------------------------------------------------------------------- */ -#if defined(_WIN32) || defined(MAC_OSX_TK) +#if defined(_WIN32) static int TestmetricsObjCmd( ClientData clientData, /* Main window for application. */ @@ -1775,38 +1798,15 @@ TestmetricsObjCmd( char buf[TCL_INTEGER_SPACE]; int val; -#ifdef _WIN32 if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } -#else - Tk_Window tkwin = (Tk_Window) clientData; - TkWindow *winPtr; - - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "option window"); - return TCL_ERROR; - } - - winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); - if (winPtr == NULL) { - return TCL_ERROR; - } -#endif if (strcmp(Tcl_GetString(objv[1]), "cyvscroll") == 0) { -#ifdef _WIN32 val = GetSystemMetrics(SM_CYVSCROLL); -#else - val = ((TkScrollbar *) winPtr->instanceData)->width; -#endif } else if (strcmp(Tcl_GetString(objv[1]), "cxhscroll") == 0) { -#ifdef _WIN32 val = GetSystemMetrics(SM_CXHSCROLL); -#else - val = ((TkScrollbar *) winPtr->instanceData)->width; -#endif } else { Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]), "\": must be cxhscroll or cyvscroll", NULL); diff --git a/generic/tkText.c b/generic/tkText.c index d43bef6..4c536a2 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -5823,7 +5823,7 @@ SearchCore( firstOffset = 0; } - if (alreadySearchOffset != -1) { + if (alreadySearchOffset >= 0) { if (searchSpecPtr->backwards) { if (alreadySearchOffset < lastOffset) { lastOffset = alreadySearchOffset; @@ -5912,17 +5912,17 @@ SearchCore( * match. */ - const char c = pattern[0]; + const char c = matchLength ? pattern[0] : '\0'; - if (alreadySearchOffset != -1) { + if (alreadySearchOffset >= 0) { p = startOfLine + alreadySearchOffset; alreadySearchOffset = -1; } else { p = startOfLine + lastOffset -1; } while (p >= startOfLine + firstOffset) { - if (p[0] == c && !strncmp(p, pattern, - (size_t) matchLength)) { + if (matchLength == 0 || (p[0] == c && !strncmp( + p, pattern, (size_t) matchLength))) { goto backwardsMatch; } p--; @@ -6085,10 +6085,14 @@ SearchCore( if (firstNewLine != -1) { break; } else { - alreadySearchOffset -= matchLength; + alreadySearchOffset -= (matchLength ? matchLength : 1); + if (alreadySearchOffset < 0) { + break; + } } } else { - firstOffset = p - startOfLine + matchLength; + firstOffset = matchLength ? p - startOfLine + matchLength + : p - startOfLine + 1; if (firstOffset >= lastOffset) { /* * Now, we have to be careful not to find diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 126b631..348b8c4 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -24,6 +24,11 @@ #ifdef MAC_OSX_TK #include "tkMacOSXInt.h" +#define OK_TO_LOG (!TkpAppIsDrawing()) +#define FORCE_DISPLAY(winPtr) TkpDisplayWindow(winPtr) +#else +#define OK_TO_LOG 1 +#define FORCE_DISPLAY(winPtr) #endif /* @@ -203,12 +208,21 @@ typedef struct TextStyle { (fabs((double1)-(double2))*((scaleFactor)+1.0) < 0.3) /* - * Macro to make debugging/testing logging a little easier. + * Macros to make debugging/testing logging a little easier. + * + * On OSX 10.14 Drawing procedures are sometimes run because the system has + * decided to redraw the window. This can corrupt the data that a test is + * trying to collect. So we don't write to the logging variables when the + * drawing procedure is being run that way. Other systems can always log. */ -#define LOG(toVar,what) \ - Tcl_SetVar2(textPtr->interp, toVar, NULL, (what), \ - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT) +#define LOG(toVar,what) \ + if (OK_TO_LOG) \ + Tcl_SetVar2(textPtr->interp, toVar, NULL, (what), \ + TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT) +#define CLEAR(var) \ + if (OK_TO_LOG) \ + Tcl_SetVar2(interp, var, NULL, "", TCL_GLOBAL_ONLY) /* * The following structure describes one line of the display, which may be @@ -3121,6 +3135,18 @@ GenerateWidgetViewSyncEvent( TkText *textPtr, /* Information about text widget. */ Bool InSync) /* true if in sync, false otherwise */ { + /* + * OSX 10.14 needs to be told to display the window when the Text Widget + * is in sync. (That is, to run DisplayText inside of the drawRect + * method.) Otherwise the screen might not get updated until an event + * like a mouse click is received. But that extra drawing corrupts the + * data that the test suite is trying to collect. + */ + + if (!tkTextDebug) { + FORCE_DISPLAY(textPtr->tkwin); + } + TkSendVirtualEvent(textPtr->tkwin, "WidgetViewSync", Tcl_NewBooleanObj(InSync)); } @@ -4136,7 +4162,7 @@ DisplayText( Tcl_Preserve(interp); if (tkTextDebug) { - Tcl_SetVar2(interp, "tk_textRelayout", NULL, "", TCL_GLOBAL_ONLY); + CLEAR("tk_textRelayout"); } if (!Tk_IsMapped(textPtr->tkwin) || (dInfoPtr->maxX <= dInfoPtr->x) @@ -4147,7 +4173,7 @@ DisplayText( } numRedisplays++; if (tkTextDebug) { - Tcl_SetVar2(interp, "tk_textRedraw", NULL, "", TCL_GLOBAL_ONLY); + CLEAR("tk_textRedraw"); } /* @@ -5134,6 +5160,7 @@ TkTextRelayoutWindow( TextDInfo *dInfoPtr = textPtr->dInfoPtr; GC newGC; XGCValues gcValues; + Bool inSync = 1; /* * Schedule the window redisplay. See TkTextChanged for the reason why @@ -5142,6 +5169,7 @@ TkTextRelayoutWindow( if (!(dInfoPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(DisplayText, textPtr); + inSync = 0; } dInfoPtr->flags |= REDRAW_PENDING|REDRAW_BORDERS|DINFO_OUT_OF_DATE |REPICK_NEEDED; @@ -5213,6 +5241,7 @@ TkTextRelayoutWindow( dInfoPtr->yScrollFirst = dInfoPtr->yScrollLast = -1; if (mask & TK_TEXT_LINE_GEOMETRY) { + /* * Set up line metric recalculation. * @@ -5237,7 +5266,11 @@ TkTextRelayoutWindow( textPtr->refCount++; dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, textPtr); - GenerateWidgetViewSyncEvent(textPtr, 0); + inSync = 0; + } + + if (!inSync) { + GenerateWidgetViewSyncEvent(textPtr, 0); } } } @@ -6264,7 +6297,8 @@ TkTextPendingsync( TextDInfo *dInfoPtr = textPtr->dInfoPtr; return ( - ((dInfoPtr->metricEpoch == -1) && + (!(dInfoPtr->flags & REDRAW_PENDING) && + (dInfoPtr->metricEpoch == -1) && (dInfoPtr->lastMetricUpdateLine == dInfoPtr->currentMetricUpdateLine)) ? 0 : 1); } diff --git a/generic/ttk/ttkDefaultTheme.c b/generic/ttk/ttkDefaultTheme.c index 4a06192..d331655 100644 --- a/generic/ttk/ttkDefaultTheme.c +++ b/generic/ttk/ttkDefaultTheme.c @@ -18,6 +18,10 @@ static const int WIN32_XDRAWLINE_HACK = 1; static const int WIN32_XDRAWLINE_HACK = 0; #endif +#if defined(MAC_OSX_TK) + #define IGNORES_VISUAL +#endif + #define BORDERWIDTH 2 #define SCROLLBAR_WIDTH 14 #define MIN_THUMB_SIZE 8 @@ -510,7 +514,7 @@ static void IndicatorElementDraw( XGCValues gcValues; GC copyGC; unsigned long imgColors[8]; - XImage *img; + XImage *img = NULL; Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding); b = Ttk_PadBox(b, padding); @@ -550,15 +554,48 @@ static void IndicatorElementDraw( /* * Create a scratch buffer to store the image: */ - img = XGetImage(display,d, 0, 0, - (unsigned int)spec->width, (unsigned int)spec->height, - AllPlanes, ZPixmap); - if (img == NULL) + +#if defined(IGNORES_VISUAL) + + /* + * Platforms which ignore the VisualInfo can use XCreateImage to get the + * scratch image. This is essential on macOS, where it is not safe to call + * XGetImage in a display procedure. + */ + + img = XCreateImage(display, NULL, 32, ZPixmap, 0, NULL, + (unsigned int)spec->width, (unsigned int)spec->height, + 0, 0); +#else + + /* + * This trick allows creating the scratch XImage without having to + * construct a VisualInfo. + */ + + img = XGetImage(display, d, 0, 0, + (unsigned int)spec->width, (unsigned int)spec->height, + AllPlanes, ZPixmap); +#endif + + if (img == NULL) { + return; + } + +#if defined(IGNORES_VISUAL) + + img->data = ckalloc(img->bytes_per_line * img->height); + if (img->data == NULL) { + XDestroyImage(img); return; + } + +#endif /* - * Create the image, painting it into an XImage one pixel at a time. + * Create the image, painting it into the XImage one pixel at a time. */ + index = Ttk_StateTableLookup(spec->map, state); for (iy=0 ; iy<spec->height ; iy++) { for (ix=0 ; ix<spec->width ; ix++) { @@ -568,18 +605,31 @@ static void IndicatorElementDraw( } /* - * Copy onto our target drawable surface. + * Copy the image onto our target drawable surface. */ + memset(&gcValues, 0, sizeof(gcValues)); copyGC = Tk_GetGC(tkwin, 0, &gcValues); - TkPutImage(NULL, 0, display, d, copyGC, img, 0, 0, b.x, b.y, spec->width, spec->height); /* * Tidy up. */ + Tk_FreeGC(display, copyGC); + + /* + * Protect against the possibility that some future platform might + * not use the Tk memory manager in its implementation of XDestroyImage, + * even though that would be an extremely strange thing to do. + */ + +#if defined(IGNORES_VISUAL) + ckfree(img->data); + img->data = NULL; +#endif + XDestroyImage(img); } diff --git a/generic/ttk/ttkTheme.c b/generic/ttk/ttkTheme.c index 2f95962..c0bd784 100644 --- a/generic/ttk/ttkTheme.c +++ b/generic/ttk/ttkTheme.c @@ -18,6 +18,13 @@ #define PKG_ASSOC_KEY "Ttk" +#ifdef MAC_OSX_TK + extern void TkMacOSXFlushWindows(void); + #define UPDATE_WINDOWS() TkMacOSXFlushWindows() +#else + #define UPDATE_WINDOWS() +#endif + /*------------------------------------------------------------------------ * +++ Styles. * @@ -513,6 +520,7 @@ static void ThemeChangedProc(ClientData clientData) Tcl_BackgroundException(pkgPtr->interp, code); } pkgPtr->themeChangePending = 0; + UPDATE_WINDOWS(); } /* diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index d957ad2..bef84f3 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -1825,7 +1825,7 @@ static int DrawSubtree( static int DrawForest( Treeview *tv, TreeItem *item, Drawable d, int depth, int row) { - while (item && row <= tv->tree.yscroll.last) { + while (item && row < tv->tree.yscroll.last) { row = DrawSubtree(tv, item, d, depth, row); item = item->next; } diff --git a/library/demos/ttkbut.tcl b/library/demos/ttkbut.tcl index 904cd31..ab49cf4 100644 --- a/library/demos/ttkbut.tcl +++ b/library/demos/ttkbut.tcl @@ -21,7 +21,7 @@ ttk::label $w.msg -font $font -wraplength 4i -justify left -text "Ttk is the new pack $w.msg -side top -fill x ## See Code / Dismiss -pack [addSeeDismiss $w.seeDismiss $w {enabled cheese tomato basil oregano happyness}]\ +pack [addSeeDismiss $w.seeDismiss $w {enabled cheese tomato basil oregano happiness}]\ -side bottom -fill x ## Add buttons for setting the theme @@ -69,11 +69,11 @@ pack $w.checks.e $w.checks.sep1 $w.checks.c1 $w.checks.c2 $w.checks.sep2 \ ## Set up the radiobutton group ttk::labelframe $w.radios -text "Radiobuttons" -ttk::radiobutton $w.radios.r1 -text "Great" -variable happyness -value great -ttk::radiobutton $w.radios.r2 -text "Good" -variable happyness -value good -ttk::radiobutton $w.radios.r3 -text "OK" -variable happyness -value ok -ttk::radiobutton $w.radios.r4 -text "Poor" -variable happyness -value poor -ttk::radiobutton $w.radios.r5 -text "Awful" -variable happyness -value awful +ttk::radiobutton $w.radios.r1 -text "Great" -variable happiness -value great +ttk::radiobutton $w.radios.r2 -text "Good" -variable happiness -value good +ttk::radiobutton $w.radios.r3 -text "OK" -variable happiness -value ok +ttk::radiobutton $w.radios.r4 -text "Poor" -variable happiness -value poor +ttk::radiobutton $w.radios.r5 -text "Awful" -variable happiness -value awful pack $w.radios.r1 $w.radios.r2 $w.radios.r3 $w.radios.r4 $w.radios.r5 \ -fill x -padx 3 -pady 2 diff --git a/library/tk.tcl b/library/tk.tcl index d2f7b65..61d1354 100644 --- a/library/tk.tcl +++ b/library/tk.tcl @@ -11,7 +11,7 @@ # this file, and for a DISCLAIMER OF ALL WARRANTIES. # Verify that we have Tk binary and script components from the same release -package require -exact Tk 8.6.8 +package require -exact Tk 8.6.9 # Create a ::tk namespace namespace eval ::tk { diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl index 8772587..1ed87db 100644 --- a/library/ttk/treeview.tcl +++ b/library/ttk/treeview.tcl @@ -120,7 +120,7 @@ proc ttk::treeview::ActivateHeading {w heading} { variable State if {$w != $State(activeWidget) || $heading != $State(activeHeading)} { - if {$State(activeHeading) != {}} { + if {[winfo exists $State(activeWidget)] && $State(activeHeading) != {}} { $State(activeWidget) heading $State(activeHeading) state !active } if {$heading != {}} { diff --git a/macosx/README b/macosx/README index bcd5dce..c63b8ae 100644 --- a/macosx/README +++ b/macosx/README @@ -561,3 +561,12 @@ source and destination rectangles for the scrolling. The embedded windows are redrawn within the DisplayText function by some conditional code which is only used for macOS. +5.0 Virtual events on 10.14 +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +10.14 supports system appearance changes, and has added a "Dark Mode" +that casts all window frames and menus as black. Tk 8.6.9 has added two +virtual events, <<LightAqua>> and <<DarkAqua>>, to allow you to update +your Tk app's appearance when the system appearance changes. Just bind +your appearance-updating code to these virtual events and you will see +it triggered when the system appearance toggles between dark and light. diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index 6930a36..ea78d43 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -420,6 +420,9 @@ TkpComputeButtonGeometry( width += butPtr->inset*2; height += butPtr->inset*2; + if ([NSApp macMinorVersion] == 6) { + width += 12; + } Tk_GeometryRequest(butPtr->tkwin, width, height); Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset); @@ -1198,3 +1201,11 @@ PulseDefaultButtonProc(ClientData clientData) PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData); } +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c index 07a8419..efd3c69 100644 --- a/macosx/tkMacOSXClipboard.c +++ b/macosx/tkMacOSXClipboard.c @@ -12,6 +12,7 @@ */ #include "tkMacOSXPrivate.h" +#include "tkMacOSXConstants.h" #include "tkSelect.h" static NSInteger changeCount = -1; @@ -70,10 +71,8 @@ static Tk_Window clipboardOwner = NULL; if (clipboardOwner && [[NSPasteboard generalPasteboard] changeCount] != changeCount) { TkDisplay *dispPtr = TkGetDisplayList(); - if (dispPtr) { XEvent event; - event.xany.type = SelectionClear; event.xany.serial = NextRequest(Tk_Display(clipboardOwner)); event.xany.send_event = False; @@ -125,8 +124,10 @@ TkSelGetSelection( int result = TCL_ERROR; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (dispPtr && selection == dispPtr->clipboardAtom && (target == XA_STRING - || target == dispPtr->utf8Atom)) { + int haveExternalClip = ([[NSPasteboard generalPasteboard] changeCount] != changeCount); + if (dispPtr && (haveExternalClip || dispPtr->clipboardActive) + && selection == dispPtr->clipboardAtom + && (target == XA_STRING || target == dispPtr->utf8Atom)) { NSString *string = nil; NSPasteboard *pb = [NSPasteboard generalPasteboard]; NSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject: @@ -176,7 +177,6 @@ XSetSelectionOwner( clipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL; if (!dispPtr->clipboardActive) { NSPasteboard *pb = [NSPasteboard generalPasteboard]; - changeCount = [pb declareTypes:[NSArray array] owner:NSApp]; } } @@ -290,28 +290,6 @@ TkSelPropProc( } /* - *---------------------------------------------------------------------- - * - * TkSuspendClipboard -- - * - * Handle clipboard conversion as required by the suppend event. - * - * Results: - * None. - * - * Side effects: - * The local scrap is moved to the global scrap. - * - *---------------------------------------------------------------------- - */ - -void -TkSuspendClipboard(void) -{ - changeCount = [[NSPasteboard generalPasteboard] changeCount]; -} - -/* * Local Variables: * mode: objc * c-basic-offset: 4 diff --git a/macosx/tkMacOSXConfig.c b/macosx/tkMacOSXConfig.c index bdfcb6e..841fc54 100644 --- a/macosx/tkMacOSXConfig.c +++ b/macosx/tkMacOSXConfig.c @@ -41,3 +41,12 @@ TkpGetSystemDefault( { return NULL; } + +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ diff --git a/macosx/tkMacOSXConstants.h b/macosx/tkMacOSXConstants.h index 95983dd..0badf1a 100644 --- a/macosx/tkMacOSXConstants.h +++ b/macosx/tkMacOSXConstants.h @@ -15,18 +15,32 @@ #ifndef _TKMACCONSTANTS #define _TKMACCONSTANTS +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 +#define NSFullScreenWindowMask (1 << 14) +#endif + /* * Let's raise a glass for the project manager who improves our lives by * generating deprecation warnings about pointless changes of the names * of constants. */ +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +#define kCTFontDefaultOrientation kCTFontOrientationDefault +#define kCTFontVerticalOrientation kCTFontOrientationVertical +#endif + #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 #define NSOKButton NSModalResponseOK #endif +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101100 +#define kCTFontUserFixedPitchFontType kCTFontUIFontUserFixedPitch +#endif + #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 #define NSAppKitDefined NSEventTypeAppKitDefined +#define NSApplicationDefined NSEventTypeApplicationDefined #define NSApplicationActivatedEventType NSEventSubtypeApplicationActivated #define NSApplicationDeactivatedEventType NSEventSubtypeApplicationDeactivated #define NSWindowExposedEventType NSEventSubtypeWindowExposed @@ -79,6 +93,7 @@ #define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock #define NSShiftKeyMask NSEventModifierFlagShift #define NSAnyEventMask NSEventMaskAny +#define NSApplicationDefinedMask NSEventMaskApplicationDefined #define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground #define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow #define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel @@ -90,6 +105,17 @@ #define NSUnifiedTitleAndToolbarWindowMask NSWindowStyleMaskUnifiedTitleAndToolbar #define NSMiniaturizableWindowMask NSWindowStyleMaskMiniaturizable #define NSBorderlessWindowMask NSWindowStyleMaskBorderless +#define NSFullScreenWindowMask NSWindowStyleMaskFullScreen #endif +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 +#define NSStringPboardType NSPasteboardTypeString +#define NSOnState NSControlStateValueOn +#define NSOffState NSControlStateValueOff +// Now we are also changing names of methods! +#define graphicsContextWithGraphicsPort graphicsContextWithCGContext #endif + + +#endif + diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index 8d20d4e..e828b39 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -182,10 +182,6 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { #pragma mark TKApplication(TKDialog) -@interface NSColorPanel(TKDialog) -- (void) _setUseModalAppearance: (BOOL) flag; -@end - @implementation TKApplication(TKDialog) - (void) tkFilePanelDidEnd: (NSSavePanel *) panel @@ -1198,36 +1194,42 @@ TkAboutDlg(void) NSString *year = [dateFormatter stringFromDate:[NSDate date]]; [dateFormatter release]; - - NSMutableParagraphStyle *style = - [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] - autorelease]; - - [style setAlignment:NSCenterTextAlignment]; - - NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: - @"Tcl & Tk", @"ApplicationName", - @"Tcl " TCL_VERSION " & Tk " TK_VERSION, @"ApplicationVersion", - @TK_PATCH_LEVEL, @"Version", - image, @"ApplicationIcon", - [NSString stringWithFormat:@"Copyright %1$C 1987-%2$@.", 0xA9, - year], @"Copyright", - [[[NSAttributedString alloc] initWithString: - [NSString stringWithFormat: - @"%1$C 1987-%2$@ Tcl Core Team." "\n\n" - "%1$C 1989-%2$@ Contributors." "\n\n" - "%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC." "\n\n" - "%1$C 2014-%2$@ Marc Culler." "\n\n" - "%1$C 2002-%2$@ Daniel A. Steffen." "\n\n" - "%1$C 2001-2009 Apple Inc." "\n\n" - "%1$C 2001-2002 Jim Ingham & Ian Reid" "\n\n" - "%1$C 1998-2000 Jim Ingham & Ray Johnson" "\n\n" - "%1$C 1998-2000 Scriptics Inc." "\n\n" - "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] attributes: - [NSDictionary dictionaryWithObject:style - forKey:NSParagraphStyleAttributeName]] autorelease], @"Credits", - nil]; - [NSApp orderFrontStandardAboutPanelWithOptions:options]; + + /* + * This replaces the old about dialog with a standard alert that displays + * correctly on 10.14. + */ + + NSString *version = @"Tcl " TCL_PATCH_LEVEL " & Tk " TCL_PATCH_LEVEL; + NSString *url = @"www.tcl-lang.org"; + NSTextView *credits = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,300,300)]; + NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; + NSDictionary *textAttributes = [NSDictionary dictionaryWithObject:font + forKey:NSFontAttributeName]; + [credits insertText: [[NSAttributedString alloc] + initWithString:[NSString stringWithFormat: @"\n" + "Tcl and Tk are distributed under a modified BSD license: " + "www.tcl.tk/software/tcltk/license.html\n\n" + "%1$C 1987-%2$@ Tcl Core Team and Contributers.\n\n" + "%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC.\n\n" + "%1$C 2014-%2$@ Marc Culler.\n\n" + "%1$C 2002-2012 Daniel A. Steffen.\n\n" + "%1$C 2001-2009 Apple Inc.\n\n" + "%1$C 2001-2002 Jim Ingham & Ian Reid\n\n" + "%1$C 1998-2000 Jim Ingham & Ray Johnson\n\n" + "%1$C 1998-2000 Scriptics Inc.\n\n" + "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] + attributes:textAttributes] + replacementRange:NSMakeRange(0,0)]; + [credits setDrawsBackground:NO]; + [credits setEditable:NO]; + NSAlert *about = [[NSAlert alloc] init]; + [[about window] setTitle:@"About Tcl & Tk"]; + [about setMessageText: version]; + [about setInformativeText:url]; + about.accessoryView = credits; + [about runModal]; + [about release]; } /* @@ -1257,7 +1259,7 @@ TkMacOSXStandardAboutPanelObjCmd( Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } - [NSApp orderFrontStandardAboutPanelWithOptions:[NSDictionary dictionary]]; + TkAboutDlg(); return TCL_OK; } diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 1e1e893..faad137 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -18,6 +18,12 @@ #include "tkMacOSXDebug.h" #include "tkButton.h" +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 +#define GET_CGCONTEXT [[NSGraphicsContext currentContext] CGContext] +#else +#define GET_CGCONTEXT [[NSGraphicsContext currentContext] graphicsPort] +#endif + /* #ifdef TK_MAC_DEBUG #define TK_MAC_DEBUG_DRAWING @@ -105,6 +111,25 @@ TkMacOSXInitCGDrawing( * * Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep. * + * This is only used by XGetImage, which is never called. And this + * implementation does not work correctly. Originally it relied on + * [NSBitmapImageRep initWithFocusedViewRect:view_rect] which was + * deprecated by Apple in OSX 10.14 and also required the use of other + * deprecated functions such as [NSView lockFocus]. Apple's suggested + * replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that + * is what is being used here. However, that method only works when the + * view has a valid CGContext, and a view is only guaranteed to have a + * valid context during a call to [NSView drawRect]. To further + * complicate matters, cacheDisplayInRect calls [NSView drawRect]. + * Essentially it is asking the view to draw a subrectangle of itself into + * a special graphics context which is linked to the BitmapImageRep. But + * our implementation of [NSView drawRect] does not allow recursive calls. + * If called recursively it returns immediately without doing any drawing. + * So the bottom line is that this function either returns a NULL pointer + * or a black image. To make it useful would require a significant amount + * of rewriting of the drawRect method. Perhaps the next release of OSX + * will include some more helpful ways of doing this. + * * Results: * Returns an NSBitmapRep representing the image of the given * rectangle of the given drawable. This object is retained. @@ -128,15 +153,16 @@ TkMacOSXBitmapRepFromDrawableRect( unsigned int height) { MacDrawable *mac_drawable = (MacDrawable *) drawable; - CGContextRef cg_context=NULL; - CGImageRef cg_image=NULL, sub_cg_image=NULL; - NSBitmapImageRep *bitmap_rep=NULL; + CGContextRef cg_context = NULL; + CGImageRef cg_image=NULL, sub_cg_image = NULL; + NSBitmapImageRep *bitmap_rep = NULL; NSView *view=NULL; if ( mac_drawable->flags & TK_IS_PIXMAP ) { + /* - * This means that the MacDrawable is functioning as a - * Tk Pixmap, so its view field is NULL. - */ + * This MacDrawable is a bitmap, so its view is NULL. + */ + cg_context = TkMacOSXGetCGContextForDrawable(drawable); CGRect image_rect = CGRectMake(x, y, width, height); cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context); @@ -149,22 +175,32 @@ TkMacOSXBitmapRepFromDrawableRect( CGImageRelease(cg_image); } } else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) { + /* * Convert Tk top-left to NSView bottom-left coordinates. */ + int view_height = [view bounds].size.height; NSRect view_rect = NSMakeRect(x + mac_drawable->xOff, view_height - height - y - mac_drawable->yOff, width, height); - if ( [view lockFocusIfCanDraw] ) { - bitmap_rep = [NSBitmapImageRep alloc]; - bitmap_rep = [bitmap_rep initWithFocusedViewRect:view_rect]; - [view unlockFocus]; + /* + * Attempt to copy from the view to a bitmapImageRep. If the view does + * not have a valid CGContext, doing this will silently corrupt memory + * and make a big mess. So, in that case, we mark the view as needing + * display and return NULL. + */ + + if (view == [NSView focusView]) { + bitmap_rep = [view bitmapImageRepForCachingDisplayInRect: view_rect]; + [bitmap_rep retain]; + [view cacheDisplayInRect:view_rect toBitmapImageRep:bitmap_rep]; } else { - TkMacOSXDbgMsg("Could not lock focus on view."); + TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap."); + [view setNeedsDisplay:YES]; + return NULL; } - } else { TkMacOSXDbgMsg("Invalid source drawable"); } @@ -205,26 +241,24 @@ XCopyArea( MacDrawable *srcDraw = (MacDrawable *) src; NSBitmapImageRep *bitmap_rep = NULL; CGImageRef img = NULL; + CGRect bounds, srcRect, dstRect; display->request++; - if (!width || !height) { - /* This happens all the time. - TkMacOSXDbgMsg("Drawing of empty area requested"); - */ return; } if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) { return; - /*TkMacOSXDbgMsg("Failed to setup drawing context.");*/ + TkMacOSXDbgMsg("Failed to setup drawing context."); } if ( dc.context ) { if (srcDraw->flags & TK_IS_PIXMAP) { img = TkMacOSXCreateCGImageWithDrawable(src); }else if (TkMacOSXDrawableWindow(src)) { - bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src, src_x, src_y, width, height); + bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src, + src_x, src_y, width, height); if ( bitmap_rep ) { img = [bitmap_rep CGImage]; } @@ -233,13 +267,12 @@ XCopyArea( } if (img) { - TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, gc->background, - CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height), - CGRectMake(src_x, src_y, width, height), - CGRectMake(dest_x, dest_y, width, height)); + bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height); + srcRect = CGRectMake(src_x, src_y, width, height); + dstRect = CGRectMake(dest_x, dest_y, width, height); + TkMacOSXDrawCGImage(dst, gc, dc.context, img, + gc->foreground, gc->background, bounds, srcRect, dstRect); CFRelease(img); - - } else { TkMacOSXDbgMsg("Failed to construct CGImage."); } @@ -288,7 +321,7 @@ XCopyPlane( TkMacOSXDrawingContext dc; MacDrawable *srcDraw = (MacDrawable *) src; MacDrawable *dstDraw = (MacDrawable *) dst; - + CGRect bounds, srcRect, dstRect; display->request++; if (!width || !height) { /* TkMacOSXDbgMsg("Drawing of empty area requested"); */ @@ -308,7 +341,7 @@ XCopyPlane( TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; unsigned long imageBackground = gc->background; if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP){ - CGRect srcRect = CGRectMake(src_x, src_y, width, height); + srcRect = CGRectMake(src_x, src_y, width, height); CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(clipPtr->value.pixmap); CGImageRef submask = CGImageCreateWithImageInRect(img, srcRect); CGRect rect = CGRectMake(dest_x, dest_y, width, height); @@ -333,10 +366,11 @@ XCopyPlane( CGImageRelease(submask); CGImageRelease(subimage); } else { - TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, imageBackground, - CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height), - CGRectMake(src_x, src_y, width, height), - CGRectMake(dest_x, dest_y, width, height)); + bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height); + srcRect = CGRectMake(src_x, src_y, width, height); + dstRect = CGRectMake(dest_x, dest_y, width, height); + TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, + imageBackground, bounds, srcRect, dstRect); CGImageRelease(img); } } else { /* no image */ @@ -440,10 +474,8 @@ TkMacOSXGetNSImageWithTkImage( int height) { Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0); - MacDrawable *macDraw = (MacDrawable *) pixmap; NSImage *nsImage; - macDraw->flags |= TK_USE_XIMAGE_ALPHA; Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0); nsImage = CreateNSImageWithPixmap(pixmap, width, height); Tk_FreePixmap(display, pixmap); @@ -596,11 +628,13 @@ TkMacOSXDrawCGImage( } } dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff); - if (CGImageIsMask(image)) { - /*CGContextSaveGState(context);*/ if (macDraw->flags & TK_IS_BW_PIXMAP) { - /* Set fill color to black, background comes from the context, or is transparent. */ + + /* Set fill color to black; background comes from the context, + * or is transparent. + */ + if (imageBackground != TRANSPARENT_PIXEL << 24) { CGContextClearRect(context, dstBounds); } @@ -1448,7 +1482,7 @@ TkMacOSXSetUpGraphicsPort( *---------------------------------------------------------------------- */ -int +Bool TkMacOSXSetupDrawingContext( Drawable d, GC gc, @@ -1456,40 +1490,63 @@ TkMacOSXSetupDrawingContext( TkMacOSXDrawingContext *dcPtr) { MacDrawable *macDraw = ((MacDrawable*)d); - int dontDraw = 0, isWin = 0; + Bool canDraw = true; + NSWindow *win = NULL; TkMacOSXDrawingContext dc = {}; CGRect clipBounds; - dc.clipRgn = TkMacOSXGetClipRgn(d); - if (!dontDraw) { - ClipToGC(d, gc, &dc.clipRgn); - dontDraw = dc.clipRgn ? HIShapeIsEmpty(dc.clipRgn) : 0; + /* + * If the drawable is not a pixmap and it has an associated + * NSWindow then we know we are drawing to a window. + */ + + if (!(macDraw->flags & TK_IS_PIXMAP)) { + win = TkMacOSXDrawableWindow(d); } - if (dontDraw) { + + /* + * Check that we have a non-empty clipping region. + */ + + dc.clipRgn = TkMacOSXGetClipRgn(d); + ClipToGC(d, gc, &dc.clipRgn); + if (dc.clipRgn && HIShapeIsEmpty(dc.clipRgn)) { + canDraw = false; goto end; } - if (useCG) { - dc.context = TkMacOSXGetCGContextForDrawable(d); - } - if (!dc.context || !(macDraw->flags & TK_IS_PIXMAP)) { - isWin = (TkMacOSXDrawableWindow(d) != nil); - } + + /* + * If we already have a CGContext, use it. Otherwise, if we + * 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 (isWin) { + } else if (win) { NSView *view = TkMacOSXDrawableView(macDraw); if (view) { - if (view != [NSView focusView]) { - dc.focusLocked = [view lockFocusIfCanDraw]; - dontDraw = !dc.focusLocked; - } else { - dontDraw = ![view canDraw]; - } - if (dontDraw) { - goto end; - } + + /* + * We can only draw into the view when the current CGContext is + * valid and belongs to the view. Validity can only be guaranteed + * inside of a view's drawRect or setFrame methods. The isDrawing + * attribute tells us whether we are being called from one of those + * methods. + * + * If the CGContext is not valid, or belongs to a different View, + * 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; + goto end; + } dc.view = view; - dc.context = [[NSGraphicsContext currentContext] graphicsPort]; + dc.context = GET_CGCONTEXT; dc.portBounds = NSRectToCGRect([view bounds]); if (dc.clipRgn) { clipBounds = CGContextGetClipBoundingBox(dc.context); @@ -1502,14 +1559,17 @@ 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}; dc.portBounds.origin.x += macDraw->xOff; dc.portBounds.origin.y += macDraw->yOff; - if (!dc.focusLocked) { - CGContextSaveGState(dc.context); - } + CGContextSaveGState(dc.context); CGContextSetTextDrawingMode(dc.context, kCGTextFill); CGContextConcatCTM(dc.context, t); if (dc.clipRgn) { @@ -1544,7 +1604,7 @@ TkMacOSXSetupDrawingContext( double w = gc->line_width; TkMacOSXSetColorInContext(gc, gc->foreground, dc.context); - if (isWin) { + if (win) { CGContextSetPatternPhase(dc.context, CGSizeMake( dc.portBounds.size.width, dc.portBounds.size.height)); } @@ -1582,13 +1642,21 @@ TkMacOSXSetupDrawingContext( } } } + end: - if (dontDraw && dc.clipRgn) { +#ifdef TK_MAC_DEBUG_DRAWING + if (!canDraw && win != NULL) { + TkWindow *winPtr = TkMacOSXGetTkWindow(win); + if (winPtr) fprintf(stderr, "Cannot draw in %s - postponing.\n", + Tk_PathName(winPtr)); + } +#endif + if (!canDraw && dc.clipRgn) { CFRelease(dc.clipRgn); dc.clipRgn = NULL; } *dcPtr = dc; - return !dontDraw; + return canDraw; } /* @@ -1613,12 +1681,7 @@ TkMacOSXRestoreDrawingContext( { if (dcPtr->context) { CGContextSynchronize(dcPtr->context); - [[dcPtr->view window] setViewsNeedDisplay:YES]; - if (dcPtr->focusLocked) { - [dcPtr->view unlockFocus]; - } else { - CGContextRestoreGState(dcPtr->context); - } + CGContextRestoreGState(dcPtr->context); } if (dcPtr->clipRgn) { CFRelease(dcPtr->clipRgn); @@ -1657,17 +1720,13 @@ TkMacOSXGetClipRgn( #ifdef TK_MAC_DEBUG_DRAWING TkMacOSXDbgMsg("%s", macDraw->winPtr->pathName); NSView *view = TkMacOSXDrawableView(macDraw); - if ([view lockFocusIfCanDraw]) { - CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; - CGContextSaveGState(context); - CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0, - -1.0, 0.0, [view bounds].size.height)); - ChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context); - CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1); - CGContextEOFillPath(context); - CGContextRestoreGState(context); - [view unlockFocus]; - } + CGContextSaveGState(context); + CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0, + -1.0, 0.0, [view bounds].size.height)); + ChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context); + CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1); + CGContextEOFillPath(context); + CGContextRestoreGState(context); #endif /* TK_MAC_DEBUG_DRAWING */ } @@ -1727,13 +1786,11 @@ TkpClipDrawableToRect( int width, int height) { MacDrawable *macDraw = (MacDrawable *) d; - NSView *view = TkMacOSXDrawableView(macDraw); if (macDraw->drawRgn) { CFRelease(macDraw->drawRgn); macDraw->drawRgn = NULL; } - if (width >= 0 && height >= 0) { CGRect clipRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff, width, height); @@ -1749,17 +1806,6 @@ TkpClipDrawableToRect( } else { macDraw->drawRgn = drawRgn; } - if (view && view != [NSView focusView] && [view lockFocusIfCanDraw]) { - clipRect.origin.y = [view bounds].size.height - - (clipRect.origin.y + clipRect.size.height); - NSRectClip(NSRectFromCGRect(clipRect)); - macDraw->flags |= TK_FOCUSED_VIEW; - } - } else { - if (view && (macDraw->flags & TK_FOCUSED_VIEW)) { - [view unlockFocus]; - macDraw->flags &= ~TK_FOCUSED_VIEW; - } } } diff --git a/macosx/tkMacOSXEntry.c b/macosx/tkMacOSXEntry.c index ab236c6..4ab3111 100644 --- a/macosx/tkMacOSXEntry.c +++ b/macosx/tkMacOSXEntry.c @@ -123,8 +123,14 @@ TkpDrawEntryBorderAndFocus( if (isSpinbox) { int incDecWidth; - oldWidth = Tk_Width(tkwin); + /* + * Temporarily change the width of the widget so that the same code can + * be used for drawing the Entry portion of the Spinbox as is used to + * draw an ordinary Entry. The width must be restored before + * returning. + */ + oldWidth = Tk_Width(tkwin); ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH, &incDecWidth); Tk_Width(tkwin) -= incDecWidth + 1; @@ -149,6 +155,15 @@ TkpDrawEntryBorderAndFocus( bounds.size.width = Tk_Width(tkwin) - 2*MAC_OSX_FOCUS_WIDTH; bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH; if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) { + + /* + * No graphics context is available. If the widget is a Spinbox, we + * must restore its width before returning 0. (Ticket [273b6a4996].) + */ + + if (isSpinbox) { + Tk_Width(tkwin) = oldWidth; + } return 0; } ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c index 226f75c..d866b02 100644 --- a/macosx/tkMacOSXEvent.c +++ b/macosx/tkMacOSXEvent.c @@ -112,14 +112,23 @@ enum { * * TkMacOSXFlushWindows -- * - * This routine flushes all the visible windows of the application. It is - * called by XSync(). + * 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. * * Side effects: - * Flushes all visible Cocoa windows + * Calls the drawRect method of the contentView of each visible + * window. * *---------------------------------------------------------------------- */ @@ -129,9 +138,20 @@ TkMacOSXFlushWindows(void) { NSArray *macWindows = [NSApp orderedWindows]; - for (NSWindow *w in macWindows) { - if (TkMacOSXGetXWindow(w)) { - [w displayIfNeeded]; + if ([macWindows count] > 0) { + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){} + } + if ([NSApp isDrawing]) { + for (NSWindow *w in macWindows) { + if (TkMacOSXGetXWindow(w)) { + [w setViewsNeedDisplay:YES]; + } + } + } else { + for (NSWindow *w in macWindows) { + if (TkMacOSXGetXWindow(w)) { + [w display]; + } } } } diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index d92e6b4..353ad6b 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -14,19 +14,11 @@ #include "tkMacOSXPrivate.h" #include "tkMacOSXFont.h" +#include "tkMacOSXConstants.h" -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 #define defaultOrientation kCTFontDefaultOrientation #define verticalOrientation kCTFontVerticalOrientation -#else -#define defaultOrientation kCTFontOrientationDefault -#define verticalOrientation kCTFontOrientationVertical -#endif -#if MAC_OS_X_VERSION_MIN_REQUIRED < 101100 #define fixedPitch kCTFontUserFixedPitchFontType -#else -#define fixedPitch kCTFontUIFontUserFixedPitch -#endif /* #ifdef TK_MAC_DEBUG @@ -103,12 +95,6 @@ static void DrawCharsInContext(Display *display, Drawable drawable, GC gc, Tk_Font tkfont, const char *source, int numBytes, int rangeStart, int rangeLength, int x, int y, double angle); -@interface NSFont(TKFont) -- (NSFont *) bestMatchingFontForCharacters: (const UTF16Char *) characters - length: (NSUInteger) length attributes: (NSDictionary *) attributes - actualCoveredLength: (NSUInteger *) coveredLength; -@end - #pragma mark - #pragma mark Font Helpers: @@ -851,6 +837,10 @@ TkpMeasureCharsInContext( double maxWidth = maxLength + offset; NSCharacterSet *cs; + /* + * Get a line breakpoint in the source string. + */ + index = start; if (flags & TK_WHOLE_WORDS) { index = CTTypesetterSuggestLineBreak(typesetter, start, maxWidth); @@ -861,15 +851,43 @@ TkpMeasureCharsInContext( if (index <= start && !(flags & TK_WHOLE_WORDS)) { index = CTTypesetterSuggestClusterBreak(typesetter, start, maxWidth); } + + /* + * Trim right whitespace/lineending characters. + */ + cs = (index <= len && (flags & TK_WHOLE_WORDS)) ? whitespaceCharacterSet : lineendingCharacterSet; while (index > start && [cs characterIsMember:[string characterAtIndex:(index - 1)]]) { index--; } + + /* + * If there is no line breakpoint in the source string between + * its start and the index position that fits in maxWidth, then + * CTTypesetterSuggestLineBreak() returns that very last index. + * However if the TK_WHOLE_WORDS flag is set, we want to break + * at a word boundary. In this situation, unless TK_AT_LEAST_ONE + * is set, we must report that zero chars actually fit (in other + * words the smallest word of the source string is still larger + * than maxWidth). + */ + + if ((index >= start) && (index < len) && + (flags & TK_WHOLE_WORDS) && !(flags & TK_AT_LEAST_ONE) && + ![cs characterIsMember:[string characterAtIndex:index]]) { + index = start; + } + if (index <= start && (flags & TK_AT_LEAST_ONE)) { index = start + 1; } + + /* + * Now measure the string width in pixels. + */ + if (index > 0) { range.length = index; line = CTTypesetterCreateLine(typesetter, range); diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index 096faac..a5c870a 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -6,7 +6,7 @@ * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net> - * Copyright 2017 Marc Culler. + * Copyright 2017-2018 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -29,7 +29,8 @@ _XInitImageFuncPtrs( * * TkMacOSXCreateCGImageWithXImage -- * - * Create CGImage from XImage, copying the image data. + * Create CGImage from XImage, copying the image data. Called + * in Tk_PutImage and (currently) nowhere else. * * Results: * CGImage, release after use. @@ -46,8 +47,7 @@ static void ReleaseData(void *info, const void *data, size_t size) { CGImageRef TkMacOSXCreateCGImageWithXImage( - XImage *image, - int use_ximage_alpha) + XImage *image) { CGImageRef img = NULL; size_t bitsPerComponent, bitsPerPixel; @@ -88,21 +88,17 @@ TkMacOSXCreateCGImageWithXImage( bitsPerPixel, image->bytes_per_line, provider, decode, 0); } } else if (image->format == ZPixmap && image->bits_per_pixel == 32) { + /* * Color image */ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); - bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = (image->byte_order == MSBFirst ? - kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little); - if (use_ximage_alpha) { - bitmapInfo |= kCGImageAlphaPremultipliedFirst; - } else { - bitmapInfo |= kCGImageAlphaNoneSkipFirst; - } + kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big); + bitmapInfo |= kCGImageAlphaLast; data = memcpy(ckalloc(len), image->data + image->xoffset, len); if (data) { provider = CGDataProviderCreateWithData(data, data, len, releaseData); @@ -128,7 +124,12 @@ TkMacOSXCreateCGImageWithXImage( * * XGetImage -- * - * This function copies data from a pixmap or window into an XImage. + * This function copies data from a pixmap or window into an XImage. It + * is essentially never used. At one time it was called by + * pTkImgPhotoDisplay, but that is no longer the case. Currently it is + * called two places, one of which is requesting an XY image which we do + * not support. It probably does not work correctly -- see the comments + * for TkMacOSXBitmapRepFromDrawableRect. * * Results: * Returns a newly allocated XImage containing the data from the given @@ -165,7 +166,6 @@ XGetImage( unsigned int bytes_per_row, size, row, n, m; unsigned int scalefactor=1, scaled_height=height, scaled_width=width; NSWindow *win = TkMacOSXDrawableWindow(drawable); - MacDrawable *macDraw = ((MacDrawable*)drawable); static enum {unknown, no, yes} has_retina = unknown; if (win && has_retina == unknown) { @@ -178,9 +178,11 @@ XGetImage( } if (has_retina == yes) { + /* * We only allow scale factors 1 or 2, as Apple currently does. */ + #ifdef __clang__ scalefactor = [win backingScaleFactor] == 2.0 ? 2 : 1; #endif @@ -192,8 +194,9 @@ XGetImage( if (width == 0 || height == 0) { return NULL; } + bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable, - x, y, width, height); + x, y, width, height); if (!bitmap_rep) { TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep"); return NULL; @@ -206,39 +209,24 @@ XGetImage( (bitmap_fmt != 0 && bitmap_fmt != 1) || [bitmap_rep samplesPerPixel] != 4 || [bitmap_rep isPlanar] != 0 || - bytes_per_row != 4 * scaled_width || + bytes_per_row < 4 * scaled_width || size != bytes_per_row*scaled_height ) { TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format"); CFRelease(bitmap_rep); return NULL; } - - if (macDraw->flags & TK_USE_XIMAGE_ALPHA) { - /* - * When called by TkImgPhotoDisplay we are being asked to return a - * background image to be blended with the photoimage using its - * alpha channel, if it has one. Returning a black pixmap here - * makes TkImgPhotoDisplay create an XImage with a premultiplied - * alpha channel, as favored by Apple. When TkImgPhotoDisplay - * passes this XImage to TkPutImage, targeting a pixmap, it creates - * an image with correct transparency. This is used, for example, - * when creating an iconphoto or a menu image from a PNG - * photoimage. - */ - bzero(bitmap, size); - } else { - memcpy(bitmap, (char *)[bitmap_rep bitmapData], size); - } + memcpy(bitmap, (char *)[bitmap_rep bitmapData], size); CFRelease(bitmap_rep); /* * When Apple extracts a bitmap from an NSView, it may be in * either BGRA or ABGR format. For an XImage we need RGBA. */ + struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr; - for (row=0, n=0; row<scaled_height; row++, n+=bytes_per_row) { - for (m=n; m<n+bytes_per_row; m+=4) { + for (row = 0, n = 0; row < scaled_height; row++, n += bytes_per_row) { + for (m = n; m < n + 4*scaled_width; m += 4) { R = *(bitmap + m + pixel.r); G = *(bitmap + m + pixel.g); B = *(bitmap + m + pixel.b); @@ -514,8 +502,9 @@ XCreateImage( * * TkPutImage -- * - * Copies a subimage from an in-memory image to a rectangle of - * of the specified drawable. + * Copies a rectangular subimage of an XImage into a drawable. + * Currently this is only called by TkImgPhotoDisplay, using + * a Window as the drawable. * * Results: * None. @@ -542,23 +531,38 @@ TkPutImage( unsigned int height) /* distination and source. */ { TkMacOSXDrawingContext dc; - MacDrawable *macDraw = ((MacDrawable*)drawable); + MacDrawable *macDraw = (MacDrawable *) drawable; display->request++; if (!TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc)) { return BadDrawable; } if (dc.context) { - CGImageRef img = TkMacOSXCreateCGImageWithXImage(image, - macDraw->flags & TK_USE_XIMAGE_ALPHA); + CGRect bounds, srcRect, dstRect; + CGImageRef img = TkMacOSXCreateCGImageWithXImage(image); + + /* + * The CGContext for a pixmap is RGB only, with A = 0. + */ + + if (!(macDraw->flags & TK_IS_PIXMAP)) { + CGContextSetBlendMode(dc.context, kCGBlendModeSourceAtop); + } if (img) { - /* If the XImage has big pixels, rescale the source dimensions.*/ + + /* If the XImage has big pixels, the source is rescaled to reflect + * the actual pixel dimensions. This is not currently used, but + * could arise if the image were copied from a retina monitor and + * redrawn on an ordinary monitor. + */ + int pp = image->pixelpower; + bounds = CGRectMake(0, 0, image->width, image->height); + srcRect = CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp); + dstRect = CGRectMake(dest_x, dest_y, width, height); TkMacOSXDrawCGImage(drawable, gc, dc.context, - img, gc->foreground, gc->background, - CGRectMake(0, 0, image->width<<pp, image->height<<pp), - CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp), - CGRectMake(dest_x, dest_y, width, height)); + img, gc->foreground, gc->background, + bounds, srcRect, dstRect); CFRelease(img); } else { TkMacOSXDbgMsg("Invalid source drawable"); diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index e03b5aa..817b68b 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -16,7 +16,6 @@ #include "tkMacOSXPrivate.h" #include <sys/stat.h> -#include <sys/utsname.h> #include <dlfcn.h> #include <objc/objc-auto.h> @@ -29,25 +28,12 @@ static char tkLibPath[PATH_MAX + 1] = ""; static char scriptPath[PATH_MAX + 1] = ""; -long tkMacOSXMacOSXVersion = 0; - #pragma mark TKApplication(TKInit) -@interface TKApplication(TKKeyboard) -- (void) keyboardChanged: (NSNotification *) notification; -@end - -#define TKApplication_NSApplicationDelegate <NSApplicationDelegate> -@interface TKApplication(TKWindowEvent) TKApplication_NSApplicationDelegate -- (void) _setupWindowNotifications; -@end - -@interface TKApplication(TKMenus) -- (void) _setupMenus; -@end - @implementation TKApplication @synthesize poolLock = _poolLock; +@synthesize macMinorVersion = _macMinorVersion; +@synthesize isDrawing = _isDrawing; @end /* @@ -153,13 +139,34 @@ long tkMacOSXMacOSXVersion = 0; [NSApp setPoolLock:0]; /* + * Record the OS version we are running on. + */ + int minorVersion; +#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000 + Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion); +#else + NSOperatingSystemVersion systemVersion; + systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; + minorVersion = systemVersion.minorVersion; +#endif + [NSApp setMacMinorVersion: minorVersion]; + + /* + * We are not drawing right now. + */ + + [NSApp setIsDrawing:NO]; + + /* * Be our own delegate. */ + [self setDelegate:self]; /* * Make sure we are allowed to open windows. */ + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; /* @@ -255,7 +262,6 @@ TkpInit( */ if (!initialized) { - struct utsname name; struct stat st; initialized = 1; @@ -268,20 +274,6 @@ TkpInit( # error Mac OS X 10.6 required #endif - if (!uname(&name)) { - tkMacOSXMacOSXVersion = (strtod(name.release, NULL) + 96) * 10; - } - /*Check for new versioning scheme on Yosemite (10.10) and later.*/ - if (MAC_OS_X_VERSION_MIN_REQUIRED > 100000) { - tkMacOSXMacOSXVersion = MAC_OS_X_VERSION_MIN_REQUIRED/100; - } - if (tkMacOSXMacOSXVersion && MAC_OS_X_VERSION_MIN_REQUIRED < 100000 && - tkMacOSXMacOSXVersion/10 < MAC_OS_X_VERSION_MIN_REQUIRED/10) { - Tcl_Panic("Mac OS X 10.%d or later required !", - (MAC_OS_X_VERSION_MIN_REQUIRED/10)-100); - } - - #ifdef TK_FRAMEWORK /* * When Tk is in a framework, force tcl_findLibrary to look in the @@ -377,6 +369,14 @@ TkpInit( Tcl_CreateObjCommand(interp, "::tk::mac::iconBitmap", TkMacOSXIconBitmapObjCmd, NULL, NULL); + /* + * Workaround for 3efbe4a397; console not accepting keyboard input on 10.14 + * if displayed before main window. This places console in background and it + * accepts input after being raised. + */ + + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} + return TCL_OK; } diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index 52be0e1..d942286 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -83,11 +83,10 @@ typedef struct TkWindowPrivate MacDrawable; #define TK_CLIP_INVALID 0x02 #define TK_HOST_EXISTS 0x04 #define TK_DRAWN_UNDER_MENU 0x08 -#define TK_FOCUSED_VIEW 0x10 -#define TK_IS_PIXMAP 0x20 -#define TK_IS_BW_PIXMAP 0x40 -#define TK_DO_NOT_DRAW 0x80 -#define TK_USE_XIMAGE_ALPHA 0x100 +#define TK_IS_PIXMAP 0x10 +#define TK_IS_BW_PIXMAP 0x20 +#define TK_DO_NOT_DRAW 0x40 + /* * 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 @@ -199,6 +198,10 @@ MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x, MODULE_SCOPE void TkpRetainRegion(TkRegion r); 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 Bool TkTestAppIsDrawing(void); + /* * Include the stubbed internal platform-specific API. */ diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index ba885d1..31fffa1 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -68,15 +68,19 @@ unsigned short releaseCode; processingCompose = NO; } + w = [theEvent window]; + TkWindow *winPtr = TkMacOSXGetTkWindow(w); + Tk_Window tkwin = (Tk_Window) winPtr; + XEvent xEvent; + + if (!winPtr) { + return theEvent; + } + switch (type) { case NSKeyUp: - /*Fix for bug #1ba71a86bb: key release firing on key press.*/ - w = [theEvent window]; - XEvent xEvent; setupXEvent(&xEvent, w, 0); - TkWindow *winPtr = TkMacOSXGetTkWindow(w); - Tk_Window tkwin = (Tk_Window) winPtr; xEvent.xany.type = KeyRelease; xEvent.xkey.keycode = releaseCode; xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); @@ -88,10 +92,9 @@ unsigned short releaseCode; case NSFlagsChanged: modifiers = [theEvent modifierFlags]; keyCode = [theEvent keyCode]; - // w = [self windowWithWindowNumber:[theEvent windowNumber]]; - w = [theEvent window]; + #if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1 - NSLog(@"-[%@(%p) %s] r=%d mods=%u '%@' '%@' code=%u c=%d %@ %d", [self class], self, _cmd, repeat, modifiers, characters, charactersIgnoringModifiers, keyCode,([charactersIgnoringModifiers length] == 0) ? 0 : [charactersIgnoringModifiers characterAtIndex: 0], w, type); + TKLog(@"-[%@(%p) %s] r=%d mods=%u '%@' '%@' code=%u c=%d %@ %d", [self class], self, _cmd, repeat, modifiers, characters, charactersIgnoringModifiers, keyCode,([charactersIgnoringModifiers length] == 0) ? 0 : [charactersIgnoringModifiers characterAtIndex: 0], w, type); #endif break; @@ -246,7 +249,7 @@ unsigned short releaseCode; XEvent xEvent; if (NS_KEYLOG) - NSLog (@"insertText '%@'\tlen = %d", aString, len); + TKLog (@"insertText '%@'\tlen = %d", aString, len); processingCompose = NO; finishedCompose = YES; @@ -279,7 +282,7 @@ unsigned short releaseCode; NSString *str = [aString respondsToSelector: @selector (string)] ? [aString string] : aString; if (NS_KEYLOG) - NSLog (@"setMarkedText '%@' len =%lu range %lu from %lu", str, + TKLog (@"setMarkedText '%@' len =%lu range %lu from %lu", str, (unsigned long) [str length], (unsigned long) selRange.length, (unsigned long) selRange.location); @@ -306,7 +309,7 @@ unsigned short releaseCode; NSRange rng = privateWorkingText != nil ? NSMakeRange (0, [privateWorkingText length]) : NSMakeRange (NSNotFound, 0); if (NS_KEYLOG) - NSLog (@"markedRange request"); + TKLog (@"markedRange request"); return rng; } @@ -314,7 +317,7 @@ unsigned short releaseCode; - (void)unmarkText { if (NS_KEYLOG) - NSLog (@"unmark (accept) text"); + TKLog (@"unmark (accept) text"); [self deleteWorkingText]; processingCompose = NO; } @@ -330,7 +333,7 @@ unsigned short releaseCode; pt.y = caret_y; pt = [self convertPoint: pt toView: nil]; - pt = [[self window] convertPointToScreen: pt]; + pt = [[self window] tkConvertPointToScreen: pt]; pt.y -= caret_height; rect.origin = pt; @@ -349,7 +352,7 @@ unsigned short releaseCode; - (void)doCommandBySelector: (SEL)aSelector { if (NS_KEYLOG) - NSLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector)); + TKLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector)); processingCompose = NO; if (aSelector == @selector (deleteBackward:)) { @@ -379,7 +382,7 @@ unsigned short releaseCode; - (NSRange)selectedRange { if (NS_KEYLOG) - NSLog (@"selectedRange request"); + TKLog (@"selectedRange request"); return NSMakeRange (NSNotFound, 0); } @@ -387,7 +390,7 @@ unsigned short releaseCode; - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint { if (NS_KEYLOG) - NSLog (@"characterIndexForPoint request"); + TKLog (@"characterIndexForPoint request"); return 0; } @@ -397,7 +400,7 @@ unsigned short releaseCode; static NSAttributedString *str = nil; if (str == nil) str = [NSAttributedString new]; if (NS_KEYLOG) - NSLog (@"attributedSubstringFromRange request"); + TKLog (@"attributedSubstringFromRange request"); return str; } /* End <NSTextInput> impl. */ @@ -411,7 +414,7 @@ unsigned short releaseCode; if (privateWorkingText == nil) return; if (NS_KEYLOG) - NSLog(@"deleteWorkingText len = %lu\n", + TKLog(@"deleteWorkingText len = %lu\n", (unsigned long)[privateWorkingText length]); [privateWorkingText release]; privateWorkingText = nil; @@ -431,6 +434,9 @@ setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state) { TkWindow *winPtr = TkMacOSXGetTkWindow(w); Tk_Window tkwin = (Tk_Window) winPtr; + if (!winPtr) { + return; + } memset(xEvent, 0, sizeof(XEvent)); xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index 404f625..590402a 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -110,6 +110,11 @@ static int ModifierCharWidth(Tk_Font tkfont); #pragma mark TKMenu +/* + * This interface is not declared in tkMacOSXPrivate.h because it requires + * tkMenu.h. + */ + @interface TKMenu(TKMenuPrivate) - (id) initWithTkMenu: (TkMenu *) tkMenu; - (TkMenu *) tkMenu; @@ -117,10 +122,6 @@ static int ModifierCharWidth(Tk_Font tkfont); - (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index; @end -#define TKMenu_NSMenuDelegate <NSMenuDelegate> -@interface TKMenu(TKMenuDelegate) TKMenu_NSMenuDelegate -@end - @implementation TKMenu - (void) setSpecial: (NSUInteger) special { @@ -367,10 +368,6 @@ static int ModifierCharWidth(Tk_Font tkfont); #pragma mark TKApplication(TKMenu) -@interface NSApplication(TKMenu) -- (void) setAppleMenu: (NSMenu *) menu; -@end - @implementation TKApplication(TKMenu) - (void) menuBeginTracking: (NSNotification *) notification @@ -785,7 +782,7 @@ TkpPostMenu( NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1); frame.origin = [view convertPoint: - [win convertPointFromScreen:frame.origin] fromView:nil]; + [win tkConvertPointFromScreen:frame.origin] fromView:nil]; NSMenu *menu = (NSMenu *) menuPtr->platformData; NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc] @@ -1139,7 +1136,7 @@ TkpComputeStandardMenuGeometry( columnEntryPtr->x = x; columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN; } - x += maxIndicatorSpace + maxWidth + 2 * borderWidth; + x += maxIndicatorSpace + maxWidth + 2 * activeBorderWidth; maxWidth = maxIndicatorSpace = 0; lastColumnBreak = i; y = borderWidth; @@ -1625,8 +1622,7 @@ TkpDrawMenuEntry( int height, /* Height of the current rectangle */ int strictMotif, /* Boolean flag */ int drawArrow) /* Whether or not to draw the cascade arrow - * for cascade items. Only applies to - * Windows. */ + * for cascade items. */ { } diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c index a85e572..1acefe5 100644 --- a/macosx/tkMacOSXMenubutton.c +++ b/macosx/tkMacOSXMenubutton.c @@ -843,3 +843,11 @@ TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr) return 1; } +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ diff --git a/macosx/tkMacOSXMenus.c b/macosx/tkMacOSXMenus.c index f8f00a6..15dbad4 100644 --- a/macosx/tkMacOSXMenus.c +++ b/macosx/tkMacOSXMenus.c @@ -379,13 +379,13 @@ GenerateEditEvent( XVirtualEvent event; int x, y; TkWindow *winPtr = TkMacOSXGetTkWindow([NSApp keyWindow]); - Tk_Window tkwin = (Tk_Window) winPtr; + Tk_Window tkwin; - if (tkwin == NULL) { + if (!winPtr) { return; } tkwin = (Tk_Window) winPtr->dispPtr->focusPtr; - if (tkwin == NULL) { + if (!tkwin) { return; } bzero(&event, sizeof(XVirtualEvent)); diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 010023f..828d874 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -90,14 +90,14 @@ enum { /* Create an Xevent to add to the Tk queue. */ NSPoint global, local = [theEvent locationInWindow]; if (eventWindow) { /* local will be in window coordinates. */ - global = [eventWindow convertPointToScreen: local]; + global = [eventWindow tkConvertPointToScreen: local]; local.y = [eventWindow frame].size.height - local.y; global.y = tkMacOSXZeroScreenHeight - global.y; } else { /* local will be in screen coordinates. */ if (_windowWithMouse ) { eventWindow = _windowWithMouse; global = local; - local = [eventWindow convertPointFromScreen: local]; + local = [eventWindow tkConvertPointFromScreen: local]; local.y = [eventWindow frame].size.height - local.y; global.y = tkMacOSXZeroScreenHeight - global.y; } else { /* We have no window. Use the screen???*/ @@ -373,7 +373,7 @@ XQueryPointer( if (win) { NSPoint local; - local = [win convertPointFromScreen:global]; + local = [win tkConvertPointFromScreen:global]; local.y = [win frame].size.height - local.y; if (macWin->winPtr && macWin->winPtr->wmInfoPtr) { local.x -= macWin->winPtr->wmInfoPtr->xInParent; @@ -471,7 +471,7 @@ TkGenerateButtonEvent( if (win) { NSPoint local = NSMakePoint(x, tkMacOSXZeroScreenHeight - y); - local = [win convertPointFromScreen:local]; + local = [win tkConvertPointFromScreen:local]; local.y = [win frame].size.height - local.y; if (macWin->winPtr && macWin->winPtr->wmInfoPtr) { local.x -= macWin->winPtr->wmInfoPtr->xInParent; diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index fad61b4..8c01fe3 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -32,38 +32,107 @@ static void TkMacOSXNotifyExitHandler(ClientData clientData); static void TkMacOSXEventsSetupProc(ClientData clientData, int flags); static void TkMacOSXEventsCheckProc(ClientData clientData, int flags); -#pragma mark TKApplication(TKNotify) - -@interface NSApplication(TKNotify) -/* We need to declare this hidden method. */ -- (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event; -@end +#ifdef TK_MAC_DEBUG_EVENTS +static char* Tk_EventName[39] = { + "", + "", + "KeyPress", /*2*/ + "KeyRelease", /*3*/ + "ButtonPress", /*4*/ + "ButtonRelease", /*5*/ + "MotionNotify", /*6*/ + "EnterNotify", /*7*/ + "LeaveNotify", /*8*/ + "FocusIn", /*9*/ + "FocusOut", /*10*/ + "KeymapNotify", /*11*/ + "Expose", /*12*/ + "GraphicsExpose", /*13*/ + "NoExpose", /*14*/ + "VisibilityNotify", /*15*/ + "CreateNotify", /*16*/ + "DestroyNotify", /*17*/ + "UnmapNotify", /*18*/ + "MapNotify", /*19*/ + "MapRequest", /*20*/ + "ReparentNotify", /*21*/ + "ConfigureNotify", /*22*/ + "ConfigureRequest", /*23*/ + "GravityNotify", /*24*/ + "ResizeRequest", /*25*/ + "CirculateNotify", /*26*/ + "CirculateRequest", /*27*/ + "PropertyNotify", /*28*/ + "SelectionClear", /*29*/ + "SelectionRequest", /*30*/ + "SelectionNotify", /*31*/ + "ColormapNotify", /*32*/ + "ClientMessage", /*33*/ + "MappingNotify", /*34*/ + "VirtualEvent", /*35*/ + "ActivateNotify", /*36*/ + "DeactivateNotify", /*37*/ + "MouseWheelEvent" /*38*/ +}; -@implementation NSWindow(TKNotify) -- (id) tkDisplayIfNeeded +static Tk_RestrictAction +InspectQueueRestrictProc( + ClientData arg, + XEvent *eventPtr) { - if (![self isAutodisplay]) { - [self displayIfNeeded]; + XVirtualEvent* ve = (XVirtualEvent*) eventPtr; + const char *name; + long serial = ve->serial; + long time = eventPtr->xkey.time; + + if (eventPtr->type == VirtualEvent) { + name = ve->name; + } else { + name = Tk_EventName[eventPtr->type]; } - return nil; + fprintf(stderr, " > %s;serial = %lu; time=%lu)\n", + name, serial, time); + return TK_DEFER_EVENT; } -@end -@implementation TKApplication(TKNotify) -/* Display all windows each time an event is removed from the queue.*/ -- (NSEvent *) nextEventMatchingMask: (NSUInteger) mask - untilDate: (NSDate *) expiration inMode: (NSString *) mode - dequeue: (BOOL) deqFlag +/* + * Debugging tool which prints the current Tcl queue. + */ + +void DebugPrintQueue(void) { - NSEvent *event = [super nextEventMatchingMask:mask - untilDate:expiration - inMode:mode - dequeue:deqFlag]; - /* Retain this event for later use. Must be released.*/ - [event retain]; - [NSApp makeWindowsPerform:@selector(tkDisplayIfNeeded) inOrder:NO]; - return event; + ClientData oldArg; + Tk_RestrictProc *oldProc; + + oldProc = Tk_RestrictEvents(InspectQueueRestrictProc, NULL, &oldArg); + fprintf(stderr, "Current queue:\n"); + while (Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT)) {}; + Tk_RestrictEvents(oldProc, oldArg, &oldArg); } +# endif + +#pragma mark TKApplication(TKNotify) + +@implementation TKApplication(TKNotify) +/* + * Earlier versions of Tk would override nextEventMatchingMask here, adding a + * call to displayIfNeeded on all windows after calling super. This would cause + * windows to be redisplayed (if necessary) each time that an event was + * received. This was intended to replace Apple's default autoDisplay + * mechanism, which the earlier versions of Tk would disable. When autoDisplay + * is set to the default value of YES, the Apple event loop will call + * displayIfNeeded on all windows at the beginning of each iteration of their + * event loop. Since Tk does not call the Apple event loop, it was thought + * that the autoDisplay behavior needed to be replicated. + * + * However, as of OSX 10.14 (Mojave) the autoDisplay property became + * deprecated. Luckily it turns out that, even though we don't ever start the + * Apple event loop, the Apple window manager still calls displayIfNeeded on + * all windows on a regular basis, perhaps each time the queue is empty. So we + * no longer, and perhaps never did need to set autoDisplay to NO, nor call + * displayIfNeeded on our windows. We can just leave all of that to the window + * manager. + */ /* * Call super then check the pasteboard. @@ -72,6 +141,10 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags); { [super sendEvent:theEvent]; [NSApp tkCheckPasteboard]; +#ifdef TK_MAC_DEBUG_EVENTS + fprintf(stderr, "Sending event of type %d\n", (int)[theEvent type]); + DebugPrintQueue(); +#endif } @end @@ -91,7 +164,7 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags); *---------------------------------------------------------------------- */ -static NSString * +NSString * GetRunLoopMode(NSModalSession modalSession) { NSString *runLoopMode = nil; @@ -229,7 +302,6 @@ TkMacOSXEventsSetupProc( if (currentEvent.type > 0) { Tcl_SetMaxBlockTime(&zeroBlockTime); } - [currentEvent release]; } } } @@ -298,7 +370,6 @@ TkMacOSXEventsCheckProc( [NSApp sendEvent:currentEvent]; } } - [currentEvent release]; } else { break; } diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 730ccaa..a2a7a8f 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -131,7 +131,6 @@ typedef struct TkMacOSXDrawingContext { NSView *view; HIShapeRef clipRgn; CGRect portBounds; - int focusLocked; } TkMacOSXDrawingContext; /* @@ -190,8 +189,7 @@ MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window); MODULE_SCOPE EventModifiers TkMacOSXModifierState(void); MODULE_SCOPE NSBitmapImageRep* TkMacOSXBitmapRepFromDrawableRect(Drawable drawable, int x, int y, unsigned int width, unsigned int height); -MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image, - int use_ximage_alpha); +MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image); MODULE_SCOPE void TkMacOSXDrawCGImage(Drawable d, GC gc, CGContextRef context, CGImageRef image, unsigned long imageForeground, unsigned long imageBackground, CGRect imageBounds, @@ -252,6 +250,9 @@ VISIBILITY_HIDDEN - (BOOL)isSpecial:(NSUInteger)special; @end +@interface TKMenu(TKMenuDelegate) <NSMenuDelegate> +@end + VISIBILITY_HIDDEN @interface TKApplication : NSApplication { @private @@ -265,9 +266,13 @@ VISIBILITY_HIDDEN #ifdef __i386__ /* The Objective C runtime used on i386 requires this. */ int _poolLock; + int _macMinorVersion; + Bool _isDrawing; #endif } @property int poolLock; +@property int macMinorVersion; +@property Bool isDrawing; @end @interface TKApplication(TKInit) @@ -276,6 +281,22 @@ VISIBILITY_HIDDEN - (void)_lockAutoreleasePool; - (void)_unlockAutoreleasePool; @end +@interface TKApplication(TKKeyboard) +- (void) keyboardChanged: (NSNotification *) notification; +@end +@interface TKApplication(TKWindowEvent) <NSApplicationDelegate> +- (void) _setupWindowNotifications; +@end +@interface TKApplication(TKMenu) +- (void)tkSetMainMenu:(TKMenu *)menu; +@end +@interface TKApplication(TKMenus) +- (void) _setupMenus; +@end +@interface NSApplication(TKNotify) +/* We need to declare this hidden method. */ +- (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event; +@end @interface TKApplication(TKEvent) - (NSEvent *)tkProcessEvent:(NSEvent *)theEvent; @end @@ -285,9 +306,6 @@ VISIBILITY_HIDDEN @interface TKApplication(TKKeyEvent) - (NSEvent *)tkProcessKeyEvent:(NSEvent *)theEvent; @end -@interface TKApplication(TKMenu) -- (void)tkSetMainMenu:(TKMenu *)menu; -@end @interface TKApplication(TKClipboard) - (void)tkProvidePasteboard:(TkDisplay *)dispPtr; - (void)tkCheckPasteboard; @@ -312,13 +330,8 @@ VISIBILITY_HIDDEN @end VISIBILITY_HIDDEN -@interface TKContentView : NSView <NSTextInput> { -@private - /*Remove private API calls.*/ -#if 0 - id _savedSubviews; - BOOL _subviewsSetAside; -#endif +@interface TKContentView : NSView <NSTextInput> +{ NSString *privateWorkingText; } @end @@ -329,8 +342,7 @@ VISIBILITY_HIDDEN @interface TKContentView(TKWindowEvent) - (void) drawRect: (NSRect) rect; -- (void) generateExposeEvents: (HIShapeRef) shape; -- (void) viewDidEndLiveResize; +- (void) generateExposeEvents: (HIShapeRef) shape; - (void) tkToolbarButton: (id) sender; - (BOOL) isOpaque; - (BOOL) wantsDefaultClipping; @@ -343,8 +355,14 @@ VISIBILITY_HIDDEN @end @interface NSWindow(TKWm) -- (NSPoint) convertPointToScreen:(NSPoint)point; -- (NSPoint) convertPointFromScreen:(NSPoint)point; +- (NSPoint) tkConvertPointToScreen:(NSPoint)point; +- (NSPoint) tkConvertPointFromScreen:(NSPoint)point; +@end + +@interface NSDrawerWindow : NSWindow +{ + id _i1, _i2; +} @end #pragma mark NSMenu & NSMenuItem Utilities @@ -375,4 +393,32 @@ VISIBILITY_HIDDEN keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask; @end +@interface NSColorPanel(TKDialog) +- (void) _setUseModalAppearance: (BOOL) flag; +@end + +@interface NSFont(TKFont) +- (NSFont *) bestMatchingFontForCharacters: (const UTF16Char *) characters + length: (NSUInteger) length attributes: (NSDictionary *) attributes + actualCoveredLength: (NSUInteger *) coveredLength; +@end + +/* + * This method of NSApplication is not declared in NSApplication.h so we + * declare it here to be a method of the TKMenu category. + */ + +@interface NSApplication(TKMenu) +- (void) setAppleMenu: (NSMenu *) menu; +@end + #endif /* _TKMACPRIV */ + +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index a8018a5..d1287bb 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -8,6 +8,7 @@ * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net> * Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC. + * Copyright (c) 2018 Marc Culler * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -26,25 +27,40 @@ #define MIN_SLIDER_LENGTH 5 -/*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling of scrollbar values.*/ +/*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.*/ #ifdef __LP64__ #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) #else #define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum)) #endif /* __LP64__ */ -#define MOUNTAIN_LION_STYLE (NSAppKitVersionNumber < 1138) +/* + * Apple reversed the scroll direction with the release of OSX 10.7 Lion. + */ + +#define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138) /* - * Declaration of Mac specific scrollbar structure. + * Declaration of an extended scrollbar structure with Mac specific additions. */ typedef struct MacScrollbar { - TkScrollbar information; /* Generic scrollbar info. */ + TkScrollbar information; /* Generic scrollbar info. */ GC troughGC; /* For drawing trough. */ GC copyGC; /* Used for copying from pixmap onto screen. */ + Bool buttonDown; /* Is the mouse button down? */ + Bool mouseOver; /* Is the pointer over the scrollbar. */ + HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */ } MacScrollbar; +/* Used to initialize a MacScrollbar's info field. */ +HIThemeTrackDrawInfo defaultInfo = { + .version = 0, + .min = 0.0, + .max = 100.0, + .attributes = kThemeTrackShowThumb, +}; + /* * The class procedure table for the scrollbar widget. All fields except size * are left initialized to NULL, which should happen automatically since the @@ -59,7 +75,7 @@ const Tk_ClassProcs tkpScrollbarProcs = { }; -/*Information on scrollbar layout, metrics, and draw info.*/ +/* Information on scrollbar layout, metrics, and draw info.*/ typedef struct ScrollbarMetrics { SInt32 width, minThumbHeight; int minHeight, topArrowHeight, bottomArrowHeight; @@ -71,20 +87,13 @@ static ScrollbarMetrics metrics = { 15, 54, 26, 14, 14, kControlSizeNormal /* kThemeScrollBarMedium */ }; -HIThemeTrackDrawInfo info = { - .version = 0, - .min = 0.0, - .max = 100.0, - .attributes = kThemeTrackShowThumb, -}; - /* - * Forward declarations for procedures defined later in this file: + * Declarations of static functions defined later in this file: */ static void ScrollbarEventProc(ClientData clientData, XEvent *eventPtr); -static int ScrollbarPress(TkScrollbar *scrollPtr, XEvent *eventPtr); +static int ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr); static void UpdateControlValues(TkScrollbar *scrollPtr); /* @@ -112,8 +121,19 @@ TkpCreateScrollbar( scrollPtr->troughGC = None; scrollPtr->copyGC = None; - - Tk_CreateEventHandler(tkwin,ExposureMask|StructureNotifyMask|FocusChangeMask|ButtonPressMask|ButtonReleaseMask|EnterWindowMask|LeaveWindowMask|VisibilityChangeMask, ScrollbarEventProc, scrollPtr); + scrollPtr->info = defaultInfo; + scrollPtr->buttonDown = false; + + Tk_CreateEventHandler(tkwin, + ExposureMask | + StructureNotifyMask | + FocusChangeMask | + ButtonPressMask | + ButtonReleaseMask | + EnterWindowMask | + LeaveWindowMask | + VisibilityChangeMask, + ScrollbarEventProc, scrollPtr); return (TkScrollbar *) scrollPtr; } @@ -131,7 +151,7 @@ TkpCreateScrollbar( * None. * * Side effects: - * Information appears on the screen. + * Draws a scrollbar on the screen. * *-------------------------------------------------------------- */ @@ -141,6 +161,7 @@ TkpDisplayScrollbar( ClientData clientData) /* Information about window. */ { register TkScrollbar *scrollPtr = (TkScrollbar *) clientData; + MacScrollbar *msPtr = (MacScrollbar *) scrollPtr; register Tk_Window tkwin = scrollPtr->tkwin; TkWindow *winPtr = (TkWindow *) tkwin; TkMacOSXDrawingContext dc; @@ -164,7 +185,7 @@ TkpDisplayScrollbar( .ty = viewHeight}; CGContextConcatCTM(dc.context, t); - /*Draw Unix-style scroll trough to provide rect for native scrollbar.*/ + /*Draw a 3D rectangle to provide a base for the native scrollbar.*/ if (scrollPtr->highlightWidth != 0) { GC fgGC, bgGC; @@ -188,12 +209,13 @@ TkpDisplayScrollbar( Tk_Width(tkwin) - 2*scrollPtr->inset, Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT); - /*Update values and draw in native rect.*/ + /* Update values and then draw the native scrollbar over the rectangle.*/ UpdateControlValues(scrollPtr); - if (MOUNTAIN_LION_STYLE) { - HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationInverted); + + if (SNOW_LEOPARD_STYLE) { + HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationInverted); } else { - HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal); + HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationNormal); } TkMacOSXRestoreDrawingContext(&dc); @@ -228,20 +250,29 @@ TkpComputeScrollbarGeometry( { /* - * 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. + * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to + * account for some differences between macOS and X11. The Unix scrollbar + * has an arrow button on each end. On macOS 10.6 (Snow Leopard) the + * scrollbars by default have both arrow buttons at the bottom or right. + * (There is a preferences setting to use the Unix layout, but we are not + * supporting that!) On more recent versions of macOS there are no arrow + * buttons at all. The case of no arrow buttons can be handled as a special + * case of having both buttons at the end, but where scrollPtr->arrowLength + * happens to be zero. To adjust for having both arrows at the same end we + * shift the scrollbar up by the arrowLength. */ - int width, fieldLength; + int fieldLength; if (scrollPtr->highlightWidth < 0) { scrollPtr->highlightWidth = 0; } scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth; - width = (scrollPtr->vertical) ? Tk_Width(scrollPtr->tkwin) - : Tk_Height(scrollPtr->tkwin); - scrollPtr->arrowLength = width - 2*scrollPtr->inset + 1; + if ([NSApp macMinorVersion] == 6) { + scrollPtr->arrowLength = scrollPtr->width; + } else { + scrollPtr->arrowLength = 0; + } fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin) : Tk_Width(scrollPtr->tkwin)) - 2*(scrollPtr->arrowLength + scrollPtr->inset); @@ -269,24 +300,26 @@ TkpComputeScrollbarGeometry( if (scrollPtr->sliderLast > fieldLength) { scrollPtr->sliderLast = fieldLength; } - scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset; - scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset; + scrollPtr->sliderFirst += -scrollPtr->arrowLength + scrollPtr->inset; + scrollPtr->sliderLast += scrollPtr->inset; /* - * Register the desired geometry for the window (leave enough space for - * the two arrows plus a minimum-size slider, plus border around the whole - * window, if any). Then arrange for the window to be redisplayed. + * Register the desired geometry for the window. Leave enough space for the + * two arrows, if there are any arrows, plus a minimum-size slider, plus + * border around the whole window, if any. Then arrange for the window to + * be redisplayed. */ - if (scrollPtr->vertical) { + if (scrollPtr->vertical) { Tk_GeometryRequest(scrollPtr->tkwin, scrollPtr->width + 2*scrollPtr->inset, 2*(scrollPtr->arrowLength + scrollPtr->borderWidth - + scrollPtr->inset)); + + scrollPtr->inset) + metrics.minThumbHeight); } else { Tk_GeometryRequest(scrollPtr->tkwin, 2*(scrollPtr->arrowLength + scrollPtr->borderWidth - + scrollPtr->inset), scrollPtr->width + 2*scrollPtr->inset); + + scrollPtr->inset) + metrics.minThumbHeight, + scrollPtr->width + 2*scrollPtr->inset); } Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset); } @@ -319,8 +352,6 @@ TkpDestroyScrollbar( if (macScrollPtr->copyGC != None) { Tk_FreeGC(scrollPtr->display, macScrollPtr->copyGC); } - - macScrollPtr=NULL; } /* @@ -330,13 +361,13 @@ TkpDestroyScrollbar( * * This procedure is called after the generic code has finished * processing configuration options, in order to configure platform - * specific options. + * specific options. There are no such option on the Mac, however. * * Results: * None. * * Side effects: - * Configuration info may get changed. + * Currently, none. * *---------------------------------------------------------------------- */ @@ -344,8 +375,6 @@ TkpDestroyScrollbar( void TkpConfigureScrollbar( register TkScrollbar *scrollPtr) -/* Information about widget; may or may not - * already have values for some fields. */ { } @@ -375,54 +404,51 @@ 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. + /* + * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment + * since it does not involve the arrow buttons. */ - int length, fieldlength, width, tmp; + int length, 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) { + if (x < inset || x >= width - inset || + y < inset || y >= length - inset) { return OUTSIDE; } /* - * All of the calculations in this procedure mirror those in - * TkpDisplayScrollbar. Be sure to keep the two consistent. + * Here we assume that the scrollbar is layed out with both arrow buttons + * at the bottom (or right). Except on 10.6, however, the arrows do not + * actually exist, i.e. the arrowLength is 0. These are the same + * assumptions which are being made in TkpComputeScrollbarGeometry. */ - if (y < scrollPtr->sliderFirst) { + if (y < scrollPtr->sliderFirst + scrollPtr->arrowLength) { return TOP_GAP; - } - if (y < scrollPtr->sliderLast) { + } + if (y < scrollPtr->sliderLast) { return SLIDER; - } - if (y < fieldlength){ + } + if (y < length - (2*scrollPtr->arrowLength + inset)) { return BOTTOM_GAP; - } - if (y < fieldlength + arrowSize) { + } + /* On systems newer than 10.6 we have already returned. */ + if (y < length - (scrollPtr->arrowLength + inset)) { return TOP_ARROW; - } - return BOTTOM_ARROW; - + } + return BOTTOM_ARROW; } /* @@ -449,6 +475,7 @@ static void UpdateControlValues( TkScrollbar *scrollPtr) /* Scrollbar data struct. */ { + MacScrollbar *msPtr = (MacScrollbar *)scrollPtr; Tk_Window tkwin = scrollPtr->tkwin; MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin); double dViewSize; @@ -464,7 +491,7 @@ UpdateControlValues( frame.origin.y = viewHeight - (frame.origin.y + frame.size.height); contrlRect = NSRectToCGRect(frame); - info.bounds = contrlRect; + msPtr->info.bounds = contrlRect; width = contrlRect.size.width; height = contrlRect.size.height; @@ -474,11 +501,11 @@ UpdateControlValues( * have been computed. */ - info.bounds = contrlRect; + msPtr->info.bounds = contrlRect; if (scrollPtr->vertical) { - info.attributes &= ~kThemeTrackHorizontal; + msPtr->info.attributes &= ~kThemeTrackHorizontal; } else { - info.attributes |= kThemeTrackHorizontal; + msPtr->info.attributes |= kThemeTrackHorizontal; } /* @@ -495,25 +522,25 @@ UpdateControlValues( factor = RangeToFactor(maximum); dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) * factor; - info.max = MIN_SCROLLBAR_VALUE + + msPtr->info.max = MIN_SCROLLBAR_VALUE + factor - dViewSize; - info.trackInfo.scrollbar.viewsize = dViewSize; + msPtr->info.trackInfo.scrollbar.viewsize = dViewSize; if (scrollPtr->vertical) { - if (MOUNTAIN_LION_STYLE) { - info.value = factor * scrollPtr->firstFraction; + if (SNOW_LEOPARD_STYLE) { + msPtr->info.value = factor * scrollPtr->firstFraction; } else { - info.value = info.max - factor * scrollPtr->firstFraction; + msPtr->info.value = msPtr->info.max - factor * scrollPtr->firstFraction; } } else { - info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction; + msPtr->info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction; } if((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0) || height <= metrics.minHeight) { - info.enableState = kThemeTrackHideTrack; + msPtr->info.enableState = kThemeTrackHideTrack; } else { - info.enableState = kThemeTrackActive; - info.attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost; + msPtr->info.enableState = kThemeTrackActive; + msPtr->info.attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost; } } @@ -521,29 +548,79 @@ UpdateControlValues( /* *-------------------------------------------------------------- * - * ScrollbarPress -- + * ScrollbarEvent -- * * This procedure is invoked in response to <ButtonPress>, <ButtonRelease>, - * <EnterNotify>, and <LeaveNotify> events. Scrollbar appearance is modified. + * <EnterNotify>, and <LeaveNotify> events. The Scrollbar appearance is + * modified for each event. * *-------------------------------------------------------------- */ static int -ScrollbarPress(TkScrollbar *scrollPtr, XEvent *eventPtr) +ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr) { + MacScrollbar *msPtr = (MacScrollbar *)scrollPtr; + + /* The pressState does not indicate whether the moused button was + * pressed at some location in the Scrollbar. Rather, it indicates + * that the scrollbar should appear as if it were pressed in that + * location. The standard Mac behavior is that once the button is + * pressed inside the Scrollbar the appearance should not change until + * the button is released, even if the mouse moves outside of the + * scrollbar. However, if the mouse lies over the scrollbar but the + * button is not pressed then the appearance should be the same as if + * the button had been pressed on the slider, i.e. kThemeThumbPressed. + * See the file Appearance.r, or HIToolbox.bridgesupport on 10.14. + */ - if (eventPtr->type == ButtonPress) { - UpdateControlValues(scrollPtr); - info.trackInfo.scrollbar.pressState = 1; - } - if (eventPtr->type == EnterNotify) { - info.trackInfo.scrollbar.pressState = 1; - } - if (eventPtr->type == ButtonRelease || eventPtr->type == LeaveNotify) { - info.trackInfo.scrollbar.pressState = 0; - } - return TCL_OK; + if (eventPtr->type == ButtonPress) { + msPtr->buttonDown = true; + UpdateControlValues(scrollPtr); + int where = TkpScrollbarPosition(scrollPtr, + eventPtr->xbutton.x, + eventPtr->xbutton.y); + switch(where) { + case OUTSIDE: + msPtr->info.trackInfo.scrollbar.pressState = 0; + break; + case TOP_GAP: + msPtr->info.trackInfo.scrollbar.pressState = kThemeTopTrackPressed; + break; + case SLIDER: + msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed; + break; + case BOTTOM_GAP: + msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomTrackPressed; + break; + case TOP_ARROW: + /* This looks wrong and the docs say it is wrong but it works. */ + msPtr->info.trackInfo.scrollbar.pressState = kThemeTopInsideArrowPressed; + break; + case BOTTOM_ARROW: + msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomOutsideArrowPressed; + break; + } + } + if (eventPtr->type == ButtonRelease) { + msPtr->buttonDown = false; + if (!msPtr->mouseOver) { + msPtr->info.trackInfo.scrollbar.pressState = 0; + } + } + if (eventPtr->type == EnterNotify) { + msPtr->mouseOver = true; + if (!msPtr->buttonDown) { + msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed; + } + } + if (eventPtr->type == LeaveNotify) { + msPtr->mouseOver = false; + if (!msPtr->buttonDown) { + msPtr->info.trackInfo.scrollbar.pressState = 0; + } + } + return TCL_OK; } @@ -585,9 +662,18 @@ ScrollbarEventProc( case ButtonRelease: case EnterNotify: case LeaveNotify: - ScrollbarPress(clientData, eventPtr); + ScrollbarEvent(clientData, eventPtr); break; default: TkScrollbarEventProc(clientData, eventPtr); } } + +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 3d5e986..0f9214f 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -205,6 +205,13 @@ XMapWindow( event.xvisibility.type = VisibilityNotify; event.xvisibility.state = VisibilityUnobscured; NotifyVisibility(macWin->winPtr, &event); + + /* + * Make sure that subwindows get displayed. + */ + + GenerateConfigureNotify(macWin->winPtr, 1); + } /* @@ -295,10 +302,12 @@ XUnmapWindow( event.xunmap.from_configure = false; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); } else { + /* * Rebuild the visRgn clip region for the parent so it will be allowed * to draw in the space from which this subwindow was removed. */ + if (parentPtr && parentPtr->privatePtr->visRgn) { TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(parentPtr->privatePtr), parentPtr->privatePtr->visRgn); @@ -380,10 +389,12 @@ XMoveResizeWindow( if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { NSWindow *w = macWin->winPtr->wmInfoPtr->window; if (w) { + /* We explicitly convert everything to doubles so we don't get * surprised (again) by what happens when you do arithmetic with * unsigned ints. */ + CGFloat X = (CGFloat)x; CGFloat Y = (CGFloat)y; CGFloat Width = (CGFloat)width; @@ -470,6 +481,7 @@ MoveResizeWindow( if (contWinPtr) { macParent = contWinPtr->privatePtr; } else { + /* * Here we should handle out of process embedding. At this point, * we are assuming that the changes.x,y is not maintained, if you @@ -478,6 +490,7 @@ MoveResizeWindow( */ } } else { + /* * TODO: update all xOff & yOffs */ @@ -569,6 +582,7 @@ XRaiseWindow( if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { TkWmRestackToplevel(macWin->winPtr, Above, NULL); } else { + /* * TODO: this should generate damage */ @@ -603,7 +617,8 @@ XLowerWindow( if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { TkWmRestackToplevel(macWin->winPtr, Below, NULL); } else { - /* + + /* * TODO: this should generate damage */ } @@ -874,6 +889,7 @@ TkMacOSXUpdateClipRgn( } CFRelease(rgn); } else { + /* * An unmapped window has empty clip regions to prevent any * (erroneous) drawing into it or its children from becoming @@ -1134,6 +1150,7 @@ void * TkMacOSXGetRootControl( Drawable drawable) { + /* * will probably need to fix this up for embedding */ @@ -1314,6 +1331,7 @@ UpdateOffsets( TkWindow *childPtr; if (winPtr->privatePtr == NULL) { + /* * We haven't called Tk_MakeWindowExist for this window yet. The offset * information will be postponed and calulated at that time. (This will diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c index 1882ce6..b7923b0 100644 --- a/macosx/tkMacOSXTest.c +++ b/macosx/tkMacOSXTest.c @@ -80,6 +80,33 @@ DebuggerObjCmd( } /* + *---------------------------------------------------------------------- + * + * TkTestAppIsDrawing -- + * + * A test widget display procedure which records calls can use this to + * detect whether it is being called from within [NSView drawRect]. + * If so, it probably should not be recording the call since it was + * probably generated spontaneously by the window manager rather than + * by an explicit call to update. This is just a wrapper for the NSApp + * property. + * + * + * Results: + * Returns true if and only if called from within [NSView drawRect]. + * + * 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 bbfe5b7..ba2134d 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -68,11 +68,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification); #endif BOOL movedOnly = [[notification name] - isEqualToString:NSWindowDidMoveNotification]; - - if (movedOnly) { - /* constraining to screen after move not needed with AppKit */ - } + isEqualToString:NSWindowDidMoveNotification]; NSWindow *w = [notification object]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); @@ -96,6 +92,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; flags |= TK_SIZE_CHANGED; } if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) { + /* * Propagate geometry changes immediately. */ @@ -119,6 +116,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; TkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState; Tk_MapWindow((Tk_Window) winPtr); if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) { + /* * Process all Tk events generated by Tk_MapWindow(). */ @@ -138,6 +136,59 @@ extern NSString *NSWindowDidOrderOffScreenNotification; } } +- (NSSize)window:(NSWindow *)window + willUseFullScreenContentSize:(NSSize)proposedSize +{ + + /* + * We don't need to change the proposed size, but we do need to + * implement this method. Otherwise the full screen window will + * be sized to the screen's visibleFrame, leaving black bands at + * the top and bottom. + */ + + return proposedSize; +} + +- (void) windowEnteredFullScreen: (NSNotification *) notification +{ +#ifdef TK_MAC_DEBUG_NOTIFICATIONS + TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification); +#endif + NSWindow *w = [notification object]; + TkWindow *winPtr = TkMacOSXGetTkWindow(w); + MacDrawable *macWin = winPtr->privatePtr; + + /* + * We must apply the current window attributes when the window becomes a + * FullScreen or a split screen window. Otherwise the mouse cursor will be + * offset by the title bar height. The notification is sent in both cases. + */ + + if (winPtr) { + TkMacOSXApplyWindowAttributes(macWin->winPtr, w); + } +} + +- (void) windowExitedFullScreen: (NSNotification *) notification +{ +#ifdef TK_MAC_DEBUG_NOTIFICATIONS + TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification); +#endif + NSWindow *w = [notification object]; + TkWindow *winPtr = TkMacOSXGetTkWindow(w); + MacDrawable *macWin = winPtr->privatePtr; + + /* + * Also apply the current window attributes when the window returns to its + * normal size, for the same reason. + */ + + if (winPtr) { + TkMacOSXApplyWindowAttributes(macWin->winPtr, w); + } +} + - (void) windowCollapsed: (NSNotification *) notification { #ifdef TK_MAC_DEBUG_NOTIFICATIONS @@ -174,6 +225,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; return (winPtr ? NO : YES); } + #ifdef TK_MAC_DEBUG_NOTIFICATIONS - (void) windowDragStart: (NSNotification *) notification @@ -213,6 +265,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification; //Tk_UnmapWindow((Tk_Window) winPtr); } } + + #endif /* TK_MAC_DEBUG_NOTIFICATIONS */ - (void) _setupWindowNotifications @@ -221,12 +275,19 @@ extern NSString *NSWindowDidOrderOffScreenNotification; #define observe(n, s) \ [nc addObserver:self selector:@selector(s) name:(n) object:nil] + observe(NSWindowDidBecomeKeyNotification, windowActivation:); observe(NSWindowDidResignKeyNotification, windowActivation:); observe(NSWindowDidMoveNotification, windowBoundsChanged:); observe(NSWindowDidResizeNotification, windowBoundsChanged:); observe(NSWindowDidDeminiaturizeNotification, windowExpanded:); observe(NSWindowDidMiniaturizeNotification, windowCollapsed:); + +#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070) + observe(NSWindowDidEnterFullScreenNotification, windowEnteredFullScreen:); + observe(NSWindowDidExitFullScreenNotification, windowExitedFullScreen:); +#endif + #ifdef TK_MAC_DEBUG_NOTIFICATIONS observe(NSWindowWillMoveNotification, windowDragStart:); observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:); @@ -236,6 +297,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; observe(NSWindowDidOrderOffScreenNotification, windowUnmapped:); #endif #undef observe + } @end @@ -256,7 +318,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification; #ifdef TK_MAC_DEBUG_NOTIFICATIONS TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification); #endif - TkSuspendClipboard(); } - (void) applicationShowHide: (NSNotification *) notification @@ -296,10 +357,35 @@ extern NSString *NSWindowDidOrderOffScreenNotification; /* *---------------------------------------------------------------------- * + * TkpAppIsDrawing -- + * + * 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 +TkpAppIsDrawing(void) { + return [NSApp isDrawing]; +} + + +/* + *---------------------------------------------------------------------- + * * GenerateUpdates -- * * Given a Macintosh update region and a Tk window this function geneates - * a X Expose event for the window if it is within the update region. The + * an X Expose event for the window if it meets the update region. The * function will then recursivly have each damaged window generate Expose * events for its child windows. * @@ -360,7 +446,7 @@ GenerateUpdates( Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); #ifdef TK_MAC_DEBUG_DRAWING - NSLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x, + TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x, event.xexpose.y, event.xexpose.width, event.xexpose.height); #endif @@ -579,10 +665,12 @@ TkGenWMConfigureEvent( if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) && ((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) { if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) { + /* * Don't set external width, since the user didn't change it * from what the widgets asked for. */ + } else if (wmPtr->gridWin != NULL) { wmPtr->width = wmPtr->reqGridWidth + (width - winPtr->reqWidth)/wmPtr->widthInc; @@ -594,10 +682,12 @@ TkGenWMConfigureEvent( } if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) { + /* * Don't set external height, since the user didn't change it * from what the widgets asked for. */ + } else if (wmPtr->gridWin != NULL) { wmPtr->height = wmPtr->reqGridHeight + (height - winPtr->reqHeight)/wmPtr->heightInc; @@ -796,129 +886,208 @@ ConfigureRestrictProc( const NSRect *rectsBeingDrawn; NSInteger rectsBeingDrawnCount; - [self getRectsBeingDrawn:&rectsBeingDrawn count:&rectsBeingDrawnCount]; - #ifdef TK_MAC_DEBUG_DRAWING - TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd, NSStringFromRect(rect)); - [[NSColor colorWithDeviceRed:0.0 green:1.0 blue:0.0 alpha:.1] setFill]; - NSRectFillListUsingOperation(rectsBeingDrawn, rectsBeingDrawnCount, - NSCompositeSourceOver); + TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); + if (winPtr) fprintf(stderr, "drawRect: drawing %s\n", + Tk_PathName(winPtr)); #endif + /* + * We do not allow recursive calls to drawRect, but we only log + * them on OSX > 10.13, where they should never happen. + */ + + if ([NSApp isDrawing]) { + if ([NSApp macMinorVersion] > 13) { + TKLog(@"WARNING: a recursive call to drawRect was aborted."); + } + return; + } + + [NSApp setIsDrawing: YES]; + + [self getRectsBeingDrawn:&rectsBeingDrawn count:&rectsBeingDrawnCount]; CGFloat height = [self bounds].size.height; HIMutableShapeRef drawShape = HIShapeCreateMutable(); while (rectsBeingDrawnCount--) { CGRect r = NSRectToCGRect(*rectsBeingDrawn++); + +#ifdef TK_MAC_DEBUG_DRAWING + fprintf(stderr, "drawRect: %dx%d@(%d,%d)\n", (int)r.size.width, + (int)r.size.height, (int)r.origin.x, (int)r.origin.y); +#endif + r.origin.y = height - (r.origin.y + r.size.height); HIShapeUnionWithRect(drawShape, &r); } - if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) { - [self generateExposeEvents:(HIShapeRef)drawShape]; - } else { - [self performSelectorOnMainThread:@selector(generateExposeEvents:) - withObject:(id)drawShape waitUntilDone:NO - modes:[NSArray arrayWithObjects:NSRunLoopCommonModes, - - NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode, - nil]]; - } - + [self generateExposeEvents:(HIShapeRef)drawShape]; CFRelease(drawShape); + [NSApp setIsDrawing: NO]; + +#ifdef TK_MAC_DEBUG_DRAWING + fprintf(stderr, "drawRect: done.\n"); +#endif } -(void) setFrameSize: (NSSize)newsize { [super setFrameSize: newsize]; - if ([self inLiveResize]) { - NSWindow *w = [self window]; - TkWindow *winPtr = TkMacOSXGetTkWindow(w); - Tk_Window tkwin = (Tk_Window) winPtr; + NSWindow *w = [self window]; + TkWindow *winPtr = TkMacOSXGetTkWindow(w); + Tk_Window tkwin = (Tk_Window) winPtr; + if (winPtr) { unsigned int width = (unsigned int)newsize.width; unsigned int height=(unsigned int)newsize.height; ClientData oldArg; Tk_RestrictProc *oldProc; - /* This can be called from outside the Tk event loop. + /* + * This can be called from outside the Tk event loop. * Since it calls Tcl_DoOneEvent, we need to make sure we * don't clobber the AutoreleasePool set up by the caller. */ + [NSApp _lockAutoreleasePool]; /* - * Try to prevent flickers and flashes. + * Disable Tk drawing until the window has been completely configured. */ - NSDisableScreenUpdates(); - /* Disable Tk drawing until the window has been completely configured.*/ TkMacOSXSetDrawingEnabled(winPtr, 0); - /* Generate and handle a ConfigureNotify event for the new size.*/ + /* + * 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); - /* Now that Tk has configured all subwindows we can create the clip regions. */ + /* + * Now that Tk has configured all subwindows, create the clip regions. + */ + TkMacOSXSetDrawingEnabled(winPtr, 1); TkMacOSXInvalClipRgns(tkwin); TkMacOSXUpdateClipRgn(winPtr); - /* Finally, generate and process expose events to redraw the window. */ + /* + * 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)) {} [w displayIfNeeded]; - NSEnableScreenUpdates(); + + /* + * Finally, unlock the main autoreleasePool. + */ + [NSApp _unlockAutoreleasePool]; } } /* - * As insurance against bugs that might cause layout glitches during a live - * resize, we redraw the window one more time at the end of the resize - * operation. + * Core method of this class: generates expose events for redrawing. The + * expose events are immediately removed from the Tcl event loop and processed. + * This causes drawing procedures to be scheduled as idle events. Then all + * pending idle events are processed so the drawing will actually take place. */ -- (void)viewDidEndLiveResize -{ - HIRect bounds = NSRectToCGRect([self bounds]); - HIShapeRef shape = HIShapeCreateWithRect(&bounds); - [super viewDidEndLiveResize]; - [self generateExposeEvents: shape]; -} - -/* Core method of this class: generates expose events for redrawing. 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 { unsigned long serial; CGRect updateBounds; int updatesNeeded; TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); - + ClientData oldArg; + Tk_RestrictProc *oldProc; if (!winPtr) { - return; + return; } - /* Generate Tk Expose events. */ + /* + * Generate Tk Expose events. + */ + HIShapeGetBounds(shape, &updateBounds); - /* All of these events will share the same serial number. */ + + /* + * All of these events will share the same serial number. + */ + serial = LastKnownRequestProcessed(Tk_Display(winPtr)); 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)) {} + if (updatesNeeded) { + + /* + * First process all of the Expose events. + */ + + oldProc = Tk_RestrictEvents(ExposeRestrictProc, UINT2PTR(serial), &oldArg); + while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}; Tk_RestrictEvents(oldProc, oldArg, &oldArg); + + /* + * Starting with OSX 10.14, which uses Core Animation to draw windows, + * all drawing must be done within the drawRect method. (The CGContext + * which draws to the backing CALayer is created by the NSView before + * calling drawRect, and destroyed when drawRect returns. Drawing done + * with the current CGContext outside of the drawRect method has no + * effect.) + * + * 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. + */ + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} + } +} + +/* + * This method is called when a user changes between light and dark mode. + * The implementation here generates a Tk virtual event which can be bound + * to a function that redraws the window in an appropriate style. + */ + +- (void) viewDidChangeEffectiveAppearance +{ + XVirtualEvent event; + int x, y; + NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"]; + NSWindow *w = [self window]; + TkWindow *winPtr = TkMacOSXGetTkWindow(w); + Tk_Window tkwin = (Tk_Window) winPtr; + + if (!winPtr) { + return; + } + bzero(&event, sizeof(XVirtualEvent)); + event.type = VirtualEvent; + event.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); + event.send_event = false; + event.display = Tk_Display(tkwin); + event.event = Tk_WindowId(tkwin); + event.root = XRootWindow(Tk_Display(tkwin), 0); + event.subwindow = None; + event.time = TkpGetMS(); + XQueryPointer(NULL, winPtr->window, NULL, NULL, + &event.x_root, &event.y_root, &x, &y, &event.state); + Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y); + event.same_screen = true; + if (osxMode == nil) { + event.name = Tk_GetUid("LightAqua"); + Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); + return; + } + if ([osxMode isEqual:@"Dark"]) { + event.name = Tk_GetUid("DarkAqua"); + Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); + return; } } @@ -926,6 +1095,7 @@ ConfigureRestrictProc( * This is no-op on 10.7 and up because Apple has removed this widget, * but we are leaving it here for backwards compatibility. */ + - (void) tkToolbarButton: (id) sender { #ifdef TK_MAC_DEBUG_EVENTS @@ -935,6 +1105,9 @@ ConfigureRestrictProc( int x, y; TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); Tk_Window tkwin = (Tk_Window) winPtr; + if (!winPtr){ + return; + } bzero(&event, sizeof(XVirtualEvent)); event.type = VirtualEvent; event.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); @@ -955,7 +1128,6 @@ ConfigureRestrictProc( - (BOOL) isOpaque { NSWindow *w = [self window]; - return (w && (([w styleMask] & NSTexturedBackgroundWindowMask) || ![w isOpaque]) ? NO : YES); } diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index a0fda96..7e63857 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -204,16 +204,16 @@ static int windowHashInit = false; @implementation NSWindow(TKWm) #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 -- (NSPoint) convertPointToScreen: (NSPoint) point +- (NSPoint) tkConvertPointToScreen: (NSPoint) point { return [self convertBaseToScreen:point]; } -- (NSPoint) convertPointFromScreen: (NSPoint)point +- (NSPoint) tkConvertPointFromScreen: (NSPoint)point { return [self convertScreenToBase:point]; } #else -- (NSPoint) convertPointToScreen: (NSPoint) point +- (NSPoint) tkConvertPointToScreen: (NSPoint) point { NSRect pointrect; pointrect.origin = point; @@ -221,7 +221,7 @@ static int windowHashInit = false; pointrect.size.height = 0; return [self convertRectToScreen:pointrect].origin; } -- (NSPoint) convertPointFromScreen: (NSPoint)point +- (NSPoint) tkConvertPointFromScreen: (NSPoint)point { NSRect pointrect; pointrect.origin = point; @@ -379,47 +379,23 @@ static void RemapWindows(TkWindow *winPtr, #pragma mark TKWindow(TKWm) -@interface NSDrawerWindow : NSWindow -{ - id _i1, _i2; -} -@end - - @implementation TKWindow: NSWindow -#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_12 -/* - * Override automatic fullscreen button on >10.12 because system fullscreen API - * confuses Tk window geometry. Custom implementation setting fullscreen status using - * Tk API and NSStatusItem in menubar to exit fullscreen status. - */ -NSStatusItem *exitFullScreen; - -- (void)toggleFullScreen:(id)sender +#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101200) +- (void)toggleTabBar:(id)sender { TkWindow *winPtr = TkMacOSXGetTkWindow(self); - Tk_Window tkwin = (TkWindow*)winPtr; - Tcl_Interp *interp = Tk_Interp(tkwin); - - if (([self styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask) { - TkMacOSXMakeFullscreen(winPtr, self, 0, interp); - } else { - TkMacOSXMakeFullscreen(winPtr, self, 1, interp); + MacDrawable *macWin = winPtr->privatePtr; + if (!winPtr) { + return; + } + [super toggleTabBar:sender]; + if (([self styleMask] & NSFullScreenWindowMask) == 0) { + TkMacOSXApplyWindowAttributes(macWin->winPtr, self); } } - --(void)restoreOldScreen:(id)sender { - - TkWindow *winPtr = TkMacOSXGetTkWindow(self); - Tk_Window tkwin = (TkWindow*)winPtr; - Tcl_Interp *interp = Tk_Interp(tkwin); - - TkMacOSXMakeFullscreen(winPtr, self, 0, interp); - [[NSStatusBar systemStatusBar] removeStatusItem: exitFullScreen]; -} - #endif + @end @implementation TKWindow(TKWm) @@ -427,14 +403,15 @@ NSStatusItem *exitFullScreen; - (BOOL) canBecomeKeyWindow { TkWindow *winPtr = TkMacOSXGetTkWindow(self); - - return (winPtr && winPtr->wmInfoPtr && (winPtr->wmInfoPtr->macClass == - kHelpWindowClass || winPtr->wmInfoPtr->attributes & - kWindowNoActivatesAttribute)) ? NO : YES; + if (!winPtr) { + return NO; + } + return (winPtr->wmInfoPtr && + (winPtr->wmInfoPtr->macClass == kHelpWindowClass || + winPtr->wmInfoPtr->attributes & kWindowNoActivatesAttribute) + ) ? NO : YES; } - - #if DEBUG_ZOMBIES - (id) retain { @@ -444,7 +421,8 @@ NSStatusItem *exitFullScreen; title = "unnamed window"; } if (DEBUG_ZOMBIES > 1){ - printf("Retained <%s>. Count is: %lu\n", title, [self retainCount]); + fprintf(stderr, "Retained <%s>. Count is: %lu\n", + title, [self retainCount]); } return result; } @@ -457,7 +435,8 @@ NSStatusItem *exitFullScreen; title = "unnamed window"; } if (DEBUG_ZOMBIES > 1){ - printf("Autoreleased <%s>. Count is %lu\n", title, [self retainCount]); + fprintf(stderr, "Autoreleased <%s>. Count is %lu\n", + title, [self retainCount]); } return result; } @@ -468,7 +447,8 @@ NSStatusItem *exitFullScreen; title = "unnamed window"; } if (DEBUG_ZOMBIES > 1){ - printf("Releasing <%s>. Count is %lu\n", title, [self retainCount]); + fprintf(stderr, "Releasing <%s>. Count is %lu\n", + title, [self retainCount]); } [super release]; } @@ -479,7 +459,8 @@ NSStatusItem *exitFullScreen; title = "unnamed window"; } if (DEBUG_ZOMBIES > 0){ - printf(">>>> Freeing <%s>. Count is %lu\n", title, [self retainCount]); + fprintf(stderr, ">>>> Freeing <%s>. Count is %lu\n", + title, [self retainCount]); } [super dealloc]; } @@ -600,15 +581,15 @@ FrontWindowAtPoint( { NSPoint p = NSMakePoint(x, tkMacOSXZeroScreenHeight - y); NSArray *windows = [NSApp orderedWindows]; - TkWindow *front = NULL; + TkWindow *winPtr = NULL; for (NSWindow *w in windows) { - if (w && NSMouseInRect(p, [w frame], NO)) { - front = TkMacOSXGetTkWindow(w); - break; - } + winPtr = TkMacOSXGetTkWindow(w); + if (winPtr && NSMouseInRect(p, [w frame], NO)) { + break; } - return front; + } + return winPtr; } /* @@ -736,7 +717,6 @@ TkWmMapWindow( * mapped. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; - if (wmPtr->flags & WM_NEVER_MAPPED) { /* * Create the underlying Mac window for this Tk window. @@ -808,7 +788,6 @@ TkWmMapWindow( /*Add window to Window menu.*/ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); [win setExcludedFromWindowsMenu:NO]; - } /* @@ -1288,10 +1267,11 @@ WmSetAttribute( return TCL_ERROR; } if (boolean != ((wmPtr->flags & WM_FULLSCREEN) != 0)) { - if (TkMacOSXMakeFullscreen(winPtr, macWindow, boolean, interp) - != TCL_OK) { - return TCL_ERROR; - } +#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070) + [macWindow toggleFullScreen:macWindow]; +#else + TKLog(@"The fullscreen attribute is ignored on this system.."); +#endif } break; case WMATT_MODIFIED: @@ -5646,20 +5626,18 @@ TkMacOSXMakeRealWindowExist( } TKContentView *contentView = [[TKContentView alloc] initWithFrame:NSZeroRect]; - [window setColorSpace:[NSColorSpace deviceRGBColorSpace]]; [window setContentView:contentView]; [contentView release]; [window setDelegate:NSApp]; [window setAcceptsMouseMovedEvents:YES]; [window setReleasedWhenClosed:NO]; - [window setAutodisplay:NO]; if (styleMask & NSUtilityWindowMask) { [(NSPanel*)window setFloatingPanel:YES]; } if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) && !(styleMask & NSDocModalWindowMask)) { /* - * Workaround for [Bug 2824538]: Texured windows are draggable + * Workaround for [Bug 2824538]: Textured windows are draggable * from opaque content. */ [window setMovableByWindowBackground:NO]; @@ -5675,7 +5653,7 @@ TkMacOSXMakeRealWindowExist( geometry.size.height += structureRect.size.height; geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y + geometry.size.height); - [window setFrame:geometry display:NO]; + [window setFrame:geometry display:YES]; TkMacOSXRegisterOffScreenWindow((Window) macWin, window); macWin->flags |= TK_HOST_EXISTS; } @@ -5683,6 +5661,33 @@ TkMacOSXMakeRealWindowExist( /* *---------------------------------------------------------------------- * + * TkpDisplayWindow -- + * + * Mark the contentView of this window as needing display so the + * window will be drawn by the window manager. If this is called + * within the drawRect method, do nothing. + * + * Results: + * None. + * + * Side effects: + * The window's contentView is marked as needing display. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE void +TkpDisplayWindow(Tk_Window tkwin) { + if (![NSApp isDrawing]) { + TkWindow *winPtr = (TkWindow*)tkwin; + NSWindow *w = TkMacOSXDrawableWindow(winPtr->window); + [[w contentView] setNeedsDisplay: YES]; + } +} + +/* + *---------------------------------------------------------------------- + * * TkMacOSXRegisterOffScreenWindow -- * * This function adds the passed in Off Screen Port to the hash table @@ -6353,6 +6358,20 @@ ApplyWindowAttributeFlagChanges( tkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute)) || initial) { NSWindowCollectionBehavior b = NSWindowCollectionBehaviorDefault; + + /* + * This behavior, which makes the green button expand a window to + * full screen, was included in the default as of OSX 10.13. For + * uniformity we use the new default in all versions of the OS + * where the behavior exists. + */ + +#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070) + if (!(macWindow.styleMask & NSWindowStyleMaskUtilityWindow)) { + b |= NSWindowCollectionBehaviorFullScreenPrimary; + } +#endif + if (newAttributes & tkCanJoinAllSpacesAttribute) { b |= NSWindowCollectionBehaviorCanJoinAllSpaces; } else if (newAttributes & tkMoveToActiveSpaceAttribute) { @@ -6473,117 +6492,6 @@ ApplyMasterOverrideChanges( /* *---------------------------------------------------------------------- * - * TkMacOSXMakeFullscreen -- - * - * This procedure sets a fullscreen window to the size of the screen. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -TkMacOSXMakeFullscreen( - TkWindow *winPtr, - NSWindow *window, - int fullscreen, - Tcl_Interp *interp) -{ - WmInfo *wmPtr = winPtr->wmInfoPtr; - int result = TCL_OK, wasFullscreen = (wmPtr->flags & WM_FULLSCREEN); - static unsigned long prevMask = 0, prevPres = 0; - - - if (fullscreen) { - int screenWidth = WidthOfScreen(Tk_Screen(winPtr)); - int screenHeight = HeightOfScreen(Tk_Screen(winPtr)); - - /* - * Check max width and height if set by the user. - */ - - if ((wmPtr->maxWidth > 0 && wmPtr->maxWidth < screenWidth) - || (wmPtr->maxHeight > 0 && wmPtr->maxHeight < screenHeight)) { - if (interp) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't set fullscreen attribute for \"%s\": max" - " width/height is too small", winPtr->pathName)); - Tcl_SetErrorCode(interp, "TK", "FULLSCREEN", - "CONSTRAINT_FAILURE", NULL); - } - result = TCL_ERROR; - wmPtr->flags &= ~WM_FULLSCREEN; - } else { - Tk_UnmapWindow((Tk_Window) winPtr); - NSRect bounds = [window contentRectForFrameRect:[window frame]]; - NSRect screenBounds = NSMakeRect(0, 0, screenWidth, screenHeight); - - if (!NSEqualRects(bounds, screenBounds) && !wasFullscreen) { - wmPtr->configX = wmPtr->x; - wmPtr->configY = wmPtr->y; - wmPtr->configAttributes = wmPtr->attributes; - wmPtr->attributes &= ~kWindowResizableAttribute; - ApplyWindowAttributeFlagChanges(winPtr, window, - wmPtr->configAttributes, wmPtr->flags, 1, 0); - wmPtr->flags |= WM_SYNC_PENDING; - [window setFrame:[window frameRectForContentRect: - screenBounds] display:YES]; - wmPtr->flags &= ~WM_SYNC_PENDING; - } - wmPtr->flags |= WM_FULLSCREEN; - } - - prevMask = [window styleMask]; - prevPres = [NSApp presentationOptions]; - [window setStyleMask: NSFullScreenWindowMask]; - [NSApp setPresentationOptions: NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar]; - - /*Fullscreen implementation for 10.13 and later.*/ - #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_12 - exitFullScreen = [[[NSStatusBar systemStatusBar] - statusItemWithLength:NSVariableStatusItemLength] retain]; - NSImage *exitIcon = [NSImage imageNamed:@"NSExitFullScreenTemplate"]; - [exitFullScreen setImage:exitIcon]; - [exitFullScreen setHighlightMode:YES]; - [exitFullScreen setToolTip:@"Exit Full Screen"]; - [exitFullScreen setTarget:window]; - [exitFullScreen setAction:@selector(restoreOldScreen:)]; - #endif - - Tk_MapWindow((Tk_Window) winPtr); - } else { - wmPtr->flags &= ~WM_FULLSCREEN; - [NSApp setPresentationOptions: prevPres]; - [window setStyleMask: prevMask]; - } - - if (wasFullscreen && !(wmPtr->flags & WM_FULLSCREEN)) { - Tk_UnmapWindow((Tk_Window) winPtr); - UInt64 oldAttributes = wmPtr->attributes; - NSRect bounds = NSMakeRect(wmPtr->configX, tkMacOSXZeroScreenHeight - - (wmPtr->configY + wmPtr->yInParent + wmPtr->configHeight), - wmPtr->xInParent + wmPtr->configWidth, - wmPtr->yInParent + wmPtr->configHeight); - - wmPtr->attributes |= wmPtr->configAttributes & - kWindowResizableAttribute; - ApplyWindowAttributeFlagChanges(winPtr, window, oldAttributes, - wmPtr->flags, 1, 0); - wmPtr->flags |= WM_SYNC_PENDING; - [window setFrame:[window frameRectForContentRect:bounds] display:YES]; - wmPtr->flags &= ~WM_SYNC_PENDING; - Tk_MapWindow((Tk_Window) winPtr); - } - return result; -} - -/* - *---------------------------------------------------------------------- - * * GetMinSize -- * * This function computes the current minWidth and minHeight values for a diff --git a/macosx/tkMacOSXWm.h b/macosx/tkMacOSXWm.h index e904f50..43f1a7a 100644 --- a/macosx/tkMacOSXWm.h +++ b/macosx/tkMacOSXWm.h @@ -185,6 +185,15 @@ typedef struct TkWmInfo { TkWindow *scrollWinPtr; /* Ptr to scrollbar handling grow widget. */ TkMenu *menuPtr; NSWindow *window; + + /* + * Space to cache current window state when window becomes Fullscreen. + */ + + unsigned long cachedStyle; + unsigned long cachedPresentation; + NSRect cachedBounds; + } WmInfo; /* diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 66f519f..cc98e84 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -3,7 +3,7 @@ * * This file contains most of the X calls called by Tk. Many of these * calls are just stubs and either don't make sense on the Macintosh or - * their implamentation just doesn't do anything. Other calls will + * their implementation just doesn't do anything. Other calls will * eventually be moved into other files. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. @@ -178,7 +178,7 @@ TkpOpenDisplay( { int major, minor, patch; -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000 Gestalt(gestaltSystemVersionMajor, (SInt32*)&major); Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor); Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch); @@ -203,7 +203,6 @@ TkpOpenDisplay( screen->root_visual = ckalloc(sizeof(Visual)); screen->root_visual->visualid = 0; screen->root_visual->class = TrueColor; - screen->root_visual->alpha_mask = 0xFF000000; screen->root_visual->red_mask = 0x00FF0000; screen->root_visual->green_mask = 0x0000FF00; screen->root_visual->blue_mask = 0x000000FF; diff --git a/tests/bitmap.test b/tests/bitmap.test index 6e2573f..fea675d 100644 --- a/tests/bitmap.test +++ b/tests/bitmap.test @@ -84,12 +84,14 @@ test bitmap-3.1 {Tk_FreeBitmapFromObj - reference counts} -constraints { test bitmap-4.1 {FreeBitmapObjProc} -constraints { testbitmap +} -setup { + proc copy {s} {return [string index $s 0][string range $s 1 end]} } -body { - set x [join questhead] + set x [copy questhead] button .b -bitmap $x - set y [join questhead] + set y [copy questhead] .b configure -bitmap $y - set z [join questhead] + set z [copy questhead] .b configure -bitmap $z set result {} lappend result [testbitmap questhead] @@ -102,6 +104,7 @@ test bitmap-4.1 {FreeBitmapObjProc} -constraints { set y bogus return $result } -cleanup { + rename copy {} destroy .b } -result {{{1 3}} {{1 2}} {{1 1}} {}} diff --git a/tests/border.test b/tests/border.test index 981e640..f610ad8 100644 --- a/tests/border.test +++ b/tests/border.test @@ -131,12 +131,13 @@ test border-3.1 {FreeBorderObjProc} -constraints { testborder } -setup { set result {} + proc copy {s} {return [string index $s 0][string range $s 1 end]} } -body { - set x [join purple] + set x [copy purple] button .b -bg $x -text .b1 - set y [join purple] + set y [copy purple] .b configure -bg $y - set z [join purple] + set z [copy purple] .b configure -bg $z lappend result [testborder purple] set x red @@ -148,6 +149,7 @@ test border-3.1 {FreeBorderObjProc} -constraints { set y bogus return $result } -cleanup { + rename copy {} destroy .b } -result {{{1 3}} {{1 2}} {{1 1}} {}} diff --git a/tests/canvImg.test b/tests/canvImg.test index a609337..ea413bb 100644 --- a/tests/canvImg.test +++ b/tests/canvImg.test @@ -722,6 +722,7 @@ test canvImg-9.1 {DisplayImage procedure} -constraints testImageType -setup { test canvImg-10.1 {TranslateImage procedure} -constraints testImageType -setup { .c delete all + update } -body { image create test foo -variable x .c create image 50 100 -image foo -tags image -anchor nw @@ -737,6 +738,7 @@ test canvImg-10.1 {TranslateImage procedure} -constraints testImageType -setup { test canvImg-11.1 {TranslateImage procedure} -constraints testImageType -setup { .c delete all + update } -body { image create test foo -variable x .c create image 50 100 -image foo -tags image -anchor nw @@ -768,6 +770,7 @@ test canvImg-11.3 {ImageChangedProc procedure} -constraints { testImageType } -setup { .c delete all + update } -body { image create test foo -variable x image create test foo2 -variable y diff --git a/tests/clipboard.test b/tests/clipboard.test index 7f72f17..9689942 100644 --- a/tests/clipboard.test +++ b/tests/clipboard.test @@ -11,6 +11,11 @@ # environment variable TK_ALT_DISPLAY is set to an alternate display. # +################################################################# +# Note that some of these tests may fail if another application # +# is grabbing the clipboard (e.g. an X server, or a VNC viewer) # +################################################################# + package require tcltest 2.2 namespace import ::tcltest::* eval tcltest::configure $argv diff --git a/tests/color.test b/tests/color.test index aa20099..6fefd90 100644 --- a/tests/color.test +++ b/tests/color.test @@ -277,13 +277,17 @@ test color-3.4 {Tk_FreeColorFromObj - unlinking from list} colorsFree { lappend result [testcolor purple] } {{{4 1} {3 0} {2 0} {1 0}} {{4 1} {2 0} {1 0}} {{4 1} {2 0}} {{2 0}} {}} -test color-4.1 {FreeColorObjProc} colorsFree { +test color-4.1 {FreeColorObjProc} -constraints { + colorsFree +} -setup { + proc copy {s} {return [string index $s 0][string range $s 1 end]} +} -body { destroy .b - set x [format purple] + set x [copy purple] button .b -foreground $x -text .b1 - set y [format purple] + set y [copy purple] .b configure -foreground $y - set z [format purple] + set z [copy purple] .b configure -foreground $z set result {} lappend result [testcolor purple] @@ -295,7 +299,9 @@ test color-4.1 {FreeColorObjProc} colorsFree { lappend result [testcolor purple] set y bogus set result -} {{{1 3}} {{1 2}} {{1 1}} {}} +} -cleanup { + rename copy {} +} -result {{{1 3}} {{1 2}} {{1 1}} {}} destroy .t diff --git a/tests/cursor.test b/tests/cursor.test index ab7949e..172c982 100644 --- a/tests/cursor.test +++ b/tests/cursor.test @@ -144,12 +144,14 @@ test cursor-3.1 {Tk_FreeCursorFromObj - reference counts} -constraints { test cursor-4.1 {FreeCursorObjProc} -constraints { testcursor +} -setup { + proc copy {s} {return [string index $s 0][string range $s 1 end]} } -body { - set x [join heart] + set x [copy heart] button .b -cursor $x - set y [join heart] + set y [copy heart] .b configure -cursor $y - set z [join heart] + set z [copy heart] .b configure -cursor $z set result {} lappend result [testcursor heart] @@ -162,6 +164,7 @@ test cursor-4.1 {FreeCursorObjProc} -constraints { set y bogus set result } -cleanup { + rename copy {} destroy .b } -result {{{1 3}} {{1 2}} {{1 1}} {}} diff --git a/tests/font.test b/tests/font.test index 4fcf194..f7fb325 100644 --- a/tests/font.test +++ b/tests/font.test @@ -38,7 +38,7 @@ wm geom .t +0+0 update idletasks switch [tk windowingsystem] { - x11 {set fixed "fixed"} + x11 {set fixed "TkFixedFont"} win32 {set fixed "courier 12"} aqua {set fixed "monaco 9"} } diff --git a/tests/image.test b/tests/image.test index e2e602e..d4ea745 100644 --- a/tests/image.test +++ b/tests/image.test @@ -349,6 +349,7 @@ test image-8.1 {Tk_ImageCmd procedure, "inuse" option} -constraints { test image-9.1 {Tk_ImageChanged procedure} -constraints testImageType -setup { .c delete all imageCleanup + update } -body { image create test foo -variable x .c create image 50 50 -image foo @@ -364,6 +365,7 @@ test image-9.1 {Tk_ImageChanged procedure} -constraints testImageType -setup { test image-9.2 {Tk_ImageChanged procedure} -constraints testImageType -setup { .c delete all imageCleanup + update } -body { image create test foo -variable x .c create image 50 50 -image foo diff --git a/tests/option.test b/tests/option.test index ea5b5d1..c8e29da 100644 --- a/tests/option.test +++ b/tests/option.test @@ -386,7 +386,7 @@ test option-15.6 {database files} -body { test option-15.7 {database files} -body { option read $option1 option get . x9 color -} -result " \t\\A\n" +} -result " \\\t\\A\n" test option-15.8 {database files} -body { option read $option1 widget foo } -returnCodes error -result {wrong # args: should be "option readfile fileName ?priority?"} @@ -415,6 +415,22 @@ test option-16.1 {ReadOptionFile} -body { removeFile $option4 } -result {true false} +set opt162val {label { + foo bar +} +} +set opt162list [split $opt162val \n] + +test option-16.2 {ticket 766ef52f3} { + set option5 [makeFile {} option.file4] + set file [open $option5 w] + fconfigure $file -translation crlf + puts $file "*notok: $opt162list" + close $file + option read $option5 userDefault + option get . notok notok +} $opt162list + deleteWindows # cleanup diff --git a/tests/scrollbar.test b/tests/scrollbar.test index bd14067..9d6a83c 100644 --- a/tests/scrollbar.test +++ b/tests/scrollbar.test @@ -18,23 +18,38 @@ proc scroll args { proc getTroughSize {w} { if {[testConstraint testmetrics]} { + # Only Windows has [testmetrics] if [string match v* [$w cget -orient]] { return [expr [winfo height $w] - 2*[testmetrics cyvscroll $w]] } else { return [expr [winfo width $w] - 2*[testmetrics cxhscroll $w]] } } else { - if [string match v* [$w cget -orient]] { - return [expr [winfo height $w] \ - - ([winfo width $w] \ - - [$w cget -highlightthickness] \ - - [$w cget -bd] + 1)*2] - } else { - return [expr [winfo width $w] \ - - ([winfo height $w] \ - - [$w cget -highlightthickness] \ - - [$w cget -bd] + 1)*2] - } + if {[tk windowingsystem] eq "x11"} { + # Calculations here assume that the arrow area is a square. + if [string match v* [$w cget -orient]] { + return [expr [winfo height $w] \ + - ([winfo width $w] \ + - [$w cget -highlightthickness] \ + - [$w cget -bd] + 1)*2] + } else { + return [expr [winfo width $w] \ + - ([winfo height $w] \ + - [$w cget -highlightthickness] \ + - [$w cget -bd] + 1)*2] + } + } else { + # macOS aqua + if [string match v* [$w cget -orient]] { + return [expr [winfo height $w] \ + - ([$w cget -highlightthickness] \ + +[$w cget -bd])*2] + } else { + return [expr [winfo width $w] \ + - ([$w cget -highlightthickness] \ + +[$w cget -bd])*2] + } + } } } @@ -255,13 +270,13 @@ test scrollbar-3.35 {ScrollbarWidgetCmd procedure, "fraction" option} { format {%.6g} [.s fraction 4 21] } [format %.6g [expr (21.0 - ([winfo height .s] - [getTroughSize .s])/2.0) \ /([getTroughSize .s] - 1)]] -test scrollbar-3.36 {ScrollbarWidgetCmd procedure, "fraction" option} unix { +test scrollbar-3.36 {ScrollbarWidgetCmd procedure, "fraction" option} x11 { format {%.6g} [.s fraction 4 179] } {1} test scrollbar-3.37 {ScrollbarWidgetCmd procedure, "fraction" option} {testmetrics} { format {%.6g} [.s fraction 4 [expr 200 - [testmetrics cyvscroll .s]]] } {1} -test scrollbar-3.38 {ScrollbarWidgetCmd procedure, "fraction" option} unix { +test scrollbar-3.38 {ScrollbarWidgetCmd procedure, "fraction" option} x11 { format {%.6g} [.s fraction 4 178] } {0.993711} test scrollbar-3.39 {ScrollbarWidgetCmd procedure, "fraction" option} {testmetrics win} { @@ -281,9 +296,15 @@ test scrollbar-3.41 {ScrollbarWidgetCmd procedure, "fraction" option} { format {%.6g} [.t.s fraction 100 0] } {0.5} if {[testConstraint testmetrics]} { + # Only Windows has [testmetrics] place configure .t.s -width [expr 2*[testmetrics cxhscroll .t.s]+1] } else { - place configure .t.s -width [expr [winfo reqwidth .t.s] - 4] + if {[tk windowingsystem] eq "x11"} { + place configure .t.s -width [expr [winfo height .t.s] - 2*([.t.s cget -highlightthickness] + [.t.s cget -bd] + 1)] + } else { + # macOS aqua + place configure .t.s -width [expr 2*([.t.s cget -highlightthickness] + [.t.s cget -bd])] + } } update test scrollbar-3.42 {ScrollbarWidgetCmd procedure, "fraction" option} { @@ -317,9 +338,13 @@ test scrollbar-3.48 {ScrollbarWidgetCmd procedure, "identify" option} { test scrollbar-3.49 {ScrollbarWidgetCmd procedure, "identify" option} { list [catch {.s identify -1 bogus} msg] $msg } {1 {expected integer but got "bogus"}} -test scrollbar-3.50 {ScrollbarWidgetCmd procedure, "identify" option} { +test scrollbar-3.50.1 {ScrollbarWidgetCmd procedure, "identify" option} notAqua { .s identify 5 5 } {arrow1} +test scrollbar-3.50.1 {ScrollbarWidgetCmd procedure, "identify" option} aqua { + # macOS scrollbars have no arrows nowadays + .s identify 5 5 +} {trough1} test scrollbar-3.51 {ScrollbarWidgetCmd procedure, "identify" option} { .s identify 5 35 } {trough1} @@ -330,9 +355,13 @@ test scrollbar-3.52 {ScrollbarWidgetCmd procedure, "identify" option} { test scrollbar-3.53 {ScrollbarWidgetCmd procedure, "identify" option} { .s identify 5 145 } {trough2} -test scrollbar-3.54 {ScrollbarWidgetCmd procedure, "identify" option} {unixOrPc} { +test scrollbar-3.54.1 {ScrollbarWidgetCmd procedure, "identify" option} notAqua { .s identify 5 195 } {arrow2} +test scrollbar-3.54.2 {ScrollbarWidgetCmd procedure, "identify" option} aqua { + # macOS scrollbars have no arrows nowadays + .s identify 5 195 +} {trough2} test scrollbar-3.56 {ScrollbarWidgetCmd procedure, "identify" option} unix { .s identify 0 0 } {} @@ -455,12 +484,20 @@ test scrollbar-6.9 {ScrollbarPosition procedure} { test scrollbar-6.10 {ScrollbarPosition procedure} { .s identify [winfo width .s] [expr [winfo height .s] / 2] } {} -test scrollbar-6.11 {ScrollbarPosition procedure} unix { +test scrollbar-6.11.1 {ScrollbarPosition procedure} x11 { .s identify 8 4 } {arrow1} -test scrollbar-6.12 {ScrollbarPosition procedure} unix { +test scrollbar-6.11.2 {ScrollbarPosition procedure} aqua { + # macOS scrollbars have no arrows nowadays + .s identify 8 4 +} {trough1} +test scrollbar-6.12.1 {ScrollbarPosition procedure} x11 { .s identify 8 19 } {arrow1} +test scrollbar-6.12.2 {ScrollbarPosition procedure} aqua { + # macOS scrollbars have no arrows nowadays + .s identify 8 19 +} {trough1} test scrollbar-6.14 {ScrollbarPosition procedure} win { .s identify [expr [winfo width .s] / 2] 0 } {arrow1} @@ -504,11 +541,7 @@ test scrollbar-6.24 {ScrollbarPosition procedure} unix { test scrollbar-6.25 {ScrollbarPosition procedure} unix { .s identify 8 179 } {trough2} -test scrollbar-6.27 {ScrollbarPosition procedure} {testmetrics win knownBug} { - # This asks for 8,21, which is actually the slider, but there is a - # bug in that GetSystemMetrics(SM_CYVTHUMB) actually returns a value - # that is larger than the thumb displayed, skewing the ability to - # calculate the trough2 area correctly (Win2k). -- hobbs +test scrollbar-6.27 {ScrollbarPosition procedure} {testmetrics win} { .s identify [expr [winfo width .s] / 2] [expr int(.4 / [.s delta 0 1]) \ + [testmetrics cyvscroll .s]] } {trough2} @@ -516,12 +549,20 @@ test scrollbar-6.28 {ScrollbarPosition procedure} {testmetrics win} { .s identify [expr [winfo width .s] / 2] [expr [winfo height .s] \ - [testmetrics cyvscroll .s] - 1] } {trough2} -test scrollbar-6.29 {ScrollbarPosition procedure} unix { +test scrollbar-6.29.1 {ScrollbarPosition procedure} x11 { .s identify 8 180 } {arrow2} -test scrollbar-6.30 {ScrollbarPosition procedure} unix { +test scrollbar-6.29.2 {ScrollbarPosition procedure} aqua { + # macOS scrollbars have no arrows nowadays + .s identify 8 180 +} {trough2} +test scrollbar-6.30.1 {ScrollbarPosition procedure} x11 { .s identify 8 195 } {arrow2} +test scrollbar-6.30.2 {ScrollbarPosition procedure} aqua { + # macOS scrollbars have no arrows nowadays + .s identify 8 195 +} {trough2} test scrollbar-6.32 {ScrollbarPosition procedure} {testmetrics win} { .s identify [expr [winfo width .s] / 2] [expr [winfo height .s] \ - [testmetrics cyvscroll .s]] @@ -550,15 +591,23 @@ place .t.s -width 200 .t.s set .2 .4 update -test scrollbar-6.39 {ScrollbarPosition procedure} unix { +test scrollbar-6.39.1 {ScrollbarPosition procedure} x11 { .t.s identify 4 8 } {arrow1} +test scrollbar-6.39.2 {ScrollbarPosition procedure} aqua { + # macOS scrollbars have no arrows nowadays + .t.s identify 4 8 +} {trough1} test scrollbar-6.40 {ScrollbarPosition procedure} win { .t.s identify 0 [expr [winfo height .t.s] / 2] } {arrow1} -test scrollbar-6.41 {ScrollbarPosition procedure} unix { +test scrollbar-6.41.1 {ScrollbarPosition procedure} x11 { .t.s identify 82 8 } {slider} +test scrollbar-6.41.2 {ScrollbarPosition procedure} aqua { + # macOS scrollbars have no arrows nowadays + .t.s identify 82 8 +} {trough2} test scrollbar-6.43 {ScrollbarPosition procedure} {testmetrics win} { .t.s identify [expr int(.4 / [.t.s delta 1 0]) + [testmetrics cxhscroll .t.s] \ - 1] [expr [winfo height .t.s] / 2] @@ -582,7 +631,9 @@ test scrollbar-7.1 {EventuallyRedraw} { catch {destroy .t} toplevel .t wm geometry .t +0+0 -test scrollbar-8.1 {TkScrollbarEventProc: recursive deletion} { +test scrollbar-8.1 {TkScrollbarEventProc: recursive deletion} notAqua { + # constrained by notAqua because this test clicks on an arrow of the + # scrollbar - but macOS has no such arrows in modern scrollbars proc doit {args} { destroy .t.f } proc bgerror {args} {} destroy .t.f @@ -601,7 +652,9 @@ test scrollbar-8.1 {TkScrollbarEventProc: recursive deletion} { rename bgerror {} set result } {1 0 0} -test scrollbar-8.2 {TkScrollbarEventProc: recursive deletion} { +test scrollbar-8.2 {TkScrollbarEventProc: recursive deletion} notAqua { + # constrained by notAqua because this test clicks on an arrow of the + # scrollbar - but macOS has no such arrows in modern scrollbars proc doit {args} { destroy .t.f.s } proc bgerror {args} {} destroy .t.f @@ -632,7 +685,7 @@ test scrollbar-9.1 {scrollbar widget vs hidden commands} { list [winfo children .] [interp hidden] } [list {} $l] -test scrollbar-10.1 {<MouseWheel> event on scrollbar} -constraints {win|unix} -setup { +test scrollbar-10.1.1 {<MouseWheel> event on scrollbar} -constraints {notAqua} -setup { destroy .t .s } -body { pack [text .t -yscrollcommand {.s set}] -side left @@ -646,8 +699,22 @@ test scrollbar-10.1 {<MouseWheel> event on scrollbar} -constraints {win|unix} -s } -cleanup { destroy .t .s } -result {5.0} +test scrollbar-10.1.2 {<MouseWheel> event on scrollbar} -constraints {aqua} -setup { + destroy .t .s +} -body { + pack [text .t -yscrollcommand {.s set}] -side left + for {set i 1} {$i < 100} {incr i} {.t insert end "Line $i\n"} + pack [scrollbar .s -command {.t yview}] -fill y -expand 1 -side left + update + focus -force .s + event generate .s <MouseWheel> -delta -4 + after 200 {set eventprocessed 1} ; vwait eventprocessed + .t index @0,0 +} -cleanup { + destroy .t .s +} -result {5.0} -test scrollbar-10.2 {<MouseWheel> event on scrollbar} -constraints {win|unix} -setup { +test scrollbar-10.2.1 {<MouseWheel> event on scrollbar} -constraints {notAqua} -setup { destroy .t .s } -body { pack [text .t -xscrollcommand {.s set} -wrap none] -side top @@ -661,6 +728,20 @@ test scrollbar-10.2 {<MouseWheel> event on scrollbar} -constraints {win|unix} -s } -cleanup { destroy .t .s } -result {1.4} +test scrollbar-10.2.2 {<MouseWheel> event on scrollbar} -constraints {aqua} -setup { + destroy .t .s +} -body { + pack [text .t -xscrollcommand {.s set} -wrap none] -side top + for {set i 1} {$i < 100} {incr i} {.t insert end "Char $i "} + pack [scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top + update + focus -force .s + event generate .s <Shift-MouseWheel> -delta -4 + after 200 {set eventprocessed 1} ; vwait eventprocessed + .t index @0,0 +} -cleanup { + destroy .t .s +} -result {1.4} test scrollbar-11.1 {bug fix: [011706ec42] Scrollbar unsafe wrt widget destruction} -body { proc destroy_scrollbar {} { diff --git a/tests/text.test b/tests/text.test index c656446..988417e 100644 --- a/tests/text.test +++ b/tests/text.test @@ -3021,23 +3021,24 @@ test text-11a.22 {TextWidgetCmd procedure, "sync" option with -command} -setup { set ::x 0 toplevel .top pack [text .top.yt] + update set content {} for {set i 1} {$i < 30} {incr i} { append content [string repeat "$i " 15] \n } .top.yt insert 1.0 $content # first case: line metrics calculation still running when launching 'sync -command' - lappend res [.top.yt pendingsync] + lappend res [.top.yt pendingsync] ; # {1} .top.yt sync -command [list set ::x 1] - lappend res $::x + lappend res $::x ; # {1 0} # now finish line metrics calculations while {[.top.yt pendingsync]} {update} - lappend res [.top.yt pendingsync] $::x + lappend res [.top.yt pendingsync] $::x ; # {1 0 0 1} # second case: line metrics calculation completed when launching 'sync -command' .top.yt sync -command [list set ::x 2] - lappend res $::x + lappend res $::x ; # {1 0 0 1 1} vwait ::x - lappend res $::x + lappend res $::x ; # {1 0 0 1 1 2} } -cleanup { destroy .top.yt .top } -result {1 0 0 1 1 2} @@ -3047,6 +3048,7 @@ test text-11a.31 {"<<WidgetViewSync>>" event} -setup { } -body { toplevel .top pack [text .top.yt] + update set content {} for {set i 1} {$i < 300} {incr i} { append content [string repeat "$i " 15] \n @@ -3080,6 +3082,7 @@ test text-11a.41 {"sync" "pendingsync" and <<WidgetViewSync>>} -setup { set res {} toplevel .top pack [text .top.yt] + update set content {} for {set i 1} {$i < 300} {incr i} { append content [string repeat "$i " 50] \n @@ -5557,9 +5560,7 @@ test text-22.198 {TextSearchCmd, regexp search multi-line} -body { } -cleanup { destroy .t } -result {2.0 19} -test text-22.199 {TextSearchCmd, regexp search multi-line} -constraints { - knownBug -} -body { +test text-22.199 {TextSearchCmd, regexp search multi-line} -body { pack [text .t] .t insert 1.0 "aaaa\nbbbb\ncccc\nbbbb\naaaa\n" set foo {} @@ -5568,9 +5569,7 @@ test text-22.199 {TextSearchCmd, regexp search multi-line} -constraints { } -cleanup { destroy .t } -result {2.0 19} -test text-22.200 {TextSearchCmd, regexp search multi-line} -constraints { - knownBug -} -body { +test text-22.200 {TextSearchCmd, regexp search multi-line} -body { pack [text .t] .t insert 1.0 "aaaa\nbbbb\ncccc\nbbbb\naaaa\n" set foo {} @@ -5588,23 +5587,18 @@ test text-22.201 {TextSearchCmd, regexp search multi-line} -body { } -cleanup { destroy .t } -result {1.0 24} -test text-22.202 {TextSearchCmd, regexp search multi-line} -constraints { - knownBug -} -body { +test text-22.202 {TextSearchCmd, regexp search multi-line} -body { pack [text .t] .t insert 1.0 "aaaa\nbbbb\nbbbb\nbbbb\nbbbb\n" list [.t search -regexp -backward -all -count foo \ - -- {b+\n|a+\n(b+\n)+} end] $foo + -- {(b+\n|a+\n)(b+\n)+} end] $foo } -cleanup { destroy .t } -result {1.0 25} -test text-22.203 {TextSearchCmd, regexp search multi-line} -constraints { - knownBug -} -body { +test text-22.203 {TextSearchCmd, regexp search multi-line} -body { pack [text .t] .t insert 1.0 "aaaa\nbbbb\nbbbb\nbbbb\nbbbb\n" - .t search -regexp -backward -- {b+\n|a+\n(b+\n)+} end -# Should match at 1.0 for a true greedy match + .t search -regexp -backward -- {(b+\n|a+\n)(b+\n)+} end } -cleanup { destroy .t } -result {1.0} @@ -5873,7 +5867,219 @@ test text-22.225 {TextSearchCmd, strict limits} -body { } -cleanup { destroy .t } -result {} - +test text-22.226 {TextSearchCmd, exact search for the empty string} -body { + text .t + set res [.t search -count C "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.227 {TextSearchCmd, exact search for the empty string} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C "" 2.5] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.5 0} +test text-22.228 {TextSearchCmd, exact search all empty strings} -body { + text .t + set res [.t search -count C -all "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.229 {TextSearchCmd, exact search all empty strings} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -all "" 2.5 2.8] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.5 2.6 2.7 {0 0 0}} +test text-22.230 {TextSearchCmd, exact search all empty strings, with overlap} -body { + text .t + set res [.t search -count C -all -overlap "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.231 {TextSearchCmd, exact search all empty strings, with overlap} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -all -overlap "" 2.5 2.8] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.5 2.6 2.7 {0 0 0}} +test text-22.232 {TextSearchCmd, regexp search for the empty string} -body { + text .t + set res [.t search -count C -regexp "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.233 {TextSearchCmd, regexp search for the empty string} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -regexp "" 2.5] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.5 0} +test text-22.234 {TextSearchCmd, regexp search all empty strings} -body { + text .t + set res [.t search -count C -all -regexp "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.235 {TextSearchCmd, regexp search all empty strings} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -all -regexp "" 2.5 2.8] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.5 2.6 2.7 {0 0 0}} +test text-22.236 {TextSearchCmd, regexp search all empty strings, with overlap} -body { + text .t + set res [.t search -count C -all -regexp -overlap "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.237 {TextSearchCmd, regexp search all empty strings, with overlap} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -all -regexp -overlap "" 2.5 2.8] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.5 2.6 2.7 {0 0 0}} +test text-22.238 {TextSearchCmd, exact backwards search for the empty string} -body { + text .t + set res [.t search -count C -backwards "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.239 {TextSearchCmd, exact backwards search for the empty string} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -backwards "" 2.5] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.4 0} +test text-22.240 {TextSearchCmd, exact backwards search all empty strings} -body { + text .t + set res [.t search -count C -backwards -all "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.241 {TextSearchCmd, exact backwards search all empty strings} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -backwards -all "" 2.5 2.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.4 2.3 2.2 2.1 2.0 {0 0 0 0 0}} +test text-22.242 {TextSearchCmd, exact backwards search all empty strings, with overlap} -body { + text .t + set res [.t search -count C -backwards -all -overlap "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.243 {TextSearchCmd, exact backwards search all empty strings, with overlap} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -backwards -all -overlap "" 2.5 2.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.4 2.3 2.2 2.1 2.0 {0 0 0 0 0}} +test text-22.244 {TextSearchCmd, regexp backwards search for the empty string} -body { + text .t + set res [.t search -count C -backwards -regexp "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.245 {TextSearchCmd, regexpbackwards search for the empty string} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -backwards -regexp "" 2.5] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.4 0} +test text-22.246 {TextSearchCmd, regexp backwards search all empty strings} -body { + text .t + set res [.t search -count C -backwards -all -regexp "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.247 {TextSearchCmd, regexp backwards search all empty strings} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -backwards -all -regexp "" 2.5 2.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.4 2.3 2.2 2.1 2.0 {0 0 0 0 0}} +test text-22.248 {TextSearchCmd, regexp backwards search all empty strings, with overlap} -body { + text .t + set res [.t search -count C -backwards -all -regexp -overlap "" 1.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {1.0 0} +test text-22.249 {TextSearchCmd, regexp backwards search all empty strings, with overlap} -body { + text .t + .t insert end "Searching for the\nempty string!" + set res [.t search -count C -backwards -all -regexp -overlap "" 2.5 2.0] + lappend res $C +} -cleanup { + destroy .t + unset -nocomplain res C +} -result {2.4 2.3 2.2 2.1 2.0 {0 0 0 0 0}} +test text-22.250 {TextSearchCmd, backwards search all matching at start of line} -body { + text .t + .t insert end "abc" + set res [.t search -backwards -all b end] ; # works + lappend res [.t search -backwards a end] ; # works + lappend res [.t search -backwards -all a end] ; # used to hang +} -cleanup { + destroy .t +} -result {1.1 1.0 1.0} test text-23.1 {TkTextGetTabs procedure} -setup { text .t -highlightthickness 0 -bd 0 -relief flat -padx 0 -width 100 @@ -6339,6 +6545,8 @@ test text-27.10 {TextEditCmd procedure, set modified flag} -body { test text-27.11 {TextEditCmd procedure, set modified flag repeat} -setup { text .t pack .t +# Make sure the Text is mapped before we start + update set ::retval {} } -body { bind .t <<Modified>> "lappend ::retval modified" diff --git a/tests/textDisp.test b/tests/textDisp.test index 115b8cf..208f664 100644 --- a/tests/textDisp.test +++ b/tests/textDisp.test @@ -3374,6 +3374,16 @@ test textDisp-24.24 {TkTextCharLayoutProc, justification and tabs} {textfonts} { .t tag add x 1.0 end list [.t bbox 1.0] [.t bbox 1.10] } [list [list 45 3 7 $fixedHeight] [list 94 3 7 $fixedHeight]] +test textDisp-24.25 {TkTextCharLayoutProc, justification and tabs} -constraints {textfonts} -setup { + text .tt -tabs {40 right} -wrap none -font $fixedFont + pack .tt +} -body { + .tt insert end \t9\n\t99\n\t999 + update + list [.tt bbox 1.1] [.tt bbox 2.2] [.tt bbox 3.3] +} -cleanup { + destroy .tt +} -result [list [list 38 5 7 $fixedHeight] [list 38 20 7 $fixedHeight] [list 38 35 7 $fixedHeight]] .t configure -width 40 -bd 0 -relief flat -highlightthickness 0 -padx 0 \ -tabs 100 diff --git a/tests/textWind.test b/tests/textWind.test index fd29e19..e189663 100644 --- a/tests/textWind.test +++ b/tests/textWind.test @@ -11,28 +11,26 @@ namespace import ::tcltest::* tcltest::configure {*}$argv tcltest::loadTestedCommands -# Create entries in the option database to be sure that geometry options -# like border width have predictable values. - -option add *Text.borderWidth 2 -option add *Text.highlightThickness 2 -option add *Text.font {Courier -12} +deleteWindows +set fixedFont {"Courier New" -12} +set fixedHeight [font metrics $fixedFont -linespace] +set fixedWidth [font measure $fixedFont m] +set fixedAscent [font metrics $fixedFont -ascent] -deleteWindows -# Widget used in tests 1.* - 16.* -text .t -width 30 -height 6 -bd 2 -highlightthickness 2 +# Widget used in almost all tests +set tWidth 30 +set tHeight 6 +text .t -width $tWidth -height $tHeight -bd 2 -highlightthickness 2 \ + -font $fixedFont pack .t -expand 1 -fill both update .t debug on -# 15 on XP, 13 on Solaris 8 -set fixedHeight [font metrics {Courier -12} -linespace] -set fixedDiff [expr {$fixedHeight - 13}] ;# 2 on XP set color [expr {[winfo depth .t] > 1 ? "green" : "black"}] wm geometry . {} - + # The statements below reset the main window; it's needed if the window # manager is mwm to make mwm forget about a previous minimum size setting. @@ -41,9 +39,16 @@ wm minsize . 1 1 wm positionfrom . user wm deiconify . +set bw [.t cget -borderwidth] +set px [.t cget -padx] +set py [.t cget -pady] +set hlth [.t cget -highlightthickness] +set padx [expr {$bw+$px+$hlth}] +set pady [expr {$bw+$py+$hlth}] + # ---------------------------------------------------------------------- -test textWind-1.1 {basic tests of options} -constraints fonts -setup { +test textWind-1.1 {basic tests of options} -setup { .t delete 1.0 end } -body { .t insert end "This is the first line" @@ -53,8 +58,13 @@ test textWind-1.1 {basic tests of options} -constraints fonts -setup { update list [winfo ismapped .f] [winfo geom .f] [.t bbox .f] \ [.t window configure .f -window] -} -result {1 3x3+19+23 {19 23 3 3} {-window {} {} {} .f}} -test textWind-1.2 {basic tests of options} -constraints fonts -setup { +} -result [list \ + 1 \ + 3x3+[expr {$padx+2*$fixedWidth}]+[expr {$pady+$fixedHeight+(($fixedHeight-3)/2)}] \ + [list [expr {$padx+2*$fixedWidth}] [expr {$pady+$fixedHeight+(($fixedHeight-3)/2)}] 3 3] \ + {-window {} {} {} .f}] + +test textWind-1.2 {basic tests of options} -setup { .t delete 1.0 end } -body { .t insert end "This is the first line" @@ -64,7 +74,12 @@ test textWind-1.2 {basic tests of options} -constraints fonts -setup { update list [winfo ismapped .f] [winfo geom .f] [.t bbox .f] \ [.t window configure .f -align] -} -result {1 3x3+19+18 {19 18 3 3} {-align {} {} center top}} +} -result [list \ + 1 \ + 3x3+[expr {$padx+2*$fixedWidth}]+[expr {$pady+$fixedHeight}] \ + [list [expr {$padx+2*$fixedWidth}] [expr {$pady+$fixedHeight}] 3 3] \ + {-align {} {} center top}] + test textWind-1.3 {basic tests of options} -setup { .t delete 1.0 end } -body { @@ -73,17 +88,23 @@ test textWind-1.3 {basic tests of options} -setup { .t window create 2.2 -create "Test script" .t window configure 2.2 -create } -result {-create {} {} {} {Test script}} -test textWind-1.4 {basic tests of options} -constraints fonts -setup { + +test textWind-1.4 {basic tests of options} -setup { .t delete 1.0 end } -body { .t insert end "This is the first line" .t insert end "\nAnd this is a second line, which wraps around" + # the window .f should be wider than the fixed width frame .f -width 10 -height 20 -bg $color .t window create 2.2 -window .f -padx 5 update list [winfo geom .f] [.t window configure .f -padx] [.t bbox 2.3] -} -result {10x20+24+18 {-padx {} {} 0 5} {39 21 7 13}} -test textWind-1.5 {basic tests of options} -constraints fonts -setup { +} -result [list \ + 10x20+[expr {$padx+2*$fixedWidth+5}]+[expr {$pady+$fixedHeight}] \ + {-padx {} {} 0 5} \ + [list [expr {$padx+2*$fixedWidth+10+2*5}] [expr {$pady+$fixedHeight+((20-$fixedHeight)/2)}] $fixedWidth $fixedHeight]] + +test textWind-1.5 {basic tests of options} -setup { .t delete 1.0 end } -body { .t insert end "This is the first line" @@ -92,8 +113,12 @@ test textWind-1.5 {basic tests of options} -constraints fonts -setup { .t window create 2.2 -window .f -pady 4 update list [winfo geom .f] [.t window configure .f -pady] [.t bbox 2.31] -} -result {10x20+19+22 {-pady {} {} 0 4} {19 46 7 13}} -test textWind-1.6 {basic tests of options} -constraints fonts -setup { +} -result [list \ + 10x20+[expr {$padx+2*$fixedWidth}]+[expr {$pady+$fixedHeight+4}] \ + {-pady {} {} 0 4} \ + [list [expr {$padx+2*$fixedWidth}] [expr {$pady+$fixedHeight+20+2*4}] $fixedWidth $fixedHeight]] + +test textWind-1.6 {basic tests of options} -setup { .t delete 1.0 end } -body { .t insert end "This is the first line" @@ -102,7 +127,9 @@ test textWind-1.6 {basic tests of options} -constraints fonts -setup { .t window create 2.2 -window .f -stretch 1 update list [winfo geom .f] [.t window configure .f -stretch] -} -result {5x13+19+18 {-stretch {} {} 0 1}} +} -result [list \ + 5x$fixedHeight+[expr {$padx+2*$fixedWidth}]+[expr {$pady+$fixedHeight}] \ + {-stretch {} {} 0 1}] .t delete 1.0 end @@ -301,7 +328,8 @@ test textWind-3.1 {EmbWinConfigure procedure} -setup { } -cleanup { destroy .f } -returnCodes error -result {unknown option "-foo"} -test textWind-3.2 {EmbWinConfigure procedure} -constraints fonts -setup { + +test textWind-3.2 {EmbWinConfigure procedure} -setup { destroy .f } -body { .t insert 1.0 "Some sample text" @@ -314,7 +342,8 @@ test textWind-3.2 {EmbWinConfigure procedure} -constraints fonts -setup { } -cleanup { destroy .f } -returnCodes error -result {bad text index ".f"} -test textWind-3.3 {EmbWinConfigure procedure} -constraints fonts -setup { + +test textWind-3.3 {EmbWinConfigure procedure} -setup { destroy .f } -body { .t insert 1.0 "Some sample text" @@ -327,8 +356,10 @@ test textWind-3.3 {EmbWinConfigure procedure} -constraints fonts -setup { list [winfo ismapped .f] [.t bbox 1.4] } -cleanup { destroy .f -} -result {0 {26 5 7 13}} -test textWind-3.4 {EmbWinConfigure procedure} -constraints fonts -setup { +} -result [list 0 \ + [list [expr {$padx+3*$fixedWidth}] $pady $fixedWidth $fixedHeight]] + +test textWind-3.4 {EmbWinConfigure procedure} -setup { destroy .t.f } -body { .t insert 1.0 "Some sample text" @@ -341,7 +372,8 @@ test textWind-3.4 {EmbWinConfigure procedure} -constraints fonts -setup { } -cleanup { destroy .t.f } -returnCodes error -result {bad text index ".t.f"} -test textWind-3.5 {EmbWinConfigure procedure} -constraints fonts -setup { + +test textWind-3.5 {EmbWinConfigure procedure} -setup { destroy .t.f } -body { .t insert 1.0 "Some sample text" @@ -354,8 +386,10 @@ test textWind-3.5 {EmbWinConfigure procedure} -constraints fonts -setup { list [winfo ismapped .t.f] [.t bbox 1.4] } -cleanup { destroy .t.f -} -result {0 {26 5 7 13}} -test textWind-3.6 {EmbWinConfigure procedure} -constraints fonts -setup { +} -result [list 0 \ + [list [expr {$padx+3*$fixedWidth}] $pady $fixedWidth $fixedHeight]] + +test textWind-3.6 {EmbWinConfigure procedure} -setup { destroy .f } -body { .t insert 1.0 "Some sample text" @@ -367,7 +401,9 @@ test textWind-3.6 {EmbWinConfigure procedure} -constraints fonts -setup { list [catch {.t index .f} msg] $msg [winfo ismapped .f] [.t bbox 1.4] } -cleanup { destroy .f -} -result {0 1.3 1 {36 8 7 13}} +} -result [list 0 1.3 1 \ + [list [expr {$padx+3*$fixedWidth+10}] [expr {$pady+((20-$fixedHeight)/2)}] $fixedWidth $fixedHeight]] + test textWind-3.7 {EmbWinConfigure procedure} -setup { destroy .f } -body { @@ -450,8 +486,7 @@ test textWind-4.6 {AlignParseProc and AlignPrintProc procedures} -body { .t window configure 1.0 -align } -result {-align {} {} center top} - -test textWind-5.1 {EmbWinStructureProc procedure} -constraints fonts -setup { +test textWind-5.1 {EmbWinStructureProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -462,7 +497,8 @@ test textWind-5.1 {EmbWinStructureProc procedure} -constraints fonts -setup { destroy .f .t index .f } -returnCodes error -result {bad text index ".f"} -test textWind-5.2 {EmbWinStructureProc procedure} -constraints fonts -setup { + +test textWind-5.2 {EmbWinStructureProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -473,8 +509,11 @@ test textWind-5.2 {EmbWinStructureProc procedure} -constraints fonts -setup { destroy .f catch {.t index .f} list [.t bbox 1.2] [.t bbox 1.3] -} -result {{19 11 0 0} {19 5 7 13}} -test textWind-5.3 {EmbWinStructureProc procedure} -constraints fonts -setup { +} -result [list \ + [list [expr {$padx+2*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0] \ + [list [expr {$padx+2*$fixedWidth}] $pady $fixedWidth $fixedHeight]] + +test textWind-5.3 {EmbWinStructureProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -486,7 +525,8 @@ test textWind-5.3 {EmbWinStructureProc procedure} -constraints fonts -setup { destroy .f .t index .f } -returnCodes error -result {bad text index ".f"} -test textWind-5.4 {EmbWinStructureProc procedure} -constraints fonts -setup { + +test textWind-5.4 {EmbWinStructureProc procedure} -setup { .t delete 1.0 end } -body { .t insert 1.0 "Some sample text" @@ -497,8 +537,11 @@ test textWind-5.4 {EmbWinStructureProc procedure} -constraints fonts -setup { destroy .f catch {.t index .f} list [.t bbox 1.2] [.t bbox 1.3] -} -result {{19 18 0 0} {19 5 7 13}} -test textWind-5.5 {EmbWinStructureProc procedure} -constraints fonts -setup { +} -result [list \ + [list [expr {$padx+2*$fixedWidth}] [expr {$pady+$fixedHeight}] 0 0] \ + [list [expr {$padx+2*$fixedWidth}] $pady $fixedWidth $fixedHeight]] + +test textWind-5.5 {EmbWinStructureProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -509,10 +552,12 @@ test textWind-5.5 {EmbWinStructureProc procedure} -constraints fonts -setup { destroy .f update list [catch {.t index .f} msg] $msg [.t bbox 1.2] [.t bbox 1.3] -} -result {0 1.2 {19 6 20 10} {39 5 7 13}} +} -result [list 0 1.2 \ + [list [expr {$padx+2*$fixedWidth}] [expr {$pady+(($fixedHeight-10)/2)}] 20 10] \ + [list [expr {$padx+2*$fixedWidth+20}] $pady $fixedWidth $fixedHeight]] -test textWind-6.1 {EmbWinRequestProc procedure} -constraints fonts -setup { +test textWind-6.1 {EmbWinRequestProc procedure} -setup { .t delete 1.0 end destroy .f set result {} @@ -525,12 +570,14 @@ test textWind-6.1 {EmbWinRequestProc procedure} -constraints fonts -setup { lappend result [.t bbox 1.2] [.t bbox 1.3] } -cleanup { destroy .f -} -result {{19 5 10 20} {29 8 7 13} {19 5 25 30} {44 13 7 13}} +} -result [list \ + [list [expr {$padx+2*$fixedWidth}] $pady 10 20] \ + [list [expr {$padx+2*$fixedWidth+10}] [expr {$pady+((20-$fixedHeight)/2)}] $fixedWidth $fixedHeight] \ + [list [expr {$padx+2*$fixedWidth}] $pady 25 30] \ + [list [expr {$padx+2*$fixedWidth+25}] [expr {$pady+((30-$fixedHeight)/2)}] $fixedWidth $fixedHeight]] -test textWind-7.1 {EmbWinLostSlaveProc procedure} -constraints { - textfonts -} -setup { +test textWind-7.1 {EmbWinLostSlaveProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -543,10 +590,11 @@ test textWind-7.1 {EmbWinLostSlaveProc procedure} -constraints { list [winfo geom .f] [.t bbox 1.2] } -cleanup { destroy .f -} -result [list 10x20+105+55 [list 19 [expr {11+$fixedDiff/2}] 0 0]] -test textWind-7.2 {EmbWinLostSlaveProc procedure} -constraints { - textfonts -} -setup { +} -result [list \ + 10x20+[expr {$padx+100}]+[expr {$pady+50}] \ + [list [expr {$padx+2*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0]] + +test textWind-7.2 {EmbWinLostSlaveProc procedure} -setup { .t delete 1.0 end destroy .t.f } -body { @@ -559,10 +607,11 @@ test textWind-7.2 {EmbWinLostSlaveProc procedure} -constraints { list [winfo geom .t.f] [.t bbox 1.2] } -cleanup { destroy .t.f -} -result [list 10x20+105+55 [list 19 [expr {11+$fixedDiff/2}] 0 0]] +} -result [list \ + 10x20+[expr {$padx+100}]+[expr {$pady+50}] \ + [list [expr {$padx+2*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0]] - -test textWind-8.1 {EmbWinDeleteProc procedure} -constraints fonts -setup { +test textWind-8.1 {EmbWinDeleteProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -573,8 +622,12 @@ test textWind-8.1 {EmbWinDeleteProc procedure} -constraints fonts -setup { set x XXX .t delete 1.2 list $x [.t bbox 1.2] [.t bbox 1.3] [winfo exists .f] -} -result {destroyed {19 5 7 13} {26 5 7 13} 0} -test textWind-8.2 {EmbWinDeleteProc procedure} -constraints fonts -setup { +} -result [list destroyed \ + [list [expr {$padx+2*$fixedWidth}] $pady $fixedWidth $fixedHeight] \ + [list [expr {$padx+3*$fixedWidth}] $pady $fixedWidth $fixedHeight] \ + 0] + +test textWind-8.2 {EmbWinDeleteProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -615,9 +668,8 @@ test textWind-10.1 {EmbWinLayoutProc procedure} -setup { } -cleanup { destroy .f } -result {1 10 20 1.5} -test textWind-10.2 {EmbWinLayoutProc procedure, error in creating window} -constraints { - fonts -} -setup { + +test textWind-10.2 {EmbWinLayoutProc procedure, error in creating window} -setup { .t delete 1.0 end proc bgerror args { global msg @@ -625,7 +677,7 @@ test textWind-10.2 {EmbWinLayoutProc procedure, error in creating window} -const } } -body { .t insert 1.0 "Some sample text" - .t window create 1.5 -create { + .t window create 1.5 -create { error "couldn't create window" } set msg xyzzy @@ -633,10 +685,11 @@ test textWind-10.2 {EmbWinLayoutProc procedure, error in creating window} -const list $msg [.t bbox 1.5] } -cleanup { rename bgerror {} -} -result {{{couldn't create window}} {40 11 0 0}} -test textWind-10.3 {EmbWinLayoutProc procedure, error in creating window} -constraints { - fonts -} -setup { +} -result [list \ + {{couldn't create window}} \ + [list [expr {$padx+5*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0]] + +test textWind-10.3 {EmbWinLayoutProc procedure, error in creating window} -setup { .t delete 1.0 end proc bgerror args { global msg @@ -652,26 +705,16 @@ test textWind-10.3 {EmbWinLayoutProc procedure, error in creating window} -const list $msg [.t bbox 1.5] } -cleanup { rename bgerror {} -} -result {{{bad window path name "gorp"}} {40 11 0 0}} - .t delete 1.0 end - destroy .t.f - proc bgerror args { - global msg - if {[lsearch -exact $msg $args] == -1} { - lappend msg $args - } - } +} -result [list \ + {{bad window path name "gorp"}} \ + [list [expr {$padx+5*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0]] -test textWind-10.4 {EmbWinLayoutProc procedure, error in creating window} -constraints { - textfonts -} -setup { +test textWind-10.4 {EmbWinLayoutProc procedure, error in creating window} -setup { .t delete 1.0 end destroy .t.f proc bgerror args { global msg - if {[lsearch -exact $msg $args] == -1} { - lappend msg $args - } + lappend msg $args } } -body { .t insert 1.0 "Some sample text" @@ -693,17 +736,17 @@ test textWind-10.4 {EmbWinLayoutProc procedure, error in creating window} -const } -cleanup { destroy .t.f rename bgerror {} -} -result [list {{can't embed .t.f.f relative to .t}} {{window name "f" already exists in parent}} [list 40 [expr {11+$fixedDiff/2}] 0 0] 1] -test textWind-10.5 {EmbWinLayoutProc procedure, error in creating window} -constraints { - textfonts -} -setup { +} -result [list \ + {{can't embed .t.f.f relative to .t}} {{window name "f" already exists in parent}} \ + [list [expr {$padx+5*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0] \ + 1] + +test textWind-10.5 {EmbWinLayoutProc procedure, error in creating window} -setup { .t delete 1.0 end destroy .t.f proc bgerror args { global msg - if {[lsearch -exact $msg $args] == -1} { - lappend msg $args - } + lappend msg $args } } -body { .t insert 1.0 "Some sample text" @@ -718,10 +761,8 @@ test textWind-10.5 {EmbWinLayoutProc procedure, error in creating window} -const destroy .t.f rename bgerror {} } -result {{{can't embed .t.f.f relative to .t}} 1} -catch {destroy .t.f} -test textWind-10.6 {EmbWinLayoutProc procedure, error in creating window} -constraints { - textfonts -} -setup { + +test textWind-10.6 {EmbWinLayoutProc procedure, error in creating window} -setup { .t delete 1.0 end proc bgerror args { global msg @@ -731,6 +772,7 @@ test textWind-10.6 {EmbWinLayoutProc procedure, error in creating window} -const } } -body { .t insert 1.0 "Some sample text" + update .t window create 1.5 -create { concat .t } @@ -739,17 +781,16 @@ test textWind-10.6 {EmbWinLayoutProc procedure, error in creating window} -const lappend msg [.t bbox 1.5] } -cleanup { rename bgerror {} -} -result [list {{can't embed .t relative to .t}} [list 40 [expr {11+$fixedDiff/2}] 0 0]] -test textWind-10.7 {EmbWinLayoutProc procedure, error in creating window} -constraints { - textfonts -} -setup { +} -result [list \ + {{can't embed .t relative to .t}} \ + [list [expr {$padx+5*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0]] + +test textWind-10.7 {EmbWinLayoutProc procedure, error in creating window} -setup { .t delete 1.0 end destroy .t2 proc bgerror args { global msg - if {[lsearch -exact $msg $args] == -1} { - lappend msg $args - } + lappend msg $args } } -body { .t insert 1.0 "Some sample text" @@ -763,15 +804,16 @@ test textWind-10.7 {EmbWinLayoutProc procedure, error in creating window} -const lappend msg [.t bbox 1.5] } -cleanup { rename bgerror {} -} -result [list {{can't embed .t2 relative to .t}} {{window name "t2" already exists in parent}} [list 40 [expr {11+$fixedDiff/2}] 0 0]] +} -result [list \ + {{can't embed .t2 relative to .t}} {{window name "t2" already exists in parent}} \ + [list [expr {$padx+5*$fixedWidth}] [expr {$pady+($fixedHeight/2)}] 0 0]] + test textWind-10.8 {EmbWinLayoutProc procedure, error in creating window} -setup { .t delete 1.0 end destroy .t2 proc bgerror args { global msg - if {[lsearch -exact $msg $args] == -1} { - lappend msg $args - } + lappend msg $args } } -body { .t insert 1.0 "Some sample text" @@ -804,9 +846,8 @@ test textWind-10.9 {EmbWinLayoutProc procedure, steal window from self} -setup { } -cleanup { destroy .t.b } -result {1.3} -test textWind-10.10 {EmbWinLayoutProc procedure, doesn't fit on line} -constraints { - fonts -} -setup { + +test textWind-10.10 {EmbWinLayoutProc procedure, doesn't fit on line} -setup { .t delete 1.0 end destroy .f } -body { @@ -817,10 +858,11 @@ test textWind-10.10 {EmbWinLayoutProc procedure, doesn't fit on line} -constrain list [.t bbox .f] [.t bbox 1.13] } -cleanup { destroy .f -} -result {{89 5 126 20} {5 25 7 13}} -test textWind-10.11 {EmbWinLayoutProc procedure, doesn't fit on line} -constraints { - fonts -} -setup { +} -result [list \ + [list [expr {$padx+12*$fixedWidth}] $pady [expr {$tWidth*$fixedWidth-12*$fixedWidth}] 20] \ + [list $padx [expr {$pady+20}] $fixedWidth $fixedHeight]] + +test textWind-10.11 {EmbWinLayoutProc procedure, doesn't fit on line} -setup { .t delete 1.0 end destroy .f } -body { @@ -832,10 +874,11 @@ test textWind-10.11 {EmbWinLayoutProc procedure, doesn't fit on line} -constrain list [.t bbox .f] [.t bbox 1.13] } -cleanup { destroy .f -} -result {{89 5 126 20} {5 25 7 13}} -test textWind-10.12 {EmbWinLayoutProc procedure, doesn't fit on line} -constraints { - fonts -} -setup { +} -result [list \ + [list [expr {$padx+12*$fixedWidth}] $pady [expr {$tWidth*$fixedWidth-12*$fixedWidth}] 20] \ + [list $padx [expr {$pady+20}] $fixedWidth $fixedHeight]] + +test textWind-10.12 {EmbWinLayoutProc procedure, doesn't fit on line} -setup { .t delete 1.0 end destroy .f } -body { @@ -847,7 +890,10 @@ test textWind-10.12 {EmbWinLayoutProc procedure, doesn't fit on line} -constrain list [.t bbox .f] [.t bbox 1.13] } -cleanup { destroy .f -} -result {{5 18 127 20} {132 21 7 13}} +} -result [list \ + [list $padx [expr {$pady+$fixedHeight}] 127 20] \ + [list [expr {$padx+127}] [expr {$pady+$fixedHeight+((20-$fixedHeight)/2)}] $fixedWidth $fixedHeight]] + test textWind-10.13 {EmbWinLayoutProc procedure, doesn't fit on line} -setup { .t delete 1.0 end destroy .f @@ -860,10 +906,11 @@ test textWind-10.13 {EmbWinLayoutProc procedure, doesn't fit on line} -setup { list [.t bbox .f] [.t bbox 1.13] } -cleanup { destroy .f -} -result {{89 5 126 20} {}} -test textWind-10.14 {EmbWinLayoutProc procedure, doesn't fit on line} -constraints { - fonts -} -setup { +} -result [list \ + [list [expr {$padx+12*$fixedWidth}] $pady [expr {$tWidth*$fixedWidth-12*$fixedWidth}] 20] \ + {}] + +test textWind-10.14 {EmbWinLayoutProc procedure, doesn't fit on line} -setup { .t delete 1.0 end destroy .f } -body { @@ -875,10 +922,11 @@ test textWind-10.14 {EmbWinLayoutProc procedure, doesn't fit on line} -constrain list [.t bbox .f] [.t bbox 1.13] } -cleanup { destroy .f -} -result {{89 5 126 78} {}} -test textWind-10.15 {EmbWinLayoutProc procedure, doesn't fit on line} -constraints { - fonts -} -setup { +} -result [list \ + [list [expr {$padx+12*$fixedWidth}] $pady [expr {$tWidth*$fixedWidth-12*$fixedWidth}] [expr {$tHeight*$fixedHeight}]] \ + {}] + +test textWind-10.15 {EmbWinLayoutProc procedure, doesn't fit on line} -setup { .t delete 1.0 end destroy .f } -body { @@ -890,14 +938,17 @@ test textWind-10.15 {EmbWinLayoutProc procedure, doesn't fit on line} -constrain list [.t bbox .f] [.t bbox 1.13] } -cleanup { destroy .f -} -result {{5 18 210 65} {}} - +} -result [list \ + [list $padx [expr {$pady+$fixedHeight}] [expr {$tWidth*$fixedWidth}] [expr {($tHeight-1)*$fixedHeight}]] \ + {}] test textWind-11.1 {EmbWinDisplayProc procedure, geometry transforms} -setup { .t delete 1.0 end destroy .f place forget .t pack .t +# Make sure the Text is mapped before we start + update } -body { .t insert 1.0 "Some sample text" pack forget .t @@ -909,12 +960,15 @@ test textWind-11.1 {EmbWinDisplayProc procedure, geometry transforms} -setup { } -cleanup { destroy .f place forget .t -} -result {30x20+119+55} +} -result [list 30x20+[expr {$padx+30+12*$fixedWidth}]+[expr {$pady+50}]] + test textWind-11.2 {EmbWinDisplayProc procedure, geometry transforms} -setup { .t delete 1.0 end destroy .t.f place forget .t pack .t +# Make sure the Text is mapped before we start + update } -body { .t insert 1.0 "Some sample text" pack forget .t @@ -927,12 +981,15 @@ test textWind-11.2 {EmbWinDisplayProc procedure, geometry transforms} -setup { destroy .t.f place forget .t pack .t -} -result {30x20+89+5} +} -result [list 30x20+[expr {$padx+12*$fixedWidth}]+$pady] + test textWind-11.3 {EmbWinDisplayProc procedure, configuration optimization} -setup { .t delete 1.0 end destroy .f place forget .t pack .t +# Make sure the Text is mapped before we start + update } -body { .t insert 1.0 "Some sample text" frame .f -width 30 -height 20 -bg $color @@ -949,9 +1006,8 @@ test textWind-11.3 {EmbWinDisplayProc procedure, configuration optimization} -se place forget .t pack .t } -result {no configures} -test textWind-11.4 {EmbWinDisplayProc procedure, horizontal scrolling} -constraints { - fonts -} -setup { + +test textWind-11.4 {EmbWinDisplayProc procedure, horizontal scrolling} -setup { .t delete 1.0 end destroy .f .f2 } -body { @@ -969,10 +1025,12 @@ test textWind-11.4 {EmbWinDisplayProc procedure, horizontal scrolling} -constrai list [winfo ismapped .f] [winfo geom .f] [.t bbox .f] [winfo ismapped .f2] } -cleanup { destroy .f .f2 -} -result {1 30x20+103+18 {103 18 30 20} 0} -test textWind-11.5 {EmbWinDisplayProc procedure, horizontal scrolling} -constraints { - fonts -} -setup { +} -result [list 1 \ + 30x20+[expr {$padx+14*$fixedWidth}]+[expr {$pady+$fixedHeight}] \ + [list [expr {$padx+14*$fixedWidth}] [expr {$pady+$fixedHeight}] 30 20] \ + 0] + +test textWind-11.5 {EmbWinDisplayProc procedure, horizontal scrolling} -setup { .t delete 1.0 end destroy .f .f2 } -body { @@ -990,10 +1048,11 @@ test textWind-11.5 {EmbWinDisplayProc procedure, horizontal scrolling} -constrai update list [winfo ismapped .f] [winfo ismapped .f2] [winfo geom .f2] [.t bbox .f2] } -cleanup { - destroy .f .f2 -} -result {0 1 40x10+119+23 {119 23 40 10}} -.t configure -wrap char - + destroy .f .f2 + .t configure -wrap char +} -result [list 0 1 \ + 40x10+[expr {$padx+37*$fixedWidth+30-25*$fixedWidth}]+[expr {$pady+$fixedHeight+((20-10)/2)}] \ + [list [expr {$padx+37*$fixedWidth+30-25*$fixedWidth}] [expr {$pady+$fixedHeight+((20-10)/2)}] 40 10]] test textWind-12.1 {EmbWinUndisplayProc procedure, mapping/unmapping} -setup { .t delete 1.0 end @@ -1035,8 +1094,11 @@ test textWind-13.1 {EmbWinBboxProc procedure} -setup { list [winfo geom .f] [.t bbox .f] } -cleanup { destroy .f -} -result {5x5+21+6 {21 6 5 5}} -test textWind-13.2 {EmbWinBboxProc procedure} -constraints fonts -setup { +} -result [list \ + 5x5+[expr {$padx+2*$fixedWidth+2}]+[expr {$pady+1}] \ + [list [expr {$padx+2*$fixedWidth+2}] [expr {$pady+1}] 5 5]] + +test textWind-13.2 {EmbWinBboxProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -1047,8 +1109,11 @@ test textWind-13.2 {EmbWinBboxProc procedure} -constraints fonts -setup { list [winfo geom .f] [.t bbox .f] } -cleanup { destroy .f -} -result {5x5+21+9 {21 9 5 5}} -test textWind-13.3 {EmbWinBboxProc procedure} -constraints fonts -setup { +} -result [list \ + 5x5+[expr {$padx+2*$fixedWidth+2}]+[expr {$pady+1+(($fixedHeight-7)/2)}] \ + [list [expr {$padx+2*$fixedWidth+2}] [expr {$pady+1+(($fixedHeight-7)/2)}] 5 5]] + +test textWind-13.3 {EmbWinBboxProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -1059,8 +1124,11 @@ test textWind-13.3 {EmbWinBboxProc procedure} -constraints fonts -setup { list [winfo geom .f] [.t bbox .f] } -cleanup { destroy .f -} -result {5x5+21+10 {21 10 5 5}} -test textWind-13.4 {EmbWinBboxProc procedure} -constraints fonts -setup { +} -result [list \ + 5x5+[expr {$padx+2*$fixedWidth+2}]+[expr {$pady+1+($fixedAscent-6)}] \ + [list [expr {$padx+2*$fixedWidth+2}] [expr {$pady+1+($fixedAscent-6)}] 5 5]] + +test textWind-13.4 {EmbWinBboxProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -1071,8 +1139,11 @@ test textWind-13.4 {EmbWinBboxProc procedure} -constraints fonts -setup { list [winfo geom .f] [.t bbox .f] } -cleanup { destroy .f -} -result {5x5+21+12 {21 12 5 5}} -test textWind-13.5 {EmbWinBboxProc procedure} -constraints fonts -setup { +} -result [list \ + 5x5+[expr {$padx+2*$fixedWidth+2}]+[expr {$pady+1+($fixedHeight-7)}] \ + [list [expr {$padx+2*$fixedWidth+2}] [expr {$pady+1+($fixedHeight-7)}] 5 5]] + +test textWind-13.5 {EmbWinBboxProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -1083,8 +1154,11 @@ test textWind-13.5 {EmbWinBboxProc procedure} -constraints fonts -setup { list [winfo geom .f] [.t bbox .f] } -cleanup { destroy .f -} -result {5x11+21+6 {21 6 5 11}} -test textWind-13.6 {EmbWinBboxProc procedure} -constraints fonts -setup { +} -result [list \ + 5x[expr {$fixedHeight-2}]+[expr {$padx+2*$fixedWidth+2}]+[expr {$pady+1}] \ + [list [expr {$padx+2*$fixedWidth+2}] [expr {$pady+1}] 5 [expr {$fixedHeight-2}]]] + +test textWind-13.6 {EmbWinBboxProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -1095,8 +1169,11 @@ test textWind-13.6 {EmbWinBboxProc procedure} -constraints fonts -setup { list [winfo geom .f] [.t bbox .f] } -cleanup { destroy .f -} -result {5x11+21+6 {21 6 5 11}} -test textWind-13.7 {EmbWinBboxProc procedure} -constraints fonts -setup { +} -result [list \ + 5x[expr {$fixedHeight-2}]+[expr {$padx+2*$fixedWidth+2}]+[expr {$pady+1}] \ + [list [expr {$padx+2*$fixedWidth+2}] [expr {$pady+1}] 5 [expr {$fixedHeight-2}]]] + +test textWind-13.7 {EmbWinBboxProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -1107,8 +1184,11 @@ test textWind-13.7 {EmbWinBboxProc procedure} -constraints fonts -setup { list [winfo geom .f] [.t bbox .f] } -cleanup { destroy .f -} -result {5x9+21+6 {21 6 5 9}} -test textWind-13.8 {EmbWinBboxProc procedure} -constraints fonts -setup { +} -result [list \ + 5x[expr {$fixedAscent-1}]+[expr {$padx+2*$fixedWidth+2}]+[expr {$pady+1}] \ + [list [expr {$padx+2*$fixedWidth+2}] [expr {$pady+1}] 5 [expr {$fixedAscent-1}]]] + +test textWind-13.8 {EmbWinBboxProc procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -1119,10 +1199,11 @@ test textWind-13.8 {EmbWinBboxProc procedure} -constraints fonts -setup { list [winfo geom .f] [.t bbox .f] } -cleanup { destroy .f -} -result {5x11+21+6 {21 6 5 11}} -test textWind-13.9 {EmbWinBboxProc procedure, spacing options} -constraints { - fonts -} -setup { +} -result [list \ + 5x[expr {$fixedHeight-2}]+[expr {$padx+2*$fixedWidth+2}]+[expr {$pady+1}] \ + [list [expr {$padx+2*$fixedWidth+2}] [expr {$pady+1}] 5 [expr {$fixedHeight-2}]]] + +test textWind-13.9 {EmbWinBboxProc procedure, spacing options} -setup { .t delete 1.0 end destroy .f } -body { @@ -1134,8 +1215,11 @@ test textWind-13.9 {EmbWinBboxProc procedure, spacing options} -constraints { update list [winfo geom .f] [.t bbox .f] } -cleanup { + .t configure -spacing1 0 -spacing3 0 destroy .f -} -result {5x5+21+14 {21 14 5 5}} +} -result [list \ + 5x5+[expr {$padx+2*$fixedWidth+2}]+[expr {$pady+5+(($fixedHeight-5)/2)}] \ + [list [expr {$padx+2*$fixedWidth+2}] [expr {$pady+5+(($fixedHeight-5)/2)}] 5 5]] test textWind-14.1 {EmbWinDelayedUnmap procedure} -setup { @@ -1157,6 +1241,7 @@ test textWind-14.1 {EmbWinDelayedUnmap procedure} -setup { } -cleanup { destroy .f } -result {modified removed unmapped updated} + test textWind-14.2 {EmbWinDelayedUnmap procedure} -setup { .t delete 1.0 end destroy .f @@ -1176,6 +1261,7 @@ test textWind-14.2 {EmbWinDelayedUnmap procedure} -setup { } -cleanup { destroy .f } -result {modified deleted updated} + test textWind-14.3 {EmbWinDelayedUnmap procedure} -setup { .t delete 1.0 end destroy .f @@ -1191,6 +1277,7 @@ test textWind-14.3 {EmbWinDelayedUnmap procedure} -setup { } -cleanup { destroy .f } -result {1 0} + test textWind-14.4 {EmbWinDelayedUnmap procedure} -setup { .t delete 1.0 end destroy .t.f @@ -1207,13 +1294,13 @@ test textWind-14.4 {EmbWinDelayedUnmap procedure} -setup { destroy .t.f } -result {1 0} - test textWind-15.1 {TkTextWindowIndex procedure} -setup { .t delete 1.0 end } -body { .t index .foo } -returnCodes error -result {bad text index ".foo"} -test textWind-15.2 {TkTextWindowIndex procedure} -constraints fonts -setup { + +test textWind-15.2 {TkTextWindowIndex procedure} -setup { .t delete 1.0 end destroy .f } -body { @@ -1227,7 +1314,8 @@ test textWind-15.2 {TkTextWindowIndex procedure} -constraints fonts -setup { list [.t index .f] [.t bbox 1.7] } -cleanup { destroy .f -} -result {1.6 {77 8 7 13}} +} -result [list 1.6 \ + [list [expr {$padx+6*$fixedWidth+30}] [expr {$pady+((20-$fixedHeight)/2)}] $fixedWidth $fixedHeight]] test textWind-16.1 {EmbWinTextStructureProc procedure} -setup { @@ -1245,6 +1333,7 @@ test textWind-16.1 {EmbWinTextStructureProc procedure} -setup { } -cleanup { pack .t } -result 0 + test textWind-16.2 {EmbWinTextStructureProc procedure} -setup { .t delete 1.0 end destroy .f .f2 @@ -1263,7 +1352,12 @@ test textWind-16.2 {EmbWinTextStructureProc procedure} -setup { lappend result [winfo geom .f] [.t bbox .f] } -cleanup { destroy .f .f2 -} -result {30x20+47+5 {47 5 30 20} 30x20+47+35 {47 5 30 20}} +} -result [list \ + 30x20+[expr {$padx+6*$fixedWidth}]+$pady \ + [list [expr {$padx+6*$fixedWidth}] $pady 30 20] \ + 30x20+[expr {$padx+6*$fixedWidth}]+[expr {$pady+30}] \ + [list [expr {$padx+6*$fixedWidth}] $pady 30 20]] + test textWind-16.3 {EmbWinTextStructureProc procedure} -setup { .t delete 1.0 end } -body { @@ -1276,6 +1370,7 @@ test textWind-16.3 {EmbWinTextStructureProc procedure} -setup { } -cleanup { pack .t } -result {} + test textWind-16.4 {EmbWinTextStructureProc procedure} -setup { .t delete 1.0 end } -body { @@ -1290,7 +1385,7 @@ test textWind-16.4 {EmbWinTextStructureProc procedure} -setup { list [winfo ismapped .t.f] [.t bbox .t.f] } -cleanup { pack .t -} -result {1 {47 5 30 20}} +} -result [list 1 [list [expr {$padx+6*$fixedWidth}] $pady 30 20]] test textWind-17.1 {peer widgets and embedded windows} -setup { diff --git a/tests/winClipboard.test b/tests/winClipboard.test index 2a7ad73..2f72966 100644 --- a/tests/winClipboard.test +++ b/tests/winClipboard.test @@ -15,8 +15,10 @@ eval tcltest::configure $argv tcltest::loadTestedCommands namespace import -force tcltest::test -# Note that these tests may fail if another application is grabbing the -# clipboard (e.g. an X server) +################################################################# +# Note that some of these tests may fail if another application # +# is grabbing the clipboard (e.g. an X server, or a VNC viewer) # +################################################################# test winClipboard-1.1 {TkSelGetSelection} -constraints win -setup { clipboard clear diff --git a/unix/configure b/unix/configure index 1259c92..56e9df4 100755 --- a/unix/configure +++ b/unix/configure @@ -1338,7 +1338,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu TK_VERSION=8.6 TK_MAJOR_VERSION=8 TK_MINOR_VERSION=6 -TK_PATCH_LEVEL=".8" +TK_PATCH_LEVEL=".9" VERSION=${TK_VERSION} LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv" @@ -5417,7 +5417,7 @@ fi fi ;; - FreeBSD-*) + DragonFly-*|FreeBSD-*) # This configuration from FreeBSD Ports. SHLIB_CFLAGS="-fPIC" SHLIB_LD="${CC} -shared" @@ -6625,7 +6625,7 @@ fi BSD/OS*) ;; CYGWIN_*|MINGW32_*) ;; IRIX*) ;; - NetBSD-*|FreeBSD-*|OpenBSD-*) ;; + NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; *) SHLIB_CFLAGS="-fPIC" ;; @@ -7465,70 +7465,6 @@ _ACEOF fi - echo "$as_me:$LINENO: checking for DIR64" >&5 -echo $ECHO_N "checking for DIR64... $ECHO_C" >&6 -if test "${tcl_cv_DIR64+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <sys/types.h> -#include <dirent.h> -int -main () -{ -struct dirent64 *p; DIR64 d = opendir64("."); - p = readdir64(d); rewinddir64(d); closedir64(d); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - tcl_cv_DIR64=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -tcl_cv_DIR64=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $tcl_cv_DIR64" >&5 -echo "${ECHO_T}$tcl_cv_DIR64" >&6 - if test "x${tcl_cv_DIR64}" = "xyes" ; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_DIR64 1 -_ACEOF - - fi - echo "$as_me:$LINENO: checking for struct stat64" >&5 echo $ECHO_N "checking for struct stat64... $ECHO_C" >&6 if test "${tcl_cv_struct_stat64+set}" = set; then @@ -8351,191 +8287,6 @@ fi #-------------------------------------------------------------------- -# Under Solaris 2.4, strtod returns the wrong value for the -# terminating character under some conditions. Check for this -# and if the problem exists use a substitute procedure -# "fixstrtod" (provided by Tcl) that corrects the error. -#-------------------------------------------------------------------- - - - echo "$as_me:$LINENO: checking for strtod" >&5 -echo $ECHO_N "checking for strtod... $ECHO_C" >&6 -if test "${ac_cv_func_strtod+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define strtod to an innocuous variant, in case <limits.h> declares strtod. - For example, HP-UX 11i <limits.h> declares gettimeofday. */ -#define strtod innocuous_strtod - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char strtod (); below. - Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - <limits.h> exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - -#undef strtod - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char strtod (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_strtod) || defined (__stub___strtod) -choke me -#else -char (*f) () = strtod; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != strtod; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_strtod=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_strtod=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_strtod" >&5 -echo "${ECHO_T}$ac_cv_func_strtod" >&6 -if test $ac_cv_func_strtod = yes; then - tcl_strtod=1 -else - tcl_strtod=0 -fi - - if test "$tcl_strtod" = 1; then - echo "$as_me:$LINENO: checking for Solaris2.4/Tru64 strtod bugs" >&5 -echo $ECHO_N "checking for Solaris2.4/Tru64 strtod bugs... $ECHO_C" >&6 -if test "${tcl_cv_strtod_buggy+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - - if test "$cross_compiling" = yes; then - tcl_cv_strtod_buggy=buggy -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - - extern double strtod(); - int main() { - char *infString="Inf", *nanString="NaN", *spaceString=" "; - char *term; - double value; - value = strtod(infString, &term); - if ((term != infString) && (term[-1] == 0)) { - exit(1); - } - value = strtod(nanString, &term); - if ((term != nanString) && (term[-1] == 0)) { - exit(1); - } - value = strtod(spaceString, &term); - if (term == (spaceString+1)) { - exit(1); - } - exit(0); - } -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - tcl_cv_strtod_buggy=ok -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -tcl_cv_strtod_buggy=buggy -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -echo "$as_me:$LINENO: result: $tcl_cv_strtod_buggy" >&5 -echo "${ECHO_T}$tcl_cv_strtod_buggy" >&6 - if test "$tcl_cv_strtod_buggy" = buggy; then - case $LIBOBJS in - "fixstrtod.$ac_objext" | \ - *" fixstrtod.$ac_objext" | \ - "fixstrtod.$ac_objext "* | \ - *" fixstrtod.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS fixstrtod.$ac_objext" ;; -esac - - USE_COMPAT=1 - -cat >>confdefs.h <<\_ACEOF -#define strtod fixstrtod -_ACEOF - - fi - fi - - -#-------------------------------------------------------------------- # Check for various typedefs and provide substitutes if # they don't exist. #-------------------------------------------------------------------- @@ -9710,7 +9461,7 @@ ac_x_header_dirs=' /usr/openwin/share/include' if test "$ac_x_includes" = no; then - # Guess where to find include files, by looking for Xlib.h. + # Guess where to find include files, by looking for Intrinsic.h. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -9718,7 +9469,7 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <X11/Xlib.h> +#include <X11/Intrinsic.h> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 @@ -9745,7 +9496,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do - if test -r "$ac_dir/X11/Xlib.h"; then + if test -r "$ac_dir/X11/Intrinsic.h"; then ac_x_includes=$ac_dir break fi @@ -9759,18 +9510,18 @@ if test "$ac_x_libraries" = no; then # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS - LIBS="-lX11 $LIBS" + LIBS="-lXt $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <X11/Xlib.h> +#include <X11/Intrinsic.h> int main () { -XrmInitialize () +XtMalloc (0) ; return 0; } diff --git a/unix/configure.in b/unix/configure.in index a2ed566..0d7b0b2 100644 --- a/unix/configure.in +++ b/unix/configure.in @@ -25,7 +25,7 @@ m4_ifdef([SC_USE_CONFIG_HEADERS], [ TK_VERSION=8.6 TK_MAJOR_VERSION=8 TK_MINOR_VERSION=6 -TK_PATCH_LEVEL=".8" +TK_PATCH_LEVEL=".9" VERSION=${TK_VERSION} LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv" @@ -197,15 +197,6 @@ AC_CHECK_HEADERS(sys/time.h) AC_HEADER_TIME #-------------------------------------------------------------------- -# Under Solaris 2.4, strtod returns the wrong value for the -# terminating character under some conditions. Check for this -# and if the problem exists use a substitute procedure -# "fixstrtod" (provided by Tcl) that corrects the error. -#-------------------------------------------------------------------- - -SC_BUGGY_STRTOD - -#-------------------------------------------------------------------- # Check for various typedefs and provide substitutes if # they don't exist. #-------------------------------------------------------------------- diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 0ee12f9..1953798 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -1516,7 +1516,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ LDFLAGS="$LDFLAGS -pthread" ]) ;; - FreeBSD-*) + DragonFly-*|FreeBSD-*) # This configuration from FreeBSD Ports. SHLIB_CFLAGS="-fPIC" SHLIB_LD="${CC} -shared" @@ -2012,7 +2012,7 @@ dnl # preprocessing tests use only CPPFLAGS. BSD/OS*) ;; CYGWIN_*|MINGW32_*) ;; IRIX*) ;; - NetBSD-*|FreeBSD-*|OpenBSD-*) ;; + NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; *) SHLIB_CFLAGS="-fPIC" ;; @@ -2398,59 +2398,6 @@ AC_DEFUN([SC_TIME_HANDLER], [ ]) #-------------------------------------------------------------------- -# SC_BUGGY_STRTOD -# -# Under Solaris 2.4, strtod returns the wrong value for the -# terminating character under some conditions. Check for this -# and if the problem exists use a substitute procedure -# "fixstrtod" (provided by Tcl) that corrects the error. -# Also, on Compaq's Tru64 Unix 5.0, -# strtod(" ") returns 0.0 instead of a failure to convert. -# -# Arguments: -# none -# -# Results: -# -# Might defines some of the following vars: -# strtod (=fixstrtod) -# -#-------------------------------------------------------------------- - -AC_DEFUN([SC_BUGGY_STRTOD], [ - AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0) - if test "$tcl_strtod" = 1; then - AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[ - AC_TRY_RUN([ - extern double strtod(); - int main() { - char *infString="Inf", *nanString="NaN", *spaceString=" "; - char *term; - double value; - value = strtod(infString, &term); - if ((term != infString) && (term[-1] == 0)) { - exit(1); - } - value = strtod(nanString, &term); - if ((term != nanString) && (term[-1] == 0)) { - exit(1); - } - value = strtod(spaceString, &term); - if (term == (spaceString+1)) { - exit(1); - } - exit(0); - }], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy, - tcl_cv_strtod_buggy=buggy)]) - if test "$tcl_cv_strtod_buggy" = buggy; then - AC_LIBOBJ([fixstrtod]) - USE_COMPAT=1 - AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?]) - fi - fi -]) - -#-------------------------------------------------------------------- # SC_TCL_LINK_LIBS # # Search for the libraries needed to link the Tcl shell. diff --git a/unix/tk.spec b/unix/tk.spec index 24019d4..159c533 100644 --- a/unix/tk.spec +++ b/unix/tk.spec @@ -4,7 +4,7 @@ Name: tk Summary: Tk graphical toolkit for the Tcl scripting language. -Version: 8.6.8 +Version: 8.6.9 Release: 2 License: BSD Group: Development/Languages diff --git a/unix/tkConfig.h.in b/unix/tkConfig.h.in index 4fd7726..72d97c8 100644 --- a/unix/tkConfig.h.in +++ b/unix/tkConfig.h.in @@ -13,6 +13,9 @@ /* Do we have access to Darwin CoreFoundation.framework? */ #undef HAVE_COREFOUNDATION +/* Is 'DIR64' in <sys/types.h>? */ +#undef HAVE_DIR64 + /* Compiler support for module scope symbols */ #undef HAVE_HIDDEN @@ -238,9 +241,6 @@ /* Define to `unsigned' if <sys/types.h> does not define. */ #undef size_t -/* Do we want to use the strtod() in compat? */ -#undef strtod - /* Define to `int' if <sys/types.h> doesn't define. */ #undef uid_t diff --git a/unix/tkUnixMenu.c b/unix/tkUnixMenu.c index bc1bd2e..38b6c58 100644 --- a/unix/tkUnixMenu.c +++ b/unix/tkUnixMenu.c @@ -52,8 +52,8 @@ static void SetHelpMenu(TkMenu *menuPtr); static void DrawMenuEntryAccelerator(TkMenu *menuPtr, TkMenuEntry *mePtr, Drawable d, GC gc, Tk_Font tkfont, const Tk_FontMetrics *fmPtr, - Tk_3DBorder activeBorder, int x, int y, - int width, int height, int drawArrow); + Tk_3DBorder activeBorder, Tk_3DBorder bgBorder, + int x, int y, int width, int height, int drawArrow); static void DrawMenuEntryBackground(TkMenu *menuPtr, TkMenuEntry *mePtr, Drawable d, Tk_3DBorder activeBorder, Tk_3DBorder bgBorder, @@ -481,6 +481,7 @@ DrawMenuEntryAccelerator( Tk_Font tkfont, /* The precalculated font */ const Tk_FontMetrics *fmPtr,/* The precalculated metrics */ Tk_3DBorder activeBorder, /* The border for an active item */ + Tk_3DBorder bgBorder, /* The background border */ int x, /* Left coordinate of entry rect */ int y, /* Top coordinate of entry rect */ int width, /* Width of entry */ @@ -510,8 +511,9 @@ DrawMenuEntryAccelerator( points[1].y = points[0].y + CASCADE_ARROW_HEIGHT; points[2].x = points[0].x + CASCADE_ARROW_WIDTH; points[2].y = points[0].y + CASCADE_ARROW_HEIGHT/2; - Tk_Fill3DPolygon(menuPtr->tkwin, d, activeBorder, points, 3, - DECORATION_BORDER_WIDTH, + Tk_Fill3DPolygon(menuPtr->tkwin, d, + (mePtr->state == ENTRY_ACTIVE) ? activeBorder : bgBorder, + points, 3, DECORATION_BORDER_WIDTH, (menuPtr->postedCascade == mePtr) ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED); } else if (mePtr->accelPtr != NULL) { @@ -638,7 +640,7 @@ DrawMenuSeparator( points[0].x = x; points[0].y = y + height/2; - points[1].x = width - 1; + points[1].x = x + width - 1; points[1].y = points[0].y; border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1, @@ -1193,7 +1195,7 @@ DrawTearoffEntry( points[0].y = y + height/2; points[1].y = points[0].y; segmentWidth = 6; - maxX = width - 1; + maxX = x + width - 1; border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); while (points[0].x < maxX) { @@ -1326,8 +1328,7 @@ TkpDrawMenuEntry( int height, /* Height of the current rectangle */ int strictMotif, /* Boolean flag */ int drawArrow) /* Whether or not to draw the cascade arrow - * for cascade items. Only applies to - * Windows. */ + * for cascade items. */ { GC gc, indicatorGC; XColor *indicatorColor, *disableColor = NULL; @@ -1435,7 +1436,8 @@ TkpDrawMenuEntry( DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, - activeBorder, x, adjustedY, width, adjustedHeight, drawArrow); + activeBorder, bgBorder, x, adjustedY, width, adjustedHeight, + drawArrow); if (!mePtr->hideMargin) { if (mePtr->state == ENTRY_ACTIVE) { bgBorder = activeBorder; @@ -1718,7 +1720,7 @@ TkpComputeStandardMenuGeometry( menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN; } windowWidth = x + indicatorSpace + labelWidth + accelWidth - + 2 * activeBorderWidth + 2 * borderWidth; + + 2 * activeBorderWidth + borderWidth; windowHeight += borderWidth; diff --git a/unix/tkUnixRFont.c b/unix/tkUnixRFont.c index 8e0ce55..70aebfa 100644 --- a/unix/tkUnixRFont.c +++ b/unix/tkUnixRFont.c @@ -711,9 +711,19 @@ Tk_MeasureChars( (flags & TK_AT_LEAST_ONE && curByte == 0)) { curX = newX; curByte = newByte; - } else if (flags & TK_WHOLE_WORDS && termX != 0) { - curX = termX; - curByte = termByte; + } else if (flags & TK_WHOLE_WORDS) { + if ((flags & TK_AT_LEAST_ONE) && (termX == 0)) { + /* + * No space was seen before reaching the right + * of the allotted maxLength space, i.e. no word + * boundary. Return the string that fills the + * allotted space, without overfill. + * curX and curByte are already the right ones: + */ + } else { + curX = termX; + curByte = termByte; + } } break; } diff --git a/unix/tkUnixScrlbr.c b/unix/tkUnixScrlbr.c index 0507211..2446c3f 100644 --- a/unix/tkUnixScrlbr.c +++ b/unix/tkUnixScrlbr.c @@ -289,6 +289,11 @@ TkpComputeScrollbarGeometry( scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth; width = (scrollPtr->vertical) ? Tk_Width(scrollPtr->tkwin) : Tk_Height(scrollPtr->tkwin); + + /* + * Next line assumes that the arrow area is a square. + */ + scrollPtr->arrowLength = width - 2*scrollPtr->inset + 1; fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin) : Tk_Width(scrollPtr->tkwin)) diff --git a/win/configure b/win/configure index 15d509e..203d702 100755 --- a/win/configure +++ b/win/configure @@ -1312,7 +1312,7 @@ SHELL=/bin/sh TK_VERSION=8.6 TK_MAJOR_VERSION=8 TK_MINOR_VERSION=6 -TK_PATCH_LEVEL=".8" +TK_PATCH_LEVEL=".9" VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION #------------------------------------------------------------------------ diff --git a/win/configure.in b/win/configure.in index 5ec7c35..167fd3d 100644 --- a/win/configure.in +++ b/win/configure.in @@ -14,7 +14,7 @@ SHELL=/bin/sh TK_VERSION=8.6 TK_MAJOR_VERSION=8 TK_MINOR_VERSION=6 -TK_PATCH_LEVEL=".8" +TK_PATCH_LEVEL=".9" VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION #------------------------------------------------------------------------ diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c index 03c0cde..877eed4 100644 --- a/win/tkWinClipboard.c +++ b/win/tkWinClipboard.c @@ -55,9 +55,14 @@ TkSelGetSelection( Tcl_Encoding encoding; int result, locale, noBackslash = 0; + if (!OpenClipboard(NULL)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "clipboard cannot be opened, another application grabbed it")); + Tcl_SetErrorCode(interp, "TK", "CLIPBOARD", "BUSY", NULL); + return TCL_ERROR; + } if ((selection != Tk_InternAtom(tkwin, "CLIPBOARD")) - || (target != XA_STRING) - || !OpenClipboard(NULL)) { + || (target != XA_STRING)) { goto error; } diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index 5dc8f8a..a409764 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -1482,6 +1482,15 @@ GetMenuIndicatorGeometry( Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin, menuPtr->borderWidthPtr, &borderWidth); *widthPtr = indicatorDimensions[1] - borderWidth; + + /* + * Quite dubious about the above (why would borderWidth play a role?) + * and about how indicatorDimensions[1] is obtained in SetDefaults(). + * At least don't let the result be negative! + */ + if (*widthPtr < 0) { + *widthPtr = 0; + } } } @@ -1840,7 +1849,7 @@ DrawMenuEntryArrow( int width, /* Width of menu entry */ int height, /* Height of menu entry */ int drawArrow) /* For cascade menus, whether of not to draw - * the arraw. I cannot figure out Windows' + * the arrow. I cannot figure out Windows' * algorithm for where to draw this. */ { COLORREF oldFgColor; @@ -2428,7 +2437,7 @@ DrawTearoffEntry( points[0].y = y + height/2; points[1].y = points[0].y; segmentWidth = 6; - maxX = width - 1; + maxX = x + width - 1; border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); while (points[0].x < maxX) { @@ -2500,7 +2509,7 @@ TkpDrawMenuEntry( int strictMotif, /* Boolean flag */ int drawingParameters) /* Whether or not to draw the cascade arrow * for cascade items and accelerator - * cues. Only applies to Windows. */ + * cues. */ { GC gc, indicatorGC; TkMenu *menuPtr = mePtr->menuPtr; @@ -2874,7 +2883,7 @@ TkpComputeStandardMenuGeometry( menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN; } x += indicatorSpace + labelWidth + accelWidth - + 2 * borderWidth; + + 2 * activeBorderWidth; indicatorSpace = labelWidth = accelWidth = 0; lastColumnBreak = i; y = borderWidth; @@ -2944,8 +2953,8 @@ TkpComputeStandardMenuGeometry( menuPtr->entries[j]->x = x; menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN; } - windowWidth = x + indicatorSpace + labelWidth + accelWidth + accelSpace - + 2 * activeBorderWidth + 2 * borderWidth; + windowWidth = x + indicatorSpace + labelWidth + accelWidth + + 2 * activeBorderWidth + borderWidth; windowHeight += borderWidth; @@ -3281,6 +3290,7 @@ SetDefaults( * * The code below was given to me by Microsoft over the phone. It is the * only way to ensure menu items line up, and is not documented. + * How strange the calculation of indicatorDimensions[1] is...! */ indicatorDimensions[0] = GetSystemMetrics(SM_CYMENUCHECK); diff --git a/xlib/X11/Xlib.h b/xlib/X11/Xlib.h index b027e28..8d8ec68 100644 --- a/xlib/X11/Xlib.h +++ b/xlib/X11/Xlib.h @@ -203,9 +203,6 @@ typedef struct { int class; /* class of screen (monochrome, etc.) */ #endif unsigned long red_mask, green_mask, blue_mask; /* mask values */ -#if defined(MAC_OSX_TK) - unsigned long alpha_mask; -#endif int bits_per_rgb; /* log base 2 of distinct color values */ int map_entries; /* color map entries */ } Visual; @@ -335,7 +332,6 @@ typedef struct _XImage { XPointer obdata; /* hook for the object routines to hang on */ #if defined(MAC_OSX_TK) int pixelpower; /* n such that pixels are 2^n x 2^n blocks*/ - unsigned long alpha_mask; #endif struct funcs { /* image manipulation routines */ struct _XImage *(*create_image)(); |