Moved area_darwin.go to direct Objective-C use.
This commit is contained in:
parent
3e712db2e0
commit
11ef974b48
132
area_darwin.go
132
area_darwin.go
|
@ -11,77 +11,19 @@ import (
|
||||||
// #include <stdlib.h>
|
// #include <stdlib.h>
|
||||||
//// #include <HIToolbox/Events.h>
|
//// #include <HIToolbox/Events.h>
|
||||||
// #include "objc_darwin.h"
|
// #include "objc_darwin.h"
|
||||||
// extern BOOL areaView_isFlipped_acceptsFirstResponder(id, SEL);
|
// #include "area_darwin.h"
|
||||||
// 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);
|
|
||||||
// extern void areaView_keyDown(id, SEL, id);
|
|
||||||
// extern void areaView_keyUp(id, SEL, id);
|
|
||||||
// extern void areaView_flagsChanged(id, SEL, id);
|
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
const (
|
|
||||||
__goArea = "goArea"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_goArea C.id
|
|
||||||
_NSView = objc_getClass("NSView")
|
_NSView = objc_getClass("NSView")
|
||||||
)
|
)
|
||||||
|
|
||||||
var goAreaSels = []selector{
|
|
||||||
selector{"drawRect:", uintptr(C._areaView_drawRect), sel_void_rect,
|
|
||||||
"actually drawing Areas"},
|
|
||||||
selector{"isFlipped", uintptr(C.areaView_isFlipped_acceptsFirstResponder), sel_bool,
|
|
||||||
"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,
|
|
||||||
"handling mouse button 1 presses in Area"},
|
|
||||||
selector{"mouseDragged:", uintptr(C.areaView_mouseMoved_mouseDragged), sel_void_id,
|
|
||||||
"handling mouse button 1 dragging in Area"},
|
|
||||||
selector{"mouseUp:", uintptr(C.areaView_mouseUp), sel_void_id,
|
|
||||||
"handling mouse button 1 releases in Area"},
|
|
||||||
selector{"rightMouseDown:", uintptr(C.areaView_mouseDown), sel_void_id,
|
|
||||||
"handling mouse button 3 presses in Area"},
|
|
||||||
selector{"rightMouseDragged:", uintptr(C.areaView_mouseMoved_mouseDragged), sel_void_id,
|
|
||||||
"handling mouse button 3 dragging in Area"},
|
|
||||||
selector{"rightMouseUp:", uintptr(C.areaView_mouseUp), sel_void_id,
|
|
||||||
"handling mouse button 3 releases in Area"},
|
|
||||||
selector{"otherMouseDown:", uintptr(C.areaView_mouseDown), sel_void_id,
|
|
||||||
"handling mouse button 2 (and 4 and higher) presses in Area"},
|
|
||||||
selector{"otherMouseDragged:", uintptr(C.areaView_mouseMoved_mouseDragged), sel_void_id,
|
|
||||||
"handling mouse button 2 (and 4 and higher) dragging in Area"},
|
|
||||||
selector{"otherMouseUp:", uintptr(C.areaView_mouseUp), sel_void_id,
|
|
||||||
"handling mouse button 2 (and 4 and higher) releases in Area"},
|
|
||||||
selector{"keyDown:", uintptr(C.areaView_keyDown), sel_void_id,
|
|
||||||
"handling key presses in Area"},
|
|
||||||
selector{"keyUp:", uintptr(C.areaView_keyUp), sel_void_id,
|
|
||||||
"handling key releases in Area"},
|
|
||||||
selector{"flagsChanged:", uintptr(C.areaView_flagsChanged), sel_void_id,
|
|
||||||
"handling Modifiers presses and releases in Area"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func mkAreaClass() error {
|
func mkAreaClass() error {
|
||||||
id, err := makeClass(__goArea, _NSView, goAreaSels,
|
|
||||||
"the implementation of Area on Mac OS X")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_goArea = id
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeArea(parentWindow C.id, alternate bool, s *sysData) C.id {
|
func makeArea(parentWindow C.id, alternate bool, s *sysData) C.id {
|
||||||
area := C.objc_msgSend_noargs(_goArea, _alloc)
|
area := C.makeArea()
|
||||||
area = initWithDummyFrame(area)
|
|
||||||
// TODO others?
|
|
||||||
retrack(area, s)
|
|
||||||
area = newScrollView(area)
|
area = newScrollView(area)
|
||||||
addControl(parentWindow, area)
|
addControl(parentWindow, area)
|
||||||
return area
|
return area
|
||||||
|
@ -113,32 +55,11 @@ func areaView_drawRect(self C.id, rect C.struct_xrect) {
|
||||||
C.int64_t(cliprect.Min.X), C.int64_t(cliprect.Min.Y))
|
C.int64_t(cliprect.Min.X), C.int64_t(cliprect.Min.Y))
|
||||||
}
|
}
|
||||||
|
|
||||||
//export areaView_isFlipped_acceptsFirstResponder
|
|
||||||
func areaView_isFlipped_acceptsFirstResponder(self C.id, sel C.SEL) C.BOOL {
|
|
||||||
// yes use the same function for both methods since they're just going to return YES anyway
|
|
||||||
// isFlipped gives us a coordinate system with (0,0) at the top-left
|
|
||||||
// acceptsFirstResponder lets us respond to events
|
|
||||||
return C.BOOL(C.YES)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_addTrackingArea = sel_getUid("addTrackingArea:")
|
_addTrackingArea = sel_getUid("addTrackingArea:")
|
||||||
_removeTrackingArea = sel_getUid("removeTrackingArea:")
|
_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")
|
||||||
|
|
||||||
|
@ -156,7 +77,7 @@ func parseModifiers(e C.id) (m Modifiers) {
|
||||||
_NSCommandKeyMask = 1 << 20
|
_NSCommandKeyMask = 1 << 20
|
||||||
)
|
)
|
||||||
|
|
||||||
mods := uintptr(C.objc_msgSend_uintret_noargs(e, _modifierFlags))
|
mods := uintptr(C.modifierFlags(e))
|
||||||
if (mods & _NSShiftKeyMask) != 0 {
|
if (mods & _NSShiftKeyMask) != 0 {
|
||||||
m |= Shift
|
m |= Shift
|
||||||
}
|
}
|
||||||
|
@ -185,7 +106,7 @@ func areaMouseEvent(self C.id, e C.id, click bool, up bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
me.Modifiers = parseModifiers(e)
|
me.Modifiers = parseModifiers(e)
|
||||||
which := uint(C.objc_msgSend_intret_noargs(e, _buttonNumber)) + 1
|
which := uint(C.buttonNumber(e)) + 1
|
||||||
if which == 3 { // swap middle and right button numbers
|
if which == 3 { // swap middle and right button numbers
|
||||||
which = 2
|
which = 2
|
||||||
} else if which == 2 {
|
} else if which == 2 {
|
||||||
|
@ -199,9 +120,8 @@ func areaMouseEvent(self C.id, e C.id, click bool, up bool) {
|
||||||
} else {
|
} else {
|
||||||
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])
|
|
||||||
// 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)
|
// 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.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)
|
||||||
}
|
}
|
||||||
|
@ -225,19 +145,19 @@ 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, e C.id) {
|
||||||
// for moving, this is handled by the tracking rect stuff above
|
// 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
|
||||||
areaMouseEvent(self, e, false, false)
|
areaMouseEvent(self, e, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export areaView_mouseDown
|
//export areaView_mouseDown
|
||||||
func areaView_mouseDown(self C.id, sel C.SEL, e C.id) {
|
func areaView_mouseDown(self C.id, e C.id) {
|
||||||
areaMouseEvent(self, e, true, false)
|
areaMouseEvent(self, e, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export areaView_mouseUp
|
//export areaView_mouseUp
|
||||||
func areaView_mouseUp(self C.id, sel C.SEL, e C.id) {
|
func areaView_mouseUp(self C.id, e C.id) {
|
||||||
areaMouseEvent(self, e, true, true)
|
areaMouseEvent(self, e, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,60 +165,52 @@ var (
|
||||||
_keyCode = sel_getUid("keyCode")
|
_keyCode = sel_getUid("keyCode")
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleKeyEvent(self C.id, SEL C.SEL, e C.id) {
|
func sendKeyEvent(self C.id, e C.id, ke KeyEvent) bool {
|
||||||
C.objc_msgSendSuper_id(self, _NSView, SEL, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendKeyEvent(self C.id, sel C.SEL, e C.id, ke KeyEvent) {
|
|
||||||
s := getSysData(self)
|
s := getSysData(self)
|
||||||
handled, repaint := s.handler.Key(ke)
|
handled, repaint := s.handler.Key(ke)
|
||||||
if repaint {
|
if repaint {
|
||||||
C.objc_msgSend_noargs(self, _display)
|
C.objc_msgSend_noargs(self, _display)
|
||||||
}
|
}
|
||||||
if !handled {
|
return handled
|
||||||
handleKeyEvent(self, sel, e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func areaKeyEvent(self C.id, sel C.SEL, e C.id, up bool) {
|
func areaKeyEvent(self C.id, e C.id, up bool) bool {
|
||||||
var ke KeyEvent
|
var ke KeyEvent
|
||||||
|
|
||||||
keyCode := uintptr(C.objc_msgSend_ushortret_noargs(e, _keyCode))
|
keyCode := uintptr(C.keyCode(e))
|
||||||
ke, ok := fromKeycode(keyCode)
|
ke, ok := fromKeycode(keyCode)
|
||||||
if !ok {
|
if !ok {
|
||||||
// no such key; modifiers by themselves are handled by -[self flagsChanged:]
|
// no such key; modifiers by themselves are handled by -[self flagsChanged:]
|
||||||
handleKeyEvent(self, sel, e)
|
return false
|
||||||
return
|
|
||||||
}
|
}
|
||||||
// either ke.Key or ke.ExtKey will be set at this point
|
// either ke.Key or ke.ExtKey will be set at this point
|
||||||
ke.Modifiers = parseModifiers(e)
|
ke.Modifiers = parseModifiers(e)
|
||||||
ke.Up = up
|
ke.Up = up
|
||||||
sendKeyEvent(self, sel, e, ke)
|
return sendKeyEvent(self, e, ke)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export areaView_keyDown
|
//export areaView_keyDown
|
||||||
func areaView_keyDown(self C.id, sel C.SEL, e C.id) {
|
func areaView_keyDown(self C.id, e C.id) C.BOOL {
|
||||||
areaKeyEvent(self, sel, e, false)
|
return toBOOL(areaKeyEvent(self, e, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
//export areaView_keyUp
|
//export areaView_keyUp
|
||||||
func areaView_keyUp(self C.id, sel C.SEL, e C.id) {
|
func areaView_keyUp(self C.id, e C.id) C.BOOL {
|
||||||
areaKeyEvent(self, sel, e, true)
|
return toBOOL(areaKeyEvent(self, e, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
//export areaView_flagsChanged
|
//export areaView_flagsChanged
|
||||||
func areaView_flagsChanged(self C.id, sel C.SEL, e C.id) {
|
func areaView_flagsChanged(self C.id, e C.id) C.BOOL {
|
||||||
var ke KeyEvent
|
var ke KeyEvent
|
||||||
|
|
||||||
// Mac OS X sends this event on both key up and key down.
|
// Mac OS X sends this event on both key up and key down.
|
||||||
// Fortunately -[e keyCode] IS valid here, so we can simply map from key code to Modifiers, get the value of [e modifierFlags], the respective bit is set or not — that will give us the up/down state
|
// Fortunately -[e keyCode] IS valid here, so we can simply map from key code to Modifiers, get the value of [e modifierFlags], the respective bit is set or not — that will give us the up/down state
|
||||||
keyCode := uintptr(C.objc_msgSend_ushortret_noargs(e, _keyCode))
|
keyCode := uintptr(C.keyCode(e))
|
||||||
mod, ok := keycodeModifiers[keyCode] // comma-ok form to avoid adding entries
|
mod, ok := keycodeModifiers[keyCode] // comma-ok form to avoid adding entries
|
||||||
if !ok { // unknown modifier; ignore
|
if !ok { // unknown modifier; ignore
|
||||||
handleKeyEvent(self, sel, e)
|
return C.NO
|
||||||
return
|
|
||||||
}
|
}
|
||||||
ke.Modifiers = parseModifiers(e)
|
ke.Modifiers = parseModifiers(e)
|
||||||
ke.Up = (ke.Modifiers & mod) == 0
|
ke.Up = (ke.Modifiers & mod) == 0
|
||||||
sendKeyEvent(self, sel, e, ke)
|
return toBOOL(sendKeyEvent(self, e, ke))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* 13 may 2014 */
|
||||||
|
|
||||||
|
extern id makeArea(void);
|
||||||
|
extern uintptr_t modifierFlags(id);
|
||||||
|
extern struct xpoint getTranslatedEventPoint(id, id);
|
||||||
|
extern intptr_t buttonNumber(id);
|
||||||
|
extern uintptr_t pressedMouseButtons(void);
|
||||||
|
extern uintptr_t keyCode(id);
|
|
@ -0,0 +1,123 @@
|
||||||
|
// 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 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 = makeTrackingArea(self); // TODO make inline
|
||||||
|
[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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO move getTranslatedEventPoint() here
|
||||||
|
|
||||||
|
intptr_t buttonNumber(id e)
|
||||||
|
{
|
||||||
|
return fromNSInteger([toNSEvent(e) buttonNumber]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t pressedMouseButtons(void)
|
||||||
|
{
|
||||||
|
return fromNSUInteger([NSEvent pressedMouseButtons]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t keyCode(id e)
|
||||||
|
{
|
||||||
|
return (uintptr_t) ([toNSEvent(e) keyCode]);
|
||||||
|
}
|
Loading…
Reference in New Issue