xcon: move wire core into workspace crate
This commit is contained in:
parent
61ec13def0
commit
d8380b3dce
11 changed files with 138 additions and 99 deletions
275
xcon/src/consts.rs
Normal file
275
xcon/src/consts.rs
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
pub const XGE_EVENT: u8 = 35;
|
||||
|
||||
pub const INPUT_DEVICE_ALL: u16 = 0;
|
||||
pub const INPUT_DEVICE_ALL_MASTER: u16 = 1;
|
||||
|
||||
pub const WINDOW_CLASS_INPUT_OUTPUT: u16 = 1;
|
||||
|
||||
pub const ATOM_NONE: u32 = 0;
|
||||
pub const ATOM_ANY: u32 = 0;
|
||||
pub const ATOM_PRIMARY: u32 = 1;
|
||||
pub const ATOM_SECONDARY: u32 = 2;
|
||||
pub const ATOM_ARC: u32 = 3;
|
||||
pub const ATOM_ATOM: u32 = 4;
|
||||
pub const ATOM_BITMAP: u32 = 5;
|
||||
pub const ATOM_CARDINAL: u32 = 6;
|
||||
pub const ATOM_COLORMAP: u32 = 7;
|
||||
pub const ATOM_CURSOR: u32 = 8;
|
||||
pub const ATOM_CUT_BUFFER0: u32 = 9;
|
||||
pub const ATOM_CUT_BUFFER1: u32 = 10;
|
||||
pub const ATOM_CUT_BUFFER2: u32 = 11;
|
||||
pub const ATOM_CUT_BUFFER3: u32 = 12;
|
||||
pub const ATOM_CUT_BUFFER4: u32 = 13;
|
||||
pub const ATOM_CUT_BUFFER5: u32 = 14;
|
||||
pub const ATOM_CUT_BUFFER6: u32 = 15;
|
||||
pub const ATOM_CUT_BUFFER7: u32 = 16;
|
||||
pub const ATOM_DRAWABLE: u32 = 17;
|
||||
pub const ATOM_FONT: u32 = 18;
|
||||
pub const ATOM_INTEGER: u32 = 19;
|
||||
pub const ATOM_PIXMAP: u32 = 20;
|
||||
pub const ATOM_POINT: u32 = 21;
|
||||
pub const ATOM_RECTANGLE: u32 = 22;
|
||||
pub const ATOM_RESOURCE_MANAGER: u32 = 23;
|
||||
pub const ATOM_RGB_COLOR_MAP: u32 = 24;
|
||||
pub const ATOM_RGB_BEST_MAP: u32 = 25;
|
||||
pub const ATOM_RGB_BLUE_MAP: u32 = 26;
|
||||
pub const ATOM_RGB_DEFAULT_MAP: u32 = 27;
|
||||
pub const ATOM_RGB_GRAY_MAP: u32 = 28;
|
||||
pub const ATOM_RGB_GREEN_MAP: u32 = 29;
|
||||
pub const ATOM_RGB_RED_MAP: u32 = 30;
|
||||
pub const ATOM_STRING: u32 = 31;
|
||||
pub const ATOM_VISUALID: u32 = 32;
|
||||
pub const ATOM_WINDOW: u32 = 33;
|
||||
pub const ATOM_WM_COMMAND: u32 = 34;
|
||||
pub const ATOM_WM_HINTS: u32 = 35;
|
||||
pub const ATOM_WM_CLIENT_MACHINE: u32 = 36;
|
||||
pub const ATOM_WM_ICON_NAME: u32 = 37;
|
||||
pub const ATOM_WM_ICON_SIZE: u32 = 38;
|
||||
pub const ATOM_WM_NAME: u32 = 39;
|
||||
pub const ATOM_WM_NORMAL_HINTS: u32 = 40;
|
||||
pub const ATOM_WM_SIZE_HINTS: u32 = 41;
|
||||
pub const ATOM_WM_ZOOM_HINTS: u32 = 42;
|
||||
pub const ATOM_MIN_SPACE: u32 = 43;
|
||||
pub const ATOM_NORM_SPACE: u32 = 44;
|
||||
pub const ATOM_MAX_SPACE: u32 = 45;
|
||||
pub const ATOM_END_SPACE: u32 = 46;
|
||||
pub const ATOM_SUPERSCRIPT_X: u32 = 47;
|
||||
pub const ATOM_SUPERSCRIPT_Y: u32 = 48;
|
||||
pub const ATOM_SUBSCRIPT_X: u32 = 49;
|
||||
pub const ATOM_SUBSCRIPT_Y: u32 = 50;
|
||||
pub const ATOM_UNDERLINE_POSITION: u32 = 51;
|
||||
pub const ATOM_UNDERLINE_THICKNESS: u32 = 52;
|
||||
pub const ATOM_STRIKEOUT_ASCENT: u32 = 53;
|
||||
pub const ATOM_STRIKEOUT_DESCENT: u32 = 54;
|
||||
pub const ATOM_ITALIC_ANGLE: u32 = 55;
|
||||
pub const ATOM_X_HEIGHT: u32 = 56;
|
||||
pub const ATOM_QUAD_WIDTH: u32 = 57;
|
||||
pub const ATOM_WEIGHT: u32 = 58;
|
||||
pub const ATOM_POINT_SIZE: u32 = 59;
|
||||
pub const ATOM_RESOLUTION: u32 = 60;
|
||||
pub const ATOM_COPYRIGHT: u32 = 61;
|
||||
pub const ATOM_NOTICE: u32 = 62;
|
||||
pub const ATOM_FONT_NAME: u32 = 63;
|
||||
pub const ATOM_FAMILY_NAME: u32 = 64;
|
||||
pub const ATOM_FULL_NAME: u32 = 65;
|
||||
pub const ATOM_CAP_HEIGHT: u32 = 66;
|
||||
pub const ATOM_WM_CLASS: u32 = 67;
|
||||
pub const ATOM_WM_TRANSIENT_FOR: u32 = 68;
|
||||
|
||||
pub const EVENT_MASK_NO_EVENT: u32 = 0;
|
||||
pub const EVENT_MASK_KEY_PRESS: u32 = 1;
|
||||
pub const EVENT_MASK_KEY_RELEASE: u32 = 2;
|
||||
pub const EVENT_MASK_BUTTON_PRESS: u32 = 4;
|
||||
pub const EVENT_MASK_BUTTON_RELEASE: u32 = 8;
|
||||
pub const EVENT_MASK_ENTER_WINDOW: u32 = 16;
|
||||
pub const EVENT_MASK_LEAVE_WINDOW: u32 = 32;
|
||||
pub const EVENT_MASK_POINTER_MOTION: u32 = 64;
|
||||
pub const EVENT_MASK_POINTER_MOTION_HINT: u32 = 128;
|
||||
pub const EVENT_MASK_BUTTON_1_MOTION: u32 = 256;
|
||||
pub const EVENT_MASK_BUTTON_2_MOTION: u32 = 512;
|
||||
pub const EVENT_MASK_BUTTON_3_MOTION: u32 = 1024;
|
||||
pub const EVENT_MASK_BUTTON_4_MOTION: u32 = 2048;
|
||||
pub const EVENT_MASK_BUTTON_5_MOTION: u32 = 4096;
|
||||
pub const EVENT_MASK_BUTTON_MOTION: u32 = 8192;
|
||||
pub const EVENT_MASK_KEYMAP_STATE: u32 = 16384;
|
||||
pub const EVENT_MASK_EXPOSURE: u32 = 32768;
|
||||
pub const EVENT_MASK_VISIBILITY_CHANGE: u32 = 65536;
|
||||
pub const EVENT_MASK_STRUCTURE_NOTIFY: u32 = 131072;
|
||||
pub const EVENT_MASK_RESIZE_REDIRECT: u32 = 262144;
|
||||
pub const EVENT_MASK_SUBSTRUCTURE_NOTIFY: u32 = 524288;
|
||||
pub const EVENT_MASK_SUBSTRUCTURE_REDIRECT: u32 = 1048576;
|
||||
pub const EVENT_MASK_FOCUS_CHANGE: u32 = 2097152;
|
||||
pub const EVENT_MASK_PROPERTY_CHANGE: u32 = 4194304;
|
||||
pub const EVENT_MASK_COLOR_MAP_CHANGE: u32 = 8388608;
|
||||
pub const EVENT_MASK_OWNER_GRAB_BUTTON: u32 = 16777216;
|
||||
|
||||
pub const XI_EVENT_MASK_DEVICE_CHANGED: u32 = 2;
|
||||
pub const XI_EVENT_MASK_KEY_PRESS: u32 = 4;
|
||||
pub const XI_EVENT_MASK_KEY_RELEASE: u32 = 8;
|
||||
pub const XI_EVENT_MASK_BUTTON_PRESS: u32 = 16;
|
||||
pub const XI_EVENT_MASK_BUTTON_RELEASE: u32 = 32;
|
||||
pub const XI_EVENT_MASK_MOTION: u32 = 64;
|
||||
pub const XI_EVENT_MASK_ENTER: u32 = 128;
|
||||
pub const XI_EVENT_MASK_LEAVE: u32 = 256;
|
||||
pub const XI_EVENT_MASK_FOCUS_IN: u32 = 512;
|
||||
pub const XI_EVENT_MASK_FOCUS_OUT: u32 = 1024;
|
||||
pub const XI_EVENT_MASK_HIERARCHY: u32 = 2048;
|
||||
pub const XI_EVENT_MASK_PROPERTY: u32 = 4096;
|
||||
pub const XI_EVENT_MASK_RAW_KEY_PRESS: u32 = 8192;
|
||||
pub const XI_EVENT_MASK_RAW_KEY_RELEASE: u32 = 16384;
|
||||
pub const XI_EVENT_MASK_RAW_BUTTON_PRESS: u32 = 32768;
|
||||
pub const XI_EVENT_MASK_RAW_BUTTON_RELEASE: u32 = 65536;
|
||||
pub const XI_EVENT_MASK_RAW_MOTION: u32 = 131072;
|
||||
pub const XI_EVENT_MASK_TOUCH_BEGIN: u32 = 262144;
|
||||
pub const XI_EVENT_MASK_TOUCH_UPDATE: u32 = 524288;
|
||||
pub const XI_EVENT_MASK_TOUCH_END: u32 = 1048576;
|
||||
pub const XI_EVENT_MASK_TOUCH_OWNERSHIP: u32 = 2097152;
|
||||
pub const XI_EVENT_MASK_RAW_TOUCH_BEGIN: u32 = 4194304;
|
||||
pub const XI_EVENT_MASK_RAW_TOUCH_UPDATE: u32 = 8388608;
|
||||
pub const XI_EVENT_MASK_RAW_TOUCH_END: u32 = 16777216;
|
||||
pub const XI_EVENT_MASK_BARRIER_HIT: u32 = 33554432;
|
||||
pub const XI_EVENT_MASK_BARRIER_LEAVE: u32 = 67108864;
|
||||
|
||||
pub const PRESENT_EVENT_MASK_NO_EVENT: u32 = 0;
|
||||
pub const PRESENT_EVENT_MASK_CONFIGURE_NOTIFY: u32 = 1;
|
||||
pub const PRESENT_EVENT_MASK_COMPLETE_NOTIFY: u32 = 2;
|
||||
pub const PRESENT_EVENT_MASK_IDLE_NOTIFY: u32 = 4;
|
||||
pub const PRESENT_EVENT_MASK_REDIRECT_NOTIFY: u32 = 8;
|
||||
|
||||
pub const INPUT_DEVICE_TYPE_MASTER_POINTER: u16 = 1;
|
||||
pub const INPUT_DEVICE_TYPE_MASTER_KEYBOARD: u16 = 2;
|
||||
pub const INPUT_DEVICE_TYPE_SLAVE_POINTER: u16 = 3;
|
||||
pub const INPUT_DEVICE_TYPE_SLAVE_KEYBOARD: u16 = 4;
|
||||
pub const INPUT_DEVICE_TYPE_FLOATING_SLAVE: u16 = 5;
|
||||
|
||||
pub const XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT: u32 = 1;
|
||||
pub const XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE: u32 = 2;
|
||||
pub const XKB_PER_CLIENT_FLAG_AUTO_RESET_CONTROLS: u32 = 4;
|
||||
pub const XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED: u32 = 8;
|
||||
pub const XKB_PER_CLIENT_FLAG_SEND_EVENT_USES_XKB_STATE: u32 = 16;
|
||||
|
||||
pub const INPUT_HIERARCHY_MASK_MASTER_ADDED: u32 = 1;
|
||||
pub const INPUT_HIERARCHY_MASK_MASTER_REMOVED: u32 = 2;
|
||||
pub const INPUT_HIERARCHY_MASK_SLAVE_ADDED: u32 = 4;
|
||||
pub const INPUT_HIERARCHY_MASK_SLAVE_REMOVED: u32 = 8;
|
||||
pub const INPUT_HIERARCHY_MASK_SLAVE_ATTACHED: u32 = 16;
|
||||
pub const INPUT_HIERARCHY_MASK_SLAVE_DETACHED: u32 = 32;
|
||||
pub const INPUT_HIERARCHY_MASK_DEVICE_ENABLED: u32 = 64;
|
||||
pub const INPUT_HIERARCHY_MASK_DEVICE_DISABLED: u32 = 128;
|
||||
|
||||
pub const GRAB_MODE_SYNC: u8 = 0;
|
||||
pub const GRAB_MODE_ASYNC: u8 = 1;
|
||||
|
||||
pub const GRAB_STATUS_SUCCESS: u8 = 0;
|
||||
pub const GRAB_STATUS_ALREADY_GRABBED: u8 = 1;
|
||||
pub const GRAB_STATUS_INVALID_TIME: u8 = 2;
|
||||
pub const GRAB_STATUS_NOT_VIEWABLE: u8 = 3;
|
||||
pub const GRAB_STATUS_FROZEN: u8 = 4;
|
||||
|
||||
pub const IMAGE_FORMAT_XY_BITMAP: u8 = 0;
|
||||
pub const IMAGE_FORMAT_XY_PIXMAP: u8 = 1;
|
||||
pub const IMAGE_FORMAT_Z_PIXMAP: u8 = 2;
|
||||
|
||||
pub const COMPOSITE_REDIRECT_AUTOMATIC: u8 = 0;
|
||||
pub const COMPOSITE_REDIRECT_MANUAL: u8 = 1;
|
||||
|
||||
pub const RENDER_PICT_TYPE_INDEXED: u8 = 0;
|
||||
pub const RENDER_PICT_TYPE_DIRECT: u8 = 1;
|
||||
|
||||
pub const PROP_MODE_REPLACE: u8 = 0;
|
||||
pub const PROP_MODE_PREPEND: u8 = 1;
|
||||
pub const PROP_MODE_APPEND: u8 = 2;
|
||||
|
||||
pub const ICCCM_WM_HINT_INPUT: i32 = 1 << 0;
|
||||
pub const ICCCM_WM_HINT_STATE: i32 = 1 << 1;
|
||||
pub const ICCCM_WM_HINT_ICON_PIXMAP: i32 = 1 << 2;
|
||||
pub const ICCCM_WM_HINT_ICON_WINDOW: i32 = 1 << 3;
|
||||
pub const ICCCM_WM_HINT_ICON_POSITION: i32 = 1 << 4;
|
||||
pub const ICCCM_WM_HINT_ICON_MASK: i32 = 1 << 5;
|
||||
pub const ICCCM_WM_HINT_WINDOW_GROUP: i32 = 1 << 6;
|
||||
pub const ICCCM_WM_HINT_X_URGENCY: i32 = 1 << 8;
|
||||
|
||||
pub const ICCCM_SIZE_HINT_US_POSITION: u32 = 1 << 0;
|
||||
pub const ICCCM_SIZE_HINT_US_SIZE: u32 = 1 << 1;
|
||||
pub const ICCCM_SIZE_HINT_P_POSITION: u32 = 1 << 2;
|
||||
pub const ICCCM_SIZE_HINT_P_SIZE: u32 = 1 << 3;
|
||||
pub const ICCCM_SIZE_HINT_P_MIN_SIZE: u32 = 1 << 4;
|
||||
pub const ICCCM_SIZE_HINT_P_MAX_SIZE: u32 = 1 << 5;
|
||||
pub const ICCCM_SIZE_HINT_P_RESIZE_INC: u32 = 1 << 6;
|
||||
pub const ICCCM_SIZE_HINT_P_ASPECT: u32 = 1 << 7;
|
||||
pub const ICCCM_SIZE_HINT_BASE_SIZE: u32 = 1 << 8;
|
||||
pub const ICCCM_SIZE_HINT_P_WIN_GRAVITY: u32 = 1 << 9;
|
||||
|
||||
pub const MWM_HINTS_FLAGS_FIELD: usize = 0;
|
||||
pub const MWM_HINTS_DECORATIONS_FIELD: usize = 2;
|
||||
pub const MWM_HINTS_DECORATIONS: u32 = 1 << 1;
|
||||
pub const MWM_DECOR_ALL: u32 = 1 << 0;
|
||||
pub const MWM_DECOR_BORDER: u32 = 1 << 1;
|
||||
pub const MWM_DECOR_TITLE: u32 = 1 << 3;
|
||||
|
||||
pub const RES_CLIENT_ID_MASK_CLIENT_XID: u32 = 1;
|
||||
pub const RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID: u32 = 2;
|
||||
|
||||
pub const INPUT_FOCUS_NONE: u8 = 0;
|
||||
pub const INPUT_FOCUS_POINTER_ROOT: u8 = 1;
|
||||
pub const INPUT_FOCUS_PARENT: u8 = 2;
|
||||
pub const INPUT_FOCUS_FOLLOW_KEYBOARD: u8 = 3;
|
||||
|
||||
pub const NOTIFY_MODE_NORMAL: u8 = 0;
|
||||
pub const NOTIFY_MODE_GRAB: u8 = 1;
|
||||
pub const NOTIFY_MODE_UNGRAB: u8 = 2;
|
||||
pub const NOTIFY_MODE_WHILE_GRABBED: u8 = 3;
|
||||
|
||||
pub const NOTIFY_DETAIL_ANCESTOR: u8 = 0;
|
||||
pub const NOTIFY_DETAIL_VIRTUAL: u8 = 1;
|
||||
pub const NOTIFY_DETAIL_INFERIOR: u8 = 2;
|
||||
pub const NOTIFY_DETAIL_NONLINEAR: u8 = 3;
|
||||
pub const NOTIFY_DETAIL_NONLINEAR_VIRTUAL: u8 = 4;
|
||||
pub const NOTIFY_DETAIL_POINTER: u8 = 5;
|
||||
pub const NOTIFY_DETAIL_POINTER_ROOT: u8 = 6;
|
||||
pub const NOTIFY_DETAIL_NONE: u8 = 7;
|
||||
|
||||
pub const ICCCM_WM_STATE_WITHDRAWN: u32 = 0;
|
||||
pub const ICCCM_WM_STATE_NORMAL: u32 = 1;
|
||||
pub const ICCCM_WM_STATE_ICONIC: u32 = 3;
|
||||
|
||||
pub const _NET_WM_STATE_REMOVE: u32 = 0;
|
||||
pub const _NET_WM_STATE_ADD: u32 = 1;
|
||||
pub const _NET_WM_STATE_TOGGLE: u32 = 2;
|
||||
|
||||
pub const _NET_WM_MOVERESIZE_SIZE_TOPLEFT: u32 = 0;
|
||||
pub const _NET_WM_MOVERESIZE_SIZE_TOP: u32 = 1;
|
||||
pub const _NET_WM_MOVERESIZE_SIZE_TOPRIGHT: u32 = 2;
|
||||
pub const _NET_WM_MOVERESIZE_SIZE_RIGHT: u32 = 3;
|
||||
pub const _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT: u32 = 4;
|
||||
pub const _NET_WM_MOVERESIZE_SIZE_BOTTOM: u32 = 5;
|
||||
pub const _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT: u32 = 6;
|
||||
pub const _NET_WM_MOVERESIZE_SIZE_LEFT: u32 = 7;
|
||||
pub const _NET_WM_MOVERESIZE_MOVE: u32 = 8;
|
||||
pub const _NET_WM_MOVERESIZE_SIZE_KEYBOARD: u32 = 9;
|
||||
pub const _NET_WM_MOVERESIZE_MOVE_KEYBOARD: u32 = 10;
|
||||
pub const _NET_WM_MOVERESIZE_CANCEL: u32 = 11;
|
||||
|
||||
pub const STACK_MODE_ABOVE: u32 = 0;
|
||||
pub const STACK_MODE_BELOW: u32 = 1;
|
||||
pub const STACK_MODE_TOP_IF: u32 = 2;
|
||||
pub const STACK_MODE_BOTTOM_IF: u32 = 3;
|
||||
pub const STACK_MODE_OPPOSITE: u32 = 4;
|
||||
|
||||
pub const CONFIG_WINDOW_X: u16 = 1;
|
||||
pub const CONFIG_WINDOW_Y: u16 = 2;
|
||||
pub const CONFIG_WINDOW_WIDTH: u16 = 4;
|
||||
pub const CONFIG_WINDOW_HEIGHT: u16 = 8;
|
||||
pub const CONFIG_WINDOW_BORDER_WIDTH: u16 = 16;
|
||||
pub const CONFIG_WINDOW_SIBLING: u16 = 32;
|
||||
pub const CONFIG_WINDOW_STACK_MODE: u16 = 64;
|
||||
|
||||
pub const SET_SELECTION_OWNER: u8 = 0;
|
||||
pub const SELECTION_WINDOW_DESTROY: u8 = 1;
|
||||
pub const SELECTION_CLIENT_CLOSE: u8 = 2;
|
||||
|
||||
pub const SET_SELECTION_OWNER_MASK: u32 = 1;
|
||||
pub const SELECTION_WINDOW_DESTROY_MASK: u32 = 2;
|
||||
pub const SELECTION_CLIENT_CLOSE_MASK: u32 = 4;
|
||||
73
xcon/src/formatter.rs
Normal file
73
xcon/src/formatter.rs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
use {
|
||||
crate::Message,
|
||||
jay_utils::buf::DynamicBuf,
|
||||
std::rc::Rc,
|
||||
uapi::{AssertPacked, OwnedFd, Packed},
|
||||
};
|
||||
|
||||
pub struct Formatter<'a> {
|
||||
fds: &'a mut Vec<Rc<OwnedFd>>,
|
||||
buf: &'a mut DynamicBuf,
|
||||
ext_opcode: u8,
|
||||
}
|
||||
|
||||
impl<'a> Formatter<'a> {
|
||||
pub fn new(fds: &'a mut Vec<Rc<OwnedFd>>, buf: &'a mut DynamicBuf, ext_opcode: u8) -> Self {
|
||||
Self {
|
||||
fds,
|
||||
buf,
|
||||
ext_opcode,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ext_opcode(&self) -> u8 {
|
||||
self.ext_opcode
|
||||
}
|
||||
|
||||
pub fn pad(&mut self, pad: usize) {
|
||||
static BUF: [u8; 8] = [0; 8];
|
||||
self.buf.extend_from_slice(&BUF[..pad]);
|
||||
}
|
||||
|
||||
pub fn pad_to(&mut self, size: usize) {
|
||||
static BUF: [u8; 8] = [0; 8];
|
||||
while self.buf.len() < size {
|
||||
let len = (size - self.buf.len()).min(8);
|
||||
self.buf.extend_from_slice(&BUF[..len]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn align(&mut self, alignment: usize) {
|
||||
static BUF: [u8; 8] = [0; 8];
|
||||
let len = self.buf.len().wrapping_neg() & (alignment - 1);
|
||||
self.buf.extend_from_slice(&BUF[..len]);
|
||||
}
|
||||
|
||||
pub fn write_packed<T: Packed + ?Sized>(&mut self, t: &T) {
|
||||
self.buf.extend_from_slice(uapi::as_bytes(t));
|
||||
}
|
||||
|
||||
pub fn write_list<'b, T: Message<'b>>(&mut self, t: &[T]) {
|
||||
if T::IS_POD {
|
||||
self.buf
|
||||
.extend_from_slice(uapi::as_bytes(unsafe { AssertPacked::new(t) }));
|
||||
} else {
|
||||
for t in t {
|
||||
t.serialize(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_bytes(&mut self, b: &[u8]) {
|
||||
self.buf.extend_from_slice(b);
|
||||
}
|
||||
|
||||
pub fn write_request_length(&mut self) {
|
||||
let len: u16 = (self.buf.len() / 4) as u16;
|
||||
self.buf[2..4].copy_from_slice(&len.to_ne_bytes());
|
||||
}
|
||||
|
||||
pub fn add_fd(&mut self, fd: &Rc<OwnedFd>) {
|
||||
self.fds.push(fd.clone());
|
||||
}
|
||||
}
|
||||
95
xcon/src/lib.rs
Normal file
95
xcon/src/lib.rs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
pub use {
|
||||
formatter::Formatter,
|
||||
parser::Parser,
|
||||
wire_type::{Message, Request, SendEvent, XEvent},
|
||||
};
|
||||
use {
|
||||
bstr::BString,
|
||||
jay_bufio::BufIoError,
|
||||
jay_io_uring::IoUringError,
|
||||
jay_utils::oserror::OsError,
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub mod consts;
|
||||
mod formatter;
|
||||
mod parser;
|
||||
mod wire_type;
|
||||
pub mod xauthority;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XconError {
|
||||
#[error("Unexpected EOF")]
|
||||
UnexpectedEof,
|
||||
#[error("Buffer slice is not properly aligned")]
|
||||
UnalignedSlice,
|
||||
#[error("Neither XAUTHORITY nor HOME is set")]
|
||||
HomeNotSet,
|
||||
#[error("Could not read Xauthority file")]
|
||||
ReadXAuthority(#[source] std::io::Error),
|
||||
#[error("Display field in Xauthority could not be parsed")]
|
||||
InvalidAuthorityDisplay,
|
||||
#[error("The DISPLAY is not set")]
|
||||
DisplayNotSet,
|
||||
#[error("DISPLAY contains an invalid value")]
|
||||
InvalidDisplayFormat,
|
||||
#[error("Could not create a unix socket")]
|
||||
CreateSocket(#[source] OsError),
|
||||
#[error("Could not connect to Xserver")]
|
||||
ConnectSocket(#[source] IoUringError),
|
||||
#[error("Could not retrive the hostname")]
|
||||
Hostname(#[source] OsError),
|
||||
#[error("Server did not send enough fds")]
|
||||
NotEnoughFds,
|
||||
#[error("Server rejected our connection attempt: {0}")]
|
||||
Connect(BString),
|
||||
#[error("Server requires additional authentication: {0}")]
|
||||
Authenticate(BString),
|
||||
#[error(transparent)]
|
||||
BufIoError(#[from] BufIoError),
|
||||
#[error("The server did not send a reply to a request")]
|
||||
MissingReply,
|
||||
#[error("The server did not send fds with a reply")]
|
||||
MissingFds,
|
||||
#[error("The server sent a message with an excessive size")]
|
||||
ExcessiveMessageSize,
|
||||
#[error(transparent)]
|
||||
XconError(Rc<XconError>),
|
||||
#[error("The server does not support the `{0}` extension")]
|
||||
ExtensionUnavailable(&'static str),
|
||||
#[error("The server returned error {0}")]
|
||||
CoreError(u8),
|
||||
#[error("The extension `{0}` returned error {1}")]
|
||||
ExtensionError(&'static str, u8),
|
||||
#[error("The connection to the server has already been closed")]
|
||||
Dead,
|
||||
#[error("Could not query the `{0}` extension")]
|
||||
QueryExtension(BString, #[source] Box<XconError>),
|
||||
#[error("All available xids have been used")]
|
||||
XidExhausted,
|
||||
#[error("Enum contains an unknown variant")]
|
||||
UnknownEnumVariant,
|
||||
#[error("Could not query the render pict formats")]
|
||||
QueryPictFormats(#[source] Box<XconError>),
|
||||
#[error("The server does not support the picture format for cursors")]
|
||||
CursorFormatNotSupported,
|
||||
#[error("Could not create a pixmap")]
|
||||
CreatePixmap(#[source] Box<XconError>),
|
||||
#[error("Could not create a graphics context")]
|
||||
CreateGc(#[source] Box<XconError>),
|
||||
#[error("Could not upload an image")]
|
||||
PutImage(#[source] Box<XconError>),
|
||||
#[error("Could not create a picture")]
|
||||
CreatePicture(#[source] Box<XconError>),
|
||||
#[error("Could not create a cursor")]
|
||||
CreateCursor(#[source] Box<XconError>),
|
||||
#[error("Property has an invalid type")]
|
||||
InvalidPropertyType,
|
||||
#[error("Property has an invalid format. Expected: {0}; Actual: {1}")]
|
||||
InvalidPropertyFormat(u8, u8),
|
||||
#[error("Length of the property data is not a multiple of its format")]
|
||||
IrregularPropertyLength,
|
||||
#[error("The property is not set")]
|
||||
PropertyUnavailable,
|
||||
}
|
||||
137
xcon/src/parser.rs
Normal file
137
xcon/src/parser.rs
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
use {
|
||||
crate::{Message, XconError},
|
||||
bstr::{BStr, ByteSlice},
|
||||
jay_utils::ptr_ext::PtrExt,
|
||||
std::{borrow::Cow, rc::Rc},
|
||||
uapi::{OwnedFd, Pod},
|
||||
};
|
||||
|
||||
pub struct Parser<'a> {
|
||||
pos: usize,
|
||||
buf: &'a [u8],
|
||||
fds_pos: usize,
|
||||
fds: Vec<Rc<OwnedFd>>,
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn new(buf: &'a [u8], fds: Vec<Rc<OwnedFd>>) -> Self {
|
||||
Self {
|
||||
buf,
|
||||
pos: 0,
|
||||
fds,
|
||||
fds_pos: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eof(&self) -> bool {
|
||||
self.pos == self.buf.len()
|
||||
}
|
||||
|
||||
fn rem(&self) -> usize {
|
||||
self.buf.len() - self.pos
|
||||
}
|
||||
|
||||
pub fn unmarshal<T: Message<'a>>(&mut self) -> Result<T, XconError> {
|
||||
T::deserialize(self)
|
||||
}
|
||||
|
||||
pub fn pad(&mut self, new: usize) -> Result<(), XconError> {
|
||||
if new > self.buf.len() - self.pos {
|
||||
return Err(XconError::UnexpectedEof);
|
||||
}
|
||||
self.pos += new;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn align(&mut self, n: usize) -> Result<(), XconError> {
|
||||
let new = self.pos + (self.pos.wrapping_neg() & (n - 1));
|
||||
if new > self.buf.len() {
|
||||
return Err(XconError::UnexpectedEof);
|
||||
}
|
||||
self.pos = new;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_fd(&mut self) -> Result<Rc<OwnedFd>, XconError> {
|
||||
if self.fds_pos >= self.fds.len() {
|
||||
return Err(XconError::NotEnoughFds);
|
||||
}
|
||||
self.fds_pos += 1;
|
||||
Ok(self.fds[self.fds_pos - 1].clone())
|
||||
}
|
||||
|
||||
pub fn read_pod<T: Pod>(&mut self) -> Result<T, XconError> {
|
||||
match uapi::pod_read_init(&self.buf[self.pos..]) {
|
||||
Ok(v) => {
|
||||
self.pos += size_of::<T>();
|
||||
Ok(v)
|
||||
}
|
||||
_ => Err(XconError::UnexpectedEof),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_list_slice<T: Message<'a> + Pod>(
|
||||
&mut self,
|
||||
n: Option<usize>,
|
||||
) -> Result<&'a [T], XconError> {
|
||||
let n = match n {
|
||||
Some(n) => n,
|
||||
_ => self.rem() / size_of::<T>(),
|
||||
};
|
||||
let len = size_of::<T>() * n;
|
||||
if len > self.rem() {
|
||||
return Err(XconError::UnexpectedEof);
|
||||
}
|
||||
if self.buf[self.pos..].as_ptr() as usize & (align_of::<T>() - 1) != 0 {
|
||||
return Err(XconError::UnalignedSlice);
|
||||
}
|
||||
let res =
|
||||
unsafe { std::slice::from_raw_parts(self.buf.as_ptr().add(self.pos) as *const T, n) };
|
||||
self.pos += len;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn read_list<T: Message<'a> + Clone>(
|
||||
&mut self,
|
||||
n: Option<usize>,
|
||||
) -> Result<Cow<'a, [T]>, XconError> {
|
||||
let mut res = vec![];
|
||||
if let Some(n) = n {
|
||||
for _ in 0..n {
|
||||
res.push(T::deserialize(self)?);
|
||||
}
|
||||
} else {
|
||||
while !self.eof() {
|
||||
res.push(T::deserialize(self)?);
|
||||
}
|
||||
}
|
||||
Ok(res.into())
|
||||
}
|
||||
|
||||
pub fn read_bytes<const N: usize>(&mut self) -> Result<&'a [u8; N], XconError> {
|
||||
if N > self.rem() {
|
||||
return Err(XconError::UnexpectedEof);
|
||||
}
|
||||
let res = unsafe { self.buf.as_ptr().add(self.pos).cast::<[u8; N]>().deref() };
|
||||
self.pos += N;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn read_slice(&mut self, n: usize) -> Result<&'a [u8], XconError> {
|
||||
if n > self.rem() {
|
||||
return Err(XconError::UnexpectedEof);
|
||||
}
|
||||
let res = &self.buf[self.pos..self.pos + n];
|
||||
self.pos += n;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn read_string(&mut self, n: usize) -> Result<&'a BStr, XconError> {
|
||||
if n > self.rem() {
|
||||
return Err(XconError::UnexpectedEof);
|
||||
}
|
||||
let res = &self.buf[self.pos..self.pos + n];
|
||||
self.pos += n;
|
||||
Ok(res.as_bstr())
|
||||
}
|
||||
}
|
||||
153
xcon/src/wire_type.rs
Normal file
153
xcon/src/wire_type.rs
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
use {
|
||||
crate::{Formatter, Parser, XconError},
|
||||
bstr::{BStr, ByteSlice},
|
||||
std::{borrow::Cow, fmt::Debug, rc::Rc},
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
#[cold]
|
||||
fn unimplemented() -> ! {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
pub unsafe trait Message<'a>: Clone + Debug + 'a {
|
||||
type Generic<'b>: Message<'b>;
|
||||
const IS_POD: bool;
|
||||
const HAS_FDS: bool;
|
||||
|
||||
fn serialize(&self, formatter: &mut Formatter) {
|
||||
let _ = formatter;
|
||||
unimplemented()
|
||||
}
|
||||
|
||||
fn deserialize(parser: &mut Parser<'a>) -> Result<Self, XconError> {
|
||||
let _ = parser;
|
||||
unimplemented()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Request<'a>: Message<'a> {
|
||||
type Reply: Message<'static>;
|
||||
const EXTENSION: Option<usize>;
|
||||
const IS_VOID: bool;
|
||||
}
|
||||
|
||||
pub trait XEvent<'a>: Message<'a> {
|
||||
const EXTENSION: Option<usize>;
|
||||
const OPCODE: u16;
|
||||
}
|
||||
|
||||
macro_rules! simple {
|
||||
($ty:ty) => {
|
||||
unsafe impl Message<'_> for $ty {
|
||||
type Generic<'b> = $ty;
|
||||
const IS_POD: bool = true;
|
||||
const HAS_FDS: bool = false;
|
||||
|
||||
fn serialize(&self, formatter: &mut Formatter) {
|
||||
formatter.write_packed(self);
|
||||
}
|
||||
|
||||
fn deserialize(parser: &mut Parser<'_>) -> Result<Self, XconError> {
|
||||
parser.read_pod()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
simple!(u8);
|
||||
simple!(i8);
|
||||
simple!(u16);
|
||||
simple!(i16);
|
||||
simple!(u32);
|
||||
simple!(i32);
|
||||
simple!(u64);
|
||||
simple!(i64);
|
||||
|
||||
unsafe impl<'a> Message<'a> for () {
|
||||
type Generic<'b> = ();
|
||||
const IS_POD: bool = false;
|
||||
const HAS_FDS: bool = false;
|
||||
}
|
||||
|
||||
unsafe impl<'a> Message<'a> for &'a BStr {
|
||||
type Generic<'b> = &'b BStr;
|
||||
const IS_POD: bool = true;
|
||||
const HAS_FDS: bool = false;
|
||||
|
||||
fn serialize(&self, formatter: &mut Formatter) {
|
||||
formatter.write_packed(self.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: Message<'a>> Message<'a> for &'a [T] {
|
||||
type Generic<'b> = &'b [T::Generic<'b>];
|
||||
const IS_POD: bool = false;
|
||||
const HAS_FDS: bool = false;
|
||||
|
||||
fn serialize(&self, formatter: &mut Formatter) {
|
||||
formatter.write_list(self);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T> Message<'a> for Cow<'a, [T]>
|
||||
where
|
||||
T: Message<'a>,
|
||||
{
|
||||
type Generic<'b> = Cow<'b, [T::Generic<'b>]>;
|
||||
const IS_POD: bool = false;
|
||||
const HAS_FDS: bool = false;
|
||||
|
||||
fn serialize(&self, formatter: &mut Formatter) {
|
||||
formatter.write_list(self);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> Message<'a> for Rc<OwnedFd> {
|
||||
type Generic<'b> = Rc<OwnedFd>;
|
||||
const IS_POD: bool = false;
|
||||
const HAS_FDS: bool = true;
|
||||
|
||||
fn serialize(&self, formatter: &mut Formatter) {
|
||||
formatter.add_fd(self);
|
||||
}
|
||||
|
||||
fn deserialize(parser: &mut Parser<'a>) -> Result<Self, XconError> {
|
||||
parser.read_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SendEvent {
|
||||
pub propagate: u8,
|
||||
pub destination: u32,
|
||||
pub event_mask: u32,
|
||||
}
|
||||
|
||||
unsafe impl<'a> Message<'a> for SendEvent {
|
||||
type Generic<'b> = SendEvent;
|
||||
const IS_POD: bool = false;
|
||||
const HAS_FDS: bool = false;
|
||||
|
||||
fn serialize(&self, formatter: &mut Formatter) {
|
||||
{
|
||||
let propagate_bytes = self.propagate.to_ne_bytes();
|
||||
let destination_bytes = self.destination.to_ne_bytes();
|
||||
let event_mask_bytes = self.event_mask.to_ne_bytes();
|
||||
formatter.write_bytes(&[
|
||||
25,
|
||||
propagate_bytes[0],
|
||||
0,
|
||||
0,
|
||||
destination_bytes[0],
|
||||
destination_bytes[1],
|
||||
destination_bytes[2],
|
||||
destination_bytes[3],
|
||||
event_mask_bytes[0],
|
||||
event_mask_bytes[1],
|
||||
event_mask_bytes[2],
|
||||
event_mask_bytes[3],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
97
xcon/src/xauthority.rs
Normal file
97
xcon/src/xauthority.rs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
use {
|
||||
crate::XconError,
|
||||
bstr::{BString, ByteSlice},
|
||||
std::{fs::File, io::Read},
|
||||
};
|
||||
|
||||
pub const LOCAL: u16 = 256;
|
||||
|
||||
pub const MIT_MAGIC_COOKIE: &[u8] = b"MIT-MAGIC-COOKIE-1";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct XAuthority {
|
||||
pub family: u16,
|
||||
pub host: BString,
|
||||
pub display: u32,
|
||||
pub method: BString,
|
||||
pub value: BString,
|
||||
}
|
||||
|
||||
impl XAuthority {
|
||||
pub fn load() -> Result<Vec<XAuthority>, XconError> {
|
||||
let path = 'path: {
|
||||
if let Ok(p) = std::env::var("XAUTHORITY") {
|
||||
break 'path p;
|
||||
}
|
||||
if let Ok(home) = std::env::var("HOME") {
|
||||
break 'path format!("{home}/.Xauthority");
|
||||
}
|
||||
return Err(XconError::HomeNotSet);
|
||||
};
|
||||
let mut buf = vec![];
|
||||
if let Err(e) = File::open(path).and_then(|mut f| f.read_to_end(&mut buf)) {
|
||||
return Err(XconError::ReadXAuthority(e));
|
||||
}
|
||||
Parser::parse(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
struct Parser<'a> {
|
||||
pos: usize,
|
||||
buf: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
fn parse(buf: &[u8]) -> Result<Vec<XAuthority>, XconError> {
|
||||
let mut slf = Parser { pos: 0, buf };
|
||||
let mut res = vec![];
|
||||
while slf.rem() > 0 {
|
||||
res.push(slf.parse_one()?);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn rem(&self) -> usize {
|
||||
self.buf.len() - self.pos
|
||||
}
|
||||
|
||||
fn parse_one(&mut self) -> Result<XAuthority, XconError> {
|
||||
Ok(XAuthority {
|
||||
family: self.read_u16()?,
|
||||
host: self.read_string()?,
|
||||
display: {
|
||||
let s = self.read_string()?;
|
||||
match s.to_str() {
|
||||
Ok(s) => match s.parse() {
|
||||
Ok(v) => v,
|
||||
_ => return Err(XconError::InvalidAuthorityDisplay),
|
||||
},
|
||||
_ => return Err(XconError::InvalidAuthorityDisplay),
|
||||
}
|
||||
},
|
||||
method: self.read_string()?,
|
||||
value: self.read_string()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn read_u16(&mut self) -> Result<u16, XconError> {
|
||||
if self.rem() < 2 {
|
||||
return Err(XconError::UnexpectedEof);
|
||||
}
|
||||
let bytes = [self.buf[self.pos], self.buf[self.pos + 1]];
|
||||
self.pos += 2;
|
||||
Ok(u16::from_be_bytes(bytes))
|
||||
}
|
||||
|
||||
fn read_string(&mut self) -> Result<BString, XconError> {
|
||||
let len = self.read_u16()? as usize;
|
||||
if self.rem() < len {
|
||||
log::info!("rem = {}; len = {}", self.rem(), len);
|
||||
return Err(XconError::UnexpectedEof);
|
||||
}
|
||||
let res = self.buf[self.pos..self.pos + len].to_vec();
|
||||
self.pos += len;
|
||||
let res = res.into();
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue