2014-05-13 08:33:37 -05:00
// 13 may 2014
# include "objc_darwin.h"
# include "_cgo_export.h"
2014-05-20 07:08:55 -05:00
# import < AppKit / NSView . h >
# import < AppKit / NSTrackingArea . h >
# import < Foundation / NSGeometry . h >
# import < AppKit / NSEvent . h >
# import < AppKit / NSBitmapImageRep . h >
2014-05-13 08:33:37 -05:00
# define to ( T , x ) ( ( T * ) ( x ) )
# define toNSEvent ( x ) to ( NSEvent , ( x ) )
2014-05-15 20:45:42 -05:00
# define toAreaView ( x ) to ( areaView , ( x ) )
2014-05-13 08:33:37 -05:00
# define toNSInteger ( x ) ( ( NSInteger ) ( x ) )
# define fromNSInteger ( x ) ( ( intptr_t ) ( x ) )
# define toNSUInteger ( x ) ( ( NSUInteger ) ( x ) )
# define fromNSUInteger ( x ) ( ( uintptr_t ) ( x ) )
2014-05-16 08:13:11 -05:00
extern NSRect dummyRect ;
2014-05-13 08:33:37 -05:00
@ interface areaView : NSView {
NSTrackingArea * trackingArea ;
}
@ end
@ implementation areaView
- ( id ) initWithFrame : ( NSRect ) r
{
self = [ super initWithFrame : r ] ;
if ( self )
[ self retrack ] ;
// TODO other properties ?
return self ;
}
- ( void ) drawRect : ( NSRect ) cliprect
{
struct xrect rect ;
rect . x = ( intptr_t ) cliprect . origin . x ;
rect . y = ( intptr_t ) cliprect . origin . y ;
rect . width = ( intptr_t ) cliprect . size . width ;
rect . height = ( intptr_t ) cliprect . size . height ;
areaView_drawRect ( self , rect ) ;
}
- ( BOOL ) isFlipped
{
return YES ;
}
- ( BOOL ) acceptsFirstResponder
{
return YES ;
}
2014-06-07 03:19:37 -05:00
// this will have the Area receive a click that switches to the Window it is in from another one
- ( BOOL ) acceptsFirstMouse : ( NSEvent * ) e
{
return YES ;
}
2014-05-13 08:33:37 -05:00
- ( void ) retrack
{
2014-05-15 19:42:29 -05:00
trackingArea = [ [ NSTrackingArea alloc ]
initWithRect : [ self bounds ]
// this bit mask ( except for NSTrackingInVisibleRect , which was added later to prevent events from being triggered outside the visible area of the Area ) comes from https : // github . com / andlabs / misctestprogs / blob / master / cocoaviewmousetest . m ( and I wrote this bit mask on 25 april 2014 ) and yes I know it includes enter / exit even though we don ' t watch those events ; it probably won ' t really matter anyway but if it does I can change it easily
options : ( NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways | NSTrackingEnabledDuringMouseDrag | NSTrackingInVisibleRect )
owner : self
userInfo : nil ] ;
2014-05-13 08:33:37 -05:00
[ self addTrackingArea : trackingArea ] ;
}
- ( void ) updateTrackingAreas
{
[ self removeTrackingArea : trackingArea ] ;
[ trackingArea release ] ;
[ self retrack ] ;
}
2014-06-02 11:27:23 -05:00
# define event ( m , f ) \
2014-05-13 08:33:37 -05:00
- ( void ) m : ( NSEvent * ) e \
{ \
f ( self , e ) ; \
}
2014-06-02 11:27:23 -05:00
event ( mouseMoved , areaView_mouseMoved _mouseDragged )
event ( mouseDragged , areaView_mouseMoved _mouseDragged )
event ( rightMouseDragged , areaView_mouseMoved _mouseDragged )
event ( otherMouseDragged , areaView_mouseMoved _mouseDragged )
event ( mouseDown , areaView_mouseDown )
event ( rightMouseDown , areaView_mouseDown )
event ( otherMouseDown , areaView_mouseDown )
event ( mouseUp , areaView_mouseUp )
event ( rightMouseUp , areaView_mouseUp )
event ( otherMouseUp , areaView_mouseUp )
event ( keyDown , areaView_keyDown )
event ( keyUp , areaView_keyUp )
event ( flagsChanged , areaView_flagsChanged )
2014-05-13 08:33:37 -05:00
@ end
2014-06-07 17:17:29 -05:00
Class areaClass ;
void initAreaClass ( void )
{
areaClass = [ areaView class ] ;
}
2014-05-13 08:33:37 -05:00
id makeArea ( void )
{
return [ [ areaView alloc ]
2014-05-16 08:13:11 -05:00
initWithFrame : dummyRect ] ;
2014-05-13 08:33:37 -05:00
}
2014-05-15 21:15:54 -05:00
void drawImage ( void * pixels , intptr_t width , intptr_t height , intptr_t stride , intptr_t xdest , intptr_t ydest )
{
unsigned char * planes [ 1 ] ; // NSBitmapImageRep wants an array of planes ; we have one plane
NSBitmapImageRep * bitmap ;
planes [ 0 ] = ( unsigned char * ) pixels ;
bitmap = [ [ NSBitmapImageRep alloc ]
initWithBitmapDataPlanes : planes
pixelsWide : toNSInteger ( width )
pixelsHigh : toNSInteger ( height )
bitsPerSample : 8
samplesPerPixel : 4
hasAlpha : YES
isPlanar : NO
colorSpaceName : NSCalibratedRGBColorSpace // TODO NSDeviceRGBColorSpace ?
bitmapFormat : 0 // this is where the flag for placing alpha first would go if alpha came first ; the default is alpha last , which is how we ' re doing things ( otherwise the docs say "Color planes are arranged in the standard order—for example, red before green before blue for RGB color." ) ; this is also where the flag for non - premultiplied colors would go if we used it ( the default is alpha - premultiplied )
bytesPerRow : toNSInteger ( stride )
bitsPerPixel : 32 ] ;
// TODO this CAN fali ; check error
[ bitmap drawInRect : NSMakeRect ( ( CGFloat ) xdest , ( CGFloat ) ydest , ( CGFloat ) width , ( CGFloat ) height )
fromRect : NSZeroRect // draw whole image
operation : NSCompositeSourceOver
fraction : 1.0
respectFlipped : YES
hints : nil ] ;
[ bitmap release ] ;
}
2014-05-13 08:33:37 -05:00
uintptr_t modifierFlags ( id e )
{
return fromNSUInteger ( [ toNSEvent ( e ) modifierFlags ] ) ;
}
2014-05-15 20:45:42 -05:00
struct xpoint getTranslatedEventPoint ( id area , id e )
{
NSPoint p ;
struct xpoint q ;
p = [ toAreaView ( area ) convertPoint : [ toNSEvent ( e ) locationInWindow ] fromView : nil ] ;
q . x = ( intptr_t ) p . x ;
q . y = ( intptr_t ) p . y ;
return q ;
}
2014-05-13 08:33:37 -05:00
intptr_t buttonNumber ( id e )
{
return fromNSInteger ( [ toNSEvent ( e ) buttonNumber ] ) ;
}
2014-05-15 18:55:16 -05:00
intptr_t clickCount ( id e )
{
return fromNSInteger ( [ toNSEvent ( e ) clickCount ] ) ;
}
2014-05-13 08:33:37 -05:00
uintptr_t pressedMouseButtons ( void )
{
return fromNSUInteger ( [ NSEvent pressedMouseButtons ] ) ;
}
uintptr_t keyCode ( id e )
{
return ( uintptr_t ) ( [ toNSEvent ( e ) keyCode ] ) ;
}