app.dhover×431 error×115all
// F07 IME / text input demo — an editable line with a visible caret, driven by
// zwp_text_input_v3 (text-input-unstable-v3) on top of the xdg-shell scaffold
// (../scaffold/app.d; findings: ../../scaffold.md, ../../f07-text-input.md).
//
// What it implements, per the protocol XML (text-input-unstable-v3.xml):
//
//   - bind zwp_text_input_manager_v3, get_text_input for the seat;
//   - on zwp_text_input_v3.enter: enable + set_surrounding_text +
//     set_content_type + set_cursor_rectangle(caret cells) + commit;
//   - the v3 double-buffered event state: preedit_string / commit_string /
//     delete_surrounding_text only latch *pending* state, which is applied
//     atomically on done(serial) in the exact order the XML mandates
//     (1. drop old preedit, 2. delete surrounding, 3. insert commit string,
//     4. recalculate surrounding, 5-6. install new preedit + caret);
//   - the serial discipline: the client counts its own commit requests; a
//     done.serial equal to that count permits new state requests, a stale
//     serial means "apply the edits, but do not touch protocol state yet".
//
// The line is rendered with block glyphs (no font lib): each committed UTF-8
// byte is a colored cell (color = hash of the byte), the pre-edit is rendered
// inline at the caret as cells over a bright underline band, and the caret is
// a white bar. The *real* strings are logged (`text committed="…" preedit="…"`).
// wl_keyboard events are logged in full (keycode, xkb keysym, UTF-8) so the
// findings doc can answer which key events still arrive while an IME composes.
// Plain typing also works without an IME: xkbcommon translates the key, the
// demo edits locally and resends state with change_cause=other.
//
// Headless-safe: no compositor → SKIP, exit 0; no zwp_text_input_manager_v3 or
// no wl_seat → the absence is logged as the finding and the run still exits 0.
module 
(module) app
app
;
import c; // ImportC: wayland-client + xdg-shell + text-input-v3 glue + xkbcommon
unable to read module `c` Expected 'c.d' or 'c/package.d' in one of the following import paths:
unable to read module `c` Expected 'c.d' or 'c/package.d' in one of the following import paths:
import instrument;
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
(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
(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.memcpy = void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
,
(alias) app.memmove = void* core.stdc.string.memmove(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memmove
,
(alias) app.strcmp = int core.stdc.string.strcmp(scope const(char*) s1, scope const(char*) s2) pure nothrow @nogc
strcmp
,
(alias) app.strlen = ulong core.stdc.string.strlen(scope const(char*) s) pure nothrow @nogc
strlen
;
// ----------------------------------------------------------------- tunables enum int
(constant) int app.defaultWidth = 640
defaultWidth
= 640;
enum int
(constant) int app.defaultHeight = 220
defaultHeight
= 220;
enum int
(constant) int app.autoExitFrames = 150
autoExitFrames
= 150; // ≈ 2.5 s at 60 Hz
enum long
(constant) long app.autoExitUsCap = 3000000L
autoExitUsCap
= 3_000_000;
enum int
(constant) int app.textCap = 240
textCap
= 240; // committed-line byte budget (protocol max is 4000)
// Block-glyph layout (surface-local px — the units set_cursor_rectangle takes). enum int
(constant) int app.cellX0 = 16
cellX0
= 16,
(constant) int app.cellY0 = 96
cellY0
= 96,
(constant) int app.cellW = 12
cellW
= 12,
(constant) int app.cellH = 48
cellH
= 48,
(constant) int app.underlineH = 6
underlineH
= 6;
// Keysyms used for local editing (values from xkbcommon-keysyms.h). enum uint
(constant) uint app.keyBackSpace = 65288u
keyBackSpace
= 0xff08,
(constant) uint app.keyEscape = 65307u
keyEscape
= 0xff1b,
(constant) uint app.keyLeft = 65361u
keyLeft
= 0xff51,
(constant) uint app.keyRight = 65363u
keyRight
= 0xff53;
// -------------------------------------------------------------------- state struct
(struct) app.Buffer
Buffer
{ wl_buffer*
(field) _error_ app.Buffer.handle
handle
;
undefined identifier `wl_buffer`
uint*
(field) uint* app.Buffer.pixels
pixels
;
(alias) object.size_t = ulong
size_t
(field) ulong app.Buffer.byteSize
byteSize
;
int
(field) int app.Buffer.width
width
,
(field) int app.Buffer.height
height
;
bool
(field) bool app.Buffer.busy
busy
;
} __gshared { wl_display*
_error_ app.g_display
g_display
;
undefined identifier `wl_display`, did you mean variable `g_display`?
wl_registry*
_error_ app.g_registry
g_registry
;
undefined identifier `wl_registry`, did you mean variable `g_registry`?
wl_compositor*
_error_ app.g_compositor
g_compositor
;
undefined identifier `wl_compositor`, did you mean variable `g_compositor`?
wl_shm*
_error_ app.g_shm
g_shm
;
undefined identifier `wl_shm`, did you mean variable `g_shm`?
wl_seat*
_error_ app.g_seat
g_seat
;
undefined identifier `wl_seat`, did you mean variable `g_seat`?
wl_keyboard*
_error_ app.g_keyboard
g_keyboard
;
undefined identifier `wl_keyboard`, did you mean variable `g_keyboard`?
xdg_wm_base*
_error_ app.g_wmBase
g_wmBase
;
undefined identifier `xdg_wm_base`
wl_surface*
_error_ app.g_surface
g_surface
;
undefined identifier `wl_surface`, did you mean variable `g_surface`?
xdg_surface*
_error_ app.g_xdgSurface
g_xdgSurface
;
undefined identifier `xdg_surface`, did you mean variable `g_surface`?
xdg_toplevel*
_error_ app.g_toplevel
g_toplevel
;
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
wl_callback*
_error_ app.g_frameCb
g_frameCb
;
undefined identifier `wl_callback`
zwp_text_input_manager_v3*
_error_ app.g_tiManager
g_tiManager
;
undefined identifier `zwp_text_input_manager_v3`
zwp_text_input_v3*
_error_ app.g_ti
g_ti
;
undefined identifier `zwp_text_input_v3`
xkb_context*
_error_ app.g_xkbCtx
g_xkbCtx
;
undefined identifier `xkb_context`
xkb_keymap*
_error_ app.g_xkbKeymap
g_xkbKeymap
;
undefined identifier `xkb_keymap`
xkb_state*
_error_ app.g_xkbState
g_xkbState
;
undefined identifier `xkb_state`
(struct) app.Buffer
Buffer
[2]
_error_ app.g_buffers
g_buffers
;
int
(__gshared global) int app.g_width
g_width
= defaultWidth,
(__gshared global) int app.g_height
g_height
= defaultHeight;
int
(__gshared global) int app.g_pendingWidth
g_pendingWidth
,
(__gshared global) int app.g_pendingHeight
g_pendingHeight
;
bool
(__gshared global) bool app.g_configured
g_configured
,
(__gshared global) bool app.g_running
g_running
= true,
(__gshared global) bool app.g_autoExit
g_autoExit
;
int
(__gshared global) int app.g_frames
g_frames
,
(__gshared global) int app.g_commits
g_commits
;
// --- the editable line ------------------------------------------------- char[
(constant) int app.textCap = 240
textCap
+ 1]
(__gshared global) char[241] app.g_text
g_text
= '\0'; // committed text, NUL-terminated
int
(__gshared global) int app.g_textLen
g_textLen
;
int
(__gshared global) int app.g_cursor
g_cursor
; // byte index into g_text
char[textCap + 1]
(__gshared global) char[241] app.g_preedit
g_preedit
= '\0'; // current (applied) pre-edit
int
(__gshared global) int app.g_preeditLen
g_preeditLen
;
int
(__gshared global) int app.g_preeditCb
g_preeditCb
,
(__gshared global) int app.g_preeditCe
g_preeditCe
; // caret begin/end inside the pre-edit, bytes
// --- zwp_text_input_v3 client state ------------------------------------ bool
(__gshared global) bool app.g_tiFocused
g_tiFocused
; // between enter and leave
uint
(__gshared global) uint app.g_tiCommits
g_tiCommits
; // number of commit requests sent == expected done serial
// pending (double-buffered) event state, applied on done(): char[textCap + 1]
(__gshared global) char[241] app.g_pendPreedit
g_pendPreedit
= '\0';
int
(__gshared global) int app.g_pendPreeditLen
g_pendPreeditLen
,
(__gshared global) int app.g_pendPreeditCb
g_pendPreeditCb
,
(__gshared global) int app.g_pendPreeditCe
g_pendPreeditCe
;
char[textCap + 1]
(__gshared global) char[241] app.g_pendCommit
g_pendCommit
= '\0';
int
(__gshared global) int app.g_pendCommitLen
g_pendCommitLen
;
uint
(__gshared global) uint app.g_pendDelBefore
g_pendDelBefore
,
(__gshared global) uint app.g_pendDelAfter
g_pendDelAfter
;
} // ----------------------------------------------------------- text utilities int
int app.clampInt(int v, int lo, int hi) nothrow @nogc
clampInt
(int
(parameter) int v
v
, int
(parameter) int lo
lo
, int
(parameter) int hi
hi
) nothrow @nogc
{ return
(parameter) int v
v
<
(parameter) int lo
lo
?
(parameter) int lo
lo
: (
(parameter) int v
v
>
(parameter) int hi
hi
?
(parameter) int hi
hi
:
(parameter) int v
v
);
} /// Copy a NUL-terminated C string into a bounded buffer, returning the length. int
int app.copyStr(const(char)* src, ref char[241] dst) nothrow @nogc

Copy a NUL-terminated C string into a bounded buffer, returning the length.

copyStr
(const(char)*
(parameter) const(char)* src
src
, ref char[textCap + 1]
(parameter) char[241] dst
dst
) nothrow @nogc
{ int
(local variable) int n
n
=
(parameter) const(char)* src
src
is null ? 0 : cast(int)
ulong core.stdc.string.strlen(scope const(char*) s) pure nothrow @nogc
strlen
(
(parameter) const(char)* src
src
);
if (
(local variable) int n
n
>
(constant) int app.textCap = 240
textCap
)
(local variable) int n
n
=
(constant) int app.textCap = 240
textCap
;
if (
(local variable) int n
n
> 0)
void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
(
(parameter) char[241] dst
dst
.
(constant) char* char[241].ptr = &dst
ptr
,
(parameter) const(char)* src
src
,
(local variable) int n
n
);
(parameter) char[241] dst
dst
[
(local variable) int n
n
] = '\0';
return
(local variable) int n
n
;
} void
void app.insertAtCursor(const(char)* s, int n) nothrow @nogc
insertAtCursor
(const(char)*
(parameter) const(char)* s
s
, int
(parameter) int n
n
) nothrow @nogc
{ if (
(parameter) int n
n
<= 0 ||
(__gshared global) int app.g_textLen
g_textLen
+
(parameter) int n
n
>
(constant) int app.textCap = 240
textCap
)
return;
void* core.stdc.string.memmove(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memmove
(
(__gshared global) char[241] app.g_text
g_text
.
(constant) char* char[241].ptr = &g_text
ptr
+
(__gshared global) int app.g_cursor
g_cursor
+
(parameter) int n
n
,
(__gshared global) char[241] app.g_text
g_text
.
(constant) char* char[241].ptr = &g_text
ptr
+
(__gshared global) int app.g_cursor
g_cursor
,
(__gshared global) int app.g_textLen
g_textLen
-
(__gshared global) int app.g_cursor
g_cursor
);
void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
(
(__gshared global) char[241] app.g_text
g_text
.
(constant) char* char[241].ptr = &g_text
ptr
+
(__gshared global) int app.g_cursor
g_cursor
,
(parameter) const(char)* s
s
,
(parameter) int n
n
);
(__gshared global) int app.g_textLen
g_textLen
+=
(parameter) int n
n
;
(__gshared global) int app.g_cursor
g_cursor
+=
(parameter) int n
n
;
(__gshared global) char[241] app.g_text
g_text
[
(__gshared global) int app.g_textLen
g_textLen
] = '\0';
} void
void app.deleteRange(int begin, int end) nothrow @nogc
deleteRange
(int
(parameter) int begin
begin
, int
(parameter) int end
end
) nothrow @nogc // [begin, end) in bytes
{
(parameter) int begin
begin
=
int app.clampInt(int v, int lo, int hi) nothrow @nogc
clampInt
(
(parameter) int begin
begin
, 0,
(__gshared global) int app.g_textLen
g_textLen
);
(parameter) int end
end
=
int app.clampInt(int v, int lo, int hi) nothrow @nogc
clampInt
(
(parameter) int end
end
,
(parameter) int begin
begin
,
(__gshared global) int app.g_textLen
g_textLen
);
void* core.stdc.string.memmove(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memmove
(
(__gshared global) char[241] app.g_text
g_text
.
(constant) char* char[241].ptr = &g_text
ptr
+
(parameter) int begin
begin
,
(__gshared global) char[241] app.g_text
g_text
.
(constant) char* char[241].ptr = &g_text
ptr
+
(parameter) int end
end
,
(__gshared global) int app.g_textLen
g_textLen
-
(parameter) int end
end
);
(__gshared global) int app.g_textLen
g_textLen
-=
(parameter) int end
end
-
(parameter) int begin
begin
;
(__gshared global) int app.g_cursor
g_cursor
=
(__gshared global) int app.g_cursor
g_cursor
>=
(parameter) int end
end
?
(__gshared global) int app.g_cursor
g_cursor
- (
(parameter) int end
end
-
(parameter) int begin
begin
) :
int app.clampInt(int v, int lo, int hi) nothrow @nogc
clampInt
(
(__gshared global) int app.g_cursor
g_cursor
, 0,
(parameter) int begin
begin
);
(__gshared global) char[241] app.g_text
g_text
[
(__gshared global) int app.g_textLen
g_textLen
] = '\0';
} /// Step one UTF-8 code point left/right from `idx` (indices never split a /// code point — the same invariant text-input-v3 demands of its byte offsets). int
int app.cpPrev(int idx) nothrow @nogc

Step one UTF-8 code point left/right from idx (indices never split a code point — the same invariant text-input-v3 demands of its byte offsets).

cpPrev
(int
(parameter) int idx
idx
) nothrow @nogc
{ do --
(parameter) int idx
idx
;
while (
(parameter) int idx
idx
> 0 && (
(__gshared global) char[241] app.g_text
g_text
[
(parameter) int idx
idx
] & 0xc0) == 0x80);
return
(parameter) int idx
idx
< 0 ? 0 :
(parameter) int idx
idx
;
} int
int app.cpNext(int idx) nothrow @nogc
cpNext
(int
(parameter) int idx
idx
) nothrow @nogc
{ do ++
(parameter) int idx
idx
;
while (
(parameter) int idx
idx
<
(__gshared global) int app.g_textLen
g_textLen
&& (
(__gshared global) char[241] app.g_text
g_text
[
(parameter) int idx
idx
] & 0xc0) == 0x80);
return
(parameter) int idx
idx
>
(__gshared global) int app.g_textLen
g_textLen
?
(__gshared global) int app.g_textLen
g_textLen
:
(parameter) int idx
idx
;
} void
void app.logText() nothrow @nogc
logText
() nothrow @nogc
{ instrEvent("text", "committed=\"%s\" cursor=%d preedit=\"%s\" preedit_cursor=%d..%d",
undefined identifier `instrEvent`, did you mean import `instrument`?
g_text.
g_text.ptr
ptr
, g_cursor, g_preedit.
g_preedit.ptr
ptr
, g_preeditCb, g_preeditCe);
} // --------------------------------------------- caret rect + protocol commits /// Caret rectangle in surface-local coordinates: the cell the caret occupies, /// accounting for the pre-edit caret offset (cursor_begin) when composing. void
void app.caretRect(out int x, out int y, out int w, out int h) nothrow @nogc

Caret rectangle in surface-local coordinates: the cell the caret occupies, accounting for the pre-edit caret offset (cursor_begin) when composing.

caretRect
(out int
(parameter) int x
x
, out int
(parameter) int y
y
, out int
(parameter) int w
w
, out int
(parameter) int h
h
) nothrow @nogc
{ immutable
(local variable) immutable(int) col
col
=
(__gshared global) int app.g_cursor
g_cursor
+ (
(__gshared global) int app.g_preeditLen
g_preeditLen
> 0 ?
int app.clampInt(int v, int lo, int hi) nothrow @nogc
clampInt
(
(__gshared global) int app.g_preeditCb
g_preeditCb
, 0,
(__gshared global) int app.g_preeditLen
g_preeditLen
) : 0);
(parameter) int x
x
=
(constant) int app.cellX0 = 16
cellX0
+
(local variable) immutable(int) col
col
*
(constant) int app.cellW = 12
cellW
;
(parameter) int y
y
=
(constant) int app.cellY0 = 96
cellY0
;
(parameter) int w
w
=
(constant) int app.cellW = 12
cellW
;
(parameter) int h
h
=
(constant) int app.cellH = 48
cellH
;
} /// Send the full client state and commit it — the only place a /// zwp_text_input_v3.commit is issued, so g_tiCommits *is* the serial the /// protocol's done event must echo. cause: 0=input_method, 1=other, -1=omit. void
void app.tiCommitState(bool enable, int cause) nothrow @nogc

Send the full client state and commit it — the only place a zwp_text_input_v3.commit is issued, so g_tiCommits is the serial the protocol's done event must echo. cause: 0=input_method, 1=other, -1=omit.

tiCommitState
(bool
(parameter) bool enable
enable
, int
(parameter) int cause
cause
) nothrow @nogc
{ if (g_ti is null || (!
(parameter) bool enable
enable
&& !
(__gshared global) bool app.g_tiFocused
g_tiFocused
))
return; if (
(parameter) bool enable
enable
)
wsi_text_input_enable(g_ti);
undefined identifier `wsi_text_input_enable`
wsi_text_input_set_surrounding_text(g_ti, g_text.
g_text.ptr
ptr
, g_cursor, g_cursor);
undefined identifier `wsi_text_input_set_surrounding_text`
if (
(parameter) int cause
cause
>= 0)
wsi_text_input_set_text_change_cause(g_ti, cast(uint) cause);
undefined identifier `wsi_text_input_set_text_change_cause`
wsi_text_input_set_content_type(g_ti,
undefined identifier `wsi_text_input_set_content_type`
ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL); int
(local variable) int x
x
,
(local variable) int y
y
,
(local variable) int w
w
,
(local variable) int h
h
;
void app.caretRect(out int x, out int y, out int w, out int h) nothrow @nogc

Caret rectangle in surface-local coordinates: the cell the caret occupies, accounting for the pre-edit caret offset (cursor_begin) when composing.

caretRect
(
(local variable) int x
x
,
(local variable) int y
y
,
(local variable) int w
w
,
(local variable) int h
h
);
wsi_text_input_set_cursor_rectangle(g_ti, x, y, w, h);
undefined identifier `wsi_text_input_set_cursor_rectangle`
wsi_text_input_commit(g_ti);
undefined identifier `wsi_text_input_commit`
(__gshared global) uint app.g_tiCommits
g_tiCommits
++;
instrEvent("ti_commit_state", "serial=%u enable=%d cause=%d cursor_rect=%d,%d %dx%d",
undefined identifier `instrEvent`, did you mean import `instrument`?
g_tiCommits, enable ? 1 : 0, cause, x, y, w, h); } // ------------------------------------------------------------ shm + drawing bool
app.ensureBuffer
ensureBuffer
(ref
(struct) app.Buffer
Buffer
(parameter) Buffer b
b
, int
(parameter) int w
w
, int
(parameter) int h
h
) nothrow @nogc
{ if (b.
b.handle
handle
!is null && (b.
b.width
width
!= w || b.
b.height
height
!= h))
{ wsi_buffer_destroy(b.
b.handle
handle
);
munmap(b.
b.pixels
pixels
, b.
b.byteSize
byteSize
);
b = Buffer.init; } if (b.
b.handle
handle
!is null)
return true; immutable
_error_ stride
stride
= w * 4;
immutable
_error_ size
size
= cast(
(unresolved type) size_t
size_t
) stride * h;
immutable
_error_ fd
fd
= memfd_create("wsi-f07", MFD_CLOEXEC);
if (fd < 0 || ftruncate(fd, cast(long) size) != 0) return false; void*
_error_ mem
mem
= mmap(null, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mem is cast(void*)-1) { close(fd); return false; } wl_shm_pool*
_error_ pool
pool
= wsi_shm_create_pool(g_shm, fd, cast(int) size);
b.
b.handle
handle
= wsi_shm_pool_create_buffer(pool, 0, w, h, stride, WL_SHM_FORMAT_ARGB8888);
wsi_shm_pool_destroy(pool); close(fd); wsi_buffer_add_listener(b.
b.handle
handle
, &g_bufferListener, &b);
b.
b.pixels
pixels
= cast(uint*) mem;
b.
b.byteSize
byteSize
= size;
b.
b.width
width
= w;
b.
b.height
height
= h;
return true; } void
app.fillRect
fillRect
(ref
(struct) app.Buffer
Buffer
(parameter) Buffer b
b
, int
(parameter) int x
x
, int
(parameter) int y
y
, int
(parameter) int w
w
, int
(parameter) int h
h
, uint argb) nothrow @nogc
{ immutable
_error_ x0
x0
= clampInt(x, 0, b.
b.width
width
),
_error_ x1
x1
= clampInt(x + w, 0, b.
b.width
width
);
immutable
_error_ y0
y0
= clampInt(y, 0, b.
b.height
height
),
_error_ y1
y1
= clampInt(y + h, 0, b.
b.height
height
);
foreach (
(parameter) yy
yy
; y0 .. y1)
{ uint*
_error_ row
row
= b.
b.pixels
pixels
+ cast(
(unresolved type) size_t
size_t
) yy * b.
b.width
width
;
row[x0 .. x1] = argb; } } /// Block glyph: a byte becomes a solid cell whose color hashes the byte value, /// so distinct characters are visually distinct without any font machinery. uint
uint app.cellColor(ubyte c, bool preedit) nothrow @nogc

Block glyph: a byte becomes a solid cell whose color hashes the byte value, so distinct characters are visually distinct without any font machinery.

cellColor
(ubyte
(parameter) ubyte c
c
, bool
(parameter) bool preedit
preedit
) nothrow @nogc
{ immutable uint
(local variable) immutable(uint) h
h
= (
(parameter) ubyte c
c
* 2654435761u) >> 8;
immutable uint
(local variable) immutable(uint) r
r
= 0x50 + (
(local variable) immutable(uint) h
h
& 0x7f),
(local variable) immutable(uint) g
g
= 0x50 + ((
(local variable) immutable(uint) h
h
>> 7) & 0x7f),
(local variable) immutable(uint) bch
bch
= 0x50 + ((
(local variable) immutable(uint) h
h
>> 14) & 0x7f);
// pre-edit cells are dimmed toward blue so they read as "not committed yet" return
(parameter) bool preedit
preedit
? 0xff000000 | (
(local variable) immutable(uint) r
r
/ 2 << 16) | (
(local variable) immutable(uint) g
g
/ 2 << 8) | 0xff
: 0xff000000 | (
(local variable) immutable(uint) r
r
<< 16) | (
(local variable) immutable(uint) g
g
<< 8) |
(local variable) immutable(uint) bch
bch
;
} void
app.paint
paint
(ref
(struct) app.Buffer
Buffer
(parameter) Buffer b
b
) nothrow @nogc
{ fillRect(b, 0, 0, b.
b.width
width
, b.
b.height
height
, 0xff14181c); // background
// status blocks (the on-screen debug string, block-glyph form): focus, // text-input present, pre-edit active, then the done-serial low bits. fillRect(b, cellX0, 16, 24, 24, g_tiFocused ? 0xff30c030 : 0xffc03030); fillRect(b, cellX0 + 32, 16, 24, 24, g_ti !is null ? 0xff3060e0 : 0xff606060); fillRect(b, cellX0 + 64, 16, 24, 24, g_preeditLen > 0 ? 0xffe0c020 : 0xff606060); foreach (
(parameter) bit
bit
; 0 .. 8)
fillRect(b, cellX0 + 112 + bit * 16, 16, 12, 24, (g_tiCommits >> (7 - bit)) & 1 ? 0xffe0e0e0 : 0xff404040); fillRect(b, cellX0 - 4, cellY0 - 4, b.
b.width
width
- 2 * cellX0 + 8, cellH + 8, 0xff20262c); // field
// committed text before the caret, pre-edit, committed after — inline. int
_error_ col
col
= 0;
void
void cells(const(char)* s, int begin, int end, bool pre) nothrow @nogc
cells
(const(char)*
(parameter) const(char)* s
s
, int
(parameter) int begin
begin
, int
(parameter) int end
end
, bool
(parameter) bool pre
pre
) nothrow @nogc
{ foreach (
(parameter) i
i
; begin .. end)
{ fillRect(b, cellX0 + col * cellW + 1, cellY0, cellW - 2, cellH - underlineH - 2, cellColor(cast(ubyte) s[i], pre)); if (pre) fillRect(b, cellX0 + col * cellW, cellY0 + cellH - underlineH, cellW, underlineH, 0xffffd040); // the underline band col++; } } cells(g_text.
g_text.ptr
ptr
, 0, g_cursor, false);
cells(g_preedit.
g_preedit.ptr
ptr
, 0, g_preeditLen, true);
cells(g_text.
g_text.ptr
ptr
, g_cursor, g_textLen, false);
int
_error_ cx
cx
,
_error_ cy
cy
,
_error_ cw
cw
,
_error_ ch
ch
;
caretRect(cx, cy, cw, ch); fillRect(b, cx - 1, cy - 4, 3, ch + 8, 0xffffffff); // the caret bar } void
void app.render() nothrow @nogc
render
() nothrow @nogc
{
(struct) app.Buffer
Buffer
*
(local variable) _error_ buf
buf
= null;
foreach (ref
(parameter) b
b
; g_buffers)
if (!b.
b.busy
busy
)
{ buf = &b; break; } if (buf is null || !ensureBuffer(*buf, g_width, g_height)) return; paint(*buf); wsi_surface_attach(g_surface, buf.
buf.handle
handle
, 0, 0);
undefined identifier `wsi_surface_attach`
wsi_surface_damage_buffer(g_surface, 0, 0, buf.
buf.width
width
, buf.
buf.height
height
);
undefined identifier `wsi_surface_damage_buffer`
if (g_frameCb is null) { g_frameCb = wsi_surface_frame(g_surface); wsi_callback_add_listener(g_frameCb, &g_frameListener, null);
undefined identifier `wsi_callback_add_listener`
} wsi_surface_commit(g_surface);
undefined identifier `wsi_surface_commit`
buf.
buf.busy
busy
= true;
(__gshared global) int app.g_commits
g_commits
++;
} // ----------------------------------------------- zwp_text_input_v3 listeners extern (C) void
app.onTiEnter
onTiEnter
(void* data, zwp_text_input_v3* ti, wl_surface*
(parameter) wl_surface* s
s
) nothrow @nogc
undefined identifier `zwp_text_input_v3`
undefined identifier `wl_surface`, did you mean variable `g_surface`?
{ g_tiFocused = true; instrEvent("ti_enter"); // Per the XML: "After an enter event or disable request all state // information is invalidated and needs to be resent by the client." tiCommitState(true, -1); } extern (C) void
app.onTiLeave
onTiLeave
(void* data, zwp_text_input_v3* ti, wl_surface*
(parameter) wl_surface* s
s
) nothrow @nogc
undefined identifier `zwp_text_input_v3`
undefined identifier `wl_surface`, did you mean variable `g_surface`?
{ // "The client should reset any preedit string previously set" — the // composition simply evaporates; nothing is committed. immutable
_error_ hadPreedit
hadPreedit
= g_preeditLen;
g_preeditLen = 0; g_preedit[0] = '\0'; instrEvent("ti_leave", "dropped_preedit_bytes=%d", hadPreedit); wsi_text_input_disable(g_ti); wsi_text_input_commit(g_ti); g_tiCommits++; g_tiFocused = false; instrEvent("ti_commit_state", "serial=%u enable=0 disable=1", g_tiCommits); logText(); } extern (C) void
app.onTiPreedit
onTiPreedit
(void* data, zwp_text_input_v3* ti,
undefined identifier `zwp_text_input_v3`
const(char)* text, int cursorBegin, int cursorEnd) nothrow @nogc { // Double-buffered: latch only; applied on done(). g_pendPreeditLen = copyStr(text, g_pendPreedit); g_pendPreeditCb = cursorBegin; g_pendPreeditCe = cursorEnd; instrEvent("ti_preedit_string", "text=\"%s\" cursor_begin=%d cursor_end=%d (pending)", g_pendPreedit.
g_pendPreedit.ptr
ptr
, cursorBegin, cursorEnd);
} extern (C) void
app.onTiCommitString
onTiCommitString
(void* data, zwp_text_input_v3* ti, const(char)* text) nothrow @nogc
undefined identifier `zwp_text_input_v3`
{ g_pendCommitLen = copyStr(text, g_pendCommit); instrEvent("ti_commit_string", "text=\"%s\" (pending)", g_pendCommit.
g_pendCommit.ptr
ptr
);
} extern (C) void
app.onTiDeleteSurrounding
onTiDeleteSurrounding
(void* data, zwp_text_input_v3* ti,
undefined identifier `zwp_text_input_v3`
uint beforeLength, uint afterLength) nothrow @nogc { g_pendDelBefore = beforeLength; g_pendDelAfter = afterLength; instrEvent("ti_delete_surrounding_text", "before=%u after=%u (pending)", beforeLength, afterLength); } /// done(serial): atomically apply the pending state in the order the protocol /// XML mandates, then — only if the serial matches our commit count — answer /// with refreshed surrounding text / cursor rectangle. extern (C) void
app.onTiDone

done(serial): atomically apply the pending state in the order the protocol XML mandates, then — only if the serial matches our commit count — answer with refreshed surrounding text / cursor rectangle.

onTiDone
(void* data, zwp_text_input_v3* ti, uint serial) nothrow @nogc
undefined identifier `zwp_text_input_v3`
{ immutable
_error_ inSync
inSync
= serial == g_tiCommits;
instrEvent("ti_done", "serial=%u client_commits=%u in_sync=%d", serial, g_tiCommits, inSync); bool
_error_ surroundingChanged
surroundingChanged
= false;
// 1. Replace existing preedit string with the cursor. g_preeditLen = 0; g_preedit[0] = '\0'; // 2. Delete requested surrounding text (lengths are bytes around the cursor). if (g_pendDelBefore != 0 || g_pendDelAfter != 0) { deleteRange(g_cursor - cast(int) g_pendDelBefore, g_cursor + cast(int) g_pendDelAfter); surroundingChanged = true; } // 3. Insert commit string with the cursor at its end. if (g_pendCommitLen > 0) { insertAtCursor(g_pendCommit.
g_pendCommit.ptr
ptr
, g_pendCommitLen);
surroundingChanged = true; } // 4. (surrounding text is recalculated when we resend state below) // 5./6. Insert new preedit text at the cursor, with the caret inside it. g_preeditLen = g_pendPreeditLen; memcpy(g_preedit.
g_preedit.ptr
ptr
, g_pendPreedit.
g_pendPreedit.ptr
ptr
, g_pendPreeditLen + 1);
g_preeditCb = g_pendPreeditCb; g_preeditCe = g_pendPreeditCe; // Pending state resets to initial after every done (per the XML). g_pendPreeditLen = g_pendPreeditCb = g_pendPreeditCe = 0; g_pendPreedit[0] = '\0'; g_pendCommitLen = 0; g_pendCommit[0] = '\0'; g_pendDelBefore = g_pendDelAfter = 0; logText(); // Serial discipline: a stale serial means our state is already newer than // what the IM saw — apply the edits but send nothing until it catches up. if (inSync && (surroundingChanged || g_preeditLen > 0)) tiCommitState(false, surroundingChanged ? 0 : -1); // 0 = input_method } // ----------------------------------------------------- wl_keyboard listeners // Logged exhaustively: the F07 finding "which raw key events still arrive // while the IME composes" falls straight out of this stream. extern (C) void
app.onKbKeymap
onKbKeymap
(void* data, wl_keyboard* kb, uint format, int
(parameter) int fd
fd
, uint
(parameter) uint size
size
) nothrow @nogc
undefined identifier `wl_keyboard`, did you mean variable `g_keyboard`?
{ instrEvent("kb_keymap", "format=%u size=%u", format, size); if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 && g_xkbCtx !is null) { void*
_error_ mem
mem
= mmap(null, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (mem !is cast(void*)-1) { g_xkbKeymap = xkb_keymap_new_from_string(g_xkbCtx, cast(const(char)*) mem, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); if (g_xkbKeymap !is null) g_xkbState = xkb_state_new(g_xkbKeymap); munmap(mem, size); } } close(fd); } extern (C) void
app.onKbEnter
onKbEnter
(void* data, wl_keyboard* kb, uint serial, wl_surface*
(parameter) wl_surface* s
s
,
undefined identifier `wl_keyboard`, did you mean variable `g_keyboard`?
undefined identifier `wl_surface`, did you mean variable `g_surface`?
wl_array* keys) nothrow @nogc
undefined identifier `wl_array`
{ instrEvent("kb_enter", "serial=%u pressed_keys=%zu", serial, keys.
keys.size
size
/ 4);
} extern (C) void
app.onKbLeave
onKbLeave
(void* data, wl_keyboard* kb, uint serial, wl_surface*
(parameter) wl_surface* s
s
) nothrow @nogc
undefined identifier `wl_keyboard`, did you mean variable `g_keyboard`?
undefined identifier `wl_surface`, did you mean variable `g_surface`?
{ instrEvent("kb_leave", "serial=%u", serial); } extern (C) void
app.onKbKey
onKbKey
(void* data, wl_keyboard* kb, uint serial, uint time,
undefined identifier `wl_keyboard`, did you mean variable `g_keyboard`?
uint key, uint state) nothrow @nogc { char[64]
_error_ symName
symName
= '\0';
char[8]
_error_ utf8
utf8
= '\0';
uint
_error_ sym
sym
= 0;
int
_error_ utf8Len
utf8Len
= 0;
if (g_xkbState !is null) { immutable
_error_ keycode
keycode
= key + 8; // evdev → XKB keycode offset
sym = xkb_state_key_get_one_sym(g_xkbState, keycode); xkb_keysym_get_name(sym, symName.
symName.ptr
ptr
, symName.length);
utf8Len = xkb_state_key_get_utf8(g_xkbState, keycode, utf8.
utf8.ptr
ptr
, utf8.length);
} instrEvent("key", "serial=%u time=%u keycode=%u state=%s sym=0x%x name=%s utf8=\"%s\"", serial, time, key, state == 1 ? "pressed".
"pressed".ptr
ptr
: "released".
"released".ptr
ptr
,
sym, symName.
symName.ptr
ptr
, utf8.
utf8.ptr
ptr
);
if (state != 1) // act on presses only return; // Local (non-IME) editing path: change_cause=other on the resulting state. if (sym == keyBackSpace && g_cursor > 0) deleteRange(cpPrev(g_cursor), g_cursor); else if (sym == keyLeft) g_cursor = g_cursor > 0 ? cpPrev(g_cursor) : 0; else if (sym == keyRight) g_cursor = cpNext(g_cursor); else if (sym == keyEscape) { g_running = false; return; } else if (utf8Len > 0 && cast(ubyte) utf8[0] >= 0x20 && utf8[0] != 0x7f) insertAtCursor(utf8.
utf8.ptr
ptr
, utf8Len);
else return; logText(); tiCommitState(false, 1); // 1 = change_cause other (keyboard, not the IM) } extern (C) void
app.onKbModifiers
onKbModifiers
(void* data, wl_keyboard* kb, uint serial,
undefined identifier `wl_keyboard`, did you mean variable `g_keyboard`?
uint depressed, uint latched, uint locked, uint group) nothrow @nogc { if (g_xkbState !is null) xkb_state_update_mask(g_xkbState, depressed, latched, locked, 0, 0, group); instrEvent("kb_modifiers", "depressed=0x%x latched=0x%x locked=0x%x group=%u", depressed, latched, locked, group); } extern (C) void
app.onKbRepeatInfo
onKbRepeatInfo
(void* data, wl_keyboard* kb, int rate, int delay) nothrow @nogc
undefined identifier `wl_keyboard`, did you mean variable `g_keyboard`?
{ instrEvent("kb_repeat_info", "rate=%d delay=%d", rate, delay); } // --------------------------------------------------------- shell + bookkeeping extern (C) void
app.onGlobal
onGlobal
(void* data, wl_registry* reg, uint name,
undefined identifier `wl_registry`, did you mean variable `g_registry`?
const(char)* iface, uint ver) nothrow @nogc { instrEvent("global", "iface=%s version=%u", iface, ver); // the registry dump static uint
uint capped(uint advertised, uint want) nothrow @nogc
capped
(uint
(parameter) uint advertised
advertised
, uint
(parameter) uint want
want
) nothrow @nogc
{ return advertised < want ? advertised : want; } if (strcmp(iface, wl_compositor_interface.name) == 0) g_compositor = cast(wl_compositor*) wsi_registry_bind(reg, name, &wl_compositor_interface, capped(ver, 4)); else if (strcmp(iface, wl_shm_interface.name) == 0) g_shm = cast(wl_shm*) wsi_registry_bind(reg, name, &wl_shm_interface, 1); else if (strcmp(iface, xdg_wm_base_interface.name) == 0) g_wmBase = cast(xdg_wm_base*) wsi_registry_bind(reg, name, &xdg_wm_base_interface, 1); else if (strcmp(iface, wl_seat_interface.name) == 0) g_seat = cast(wl_seat*) wsi_registry_bind(reg, name, &wl_seat_interface, capped(ver, 4)); else if (strcmp(iface, zwp_text_input_manager_v3_interface.name) == 0) g_tiManager = cast(zwp_text_input_manager_v3*) wsi_registry_bind(reg, name, &zwp_text_input_manager_v3_interface, 1); } extern (C) void
app.onGlobalRemove
onGlobalRemove
(void* data, wl_registry* reg, uint name) nothrow @nogc
undefined identifier `wl_registry`, did you mean variable `g_registry`?
{ } extern (C) void
app.onWmBasePing
onWmBasePing
(void* data, xdg_wm_base*
(parameter) xdg_wm_base* b
b
, uint serial) nothrow @nogc
undefined identifier `xdg_wm_base`
{ wsi_wm_base_pong(b, serial); } extern (C) void
app.onSeatCapabilities
onSeatCapabilities
(void* data, wl_seat*
(parameter) wl_seat* s
s
, uint caps) nothrow @nogc
undefined identifier `wl_seat`, did you mean variable `g_seat`?
{ instrEvent("seat_capabilities", "caps=0x%x", caps); enum uint
(constant) uint capKeyboard = 2
capKeyboard
= 2; // WL_SEAT_CAPABILITY_KEYBOARD
if ((caps & capKeyboard) && g_keyboard is null) { g_keyboard = wsi_seat_get_keyboard(s); wsi_keyboard_add_listener(g_keyboard, &g_keyboardListener, null); instrStep("wl_seat_get_keyboard"); } } extern (C) void
app.onSeatName
onSeatName
(void* data, wl_seat*
(parameter) wl_seat* s
s
, const(char)* name) nothrow @nogc
undefined identifier `wl_seat`, did you mean variable `g_seat`?
{ instrEvent("seat_name", "name=%s", name); } extern (C) void
app.onToplevelConfigure
onToplevelConfigure
(void* data, xdg_toplevel* t, int
(parameter) int w
w
, int
(parameter) int h
h
,
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
wl_array* states) nothrow @nogc
undefined identifier `wl_array`
{ g_pendingWidth = w; g_pendingHeight = h; } extern (C) void
app.onXdgSurfaceConfigure
onXdgSurfaceConfigure
(void* data, xdg_surface*
(parameter) xdg_surface* s
s
, uint serial) nothrow @nogc
undefined identifier `xdg_surface`, did you mean variable `g_surface`?
{ g_width = g_pendingWidth > 0 ? g_pendingWidth : defaultWidth; g_height = g_pendingHeight > 0 ? g_pendingHeight : defaultHeight; wsi_xdg_surface_ack_configure(s, serial); if (!g_configured) { g_configured = true; instrFirstConfigure(); } render(); } extern (C) void
app.onToplevelClose
onToplevelClose
(void* data, xdg_toplevel* t) nothrow @nogc
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
{ instrCloseRequested(); g_running = false; } extern (C) void
app.onToplevelConfigureBounds
onToplevelConfigureBounds
(void* data, xdg_toplevel* t, int
(parameter) int w
w
, int
(parameter) int h
h
) nothrow @nogc
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
{ } extern (C) void
app.onToplevelWmCapabilities
onToplevelWmCapabilities
(void* data, xdg_toplevel* t, wl_array* caps) nothrow @nogc
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
undefined identifier `wl_array`
{ } extern (C) void
app.onBufferRelease
onBufferRelease
(void* data, wl_buffer*
(parameter) wl_buffer* b
b
) nothrow @nogc
undefined identifier `wl_buffer`
{ (cast(
(unresolved type) Buffer
Buffer
*) data).
(cast(Buffer*)data).busy
busy
= false;
// sway/wlroots holds shm buffers until the *next* commit replaces them, so // both buffers can be busy when a frame callback fires; recover here. if (g_running && g_configured && g_frameCb is null) render(); } extern (C) void
app.onFrameDone
onFrameDone
(void* data, wl_callback* cb, uint timeMs) nothrow @nogc
undefined identifier `wl_callback`
{ wsi_callback_destroy(cb); g_frameCb = null; g_frames++; if (g_frames == 1) instrFirstPixelPresented(); if (g_autoExit && (g_frames >= autoExitFrames || instrNowUs() > autoExitUsCap)) { g_running = false; return; } render(); } __gshared wl_registry_listener
_error_ app.g_registryListener
g_registryListener
= {&onGlobal, &onGlobalRemove};
undefined identifier `wl_registry_listener`
__gshared xdg_wm_base_listener
_error_ app.g_wmBaseListener
g_wmBaseListener
= {&onWmBasePing};
undefined identifier `xdg_wm_base_listener`
__gshared wl_seat_listener
_error_ app.g_seatListener
g_seatListener
= {&onSeatCapabilities, &onSeatName};
undefined identifier `wl_seat_listener`
__gshared xdg_surface_listener
_error_ app.g_xdgSurfaceListener
g_xdgSurfaceListener
= {&onXdgSurfaceConfigure};
undefined identifier `xdg_surface_listener`
__gshared xdg_toplevel_listener
_error_ app.g_toplevelListener
g_toplevelListener
= {
undefined identifier `xdg_toplevel_listener`
&onToplevelConfigure, &onToplevelClose, &onToplevelConfigureBounds, &onToplevelWmCapabilities }; __gshared wl_buffer_listener
_error_ app.g_bufferListener
g_bufferListener
= {&onBufferRelease};
undefined identifier `wl_buffer_listener`
__gshared wl_callback_listener
_error_ app.g_frameListener
g_frameListener
= {&onFrameDone};
undefined identifier `wl_callback_listener`
__gshared wl_keyboard_listener
_error_ app.g_keyboardListener
g_keyboardListener
= {
undefined identifier `wl_keyboard_listener`
&onKbKeymap, &onKbEnter, &onKbLeave, &onKbKey, &onKbModifiers, &onKbRepeatInfo }; __gshared zwp_text_input_v3_listener
_error_ app.g_tiListener
g_tiListener
= {
undefined identifier `zwp_text_input_v3_listener`
&onTiEnter, &onTiLeave, &onTiPreedit, &onTiCommitString, &onTiDeleteSurrounding, &onTiDone }; // --------------------------------------------------------------------- main int
int D main()
main
()
{ instrInit("f07_wayland");
undefined identifier `instrInit`
const
(local variable) const(char*) autoEnv
autoEnv
=
char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
("WSI_AUTO_EXIT");
(__gshared global) bool app.g_autoExit
g_autoExit
=
(local variable) const(char*) autoEnv
autoEnv
!is null && *
(local variable) const(char*) autoEnv
autoEnv
== '1';
g_display = wl_display_connect(null); if (g_display is null) {
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("SKIP: no Wayland compositor (wl_display_connect returned null)\n");
return 0; } g_registry = wsi_display_get_registry(g_display); wsi_registry_add_listener(g_registry, &g_registryListener, null);
undefined identifier `wsi_registry_add_listener`
wl_display_roundtrip(g_display);
undefined identifier `wl_display_roundtrip`
if (g_compositor is null || g_shm is null || g_wmBase is null) {
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("SKIP: compositor lacks a required global\n");
wl_display_disconnect(g_display);
undefined identifier `wl_display_disconnect`
return 0; } // The two F07-specific capability probes — each absence is itself a finding. instrEvent("text_input_manager", "present=%d", g_tiManager !is null ? 1 : 0);
undefined identifier `instrEvent`, did you mean import `instrument`?
instrEvent("seat", "present=%d", g_seat !is null ? 1 : 0);
undefined identifier `instrEvent`, did you mean import `instrument`?
wsi_wm_base_add_listener(g_wmBase, &g_wmBaseListener, null);
undefined identifier `wsi_wm_base_add_listener`
if (g_seat !is null) wsi_seat_add_listener(g_seat, &g_seatListener, null);
undefined identifier `wsi_seat_add_listener`
if (g_tiManager !is null && g_seat !is null) { g_ti = wsi_text_input_manager_get_text_input(g_tiManager, g_seat); wsi_text_input_add_listener(g_ti, &g_tiListener, null);
undefined identifier `wsi_text_input_add_listener`
instrStep("zwp_text_input_manager_v3_get_text_input");
undefined identifier `instrStep`
} g_xkbCtx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); g_surface = wsi_compositor_create_surface(g_compositor); g_xdgSurface = wsi_wm_base_get_xdg_surface(g_wmBase, g_surface); wsi_xdg_surface_add_listener(g_xdgSurface, &g_xdgSurfaceListener, null);
undefined identifier `wsi_xdg_surface_add_listener`
g_toplevel = wsi_xdg_surface_get_toplevel(g_xdgSurface); wsi_toplevel_add_listener(g_toplevel, &g_toplevelListener, null);
undefined identifier `wsi_toplevel_add_listener`
wsi_toplevel_set_title(g_toplevel, "wsi-f07-text-input");
undefined identifier `wsi_toplevel_set_title`
wsi_toplevel_set_app_id(g_toplevel, "wsi-f07-text-input");
undefined identifier `wsi_toplevel_set_app_id`
instrWindowCreated();
undefined identifier `instrWindowCreated`
wsi_surface_commit(g_surface); // mandatory no-buffer first commit
undefined identifier `wsi_surface_commit`
// Poll-based pump (the F04 lesson): a blocking wl_display_dispatch would // hang forever if the compositor goes quiet (sway throttles invisible // surfaces; an IME run waits on external events), so poll with a timeout // keeps the wall-clock auto-exit live during protocol silence. immutable
(local variable) immutable(_error_) dispFd
dispFd
= wl_display_get_fd(g_display);
undefined identifier `wl_display_get_fd`
while (
(__gshared global) bool app.g_running
g_running
)
{ while (wl_display_prepare_read(g_display) != 0)
undefined identifier `wl_display_prepare_read`
wl_display_dispatch_pending(g_display);
undefined identifier `wl_display_dispatch_pending`
wl_display_flush(g_display);
undefined identifier `wl_display_flush`
pollfd
(local variable) _error_ pfd
pfd
= {dispFd, POLLIN, 0};
undefined identifier `pollfd`
if (poll(&pfd, 1, 100) > 0)
undefined identifier `poll`
wl_display_read_events(g_display);
undefined identifier `wl_display_read_events`
else wl_display_cancel_read(g_display);
undefined identifier `wl_display_cancel_read`
if (wl_display_dispatch_pending(g_display) == -1)
undefined identifier `wl_display_dispatch_pending`
break; if (
(__gshared global) bool app.g_autoExit
g_autoExit
&& instrNowUs() > autoExitUsCap)
undefined identifier `instrNowUs`
(__gshared global) bool app.g_running
g_running
= false;
} // Teardown: children before parents. if (g_ti !is null) wsi_text_input_destroy(g_ti);
undefined identifier `wsi_text_input_destroy`
if (g_tiManager !is null) wsi_text_input_manager_destroy(g_tiManager);
undefined identifier `wsi_text_input_manager_destroy`
if (g_keyboard !is null) wsi_keyboard_destroy(g_keyboard);
undefined identifier `wsi_keyboard_destroy`
if (g_xkbState !is null) xkb_state_unref(g_xkbState);
undefined identifier `xkb_state_unref`
if (g_xkbKeymap !is null) xkb_keymap_unref(g_xkbKeymap);
undefined identifier `xkb_keymap_unref`
if (g_xkbCtx !is null) xkb_context_unref(g_xkbCtx);
undefined identifier `xkb_context_unref`
foreach (ref
(parameter) b
b
; g_buffers)
if (b.
b.handle
handle
!is null)
{ wsi_buffer_destroy(b.
b.handle
handle
);
munmap(b.
b.pixels
pixels
, b.
b.byteSize
byteSize
);
} if (g_frameCb !is null) wsi_callback_destroy(g_frameCb);
undefined identifier `wsi_callback_destroy`
wsi_toplevel_destroy(g_toplevel);
undefined identifier `wsi_toplevel_destroy`
wsi_xdg_surface_destroy(g_xdgSurface);
undefined identifier `wsi_xdg_surface_destroy`
wsi_surface_destroy(g_surface);
undefined identifier `wsi_surface_destroy`
wsi_wm_base_destroy(g_wmBase);
undefined identifier `wsi_wm_base_destroy`
if (g_seat !is null) wl_proxy_destroy(cast(wl_proxy*) g_seat);
undefined identifier `wl_proxy_destroy`
wl_proxy_destroy(cast(wl_proxy*) g_shm);
undefined identifier `wl_proxy_destroy`
wl_proxy_destroy(cast(wl_proxy*) g_compositor);
undefined identifier `wl_proxy_destroy`
wl_proxy_destroy(cast(wl_proxy*) g_registry);
undefined identifier `wl_proxy_destroy`
wl_display_disconnect(g_display);
undefined identifier `wl_display_disconnect`
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("ok: frames=%d ti_present=%d ti_commits=%u final_text=\"%s\"\n",
(__gshared global) int app.g_frames
g_frames
, g_ti !is null ? 1 : 0,
(__gshared global) uint app.g_tiCommits
g_tiCommits
,
(__gshared global) char[241] app.g_text
g_text
.
(constant) char* char[241].ptr = &g_text
ptr
);
return 0; }