Skip to content

Commit

Permalink
Backport to 8.7
Browse files Browse the repository at this point in the history
  • Loading branch information
jan.nijtmans committed Nov 4, 2024
1 parent e61b418 commit 2e183c2
Show file tree
Hide file tree
Showing 55 changed files with 1,411 additions and 1,141 deletions.
17 changes: 0 additions & 17 deletions generic/tkCanvas.c
Original file line number Diff line number Diff line change
Expand Up @@ -3081,10 +3081,6 @@ DisplayCanvas(
Tk_Item *itemPtr;
Pixmap pixmap;
int screenX1, screenX2, screenY1, screenY2, width, height;
#ifdef MAC_OSX_TK
TkWindow *winPtr;
MacDrawable *macWin;
#endif

if (canvasPtr->tkwin == NULL) {
return;
Expand All @@ -3094,19 +3090,6 @@ DisplayCanvas(
goto done;
}

#ifdef MAC_OSX_TK
/*
* If drawing is disabled, all we need to do is
* clear the REDRAW_PENDING flag.
*/
winPtr = (TkWindow *)(canvasPtr->tkwin);
macWin = winPtr->privatePtr;
if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){
canvasPtr->flags &= ~REDRAW_PENDING;
return;
}
#endif

/*
* Choose a new current item if that is needed (this could cause event
* handlers to be invoked).
Expand Down
11 changes: 0 additions & 11 deletions generic/tkFont.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,17 +887,6 @@ TheWorldHasChanged(
{
TkFontInfo *fiPtr = (TkFontInfo *)clientData;

/*
* On macOS it is catastrophic to recompute all widgets while the
* [NSView drawRect] method is drawing. The best that we can do in
* that situation is to abort the recomputation and hope for the best.
* This is ignored on other platforms.
*/

if (TkpWillDrawWidget(NULL)) {
return;
}

fiPtr->updatePending = 0;
RecomputeWidgets(fiPtr->mainPtr->winPtr);
}
Expand Down
6 changes: 3 additions & 3 deletions generic/tkImage.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ Tk_ImageObjCmd(
}
if (typePtr == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"image type \"%s\" doesn't exist", arg));
"image type \"%s\" does not exist", arg));
Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE_TYPE", arg, (char *)NULL);
return TCL_ERROR;
}
Expand Down Expand Up @@ -510,7 +510,7 @@ Tk_ImageObjCmd(
return TCL_OK;

alreadyDeleted:
Tcl_SetObjResult(interp, Tcl_ObjPrintf("image \"%s\" doesn't exist",arg));
Tcl_SetObjResult(interp, Tcl_ObjPrintf("image \"%s\" does not exist",arg));
Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE", arg, (char *)NULL);
return TCL_ERROR;
}
Expand Down Expand Up @@ -656,7 +656,7 @@ Tk_GetImage(
noSuchImage:
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"image \"%s\" doesn't exist", name));
"image \"%s\" does not exist", name));
Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE", name, (char *)NULL);
}
return NULL;
Expand Down
3 changes: 3 additions & 0 deletions generic/tkStubInit.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ MODULE_SCOPE const TkStubs tkStubs;
#define TkMacOSXSetUpClippingRgn (void (*)(Drawable))(void *)doNothing
#undef TkMacOSXIsCharacterMissing
#define TkMacOSXIsCharacterMissing (int (*)(Tk_Font, unsigned int))(void *)doNothing
#undef TkMacOSXSetDrawingEnabled
#define TkMacOSXSetDrawingEnabled (void (*)(TkWindow *, int))(void *)doNothing


#if defined(_WIN32) && !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
# define Tk_TranslateWinEvent TkTranslateWinEvent
Expand Down
43 changes: 9 additions & 34 deletions generic/tkTextDisp.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
#include "tkMacOSXInt.h"
#endif

#define OK_TO_LOG (!TkpWillDrawWidget(textPtr->tkwin))

/*
* "Calculations of line pixel heights and the size of the vertical
* scrollbar."
Expand Down Expand Up @@ -205,20 +203,13 @@ typedef struct TextStyle {

/*
* 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) \
if (OK_TO_LOG) \
Tcl_SetVar2(textPtr->interp, toVar, NULL, (what), \
TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT)
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)
Tcl_SetVar2(interp, var, NULL, "", TCL_GLOBAL_ONLY)

/*
* The following structure describes one line of the display, which may be
Expand Down Expand Up @@ -4192,22 +4183,6 @@ DisplayText(
return;
}

#ifdef MAC_OSX_TK
/*
* If the toplevel is being resized it would be dangerous to try redrawing
* the widget. But we can just clear the REDRAW_PENDING flag and return.
* This display proc will be called again after the widget has been
* reconfigured.
*/

TkWindow *winPtr = (TkWindow *)(textPtr->tkwin);
MacDrawable *macWin = winPtr->privatePtr;
if (macWin && (macWin->flags & TK_DO_NOT_DRAW)) {
dInfoPtr->flags &= ~REDRAW_PENDING;
return;
}
#endif

interp = textPtr->interp;
Tcl_Preserve(interp);

Expand Down Expand Up @@ -4411,8 +4386,8 @@ DisplayText(
Tk_Draw3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
textPtr->border, textPtr->highlightWidth,
textPtr->highlightWidth,
Tk_Width(textPtr->tkwin) - 2*textPtr->highlightWidth,
Tk_Height(textPtr->tkwin) - 2*textPtr->highlightWidth,
Tk_Width(textPtr->tkwin) - 2 * textPtr->highlightWidth,
Tk_Height(textPtr->tkwin) - 2 * textPtr->highlightWidth,
textPtr->borderWidth, textPtr->relief);
if (textPtr->highlightWidth > 0) {
GC fgGC, bgGC;
Expand All @@ -4433,25 +4408,25 @@ DisplayText(
if (textPtr->padY > 0) {
Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
textPtr->border, borders, borders,
Tk_Width(textPtr->tkwin) - 2*borders, textPtr->padY,
Tk_Width(textPtr->tkwin) - 2 * borders, textPtr->padY,
0, TK_RELIEF_FLAT);
Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
textPtr->border, borders,
Tk_Height(textPtr->tkwin) - borders - textPtr->padY,
Tk_Width(textPtr->tkwin) - 2*borders,
Tk_Width(textPtr->tkwin) - 2 * borders,
textPtr->padY, 0, TK_RELIEF_FLAT);
}
if (textPtr->padX > 0) {
Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
textPtr->border, borders, borders + textPtr->padY,
textPtr->padX,
Tk_Height(textPtr->tkwin) - 2*borders -2*textPtr->padY,
Tk_Height(textPtr->tkwin) - 2 * borders -2 * textPtr->padY,
0, TK_RELIEF_FLAT);
Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin),
textPtr->border,
Tk_Width(textPtr->tkwin) - borders - textPtr->padX,
borders + textPtr->padY, textPtr->padX,
Tk_Height(textPtr->tkwin) - 2*borders -2*textPtr->padY,
Tk_Height(textPtr->tkwin) - 2 * borders -2 * textPtr->padY,
0, TK_RELIEF_FLAT);
}
dInfoPtr->flags &= ~REDRAW_BORDERS;
Expand Down
53 changes: 51 additions & 2 deletions generic/tkWindow.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,17 @@ static int Initialize(Tcl_Interp *interp);
static int NameWindow(Tcl_Interp *interp, TkWindow *winPtr,
TkWindow *parentPtr, const char *name);
static void UnlinkWindow(TkWindow *winPtr);

/*
* This static variable only makes sense for macOS and Windows, which never
* have more than one display. It is set by TkCloseDisplay, and when set
* prevents sending Enter and Leave events when all of the windows in the
* display are being destroyed. Tk does not send those events on X11; that
* job is handled by the X server.
*/

static int displayBeingClosed = 0;


/*
*----------------------------------------------------------------------
Expand All @@ -239,6 +250,7 @@ static void
TkCloseDisplay(
TkDisplay *dispPtr)
{
displayBeingClosed = 1;
TkClipCleanup(dispPtr);

if (dispPtr->name != NULL) {
Expand Down Expand Up @@ -1334,6 +1346,39 @@ Tk_CreateWindowFromPath(
*--------------------------------------------------------------
*/

#if defined(MAC_OSX_TK) || defined(_WIN32)
static void SendEnterLeaveForDestroy(
Tk_Window tkwin)
{
int x, y;
unsigned int state;
Tk_Window pointerWin;
TkWindow *containerPtr;

if (displayBeingClosed) {
return;
}
XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y,
NULL, NULL, &state);
pointerWin = Tk_CoordsToWindow(x, y, tkwin);
if (pointerWin == tkwin) {
if (!Tk_IsTopLevel(tkwin)) {
containerPtr = TkGetContainer((TkWindow *)pointerWin);
Tk_UpdatePointer((Tk_Window) containerPtr, x, y, state);
}
}

if (pointerWin && (tkwin == Tk_Parent(pointerWin))) {
Tk_UpdatePointer(Tk_Parent(tkwin), x, y, state);
}
}
#else
static void SendEnterLeaveForDestroy(
TCL_UNUSED(Tk_Window))
{
}
#endif

void
Tk_DestroyWindow(
Tk_Window tkwin) /* Window to destroy. */
Expand All @@ -1353,6 +1398,10 @@ Tk_DestroyWindow(

return;
}
if ((winPtr->flags & TK_DONT_DESTROY_WINDOW) == 0) {
SendEnterLeaveForDestroy(tkwin);
}

winPtr->flags |= TK_ALREADY_DEAD;

/*
Expand Down Expand Up @@ -1523,7 +1572,7 @@ Tk_DestroyWindow(
* Cleanup the data structures associated with this window.
*/

if (winPtr->flags & TK_WIN_MANAGED) {
if (winPtr->wmInfoPtr && (winPtr->flags & TK_WIN_MANAGED)) {
TkWmDeadWindow(winPtr);
} else if (winPtr->flags & TK_WM_COLORMAP_WINDOW) {
TkWmRemoveFromColormapWindows(winPtr);
Expand Down Expand Up @@ -2612,7 +2661,7 @@ Tk_RestackWindow(
TkWindow *otherPtr = (TkWindow *) other;

/*
* Special case: if winPtr is a top-level window then just find the
* Special case: if winPtr is a toplevel window then just find the
* top-level ancestor of otherPtr and restack winPtr above otherPtr
* without changing any of Tk's childLists.
*/
Expand Down
12 changes: 6 additions & 6 deletions library/demos/mac_styles.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,16 @@ if { [wm attributes $w -isdark] } {
}
proc beLight {f w} {
wm attributes $w -appearance aqua
$f.dark state !selected
$f.light state selected
after 10 $f.light state !hover
# A small delay is needed for the appearance change to complete.
after 10 [list $f.dark state !selected]
after 10 [list $f.light state selected]
}

proc beDark {f w} {
wm attributes $w -appearance darkaqua
$f.light state !selected
$f.dark state selected
after 10 $f.dark state !hover
# A small delay is needed for the appearance change to complete.
after 10 [list $f.light state !selected]
after 10 [list $f.dark state selected]
}
$w.notebook add $appearanceFrame -text "Appearance"

Expand Down
27 changes: 16 additions & 11 deletions library/palette.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ proc ::tk_setPalette {args} {
# which contains color information. Each element
# is named after a widget configuration option, and
# each value is the value for that option.
# Return Value:
# A list of commands which can be run to update
# the defaults database when exec'ed.

proc ::tk::RecolorTree {w colors} {
upvar $colors c
Expand All @@ -200,11 +203,14 @@ proc ::tk::RecolorTree {w colors} {
foreach dbOption [array names c] {
set option -[string tolower $dbOption]
set class [string replace $dbOption 0 0 [string toupper \
[string index $dbOption 0]]]
[string index $dbOption 0]]]
# Make sure this option is valid for this window.
if {![catch {$w configure $option} value]} {
# if the option database has a preference for this
# dbOption, then use it, otherwise use the defaults
# for the widget.
# Update the option for this window.
$w configure $option $c($dbOption)
# Retrieve a default value for this option. First check
# the option database. If it is not in the database use
# the value for the temporary prototype widget.
set defaultcolor [option get $w $dbOption $class]
if {$defaultcolor eq "" || \
([info exists prototype] && \
Expand All @@ -214,16 +220,15 @@ proc ::tk::RecolorTree {w colors} {
if {$defaultcolor ne ""} {
set defaultcolor [winfo rgb . $defaultcolor]
}
set chosencolor [lindex $value 4]
if {$chosencolor ne ""} {
set chosencolor [winfo rgb . $chosencolor]
# If the color requested for this option differs from
# the default, append a command to update the default.
set requestcolor [lindex $value 4]
if {$requestcolor ne ""} {
set requestcolor [winfo rgb . $requestcolor]
}
if {[string match $defaultcolor $chosencolor]} {
# Change the option database so that future windows will get
# the same colors.
if {![string match $defaultcolor $requestcolor]} {
append result ";\noption add [list \
*[winfo class $w].$dbOption $c($dbOption) 60]"
$w configure $option $c($dbOption)
}
}
}
Expand Down
26 changes: 12 additions & 14 deletions macosx/README
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
cause us to force closing stdin & stdout. Otherwise, given how Xcode launches
Wish remotely, they will be left open and then Wish & gdb will fight for stdin.

- The Aqua port also supports the environment variable TK_NO_STDERR which, if set
to a non-empty value, causes stderr to be redirected to /dev/null. This is
convenient because Apple sometimes releases a new OS without removing all of
their commands which log debugging information. Log messages are written to
stderr, and hence printed in the terminal, when wish or tclsh is started from
the terminal, or when running the tests. The messages are not only annoying,
they can also cause tests to fail if a debugging message is written to stderr
while a test is running tktest as a subprocess with exec or open.

3. FullScreen, Split View and Tabbed Windows
--------------------------------------------

Expand Down Expand Up @@ -470,9 +479,9 @@ https://developer.apple.com/library/mac/documentation/Cocoa/\
Reference/ApplicationKit/Classes/NSApplication_Class)

void NSApplicationMain(int argc, char *argv[]) {
[NSApplication sharedApplication];
[NSBundle loadNibNamed:@"myMain" owner:NSApp];
[NSApp run];
[NSApplication sharedApplication];
[NSBundle loadNibNamed:@"myMain" owner:NSApp];
[NSApp run];
}
Here NSApp is a standard global variable, initialized by the OS, which
points to an object in a subclass of NSApplication (called
Expand Down Expand Up @@ -510,17 +519,6 @@ specific SetupProc and then a platform specific CheckProc. In
the macOS port, these are named TkMacOSXEventsSetupProc and
TkMacOSXEventsCheckProc.

It is important to understand that the Apple window manager does not
have the concept of an expose event. Their replacement for an expose
event is to have the window manager call the [NSView drawRect] method
in any situation where an expose event for that NSView would be
generated in X11. The [NSView drawRect] method is a no-op which is
expected to be overridden by any application. In the case of Tcl, the
replacement [NSView drawRect] method creates a Tcl expose event
for each dirty rectangle of the NSView, and then adds the expose
event to the Tcl queue.


5.2 Autorelease pools
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
Loading

0 comments on commit 2e183c2

Please sign in to comment.