Fix tracking rect bug

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@23711 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2006-10-02 12:07:35 +00:00
parent c201ae734e
commit e779b4215b
4 changed files with 85 additions and 30 deletions

View file

@ -1,3 +1,12 @@
2006-10-01 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSTrackingRect.m:
* Source/NSView.m:
* Headers/AppKit/NSView.h:
Fix tracking rect bug ... the owner of the rectangle should not
be retained by a tracking rect (but should be retained by a cursor
rect). Updated documentation to clearly state what mis retained.
2006-10-01 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSTheme.m: Add rudimentary inspector.

View file

@ -328,14 +328,41 @@ typedef enum _NSFocusRingType {
event: (NSEvent *)theEvent;
#endif
/*
* Managing the Cursor
/**
* Adds a cursor rectangle. This provides for automatic update of the
* cursor to be anObject while the mouse is in aRect.<br />
* The cursor (anObject) is retained until the cursor rectangle is
* removed or discarded.<br />
* Generally your subviews should call this in their implementation of
* the -resetCursorRects method.<br />
* It is your responsibility to ensure that aRect lies within your veiw's
* visible rectangle.
*/
- (void) addCursorRect: (NSRect)aRect
cursor: (NSCursor*)anObject;
/**
* Removes all the cursor rectancles which have been set up for the
* receiver. This is equivalent to calling -removeCursorRect:cursor:
* for all cursor rectangles which have been set up.<br />
* This is called automatically before the system calls -resetCursorRects
* so you never need to call it.
*/
- (void) discardCursorRects;
/**
* Removes the cursor rectangle which was set up for the specified
* rectangle and cursor.
*/
- (void) removeCursorRect: (NSRect)aRect
cursor: (NSCursor*)anObject;
/** <subclass-override />
* This is called to establish a new set of cursor rectangles whenever
* the receiver needs to do so (eg the view has been resized). The default
* implementation does nothing, but subclasses should use it to make
* calls to -addCursorRect:cursor: to establish their new cursor rectangles.
*/
- (void) resetCursorRects;
#ifndef STRICT_OPENSTEP
@ -351,10 +378,26 @@ typedef enum _NSFocusRingType {
- (NSString *) toolTip;
#endif
/*
* Tracking rectangles
/**
* Removes a tracking rectangle which was previously established using the
* -addTrackingRect:owner:userData:assumeInside: method.<br />
* The value of tag must be the value returned by the method used to add
* the rectangle.
*/
- (void) removeTrackingRect: (NSTrackingRectTag)tag;
/**
* Adds a tracking rectangle to monitor mouse movement and generate
* mouse-entered and mouse-exited events.<br />
* The event messages are sent to anObject, which is <em>not</em>
* retained and must therefore be sure to remove any tracking rectangles
* using it before it is deallocated.<br />
* The value of data is supplied as the user data in the event objects
* generated.<br />
* If flag is YES then the mouse is assumed to be inside the tracking
* rectangle and the first event generated will therefore be a mouse exit,
* if it is NO then the first event generated will be a mouse entry.
*/
- (NSTrackingRectTag) addTrackingRect: (NSRect)aRect
owner: (id)anObject
userData: (void*)data

View file

@ -51,10 +51,6 @@
rectangle = aRect;
tag = aTag;
owner = anObject;
if (owner != nil)
{
RETAIN(owner);
}
user_data = theData;
flags.inside = flag;
flags.isValid = YES;
@ -63,7 +59,6 @@
- (void) dealloc
{
TEST_RELEASE(owner);
[super dealloc];
}
@ -103,10 +98,6 @@
{
flags.isValid = NO;
flags.checked = NO;
if (owner != nil)
{
DESTROY(owner);
}
}
}
@ -134,7 +125,7 @@
rectangle = [aDecoder decodeRect];
[aDecoder decodeValueOfObjCType: @encode(NSTrackingRectTag) at: &tag];
[aDecoder decodeValueOfObjCType: @encode(id) at: &owner];
owner = [aDecoder decodeObject];
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &inside];
flags.inside = inside;
}

View file

@ -557,6 +557,10 @@ GSSetDragTypes(NSView* obj, NSArray *types)
RELEASE(_boundsMatrix);
TEST_RELEASE(_sub_views);
TEST_RELEASE(_tracking_rects);
if (_rFlags.has_currects != 0)
{
[self discardCursorRects]; // Handle release of cursors
}
TEST_RELEASE(_cursor_rects);
[self unregisterDraggedTypes];
[self releaseGState];
@ -2610,7 +2614,7 @@ Returns YES iff any scrolling was done.
m = [rectClass allocWithZone: NSDefaultMallocZone()];
m = [m initWithRect: aRect
tag: 0
owner: anObject
owner: RETAIN(anObject)
userData: NULL
inside: YES];
[_cursor_rects addObject: m];
@ -2624,17 +2628,18 @@ Returns YES iff any scrolling was done.
{
if (_rFlags.has_currects != 0)
{
if (_rFlags.valid_rects != 0)
{
unsigned count = [_cursor_rects count];
if (count > 0)
unsigned count = [_cursor_rects count];
if (count > 0)
{
GSTrackingRect *rects[count];
[_cursor_rects getObjects: rects];
if (_rFlags.valid_rects != 0)
{
GSTrackingRect *rects[count];
NSPoint loc = ((struct NSWindow_struct *)_window)->_lastPoint;
unsigned i;
[_cursor_rects getObjects: rects];
for (i = 0; i < count; ++i)
{
GSTrackingRect *r = rects[i];
@ -2644,10 +2649,14 @@ Returns YES iff any scrolling was done.
}
[r invalidate];
}
_rFlags.valid_rects = 0;
}
_rFlags.valid_rects = 0;
while (count-- > 0)
{
RELEASE([rects[count] owner]);
}
[_cursor_rects removeAllObjects];
}
[_cursor_rects removeAllObjects];
_rFlags.has_currects = 0;
}
}
@ -2677,6 +2686,7 @@ Returns YES iff any scrolling was done.
_rFlags.has_currects = 0;
_rFlags.valid_rects = 0;
}
RELEASE(c);
break;
}
else
@ -4091,13 +4101,15 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
_rFlags.flipped_view = [self isFlipped];
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_is_rotated_from_base];
[aDecoder decodeValueOfObjCType: @encode(BOOL)
at: &_is_rotated_or_scaled_from_base];
at: &_is_rotated_from_base];
[aDecoder decodeValueOfObjCType: @encode(BOOL)
at: &_is_rotated_or_scaled_from_base];
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_post_frame_changes];
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_autoresizes_subviews];
[aDecoder decodeValueOfObjCType: @encode(BOOL)
at: &_autoresizes_subviews];
[aDecoder decodeValueOfObjCType: @encode(unsigned int)
at: &_autoresizingMask];
at: &_autoresizingMask];
[self setNextKeyView: [aDecoder decodeObject]];
[[aDecoder decodeObject] setNextKeyView: self];
@ -4109,9 +4121,9 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
while ((sub = [e nextObject]) != nil)
{
NSAssert([sub window] == nil,
NSInternalInconsistencyException);
NSInternalInconsistencyException);
NSAssert([sub superview] == nil,
NSInternalInconsistencyException);
NSInternalInconsistencyException);
[sub viewWillMoveToWindow: _window];
[sub viewWillMoveToSuperview: self];
[sub setNextResponder: self];