app.dhover×459 error×21all
// macOS/AppKit F06 demo — keyboard & keymap (../../../features/f06-keyboard.md).
// Scancode -> keysym -> text is three different questions, and AppKit splits the work
// between the hardware keyCode, the layout engine (UCKeyTranslate / the `uchr` data),
// and the text-input layer (interpretKeyEvents: -> insertText:/doCommandBySelector:).
// This demo logs all three levels and probes the boundaries.
//
// A custom NSView (KeyView, acceptsFirstResponder = YES) logs keyDown:/keyUp:/
// flagsChanged: as `key code=<scancode> sym=<charsIgnoringMods> text=<characters>
// state=down|up repeat=0|1`, then routes each keyDown through interpretKeyEvents:,
// implementing insertText:replacementRange:, the legacy insertText:, and
// doCommandBySelector: — logging which one the text system actually calls (the
// NSTextInputClient marked-text methods are F07; here we observe what arrives without
// them, which is the boundary finding F07 builds on).
//
// Three demonstrations, choreographed under WSI_AUTO_EXIT=1:
//   1. Layout engine (synchronous, no run loop / injection — robust over SSH):
//      UCKeyTranslate on the current `uchr` proves the three-level split (keyCode 0 ->
//      "a"; +shift -> "A"; option-e sets a deadKeyState + no text, then keyCode 14
//      composes "é"); an installed German `uchr` is pulled WITHOUT switching to show
//      the same scancode (keyCode 6) yield 'z' US vs 'y' QWERTZ; a TISSelectInputSource
//      switch is attempted and its OSStatus captured.
//   2. App-side chain (route 1 — synthetic NSEvent + [window sendEvent:], always works
//      in-process): a letter, shifted digit ('!'), arrow (-> doCommandBySelector:), the
//      option-e + e dead-key pair, and a repeat (isARepeat:YES) — logging what
//      interpretKeyEvents: forwards to insertText:/doCommandBySelector:.
//   3. Real HID injection (route 2 — CGEventPost): does it reach keyDown: under a
//      locked screen / over SSH? Either outcome is a finding.
// Also logs NSEvent.keyRepeatDelay / .keyRepeatInterval (the system repeat contract).
//
// 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.config

D compatible types that correspond to various basic types in associated C and C++ compilers.

Source

core/stdc/config.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
config
: c_ulong;
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
;
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
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.string

D header file for C99.

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

Source

core/stdc/string.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
string
:
(alias) app.strstr = inout(char)* core.stdc.string.strstr(return scope inout(char)* s1, scope const(char*) s2) pure nothrow @nogc
strstr
;
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:
// --- Carbon / CoreFoundation C API (layout engine + input sources) -------------- // UCKeyTranslate, the TIS* functions, LMGetKbdType, and the kTISProperty* globals // live in Carbon (HIToolbox); the build links `-framework Carbon` in addition to // Cocoa. CFData/CFArray/CFString helpers come with CoreFoundation (via Cocoa). alias
(alias) app.OSStatus = int
OSStatus
= int;
alias
(alias) app.TISInputSourceRef = void*
TISInputSourceRef
= void*;
alias
(alias) app.CFStringRef = void*
CFStringRef
= void*;
alias
(alias) app.CFDataRef = void*
CFDataRef
= void*;
alias
(alias) app.CFArrayRef = void*
CFArrayRef
= void*;
extern (C) nothrow @nogc { uint
uint app.CGMainDisplayID() nothrow @nogc
CGMainDisplayID
();
(alias) app.TISInputSourceRef = void*
TISInputSourceRef
void* app.TISCopyCurrentKeyboardLayoutInputSource() nothrow @nogc
TISCopyCurrentKeyboardLayoutInputSource
();
void*
void* app.TISGetInputSourceProperty(void* source, void* key) nothrow @nogc
TISGetInputSourceProperty
(
(alias) app.TISInputSourceRef = void*
TISInputSourceRef
(parameter) void* source
source
,
(alias) app.CFStringRef = void*
CFStringRef
(parameter) void* key
key
);
(alias) app.CFArrayRef = void*
CFArrayRef
void* app.TISCreateInputSourceList(void* properties, bool includeAllInstalled) nothrow @nogc
TISCreateInputSourceList
(void*
(parameter) void* properties
properties
, bool
(parameter) bool includeAllInstalled
includeAllInstalled
);
(alias) app.OSStatus = int
OSStatus
int app.TISSelectInputSource(void* source) nothrow @nogc
TISSelectInputSource
(
(alias) app.TISInputSourceRef = void*
TISInputSourceRef
(parameter) void* source
source
);
extern __gshared
(alias) app.CFStringRef = void*
CFStringRef
(__gshared global) void* app.kTISPropertyUnicodeKeyLayoutData
kTISPropertyUnicodeKeyLayoutData
;
extern __gshared
(alias) app.CFStringRef = void*
CFStringRef
(__gshared global) void* app.kTISPropertyInputSourceID
kTISPropertyInputSourceID
;
const(ubyte)*
const(ubyte)* app.CFDataGetBytePtr(void* d) nothrow @nogc
CFDataGetBytePtr
(
(alias) app.CFDataRef = void*
CFDataRef
(parameter) void* d
d
);
long
long app.CFArrayGetCount(void* a) nothrow @nogc
CFArrayGetCount
(
(alias) app.CFArrayRef = void*
CFArrayRef
(parameter) void* a
a
);
const(void)*
const(void)* app.CFArrayGetValueAtIndex(void* a, long idx) nothrow @nogc
CFArrayGetValueAtIndex
(
(alias) app.CFArrayRef = void*
CFArrayRef
(parameter) void* a
a
, long
(parameter) long idx
idx
);
bool
bool app.CFStringGetCString(void* s, char* buf, long bufSize, uint encoding) nothrow @nogc
CFStringGetCString
(
(alias) app.CFStringRef = void*
CFStringRef
(parameter) void* s
s
, char*
(parameter) char* buf
buf
, long
(parameter) long bufSize
bufSize
, uint
(parameter) uint encoding
encoding
);
void
void app.CFRelease(void* o) nothrow @nogc
CFRelease
(void*
(parameter) void* o
o
);
uint
uint app.LMGetKbdType() nothrow @nogc
LMGetKbdType
();
(alias) app.OSStatus = int
OSStatus
int app.UCKeyTranslate(const(void)* keyLayoutPtr, ushort virtualKeyCode, ushort keyAction, uint modifierKeyState, uint keyboardType, uint keyTranslateOptions, uint* deadKeyState, ulong maxStringLength, ulong* actualStringLength, ushort* unicodeString) nothrow @nogc
UCKeyTranslate
(const(void)*
(parameter) const(void)* keyLayoutPtr
keyLayoutPtr
, ushort
(parameter) ushort virtualKeyCode
virtualKeyCode
,
ushort
(parameter) ushort keyAction
keyAction
, uint
(parameter) uint modifierKeyState
modifierKeyState
, uint
(parameter) uint keyboardType
keyboardType
,
uint
(parameter) uint keyTranslateOptions
keyTranslateOptions
, uint*
(parameter) uint* deadKeyState
deadKeyState
, c_ulong
(parameter) ulong maxStringLength
maxStringLength
,
c_ulong*
(parameter) ulong* actualStringLength
actualStringLength
, ushort*
(parameter) ushort* unicodeString
unicodeString
);
// CoreGraphics event injection (route 2) void*
void* app.CGEventCreateKeyboardEvent(void* source, ushort vk, bool keyDown) nothrow @nogc
CGEventCreateKeyboardEvent
(void*
(parameter) void* source
source
, ushort
(parameter) ushort vk
vk
, bool
(parameter) bool keyDown
keyDown
);
void
void app.CGEventPost(uint tapLocation, void* event) nothrow @nogc
CGEventPost
(uint
(parameter) uint tapLocation
tapLocation
, void*
(parameter) void* event
event
);
void
void app.CGEventSetFlags(void* event, ulong flags) nothrow @nogc
CGEventSetFlags
(void*
(parameter) void* event
event
, ulong
(parameter) ulong flags
flags
);
} enum ushort
(constant) ushort app.kUCKeyActionDown = cast(ushort)0u
kUCKeyActionDown
= 0;
enum uint
(constant) uint app.kCFStringEncodingUTF8 = 134217984u
kCFStringEncodingUTF8
= 0x0800_0100;
enum uint
(constant) uint app.kCGHIDEventTap = 0u
kCGHIDEventTap
= 0;
enum uint
(constant) uint app.kCGSessionEventTap = 1u
kCGSessionEventTap
= 1;
// UCKeyTranslate modifier-key state is the classic high-byte modifiers >> 8. enum uint
(constant) uint app.uckShift = 2u
uckShift
= 2; // shiftKey (0x0200) >> 8
enum uint
(constant) uint app.uckOption = 8u
uckOption
= 8; // optionKey (0x0800) >> 8
// --- Cocoa geometry / NSRange --------------------------------------------------- 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
;
} extern (C) struct
(struct) app.NSRange
NSRange
{ ulong
(field) ulong app.NSRange.location
location
,
(field) ulong app.NSRange.length
length
; // NSUInteger
} // --- 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:");
const(char)*
const(char)* app.NSString.UTF8String()
UTF8String
() @selector("UTF8String");
} extern class
(class) app.NSArray
NSArray
:
(class) app.NSObject
NSObject
class `app.NSArray` Objective-C classes not supported
{ static
(class) app.NSArray
NSArray
app.NSArray app.NSArray.arrayWithObject(app.NSObject o)
arrayWithObject
(
(class) app.NSObject
NSObject
(parameter) app.NSObject o
o
) @selector("arrayWithObject:");
} extern class
(class) app.NSResponder
NSResponder
:
(class) app.NSObject
NSObject
class `app.NSResponder` Objective-C classes not supported
{ void
void app.NSResponder.interpretKeyEvents(app.NSArray events)
interpretKeyEvents
(
(class) app.NSArray
NSArray
(parameter) app.NSArray events
events
) @selector("interpretKeyEvents:");
} 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.keyEventWithType(long type, app.NSPoint location, ulong modifierFlags, double timestamp, long windowNumber, app.NSObject context, app.NSString characters, app.NSString charactersIgnoringModifiers, bool isARepeat, ushort keyCode)
keyEventWithType
(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
,
(class) app.NSString
NSString
(parameter) app.NSString characters
characters
,
(class) app.NSString
NSString
(parameter) app.NSString charactersIgnoringModifiers
charactersIgnoringModifiers
, bool
(parameter) bool isARepeat
isARepeat
, ushort
(parameter) ushort keyCode
keyCode
)
@selector("keyEventWithType:location:modifierFlags:timestamp:windowNumber:context:characters:charactersIgnoringModifiers:isARepeat:keyCode:"); ushort
ushort app.NSEvent.keyCode()
keyCode
() @selector("keyCode");
(class) app.NSString
NSString
app.NSString app.NSEvent.characters()
characters
() @selector("characters");
(class) app.NSString
NSString
app.NSString app.NSEvent.charactersIgnoringModifiers()
charactersIgnoringModifiers
() @selector("charactersIgnoringModifiers");
bool
bool app.NSEvent.isARepeat()
isARepeat
() @selector("isARepeat");
ulong
ulong app.NSEvent.modifierFlags()
modifierFlags
() @selector("modifierFlags");
static double
double app.NSEvent.keyRepeatDelay()
keyRepeatDelay
() @selector("keyRepeatDelay");
static double
double app.NSEvent.keyRepeatInterval()
keyRepeatInterval
() @selector("keyRepeatInterval");
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:"); } 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
(parameter) NSObject target
target
,
SEL sel,
(class) app.NSObject
NSObject
userInfo, bool repeats)
@selector("scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:"); } extern class
(class) app.NSApplication
NSApplication
:
(class) app.NSResponder
NSResponder
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.NSView
NSView
:
(class) app.NSResponder
NSResponder
class `app.NSView` Objective-C classes not supported
{ bool
bool app.NSView.acceptsFirstResponder()
acceptsFirstResponder
() @selector("acceptsFirstResponder");
} extern class
(class) app.NSWindow
NSWindow
:
(class) app.NSResponder
NSResponder
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");
} // The custom view: logs the three key levels and routes through the text system. class
(class) app.KeyView
KeyView
:
(class) app.NSView
NSView
class `app.KeyView` Objective-C classes not supported
{ static
(class) app.KeyView
KeyView
app.KeyView app.KeyView.alloc()
alloc
() @selector("alloc");
(class) app.KeyView
KeyView
app.KeyView app.KeyView.initWithFrame(app.NSRect frame)
initWithFrame
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect frame
frame
) @selector("initWithFrame:");
override bool
bool app.KeyView.acceptsFirstResponder()
acceptsFirstResponder
() @selector("acceptsFirstResponder")
{ return true; } void
void app.KeyView.keyDown(app.NSEvent e)
keyDown
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent e
e
) @selector("keyDown:")
{ logKey("down", e); if (e.
e.keyCode
keyCode
() == g_cgWatchCode)
g_cgArrived = true; // Route through the text-input system: this is what turns keysym-level events // into insertText:/doCommandBySelector: callbacks. instr("step", "name=interpretKeyEvents code=%u", e.
e.keyCode
keyCode
());
this.
this.interpretKeyEvents
interpretKeyEvents
(NSArray.
NSArray.arrayWithObject
arrayWithObject
(e));
} void
void app.KeyView.keyUp(app.NSEvent e)
keyUp
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent e
e
) @selector("keyUp:")
{ logKey("up", e); } void
void app.KeyView.flagsChanged(app.NSEvent e)
flagsChanged
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent e
e
) @selector("flagsChanged:")
{ instr("flags_changed", "code=%u flags=0x%llx", e.
e.keyCode
keyCode
(), e.
e.modifierFlags
modifierFlags
());
} // Modern NSTextInputClient text insertion (the one F07 will round out). void
void app.KeyView.insertText_(app.NSString s, app.NSRange r)
insertText_
(
(class) app.NSString
NSString
(parameter) app.NSString s
s
,
(struct) app.NSRange
NSRange
(parameter) app.NSRange r
r
) @selector("insertText:replacementRange:")
{ instr("insert_text", "variant=replacementRange text=%s loc=%llu len=%llu", s !is null ? s.
s.UTF8String
UTF8String
() : "", r.
r.location
location
, r.
r.length
length
);
} // Legacy single-argument insertText: (pre-NSTextInputClient NSResponder path). void
void app.KeyView.insertTextLegacy(app.NSObject s)
insertTextLegacy
(
(class) app.NSObject
NSObject
(parameter) app.NSObject s
s
) @selector("insertText:")
{ auto
_error_ str
str
= cast(
(unresolved type) NSString
NSString
) s;
instr("insert_text", "variant=legacy text=%s", str !is null ? str.
str.UTF8String
UTF8String
() : "");
} void
app.KeyView.doCommandBySelector
doCommandBySelector
(SEL sel) @selector("doCommandBySelector:")
{ instr("do_command", "selector=%s", sel.name); } } 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.NSEventTypeKeyDown = 10L
NSEventTypeKeyDown
= 10;
enum long
(constant) long app.NSEventTypeKeyUp = 11L
NSEventTypeKeyUp
= 11;
enum long
(constant) long app.NSEventTypeApplicationDefined = 15L
NSEventTypeApplicationDefined
= 15;
enum : ulong {
(enum value) app.NSEventModifierFlagShift = 131072LU
NSEventModifierFlagShift
= 1UL << 17,
(enum value) app.NSEventModifierFlagControl = 262144LU
NSEventModifierFlagControl
= 1UL << 18,
(enum value) app.NSEventModifierFlagOption = 524288LU
NSEventModifierFlagOption
= 1UL << 19,
(enum value) app.NSEventModifierFlagCommand = 1048576LU
NSEventModifierFlagCommand
= 1UL << 20,
(enum value) app.NSEventModifierFlagNumericPad = 2097152LU
NSEventModifierFlagNumericPad
= 1UL << 21,
(enum value) app.NSEventModifierFlagFunction = 8388608LU
NSEventModifierFlagFunction
= 1UL << 23,
} enum ulong
(constant) ulong app.kCGEventFlagMaskAlternate = 524288LU
kCGEventFlagMaskAlternate
= 1UL << 19; // option, for CGEvent route
// --- 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.KeyView
KeyView
(__gshared global) app.KeyView app.g_view
g_view
;
__gshared long
(__gshared global) long app.g_winNum
g_winNum
;
__gshared int
(__gshared global) int app.g_step
g_step
;
__gshared ushort
(__gshared global) ushort app.g_cgWatchCode
g_cgWatchCode
= 2; // 'd' on US ANSI — used only by route 2
__gshared bool
(__gshared global) bool app.g_cgArrived
g_cgArrived
;
// Route-1 synthetic key script. `chars`/`charsNoMod` are D string literals (always // NUL-terminated), so `.ptr` is a valid C string for initWithUTF8String. struct
(struct) app.KeySpec
KeySpec
{ ushort
(field) ushort app.KeySpec.code
code
;
ulong
(field) ulong app.KeySpec.flags
flags
;
(alias) object.string = string
string
(field) string app.KeySpec.chars
chars
; // -[NSEvent characters]
(alias) object.string = string
string
(field) string app.KeySpec.charsNoMod
charsNoMod
; // -[NSEvent charactersIgnoringModifiers]
bool
(field) bool app.KeySpec.repeat
repeat
;
(alias) object.string = string
string
(field) string app.KeySpec.label
label
;
} // keyCode 18 = '1', 123 = LeftArrow, 14 = 'e'. The option-e event carries the spacing // acute U+00B4 in `characters` (what a US dead-acute keyDown reports); the boundary // question is whether interpretKeyEvents re-composes "é" or just forwards it. immutable
(struct) app.KeySpec
KeySpec
[]
(immutable global) immutable(app.KeySpec[]) app.g_script
g_script
= [
(struct) app.KeySpec
KeySpec
(0, 0, "a", "a", false, "letter_a"),
(struct) app.KeySpec
KeySpec
(18,
(enum value) app.NSEventModifierFlagShift = 131072LU
NSEventModifierFlagShift
, "!", "1", false, "shift_1_bang"),
(struct) app.KeySpec
KeySpec
(123,
(enum value) app.NSEventModifierFlagFunction = 8388608LU
NSEventModifierFlagFunction
|
(enum value) app.NSEventModifierFlagNumericPad = 2097152LU
NSEventModifierFlagNumericPad
,
"", "", false, "arrow_left"),
(struct) app.KeySpec
KeySpec
(14,
(enum value) app.NSEventModifierFlagOption = 524288LU
NSEventModifierFlagOption
, "´", "e", false, "opt_e_deadacute"),
(struct) app.KeySpec
KeySpec
(14, 0, "e", "e", false, "e_after_dead"),
(struct) app.KeySpec
KeySpec
(0, 0, "a", "a", true, "repeat_a"),
];
(class) app.NSEvent
NSEvent
app.NSEvent app.makeKey(long type, in app.KeySpec k)
makeKey
(long
(parameter) long type
type
, in
(struct) app.KeySpec
KeySpec
(parameter) const(app.KeySpec) k
k
)
{
(unresolved type) NSString
NSString
_error_ ch
ch
= NSString.
NSString.alloc
alloc
().
NSString.alloc().initWithUTF8String
initWithUTF8String
(k.
k.chars
chars
.ptr);
(unresolved type) NSString
NSString
_error_ cm
cm
= NSString.
NSString.alloc
alloc
().
NSString.alloc().initWithUTF8String
initWithUTF8String
(k.
k.charsNoMod
charsNoMod
.ptr);
return NSEvent.
NSEvent.keyEventWithType
keyEventWithType
(type, NSPoint(0, 0), k.
k.flags
flags
, 0, g_winNum, null,
ch, cm, k.
k.repeat
repeat
, k.
k.code
code
);
} void
void app.logKey(const(char)* state, app.NSEvent e)
logKey
(const(char)*
(parameter) const(char)* state
state
,
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent e
e
)
{
(unresolved type) NSString
NSString
_error_ sym
sym
= e.
e.charactersIgnoringModifiers
charactersIgnoringModifiers
();
(unresolved type) NSString
NSString
_error_ txt
txt
= e.
e.characters
characters
();
instr("key", "code=%u sym=%s text=%s state=%s repeat=%d flags=0x%llx", e.
e.keyCode
keyCode
(), sym !is null ? sym.
sym.UTF8String
UTF8String
() : "",
txt !is null ? txt.
txt.UTF8String
UTF8String
() : "", state, e.
e.isARepeat
isARepeat
() ? 1 : 0,
e.
e.modifierFlags
modifierFlags
());
} // --- UCKeyTranslate layout-engine demonstration (synchronous) ------------------- // BMP-only UTF-16 -> UTF-8 (enough for a/A/é/z/y); writes a NUL-terminated C string. void
void app.utf16ToUtf8(const(ushort)* s, ulong n, char* o) nothrow @nogc
utf16ToUtf8
(const(ushort)*
(parameter) const(ushort)* s
s
,
(alias) object.size_t = ulong
size_t
(parameter) ulong n
n
, char*
(parameter) char* o
o
) nothrow @nogc
{
(unresolved type) size_t
size_t
_error_ j
j
= 0;
foreach (
(parameter) i
i
; 0 .. n)
{ immutable uint
_error_ c
c
= s[i];
if (c < 0x80) o[j++] = cast(char) c; else if (c < 0x800) { o[j++] = cast(char)(0xC0 | (c >> 6)); o[j++] = cast(char)(0x80 | (c & 0x3F)); } else { o[j++] = cast(char)(0xE0 | (c >> 12)); o[j++] = cast(char)(0x80 | ((c >> 6) & 0x3F)); o[j++] = cast(char)(0x80 | (c & 0x3F)); } } o[j] = 0; } // One UCKeyTranslate call; returns the number of UTF-16 units produced and updates // *deadState (kept across calls so a dead key can compose with the next press).
(alias) object.size_t = ulong
size_t
ulong app.uck(const(void)* layout, ushort vk, uint modState, uint* deadState, ushort* outUtf16, ulong cap) nothrow @nogc
uck
(const(void)*
(parameter) const(void)* layout
layout
, ushort
(parameter) ushort vk
vk
, uint
(parameter) uint modState
modState
, uint*
(parameter) uint* deadState
deadState
,
ushort*
(parameter) ushort* outUtf16
outUtf16
,
(alias) object.size_t = ulong
size_t
(parameter) ulong cap
cap
) nothrow @nogc
{ c_ulong
_error_ actual
actual
= 0;
UCKeyTranslate(layout, vk, kUCKeyActionDown, modState, LMGetKbdType(), 0, deadState, cap, &actual, outUtf16); return cast(
(unresolved type) size_t
size_t
) actual;
} void
void app.layoutDemo(const(void)* layout, const(char)* label)
layoutDemo
(const(void)*
(parameter) const(void)* layout
layout
, const(char)*
(parameter) const(char)* label
label
)
{ ushort[8]
_error_ u
u
;
char[32]
_error_ s
s
;
uint
_error_ dead
dead
;
dead = 0; auto
_error_ n
n
= uck(layout, 0, 0, &dead, u.ptr, u.
u.length
length
);
utf16ToUtf8(u.ptr, n, s.ptr); instr("uckey", "layout=%s code=0 mods=none text=%s", label, s.ptr); dead = 0; n = uck(layout, 0, uckShift, &dead, u.ptr, u.
u.length
length
);
utf16ToUtf8(u.ptr, n, s.ptr); instr("uckey", "layout=%s code=0 mods=shift text=%s", label, s.ptr); // keyCode 6: 'z' on US ANSI, 'y' on German QWERTZ — same scancode, different text. dead = 0; n = uck(layout, 6, 0, &dead, u.ptr, u.
u.length
length
);
utf16ToUtf8(u.ptr, n, s.ptr); instr("uckey", "layout=%s code=6 mods=none text=%s", label, s.ptr); // Dead key: option-e sets a dead state and emits nothing... dead = 0; n = uck(layout, 14, uckOption, &dead, u.ptr, u.
u.length
length
);
utf16ToUtf8(u.ptr, n, s.ptr); instr("compose", "layout=%s state=dead_set code=14 mods=option dead_state=%u text_len=%zu text=%s", label, dead, n, s.ptr); // ...then the next 'e' composes "é" using the retained dead state. n = uck(layout, 14, 0, &dead, u.ptr, u.
u.length
length
);
utf16ToUtf8(u.ptr, n, s.ptr); instr("compose", "layout=%s state=composed code=14 mods=none dead_state=%u text=%s", label, dead, s.ptr); } const(void)*
const(void)* app.layoutData(void* src)
layoutData
(
(alias) app.TISInputSourceRef = void*
TISInputSourceRef
(parameter) void* src
src
)
{ if (src is null) return null;
(unresolved type) CFDataRef
CFDataRef
_error_ d
d
= cast(
(unresolved type) CFDataRef
CFDataRef
) TISGetInputSourceProperty(src, kTISPropertyUnicodeKeyLayoutData);
return d is null ? null : cast(const(void)*) CFDataGetBytePtr(d); } void
void app.sourceId(void* src, char* buf, long bufSize)
sourceId
(
(alias) app.TISInputSourceRef = void*
TISInputSourceRef
(parameter) void* src
src
, char*
(parameter) char* buf
buf
, long
(parameter) long bufSize
bufSize
)
{ buf[0] = 0; if (src is null) return;
(unresolved type) CFStringRef
CFStringRef
_error_ id
id
= cast(
(unresolved type) CFStringRef
CFStringRef
) TISGetInputSourceProperty(src, kTISPropertyInputSourceID);
if (id !is null) CFStringGetCString(id, buf, bufSize, kCFStringEncodingUTF8); } void
void app.runLayoutDemos()
runLayoutDemos
()
{ instr("repeat_info", "delay_s=%.3f interval_s=%.3f", NSEvent.
NSEvent.keyRepeatDelay
keyRepeatDelay
(), NSEvent.
NSEvent.keyRepeatInterval
keyRepeatInterval
());
(unresolved type) TISInputSourceRef
TISInputSourceRef
_error_ cur
cur
= TISCopyCurrentKeyboardLayoutInputSource();
char[256]
_error_ idbuf
idbuf
;
sourceId(cur, idbuf.ptr, idbuf.
idbuf.length
length
);
instr("input_source", "role=current id=%s", idbuf.ptr); const(void)*
_error_ curLayout
curLayout
= layoutData(cur);
if (curLayout !is null) layoutDemo(curLayout, "current"); else instr("uckey", "layout=current text=<no_uchr> note=current_source_has_no_unicode_layout"); // Enumerate installed sources; pull a German keylayout's uchr WITHOUT switching.
(unresolved type) CFArrayRef
CFArrayRef
_error_ list
list
= TISCreateInputSourceList(null, true);
(unresolved type) TISInputSourceRef
TISInputSourceRef
_error_ german
german
= null;
if (list !is null) { immutable
_error_ count
count
= CFArrayGetCount(list);
foreach (
(parameter) i
i
; 0 .. count)
{ auto
_error_ src
src
= cast(
(unresolved type) TISInputSourceRef
TISInputSourceRef
) CFArrayGetValueAtIndex(list, i);
sourceId(src, idbuf.ptr, idbuf.
idbuf.length
length
);
if (strstr(idbuf.ptr, "German") !is null && layoutData(src) !is null) { german = src; break; } } } if (german !is null) { sourceId(german, idbuf.ptr, idbuf.
idbuf.length
length
);
instr("input_source", "role=german_found id=%s", idbuf.ptr); layoutDemo(layoutData(german), "german"); // Attempt a runtime system layout switch and capture the status. immutable
_error_ st
st
= TISSelectInputSource(german);
instr("layout_switch", "target=german status=%d note=%s", st, st == 0 ? "selected".ptr : "rejected".ptr); if (st == 0 && cur !is null) { immutable
_error_ back
back
= TISSelectInputSource(cur);
instr("layout_switch", "target=restore status=%d", back); } } else { instr("input_source", "role=german_found id=<none> note=german_layout_not_installed"); } if (cur !is null) CFRelease(cur); if (list !is null) CFRelease(list); } // --- Route 2: real HID injection via CGEventPost -------------------------------- void
void app.postCGKey(ushort code)
postCGKey
(ushort
(parameter) ushort code
code
)
{ void*
_error_ down
down
= CGEventCreateKeyboardEvent(null, code, true);
void*
_error_ up
up
= CGEventCreateKeyboardEvent(null, code, false);
if (down is null || up is null) { instr("cgevent_post", "result=create_failed"); return; } CGEventPost(kCGSessionEventTap, down); CGEventPost(kCGSessionEventTap, up); CFRelease(down); CFRelease(up); } // --- Run-loop script (route 1 injection + the CGEventPost probe) ------------------ void
void app.stopApp()
stopApp
()
{ instr("step", "name=NSApp_stop"); g_app.
g_app.stop
stop
(null);
// stop: only takes effect after the next event dispatch; post a synthetic // application-defined event so [NSApp run] wakes up and returns (scaffold finding).
(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);
} void
void app.onStep()
onStep
()
{ if (g_step < cast(int) g_script.
g_script.length
length
)
{ immutable
_error_ k
k
= g_script[g_step];
instr("inject", "route=1 label=%.*s code=%u repeat=%d", cast(int) k.
k.label
label
.
k.label.length
length
, k.
k.label
label
.ptr, k.
k.code
code
, k.
k.repeat
repeat
? 1 : 0);
g_win.
g_win.sendEvent
sendEvent
(makeKey(NSEventTypeKeyDown, k));
g_win.
g_win.sendEvent
sendEvent
(makeKey(NSEventTypeKeyUp, k));
} else if (g_step == cast(int) g_script.
g_script.length
length
)
{ instr("step", "name=cgevent_post tap=session code=%u", g_cgWatchCode); g_cgArrived = false; postCGKey(g_cgWatchCode); } else if (g_step == cast(int) g_script.
g_script.length
length
+ 3)
{ // Grace period elapsed: did the HID event reach our keyDown:? instr("cgevent_result", "tap=session code=%u reached=%d note=%s", g_cgWatchCode, g_cgArrived ? 1 : 0, g_cgArrived ? "delivered".ptr : "blocked_or_not_routed".ptr); } else if (g_step >= cast(int) g_script.
g_script.length
length
+ 4)
{ stopApp(); } ++g_step; } extern (Objective-C) class
(class) app.StepTarget
StepTarget
:
(class) app.NSObject
NSObject
class `app.StepTarget` Objective-C classes not supported
{ static
(class) app.StepTarget
StepTarget
app.StepTarget app.StepTarget.alloc()
alloc
() @selector("alloc");
(class) app.StepTarget
StepTarget
app.StepTarget app.StepTarget.init()
init
() @selector("init");
void
void app.StepTarget.step(app.NSTimer t)
step
(
(class) app.NSTimer
NSTimer
(parameter) app.NSTimer t
t
) @selector("step:")
{ onStep(); } } int
int D main()
main
()
{ immutable
_error_ autoExit
autoExit
= getenv("WSI_AUTO_EXIT") !is null;
instrInit("APPKIT_F06"); instr("init_start", "auto_exit=%d", autoExit ? 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(360, 240));
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-f06-keyboard"));
g_view = KeyView.
KeyView.alloc
alloc
().
KeyView.alloc().initWithFrame
initWithFrame
(contentRect);
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);
g_winNum = g_win.
g_win.windowNumber
windowNumber
();
instr("window_created", "win_num=%ld first_responder=KeyView", g_winNum); // Synchronous layout-engine + input-source demonstrations (no run loop needed). runLayoutDemos(); // Drive the route-1 script and the route-2 probe from a repeating timer inside // [NSApp run] (interpretKeyEvents: needs the running loop / live input context).
(unresolved type) StepTarget
StepTarget
_error_ target
target
= StepTarget.
StepTarget.alloc
alloc
().
StepTarget.alloc().init
init
();
instr("step", "name=script_timer_start interval_ms=200"); NSTimer.
NSTimer.scheduledTimerWithTimeInterval
scheduledTimerWithTimeInterval
(0.2, target, SEL.register("step:"), null, true);
instr("step", "name=NSApp_run"); g_app.
g_app.run
run
();
instr("loop_exit", "steps=%d", g_step); return 0; }