Import Tk 8.6.10

This commit is contained in:
Steve Dower
2020-09-24 22:55:34 +01:00
parent 5ba5cbc9af
commit 42c69189d9
365 changed files with 24323 additions and 12832 deletions

View File

@@ -31,7 +31,7 @@
*/
static int GenerateUpdates(HIShapeRef updateRgn,
CGRect *updateBounds, TkWindow *winPtr);
CGRect *updateBounds, TkWindow *winPtr);
static int GenerateActivateEvents(TkWindow *winPtr,
int activeFlag);
static void DoWindowActivate(ClientData clientData);
@@ -68,8 +68,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
BOOL movedOnly = [[notification name]
isEqualToString:NSWindowDidMoveNotification];
isEqualToString:NSWindowDidMoveNotification];
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
@@ -79,8 +78,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
int x, y, width = -1, height = -1, flags = 0;
x = bounds.origin.x;
y = tkMacOSXZeroScreenHeight - (bounds.origin.y + bounds.size.height);
if (winPtr->changes.x != x || winPtr->changes.y != y){
y = TkMacOSXZeroScreenHeight() - (bounds.origin.y + bounds.size.height);
if (winPtr->changes.x != x || winPtr->changes.y != y) {
flags |= TK_LOCATION_CHANGED;
} else {
x = y = -1;
@@ -92,15 +91,16 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
flags |= TK_SIZE_CHANGED;
}
if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
/*
* Propagate geometry changes immediately.
*/
flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
}
TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
}
}
- (void) windowExpanded: (NSNotification *) notification
@@ -136,6 +136,46 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
}
}
- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
defaultFrame:(NSRect)newFrame
{
/*
* This method needs to be implemented in order for [NSWindow isZoomed] to
* give the correct answer. But it suffices to always validate every
* request.
*/
return newFrame;
}
- (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
[(TKWindow *)[notification object] tkLayoutChanged];
}
- (void) windowExitedFullScreen: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
[(TKWindow *)[notification object] tkLayoutChanged];
}
- (void) windowCollapsed: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
@@ -158,21 +198,16 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
if (winPtr) {
TkGenWMDestroyEvent((Tk_Window) winPtr);
if (_windowWithMouse == w) {
_windowWithMouse = nil;
[w release];
}
}
/*
* If necessary, TkGenWMDestroyEvent() handles [close]ing the window,
* so can always return NO from -windowShouldClose: for a Tk window.
* If necessary, TkGenWMDestroyEvent() handles [close]ing the window, so
* can always return NO from -windowShouldClose: for a Tk window.
*/
return (winPtr ? NO : YES);
}
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
- (void) windowDragStart: (NSNotification *) notification
@@ -213,7 +248,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
}
}
#endif /* TK_MAC_DEBUG_NOTIFICATIONS */
- (void) _setupWindowNotifications
@@ -222,12 +256,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:);
@@ -251,6 +292,22 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
[NSApp tkCheckPasteboard];
/*
* When the application is activated with Command-Tab it will create a
* zombie window for every Tk window which has been withdrawn. So iterate
* through the list of windows and order out any withdrawn window.
*/
for (NSWindow *win in [NSApp windows]) {
TkWindow *winPtr = TkMacOSXGetTkWindow(win);
if (!winPtr || !winPtr->wmInfoPtr) {
continue;
}
if (winPtr->wmInfoPtr->hints.initial_state == WithdrawnState) {
[win orderOut:nil];
}
}
}
- (void) applicationDeactivate: (NSNotification *) notification
@@ -260,6 +317,20 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
#endif
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender
hasVisibleWindows:(BOOL)flag
{
/*
* Allowing the default response means that withdrawn windows will get
* displayed on the screen with unresponsive title buttons. We don't
* really want that. Besides, we can write our own code to handle this
* with ::tk::mac::ReopenApplication. So we just say NO.
*/
return NO;
}
- (void) applicationShowHide: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
@@ -299,11 +370,11 @@ 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.
* 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;
@@ -313,11 +384,11 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE Bool
TkpAppIsDrawing(void) {
return [NSApp isDrawing];
}
/*
*----------------------------------------------------------------------
@@ -443,7 +514,9 @@ GenerateActivateEvents(
int activeFlag)
{
TkGenerateActivateEvents(winPtr, activeFlag);
TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
if (activeFlag || ![NSApp isActive]) {
TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
}
return true;
}
@@ -600,17 +673,14 @@ TkGenWMConfigureEvent(
if (flags & TK_LOCATION_CHANGED) {
wmPtr->x = x;
wmPtr->y = y;
wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
}
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;
@@ -622,12 +692,10 @@ 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;
@@ -800,7 +868,10 @@ Tk_MacOSXIsAppInFront(void)
*
*/
/*Restrict event processing to Expose events.*/
/*
* Restrict event processing to Expose events.
*/
static Tk_RestrictAction
ExposeRestrictProc(
ClientData arg,
@@ -810,7 +881,10 @@ ExposeRestrictProc(
? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}
/*Restrict event processing to ConfigureNotify events.*/
/*
* Restrict event processing to ConfigureNotify events.
*/
static Tk_RestrictAction
ConfigureRestrictProc(
ClientData arg,
@@ -819,6 +893,30 @@ ConfigureRestrictProc(
return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}
/*
* If a window gets mapped inside the drawRect method, this will be run as an
* idle task, after drawRect returns, to clean up the mess.
*/
static void
RedisplayView(
ClientData clientdata)
{
NSView *view = (NSView *) clientdata;
/*
* Make sure that we are not trying to displaying a view that no longer
* exists.
*/
for (NSWindow *w in [NSApp orderedWindows]) {
if ([w contentView] == view) {
[view setNeedsDisplay:YES];
break;
}
}
}
@implementation TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect
@@ -832,17 +930,15 @@ ConfigureRestrictProc(
Tk_PathName(winPtr));
#endif
if ([NSApp simulateDrawing]) {
return;
}
/*
* We do not allow recursive calls to drawRect, but we only log
* them on OSX > 10.13, where they should never happen.
* 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] && [NSApp macMinorVersion] > 13) {
TKLog(@"WARNING: a recursive call to drawRect was aborted.");
if ([NSApp isDrawing]) {
if ([NSApp macMinorVersion] > 13) {
TKLog(@"WARNING: a recursive call to drawRect was aborted.");
}
return;
}
@@ -867,6 +963,11 @@ ConfigureRestrictProc(
CFRelease(drawShape);
[NSApp setIsDrawing: NO];
if ([self needsRedisplay]) {
[self setNeedsRedisplay:NO];
Tcl_DoWhenIdle(RedisplayView, self);
}
#ifdef TK_MAC_DEBUG_DRAWING
fprintf(stderr, "drawRect: done.\n");
#endif
@@ -878,22 +979,22 @@ ConfigureRestrictProc(
NSWindow *w = [self window];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
if (![self inLiveResize] &&
[w respondsToSelector: @selector (tkLayoutChanged)]) {
[(TKWindow *)w tkLayoutChanged];
}
if (winPtr) {
/* On OSX versions below 10.14 setFrame calls drawRect.
* On 10.14 it does its own drawing.
*/
if ([NSApp macMinorVersion] > 13) {
[NSApp setIsDrawing:YES];
}
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.
* Since it calls Tcl_DoOneEvent, we need to make sure we
* don't clobber the AutoreleasePool set up by the caller.
* 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];
@@ -909,7 +1010,7 @@ ConfigureRestrictProc(
*/
TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,
TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg);
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
@@ -933,7 +1034,7 @@ ConfigureRestrictProc(
/*
* Finally, unlock the main autoreleasePool.
*/
[NSApp _unlockAutoreleasePool];
}
}
@@ -997,16 +1098,15 @@ ConfigureRestrictProc(
}
/*
* 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.
* 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;
@@ -1027,21 +1127,17 @@ ConfigureRestrictProc(
&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"]) {
if (TkMacOSXInDarkMode(tkwin)) {
event.name = Tk_GetUid("DarkAqua");
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
return;
} else {
event.name = Tk_GetUid("LightAqua");
}
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}
/*
* This is no-op on 10.7 and up because Apple has removed this widget,
* but we are leaving it here for backwards compatibility.
* 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
@@ -1090,6 +1186,11 @@ ConfigureRestrictProc(
return YES;
}
/*
* This keyDown method does nothing, which is a huge improvement over the
* default keyDown method which beeps every time a key is pressed.
*/
- (void) keyDown: (NSEvent *) theEvent
{
#ifdef TK_MAC_DEBUG_EVENTS
@@ -1097,6 +1198,23 @@ ConfigureRestrictProc(
#endif
}
/*
* When the services menu is opened this is called for each Responder in
* the Responder chain until a service provider is found. The TkContentView
* should be the first (and generally only) Responder in the chain. We
* return the TkServices object that was created in TkpInit.
*/
- (id)validRequestorForSendType:(NSString *)sendType
returnType:(NSString *)returnType
{
if ([sendType isEqualToString:@"NSStringPboardType"] ||
[sendType isEqualToString:@"NSPasteboardTypeString"]) {
return [NSApp servicesProvider];
}
return [super validRequestorForSendType:sendType returnType:returnType];
}
@end
/*