diff --git a/ChangeLog b/ChangeLog index 27bd036af..e6f3ec881 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2013-08-30 Fred Kiefer + + * Headers/Additions/GNUstepGUI/GSDisplayServer.h + * Source/GSDisplayServer.m: Add new method -_printEventQueue. + * Source/NSWindow.m (-_checkCursorRectangles:forEvent:): Replace + hack with proper functions that handle cursor rectangles. + 2013-08-27 Fred Kiefer * Source/NSCursor.m (-mouseEntered:, -mouseExited:): diff --git a/Headers/Additions/GNUstepGUI/GSDisplayServer.h b/Headers/Additions/GNUstepGUI/GSDisplayServer.h index f8404cc03..70b781594 100644 --- a/Headers/Additions/GNUstepGUI/GSDisplayServer.h +++ b/Headers/Additions/GNUstepGUI/GSDisplayServer.h @@ -190,6 +190,7 @@ APPKIT_EXPORT NSString *GSScreenNumber; - (void) discardEventsMatchingMask: (unsigned)mask beforeEvent: (NSEvent*)limit; - (void) postEvent: (NSEvent*)anEvent atStart: (BOOL)flag; +- (void) _printEventQueue; @end diff --git a/Source/GSDisplayServer.m b/Source/GSDisplayServer.m index 47d6656c7..33da867e5 100644 --- a/Source/GSDisplayServer.m +++ b/Source/GSDisplayServer.m @@ -331,7 +331,7 @@ GSCurrentServer(void) NSCountedSet *old = (NSCountedSet*)NSMapGet(drag_types, (void*)win); NSEnumerator *drag_enum = [types objectEnumerator]; id type; - unsigned originalCount; + NSUInteger originalCount; /* * Make sure the set exists. @@ -970,14 +970,14 @@ GSCurrentServer(void) inMode: (NSString*)mode dequeue: (BOOL)flag { - unsigned pos = 0; /* Position in queue scanned so far */ - NSRunLoop *loop = nil; + NSUInteger pos = 0; /* Position in queue scanned so far */ + NSRunLoop *loop = nil; do { - unsigned count = [event_queue count]; - NSEvent *event; - unsigned i = 0; + NSUInteger count = [event_queue count]; + NSEvent *event; + NSUInteger i = 0; if (count == 0) { @@ -999,7 +999,7 @@ GSCurrentServer(void) */ if (count > pos) { - unsigned end = count - pos; + NSUInteger end = count - pos; NSRange r = NSMakeRange(pos, end); NSEvent *events[end]; @@ -1055,7 +1055,7 @@ GSCurrentServer(void) - (void) discardEventsMatchingMask: (unsigned)mask beforeEvent: (NSEvent*)limit { - unsigned index = [event_queue count]; + NSUInteger index = [event_queue count]; /* * If there is a range to use - remove all the matching events in it @@ -1063,14 +1063,14 @@ GSCurrentServer(void) */ if (index > 0) { - NSTimeInterval when = [limit timestamp]; - NSEvent *events[index]; + NSTimeInterval when = [limit timestamp]; + NSEvent *events[index]; [event_queue getObjects: events]; while (index-- > 0) { - NSEvent *event = events[index]; + NSEvent *event = events[index]; if ([event timestamp] < when) { @@ -1096,4 +1096,29 @@ GSCurrentServer(void) [event_queue addObject: anEvent]; } +- (void) _printEventQueue +{ + NSUInteger index = [event_queue count]; + + if (index > 0) + { + NSEvent *events[index]; + NSUInteger i; + + NSLog(@"Dumping events from queue"); + [event_queue getObjects: events]; + + for (i = 0; i < index; i++) + { + NSEvent *event = events[i]; + + NSLog(@"index %d %@", i, event); + } + } + else + { + NSLog(@"Event queue is empty"); + } +} + @end diff --git a/Source/NSWindow.m b/Source/NSWindow.m index 43271a8ee..046efc41d 100644 --- a/Source/NSWindow.m +++ b/Source/NSWindow.m @@ -2761,6 +2761,164 @@ resetCursorRectsForView(NSView *theView) } } +static void +checkCursorRectanglesEntered(NSView *theView, NSEvent *theEvent, NSPoint lastPoint) +{ + + /* + * Check cursor rectangles for the subviews + */ + if (theView->_rFlags.has_subviews) + { + NSArray *sb = theView->_sub_views; + NSUInteger count = [sb count]; + + if (count > 0) + { + NSView *subs[count]; + NSUInteger i; + + [sb getObjects: subs]; + for (i = 0; i < count; ++i) + { + if (![subs[i] isHidden]) + { + checkCursorRectanglesEntered(subs[i], theEvent, lastPoint); + } + } + } + } + + if (theView->_rFlags.valid_rects) + { + NSArray *tr = theView->_cursor_rects; + NSUInteger count = [tr count]; + + // Loop through cursor rectangles + if (count > 0) + { + GSTrackingRect *rects[count]; + NSPoint loc = [theEvent locationInWindow]; + NSUInteger i; + + [tr getObjects: rects]; + + for (i = 0; i < count; ++i) + { + GSTrackingRect *r = rects[i]; + BOOL last; + BOOL now; + + if ([r isValid] == NO) + continue; + + /* + * Check for presence of point in rectangle. + */ + last = NSMouseInRect(lastPoint, r->rectangle, NO); + now = NSMouseInRect(loc, r->rectangle, NO); + + // 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]; + [NSApp postEvent: e atStart: YES]; + //NSLog(@"Add enter event %@ for view %@ rect %@", e, theView, NSStringFromRect(r->rectangle)); + } + } + } + } +} + +static void +checkCursorRectanglesExited(NSView *theView, NSEvent *theEvent, NSPoint lastPoint) +{ + if (theView->_rFlags.valid_rects) + { + NSArray *tr = theView->_cursor_rects; + NSUInteger count = [tr count]; + + // Loop through cursor rectangles + if (count > 0) + { + GSTrackingRect *rects[count]; + NSPoint loc = [theEvent locationInWindow]; + NSUInteger i; + + [tr getObjects: rects]; + + for (i = 0; i < count; ++i) + { + GSTrackingRect *r = rects[i]; + BOOL last; + BOOL now; + + if ([r isValid] == NO) + continue; + + /* + * Check for presence of point in rectangle. + */ + last = NSMouseInRect(lastPoint, r->rectangle, NO); + now = NSMouseInRect(loc, r->rectangle, NO); + + // 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]; + [NSApp postEvent: e atStart: YES]; + //[NSApp postEvent: e atStart: NO]; + //NSLog(@"Add exit event %@ for view %@ rect %@", e, theView, NSStringFromRect(r->rectangle)); + } + } + } + } + + /* + * Check cursor rectangles for the subviews + */ + if (theView->_rFlags.has_subviews) + { + NSArray *sb = theView->_sub_views; + NSUInteger count = [sb count]; + + if (count > 0) + { + NSView *subs[count]; + NSUInteger i; + + [sb getObjects: subs]; + for (i = 0; i < count; ++i) + { + if (![subs[i] isHidden]) + { + checkCursorRectanglesExited(subs[i], theEvent, lastPoint); + } + } + } + } +} + - (void) resetCursorRects { [self discardCursorRects]; @@ -2782,7 +2940,7 @@ resetCursorRectsForView(NSView *theView) clickCount: 0 pressure: 0]; _lastPoint = NSMakePoint(-1,-1); - (*ccImp)(self, ccSel, _wv, e); + checkCursorRectanglesEntered(_wv, e, _lastPoint); _lastPoint = loc; } } @@ -3598,99 +3756,12 @@ resetCursorRectsForView(NSView *theView) - (void) _checkCursorRectangles: (NSView*)theView forEvent: (NSEvent*)theEvent { - // FIXME: What this method should do is to send exit events before enter events - // And all enter events should be sorted from outer to inner. With the current - // hack to post the enter events at the end of the queue this is about correct, - // as long as nothing else is in the event queue :-( - // Most likely similar reasoning should be applied to _checkTrackingRectangles:forEvent: - // the best way to achive this seems to be having to separate loops over the hierarchy. - - if (theView->_rFlags.valid_rects) - { - NSArray *tr = theView->_cursor_rects; - NSUInteger count = [tr count]; - - // Loop through cursor rectangles - if (count > 0) - { - GSTrackingRect *rects[count]; - NSPoint loc = [theEvent locationInWindow]; - NSUInteger i; - - [tr getObjects: rects]; - - for (i = 0; i < count; ++i) - { - GSTrackingRect *r = rects[i]; - BOOL last; - BOOL now; - - if ([r isValid] == NO) - continue; - - /* - * Check for presence of point in rectangle. - */ - last = NSMouseInRect(_lastPoint, r->rectangle, NO); - now = NSMouseInRect(loc, r->rectangle, NO); - - // 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: NO]; - } - // 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 - */ - if (theView->_rFlags.has_subviews) - { - NSArray *sb = theView->_sub_views; - NSUInteger count = [sb count]; - - if (count > 0) - { - NSView *subs[count]; - NSUInteger i; - - [sb getObjects: subs]; - for (i = 0; i < count; ++i) - { - if (![subs[i] isHidden]) - (*ccImp)(self, ccSel, subs[i], theEvent); - } - } - } + // As we add the events to the front of the queue, we need to add the last + // events first. That is, first the enter evnts from inner to outer and + // then the exit events + checkCursorRectanglesEntered(theView, theEvent, _lastPoint); + checkCursorRectanglesExited(theView, theEvent, _lastPoint); + //[GSServerForWindow(self) _printEventQueue]; } - (void) _processResizeEvent @@ -3934,7 +4005,9 @@ resetCursorRectsForView(NSView *theView) * cursor update event. */ if (_f.cursor_rects_enabled) + { (*ccImp)(self, ccSel, _wv, theEvent); + } } _lastPoint = [theEvent locationInWindow]; @@ -3979,7 +4052,9 @@ resetCursorRectsForView(NSView *theView) // Don't update the cursor if the window isn't the key window. if (!_f.is_key) - break; + { + break; + } if ([theEvent trackingNumber]) // It's a mouse entered { @@ -4158,7 +4233,9 @@ resetCursorRectsForView(NSView *theView) * to determine if we should send a cursor update * event. */ if (_f.cursor_rects_enabled) - (*ccImp)(self, ccSel, _wv, theEvent); + { + checkCursorRectanglesExited(_wv, theEvent, _lastPoint); + } } _lastPoint = NSMakePoint(-1, -1);