Files
nt-lite/code/user/tests/desktop_smoke/desktop_smoke.c
T

137 lines
5.6 KiB
C

// Desktop protocol smoke test. Exercises window ownership, shared surfaces, z-order, focus, capture, and pointer policy.
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <ntlite/desktop.h>
#include <ntlite/syscall.h>
#define TEST_WIDTH 160u
#define TEST_HEIGHT 100u
// Exits without depending on a compiler runtime return path.
static void exit_now(int code) {
while (true) SysExitProcess(code);
}
static void print(const char* text) {
SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) };
(void)SysWriteConsole(&request);
}
static void print_status(KSTATUS status) {
static const char digits[] = "0123456789ABCDEF";
char buffer[11] = "0x00000000";
for (uint32_t i = 0; i < 8u; ++i)
buffer[2u + i] = digits[(status >> ((7u - i) * 4u)) & 0xFu];
print(buffer);
}
// Reports one failed desktop-smoke operation with its native status.
static void fail_status(const char* operation, KSTATUS status, int code) {
print("desktop_smoke: ");
print(operation);
print(" failed status=");
print_status(status);
print("\n");
exit_now(code);
}
// Reports one failed desktop-smoke invariant.
static void fail(const char* message, int code) {
print("desktop_smoke: ");
print(message);
print("\n");
exit_now(code);
}
// Fills one mapped XRGB surface with a deterministic test pattern.
static void fill_surface(void* base, uint32_t pitch) {
uint8_t* bytes = (uint8_t*)base;
for (uint32_t y = 0; y < TEST_HEIGHT; ++y) {
uint32_t* row = (uint32_t*)(bytes + (size_t)y * pitch);
for (uint32_t x = 0; x < TEST_WIDTH; ++x)
row[x] = 0x00202080u + ((x & 0x3Fu) << 16) + ((y & 0x3Fu) << 8);
}
}
// Exercises the first final-shaped DWM client contract.
int main(void) {
SYS_HANDLE desktop = SYS_HANDLE_INVALID;
KSTATUS status = NtlDesktopConnect(&desktop);
if (!KSUCCESS(status)) fail_status("connect /Sessions/0/Desktop", status, 1);
SYS_HANDLE surface = SYS_HANDLE_INVALID;
SYS_CREATE_SURFACE_REQUEST createSurface;
memset(&createSurface, 0, sizeof(createSurface));
createSurface.Size = sizeof(createSurface);
createSurface.Width = TEST_WIDTH;
createSurface.Height = TEST_HEIGHT;
createSurface.Format = SYS_SURFACE_FORMAT_XRGB8888;
createSurface.Flags = SYS_SURFACE_FLAG_NONE;
createSurface.HandleOut = &surface;
status = SysCreateSurface(&createSurface);
if (!KSUCCESS(status)) fail_status("create surface", status, 2);
void* base = (void*)0;
uint32_t pitch = 0;
status = SysMapSurface(surface, SYS_SURFACE_MAP_READ | SYS_SURFACE_MAP_WRITE, &base, &pitch);
if (!KSUCCESS(status)) fail_status("map surface", status, 3);
if (!base || pitch < TEST_WIDTH * sizeof(uint32_t)) fail("invalid surface mapping", 3);
fill_surface(base, pitch);
DISPLAY_RECT bounds = { 40, 40, (int32_t)TEST_WIDTH, (int32_t)TEST_HEIGHT };
NTL_WINDOW_ID window = 0;
status = NtlDesktopCreateWindow(desktop, &bounds, &window);
if (!KSUCCESS(status)) fail_status("create window", status, 4);
if (window == 0) fail("create window returned zero ID", 4);
status = NtlDesktopAttachSurface(desktop, window, surface);
if (!KSUCCESS(status)) fail_status("attach surface", status, 5);
status = NtlDesktopSetVisible(desktop, window, 1u);
if (!KSUCCESS(status)) fail_status("show window", status, 6);
DISPLAY_RECT damage = { 0, 0, (int32_t)TEST_WIDTH, (int32_t)TEST_HEIGHT };
status = SysCommitSurface(surface, &damage, 1u, 0);
if (!KSUCCESS(status)) fail_status("commit surface", status, 7);
NTL_DESKTOP_REPLY query;
memset(&query, 0, sizeof(query));
status = NtlDesktopQueryWindow(desktop, window, &query);
if (!KSUCCESS(status)) fail_status("query window", status, 8);
if (query.WindowId != window || !query.Visible || !query.HasSurface ||
query.SurfaceWidth != TEST_WIDTH || query.SurfaceHeight != TEST_HEIGHT)
fail("query window returned inconsistent state", 8);
status = NtlDesktopRequestFocus(desktop, window);
if (!KSUCCESS(status)) fail_status("request focus", status, 9);
status = NtlDesktopSetPointerMode(desktop, window, NTL_DESKTOP_POINTER_CONFINED);
if (!KSUCCESS(status)) fail_status("set confined pointer mode", status, 10);
status = NtlDesktopRequestCapture(desktop, window);
if (!KSUCCESS(status)) fail_status("request capture", status, 11);
status = NtlDesktopSetPointerMode(desktop, window, NTL_DESKTOP_POINTER_RELATIVE_LOCKED);
if (!KSUCCESS(status)) fail_status("set relative-locked pointer mode", status, 12);
status = NtlDesktopReleaseCapture(desktop, window);
if (!KSUCCESS(status)) fail_status("release capture", status, 13);
status = NtlDesktopSetPointerMode(desktop, window, NTL_DESKTOP_POINTER_FREE);
if (!KSUCCESS(status)) fail_status("set free pointer mode", status, 14);
bounds.X += 24;
bounds.Y += 18;
status = NtlDesktopSetBounds(desktop, window, &bounds);
if (!KSUCCESS(status)) fail_status("set bounds", status, 15);
status = NtlDesktopLowerWindow(desktop, window);
if (!KSUCCESS(status)) fail_status("lower window", status, 16);
status = NtlDesktopRaiseWindow(desktop, window);
if (!KSUCCESS(status)) fail_status("raise window", status, 17);
status = NtlDesktopDetachSurface(desktop, window);
if (!KSUCCESS(status)) fail_status("detach surface", status, 18);
status = NtlDesktopDestroyWindow(desktop, window);
if (!KSUCCESS(status)) fail_status("destroy window", status, 19);
(void)SysUnmapSurface(base);
(void)SysCloseHandle(surface);
(void)NtlDesktopClose(desktop);
print("desktop_smoke: PASS\n");
return 0;
}