summaryrefslogtreecommitdiff
path: root/area_darwin.m
blob: c45aa40935dfb666c59d0e8d1d8b8c137654fdfd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// 13 may 2014

#include "objc_darwin.h"
#include "area_darwin.h"
#include "_cgo_export.h"
#include <AppKit/NSView.h>
#include <AppKit/NSTrackingArea.h>
#include <Foundation/NSGeometry.h>
#include <AppKit/NSEvent.h>

#define to(T, x) ((T *) (x))
#define toNSEvent(x) to(NSEvent, (x))
#define toAreaView(x) to(areaView, (x))

#define toNSInteger(x) ((NSInteger) (x))
#define fromNSInteger(x) ((intptr_t) (x))
#define toNSUInteger(x) ((NSUInteger) (x))
#define fromNSUInteger(x) ((uintptr_t) (x))

@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;
}

- (void)retrack
{
	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];
	[self addTrackingArea:trackingArea];
}

- (void)updateTrackingAreas
{
	[self removeTrackingArea:trackingArea];
	[trackingArea release];
	[self retrack];
}

#define mouseEvent(m, f) \
	- (void)m:(NSEvent *)e \
	{ \
		f(self, e); \
	}
mouseEvent(mouseMoved, areaView_mouseMoved_mouseDragged)
mouseEvent(mouseDragged, areaView_mouseMoved_mouseDragged)
mouseEvent(rightMouseDragged, areaView_mouseMoved_mouseDragged)
mouseEvent(otherMouseDragged, areaView_mouseMoved_mouseDragged)
mouseEvent(mouseDown, areaView_mouseDown)
mouseEvent(rightMouseDown, areaView_mouseDown)
mouseEvent(otherMouseDown, areaView_mouseDown)
mouseEvent(mouseUp, areaView_mouseUp)
mouseEvent(rightMouseUp, areaView_mouseUp)
mouseEvent(otherMouseUp, areaView_mouseUp)

#define keyEvent(m, f) \
	- (void)m:(NSEvent *)e \
	{ \
		if (f(self, e) == NO) \
			[super m:e]; \
	}
keyEvent(keyDown, areaView_keyDown)
keyEvent(keyUp, areaView_keyUp)
keyEvent(flagsChanged, areaView_flagsChanged)

@end

id makeArea(void)
{
	return [[areaView alloc]
		initWithFrame:NSMakeRect(0, 0, 100, 100)];
}

uintptr_t modifierFlags(id e)
{
	return fromNSUInteger([toNSEvent(e) modifierFlags]);
}

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;
}

intptr_t buttonNumber(id e)
{
	return fromNSInteger([toNSEvent(e) buttonNumber]);
}

intptr_t clickCount(id e)
{
	return fromNSInteger([toNSEvent(e) clickCount]);
}

uintptr_t pressedMouseButtons(void)
{
	return fromNSUInteger([NSEvent pressedMouseButtons]);
}

uintptr_t keyCode(id e)
{
	return (uintptr_t) ([toNSEvent(e) keyCode]);
}