tkMacOSXWindowEvent.c [plain text]
#include "tkMacOSXPrivate.h"
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"
static int GenerateUpdates(HIMutableShapeRef updateRgn,
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 *NSWindowDidOrderOffScreenNotification;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
#define NSWindowWillStartLiveResizeNotification @"NSWindowWillStartLiveResizeNotification"
#define NSWindowDidEndLiveResizeNotification @"NSWindowDidEndLiveResizeNotification"
#endif
#endif
@implementation TKApplication(TKWindowEvent)
- (void)windowActivation:(NSNotification *)notification {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
BOOL activate = [[notification name] isEqualToString:NSWindowDidBecomeKeyNotification];
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr && Tk_IsMapped(winPtr)) {
GenerateActivateEvents(winPtr, activate);
}
}
- (void)windowBoundsChanged:(NSNotification *)notification {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
BOOL movedOnly = [[notification name] isEqualToString:NSWindowDidMoveNotification];
if (movedOnly) {
}
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
WmInfo *wmPtr = winPtr->wmInfoPtr;
NSRect bounds = [w frame];
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){
flags |= TK_LOCATION_CHANGED;
} else {
x = y = -1;
}
if (!movedOnly && (winPtr->changes.width != bounds.size.width ||
winPtr->changes.height != bounds.size.height)) {
width = bounds.size.width - wmPtr->xInParent;
height = bounds.size.height - wmPtr->yInParent;
flags |= TK_SIZE_CHANGED;
}
if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
}
TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
}
}
- (void)windowExpanded:(NSNotification *)notification {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
winPtr->wmInfoPtr->hints.initial_state =
TkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState;
Tk_MapWindow((Tk_Window) winPtr);
if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
while (Tcl_ServiceEvent(0)) {}
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
GenerateActivateEvents(winPtr, 1);
} else {
Tcl_DoWhenIdle(DoWindowActivate, winPtr);
}
}
}
- (void)windowCollapsed:(NSNotification *)notification {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
Tk_UnmapWindow((Tk_Window) winPtr);
}
}
- (BOOL)windowShouldClose:(NSWindow *)w {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, w);
#endif
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
TkGenWMDestroyEvent((Tk_Window) winPtr);
}
return (winPtr ? NO : YES);
}
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
- (void)windowDragStart:(NSNotification *)notification {
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
}
- (void)windowLiveResize:(NSNotification *)notification {
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
}
- (void)windowMapped:(NSNotification *)notification {
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
}
}
- (void)windowBecameVisible:(NSNotification *)notification {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
}
- (void)windowUnmapped:(NSNotification *)notification {
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
}
}
#endif
- (void)_setupWindowNotifications {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
#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:);
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
observe(NSWindowWillMoveNotification, windowDragStart:);
observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:);
observe(NSWindowDidEndLiveResizeNotification, windowLiveResize:);
observe(NSWindowWillOrderOnScreenNotification, windowMapped:);
observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:);
observe(NSWindowDidOrderOffScreenNotification, windowUnmapped:);
#endif
#undef observe
}
@end
#pragma mark TKApplication(TKApplicationEvent)
@implementation TKApplication(TKApplicationEvent)
- (void)applicationActivate:(NSNotification *)notification {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
[NSApp tkCheckPasteboard];
}
- (void)applicationDeactivate:(NSNotification *)notification {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
TkSuspendClipboard();
}
- (void)applicationShowHide:(NSNotification *)notification {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
const char *cmd = ([[notification name] isEqualToString:
NSApplicationDidUnhideNotification] ?
"::tk::mac::OnShow" : "::tk::mac::OnHide");
Tcl_CmdInfo dummy;
if (_eventInterp && Tcl_GetCommandInfo(_eventInterp, cmd, &dummy)) {
int code = Tcl_EvalEx(_eventInterp, cmd, -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(_eventInterp);
}
Tcl_ResetResult(_eventInterp);
}
}
- (void)displayChanged:(NSNotification *)notification {
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
TkDisplay *dispPtr = TkGetDisplayList();
if (dispPtr) {
TkMacOSXDisplayChanged(dispPtr->display);
}
}
@end
#pragma mark -
static int
GenerateUpdates(
HIMutableShapeRef 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;
}
boundsRgn = HIShapeCreateWithRect(&bounds);
damageRgn = HIShapeCreateIntersection(updateRgn, boundsRgn);
if (HIShapeIsEmpty(damageRgn)) {
CFRelease(damageRgn);
CFRelease(boundsRgn);
return 0;
}
HIShapeGetBounds(damageRgn, &damageBounds);
if (!Tk_IsTopLevel(winPtr)) {
ChkErr(TkMacOSHIShapeUnion, boundsRgn, updateRgn, updateRgn);
HIShapeGetBounds(updateRgn, updateBounds);
}
CFRelease(damageRgn);
CFRelease(boundsRgn);
event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
event.xany.send_event = false;
event.xany.window = Tk_WindowId(winPtr);
event.xany.display = Tk_Display(winPtr);
event.type = Expose;
event.xexpose.x = damageBounds.origin.x - bounds.origin.x;
event.xexpose.y = damageBounds.origin.y - bounds.origin.y;
event.xexpose.width = damageBounds.size.width;
event.xexpose.height = damageBounds.size.height;
event.xexpose.count = 0;
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
#ifdef TK_MAC_DEBUG_DRAWING
TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
event.xexpose.y, event.xexpose.width, event.xexpose.height);
#endif
for (childPtr = winPtr->childList; childPtr != NULL;
childPtr = childPtr->nextPtr) {
if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
continue;
}
GenerateUpdates(updateRgn, updateBounds, childPtr);
}
if (Tk_IsContainer(winPtr)) {
childPtr = TkpGetOtherWindow(winPtr);
if (childPtr != NULL && Tk_IsMapped(childPtr)) {
GenerateUpdates(updateRgn, updateBounds, childPtr);
}
}
return 1;
}
int
GenerateActivateEvents(
TkWindow *winPtr,
int activeFlag)
{
TkGenerateActivateEvents(winPtr, activeFlag);
TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
TkMacOSXEnterExitFullscreen(winPtr, activeFlag);
return true;
}
void
DoWindowActivate(
ClientData clientData)
{
GenerateActivateEvents(clientData, 1);
}
MODULE_SCOPE int
TkMacOSXGenerateFocusEvent(
TkWindow *winPtr,
int activeFlag)
{
XEvent event;
if (winPtr->wmInfoPtr && (winPtr->wmInfoPtr->macClass == kHelpWindowClass ||
winPtr->wmInfoPtr->attributes & kWindowNoActivatesAttribute)) {
return false;
}
if (activeFlag) {
event.xany.type = FocusIn;
} else {
event.xany.type = FocusOut;
}
event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
event.xany.send_event = False;
event.xfocus.display = Tk_Display(winPtr);
event.xfocus.window = winPtr->window;
event.xfocus.mode = NotifyNormal;
event.xfocus.detail = NotifyDetailNone;
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
return true;
}
void
TkGenWMConfigureEvent(
Tk_Window tkwin,
int x,
int y,
int width,
int height,
int flags)
{
XEvent event;
WmInfo *wmPtr;
TkWindow *winPtr = (TkWindow *) tkwin;
if (tkwin == NULL) {
return;
}
event.type = ConfigureNotify;
event.xconfigure.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
event.xconfigure.send_event = False;
event.xconfigure.display = Tk_Display(tkwin);
event.xconfigure.event = Tk_WindowId(tkwin);
event.xconfigure.window = Tk_WindowId(tkwin);
event.xconfigure.border_width = winPtr->changes.border_width;
event.xconfigure.override_redirect = winPtr->atts.override_redirect;
if (winPtr->changes.stack_mode == Above) {
event.xconfigure.above = winPtr->changes.sibling;
} else {
event.xconfigure.above = None;
}
if (!(flags & TK_LOCATION_CHANGED)) {
x = Tk_X(tkwin);
y = Tk_Y(tkwin);
}
if (!(flags & TK_SIZE_CHANGED)) {
width = Tk_Width(tkwin);
height = Tk_Height(tkwin);
}
event.xconfigure.x = x;
event.xconfigure.y = y;
event.xconfigure.width = width;
event.xconfigure.height = height;
if (flags & TK_MACOSX_HANDLE_EVENT_IMMEDIATELY) {
Tk_HandleEvent(&event);
} else {
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
}
if (Tk_IsTopLevel(winPtr)) {
wmPtr = winPtr->wmInfoPtr;
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)) {
} else {
if (wmPtr->gridWin != NULL) {
wmPtr->width = wmPtr->reqGridWidth
+ (width - winPtr->reqWidth)/wmPtr->widthInc;
if (wmPtr->width < 0) {
wmPtr->width = 0;
}
} else {
wmPtr->width = width;
}
}
if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) {
} else {
if (wmPtr->gridWin != NULL) {
wmPtr->height = wmPtr->reqGridHeight
+ (height - winPtr->reqHeight)/wmPtr->heightInc;
if (wmPtr->height < 0) {
wmPtr->height = 0;
}
} else {
wmPtr->height = height;
}
}
wmPtr->configWidth = width;
wmPtr->configHeight = height;
}
}
winPtr->changes.x = x;
winPtr->changes.y = y;
winPtr->changes.width = width;
winPtr->changes.height = height;
TkMacOSXInvalClipRgns(tkwin);
}
void
TkGenWMDestroyEvent(
Tk_Window tkwin)
{
XEvent event;
event.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
event.xany.send_event = False;
event.xany.display = Tk_Display(tkwin);
event.xclient.window = Tk_WindowId(tkwin);
event.xclient.type = ClientMessage;
event.xclient.message_type = Tk_InternAtom(tkwin, "WM_PROTOCOLS");
event.xclient.format = 32;
event.xclient.data.l[0] = Tk_InternAtom(tkwin, "WM_DELETE_WINDOW");
Tk_HandleEvent(&event);
}
void
TkWmProtocolEventProc(
TkWindow *winPtr,
XEvent *eventPtr)
{
WmInfo *wmPtr;
ProtocolHandler *protPtr;
Tcl_Interp *interp;
Atom protocol;
int result;
wmPtr = winPtr->wmInfoPtr;
if (wmPtr == NULL) {
return;
}
protocol = (Atom) eventPtr->xclient.data.l[0];
for (protPtr = wmPtr->protPtr; protPtr != NULL;
protPtr = protPtr->nextPtr) {
if (protocol == protPtr->protocol) {
Tcl_Preserve(protPtr);
interp = protPtr->interp;
Tcl_Preserve(interp);
result = Tcl_GlobalEval(interp, protPtr->command);
if (result != TCL_OK) {
Tcl_AddErrorInfo(interp, "\n (command for \"");
Tcl_AddErrorInfo(interp,
Tk_GetAtomName((Tk_Window) winPtr, protocol));
Tcl_AddErrorInfo(interp, "\" window manager protocol)");
Tk_BackgroundError(interp);
}
Tcl_Release(interp);
Tcl_Release(protPtr);
return;
}
}
if (protocol == Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW")) {
Tk_DestroyWindow((Tk_Window) winPtr);
}
}
int
Tk_MacOSXIsAppInFront(void)
{
OSStatus err;
ProcessSerialNumber frontPsn, ourPsn = {0, kCurrentProcess};
Boolean isFrontProcess = true;
err = ChkErr(GetFrontProcess, &frontPsn);
if (err == noErr) {
ChkErr(SameProcess, &frontPsn, &ourPsn, &isFrontProcess);
}
return (isFrontProcess == true);
}
#pragma mark TKContentView
#import <ApplicationServices/ApplicationServices.h>
@interface TKContentView(TKWindowEvent)
- (void)drawRect:(NSRect)rect;
- (void)generateExposeEvents:(HIMutableShapeRef)shape;
- (BOOL)isOpaque;
- (BOOL)wantsDefaultClipping;
- (BOOL)acceptsFirstResponder;
- (void)keyDown:(NSEvent *)theEvent;
@end
@implementation TKContentView
@end
static Tk_RestrictAction ExposeRestrictProc(ClientData arg, XEvent *eventPtr)
{
return (eventPtr->type == Expose && eventPtr->xany.serial == PTR2UINT(arg) ?
TK_PROCESS_EVENT : TK_DEFER_EVENT);
}
@implementation TKContentView(TKWindowEvent)
- (void)drawRect:(NSRect)rect {
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);
#endif
NSWindow *w = [self window];
if ([self isOpaque] && [w showsResizeIndicator]) {
NSRect bounds = [self convertRect:[w _growBoxRect] fromView:nil];
if ([self needsToDrawRect:bounds]) {
NSEraseRect(bounds);
}
}
CGFloat height = [self bounds].size.height;
HIMutableShapeRef drawShape = HIShapeCreateMutable();
while (rectsBeingDrawnCount--) {
CGRect r = NSRectToCGRect(*rectsBeingDrawn++);
r.origin.y = height - (r.origin.y + r.size.height);
HIShapeUnionWithRect(drawShape, &r);
}
if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
[self generateExposeEvents:drawShape];
} else {
[self performSelectorOnMainThread:@selector(generateExposeEvents:)
withObject:(id)drawShape waitUntilDone:NO
modes:[NSArray arrayWithObjects:NSRunLoopCommonModes,
NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode,
nil]];
}
CFRelease(drawShape);
}
- (void)generateExposeEvents:(HIMutableShapeRef)shape {
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
unsigned long serial;
CGRect updateBounds;
if (!winPtr) {
return;
}
HIShapeGetBounds(shape, &updateBounds);
serial = LastKnownRequestProcessed(Tk_Display(winPtr));
if (GenerateUpdates(shape, &updateBounds, winPtr) &&
![[NSRunLoop currentRunLoop] currentMode] &&
Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
ClientData oldArg;
Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc,
UINT2PTR(serial), &oldArg);
while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
}
}
- (void)tkToolbarButton:(id)sender {
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd);
#endif
XVirtualEvent event;
int x, y;
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
Tk_Window tkwin = (Tk_Window) winPtr;
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;
event.name = Tk_GetUid("ToolbarButton");
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}
#ifdef TK_MAC_DEBUG_DRAWING
- (void)setFrameSize:(NSSize)newSize {
TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd, NSStringFromSize(newSize));
[super setFrameSize:newSize];
}
- (void)setNeedsDisplayInRect:(NSRect)invalidRect {
TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
NSStringFromRect(invalidRect));
[super setNeedsDisplayInRect:invalidRect];
}
#endif
- (BOOL)isOpaque {
NSWindow *w = [self window];
return (w && (([w styleMask] & NSTexturedBackgroundWindowMask) ||
![w isOpaque]) ? NO : YES);
}
- (BOOL)wantsDefaultClipping {
return NO;
}
- (BOOL)acceptsFirstResponder {
return YES;
}
- (void)keyDown:(NSEvent *)theEvent {
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
}
@end
#pragma mark TKContentViewPrivate
@interface TKContentView(TKContentViewPrivate)
- (id)initWithFrame:(NSRect)frame;
- (void)_setAsideSubviews;
- (void)_restoreSubviews;
@end
@interface NSView(TKContentViewPrivate)
- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView;
- (void)_recursiveDisplayAllDirtyWithLockFocus:(BOOL)needsLockFocus visRect:(NSRect)visRect;
- (void)_recursive:(BOOL)recurse displayRectIgnoringOpacity:(NSRect)displayRect inContext:(NSGraphicsContext *)context topView:(BOOL)topView;
- (void)_lightWeightRecursiveDisplayInRect:(NSRect)visRect;
- (BOOL)_drawRectIfEmpty;
- (void)_drawRect:(NSRect)inRect clip:(BOOL)clip;
- (void)_setDrawsOwnDescendants:(BOOL)drawsOwnDescendants;
@end
@implementation TKContentView(TKContentViewPrivate)
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
_savedSubviews = nil;
_subviewsSetAside = NO;
[self _setDrawsOwnDescendants:YES];
}
return self;
}
- (void)_setAsideSubviews
{
#ifdef TK_MAC_DEBUG
if (_subviewsSetAside || _savedSubviews) {
Tcl_Panic("TKContentView _setAsideSubviews called incorrectly");
}
#endif
_savedSubviews = _subviews;
_subviews = nil;
_subviewsSetAside = YES;
}
- (void)_restoreSubviews
{
#ifdef TK_MAC_DEBUG
if (!_subviewsSetAside || _subviews) {
Tcl_Panic("TKContentView _restoreSubviews called incorrectly");
}
#endif
_subviews = _savedSubviews;
_savedSubviews = nil;
_subviewsSetAside = NO;
}
- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView
{
[self _setAsideSubviews];
[super _recursiveDisplayRectIfNeededIgnoringOpacity:rect isVisibleRect:isVisibleRect rectIsVisibleRectForView:visibleView topView:topView];
[self _restoreSubviews];
}
- (void)_recursiveDisplayAllDirtyWithLockFocus:(BOOL)needsLockFocus visRect:(NSRect)visRect
{
BOOL needToSetAsideSubviews = !_subviewsSetAside;
if (needToSetAsideSubviews) {
[self _setAsideSubviews];
}
[super _recursiveDisplayAllDirtyWithLockFocus:needsLockFocus visRect:visRect];
if (needToSetAsideSubviews) {
[self _restoreSubviews];
}
}
- (void)_recursive:(BOOL)recurse displayRectIgnoringOpacity:(NSRect)displayRect inContext:(NSGraphicsContext *)context topView:(BOOL)topView
{
[self _setAsideSubviews];
[super _recursive:recurse displayRectIgnoringOpacity:displayRect inContext:context topView:topView];
[self _restoreSubviews];
}
- (void)_lightWeightRecursiveDisplayInRect:(NSRect)visRect {
BOOL needToSetAsideSubviews = !_subviewsSetAside;
if (needToSetAsideSubviews) {
[self _setAsideSubviews];
}
[super _lightWeightRecursiveDisplayInRect:visRect];
if (needToSetAsideSubviews) {
[self _restoreSubviews];
}
}
- (BOOL)_drawRectIfEmpty {
return YES;
}
- (void)_drawRect:(NSRect)inRect clip:(BOOL)clip {
#ifdef TK_MAC_DEBUG_DRAWING
TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd, NSStringFromRect(inRect));
#endif
BOOL subviewsWereSetAside = _subviewsSetAside;
if (subviewsWereSetAside) {
[self _restoreSubviews];
}
[super _drawRect:inRect clip:clip];
if (subviewsWereSetAside) {
[self _setAsideSubviews];
}
}
@end