Added tracking areas to Area on Mac OS X so mouse move events can work; they work now.

This commit is contained in:
Pietro Gagliardi 2014-05-10 21:03:04 -04:00
parent 5819e52f8d
commit cc01981999
5 changed files with 58 additions and 4 deletions

View File

@ -12,6 +12,7 @@ import (
//// #include <HIToolbox/Events.h> //// #include <HIToolbox/Events.h>
// #include "objc_darwin.h" // #include "objc_darwin.h"
// extern BOOL areaView_isFlipped_acceptsFirstResponder(id, SEL); // extern BOOL areaView_isFlipped_acceptsFirstResponder(id, SEL);
// extern void areaView_updateTrackingAreas(id, SEL);
// extern void areaView_mouseMoved_mouseDragged(id, SEL, id); // extern void areaView_mouseMoved_mouseDragged(id, SEL, id);
// extern void areaView_mouseDown(id, SEL, id); // extern void areaView_mouseDown(id, SEL, id);
// extern void areaView_mouseUp(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"}, "ensuring that an Area's coordinate system has (0,0) at the top-left corner"},
selector{"acceptsFirstResponder", uintptr(C.areaView_isFlipped_acceptsFirstResponder), sel_bool, selector{"acceptsFirstResponder", uintptr(C.areaView_isFlipped_acceptsFirstResponder), sel_bool,
"registering that Areas are to receive events"}, "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, selector{"mouseMoved:", uintptr(C.areaView_mouseMoved_mouseDragged), sel_void_id,
"handling mouse movements in Area"}, "handling mouse movements in Area"},
selector{"mouseDown:", uintptr(C.areaView_mouseDown), sel_void_id, 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 := C.objc_msgSend_noargs(_goArea, _alloc)
area = initWithDummyFrame(area) area = initWithDummyFrame(area)
// TODO others? // TODO others?
retrack(area, s)
area = newScrollView(area) area = newScrollView(area)
addControl(parentWindow, area) addControl(parentWindow, area)
return area return area
@ -117,6 +121,24 @@ func areaView_isFlipped_acceptsFirstResponder(self C.id, sel C.SEL) C.BOOL {
return C.BOOL(C.YES) return C.BOOL(C.YES)
} }
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 ( var (
_NSEvent = objc_getClass("NSEvent") _NSEvent = objc_getClass("NSEvent")
@ -175,6 +197,7 @@ func areaMouseEvent(self C.id, e C.id, click bool, up bool) {
which = 0 // reset for Held processing below 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]) // 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) held := C.objc_msgSend_uintret_noargs(_NSEvent, _pressedMouseButtons)
if which != 1 && (held & 1) != 0 { // button 1 if which != 1 && (held & 1) != 0 { // button 1
me.Held = append(me.Held, 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 //export areaView_mouseMoved_mouseDragged
func areaView_mouseMoved_mouseDragged(self C.id, sel C.SEL, e C.id) { 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 // 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) areaMouseEvent(self, e, false, false)
} }

View File

@ -21,6 +21,7 @@ though this is not always the case.
#include <AppKit/NSBitmapImageRep.h> #include <AppKit/NSBitmapImageRep.h>
#include <AppKit/NSCell.h> #include <AppKit/NSCell.h>
#include <AppKit/NSApplication.h> #include <AppKit/NSApplication.h>
#include <AppKit/NSTrackingArea.h>
/* used by listbox_darwin.go; requires NSString */ /* used by listbox_darwin.go; requires NSString */
id *_NSObservedObjectKey = (id *) (&NSObservedObjectKey); id *_NSObservedObjectKey = (id *) (&NSObservedObjectKey);
@ -43,6 +44,9 @@ static id c_NSFont;
static SEL s_setFont; /* objc_setFont() */ static SEL s_setFont; /* objc_setFont() */
static SEL s_systemFontOfSize; static SEL s_systemFontOfSize;
static SEL s_systemFontSizeForControlSize; static SEL s_systemFontSizeForControlSize;
static id c_NSTrackingArea;
static SEL s_bounds;
static SEL s_initTrackingArea;
void initBleh() void initBleh()
{ {
@ -60,6 +64,9 @@ void initBleh()
s_setFont = sel_getUid("setFont:"); s_setFont = sel_getUid("setFont:");
s_systemFontOfSize = sel_getUid("systemFontOfSize:"); s_systemFontOfSize = sel_getUid("systemFontOfSize:");
s_systemFontSizeForControlSize = sel_getUid("systemFontSizeForControlSize:"); 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; void *_appDelegate_applicationShouldTerminate = (void *) __appDelegate_applicationShouldTerminate;
char *encodedTerminateReply = @encode(NSApplicationTerminateReply); 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;
}

View File

@ -98,6 +98,7 @@ const (
sel_bool sel_bool
sel_void_rect sel_void_rect
sel_terminatereply_id sel_terminatereply_id
sel_void
nitypes nitypes
) )
@ -107,6 +108,7 @@ var itypes = [nitypes][]C.char{
sel_bool: []C.char{'c', '@', ':', 0}, sel_bool: []C.char{'c', '@', ':', 0},
sel_void_rect: nil, // see init() below sel_void_rect: nil, // see init() below
sel_terminatereply_id: nil, sel_terminatereply_id: nil,
sel_void: []C.char{'v', '@', ':', 0},
} }
func init() { func init() {

View File

@ -112,8 +112,10 @@ extern void initBleh();
extern id makeDummyEvent(); extern id makeDummyEvent();
/* for area_darwin.go */ /* 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 *_areaView_drawRect;
extern void drawImage(void *, int64_t, int64_t, int64_t, int64_t, int64_t); extern void drawImage(void *, int64_t, int64_t, int64_t, int64_t, int64_t);
extern id makeTrackingArea(id);
extern struct xpoint getTranslatedEventPoint(id, id); extern struct xpoint getTranslatedEventPoint(id, id);
/* for objc_darwin.go */ /* for objc_darwin.go */

View File

@ -50,7 +50,6 @@ var (
_initWithContentRect = sel_getUid("initWithContentRect:styleMask:backing:defer:") _initWithContentRect = sel_getUid("initWithContentRect:styleMask:backing:defer:")
_initWithFrame = sel_getUid("initWithFrame:") _initWithFrame = sel_getUid("initWithFrame:")
_setDelegate = sel_getUid("setDelegate:") _setDelegate = sel_getUid("setDelegate:")
_setAcceptsMouseMovedEvents = sel_getUid("setAcceptsMouseMovedEvents:")
_makeKeyAndOrderFront = sel_getUid("makeKeyAndOrderFront:") _makeKeyAndOrderFront = sel_getUid("makeKeyAndOrderFront:")
_orderOut = sel_getUid("orderOut:") _orderOut = sel_getUid("orderOut:")
_setHidden = sel_getUid("setHidden:") _setHidden = sel_getUid("setHidden:")
@ -147,8 +146,7 @@ var classTypes = [nctypes]*classData{
C.uintptr_t(_NSBackingStoreBuffered), C.uintptr_t(_NSBackingStoreBuffered),
C.BOOL(C.YES)) // defer creation of device until we show the window C.BOOL(C.YES)) // defer creation of device until we show the window
C.objc_msgSend_id(win, _setDelegate, appDelegate) C.objc_msgSend_id(win, _setDelegate, appDelegate)
// this is needed for Areas in the window to receive mouse move events // we do not need setAcceptsMouseMovedEvents: here since we are using a tracking rect in Areas for that
// C.objc_msgSend_bool(win, _setAcceptsMouseMovedEvents, C.BOOL(C.YES))
return win return win
}, },
show: func(what C.id) { show: func(what C.id) {