Import Tk 8.6.11
This commit is contained in:
@@ -30,17 +30,17 @@
|
||||
* Declaration of functions used only in this file
|
||||
*/
|
||||
|
||||
static int GenerateUpdates(HIShapeRef updateRgn,
|
||||
CGRect *updateBounds, TkWindow *winPtr);
|
||||
static int GenerateUpdates(
|
||||
CGRect *updateBounds, TkWindow *winPtr);
|
||||
static int GenerateActivateEvents(TkWindow *winPtr,
|
||||
int activeFlag);
|
||||
static void DoWindowActivate(ClientData clientData);
|
||||
|
||||
#pragma mark TKApplication(TKWindowEvent)
|
||||
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
extern NSString *NSWindowWillOrderOnScreenNotification;
|
||||
extern NSString *NSWindowDidOrderOnScreenNotification;
|
||||
extern NSString *NSWindowWillOrderOnScreenNotification;
|
||||
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
#endif
|
||||
|
||||
@@ -90,15 +90,12 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
height = bounds.size.height - wmPtr->yInParent;
|
||||
flags |= TK_SIZE_CHANGED;
|
||||
}
|
||||
if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
|
||||
/*
|
||||
* Propagate geometry changes immediately.
|
||||
*/
|
||||
/*
|
||||
* Propagate geometry changes immediately.
|
||||
*/
|
||||
|
||||
flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
|
||||
}
|
||||
|
||||
TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
|
||||
flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
|
||||
TkGenWMConfigureEvent((Tk_Window)winPtr, x, y, width, height, flags);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -114,31 +111,29 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
if (winPtr) {
|
||||
winPtr->wmInfoPtr->hints.initial_state =
|
||||
TkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState;
|
||||
Tk_MapWindow((Tk_Window) winPtr);
|
||||
if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
|
||||
Tk_MapWindow((Tk_Window)winPtr);
|
||||
|
||||
/*
|
||||
* Process all Tk events generated by Tk_MapWindow().
|
||||
*/
|
||||
/*
|
||||
* Process all Tk events generated by Tk_MapWindow().
|
||||
*/
|
||||
|
||||
while (Tcl_ServiceEvent(0)) {}
|
||||
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
|
||||
while (Tcl_ServiceEvent(0)) {}
|
||||
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
|
||||
|
||||
/*
|
||||
* NSWindowDidDeminiaturizeNotification is received after
|
||||
* NSWindowDidBecomeKeyNotification, so activate manually
|
||||
*/
|
||||
/*
|
||||
* NSWindowDidDeminiaturizeNotification is received after
|
||||
* NSWindowDidBecomeKeyNotification, so activate manually
|
||||
*/
|
||||
|
||||
GenerateActivateEvents(winPtr, 1);
|
||||
} else {
|
||||
Tcl_DoWhenIdle(DoWindowActivate, winPtr);
|
||||
}
|
||||
GenerateActivateEvents(winPtr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
|
||||
defaultFrame:(NSRect)newFrame
|
||||
{
|
||||
(void)window;
|
||||
|
||||
/*
|
||||
* This method needs to be implemented in order for [NSWindow isZoomed] to
|
||||
* give the correct answer. But it suffices to always validate every
|
||||
@@ -151,6 +146,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
- (NSSize)window:(NSWindow *)window
|
||||
willUseFullScreenContentSize:(NSSize)proposedSize
|
||||
{
|
||||
(void)window;
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -185,7 +182,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
|
||||
if (winPtr) {
|
||||
Tk_UnmapWindow((Tk_Window) winPtr);
|
||||
Tk_UnmapWindow((Tk_Window)winPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +194,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
|
||||
if (winPtr) {
|
||||
TkGenWMDestroyEvent((Tk_Window) winPtr);
|
||||
TkGenWMDestroyEvent((Tk_Window)winPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -208,6 +205,34 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
return (winPtr ? NO : YES);
|
||||
}
|
||||
|
||||
- (void) windowBecameVisible: (NSNotification *) notification
|
||||
{
|
||||
NSWindow *window = [notification object];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(window);
|
||||
if (winPtr) {
|
||||
TKContentView *view = [window contentView];
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
|
||||
if (@available(macOS 10.15, *)) {
|
||||
[view viewDidChangeEffectiveAppearance];
|
||||
}
|
||||
#endif
|
||||
[view addTkDirtyRect:[view bounds]];
|
||||
Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL);
|
||||
Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) windowMapped: (NSNotification *) notification
|
||||
{
|
||||
NSWindow *w = [notification object];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
|
||||
if (winPtr) {
|
||||
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
|
||||
- (void) windowDragStart: (NSNotification *) notification
|
||||
@@ -221,22 +246,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
//BOOL start = [[notification name] isEqualToString:NSWindowWillStartLiveResizeNotification];
|
||||
}
|
||||
|
||||
- (void) windowMapped: (NSNotification *) notification
|
||||
{
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
NSWindow *w = [notification object];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
|
||||
if (winPtr) {
|
||||
//Tk_MapWindow((Tk_Window) winPtr);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) windowBecameVisible: (NSNotification *) notification
|
||||
{
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
}
|
||||
|
||||
- (void) windowUnmapped: (NSNotification *) notification
|
||||
{
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
@@ -244,7 +253,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
|
||||
if (winPtr) {
|
||||
//Tk_UnmapWindow((Tk_Window) winPtr);
|
||||
//Tk_UnmapWindow((Tk_Window)winPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +272,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
observe(NSWindowDidResizeNotification, windowBoundsChanged:);
|
||||
observe(NSWindowDidDeminiaturizeNotification, windowExpanded:);
|
||||
observe(NSWindowDidMiniaturizeNotification, windowCollapsed:);
|
||||
observe(NSWindowWillOrderOnScreenNotification, windowMapped:);
|
||||
observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:);
|
||||
|
||||
#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
|
||||
observe(NSWindowDidEnterFullScreenNotification, windowEnteredFullScreen:);
|
||||
@@ -273,8 +284,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
observe(NSWindowWillMoveNotification, windowDragStart:);
|
||||
observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:);
|
||||
observe(NSWindowDidEndLiveResizeNotification, windowLiveResize:);
|
||||
observe(NSWindowWillOrderOnScreenNotification, windowMapped:);
|
||||
observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:);
|
||||
observe(NSWindowDidOrderOffScreenNotification, windowUnmapped:);
|
||||
#endif
|
||||
#undef observe
|
||||
@@ -288,6 +297,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
|
||||
- (void) applicationActivate: (NSNotification *) notification
|
||||
{
|
||||
(void)notification;
|
||||
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
#endif
|
||||
@@ -312,14 +323,33 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
|
||||
- (void) applicationDeactivate: (NSNotification *) notification
|
||||
{
|
||||
(void)notification;
|
||||
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* To prevent zombie windows on systems with a TouchBar, set the key window
|
||||
* to nil if the current key window is not visible. This allows a closed
|
||||
* Help or About window to be deallocated so it will not reappear as a
|
||||
* zombie when the app is reactivated.
|
||||
*/
|
||||
|
||||
NSWindow *keywindow = [NSApp keyWindow];
|
||||
if (keywindow && ![keywindow isVisible]) {
|
||||
[NSApp _setKeyWindow:nil];
|
||||
[NSApp _setMainWindow:nil];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender
|
||||
hasVisibleWindows:(BOOL)flag
|
||||
{
|
||||
(void)sender;
|
||||
(void)flag;
|
||||
|
||||
/*
|
||||
* Allowing the default response means that withdrawn windows will get
|
||||
* displayed on the screen with unresponsive title buttons. We don't
|
||||
@@ -352,6 +382,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
|
||||
- (void) displayChanged: (NSNotification *) notification
|
||||
{
|
||||
(void)notification;
|
||||
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
#endif
|
||||
@@ -368,26 +400,53 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkpAppIsDrawing --
|
||||
* TkpWillDrawWidget --
|
||||
*
|
||||
* 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.
|
||||
* being run inside of the drawRect method. If not, it may be desirable
|
||||
* for the display procedure to simply clear the REDRAW_PENDING flag
|
||||
* and return. The widget can be recorded in order to schedule a
|
||||
* redraw, via and Expose event, from within drawRect.
|
||||
*
|
||||
* This is also 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;
|
||||
* True if called from the drawRect method of a TKContentView with
|
||||
* tkwin NULL or pointing to a widget in the current focusView.
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
* Currently none. One day the tkwin parameter may be recorded to
|
||||
* handle redrawing the widget later.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MODULE_SCOPE Bool
|
||||
TkpAppIsDrawing(void) {
|
||||
return [NSApp isDrawing];
|
||||
int
|
||||
TkpWillDrawWidget(Tk_Window tkwin) {
|
||||
int result;
|
||||
if (tkwin) {
|
||||
TkWindow *winPtr = (TkWindow *)tkwin;
|
||||
TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(
|
||||
(Drawable)winPtr->privatePtr);
|
||||
result = ([NSApp isDrawing] && view == [NSView focusView]);
|
||||
#if 0
|
||||
printf("TkpWillDrawWidget: %s %d %d \n", Tk_PathName(tkwin),
|
||||
[NSApp isDrawing], (view == [NSView focusView]));
|
||||
if (!result) {
|
||||
NSRect dirtyRect;
|
||||
TkMacOSXWinNSBounds(winPtr, view, &dirtyRect);
|
||||
printf("TkpAppCanDraw: dirtyRect for %s is %s\n",
|
||||
Tk_PathName(tkwin),
|
||||
NSStringFromRect(dirtyRect).UTF8String);
|
||||
[view addTkDirtyRect:dirtyRect];
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
result = [NSApp isDrawing];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -395,55 +454,39 @@ TkpAppIsDrawing(void) {
|
||||
*
|
||||
* GenerateUpdates --
|
||||
*
|
||||
* Given a Macintosh update region and a Tk window this function geneates
|
||||
* Given an update rectangle and a Tk window, this function generates
|
||||
* an X Expose event for the window if it meets the update region. The
|
||||
* function will then recursivly have each damaged window generate Expose
|
||||
* function will then recursively have each damaged window generate Expose
|
||||
* events for its child windows.
|
||||
*
|
||||
* Results:
|
||||
* True if event(s) are generated - false otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Additional events may be place on the Tk event queue.
|
||||
* Additional events may be placed on the Tk event queue.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
GenerateUpdates(
|
||||
HIShapeRef updateRgn,
|
||||
CGRect *updateBounds,
|
||||
TkWindow *winPtr)
|
||||
{
|
||||
TkWindow *childPtr;
|
||||
XEvent event;
|
||||
CGRect bounds, damageBounds;
|
||||
HIShapeRef boundsRgn, damageRgn;
|
||||
|
||||
TkMacOSXWinCGBounds(winPtr, &bounds);
|
||||
if (!CGRectIntersectsRect(bounds, *updateBounds)) {
|
||||
return 0;
|
||||
}
|
||||
if (!HIShapeIntersectsRect(updateRgn, &bounds)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the bounding box of the area that the damage occured in.
|
||||
* Compute the bounding box of the area that the damage occurred in.
|
||||
*/
|
||||
|
||||
boundsRgn = HIShapeCreateWithRect(&bounds);
|
||||
damageRgn = HIShapeCreateIntersection(updateRgn, boundsRgn);
|
||||
if (HIShapeIsEmpty(damageRgn)) {
|
||||
CFRelease(damageRgn);
|
||||
CFRelease(boundsRgn);
|
||||
return 0;
|
||||
}
|
||||
HIShapeGetBounds(damageRgn, &damageBounds);
|
||||
|
||||
CFRelease(damageRgn);
|
||||
CFRelease(boundsRgn);
|
||||
|
||||
damageBounds = CGRectIntersection(bounds, *updateBounds);
|
||||
event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
|
||||
event.xany.send_event = false;
|
||||
event.xany.window = Tk_WindowId(winPtr);
|
||||
@@ -457,7 +500,7 @@ GenerateUpdates(
|
||||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||||
|
||||
#ifdef TK_MAC_DEBUG_DRAWING
|
||||
TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
|
||||
TKLog(@"Exposed %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
|
||||
event.xexpose.y, event.xexpose.width, event.xexpose.height);
|
||||
#endif
|
||||
|
||||
@@ -470,7 +513,7 @@ GenerateUpdates(
|
||||
if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
|
||||
continue;
|
||||
}
|
||||
GenerateUpdates(updateRgn, updateBounds, childPtr);
|
||||
GenerateUpdates(updateBounds, childPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -480,7 +523,7 @@ GenerateUpdates(
|
||||
if (Tk_IsContainer(winPtr)) {
|
||||
childPtr = TkpGetOtherWindow(winPtr);
|
||||
if (childPtr != NULL && Tk_IsMapped(childPtr)) {
|
||||
GenerateUpdates(updateRgn, updateBounds, childPtr);
|
||||
GenerateUpdates(updateBounds, childPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -491,58 +534,6 @@ GenerateUpdates(
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* GenerateActivateEvents --
|
||||
*
|
||||
* Given a Macintosh window activate event this function generates all the
|
||||
* X Activate events needed by Tk.
|
||||
*
|
||||
* Results:
|
||||
* True if event(s) are generated - false otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Additional events may be place on the Tk event queue.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
GenerateActivateEvents(
|
||||
TkWindow *winPtr,
|
||||
int activeFlag)
|
||||
{
|
||||
TkGenerateActivateEvents(winPtr, activeFlag);
|
||||
if (activeFlag || ![NSApp isActive]) {
|
||||
TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* DoWindowActivate --
|
||||
*
|
||||
* Idle handler that calls GenerateActivateEvents().
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Additional events may be place on the Tk event queue.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
DoWindowActivate(
|
||||
ClientData clientData)
|
||||
{
|
||||
GenerateActivateEvents(clientData, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -555,12 +546,12 @@ DoWindowActivate(
|
||||
* True if event(s) are generated - false otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Additional events may be place on the Tk event queue.
|
||||
* Additional events may be placed on the Tk event queue.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MODULE_SCOPE int
|
||||
static int
|
||||
TkMacOSXGenerateFocusEvent(
|
||||
TkWindow *winPtr, /* Root X window for event. */
|
||||
int activeFlag)
|
||||
@@ -599,6 +590,35 @@ TkMacOSXGenerateFocusEvent(
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* GenerateActivateEvents --
|
||||
*
|
||||
* Given a Macintosh window activate event this function generates all the
|
||||
* X Activate events needed by Tk.
|
||||
*
|
||||
* Results:
|
||||
* True if event(s) are generated - false otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* Additional events may be placed on the Tk event queue.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
GenerateActivateEvents(
|
||||
TkWindow *winPtr,
|
||||
int activeFlag)
|
||||
{
|
||||
TkGenerateActivateEvents(winPtr, activeFlag);
|
||||
if (activeFlag || ![NSApp isActive]) {
|
||||
TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -713,7 +733,7 @@ TkGenWMConfigureEvent(
|
||||
|
||||
/*
|
||||
* Now set up the changes structure. Under X we wait for the
|
||||
* ConfigureNotify to set these values. On the Mac we know imediatly that
|
||||
* ConfigureNotify to set these values. On the Mac we know immediately that
|
||||
* this is what we want - so we just set them. However, we need to make
|
||||
* sure the windows clipping region is marked invalid so the change is
|
||||
* visible to the subwindow.
|
||||
@@ -804,7 +824,7 @@ TkWmProtocolEventProc(
|
||||
if (result != TCL_OK) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (command for \"%s\" window manager protocol)",
|
||||
Tk_GetAtomName((Tk_Window) winPtr, protocol)));
|
||||
Tk_GetAtomName((Tk_Window)winPtr, protocol)));
|
||||
Tcl_BackgroundException(interp, result);
|
||||
}
|
||||
Tcl_Release(interp);
|
||||
@@ -818,8 +838,8 @@ TkWmProtocolEventProc(
|
||||
* message then just destroy the window.
|
||||
*/
|
||||
|
||||
if (protocol == Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW")) {
|
||||
Tk_DestroyWindow((Tk_Window) winPtr);
|
||||
if (protocol == Tk_InternAtom((Tk_Window)winPtr, "WM_DELETE_WINDOW")) {
|
||||
Tk_DestroyWindow((Tk_Window)winPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,47 +907,38 @@ ExposeRestrictProc(
|
||||
|
||||
static Tk_RestrictAction
|
||||
ConfigureRestrictProc(
|
||||
ClientData arg,
|
||||
TCL_UNUSED(void *),
|
||||
XEvent *eventPtr)
|
||||
{
|
||||
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.
|
||||
*/
|
||||
@implementation TKContentView(TKWindowEvent)
|
||||
|
||||
static void
|
||||
RedisplayView(
|
||||
ClientData clientdata)
|
||||
- (void) addTkDirtyRect: (NSRect) rect
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
_tkNeedsDisplay = YES;
|
||||
_tkDirtyRect = NSUnionRect(_tkDirtyRect, rect);
|
||||
[NSApp setNeedsToDraw:YES];
|
||||
}
|
||||
|
||||
@implementation TKContentView(TKWindowEvent)
|
||||
- (void) clearTkDirtyRect
|
||||
{
|
||||
_tkNeedsDisplay = NO;
|
||||
_tkDirtyRect = NSZeroRect;
|
||||
[NSApp setNeedsToDraw:NO];
|
||||
}
|
||||
|
||||
- (void) drawRect: (NSRect) rect
|
||||
{
|
||||
const NSRect *rectsBeingDrawn;
|
||||
NSInteger rectsBeingDrawnCount;
|
||||
(void)rect;
|
||||
|
||||
#ifdef TK_MAC_DEBUG_DRAWING
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
|
||||
if (winPtr) fprintf(stderr, "drawRect: drawing %s\n",
|
||||
Tk_PathName(winPtr));
|
||||
if (winPtr) {
|
||||
fprintf(stderr, "drawRect: drawing %s in %s\n",
|
||||
Tk_PathName(winPtr), NSStringFromRect(rect).UTF8String);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -936,37 +947,16 @@ RedisplayView(
|
||||
*/
|
||||
|
||||
if ([NSApp isDrawing]) {
|
||||
if ([NSApp macMinorVersion] > 13) {
|
||||
if ([NSApp macOSVersion] > 101300) {
|
||||
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);
|
||||
}
|
||||
[self generateExposeEvents:(HIShapeRef)drawShape];
|
||||
CFRelease(drawShape);
|
||||
[NSApp setIsDrawing: NO];
|
||||
|
||||
if ([self needsRedisplay]) {
|
||||
[self setNeedsRedisplay:NO];
|
||||
Tcl_DoWhenIdle(RedisplayView, self);
|
||||
}
|
||||
[self clearTkDirtyRect];
|
||||
[self generateExposeEvents:rect];
|
||||
[NSApp setIsDrawing:NO];
|
||||
|
||||
#ifdef TK_MAC_DEBUG_DRAWING
|
||||
fprintf(stderr, "drawRect: done.\n");
|
||||
@@ -978,7 +968,7 @@ RedisplayView(
|
||||
[super setFrameSize: newsize];
|
||||
NSWindow *w = [self window];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
Tk_Window tkwin = (Tk_Window)winPtr;
|
||||
|
||||
if (![self inLiveResize] &&
|
||||
[w respondsToSelector: @selector (tkLayoutChanged)]) {
|
||||
@@ -1023,13 +1013,14 @@ RedisplayView(
|
||||
TkMacOSXUpdateClipRgn(winPtr);
|
||||
|
||||
/*
|
||||
* Generate and process expose events to redraw the window.
|
||||
* Generate and process expose events to redraw the window. To avoid
|
||||
* crashes, only do this if we are being called from drawRect. See
|
||||
* ticket [1fa8c3ed8d].
|
||||
*/
|
||||
|
||||
HIRect bounds = NSRectToCGRect([self bounds]);
|
||||
HIShapeRef shape = HIShapeCreateWithRect(&bounds);
|
||||
[self generateExposeEvents: shape];
|
||||
[w displayIfNeeded];
|
||||
if([NSApp isDrawing] || [self inLiveResize]) {
|
||||
[self generateExposeEvents: [self bounds]];
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, unlock the main autoreleasePool.
|
||||
@@ -1046,11 +1037,11 @@ RedisplayView(
|
||||
* pending idle events are processed so the drawing will actually take place.
|
||||
*/
|
||||
|
||||
- (void) generateExposeEvents: (HIShapeRef) shape
|
||||
- (void) generateExposeEvents: (NSRect) rect
|
||||
{
|
||||
unsigned long serial;
|
||||
CGRect updateBounds;
|
||||
int updatesNeeded;
|
||||
CGRect updateBounds;
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
|
||||
ClientData oldArg;
|
||||
Tk_RestrictProc *oldProc;
|
||||
@@ -1059,26 +1050,25 @@ RedisplayView(
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate Tk Expose events.
|
||||
* Generate Tk Expose events. All of these events will share the same
|
||||
* serial number.
|
||||
*/
|
||||
|
||||
HIShapeGetBounds(shape, &updateBounds);
|
||||
|
||||
/*
|
||||
* All of these events will share the same serial number.
|
||||
*/
|
||||
|
||||
serial = LastKnownRequestProcessed(Tk_Display(winPtr));
|
||||
updatesNeeded = GenerateUpdates(shape, &updateBounds, winPtr);
|
||||
|
||||
updateBounds = NSRectToCGRect(rect);
|
||||
updateBounds.origin.y = ([self bounds].size.height - updateBounds.origin.y
|
||||
- updateBounds.size.height);
|
||||
updatesNeeded = GenerateUpdates(&updateBounds, winPtr);
|
||||
if (updatesNeeded) {
|
||||
|
||||
serial = LastKnownRequestProcessed(Tk_Display(winPtr));
|
||||
|
||||
/*
|
||||
* First process all of the Expose events.
|
||||
* Use the ExposeRestrictProc to process only the expose events. This
|
||||
* will create idle drawing tasks, which we handle before we return.
|
||||
*/
|
||||
|
||||
oldProc = Tk_RestrictEvents(ExposeRestrictProc, UINT2PTR(serial), &oldArg);
|
||||
while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {};
|
||||
while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {};
|
||||
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
|
||||
|
||||
/*
|
||||
@@ -1090,51 +1080,104 @@ RedisplayView(
|
||||
* 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.
|
||||
* So to run any display procs which were scheduled by the expose
|
||||
* events we process all idle events before returning.
|
||||
*/
|
||||
|
||||
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.
|
||||
* In macOS 10.14 and later this method is called when a user changes between
|
||||
* light and dark mode or changes the accent color. The implementation
|
||||
* generates two virtual events. The first is either <<LightAqua>> or
|
||||
* <<DarkAqua>>, depending on the view's current effective appearance. The
|
||||
* second is <<AppearnceChanged>> and has a data string describing the
|
||||
* effective appearance of the view and the current accent and highlight
|
||||
* colors.
|
||||
*/
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
|
||||
|
||||
static const char *const accentNames[] = {
|
||||
"Graphite",
|
||||
"Red",
|
||||
"Orange",
|
||||
"Yellow",
|
||||
"Green",
|
||||
"Blue",
|
||||
"Purple",
|
||||
"Pink"
|
||||
};
|
||||
|
||||
- (void) viewDidChangeEffectiveAppearance
|
||||
{
|
||||
XVirtualEvent event;
|
||||
int x, y;
|
||||
NSWindow *w = [self window];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
|
||||
if (!winPtr) {
|
||||
Tk_Window tkwin = (Tk_Window)TkMacOSXGetTkWindow([self window]);
|
||||
if (!tkwin) {
|
||||
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 (TkMacOSXInDarkMode(tkwin)) {
|
||||
event.name = Tk_GetUid("DarkAqua");
|
||||
} else {
|
||||
event.name = Tk_GetUid("LightAqua");
|
||||
NSAppearanceName effectiveAppearanceName = [[self effectiveAppearance] name];
|
||||
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
|
||||
static const char *defaultColor = NULL;
|
||||
|
||||
if (effectiveAppearanceName == NSAppearanceNameAqua) {
|
||||
TkSendVirtualEvent(tkwin, "LightAqua", NULL);
|
||||
} else if (effectiveAppearanceName == NSAppearanceNameDarkAqua) {
|
||||
TkSendVirtualEvent(tkwin, "DarkAqua", NULL);
|
||||
}
|
||||
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
|
||||
if ([NSApp macOSVersion] < 101500) {
|
||||
|
||||
/*
|
||||
* Mojave cannot handle the KVO shenanigans that we need for the
|
||||
* highlight and accent color notifications.
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
if (!defaultColor) {
|
||||
defaultColor = [NSApp macOSVersion] < 110000 ? "Blue" : "Multicolor";
|
||||
preferences = [[NSUserDefaults standardUserDefaults] retain];
|
||||
|
||||
/*
|
||||
* AppKit calls this method when the user changes the Accent Color
|
||||
* but not when the user changes the Highlight Color. So we register
|
||||
* to receive KVO notifications for Highlight Color as well.
|
||||
*/
|
||||
|
||||
[preferences addObserver:self
|
||||
forKeyPath:@"AppleHighlightColor"
|
||||
options:NSKeyValueObservingOptionNew
|
||||
context:NULL];
|
||||
}
|
||||
NSString *accent = [preferences stringForKey:@"AppleAccentColor"];
|
||||
NSArray *words = [[preferences stringForKey:@"AppleHighlightColor"]
|
||||
componentsSeparatedByString: @" "];
|
||||
NSString *highlight = [words count] > 3 ? [words objectAtIndex:3] : nil;
|
||||
const char *accentName = accent ? accentNames[1 + accent.intValue] : defaultColor;
|
||||
const char *highlightName = highlight ? highlight.UTF8String: defaultColor;
|
||||
char data[256];
|
||||
snprintf(data, 256, "Appearance %s Accent %s Highlight %s",
|
||||
effectiveAppearanceName.UTF8String, accentName,
|
||||
highlightName);
|
||||
TkSendVirtualEvent(tkwin, "AppearanceChanged", Tcl_NewStringObj(data, -1));
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context
|
||||
{
|
||||
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
|
||||
if (object == preferences && [keyPath isEqualToString:@"AppleHighlightColor"]) {
|
||||
if (@available(macOS 10.14, *)) {
|
||||
[self viewDidChangeEffectiveAppearance];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is no-op on 10.7 and up because Apple has removed this widget, but we
|
||||
* are leaving it here for backwards compatibility.
|
||||
@@ -1148,7 +1191,9 @@ RedisplayView(
|
||||
XVirtualEvent event;
|
||||
int x, y;
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
Tk_Window tkwin = (Tk_Window)winPtr;
|
||||
(void)sender;
|
||||
|
||||
if (!winPtr){
|
||||
return;
|
||||
}
|
||||
@@ -1169,12 +1214,10 @@ RedisplayView(
|
||||
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
|
||||
}
|
||||
|
||||
- (BOOL) isOpaque
|
||||
{
|
||||
NSWindow *w = [self window];
|
||||
return (w && (([w styleMask] & NSTexturedBackgroundWindowMask) ||
|
||||
![w isOpaque]) ? NO : YES);
|
||||
}
|
||||
/*
|
||||
* On Catalina this is never called and drawRect clips to the rect that
|
||||
* is passed to it by AppKit.
|
||||
*/
|
||||
|
||||
- (BOOL) wantsDefaultClipping
|
||||
{
|
||||
@@ -1193,6 +1236,8 @@ RedisplayView(
|
||||
|
||||
- (void) keyDown: (NSEvent *) theEvent
|
||||
{
|
||||
(void)theEvent;
|
||||
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
|
||||
#endif
|
||||
@@ -1200,7 +1245,7 @@ RedisplayView(
|
||||
|
||||
/*
|
||||
* When the services menu is opened this is called for each Responder in
|
||||
* the Responder chain until a service provider is found. The TkContentView
|
||||
* 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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user