Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Source/NSView.m
Original file line number Diff line number Diff line change
Expand Up @@ -2601,6 +2601,16 @@ - (void) displayIfNeededInRectIgnoringOpacity: (NSRect)aRect
isect = [subview convertRect: isect fromView: self];
[subview displayIfNeededInRectIgnoringOpacity: isect];
}
else if (NSIsEmptyRect(subviewFrame))
{
/* A subview with no area has nothing to draw, and is
never reached by the line above, so it would keep
itself and every view over it waiting for a display
that cannot happen. Let it settle its own flag.
*/
[subview displayIfNeededInRectIgnoringOpacity:
NSZeroRect];
}

if (subview->_rFlags.needs_display)
{
Expand Down Expand Up @@ -2729,6 +2739,17 @@ - (void) displayRectIgnoringOpacity: (NSRect)aRect
[subview displayRectIgnoringOpacity: isect
inContext: context];
}
else if (NSIsEmptyRect(subviewFrame)
&& subview->_rFlags.needs_display == YES)
{
/* A subview with no area has nothing to draw and is never
reached by the line above, so it would keep itself and
every view over it waiting for a display that cannot
happen. Let it settle its own flag.
*/
[subview displayRectIgnoringOpacity: NSZeroRect
inContext: context];
}
/*
* Is there still something to draw in the subview?
* This keeps the invariant that views further up are marked
Expand Down
101 changes: 101 additions & 0 deletions Tests/gui/NSView/emptyViewNeedsDisplay.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* A view with no area cannot draw anything. Marking it for display and
then displaying the window has to leave it, and every view above it,
clear again; otherwise nothing in that branch of the tree ever reports
itself as drawn. A view that has an area but falls outside the rectangle
being displayed is a different matter and keeps its mark. Drawing needs
the backend, so the set is skipped without one.
*/
#include "Testing.h"

#include <Foundation/NSAutoreleasePool.h>
#include <Foundation/NSGeometry.h>

#include <AppKit/NSApplication.h>
#include <AppKit/NSBox.h>
#include <AppKit/NSView.h>
#include <AppKit/NSWindow.h>

int
main(int argc, char **argv)
{
NSWindow *window;
NSView *content;
NSView *flat;
NSView *aside;
NSBox *box;

START_SET("NSView empty view needs display")

NS_DURING
{
[NSApplication sharedApplication];
}
NS_HANDLER
{
if ([[localException name] isEqualToString: NSInternalInconsistencyException])
SKIP("It looks like GNUstep backend is not yet installed")
}
NS_ENDHANDLER

NS_DURING
{
window = AUTORELEASE([[NSWindow alloc]
initWithContentRect: NSMakeRect(0, 0, 200, 200)
styleMask: NSWindowStyleMaskBorderless
backing: NSBackingStoreBuffered
defer: NO]);
content = [window contentView];

flat = AUTORELEASE([[NSView alloc]
initWithFrame: NSMakeRect(10, 10, 100, 0)]);
[content addSubview: flat];
[flat setNeedsDisplay: YES];
[window orderFront: nil];
[window display];

PASS([flat needsDisplay] == NO,
"a view with no area does not wait for a display");
PASS([content needsDisplay] == NO,
"the view holding it does not wait either");
PASS([window viewsNeedDisplay] == NO,
"the window has nothing left to display");

/* A box two pixels high gives its content view no room at all, which
is how this turns up in a real window. */
box = AUTORELEASE([[NSBox alloc]
initWithFrame: NSMakeRect(10, 100, 180, 2)]);
[box setTitlePosition: NSNoTitle];
[content addSubview: box];
[window display];

PASS([[box contentView] needsDisplay] == NO,
"the content view of a box too short for it is not left waiting");
PASS([box needsDisplay] == NO, "nor is the box");
PASS([content needsDisplay] == NO, "nor is the view holding the box");

/* A view with an area that the displayed rectangle does not reach
keeps its mark, since it still has something to draw. */
aside = AUTORELEASE([[NSView alloc]
initWithFrame: NSMakeRect(150, 150, 20, 20)]);
[content addSubview: aside];
[window display];
[aside setNeedsDisplay: YES];
[content displayIfNeededInRect: NSMakeRect(0, 0, 40, 40)];

PASS([aside needsDisplay] == YES,
"a view outside the rectangle being displayed still waits");
}
NS_HANDLER
{
if ([[localException name] isEqualToString: NSInternalInconsistencyException]
|| [[localException name] isEqualToString: @"NSWindowServerCommunicationException"])
SKIP("No display available")
else
[localException raise];
}
NS_ENDHANDLER

END_SET("NSView empty view needs display")

return 0;
}
Loading