diff --git a/ChangeLog b/ChangeLog index 44dd0aed1..b4c97276d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Fri May 7 12:16:00 1999 Richard Frith-Macdonald + + * Headers/AppKit/GSTrackingRect.h: Add a couple of ivars and make + them public. + * Source/GSTrackingRect.m: Set ivars to say what methods the owner + responds to. + * Source/NSWindow.m: Rewrite of ([-_checkTrackingRectangles:forEvent]) + and ([-_checkCursorRectangles:forEvent:]) + 1999-05-05 Adam Fedor * Headers/gnustep/gui/NSGraphicsContext.h: New lock focus methods diff --git a/Headers/gnustep/gui/GSTrackingRect.h b/Headers/gnustep/gui/GSTrackingRect.h index e4109481c..a8923fcab 100644 --- a/Headers/gnustep/gui/GSTrackingRect.h +++ b/Headers/gnustep/gui/GSTrackingRect.h @@ -33,13 +33,15 @@ @interface GSTrackingRect : NSObject { - // Attributes - NSRect rectangle; - NSTrackingRectTag tag; - id owner; - void *user_data; - BOOL inside; - BOOL isValid; +@public + NSRect rectangle; + NSTrackingRectTag tag; + id owner; + void *user_data; + BOOL inside; + BOOL isValid; + BOOL ownerRespondsToMouseEntered; + BOOL ownerRespondsToMouseExited; } // Instance methods @@ -51,7 +53,7 @@ - (NSRect) rectangle; - (NSTrackingRectTag) tag; -- owner; +- (id) owner; - (void*) userData; - (BOOL) inside; @@ -61,8 +63,8 @@ // // NSCoding protocol // -- (void) encodeWithCoder: aCoder; -- initWithCoder: aDecoder; +- (void) encodeWithCoder: (NSCoder*)aCoder; +- (id) initWithCoder: (NSCoder*)aDecoder; @end diff --git a/Source/GSTrackingRect.m b/Source/GSTrackingRect.m index 67aa50172..d3ed9329e 100644 --- a/Source/GSTrackingRect.m +++ b/Source/GSTrackingRect.m @@ -58,7 +58,13 @@ tag = aTag; owner = anObject; if (owner) - [owner retain]; + { + [owner retain]; + if ([owner respondsToSelector: @selector(mouseEntered:)]) + ownerRespondsToMouseEntered = YES; + if ([owner respondsToSelector: @selector(mouseExited:)]) + ownerRespondsToMouseExited = YES; + } user_data = theData; inside = flag; isValid = YES; @@ -111,6 +117,8 @@ { [owner release]; owner = nil; + ownerRespondsToMouseEntered = NO; + ownerRespondsToMouseExited = NO; } } } diff --git a/Source/NSWindow.m b/Source/NSWindow.m index a4c904359..d6d7f9b3e 100644 --- a/Source/NSWindow.m +++ b/Source/NSWindow.m @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -87,6 +88,14 @@ @implementation NSWindow +/* + * Class variables + */ +static SEL ccSel = @selector(_checkCusrorRectangles:forEvent:); +static SEL ctSel = @selector(_checkTrackingRectangles:forEvent:); +static IMP ccImp; +static IMP ctImp; + // // Class methods // @@ -96,6 +105,8 @@ { NSDebugLog(@"Initialize NSWindow class\n"); [self setVersion: 2]; + ccImp = [self instanceMethodForSelector: ccSel]; + ctImp = [self instanceMethodForSelector: ctSel]; } } @@ -1058,130 +1069,180 @@ accepts_mouse_moved = flag; } -- (void) checkTrackingRectangles: (NSView *)theView - forEvent: (NSEvent *)theEvent +- (void) _checkTrackingRectangles: (NSView *)theView + forEvent: (NSEvent *)theEvent { - NSArray *tr = [theView trackingRectangles]; - NSArray *sb = [theView subviews]; - GSTrackingRect *r; - unsigned i, j; - BOOL last, now; - NSEvent *e; + NSArray *tr = [theView trackingRectangles]; + NSArray *sb = [theView subviews]; + unsigned count; - j = [tr count]; // Loop through the tracking - for (i = 0; i < j; ++i) // rectangles + /* + * Loop through the tracking rectangles + */ + count = [tr count]; + if (count > 0) { - r = (GSTrackingRect *)[tr objectAtIndex: i]; - // Check mouse at last point - last = [theView mouse: last_point inRect: [r rectangle]]; - // Check mouse at current point - now = [theView mouse: [theEvent locationInWindow] inRect: [r rectangle]]; + GSTrackingRect *rects[count]; + NSPoint loc = [theEvent locationInWindow]; + BOOL flipped = [theView isFlipped]; + unsigned i; - if ((!last) && (now)) // Mouse entered event + [tr getObjects: rects]; + + for (i = 0; i < count; ++i) { - id owner = [r owner]; + BOOL last; + BOOL now; + GSTrackingRect *r = rects[i]; - if ([owner respondsToSelector: @selector(mouseEntered:)]) + /* Check mouse at last point */ + last = NSMouseInRect(last_point, r->rectangle, flipped); + /* Check mouse at current point */ + now = NSMouseInRect(loc, r->rectangle, flipped); + + if ((!last) && (now)) // Mouse entered event { - e = [NSEvent enterExitEventWithType: NSMouseEntered - location: [theEvent locationInWindow] - modifierFlags: [theEvent modifierFlags] - timestamp: 0 - windowNumber: [theEvent windowNumber] - context: NULL - eventNumber: 0 - trackingNumber: [r tag] - userData: [r userData]]; - [owner mouseEntered: e]; + if (r->ownerRespondsToMouseEntered) + { + NSEvent *e; + + e = [NSEvent enterExitEventWithType: NSMouseEntered + location: loc + modifierFlags: [theEvent modifierFlags] + timestamp: 0 + windowNumber: [theEvent windowNumber] + context: NULL + eventNumber: 0 + trackingNumber: r->tag + userData: r->user_data]; + [r->owner mouseEntered: e]; + } } - } - if ((last) && (!now)) // Mouse exited event - { - id owner = [r owner]; - - if ([owner respondsToSelector: @selector(mouseExited:)]) + if ((last) && (!now)) // Mouse exited event { - e = [NSEvent enterExitEventWithType: NSMouseExited - location: [theEvent locationInWindow] - modifierFlags: [theEvent modifierFlags] - timestamp: 0 - windowNumber: [theEvent windowNumber] - context: NULL - eventNumber: 0 - trackingNumber: [r tag] - userData: [r userData]]; - [owner mouseExited: e]; + if (r->ownerRespondsToMouseExited) + { + NSEvent *e; + + e = [NSEvent enterExitEventWithType: NSMouseExited + location: loc + modifierFlags: [theEvent modifierFlags] + timestamp: 0 + windowNumber: [theEvent windowNumber] + context: NULL + eventNumber: 0 + trackingNumber: r->tag + userData: r->user_data]; + [r->owner mouseExited: e]; + } } } } - j = [sb count]; // Check tracking rectangles - for (i = 0; i < j; ++i) // for the subviews - [self checkTrackingRectangles: [sb objectAtIndex: i] forEvent: theEvent]; + /* + * Check tracking rectangles for the subviews + */ + count = [sb count]; + if (count > 0) + { + NSView *subs[count]; + unsigned i; + + [sb getObjects: subs]; + for (i = 0; i < count; ++i) + (*ctImp)(self, ctSel, subs[i], theEvent); + } } -- (void) checkCursorRectangles: (NSView *)theView forEvent: (NSEvent *)theEvent +- (void) _checkCursorRectangles: (NSView *)theView forEvent: (NSEvent *)theEvent { - NSArray *tr = [theView cursorRectangles]; - NSArray *sb = [theView subviews]; - GSTrackingRect *r; - unsigned i, j; - BOOL last, now; - NSEvent *e; - NSPoint loc = [theEvent locationInWindow]; - NSPoint lastPointConverted; - NSPoint locationConverted; - NSRect rect; + NSArray *tr = [theView cursorRectangles]; + NSArray *sb = [theView subviews]; + unsigned count; // Loop through cursor rectangles - j = [tr count]; - for (i = 0; i < j; ++i) + count = [tr count]; + if (count > 0) { - r = (GSTrackingRect *)[tr objectAtIndex: i]; + GSTrackingRect *rects[count]; + NSPoint loc = [theEvent locationInWindow]; + NSPoint lastConv; + NSPoint locConv; + BOOL flipped = [theView isFlipped]; + unsigned i; - if ([r isValid] == NO) - continue; - lastPointConverted = [theView convertPoint: last_point fromView: nil]; - locationConverted = [theView convertPoint: loc fromView: nil]; + /* + * Convert points from window to view coordinates. + */ + lastConv = [theView convertPoint: last_point fromView: nil]; + locConv = [theView convertPoint: loc fromView: nil]; - rect = [r rectangle]; // Check mouse's last point - last = [theView mouse: lastPointConverted inRect: rect]; - now = [theView mouse: locationConverted inRect: rect]; - // Mouse entered - if ((!last) && (now)) + [tr getObjects: rects]; + + for (i = 0; i < count; ++i) { - e = [NSEvent enterExitEventWithType: NSCursorUpdate - location: loc - modifierFlags: [theEvent modifierFlags] - timestamp: 0 - windowNumber: [theEvent windowNumber] - context: [theEvent context] - eventNumber: 0 - trackingNumber: (int)YES - userData: (void *)r]; - [self postEvent: e atStart: YES]; - } - // Mouse exited - if ((last) && (!now)) - { - e = [NSEvent enterExitEventWithType: NSCursorUpdate - location: loc - modifierFlags: [theEvent modifierFlags] - timestamp: 0 - windowNumber: [theEvent windowNumber] - context: [theEvent context] - eventNumber: 0 - trackingNumber: (int)NO - userData: (void *)r]; - [self postEvent: e atStart: YES]; + GSTrackingRect *r = rects[i]; + BOOL last; + BOOL now; + + if ([r isValid] == NO) + continue; + + /* + * Check for presence of point in rectangle. + */ + last = NSMouseInRect(lastConv, r->rectangle, flipped); + now = NSMouseInRect(locConv, r->rectangle, flipped); + + // Mouse entered + if ((!last) && (now)) + { + NSEvent *e; + + e = [NSEvent enterExitEventWithType: NSCursorUpdate + location: loc + modifierFlags: [theEvent modifierFlags] + timestamp: 0 + windowNumber: [theEvent windowNumber] + context: [theEvent context] + eventNumber: 0 + trackingNumber: (int)YES + userData: (void *)r]; + [self postEvent: e atStart: YES]; + } + // Mouse exited + if ((last) && (!now)) + { + NSEvent *e; + + e = [NSEvent enterExitEventWithType: NSCursorUpdate + location: loc + modifierFlags: [theEvent modifierFlags] + timestamp: 0 + windowNumber: [theEvent windowNumber] + context: [theEvent context] + eventNumber: 0 + trackingNumber: (int)NO + userData: (void *)r]; + [self postEvent: e atStart: YES]; + } } } - // Check cursor rectangles for the subviews - j = [sb count]; - for (i = 0; i < j; ++i) - [self checkCursorRectangles: [sb objectAtIndex: i] forEvent: theEvent]; + /* + * Check cursor rectangles for the subviews + */ + count = [sb count]; + if (count > 0) + { + NSView *subs[count]; + unsigned i; + + [sb getObjects: subs]; + for (i = 0; i < count; ++i) + (*ccImp)(self, ccSel, subs[i], theEvent); + } } - (void) sendEvent: (NSEvent *)theEvent @@ -1256,14 +1317,14 @@ // We need to go through all of the views, and if there is any with // a tracking rectangle then we need to determine if we should send // a NSMouseEntered or NSMouseExited event. - [self checkTrackingRectangles: content_view forEvent: theEvent]; + (*ctImp)(self, ctSel, content_view, theEvent); if (is_key) { // We need to go through all of the views, and if there is any with // a cursor rectangle then we need to determine if we should send a // cursor update event. - [self checkCursorRectangles: content_view forEvent: theEvent]; + (*ccImp)(self, ccSel, content_view, theEvent); } last_point = [theEvent locationInWindow];