Dual-zone multi-touch trackpad input for openFrameworks on macOS
README
ofxDualTouch
Dual-zone multi-touch trackpad input for openFrameworks on macOS.
GLFW/OF do not deliver raw trackpad touch events on macOS, so this addon bridges AppKit's
NSTouch API directly into OF. Two optional zones (left/right half of the window) each track the first finger that touches them, with easing back to a centre point and click-to-lock behaviour, plus a turnkey controller that wires it all together.Requirements
- macOS only for trackpad capture (AppKit
NSTouch). Other platforms build fine
isAvailable() reports false. - openFrameworks 0.12+ (uses
glm).
Quick start (turnkey)
#include "ofxDualTouch.h"
class ofApp : public ofBaseApp {
ofxDualTouchController dualTouch;
void setup() override { dualTouch.setup(); }
void update() override { dualTouch.update(ofGetLastFrameTime()); }
void mousePressed(int x, int y, int button) override { dualTouch.handleMousePressed(x, y, button); }
};The controller owns a capture and two
ofxDualTouchZones:- Left zone centre:
(width split / 2, height / 2) - Right zone centre:
(width (0.5 + split / 2), height / 2)
setup() again in windowResized() — it is idempotent and re-swizzles the touch methods and recomputes zone centres.Raw capture (events + polling)
ofxDualTouchCapture capture;
capture.setup(); // must run after the OF window exists
ofAddListener(capture.touchDown, this, &ofApp::onTouchDown);
// ... capture.touchMoved, capture.touchUp with void onTouch...(ofxDualTouchPoint & p)
for (auto & t : capture.getTouches()) { // polling works too
ofDrawCircle(t.pos.x, t.pos.y, 10);
}ofxDualTouchPoint { int id; glm::vec2 pos; } — pos is in window pixels, y-down (already flipped from AppKit's bottom-left origin).Zones
ofxDualTouchZone implements first-finger-wins tracking plus return-to-centre:touchDown / touchMoved / touchUpfeed it raw points; a zone only accepts the
- On release the circle eases back to its centre over
lerpDurationseconds
toggleLock()/isLocked(): a click turns return-to-centre off; the circle
setLerpDuration(float),setEasing(ofxDualTouchEasingType),setCentre(glm::vec2).- Getters:
getPosition(),getTarget(),getCentre(),getTrail(),
isTouching(), isLerping(), getLerpProgress().Eight easings are provided in
ofxDualTouchEasing.h (default EASE_OUT_QUAD), as enum, names, and std::function table.Examples
example-ofxDualTouchZone(inside this addon) — the full dual-zone prototype
ofxDualTouchController (split, lock, easings, keys). Build with make Release (or make RunRelease) from addons/ofxDualTouch/example-ofxDualTouchZone. examples/input_output/ofxDualTouchExample— minimal raw capture: touch
examples/input_output/ofxDualTouchZoneExample— same dual-zone prototype as
How it works
ofxDualTouchCapture::setup() finds the OF window (ofGetCocoaWindow()) and uses class_replaceMethod to substitute the content view's touchesBegan/Moved/Ended/CancelledWithEvent: implementations. Touches are normalized from NSTouch.normalizedPosition to window pixels, the Y axis is flipped, and each NSTouch.identity is mapped to a sequential integer id that is released when the finger lifts.Note:class_replaceMethodswizzles the view's class directly. If you swizzle
a different GL view class, only the same class is affected.
License
MIT, see
license.md.
ofxAddons