milestone: 22 KF6 enabled, blake3 placeholders removed, text-login fixed
- kf6-knewstuff/kwallet: removed all-zero blake3 placeholders - CONSOLE-TO-KDE-DESKTOP-PLAN.md: 20→22 KF6 enabled count - BOOT-PROCESS-IMPROVEMENT-PLAN.md: text-login→graphical greeter path - D-Bus session/kwin compositor/sessiond enhancements from Wave tasks - Only kirigami remains suppressed (QML-dependent, environmental gate) Zero warnings. 24 commits total.
This commit is contained in:
@@ -6,16 +6,19 @@
|
||||
//
|
||||
// NOTE: This is a bounded proof scaffold, not a real compositor runtime proof.
|
||||
// Known limitations: framebuffer compositing uses private heap memory (not real
|
||||
// vesad), SHM fd passing uses payload bytes (not Unix SCM_RIGHTS), wire encoding
|
||||
// uses NUL-terminated strings (not padded Wayland format).
|
||||
// vesad), only a bounded subset of Wayland is implemented, and the compositor
|
||||
// still paints directly into a simple backing buffer instead of doing real KMS
|
||||
// scanout.
|
||||
//
|
||||
// Supported protocols: wl_display, wl_registry, wl_compositor, wl_shm, wl_shm_pool,
|
||||
// wl_surface, wl_shell, wl_shell_surface, wl_seat, wl_output, wl_callback, wl_buffer.
|
||||
//
|
||||
// Wire format: [sender:u32] [msg_size:u16|opcode:u16] [args...]
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::{Read, Write};
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::mem;
|
||||
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::sync::{atomic::{AtomicU32, Ordering}, Mutex};
|
||||
|
||||
@@ -23,6 +26,111 @@ fn map_framebuffer(_phys: usize, size: usize) -> Vec<u8> {
|
||||
vec![0u8; size]
|
||||
}
|
||||
|
||||
fn push_u32(buf: &mut Vec<u8>, value: u32) {
|
||||
buf.extend_from_slice(&value.to_le_bytes());
|
||||
}
|
||||
|
||||
fn push_i32(buf: &mut Vec<u8>, value: i32) {
|
||||
buf.extend_from_slice(&value.to_le_bytes());
|
||||
}
|
||||
|
||||
fn push_header(buf: &mut Vec<u8>, object_id: u32, opcode: u16, payload_len: usize) {
|
||||
push_u32(buf, object_id);
|
||||
let size = (8 + payload_len) as u32;
|
||||
push_u32(buf, (size << 16) | u32::from(opcode));
|
||||
}
|
||||
|
||||
fn pad_to_4(buf: &mut Vec<u8>) {
|
||||
while buf.len() % 4 != 0 {
|
||||
buf.push(0);
|
||||
}
|
||||
}
|
||||
|
||||
fn push_wayland_string(buf: &mut Vec<u8>, value: &str) {
|
||||
let bytes = value.as_bytes();
|
||||
push_u32(buf, (bytes.len() + 1) as u32);
|
||||
buf.extend_from_slice(bytes);
|
||||
buf.push(0);
|
||||
pad_to_4(buf);
|
||||
}
|
||||
|
||||
fn read_u32(data: &[u8], cursor: &mut usize) -> Result<u32, String> {
|
||||
if *cursor + 4 > data.len() {
|
||||
return Err(String::from("unexpected end of message while reading u32"));
|
||||
}
|
||||
|
||||
let value = u32::from_le_bytes([
|
||||
data[*cursor],
|
||||
data[*cursor + 1],
|
||||
data[*cursor + 2],
|
||||
data[*cursor + 3],
|
||||
]);
|
||||
*cursor += 4;
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn read_wayland_string(data: &[u8], cursor: &mut usize) -> Result<String, String> {
|
||||
let length = read_u32(data, cursor)? as usize;
|
||||
if length == 0 {
|
||||
return Ok(String::new());
|
||||
}
|
||||
if *cursor + length > data.len() {
|
||||
return Err(String::from("unexpected end of message while reading string"));
|
||||
}
|
||||
|
||||
let bytes = &data[*cursor..*cursor + length];
|
||||
let string_len = bytes.iter().position(|byte| *byte == 0).unwrap_or(bytes.len());
|
||||
*cursor += length;
|
||||
while *cursor % 4 != 0 {
|
||||
*cursor += 1;
|
||||
}
|
||||
|
||||
std::str::from_utf8(&bytes[..string_len])
|
||||
.map(str::to_owned)
|
||||
.map_err(|err| format!("invalid UTF-8 in Wayland string: {err}"))
|
||||
}
|
||||
|
||||
fn recv_with_rights(stream: &mut UnixStream, data: &mut [u8]) -> std::io::Result<(usize, VecDeque<RawFd>)> {
|
||||
let mut iov = libc::iovec {
|
||||
iov_base: data.as_mut_ptr().cast(),
|
||||
iov_len: data.len(),
|
||||
};
|
||||
let mut control = [0u8; 256];
|
||||
let mut header = libc::msghdr {
|
||||
msg_name: std::ptr::null_mut(),
|
||||
msg_namelen: 0,
|
||||
msg_iov: &mut iov,
|
||||
msg_iovlen: 1,
|
||||
msg_control: control.as_mut_ptr().cast(),
|
||||
msg_controllen: control.len(),
|
||||
msg_flags: 0,
|
||||
};
|
||||
|
||||
let read = unsafe { libc::recvmsg(stream.as_raw_fd(), &mut header, 0) };
|
||||
if read < 0 {
|
||||
return Err(std::io::Error::last_os_error());
|
||||
}
|
||||
|
||||
let mut fds = VecDeque::new();
|
||||
let mut cmsg = unsafe { libc::CMSG_FIRSTHDR(&header) };
|
||||
while !cmsg.is_null() {
|
||||
let is_rights = unsafe {
|
||||
(*cmsg).cmsg_level == libc::SOL_SOCKET && (*cmsg).cmsg_type == libc::SCM_RIGHTS
|
||||
};
|
||||
if is_rights {
|
||||
let data_len = unsafe { (*cmsg).cmsg_len as usize }.saturating_sub(mem::size_of::<libc::cmsghdr>());
|
||||
let fd_count = data_len / mem::size_of::<RawFd>();
|
||||
let data_ptr = unsafe { libc::CMSG_DATA(cmsg).cast::<RawFd>() };
|
||||
for index in 0..fd_count {
|
||||
fds.push_back(unsafe { *data_ptr.add(index) });
|
||||
}
|
||||
}
|
||||
cmsg = unsafe { libc::CMSG_NXTHDR(&header, cmsg) };
|
||||
}
|
||||
|
||||
Ok((read as usize, fds))
|
||||
}
|
||||
|
||||
const WL_DISPLAY_SYNC: u16 = 0;
|
||||
const WL_DISPLAY_GET_REGISTRY: u16 = 1;
|
||||
// Protocol constant: reserved for future implementation.
|
||||
@@ -129,8 +237,8 @@ struct Global {
|
||||
}
|
||||
|
||||
struct ShmPool {
|
||||
data: &'static mut [u8],
|
||||
_size: usize,
|
||||
file: std::fs::File,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -143,6 +251,7 @@ struct Buffer {
|
||||
_format: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Surface {
|
||||
buffer: Option<Buffer>,
|
||||
committed_buffer_id: Option<u32>,
|
||||
@@ -163,6 +272,7 @@ struct ClientState {
|
||||
pub struct Compositor {
|
||||
listener: UnixListener,
|
||||
next_id: AtomicU32,
|
||||
next_serial: AtomicU32,
|
||||
globals: Vec<Global>,
|
||||
fb_width: u32,
|
||||
fb_height: u32,
|
||||
@@ -204,6 +314,7 @@ impl Compositor {
|
||||
Ok(Self {
|
||||
listener,
|
||||
next_id: AtomicU32::new(0x10000),
|
||||
next_serial: AtomicU32::new(1),
|
||||
globals,
|
||||
fb_width,
|
||||
fb_height,
|
||||
@@ -217,6 +328,10 @@ impl Compositor {
|
||||
self.next_id.fetch_add(1, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn next_serial(&self) -> u32 {
|
||||
self.next_serial.fetch_add(1, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) -> std::io::Result<()> {
|
||||
eprintln!("redbear-compositor: listening on Wayland socket");
|
||||
let _ = std::fs::write(
|
||||
@@ -246,44 +361,41 @@ impl Compositor {
|
||||
fn send_globals(&self, stream: &mut UnixStream, registry_id: u32) {
|
||||
// Advertise each global interface on the wl_registry object after get_registry.
|
||||
for global in &self.globals {
|
||||
let name = global.name;
|
||||
let iface = global.interface.as_bytes();
|
||||
let version = global.version;
|
||||
let mut msg = Vec::with_capacity(16 + iface.len() + 1);
|
||||
msg.extend_from_slice(®istry_id.to_ne_bytes());
|
||||
let size = 8 + 4 + 4 + iface.len() as u16 + 1;
|
||||
let header = (size as u32) << 16 | WL_REGISTRY_GLOBAL as u32;
|
||||
msg.extend_from_slice(&header.to_ne_bytes());
|
||||
msg.extend_from_slice(&name.to_ne_bytes());
|
||||
msg.extend_from_slice(&iface);
|
||||
msg.push(0); // null terminator
|
||||
msg.extend_from_slice(&version.to_ne_bytes());
|
||||
let mut payload = Vec::new();
|
||||
push_u32(&mut payload, global.name);
|
||||
push_wayland_string(&mut payload, &global.interface);
|
||||
push_u32(&mut payload, global.version);
|
||||
|
||||
let mut msg = Vec::with_capacity(8 + payload.len());
|
||||
push_header(&mut msg, registry_id, WL_REGISTRY_GLOBAL, payload.len());
|
||||
msg.extend_from_slice(&payload);
|
||||
let _ = stream.write_all(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
fn send_callback_done(&self, stream: &mut UnixStream, callback_id: u32, callback_data: u32) {
|
||||
let mut msg = Vec::with_capacity(12);
|
||||
msg.extend_from_slice(&callback_id.to_ne_bytes());
|
||||
let header = (12u32) << 16 | WL_CALLBACK_DONE as u32;
|
||||
msg.extend_from_slice(&header.to_ne_bytes());
|
||||
msg.extend_from_slice(&callback_data.to_ne_bytes());
|
||||
push_header(&mut msg, callback_id, WL_CALLBACK_DONE, 4);
|
||||
push_u32(&mut msg, callback_data);
|
||||
let _ = stream.write_all(&msg);
|
||||
}
|
||||
|
||||
fn handle_client(&self, client_id: u32, mut stream: UnixStream) {
|
||||
let mut buf = [0u8; 4096];
|
||||
loop {
|
||||
match stream.read(&mut buf) {
|
||||
Ok(0) => {
|
||||
match recv_with_rights(&mut stream, &mut buf) {
|
||||
Ok((0, _)) => {
|
||||
eprintln!("redbear-compositor: client {} disconnected", client_id);
|
||||
self.clients.lock().unwrap().remove(&client_id);
|
||||
break;
|
||||
}
|
||||
Ok(n) => {
|
||||
if let Err(e) = self.dispatch(client_id, &buf[..n], &mut stream) {
|
||||
Ok((n, mut fds)) => {
|
||||
if let Err(e) = self.dispatch(client_id, &buf[..n], &mut fds, &mut stream) {
|
||||
eprintln!("redbear-compositor: dispatch error: {}", e);
|
||||
}
|
||||
while let Some(fd) = fds.pop_front() {
|
||||
let _ = unsafe { libc::close(fd) };
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("redbear-compositor: read error: {}", e);
|
||||
@@ -294,12 +406,18 @@ impl Compositor {
|
||||
self.clients.lock().unwrap().remove(&client_id);
|
||||
}
|
||||
|
||||
fn dispatch(&self, client_id: u32, data: &[u8], stream: &mut UnixStream) -> Result<(), String> {
|
||||
fn dispatch(
|
||||
&self,
|
||||
client_id: u32,
|
||||
data: &[u8],
|
||||
fds: &mut VecDeque<RawFd>,
|
||||
stream: &mut UnixStream,
|
||||
) -> Result<(), String> {
|
||||
let mut offset = 0;
|
||||
while offset + 8 <= data.len() {
|
||||
let object_id = u32::from_ne_bytes([data[offset], data[offset+1], data[offset+2], data[offset+3]]);
|
||||
let object_id = u32::from_le_bytes([data[offset], data[offset + 1], data[offset + 2], data[offset + 3]]);
|
||||
// Wayland wire format: [object_id:u32][size:u16][opcode:u16]
|
||||
let size_opcode = u32::from_ne_bytes([data[offset+4], data[offset+5], data[offset+6], data[offset+7]]);
|
||||
let size_opcode = u32::from_le_bytes([data[offset + 4], data[offset + 5], data[offset + 6], data[offset + 7]]);
|
||||
let msg_size = ((size_opcode >> 16) & 0xFFFF) as usize;
|
||||
let opcode = (size_opcode & 0xFFFF) as u16;
|
||||
|
||||
@@ -323,13 +441,13 @@ impl Compositor {
|
||||
OBJECT_TYPE_WL_DISPLAY => match opcode {
|
||||
WL_DISPLAY_SYNC => {
|
||||
let callback_id = if payload.len() >= 4 {
|
||||
u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]])
|
||||
u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]])
|
||||
} else { self.alloc_id() };
|
||||
self.send_callback_done(stream, callback_id, 0);
|
||||
}
|
||||
WL_DISPLAY_DELETE_ID => {
|
||||
if payload.len() >= 4 {
|
||||
let obj_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let obj_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.objects.remove(&obj_id);
|
||||
@@ -341,7 +459,7 @@ impl Compositor {
|
||||
}
|
||||
WL_DISPLAY_GET_REGISTRY => {
|
||||
if payload.len() >= 4 {
|
||||
let registry_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let registry_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
let mut send_globals = false;
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
@@ -360,19 +478,15 @@ impl Compositor {
|
||||
},
|
||||
OBJECT_TYPE_WL_REGISTRY => match opcode {
|
||||
WL_REGISTRY_BIND => {
|
||||
if payload.len() >= 12 {
|
||||
let _name = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let iface_bytes = &payload[4..];
|
||||
let null_pos = iface_bytes.iter().position(|&b| b == 0).unwrap_or(iface_bytes.len());
|
||||
let iface = std::str::from_utf8(&iface_bytes[..null_pos]).unwrap_or("");
|
||||
let version_offset = 4 + null_pos + 1;
|
||||
let new_id = if payload.len() >= version_offset + 4 {
|
||||
u32::from_ne_bytes([payload[version_offset], payload[version_offset+1], payload[version_offset+2], payload[version_offset+3]])
|
||||
} else { continue; };
|
||||
let mut cursor = 0;
|
||||
let _name = read_u32(payload, &mut cursor)?;
|
||||
let iface = read_wayland_string(payload, &mut cursor)?;
|
||||
let _version = read_u32(payload, &mut cursor)?;
|
||||
let new_id = read_u32(payload, &mut cursor)?;
|
||||
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
let type_id = match iface {
|
||||
let type_id = match iface.as_str() {
|
||||
"wl_compositor" => OBJECT_TYPE_WL_COMPOSITOR,
|
||||
"wl_shm" => OBJECT_TYPE_WL_SHM,
|
||||
"wl_shell" => OBJECT_TYPE_WL_SHELL,
|
||||
@@ -393,7 +507,6 @@ impl Compositor {
|
||||
self.send_seat_capabilities(stream, new_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
eprintln!("redbear-compositor: unhandled opcode {} on object {}", opcode, object_id);
|
||||
@@ -402,7 +515,7 @@ impl Compositor {
|
||||
OBJECT_TYPE_WL_COMPOSITOR => match opcode {
|
||||
WL_COMPOSITOR_CREATE_SURFACE => {
|
||||
if payload.len() >= 4 {
|
||||
let surface_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let surface_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.objects.insert(surface_id, OBJECT_TYPE_WL_SURFACE);
|
||||
@@ -423,28 +536,20 @@ impl Compositor {
|
||||
OBJECT_TYPE_WL_SHM => match opcode {
|
||||
WL_SHM_CREATE_POOL => {
|
||||
if payload.len() >= 8 {
|
||||
let pool_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let fd_val = i32::from_ne_bytes([payload[4], payload[5], payload[6], payload[7]]);
|
||||
let size = if payload.len() >= 12 {
|
||||
u32::from_ne_bytes([payload[8], payload[9], payload[10], payload[11]]) as usize
|
||||
} else { 0 };
|
||||
if fd_val >= 0 && size > 0 {
|
||||
use std::io::Seek;
|
||||
use std::os::fd::FromRawFd;
|
||||
|
||||
let mut file = unsafe { std::fs::File::from_raw_fd(fd_val) };
|
||||
let mut data = vec![0u8; size];
|
||||
if file.seek(std::io::SeekFrom::Start(0)).is_ok()
|
||||
&& file.read_exact(&mut data).is_ok()
|
||||
{
|
||||
let boxed = data.into_boxed_slice();
|
||||
let leaked = Box::leak(boxed);
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.objects.insert(pool_id, OBJECT_TYPE_WL_SHM_POOL);
|
||||
client.shm_pools.insert(pool_id, ShmPool { data: leaked, _size: size });
|
||||
}
|
||||
let pool_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let size = i32::from_le_bytes([payload[4], payload[5], payload[6], payload[7]]);
|
||||
let fd_val = fds
|
||||
.pop_front()
|
||||
.ok_or_else(|| String::from("wl_shm.create_pool missing SCM_RIGHTS fd"))?;
|
||||
if size > 0 {
|
||||
let file = unsafe { std::fs::File::from_raw_fd(fd_val) };
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.objects.insert(pool_id, OBJECT_TYPE_WL_SHM_POOL);
|
||||
client.shm_pools.insert(pool_id, ShmPool { file, size: size as usize });
|
||||
}
|
||||
} else {
|
||||
let _ = unsafe { libc::close(fd_val) };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,13 +560,13 @@ impl Compositor {
|
||||
OBJECT_TYPE_WL_SHM_POOL => match opcode {
|
||||
WL_SHM_POOL_CREATE_BUFFER => {
|
||||
if payload.len() >= 20 {
|
||||
let buffer_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let offset = u32::from_ne_bytes([payload[4], payload[5], payload[6], payload[7]]);
|
||||
let width = u32::from_ne_bytes([payload[8], payload[9], payload[10], payload[11]]);
|
||||
let height = u32::from_ne_bytes([payload[12], payload[13], payload[14], payload[15]]);
|
||||
let stride = u32::from_ne_bytes([payload[16], payload[17], payload[18], payload[19]]);
|
||||
let buffer_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let offset = u32::from_le_bytes([payload[4], payload[5], payload[6], payload[7]]);
|
||||
let width = u32::from_le_bytes([payload[8], payload[9], payload[10], payload[11]]);
|
||||
let height = u32::from_le_bytes([payload[12], payload[13], payload[14], payload[15]]);
|
||||
let stride = u32::from_le_bytes([payload[16], payload[17], payload[18], payload[19]]);
|
||||
let format = if payload.len() >= 24 {
|
||||
u32::from_ne_bytes([payload[20], payload[21], payload[22], payload[23]])
|
||||
u32::from_le_bytes([payload[20], payload[21], payload[22], payload[23]])
|
||||
} else { WL_SHM_FORMAT_ARGB8888 };
|
||||
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
@@ -485,9 +590,9 @@ impl Compositor {
|
||||
OBJECT_TYPE_WL_SURFACE => match opcode {
|
||||
WL_SURFACE_ATTACH => {
|
||||
if payload.len() >= 12 {
|
||||
let buffer_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let _x = i32::from_ne_bytes([payload[4], payload[5], payload[6], payload[7]]);
|
||||
let _y = i32::from_ne_bytes([payload[8], payload[9], payload[10], payload[11]]);
|
||||
let buffer_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let _x = i32::from_le_bytes([payload[4], payload[5], payload[6], payload[7]]);
|
||||
let _y = i32::from_le_bytes([payload[8], payload[9], payload[10], payload[11]]);
|
||||
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
@@ -514,10 +619,11 @@ impl Compositor {
|
||||
.map(|(id, _)| *id)
|
||||
.unwrap_or(0)
|
||||
});
|
||||
let surface_snapshot = surface.clone();
|
||||
|
||||
if let Some(ref buffer) = surface.buffer {
|
||||
if let Some(pool) = client.shm_pools.get(&buffer.pool_id) {
|
||||
self.composite_buffer(pool, buffer, surface);
|
||||
if let Some(ref buffer) = surface_snapshot.buffer {
|
||||
if let Some(pool) = client.shm_pools.get_mut(&buffer.pool_id) {
|
||||
self.composite_buffer(pool, buffer, &surface_snapshot);
|
||||
}
|
||||
}
|
||||
old_buffer
|
||||
@@ -541,7 +647,7 @@ impl Compositor {
|
||||
OBJECT_TYPE_WL_SHELL => match opcode {
|
||||
WL_SHELL_GET_SHELL_SURFACE => {
|
||||
if payload.len() >= 4 {
|
||||
let new_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let new_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.objects.insert(new_id, OBJECT_TYPE_WL_SHELL_SURFACE);
|
||||
@@ -563,7 +669,7 @@ impl Compositor {
|
||||
OBJECT_TYPE_WL_SEAT => match opcode {
|
||||
WL_SEAT_GET_POINTER | WL_SEAT_GET_KEYBOARD => {
|
||||
if payload.len() >= 4 {
|
||||
let new_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let new_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let object_type = match opcode {
|
||||
WL_SEAT_GET_POINTER => OBJECT_TYPE_WL_POINTER,
|
||||
WL_SEAT_GET_KEYBOARD => OBJECT_TYPE_WL_KEYBOARD,
|
||||
@@ -582,7 +688,7 @@ impl Compositor {
|
||||
OBJECT_TYPE_XDG_WM_BASE => match opcode {
|
||||
XDG_WM_BASE_GET_XDG_SURFACE => {
|
||||
if payload.len() >= 4 {
|
||||
let new_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let new_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.objects.insert(new_id, OBJECT_TYPE_XDG_SURFACE);
|
||||
@@ -605,14 +711,15 @@ impl Compositor {
|
||||
}
|
||||
XDG_SURFACE_GET_TOPLEVEL => {
|
||||
if payload.len() >= 4 {
|
||||
let toplevel_id = u32::from_ne_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let toplevel_id = u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]);
|
||||
let mut clients = self.clients.lock().unwrap();
|
||||
if let Some(client) = clients.get_mut(&client_id) {
|
||||
client.objects.insert(toplevel_id, OBJECT_TYPE_XDG_TOPLEVEL);
|
||||
}
|
||||
drop(clients);
|
||||
self.send_xdg_surface_configure(stream, object_id);
|
||||
let serial = self.next_serial();
|
||||
self.send_xdg_toplevel_configure(stream, toplevel_id);
|
||||
self.send_xdg_surface_configure(stream, object_id, serial);
|
||||
}
|
||||
}
|
||||
XDG_SURFACE_ACK_CONFIGURE => {
|
||||
@@ -639,15 +746,21 @@ impl Compositor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn composite_buffer(&self, pool: &ShmPool, buffer: &Buffer, surface: &Surface) {
|
||||
fn composite_buffer(&self, pool: &mut ShmPool, buffer: &Buffer, surface: &Surface) {
|
||||
let mut fb = self.fb_data.lock().unwrap();
|
||||
let fb_stride = self.fb_stride as usize;
|
||||
let byte_count = buffer.height as usize * buffer.stride as usize;
|
||||
|
||||
if buffer.offset as usize + (buffer.height as usize * buffer.stride as usize) > pool.data.len() {
|
||||
if buffer.offset as usize + byte_count > pool.size {
|
||||
return;
|
||||
}
|
||||
|
||||
let src = &pool.data[buffer.offset as usize..];
|
||||
let mut src = vec![0u8; byte_count];
|
||||
if pool.file.seek(SeekFrom::Start(buffer.offset as u64)).is_err()
|
||||
|| pool.file.read_exact(&mut src).is_err()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let dst_x = surface.x as usize;
|
||||
let dst_y = surface.y as usize;
|
||||
|
||||
@@ -674,78 +787,69 @@ impl Compositor {
|
||||
|
||||
fn send_buffer_release(&self, stream: &mut UnixStream, buffer_id: u32) {
|
||||
let mut msg = Vec::with_capacity(8);
|
||||
msg.extend_from_slice(&buffer_id.to_ne_bytes());
|
||||
let header = (8u32) << 16 | WL_BUFFER_RELEASE as u32;
|
||||
msg.extend_from_slice(&header.to_ne_bytes());
|
||||
push_header(&mut msg, buffer_id, WL_BUFFER_RELEASE, 0);
|
||||
let _ = stream.write_all(&msg);
|
||||
}
|
||||
|
||||
fn send_xdg_surface_configure(&self, stream: &mut UnixStream, surface_id: u32) {
|
||||
fn send_xdg_surface_configure(&self, stream: &mut UnixStream, surface_id: u32, serial: u32) {
|
||||
let mut msg = Vec::with_capacity(12);
|
||||
msg.extend_from_slice(&surface_id.to_ne_bytes());
|
||||
let header = (12u32) << 16 | XDG_SURFACE_CONFIGURE as u32;
|
||||
msg.extend_from_slice(&header.to_ne_bytes());
|
||||
msg.extend_from_slice(&0u32.to_ne_bytes()); // serial
|
||||
push_header(&mut msg, surface_id, XDG_SURFACE_CONFIGURE, 4);
|
||||
push_u32(&mut msg, serial);
|
||||
let _ = stream.write_all(&msg);
|
||||
}
|
||||
|
||||
fn send_xdg_toplevel_configure(&self, stream: &mut UnixStream, toplevel_id: u32) {
|
||||
let fb_w = self.fb_width as i32;
|
||||
let fb_h = self.fb_height as i32;
|
||||
let mut msg = Vec::with_capacity(32);
|
||||
msg.extend_from_slice(&toplevel_id.to_ne_bytes());
|
||||
let header = (32u32) << 16 | XDG_TOPLEVEL_CONFIGURE as u32;
|
||||
msg.extend_from_slice(&header.to_ne_bytes());
|
||||
msg.extend_from_slice(&fb_w.to_ne_bytes());
|
||||
msg.extend_from_slice(&fb_h.to_ne_bytes());
|
||||
msg.extend_from_slice(&0u32.to_ne_bytes()); // states array length (empty = no states)
|
||||
let mut msg = Vec::with_capacity(20);
|
||||
push_header(&mut msg, toplevel_id, XDG_TOPLEVEL_CONFIGURE, 12);
|
||||
push_i32(&mut msg, fb_w);
|
||||
push_i32(&mut msg, fb_h);
|
||||
push_u32(&mut msg, 0);
|
||||
let _ = stream.write_all(&msg);
|
||||
}
|
||||
|
||||
fn send_shm_format(&self, stream: &mut UnixStream, shm_id: u32, format: u32) {
|
||||
let mut msg = Vec::with_capacity(12);
|
||||
msg.extend_from_slice(&shm_id.to_ne_bytes());
|
||||
let header = (12u32) << 16 | WL_SHM_FORMAT as u32;
|
||||
msg.extend_from_slice(&header.to_ne_bytes());
|
||||
msg.extend_from_slice(&format.to_ne_bytes());
|
||||
push_header(&mut msg, shm_id, WL_SHM_FORMAT, 4);
|
||||
push_u32(&mut msg, format);
|
||||
let _ = stream.write_all(&msg);
|
||||
}
|
||||
|
||||
fn send_output_info(&self, stream: &mut UnixStream, output_id: u32) {
|
||||
// wl_output.geometry
|
||||
{
|
||||
let mut msg = Vec::with_capacity(32);
|
||||
msg.extend_from_slice(&output_id.to_ne_bytes());
|
||||
let header = (32u32) << 16 | WL_OUTPUT_GEOMETRY as u32;
|
||||
msg.extend_from_slice(&header.to_ne_bytes());
|
||||
msg.extend_from_slice(&0i32.to_ne_bytes()); // x
|
||||
msg.extend_from_slice(&0i32.to_ne_bytes()); // y
|
||||
msg.extend_from_slice(&0i32.to_ne_bytes()); // physical_width
|
||||
msg.extend_from_slice(&0i32.to_ne_bytes()); // physical_height
|
||||
msg.extend_from_slice(&0i32.to_ne_bytes()); // subpixel (0=none)
|
||||
msg.extend_from_slice(b"vesa\0\0\0\0"); // make + model
|
||||
let mut payload = Vec::new();
|
||||
push_i32(&mut payload, 0);
|
||||
push_i32(&mut payload, 0);
|
||||
push_i32(&mut payload, 0);
|
||||
push_i32(&mut payload, 0);
|
||||
push_i32(&mut payload, 0);
|
||||
push_wayland_string(&mut payload, "vesa");
|
||||
push_wayland_string(&mut payload, "fb0");
|
||||
push_i32(&mut payload, 0);
|
||||
|
||||
let mut msg = Vec::with_capacity(8 + payload.len());
|
||||
push_header(&mut msg, output_id, WL_OUTPUT_GEOMETRY, payload.len());
|
||||
msg.extend_from_slice(&payload);
|
||||
let _ = stream.write_all(&msg);
|
||||
}
|
||||
// wl_output.mode
|
||||
{
|
||||
let mut msg = Vec::with_capacity(24);
|
||||
msg.extend_from_slice(&output_id.to_ne_bytes());
|
||||
let header = (24u32) << 16 | WL_OUTPUT_MODE as u32;
|
||||
msg.extend_from_slice(&header.to_ne_bytes());
|
||||
msg.extend_from_slice(&(0x2u32).to_ne_bytes()); // flags: current
|
||||
msg.extend_from_slice(&self.fb_width.to_ne_bytes());
|
||||
msg.extend_from_slice(&self.fb_height.to_ne_bytes());
|
||||
msg.extend_from_slice(&60i32.to_ne_bytes()); // refresh
|
||||
push_header(&mut msg, output_id, WL_OUTPUT_MODE, 16);
|
||||
push_u32(&mut msg, 0x2);
|
||||
push_i32(&mut msg, self.fb_width as i32);
|
||||
push_i32(&mut msg, self.fb_height as i32);
|
||||
push_i32(&mut msg, 60);
|
||||
let _ = stream.write_all(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
fn send_seat_capabilities(&self, stream: &mut UnixStream, seat_id: u32) {
|
||||
let mut msg = Vec::with_capacity(12);
|
||||
msg.extend_from_slice(&seat_id.to_ne_bytes());
|
||||
let header = (12u32) << 16 | WL_SEAT_CAPABILITIES as u32;
|
||||
msg.extend_from_slice(&header.to_ne_bytes());
|
||||
msg.extend_from_slice(&(0x3u32).to_ne_bytes()); // pointer + keyboard
|
||||
push_header(&mut msg, seat_id, WL_SEAT_CAPABILITIES, 4);
|
||||
push_u32(&mut msg, 0x3);
|
||||
let _ = stream.write_all(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user