mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-22 13:10:59 +00:00
Optimisation of handling of mouse movement.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@4221 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
c18fe106ea
commit
80cb0f7b81
4 changed files with 191 additions and 111 deletions
|
@ -1,3 +1,12 @@
|
|||
Fri May 7 12:16:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
|
||||
* 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 <fedor@gnu.org>
|
||||
|
||||
* Headers/gnustep/gui/NSGraphicsContext.h: New lock focus methods
|
||||
|
|
|
@ -33,13 +33,15 @@
|
|||
|
||||
@interface GSTrackingRect : NSObject <NSCoding>
|
||||
{
|
||||
// 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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSCoder.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSGeometry.h>
|
||||
#include <Foundation/NSNotification.h>
|
||||
#include <Foundation/NSValue.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
@ -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];
|
||||
|
|
Loading…
Reference in a new issue