Mouse Movement tracking
Mouse Movement tracking
- Subject: Mouse Movement tracking
- From: Pandaa <email@hidden>
- Date: Wed, 14 Apr 2004 01:56:18 +0200
Hi,
since mouseMoved events is limited to firstResponders and I've often
needed mouse movement tracking also when views are not first responder
or not even in the main or key window, I put together a simple to use
helper class to do pixel accurate mouse moved tracking using tracking
rects. It's actually tricky to get precisely right, but here it is - if
you wanna know the details, just ask.
Enjoy, hope it's useful to someone.
Usage:
This will track mouse movements with pixel accuracy inside the bounds
of a view with no lag:
- (void)awakeFromNib
{
mainTrackingRectTag = [self addTrackingRect:_bounds owner:self
user
Data:nil assumeInside:NO];
helper = [[OCMouseMovedHelper alloc] initWithView:self];
}
- (void)mouseEntered:(NSEvent*)theEvent
{
int track = [theEvent trackingNumber];
if ( track == mainTrackingRectTag )
{
[helper addTrackingRectsForDetectingMovement];
}
else if ( [helper mouseEnteredIsMouseMovement:track] )
{
NSPoint mouse = [helper addTrackingRectsForDetectingMovement];
// aha, the mouse moved, do something
}
}
- (void)mouseExited:(NSEvent*)theEvent
{
int track = [theEvent trackingNumber];
if ( track == mainTrackingRectTag )
[helper removeTrackingRects]; // mouse outside our area of interest
else if ( [helper mouseExitedIsMouseMovement:track] )
{
NSPoint mouse = [helper addTrackingRectsForDetectingMovement];
// aha, the mouse moved, do something
}
}
If anyone has suggestions on how to improve this or if there are even
better and simpler ways of doing this it would be nice to hear.
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . .
. . . . earth water fire air software - the five elements . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . .
. email@hidden . . www.synapticpulse.net .
// OCMouseMovedHelper.h
#import <Foundation/Foundation.h>
typedef int(*ViewAddTrackingRect)(id,SEL,NSRect,id,void*,BOOL);
typedef void(*ViewRemoveTrackingRect)(id,SEL,int);
typedef NSPoint(*WindowConvertScreenToBase)(id,SEL,NSPoint);
typedef NSPoint(*ViewConvertPointFromView)(id,SEL,NSPoint,NSView*);
@interface OCMouseMovedHelper : NSObject
{
NSView *view;
NSWindow *window;
ViewAddTrackingRect addImplementation;
ViewRemoveTrackingRect removeImplementation;
WindowConvertScreenToBase screenToBaseImplementation;
ViewConvertPointFromView convertPointImplementation;
void(*trackFromPointImplementation)(id,SEL,NSPoint);
int tag[6];
}
- (id)initWithView:(NSView*)parentView; // will not retain view
- (BOOL)mouseEnteredIsMouseMovement:(int)trackingNumber;
- (BOOL)mouseExitedIsMouseMovement:(int)trackingNumber;
- (NSPoint)addTrackingRectsForDetectingMovement; // returns [NSEvent
mouseLocation] in local coordinates
-
(void)addTrackingRectsForDetectingMovementFromPoint:
(NSPoint)localMouse;
- (void)removeTrackingRects;
@end
// ---
// OCMouseMovedHelper.m
#import "OCMouseMovedHelper.h"
@implementation OCMouseMovedHelper
- (id)initWithView:(NSView*)parentView
{
if ( self = [super init] )
{
view = parentView;
addImplementation = (ViewAddTrackingRect)[view
methodForSelector:@selector(addTrackingRect:owner:userData:
assumeInside:)];
removeImplementation = (ViewRemoveTrackingRect)[view
methodForSelector:@selector(removeTrackingRect:)];
convertPointImplementation = (ViewConvertPointFromView)[view
methodForSelector:@selector(convertPoint:fromView:)];
window = [parentView window];
screenToBaseImplementation = (WindowConvertScreenToBase)[window
methodForSelector:@selector(convertScreenToBase:)];
trackFromPointImplementation = (void(*)(id,SEL,NSPoint))[self
methodForSelector:
@selector(addTrackingRectsForDetectingMovementFromPoint:)];
int i = 0;
for ( ; i < 6 ; ++i )
tag[i] = 0;
}
return self;
}
- (void)dealloc
{
[self removeTrackingRects];
[super dealloc];
}
- (BOOL)mouseEnteredIsMouseMovement:(int)trackingNumber
{
return ( (trackingNumber == tag[1]) || (trackingNumber == tag[2]) );
}
- (BOOL)mouseExitedIsMouseMovement:(int)trackingNumber
{
return ( (trackingNumber == tag[0]) || (trackingNumber == tag[3])
|| (trackingNumber == tag[4]) || (trackingNumber == tag[5]) );
}
- (NSPoint)addTrackingRectsForDetectingMovement
{
NSPoint mouse = [NSEvent mouseLocation];
mouse =
screenToBaseImplementation(window,@selector(convertScreenToBase:),mouse)
;
mouse =
convertPointImplementation(view,@selector(convertPoint:
fromView:),mouse,nil);
trackFromPointImplementation(self,@selector(addTrackingRectsForDetecting
MovementFromPoint:),mouse);
return mouse;
}
-
(void)addTrackingRectsForDetectingMovementFromPoint:(NSPoint)localMouse
{
int xi = (int)(localMouse.x+0.5), yi = (int)(localMouse.y+0.5);
NSRect clipRect;
clipRect.origin.x = xi-5; clipRect.origin.y = yi-5;
clipRect.size.width = 11; clipRect.size.height = 11;
if ( tag[5] )
removeImplementation(view,@selector(removeTrackingRect:),tag[5]);
tag[5] =
addImplementation(view,@selector(addTrackingRect:owner:userData:
assumeInside:),clipRect,view,nil,YES);
clipRect.origin.x = xi-3; clipRect.origin.y = yi-3;
clipRect.size.width = 7; clipRect.size.height = 7;
if ( tag[4] )
removeImplementation(view,@selector(removeTrackingRect:),tag[4]);
tag[4] =
addImplementation(view,@selector(addTrackingRect:owner:userData:
assumeInside:),clipRect,view,nil,YES);
clipRect.origin.x = xi-1; clipRect.origin.y = yi-1;
clipRect.size.width = 3; clipRect.size.height = 3;
if ( tag[3] )
removeImplementation(view,@selector(removeTrackingRect:),tag[3]);
tag[3] =
addImplementation(view,@selector(addTrackingRect:owner:userData:
assumeInside:),clipRect,view,nil,YES);
NSRect pixelRect;
pixelRect.origin.x = xi-0.01; pixelRect.origin.y = yi-0.01;
pixelRect.size.width = 0.999; pixelRect.size.height = 0.999;
if ( tag[0] )
removeImplementation(view,@selector(removeTrackingRect:),tag[0]);
tag[0] =
addImplementation(view,@selector(addTrackingRect:owner:userData:
assumeInside:),pixelRect,view,nil,YES);
pixelRect.origin.x = (int)(clipRect.origin.x + 0.5);
pixelRect.origin.y = clipRect.origin.y;
pixelRect.size.width = xi - (int)(clipRect.origin.x + 0.5);
pixelRect.size.height = clipRect.size.height;
if ( tag[1] )
removeImplementation(view,@selector(removeTrackingRect:),tag[1]);
tag[1] =
addImplementation(view,@selector(addTrackingRect:owner:userData:
assumeInside:),pixelRect,view,nil,NO);
pixelRect.origin.x = localMouse.x; pixelRect.origin.y =
(int)(localMouse.y + 1.5) - 0.01;
pixelRect.size.width =
clipRect.origin.x+clipRect.size.width-localMouse.x;
pixelRect.size.height =
(int)(clipRect.origin.y+clipRect.size.height+0.5)-(int)(localMouse.y +
1.5);
if ( tag[2] )
removeImplementation(view,@selector(removeTrackingRect:),tag[2]);
tag[2] =
addImplementation(view,@selector(addTrackingRect:owner:userData:
assumeInside:),pixelRect,view,nil,NO);
}
- (void)removeTrackingRects
{
int i = 0;
for ( ; i < 6 ; ++i )
if ( tag[i] != 0 )
{
removeImplementation(view,@selector(removeTrackingRectangle:),tag[i]);
tag[i] = 0;
}
}
@end
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.