app.dhover×330 error×19all
// macOS/AppKit F11 demo — scroll fidelity (../../../features/f11-scroll.md).
// AppKit hands scrollWheel: one NSEvent carrying THREE representations of the
// same physical scroll: scrollingDeltaX/Y (the modern, possibly pixel-precise
// deltas), deltaX/deltaY (the legacy line-ish units), and the phase /
// momentumPhase pair that turns a stream of events into trackpad gestures.
// This demo logs every field of every scroll event, keeps a scrollable-ruler
// offset, and prints per-gesture summaries keyed on phase transitions.
//
// What it logs (A[ssh]; locked console — no real wheel/trackpad, so events are
// built with CGEventCreateScrollWheelEvent2 and delivered IN-PROCESS via
// +[NSEvent eventWithCGEvent:] + [window sendEvent:], the f06/f07 route-1
// workhorse; the real-fling choreography is Tier C):
//   - per event: scrollingDeltaX/Y, legacy deltaX/deltaY, hasPreciseScrollingDeltas,
//     phase + momentumPhase (NSEventPhase bitmask decoded), and
//     isDirectionInvertedFromDevice;
//   - the unit duality at the CG layer: a line-unit event's synthesized
//     kCGScrollWheelEventDeltaAxis1 / FixedPtDeltaAxis1 / PointDeltaAxis1 /
//     IsContinuous fields read back (where "one notch = deltaY 1.0 =
//     scrollingDeltaY ~10" lives), same for a pixel-unit event;
//   - multi-tick and negative line values; a fractional line delta forced via
//     CGEventSetDoubleValueField(kCGScrollWheelEventFixedPtDeltaAxis1) — the
//     precision-touchpad analog;
//   - the phase probe: CGEventSetIntegerValueField(kCGScrollWheelEventScrollPhase /
//     ...MomentumPhase) with CGScrollPhase/CGMomentumScrollPhase values — does the
//     wrapped NSEvent surface them as NSEventPhase? (the CG->NS phase mapping is
//     the finding);
//   - a scripted synthetic fling: phase began -> changed... -> ended, then
//     momentum began -> changed... -> ended, plus a cancelled variant — each
//     transition driving the gesture summaries;
//   - a scrollable ruler (offset integrated from scrollingDeltaY) drawn in
//     drawRect: (visible pixels are Tier C; the offset is in the log).
//
// Modes: WSI_AUTO_EXIT=1 = bounded scripted run; without it the window stays up
// for a manual (Tier C) wheel/trackpad session. Headless-safe: prints `SKIP:`
// and exits 0 when there is no window server.
module 
(module) app
app
;
import
(package) core
core
.
(module) core.attribute

This module contains UDA's (User Defined Attributes) either used in the runtime or special UDA's recognized by compiler.

Attribute Name, Linkage, Description

gnuAbiTag, C++, Declares an ABI tag on a C++ symbol. mustuse,, Ensures that values of a struct or union type are not discarded. optional, Objective-C, Makes an Objective-C interface method optional. selector, Objective-C, Attaches an Objective-C selector to a method. standalone,, Marks a shared module constructor as not depending on any other module constructor being run first. weak,, Specifies that a global symbol should be emitted with weak linkage.

Source

core/attribute.d

@copyrightCopyright Jacob Carlborg 2015.@licenseBoost License 1.0@authorsJacob Carlborg
attribute
: selector;
module `core.attribute` import `selector` not found
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdio

D header file for C99 <stdio.h>

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h

Source

core/stdc/stdio.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly, Alex Rønne Petersen@standardsISO/IEC 9899:1999 (E)
stdio
:
(alias) app.printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
,
(alias) app.snprintf = int core.stdc.stdio.snprintf(scope char* s, ulong n, scope const(char*) format, scope const ...) nothrow @nogc
snprintf
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdlib

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html, stdlib.h

Source

core/stdc/stdlib.d

@copyrightCopyright Sean Kelly 2005 - 2014.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
stdlib
:
(alias) app.getenv = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
;
import instrument : instr, instrInit;
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
import objc.autorelease : autoreleasepool_push, autoreleasepool_pop; // objective-d
unable to read module `autorelease` Expected 'objc/autorelease.d' or 'objc/autorelease/package.d' in one of the following import paths:
unable to read module `autorelease` Expected 'objc/autorelease.d' or 'objc/autorelease/package.d' in one of the following import paths:
unable to read module `autorelease` Expected 'objc/autorelease.d' or 'objc/autorelease/package.d' in one of the following import paths:
import objc.rt : SEL;
unable to read module `rt` Expected 'objc/rt.d' or 'objc/rt/package.d' in one of the following import paths:
unable to read module `rt` Expected 'objc/rt.d' or 'objc/rt/package.d' in one of the following import paths:
unable to read module `rt` Expected 'objc/rt.d' or 'objc/rt/package.d' in one of the following import paths:
// --- Geometry ---------------------------------------------------------------------- extern (C) struct
(struct) app.NSPoint
NSPoint
{ double
(field) double app.NSPoint.x
x
,
(field) double app.NSPoint.y
y
;
} extern (C) struct
(struct) app.NSSize
NSSize
{ double
(field) double app.NSSize.width
width
,
(field) double app.NSSize.height
height
;
} extern (C) struct
(struct) app.NSRect
NSRect
{
(struct) app.NSPoint
NSPoint
(field) app.NSPoint app.NSRect.origin
origin
;
(struct) app.NSSize
NSSize
(field) app.NSSize app.NSRect.size
size
;
} // --- CoreGraphics C API -------------------------------------------------------------- extern (C) nothrow @nogc { uint
uint app.CGMainDisplayID() nothrow @nogc
CGMainDisplayID
();
(struct) app.NSRect
NSRect
app.NSRect app.CGDisplayBounds(uint display) nothrow @nogc
CGDisplayBounds
(uint
(parameter) uint display
display
);
// The non-variadic scroll constructor (up to 3 axes; we use 2). void*
void* app.CGEventCreateScrollWheelEvent2(void* source, uint units, uint wheelCount, int wheel1, int wheel2, int wheel3) nothrow @nogc
CGEventCreateScrollWheelEvent2
(void*
(parameter) void* source
source
, uint
(parameter) uint units
units
, uint
(parameter) uint wheelCount
wheelCount
,
int
(parameter) int wheel1
wheel1
, int
(parameter) int wheel2
wheel2
, int
(parameter) int wheel3
wheel3
);
void
void app.CGEventSetLocation(void* event, app.NSPoint location) nothrow @nogc
CGEventSetLocation
(void*
(parameter) void* event
event
,
(struct) app.NSPoint
NSPoint
(parameter) app.NSPoint location
location
);
void
void app.CGEventSetIntegerValueField(void* event, uint field, long value) nothrow @nogc
CGEventSetIntegerValueField
(void*
(parameter) void* event
event
, uint
(parameter) uint field
field
, long
(parameter) long value
value
);
long
long app.CGEventGetIntegerValueField(void* event, uint field) nothrow @nogc
CGEventGetIntegerValueField
(void*
(parameter) void* event
event
, uint
(parameter) uint field
field
);
void
void app.CGEventSetDoubleValueField(void* event, uint field, double value) nothrow @nogc
CGEventSetDoubleValueField
(void*
(parameter) void* event
event
, uint
(parameter) uint field
field
, double
(parameter) double value
value
);
double
double app.CGEventGetDoubleValueField(void* event, uint field) nothrow @nogc
CGEventGetDoubleValueField
(void*
(parameter) void* event
event
, uint
(parameter) uint field
field
);
void
void app.CFRelease(void* obj) nothrow @nogc
CFRelease
(void*
(parameter) void* obj
obj
);
void
void app.CGContextSetRGBFillColor(void* ctx, double r, double g, double b, double a) nothrow @nogc
CGContextSetRGBFillColor
(void*
(parameter) void* ctx
ctx
, double
(parameter) double r
r
, double
(parameter) double g
g
, double
(parameter) double b
b
, double
(parameter) double a
a
);
void
void app.CGContextFillRect(void* ctx, app.NSRect rect) nothrow @nogc
CGContextFillRect
(void*
(parameter) void* ctx
ctx
,
(struct) app.NSRect
NSRect
(parameter) app.NSRect rect
rect
);
} enum uint
(constant) uint app.kCGScrollEventUnitPixel = 0u
kCGScrollEventUnitPixel
= 0; // CGScrollEventUnit
enum uint
(constant) uint app.kCGScrollEventUnitLine = 1u
kCGScrollEventUnitLine
= 1;
// CGEventField (CGEventTypes.h), axis 1 = vertical, axis 2 = horizontal. enum : uint {
(enum value) app.kCGScrollWheelEventDeltaAxis1 = 11u
kCGScrollWheelEventDeltaAxis1
= 11, // integer line delta
(enum value) app.kCGScrollWheelEventDeltaAxis2 = 12u
kCGScrollWheelEventDeltaAxis2
= 12,
(enum value) app.kCGScrollWheelEventFixedPtDeltaAxis1 = 93u
kCGScrollWheelEventFixedPtDeltaAxis1
= 93, // 16.16 fixed-point line delta
(enum value) app.kCGScrollWheelEventFixedPtDeltaAxis2 = 94u
kCGScrollWheelEventFixedPtDeltaAxis2
= 94,
(enum value) app.kCGScrollWheelEventPointDeltaAxis1 = 96u
kCGScrollWheelEventPointDeltaAxis1
= 96, // integer pixel delta
(enum value) app.kCGScrollWheelEventPointDeltaAxis2 = 97u
kCGScrollWheelEventPointDeltaAxis2
= 97,
(enum value) app.kCGScrollWheelEventIsContinuous = 88u
kCGScrollWheelEventIsContinuous
= 88, // 1 = pixel-based device (trackpad)
(enum value) app.kCGScrollWheelEventScrollPhase = 99u
kCGScrollWheelEventScrollPhase
= 99, // CGScrollPhase
(enum value) app.kCGScrollWheelEventMomentumPhase = 123u
kCGScrollWheelEventMomentumPhase
= 123, // CGMomentumScrollPhase
} // CGScrollPhase (kCGScrollPhase*: bitmask-style values)... enum : long {
(enum value) app.cgPhaseBegan = 1L
cgPhaseBegan
= 1,
(enum value) app.cgPhaseChanged = 2L
cgPhaseChanged
= 2,
(enum value) app.cgPhaseEnded = 4L
cgPhaseEnded
= 4,
(enum value) app.cgPhaseCancelled = 8L
cgPhaseCancelled
= 8,
(enum value) app.cgPhaseMayBegin = 128L
cgPhaseMayBegin
= 128,
} // ...vs CGMomentumScrollPhase (kCGMomentumScrollPhase*: sequential values). enum : long {
(enum value) app.cgMomentumNone = 0L
cgMomentumNone
= 0,
(enum value) app.cgMomentumBegin = 1L
cgMomentumBegin
= 1,
(enum value) app.cgMomentumContinue = 2L
cgMomentumContinue
= 2,
(enum value) app.cgMomentumEnd = 3L
cgMomentumEnd
= 3,
} // NSEventPhase bitmask (NSEvent.h). enum : ulong {
(enum value) app.NSEventPhaseNone = 0LU
NSEventPhaseNone
= 0,
(enum value) app.NSEventPhaseBegan = 1LU
NSEventPhaseBegan
= 0x1,
(enum value) app.NSEventPhaseStationary = 2LU
NSEventPhaseStationary
= 0x2,
(enum value) app.NSEventPhaseChanged = 4LU
NSEventPhaseChanged
= 0x4,
(enum value) app.NSEventPhaseEnded = 8LU
NSEventPhaseEnded
= 0x8,
(enum value) app.NSEventPhaseCancelled = 16LU
NSEventPhaseCancelled
= 0x10,
(enum value) app.NSEventPhaseMayBegin = 32LU
NSEventPhaseMayBegin
= 0x20,
} // --- AppKit class declarations -------------------------------------------------------- extern (Objective-C): extern class
(class) app.NSObject
NSObject
class `app.NSObject` Objective-C classes not supported
{ } extern class
(class) app.NSString
NSString
:
(class) app.NSObject
NSObject
class `app.NSString` Objective-C classes not supported
{ static
(class) app.NSString
NSString
app.NSString app.NSString.alloc()
alloc
() @selector("alloc");
(class) app.NSString
NSString
app.NSString app.NSString.initWithUTF8String(const(char)* s)
initWithUTF8String
(const(char)*
(parameter) const(char)* s
s
) @selector("initWithUTF8String:");
} extern class
(class) app.NSEvent
NSEvent
:
(class) app.NSObject
NSObject
class `app.NSEvent` Objective-C classes not supported
{ static
(class) app.NSEvent
NSEvent
app.NSEvent app.NSEvent.eventWithCGEvent(void* cgEvent)
eventWithCGEvent
(void*
(parameter) void* cgEvent
cgEvent
) @selector("eventWithCGEvent:");
static
(class) app.NSEvent
NSEvent
app.NSEvent app.NSEvent.otherEventWithType(long type, app.NSPoint location, ulong modifierFlags, double timestamp, long windowNumber, app.NSObject context, short subtype, long data1, long data2)
otherEventWithType
(long
(parameter) long type
type
,
(struct) app.NSPoint
NSPoint
(parameter) app.NSPoint location
location
, ulong
(parameter) ulong modifierFlags
modifierFlags
,
double
(parameter) double timestamp
timestamp
, long
(parameter) long windowNumber
windowNumber
,
(class) app.NSObject
NSObject
(parameter) app.NSObject context
context
, short
(parameter) short subtype
subtype
,
long
(parameter) long data1
data1
, long
(parameter) long data2
data2
)
@selector("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"); long
long app.NSEvent.type()
type
() @selector("type");
(struct) app.NSPoint
NSPoint
app.NSPoint app.NSEvent.locationInWindow()
locationInWindow
() @selector("locationInWindow");
double
double app.NSEvent.deltaX()
deltaX
() @selector("deltaX");
double
double app.NSEvent.deltaY()
deltaY
() @selector("deltaY");
double
double app.NSEvent.scrollingDeltaX()
scrollingDeltaX
() @selector("scrollingDeltaX");
double
double app.NSEvent.scrollingDeltaY()
scrollingDeltaY
() @selector("scrollingDeltaY");
bool
bool app.NSEvent.hasPreciseScrollingDeltas()
hasPreciseScrollingDeltas
() @selector("hasPreciseScrollingDeltas");
ulong
ulong app.NSEvent.phase()
phase
() @selector("phase");
ulong
ulong app.NSEvent.momentumPhase()
momentumPhase
() @selector("momentumPhase");
bool
bool app.NSEvent.isDirectionInvertedFromDevice()
isDirectionInvertedFromDevice
() @selector("isDirectionInvertedFromDevice");
} extern class
(class) app.NSTimer
NSTimer
:
(class) app.NSObject
NSObject
class `app.NSTimer` Objective-C classes not supported
{ static
(class) app.NSTimer
NSTimer
app.NSTimer.scheduledTimerWithTimeInterval
scheduledTimerWithTimeInterval
(double interval,
(class) app.NSObject
NSObject
target,
SEL sel,
(class) app.NSObject
NSObject
userInfo, bool repeats)
@selector("scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:"); } extern class
(class) app.NSApplication
NSApplication
:
(class) app.NSObject
NSObject
class `app.NSApplication` Objective-C classes not supported
{ static
(class) app.NSApplication
NSApplication
app.NSApplication app.NSApplication.sharedApplication()
sharedApplication
() @selector("sharedApplication");
void
void app.NSApplication.setActivationPolicy(long policy)
setActivationPolicy
(long
(parameter) long policy
policy
) @selector("setActivationPolicy:");
void
void app.NSApplication.activateIgnoringOtherApps(bool flag)
activateIgnoringOtherApps
(bool
(parameter) bool flag
flag
) @selector("activateIgnoringOtherApps:");
void
void app.NSApplication.run()
run
() @selector("run");
void
void app.NSApplication.stop(app.NSObject sender)
stop
(
(class) app.NSObject
NSObject
(parameter) app.NSObject sender
sender
) @selector("stop:");
void
void app.NSApplication.postEvent(app.NSEvent event, bool atStart)
postEvent
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent event
event
, bool
(parameter) bool atStart
atStart
) @selector("postEvent:atStart:");
} extern class
(class) app.NSGraphicsContext
NSGraphicsContext
:
(class) app.NSObject
NSObject
class `app.NSGraphicsContext` Objective-C classes not supported
{ static
(class) app.NSGraphicsContext
NSGraphicsContext
app.NSGraphicsContext app.NSGraphicsContext.currentContext()
currentContext
() @selector("currentContext");
void*
void* app.NSGraphicsContext.CGContext()
CGContext
() @selector("CGContext");
} extern class
(class) app.NSView
NSView
:
(class) app.NSObject
NSObject
class `app.NSView` Objective-C classes not supported
{
(struct) app.NSRect
NSRect
app.NSRect app.NSView.bounds()
bounds
() @selector("bounds");
void
void app.NSView.setNeedsDisplay(bool flag)
setNeedsDisplay
(bool
(parameter) bool flag
flag
) @selector("setNeedsDisplay:");
} extern class
(class) app.NSWindow
NSWindow
:
(class) app.NSObject
NSObject
class `app.NSWindow` Objective-C classes not supported
{ static
(class) app.NSWindow
NSWindow
app.NSWindow app.NSWindow.alloc()
alloc
() @selector("alloc");
(class) app.NSWindow
NSWindow
app.NSWindow app.NSWindow.initWithContentRect(app.NSRect contentRect, ulong styleMask, ulong backing, bool defer)
initWithContentRect
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect contentRect
contentRect
, ulong
(parameter) ulong styleMask
styleMask
,
ulong
(parameter) ulong backing
backing
, bool
(parameter) bool defer
defer
) @selector("initWithContentRect:styleMask:backing:defer:");
void
void app.NSWindow.setTitle(app.NSString title)
setTitle
(
(class) app.NSString
NSString
(parameter) app.NSString title
title
) @selector("setTitle:");
void
void app.NSWindow.setContentView(app.NSObject view)
setContentView
(
(class) app.NSObject
NSObject
(parameter) app.NSObject view
view
) @selector("setContentView:");
void
void app.NSWindow.makeKeyAndOrderFront(app.NSObject sender)
makeKeyAndOrderFront
(
(class) app.NSObject
NSObject
(parameter) app.NSObject sender
sender
) @selector("makeKeyAndOrderFront:");
bool
bool app.NSWindow.makeFirstResponder(app.NSObject responder)
makeFirstResponder
(
(class) app.NSObject
NSObject
(parameter) app.NSObject responder
responder
) @selector("makeFirstResponder:");
void
void app.NSWindow.sendEvent(app.NSEvent event)
sendEvent
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent event
event
) @selector("sendEvent:");
long
long app.NSWindow.windowNumber()
windowNumber
() @selector("windowNumber");
(struct) app.NSRect
NSRect
app.NSRect app.NSWindow.frame()
frame
() @selector("frame");
} // The ruler view: logs every scrollWheel: payload and scrolls a tick ruler. class
(class) app.RulerView
RulerView
:
(class) app.NSView
NSView
class `app.RulerView` Objective-C classes not supported
{ static
(class) app.RulerView
RulerView
app.RulerView app.RulerView.alloc()
alloc
() @selector("alloc");
(class) app.RulerView
RulerView
app.RulerView app.RulerView.initWithFrame(app.NSRect frame)
initWithFrame
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect frame
frame
) @selector("initWithFrame:");
void
void app.RulerView.drawRect(app.NSRect dirtyRect)
drawRect
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect dirtyRect
dirtyRect
) @selector("drawRect:")
{ // Tier-C visual aid: ruler ticks every 20 pt (major every 100) offset by // the integrated scroll position, so over/under-scroll is visible. void*
_error_ ctx
ctx
= NSGraphicsContext.
NSGraphicsContext.currentContext
currentContext
().
NSGraphicsContext.currentContext().CGContext
CGContext
();
immutable
_error_ b
b
= this.
this.bounds
bounds
();
CGContextSetRGBFillColor(ctx, 0.12, 0.12, 0.14, 1); CGContextFillRect(ctx, b); immutable
_error_ off
off
= g_offsetY % 20.0;
for (double
_error_ y
y
= -off; y < b.size.height; y += 20)
{ immutable
_error_ absPos
absPos
= y + g_offsetY;
immutable
_error_ major
major
= (cast(long)(absPos / 20 + 0.5)) % 5 == 0;
CGContextSetRGBFillColor(ctx, 0.7, 0.7, 0.75, 1); CGContextFillRect(ctx, NSRect(NSPoint(0, y), NSSize(major ? 60 : 30, 1))); } } void
void app.RulerView.scrollWheel(app.NSEvent e)
scrollWheel
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent e
e
) @selector("scrollWheel:")
{ onScroll(e); } void
void app.RulerView.tick(app.NSTimer t)
tick
(
(class) app.NSTimer
NSTimer
(parameter) app.NSTimer t
t
) @selector("tick:")
{ onStep(); } } extern (D): // back to D linkage enum
(constant) int app.NSApplicationActivationPolicyRegular = 0
NSApplicationActivationPolicyRegular
= 0;
enum : ulong {
(enum value) app.NSWindowStyleMaskTitled = 1LU
NSWindowStyleMaskTitled
= 1,
(enum value) app.NSWindowStyleMaskClosable = 2LU
NSWindowStyleMaskClosable
= 2,
(enum value) app.NSWindowStyleMaskResizable = 8LU
NSWindowStyleMaskResizable
= 8,
} enum ulong
(constant) ulong app.NSBackingStoreBuffered = 2LU
NSBackingStoreBuffered
= 2;
enum long
(constant) long app.NSEventTypeApplicationDefined = 15L
NSEventTypeApplicationDefined
= 15;
// --- Demo state ----------------------------------------------------------------------- __gshared
(class) app.NSApplication
NSApplication
(__gshared global) app.NSApplication app.g_app
g_app
;
__gshared
(class) app.NSWindow
NSWindow
(__gshared global) app.NSWindow app.g_win
g_win
;
__gshared
(class) app.RulerView
RulerView
(__gshared global) app.RulerView app.g_view
g_view
;
__gshared bool
(__gshared global) bool app.g_auto
g_auto
;
__gshared int
(__gshared global) int app.g_step
g_step
;
__gshared int
(__gshared global) int app.g_arrivals
g_arrivals
;
__gshared double
(__gshared global) double app.g_offsetY
g_offsetY
= 0; // ruler position (points)
// Per-gesture accumulators, keyed on phase transitions. __gshared bool
(__gshared global) bool app.g_gestureActive
g_gestureActive
;
__gshared int
(__gshared global) int app.g_gestureEvents
g_gestureEvents
;
__gshared double
(__gshared global) double app.g_gestureScrollY
g_gestureScrollY
= 0,
(__gshared global) double app.g_gestureLegacyY
g_gestureLegacyY
= 0;
__gshared bool
(__gshared global) bool app.g_momentumActive
g_momentumActive
;
__gshared int
(__gshared global) int app.g_momentumEvents
g_momentumEvents
;
__gshared double
(__gshared global) double app.g_momentumScrollY
g_momentumScrollY
= 0;
__gshared int
(__gshared global) int app.g_gestureN
g_gestureN
; // gesture counter
// Decode the NSEventPhase bitmask into a readable token list. void
void app.phaseName(ulong phase, char* buf, ulong cap) nothrow @nogc
phaseName
(ulong
(parameter) ulong phase
phase
, char*
(parameter) char* buf
buf
,
(alias) object.size_t = ulong
size_t
(parameter) ulong cap
cap
) nothrow @nogc
{ if (phase == 0) { snprintf(buf, cap, "none"); return; }
(unresolved type) size_t
size_t
_error_ n
n
= 0;
void
void add(const(char)* t) nothrow @nogc
add
(const(char)*
(parameter) const(char)* t
t
) nothrow @nogc
{ n += snprintf(buf + n, cap - n, "%s%s", n ? "|".ptr : "".ptr, t); } if (phase & NSEventPhaseBegan) add("began"); if (phase & NSEventPhaseStationary) add("stationary"); if (phase & NSEventPhaseChanged) add("changed"); if (phase & NSEventPhaseEnded) add("ended"); if (phase & NSEventPhaseCancelled) add("cancelled"); if (phase & NSEventPhaseMayBegin) add("mayBegin"); } // --- The scrollWheel: funnel ----------------------------------------------------------- void
void app.onScroll(app.NSEvent e)
onScroll
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent e
e
)
{ ++g_arrivals; immutable
_error_ sdx
sdx
= e.
e.scrollingDeltaX
scrollingDeltaX
();
immutable
_error_ sdy
sdy
= e.
e.scrollingDeltaY
scrollingDeltaY
();
immutable
_error_ ldx
ldx
= e.
e.deltaX
deltaX
();
immutable
_error_ ldy
ldy
= e.
e.deltaY
deltaY
();
immutable
_error_ precise
precise
= e.
e.hasPreciseScrollingDeltas
hasPreciseScrollingDeltas
();
immutable
_error_ ph
ph
= e.
e.phase
phase
();
immutable
_error_ mph
mph
= e.
e.momentumPhase
momentumPhase
();
char[64]
_error_ pn
pn
= void,
_error_ mn
mn
= void;
phaseName(ph, pn.ptr, pn.length); phaseName(mph, mn.ptr, mn.length); instr("scroll", "sdx=%.2f sdy=%.2f legacy_dx=%.3f legacy_dy=%.3f precise=%d phase=0x%llx(%s) momentum=0x%llx(%s) inverted=%d", sdx, sdy, ldx, ldy, precise ? 1 : 0, ph, pn.ptr, mph, mn.ptr, e.
e.isDirectionInvertedFromDevice
isDirectionInvertedFromDevice
() ? 1 : 0);
// Ruler: integrate the modern deltas (positive sdy scrolls content up). g_offsetY -= sdy; instr("ruler", "offset_y=%.1f", g_offsetY); g_view.
g_view.setNeedsDisplay
setNeedsDisplay
(true);
// Gesture bookkeeping keyed on the phase transitions. if (ph & NSEventPhaseBegan) { g_gestureActive = true; ++g_gestureN; g_gestureEvents = 0; g_gestureScrollY = g_gestureLegacyY = 0; instr("gesture", "n=%d state=begin", g_gestureN); } if (g_gestureActive) { ++g_gestureEvents; g_gestureScrollY += sdy; g_gestureLegacyY += ldy; } if (ph & (NSEventPhaseEnded | NSEventPhaseCancelled)) { instr("gesture_summary", "n=%d kind=drag end=%s events=%d total_sdy=%.2f total_legacy_dy=%.3f", g_gestureN, (ph & NSEventPhaseCancelled) ? "cancelled".ptr : "ended".ptr, g_gestureEvents, g_gestureScrollY, g_gestureLegacyY); g_gestureActive = false; } if (mph & NSEventPhaseBegan) { g_momentumActive = true; g_momentumEvents = 0; g_momentumScrollY = 0; instr("gesture", "n=%d state=momentum_begin", g_gestureN); } if (g_momentumActive) { ++g_momentumEvents; g_momentumScrollY += sdy; } if (mph & (NSEventPhaseEnded | NSEventPhaseCancelled)) { instr("gesture_summary", "n=%d kind=momentum events=%d total_sdy=%.2f", g_gestureN, g_momentumEvents, g_momentumScrollY); g_momentumActive = false; } if (ph == NSEventPhaseNone && mph == NSEventPhaseNone) instr("gesture_summary", "kind=discrete events=1 sdy=%.2f legacy_dy=%.3f", sdy, ldy); } // --- Synthetic scroll injection ---------------------------------------------------------- // Read back what CG synthesized (or what we forced) at the Quartz layer. void
void app.logCGFields(void* cg, const(char)* label)
logCGFields
(void*
(parameter) void* cg
cg
, const(char)*
(parameter) const(char)* label
label
)
{ instr("cg_fields", "label=%s delta1=%ld fixedpt1=%.3f point1=%ld continuous=%ld phase=%ld momentum=%ld", label, CGEventGetIntegerValueField(cg, kCGScrollWheelEventDeltaAxis1), CGEventGetDoubleValueField(cg, kCGScrollWheelEventFixedPtDeltaAxis1), CGEventGetIntegerValueField(cg, kCGScrollWheelEventPointDeltaAxis1), CGEventGetIntegerValueField(cg, kCGScrollWheelEventIsContinuous), CGEventGetIntegerValueField(cg, kCGScrollWheelEventScrollPhase), CGEventGetIntegerValueField(cg, kCGScrollWheelEventMomentumPhase)); } // Window-content center in CG global coords (top-left-origin), so sendEvent's // hit test can route the wrapped event to the ruler view.
(struct) app.NSPoint
NSPoint
app.NSPoint app.windowCenterCG()
windowCenterCG
()
{ immutable
_error_ wf
wf
= g_win.
g_win.frame
frame
(); // AppKit screen coords, y-up
immutable
_error_ db
db
= CGDisplayBounds(CGMainDisplayID());
return NSPoint(wf.
wf.origin
origin
.
wf.origin.x
x
+ wf.
wf.size
size
.
wf.size.width
width
/ 2,
db.
db.size
size
.
db.size.height
height
- (wf.
wf.origin
origin
.
wf.origin.y
y
+ wf.
wf.size
size
.
wf.size.height
height
/ 2));
} // Build, wrap, dispatch. phase/momentum < 0 = leave the field untouched. void
void app.injectScroll(uint units, int wheel1, long phase, long momentum, const(char)* label, double fixedPtOverride = nan)
injectScroll
(uint
(parameter) uint units
units
, int
(parameter) int wheel1
wheel1
, long
(parameter) long phase
phase
, long
(parameter) long momentum
momentum
,
const(char)*
(parameter) const(char)* label
label
, double
(parameter) double fixedPtOverride
fixedPtOverride
= double.
(constant) double double.nan = nan
nan
)
{ void*
_error_ cg
cg
= CGEventCreateScrollWheelEvent2(null, units, 2, wheel1, 0, 0);
if (cg is null) { instr("inject", "label=%s result=create_failed", label); return; } CGEventSetLocation(cg, windowCenterCG()); if (phase >= 0) CGEventSetIntegerValueField(cg, kCGScrollWheelEventScrollPhase, phase); if (momentum >= 0) CGEventSetIntegerValueField(cg, kCGScrollWheelEventMomentumPhase, momentum); if (fixedPtOverride == fixedPtOverride) // !isNaN CGEventSetDoubleValueField(cg, kCGScrollWheelEventFixedPtDeltaAxis1, fixedPtOverride); instr("inject", "label=%s units=%s wheel1=%d cg_phase=%ld cg_momentum=%ld", label, units == kCGScrollEventUnitLine ? "line".ptr : "pixel".ptr, wheel1, phase, momentum); logCGFields(cg, label);
(unresolved type) NSEvent
NSEvent
_error_ e
e
= NSEvent.
NSEvent.eventWithCGEvent
eventWithCGEvent
(cg);
if (e is null) { instr("wrap", "label=%s result=nil", label); CFRelease(cg); return; } immutable
_error_ before
before
= g_arrivals;
g_win.
g_win.sendEvent
sendEvent
(e);
if (g_arrivals == before) { instr("route", "label=%s sendEvent=not_delivered fallback=direct", label); g_view.
g_view.scrollWheel
scrollWheel
(e);
} else instr("route", "label=%s sendEvent=delivered", label); CFRelease(cg); } // --- The scripted run ---------------------------------------------------------------------- void
void app.stopApp()
stopApp
()
{ instr("step", "name=NSApp_stop"); g_app.
g_app.stop
stop
(null);
(unresolved type) NSEvent
NSEvent
_error_ ev
ev
= NSEvent.
NSEvent.otherEventWithType
otherEventWithType
(NSEventTypeApplicationDefined,
NSPoint(0, 0), 0, 0, 0, null, 0, 0, 0); g_app.
g_app.postEvent
postEvent
(ev, true); // stop: is only checked after an event dispatch
} void
void app.onStep()
onStep
()
{ if (!g_auto) return; switch (g_step) { // -- Unit duality: line-unit (wheel notches) vs pixel-unit (trackpad-like) -- case 0: // one wheel notch up: the deltaY 1.0 / scrollingDeltaY ~10 anchor injectScroll(kCGScrollEventUnitLine, 1, -1, -1, "line_1_notch"); break; case 1: // multi-tick injectScroll(kCGScrollEventUnitLine, 3, -1, -1, "line_3_notches"); break; case 2: // negative (scroll down) injectScroll(kCGScrollEventUnitLine, -2, -1, -1, "line_minus2"); break; case 3: // pixel unit: does the wrapped event turn precise? injectScroll(kCGScrollEventUnitPixel, 10, -1, -1, "pixel_10"); break; case 4: injectScroll(kCGScrollEventUnitPixel, 120, -1, -1, "pixel_120"); break; case 5: // fractional line delta via the 16.16 fixed-point field injectScroll(kCGScrollEventUnitLine, 0, -1, -1, "line_fractional_0.4", 0.4); break; // -- Phase probe: can a CGEvent carry gesture phases into NSEvent? -- case 6: injectScroll(kCGScrollEventUnitPixel, 5, cgPhaseBegan, -1, "phase_began_probe"); break; // -- Full synthetic trackpad fling: drag phases then momentum phases -- case 7: injectScroll(kCGScrollEventUnitPixel, 30, cgPhaseChanged, -1, "fling_changed_30"); break; case 8: injectScroll(kCGScrollEventUnitPixel, 20, cgPhaseChanged, -1, "fling_changed_20"); break; case 9: injectScroll(kCGScrollEventUnitPixel, 0, cgPhaseEnded, -1, "fling_ended"); break; case 10: injectScroll(kCGScrollEventUnitPixel, 15, -1, cgMomentumBegin, "momentum_begin_15"); break; case 11: injectScroll(kCGScrollEventUnitPixel, 8, -1, cgMomentumContinue, "momentum_continue_8"); break; case 12: injectScroll(kCGScrollEventUnitPixel, 3, -1, cgMomentumContinue, "momentum_continue_3"); break; case 13: injectScroll(kCGScrollEventUnitPixel, 0, -1, cgMomentumEnd, "momentum_end"); break; // -- What does a cancelled gesture look like? -- case 14: injectScroll(kCGScrollEventUnitPixel, 4, cgPhaseBegan, -1, "cancel_began"); break; case 15: injectScroll(kCGScrollEventUnitPixel, 0, cgPhaseCancelled, -1, "cancel_cancelled"); break; case 16: instr("totals", "arrivals=%d gestures=%d final_offset_y=%.1f", g_arrivals, g_gestureN, g_offsetY); break; case 17: stopApp(); break; default: break; } ++g_step; } int
int D main()
main
()
{ g_auto = getenv("WSI_AUTO_EXIT") !is null; instrInit("APPKIT_F11"); instr("init_start", "auto_exit=%d", g_auto ? 1 : 0); instr("step", "name=CGMainDisplayID"); if (CGMainDisplayID() == 0) { printf("SKIP: no macOS window server (CGMainDisplayID == 0)\n"); return 0; } auto
_error_ pool
pool
= autoreleasepool_push();
scope (exit) autoreleasepool_pop(pool); g_app = NSApplication.
NSApplication.sharedApplication
sharedApplication
();
g_app.
g_app.setActivationPolicy
setActivationPolicy
(NSApplicationActivationPolicyRegular);
immutable
_error_ contentRect
contentRect
= NSRect(NSPoint(120, 120), NSSize(480, 320));
g_win = NSWindow.
NSWindow.alloc
alloc
().
NSWindow.alloc().initWithContentRect
initWithContentRect
(contentRect,
NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable, NSBackingStoreBuffered, false); g_win.
g_win.setTitle
setTitle
(NSString.
NSString.alloc
alloc
().
NSString.alloc().initWithUTF8String
initWithUTF8String
("wsi-f11-scroll"));
g_view = RulerView.
RulerView.alloc
alloc
().
RulerView.alloc().initWithFrame
initWithFrame
(NSRect(NSPoint(0, 0), contentRect.
contentRect.size
size
));
g_win.
g_win.setContentView
setContentView
(g_view);
g_win.
g_win.makeKeyAndOrderFront
makeKeyAndOrderFront
(null);
g_app.
g_app.activateIgnoringOtherApps
activateIgnoringOtherApps
(true);
g_win.
g_win.makeFirstResponder
makeFirstResponder
(g_view);
instr("window_created", "win_num=%ld", g_win.
g_win.windowNumber
windowNumber
());
instr("step", "name=script_timer_start interval_ms=150"); NSTimer.
NSTimer.scheduledTimerWithTimeInterval
scheduledTimerWithTimeInterval
(0.15, g_view, SEL.register("tick:"), null, true);
instr("step", "name=NSApp_run"); g_app.
g_app.run
run
();
instr("loop_exit", "steps=%d arrivals=%d", g_step, g_arrivals); return 0; }