summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-05-10 21:03:04 -0400
committerPietro Gagliardi <[email protected]>2014-05-10 21:03:04 -0400
commitcc01981999df5f60bac36adf5039c752e10384e7 (patch)
treecb0f02854c48aa8c59c1952a9ddcb43b2917f235
parent5819e52f8de793d781c8de86d6ae16aa832fdfe1 (diff)
Added tracking areas to Area on Mac OS X so mouse move events can work; they work now.
-rw-r--r--area_darwin.go25
-rw-r--r--bleh_darwin.m29
-rw-r--r--objc_darwin.go2
-rw-r--r--objc_darwin.h2
-rw-r--r--sysdata_darwin.go4
5 files changed, 58 insertions, 4 deletions
diff --git a/area_darwin.go b/area_darwin.go
index 2041494..c5f0549 100644
--- a/area_darwin.go
+++ b/area_darwin.go
@@ -12,6 +12,7 @@ import (
//// #include <HIToolbox/Events.h>
// #include "objc_darwin.h"
// extern BOOL areaView_isFlipped_acceptsFirstResponder(id, SEL);
+// extern void areaView_updateTrackingAreas(id, SEL);
// extern void areaView_mouseMoved_mouseDragged(id, SEL, id);
// extern void areaView_mouseDown(id, SEL, id);
// extern void areaView_mouseUp(id, SEL, id);
@@ -36,6 +37,8 @@ var goAreaSels = []selector{
"ensuring that an Area's coordinate system has (0,0) at the top-left corner"},
selector{"acceptsFirstResponder", uintptr(C.areaView_isFlipped_acceptsFirstResponder), sel_bool,
"registering that Areas are to receive events"},
+ selector{"updateTrackingAreas", uintptr(C.areaView_updateTrackingAreas), sel_void,
+ "updating tracking areas for handling mouse movements in Area"},
selector{"mouseMoved:", uintptr(C.areaView_mouseMoved_mouseDragged), sel_void_id,
"handling mouse movements in Area"},
selector{"mouseDown:", uintptr(C.areaView_mouseDown), sel_void_id,
@@ -78,6 +81,7 @@ func makeArea(parentWindow C.id, alternate bool, s *sysData) C.id {
area := C.objc_msgSend_noargs(_goArea, _alloc)
area = initWithDummyFrame(area)
// TODO others?
+ retrack(area, s)
area = newScrollView(area)
addControl(parentWindow, area)
return area
@@ -118,6 +122,24 @@ func areaView_isFlipped_acceptsFirstResponder(self C.id, sel C.SEL) C.BOOL {
}
var (
+ _addTrackingArea = sel_getUid("addTrackingArea:")
+ _removeTrackingArea = sel_getUid("removeTrackingArea:")
+)
+
+func retrack(area C.id, s *sysData) {
+ s.trackingArea = C.makeTrackingArea(area)
+ C.objc_msgSend_id(area, _addTrackingArea, s.trackingArea)
+}
+
+//export areaView_updateTrackingAreas
+func areaView_updateTrackingAreas(self C.id, sel C.SEL) {
+ s := getSysData(self)
+ C.objc_msgSend_id(self, _removeTrackingArea, s.trackingArea)
+ C.objc_msgSend_noargs(s.trackingArea, _release)
+ retrack(self, s)
+}
+
+var (
_NSEvent = objc_getClass("NSEvent")
_modifierFlags = sel_getUid("modifierFlags")
@@ -175,6 +197,7 @@ func areaMouseEvent(self C.id, e C.id, click bool, up bool) {
which = 0 // reset for Held processing below
}
// pressedMouseButtons is a class method; calling objc_msgSend() directly with e as an argument on these will panic (in real Objective-C the compiler can detect [e pressedMouseButtons])
+ // the docs do say don't use this for tracking since it returns the state now, and mouse move events work by tracking, but as far as I can tell dragging the mouse over the inactive window does n ot generate an event on Mac OS X, so :/ (TODO see what happens when the program is the current one; in my own separate tests no harm was done so eh; also no need for this if tracking doesn't touch dragging)
held := C.objc_msgSend_uintret_noargs(_NSEvent, _pressedMouseButtons)
if which != 1 && (held & 1) != 0 { // button 1
me.Held = append(me.Held, 1)
@@ -200,8 +223,8 @@ func areaMouseEvent(self C.id, e C.id, click bool, up bool) {
//export areaView_mouseMoved_mouseDragged
func areaView_mouseMoved_mouseDragged(self C.id, sel C.SEL, e C.id) {
+ // for moving, this is handled by the tracking rect stuff above
// for dragging, if multiple buttons are held, only one of their xxxMouseDragged: messages will be sent, so this is OK to do
- // TODO implement tracking for dragging
areaMouseEvent(self, e, false, false)
}
diff --git a/bleh_darwin.m b/bleh_darwin.m
index b537603..bc44f0f 100644
--- a/bleh_darwin.m
+++ b/bleh_darwin.m
@@ -21,6 +21,7 @@ though this is not always the case.
#include <AppKit/NSBitmapImageRep.h>
#include <AppKit/NSCell.h>
#include <AppKit/NSApplication.h>
+#include <AppKit/NSTrackingArea.h>
/* used by listbox_darwin.go; requires NSString */
id *_NSObservedObjectKey = (id *) (&NSObservedObjectKey);
@@ -43,6 +44,9 @@ static id c_NSFont;
static SEL s_setFont; /* objc_setFont() */
static SEL s_systemFontOfSize;
static SEL s_systemFontSizeForControlSize;
+static id c_NSTrackingArea;
+static SEL s_bounds;
+static SEL s_initTrackingArea;
void initBleh()
{
@@ -60,6 +64,9 @@ void initBleh()
s_setFont = sel_getUid("setFont:");
s_systemFontOfSize = sel_getUid("systemFontOfSize:");
s_systemFontSizeForControlSize = sel_getUid("systemFontSizeForControlSize:");
+ c_NSTrackingArea = objc_getClass("NSTrackingArea");
+ s_bounds = sel_getUid("bounds");
+ s_initTrackingArea = sel_getUid("initWithRect:options:owner:userInfo:");
}
/*
@@ -350,3 +357,25 @@ static NSApplicationTerminateReply __appDelegate_applicationShouldTerminate(id s
void *_appDelegate_applicationShouldTerminate = (void *) __appDelegate_applicationShouldTerminate;
char *encodedTerminateReply = @encode(NSApplicationTerminateReply);
+
+/*
+tracking areas; also here for convenience only
+*/
+
+/* IDK if this is needed; just to be safe */
+static id (*objc_msgSend_initTrackingArea)(id, SEL, NSRect, NSTrackingAreaOptions, id, id) =
+ (id (*)(id, SEL, NSRect, NSTrackingAreaOptions, id, id)) objc_msgSend;
+
+id makeTrackingArea(id area)
+{
+ id trackingArea;
+
+ trackingArea = objc_msgSend(c_NSTrackingArea, s_alloc);
+ trackingArea = (*objc_msgSend_initTrackingArea)(trackingArea, s_initTrackingArea,
+ (*objc_msgSend_stret_rect)(area, s_bounds), /* initWithRect: */
+ /* this bit mask (except for NSTrackingInVisibleRect, which was added later) 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 */
+ (NSTrackingAreaOptions) (NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways | NSTrackingEnabledDuringMouseDrag | NSTrackingInVisibleRect), /* options: */
+ area, /* owner: */
+ nil); /* userData: */
+ return trackingArea;
+}
diff --git a/objc_darwin.go b/objc_darwin.go
index b8d5f8f..c1b610d 100644
--- a/objc_darwin.go
+++ b/objc_darwin.go
@@ -98,6 +98,7 @@ const (
sel_bool
sel_void_rect
sel_terminatereply_id
+ sel_void
nitypes
)
@@ -107,6 +108,7 @@ var itypes = [nitypes][]C.char{
sel_bool: []C.char{'c', '@', ':', 0},
sel_void_rect: nil, // see init() below
sel_terminatereply_id: nil,
+ sel_void: []C.char{'v', '@', ':', 0},
}
func init() {
diff --git a/objc_darwin.h b/objc_darwin.h
index aaca07e..c7a7157 100644
--- a/objc_darwin.h
+++ b/objc_darwin.h
@@ -112,8 +112,10 @@ extern void initBleh();
extern id makeDummyEvent();
/* for area_darwin.go */
+/* TODO apparently ISO C forbids casting a function pointer to a non-function pointer; this will need to change???? */
extern void *_areaView_drawRect;
extern void drawImage(void *, int64_t, int64_t, int64_t, int64_t, int64_t);
+extern id makeTrackingArea(id);
extern struct xpoint getTranslatedEventPoint(id, id);
/* for objc_darwin.go */
diff --git a/sysdata_darwin.go b/sysdata_darwin.go
index 08ca202..0bcf316 100644
--- a/sysdata_darwin.go
+++ b/sysdata_darwin.go
@@ -50,7 +50,6 @@ var (
_initWithContentRect = sel_getUid("initWithContentRect:styleMask:backing:defer:")
_initWithFrame = sel_getUid("initWithFrame:")
_setDelegate = sel_getUid("setDelegate:")
- _setAcceptsMouseMovedEvents = sel_getUid("setAcceptsMouseMovedEvents:")
_makeKeyAndOrderFront = sel_getUid("makeKeyAndOrderFront:")
_orderOut = sel_getUid("orderOut:")
_setHidden = sel_getUid("setHidden:")
@@ -147,8 +146,7 @@ var classTypes = [nctypes]*classData{
C.uintptr_t(_NSBackingStoreBuffered),
C.BOOL(C.YES)) // defer creation of device until we show the window
C.objc_msgSend_id(win, _setDelegate, appDelegate)
- // this is needed for Areas in the window to receive mouse move events
-// C.objc_msgSend_bool(win, _setAcceptsMouseMovedEvents, C.BOOL(C.YES))
+ // we do not need setAcceptsMouseMovedEvents: here since we are using a tracking rect in Areas for that
return win
},
show: func(what C.id) {