SchOS/projects/schcom/proto.h
Nexoniarz 26bca020b6 licence: SchOS is GPL-2.0-or-later, no longer Apache-2.0
Nexoniarz is the sole author and SchOS was never published under
Apache-2.0, so this is a straight relicence. LICENSE is the FSF GPLv2 text,
every first-party SPDX header moves to GPL-2.0-or-later, and NOTICE,
README.md, docs/licensing.md and the site say so. projects/schfs-linux
follows the rest of the tree.

The GPL gives copyleft: a fork has to ship its source. It also lifts the
old "Linux drivers, never" rule, since GPL-2.0-only code combines with
GPL-2.0-or-later. "Or later" leaves room for GPLv3, but one binary still
has to pick one version, so docs/licensing.md now keeps Apache-2.0 and
GPLv3 code out of the kernel to keep Linux code possible there. BSD
4-clause code goes from "avoid" to "no", because the advertising clause
is GPL-incompatible.

LDLS still ships no .ko. That boundary is now project policy rather than
a legal requirement, and ldls.md, devices.md and licensing.md section 6
say so. refmod declares license=GPL, and ldls-check passes (27 checks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 08:48:45 +02:00

128 lines
4.5 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* The Schcom wire protocol.
*
* Versioned from the first commit, because SchWM and SchDE are separate
* programs: the protocol is a real compatibility surface on day one, not after
* the fact. A client sends SCHCOM_OP_HELLO with the version it speaks and the
* compositor either acknowledges it or closes the connection. Nothing else is
* accepted before the handshake.
*
* The shape is deliberately Wayland's, because Wayland support is intended
* later and it is MIT-licensed, so it can be linked (see the licensing note in
* the README). Borrowed, specifically:
*
* - a surface is not a window. It is a rectangle of pixels with no policy
* attached; placement belongs to SchWM.
* - a buffer is attached to a surface and nothing appears until COMMIT.
* Atomicity is the whole point: a client that is halfway through drawing
* must never be shown.
* - the compositor tells the client when to draw again (FRAME), rather than
* the client drawing whenever it likes. That is what stops a fast client
* from burning the machine rendering frames nobody sees.
*
* Where it deliberately differs, for now: a buffer is a System V shared memory
* id passed as an integer, not a file descriptor passed over SCM_RIGHTS.
* SCM_RIGHTS is the Wayland-compatible route and the kernel supports it, but an
* integer needs no ancillary-data handling on either side and this is v0. The
* message carries a `handle_kind` field so the switch does not become a
* protocol break.
*/
#ifndef SCHCOM_PROTO_H
#define SCHCOM_PROTO_H
#include <stdint.h>
#define SCHCOM_SOCKET_PATH "/tmp/schcom.sock"
/* Bumped on any incompatible change. v0 is provisional in the SchAPI sense:
* nothing here is frozen until 1.0. */
#define SCHCOM_VERSION 0u
enum schcom_op {
/* client -> compositor */
SCHCOM_OP_HELLO = 1,
SCHCOM_OP_CREATE_SURFACE = 2,
SCHCOM_OP_COMMIT = 3,
SCHCOM_OP_DESTROY = 4,
/* compositor -> client */
SCHCOM_OP_HELLO_ACK = 128,
SCHCOM_OP_SURFACE = 129, /* the buffer for a CREATE_SURFACE */
SCHCOM_OP_FRAME = 130, /* draw again now */
SCHCOM_OP_INPUT = 131,
SCHCOM_OP_ERROR = 132,
};
/* How the pixels are shared. Only SHMID exists today; the field exists so that
* adding SCM_RIGHTS later is a new value rather than a new protocol. */
enum schcom_handle_kind {
SCHCOM_HANDLE_SHMID = 1,
SCHCOM_HANDLE_FD = 2, /* reserved: passed over SCM_RIGHTS */
};
/* Every message begins with this. `length` counts the header itself, so a
* reader can skip a message it does not understand instead of losing sync --
* which is what lets an old compositor talk to a newer client at all. */
struct schcom_header {
uint32_t op;
uint32_t length;
uint32_t serial; /* echoed in the reply, 0 for events */
uint32_t surface; /* surface id, 0 where not applicable */
};
struct schcom_hello {
struct schcom_header hdr;
uint32_t version;
uint32_t pad;
};
struct schcom_create_surface {
struct schcom_header hdr;
uint32_t width;
uint32_t height;
int32_t x; /* v0: the client asks. SchWM will own this later. */
int32_t y;
};
/* The compositor's answer: here is your surface id and where its pixels live.
* Always 32-bit XRGB8888, stride in bytes, because a client that has to
* negotiate a format before it can draw a rectangle is a client that cannot be
* written in an afternoon. Format negotiation is a v1 problem. */
struct schcom_surface {
struct schcom_header hdr;
uint32_t handle_kind;
uint32_t handle; /* shm id when handle_kind == SHMID */
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t size;
};
/* Nothing is shown until this arrives. The damage rectangle is advisory: the
* compositor may repaint more, never less. */
struct schcom_commit {
struct schcom_header hdr;
int32_t x, y;
uint32_t width, height;
};
/* Raw-ish input, already routed to the surface that should have it. Codes are
* the Linux input event codes the kernel's /dev/input/eventN already speaks --
* translating them here would mean inventing a second table to disagree with
* the first. */
struct schcom_input {
struct schcom_header hdr;
uint32_t type; /* EV_KEY, EV_REL, ... */
uint32_t code;
int32_t value;
int32_t x, y; /* pointer position at the time of the event */
};
struct schcom_error {
struct schcom_header hdr;
uint32_t code;
uint32_t pad;
};
#endif /* SCHCOM_PROTO_H */