1#![allow(dead_code)]
23
24pub mod buffer;
25pub mod compositor;
26pub mod dmabuf;
27pub mod idle_inhibit;
28pub mod layer_shell;
29pub mod output;
30pub mod protocol;
31pub mod shell;
32pub mod surface;
33
34use alloc::{collections::BTreeMap, string::String, vec::Vec};
35
36use spin::RwLock;
37
38use self::{
39 buffer::{Buffer, WlShmPool},
40 protocol::{parse_message, WaylandError, WaylandMessage},
41};
42use crate::{error::KernelError, graphics::PixelFormat, sync::once_lock::GlobalState};
43
44pub type ObjectId = u32;
46
47pub struct WaylandDisplay {
49 clients: RwLock<BTreeMap<u32, WaylandClient>>,
51 next_client_id: core::sync::atomic::AtomicU32,
53 globals: RwLock<Vec<GlobalObject>>,
55 pub wl_compositor: compositor::Compositor,
57 next_pool_id: core::sync::atomic::AtomicU32,
59}
60
61impl WaylandDisplay {
62 pub fn new() -> Self {
64 let mut display = Self {
65 clients: RwLock::new(BTreeMap::new()),
66 next_client_id: core::sync::atomic::AtomicU32::new(1),
67 globals: RwLock::new(Vec::new()),
68 wl_compositor: compositor::Compositor::new(),
69 next_pool_id: core::sync::atomic::AtomicU32::new(1),
70 };
71
72 display.register_global("wl_compositor", 4);
74 display.register_global("wl_shm", 1);
75 display.register_global("xdg_wm_base", 2);
76 display.register_global(
77 layer_shell::ZWLR_LAYER_SHELL_V1,
78 layer_shell::ZWLR_LAYER_SHELL_V1_VERSION,
79 );
80 display.register_global(
81 idle_inhibit::ZWP_IDLE_INHIBIT_MANAGER_V1,
82 idle_inhibit::ZWP_IDLE_INHIBIT_MANAGER_V1_VERSION,
83 );
84 display.register_global(
85 shell::ZXDG_DECORATION_MANAGER_V1,
86 shell::ZXDG_DECORATION_MANAGER_V1_VERSION,
87 );
88 display.register_global(
89 dmabuf::ZWP_LINUX_DMABUF_V1,
90 dmabuf::ZWP_LINUX_DMABUF_V1_VERSION,
91 );
92
93 display
94 }
95
96 fn register_global(&mut self, interface: &str, version: u32) {
98 self.globals.write().push(GlobalObject {
99 interface: String::from(interface),
100 version,
101 });
102 }
103
104 pub fn connect_client(&self) -> Result<u32, KernelError> {
106 let client_id = self
107 .next_client_id
108 .fetch_add(1, core::sync::atomic::Ordering::Relaxed);
109
110 let client = WaylandClient::new(client_id);
111 self.clients.write().insert(client_id, client);
112
113 Ok(client_id)
114 }
115
116 pub fn disconnect_client(&self, client_id: u32) -> Result<(), KernelError> {
118 self.clients.write().remove(&client_id);
119 Ok(())
120 }
121
122 pub fn process_message(&self, client_id: u32, data: &[u8]) -> Result<Vec<u8>, KernelError> {
124 let clients = self.clients.read();
125 let client = clients.get(&client_id).ok_or(KernelError::NotFound {
126 resource: "client",
127 id: client_id as u64,
128 })?;
129
130 client.handle_message(data)
131 }
132
133 fn alloc_pool_id(&self) -> u32 {
135 self.next_pool_id
136 .fetch_add(1, core::sync::atomic::Ordering::Relaxed)
137 }
138}
139
140impl Default for WaylandDisplay {
141 fn default() -> Self {
142 Self::new()
143 }
144}
145
146#[derive(Debug, Clone)]
148struct GlobalObject {
149 interface: String,
150 version: u32,
151}
152
153pub struct WaylandClient {
155 id: u32,
156 objects: RwLock<BTreeMap<ObjectId, Object>>,
158 next_object_id: core::sync::atomic::AtomicU32,
160 event_queue: RwLock<Vec<u8>>,
162}
163
164impl WaylandClient {
165 fn new(id: u32) -> Self {
166 Self {
167 id,
168 objects: RwLock::new(BTreeMap::new()),
169 next_object_id: core::sync::atomic::AtomicU32::new(1),
170 event_queue: RwLock::new(Vec::new()),
171 }
172 }
173
174 fn handle_message(&self, data: &[u8]) -> Result<Vec<u8>, KernelError> {
176 if data.is_empty() {
177 return Ok(Vec::new());
178 }
179
180 let mut response = Vec::new();
181 let mut offset = 0;
182
183 while offset < data.len() {
185 let remaining = &data[offset..];
186 if remaining.len() < 8 {
187 break;
188 }
189
190 let (msg, consumed) = parse_message(remaining).map_err(KernelError::from)?;
191 offset += consumed;
192
193 let dispatch_result = self.dispatch_message(&msg);
195 match dispatch_result {
196 Ok(events) => response.extend_from_slice(&events),
197 Err(e) => {
198 crate::println!("[WAYLAND] dispatch error: {:?}", e);
200 }
201 }
202 }
203
204 Ok(response)
205 }
206
207 fn dispatch_message(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
209 let interface = {
211 let objects = self.objects.read();
212 if msg.object_id == protocol::WL_DISPLAY_ID {
213 Some(String::from("wl_display"))
214 } else {
215 objects.get(&msg.object_id).map(|o| o.interface.clone())
216 }
217 };
218
219 let iface = interface.ok_or(WaylandError::UnknownObject { id: msg.object_id })?;
220
221 match iface.as_str() {
222 "wl_display" => self.handle_display(msg),
223 "wl_registry" => self.handle_registry(msg),
224 "wl_compositor" => self.handle_compositor_request(msg),
225 "wl_shm" => self.handle_shm(msg),
226 "wl_shm_pool" => self.handle_shm_pool(msg),
227 "wl_surface" => self.handle_surface(msg),
228 "xdg_wm_base" => self.handle_xdg_wm_base(msg),
229 "xdg_surface" => self.handle_xdg_surface(msg),
230 "xdg_toplevel" => self.handle_xdg_toplevel(msg),
231 _ => Err(WaylandError::UnknownObject { id: msg.object_id }),
232 }
233 }
234
235 fn handle_display(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
238 match msg.opcode {
239 protocol::WL_DISPLAY_SYNC => {
240 let callback_id = msg
242 .args
243 .first()
244 .and_then(|a| match a {
245 protocol::Argument::Uint(v) | protocol::Argument::NewId(v) => Some(*v),
246 _ => None,
247 })
248 .unwrap_or(0);
249
250 if callback_id > 0 {
251 let mut objects = self.objects.write();
252 objects.insert(
253 callback_id,
254 Object {
255 id: callback_id,
256 interface: String::from("wl_callback"),
257 },
258 );
259 }
260
261 let mut events = protocol::build_callback_done(callback_id, 1);
263 events.extend_from_slice(&protocol::build_display_delete_id(callback_id));
264 Ok(events)
265 }
266 protocol::WL_DISPLAY_GET_REGISTRY => {
267 let registry_id = msg
269 .args
270 .first()
271 .and_then(|a| match a {
272 protocol::Argument::Uint(v) | protocol::Argument::NewId(v) => Some(*v),
273 _ => None,
274 })
275 .unwrap_or(0);
276
277 if registry_id > 0 {
278 let mut objects = self.objects.write();
279 objects.insert(
280 registry_id,
281 Object {
282 id: registry_id,
283 interface: String::from("wl_registry"),
284 },
285 );
286 }
287
288 let mut events = Vec::new();
290 events.extend_from_slice(&protocol::build_registry_global(
291 registry_id,
292 1,
293 b"wl_compositor",
294 4,
295 ));
296 events.extend_from_slice(&protocol::build_registry_global(
297 registry_id,
298 2,
299 b"wl_shm",
300 1,
301 ));
302 events.extend_from_slice(&protocol::build_registry_global(
303 registry_id,
304 3,
305 b"xdg_wm_base",
306 2,
307 ));
308
309 events.extend_from_slice(&protocol::build_shm_format(
311 registry_id,
312 protocol::WL_SHM_FORMAT_ARGB8888,
313 ));
314 events.extend_from_slice(&protocol::build_shm_format(
315 registry_id,
316 protocol::WL_SHM_FORMAT_XRGB8888,
317 ));
318
319 Ok(events)
320 }
321 _ => Err(WaylandError::UnknownOpcode {
322 object_id: msg.object_id,
323 opcode: msg.opcode,
324 }),
325 }
326 }
327
328 fn handle_registry(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
331 match msg.opcode {
332 protocol::WL_REGISTRY_BIND => {
333 let new_id = if msg.args.len() >= 2 {
337 match &msg.args[1] {
338 protocol::Argument::Uint(v) | protocol::Argument::NewId(v) => *v,
339 _ => 0,
340 }
341 } else {
342 0
343 };
344
345 let name = if let Some(protocol::Argument::Uint(n)) = msg.args.first() {
346 *n
347 } else {
348 0
349 };
350
351 let iface = match name {
353 1 => "wl_compositor",
354 2 => "wl_shm",
355 3 => "xdg_wm_base",
356 _ => "unknown",
357 };
358
359 if new_id > 0 {
360 let mut objects = self.objects.write();
361 objects.insert(
362 new_id,
363 Object {
364 id: new_id,
365 interface: String::from(iface),
366 },
367 );
368 }
369
370 Ok(Vec::new())
371 }
372 _ => Err(WaylandError::UnknownOpcode {
373 object_id: msg.object_id,
374 opcode: msg.opcode,
375 }),
376 }
377 }
378
379 fn handle_compositor_request(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
382 match msg.opcode {
383 protocol::WL_COMPOSITOR_CREATE_SURFACE => {
384 let surface_id = msg
386 .args
387 .first()
388 .and_then(|a| match a {
389 protocol::Argument::Uint(v) | protocol::Argument::NewId(v) => Some(*v),
390 _ => None,
391 })
392 .unwrap_or(0);
393
394 if surface_id > 0 {
395 let mut objects = self.objects.write();
396 objects.insert(
397 surface_id,
398 Object {
399 id: surface_id,
400 interface: String::from("wl_surface"),
401 },
402 );
403 }
404
405 with_display(|d| {
407 let _ = d
408 .wl_compositor
409 .create_surface_for_client(surface_id, self.id);
410 });
411
412 Ok(Vec::new())
413 }
414 _ => Err(WaylandError::UnknownOpcode {
415 object_id: msg.object_id,
416 opcode: msg.opcode,
417 }),
418 }
419 }
420
421 fn handle_shm(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
424 match msg.opcode {
425 protocol::WL_SHM_CREATE_POOL => {
426 let pool_obj_id = msg
430 .args
431 .first()
432 .and_then(|a| match a {
433 protocol::Argument::Uint(v) | protocol::Argument::NewId(v) => Some(*v),
434 _ => None,
435 })
436 .unwrap_or(0);
437
438 let size = if msg.args.len() >= 3 {
439 match &msg.args[2] {
440 protocol::Argument::Uint(v) => *v,
441 protocol::Argument::Int(v) => *v as u32,
442 _ => 4096,
443 }
444 } else {
445 4096
446 };
447
448 if pool_obj_id > 0 {
449 let real_pool_id = with_display(|d| d.alloc_pool_id()).unwrap_or(pool_obj_id);
451
452 let pool = WlShmPool::new(real_pool_id, self.id, size as usize);
453 buffer::register_pool(pool);
454
455 let mut objects = self.objects.write();
456 objects.insert(
457 pool_obj_id,
458 Object {
459 id: pool_obj_id,
460 interface: String::from("wl_shm_pool"),
461 },
462 );
463
464 if let Some(obj) = objects.get_mut(&pool_obj_id) {
468 obj.id = real_pool_id;
469 }
470 }
471
472 Ok(Vec::new())
473 }
474 _ => Err(WaylandError::UnknownOpcode {
475 object_id: msg.object_id,
476 opcode: msg.opcode,
477 }),
478 }
479 }
480
481 fn handle_shm_pool(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
484 match msg.opcode {
485 protocol::WL_SHM_POOL_CREATE_BUFFER => {
486 if msg.args.len() < 6 {
489 return Err(WaylandError::InvalidArgument);
490 }
491
492 let extract_u32 = |idx: usize| -> u32 {
493 match &msg.args[idx] {
494 protocol::Argument::Uint(v) | protocol::Argument::NewId(v) => *v,
495 protocol::Argument::Int(v) => *v as u32,
496 _ => 0,
497 }
498 };
499
500 let buf_obj_id = extract_u32(0);
501 let offset = extract_u32(1);
502 let width = extract_u32(2);
503 let height = extract_u32(3);
504 let stride = extract_u32(4);
505 let fmt_code = extract_u32(5);
506
507 let format = PixelFormat::from_wl_format(fmt_code).unwrap_or(PixelFormat::Xrgb8888);
508
509 let real_pool_id = {
511 let objects = self.objects.read();
512 objects.get(&msg.object_id).map(|o| o.id).unwrap_or(0)
513 };
514
515 let pool_buf_id = match buffer::with_pool_mut(real_pool_id, |pool| {
517 pool.create_buffer(offset, width, height, stride, format)
518 }) {
519 Some(Ok(id)) => id,
520 Some(Err(_)) | None => return Err(WaylandError::InvalidArgument),
521 };
522
523 if buf_obj_id > 0 {
525 let mut objects = self.objects.write();
526 objects.insert(
527 buf_obj_id,
528 Object {
529 id: buf_obj_id,
530 interface: String::from("wl_buffer"),
531 },
532 );
533 }
534
535 let _buf = Buffer::from_pool(
539 buf_obj_id,
540 real_pool_id,
541 pool_buf_id,
542 width,
543 height,
544 stride,
545 format,
546 );
547
548 Ok(Vec::new())
549 }
550 _ => Err(WaylandError::UnknownOpcode {
551 object_id: msg.object_id,
552 opcode: msg.opcode,
553 }),
554 }
555 }
556
557 fn handle_surface(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
560 match msg.opcode {
561 protocol::WL_SURFACE_ATTACH => {
562 let _buffer_id = msg
565 .args
566 .first()
567 .and_then(|a| match a {
568 protocol::Argument::Uint(v) | protocol::Argument::Object(v) => Some(*v),
569 _ => None,
570 })
571 .unwrap_or(0);
572 Ok(Vec::new())
573 }
574 protocol::WL_SURFACE_DAMAGE => {
575 Ok(Vec::new())
577 }
578 protocol::WL_SURFACE_COMMIT => {
579 let surface_id = msg.object_id;
581 with_display(|d| {
582 d.wl_compositor.with_surface_mut(surface_id, |surface| {
583 let _ = surface.commit();
584 });
585 d.wl_compositor.request_composite();
586 });
587 Ok(Vec::new())
588 }
589 _ => {
590 Ok(Vec::new())
593 }
594 }
595 }
596
597 fn handle_xdg_wm_base(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
600 match msg.opcode {
601 shell::XDG_WM_BASE_GET_XDG_SURFACE => {
602 let xdg_surface_id = msg
604 .args
605 .first()
606 .and_then(|a| match a {
607 protocol::Argument::Uint(v) | protocol::Argument::NewId(v) => Some(*v),
608 _ => None,
609 })
610 .unwrap_or(0);
611
612 let wl_surface_id = if msg.args.len() >= 2 {
613 match &msg.args[1] {
614 protocol::Argument::Uint(v) | protocol::Argument::Object(v) => *v,
615 _ => 0,
616 }
617 } else {
618 0
619 };
620
621 if xdg_surface_id > 0 {
622 let mut objects = self.objects.write();
623 objects.insert(
624 xdg_surface_id,
625 Object {
626 id: xdg_surface_id,
627 interface: String::from("xdg_surface"),
628 },
629 );
630 }
631
632 shell::with_xdg_shell_mut(|sh| {
633 let _ = sh.create_xdg_surface(xdg_surface_id, wl_surface_id);
634 });
635
636 Ok(Vec::new())
637 }
638 shell::XDG_WM_BASE_PONG => {
639 let serial = msg
641 .args
642 .first()
643 .and_then(|a| match a {
644 protocol::Argument::Uint(v) => Some(*v),
645 _ => None,
646 })
647 .unwrap_or(0);
648
649 shell::with_xdg_shell_mut(|sh| {
650 sh.handle_pong(serial);
651 });
652 Ok(Vec::new())
653 }
654 _ => Err(WaylandError::UnknownOpcode {
655 object_id: msg.object_id,
656 opcode: msg.opcode,
657 }),
658 }
659 }
660
661 fn handle_xdg_surface(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
664 match msg.opcode {
665 shell::XDG_SURFACE_GET_TOPLEVEL => {
666 let toplevel_id = msg
668 .args
669 .first()
670 .and_then(|a| match a {
671 protocol::Argument::Uint(v) | protocol::Argument::NewId(v) => Some(*v),
672 _ => None,
673 })
674 .unwrap_or(0);
675
676 if toplevel_id > 0 {
677 let mut objects = self.objects.write();
678 objects.insert(
679 toplevel_id,
680 Object {
681 id: toplevel_id,
682 interface: String::from("xdg_toplevel"),
683 },
684 );
685 }
686
687 let xdg_surface_id = msg.object_id;
688 shell::with_xdg_shell_mut(|sh| {
689 let _ = sh.create_toplevel(xdg_surface_id, toplevel_id);
690 });
691
692 let events = shell::with_xdg_shell_mut(|sh| {
694 sh.build_initial_configure(xdg_surface_id, 0, 0)
695 })
696 .unwrap_or_default();
697
698 Ok(events)
699 }
700 shell::XDG_SURFACE_ACK_CONFIGURE => {
701 let serial = msg
703 .args
704 .first()
705 .and_then(|a| match a {
706 protocol::Argument::Uint(v) => Some(*v),
707 _ => None,
708 })
709 .unwrap_or(0);
710
711 let xdg_surface_id = msg.object_id;
712 shell::with_xdg_shell_mut(|sh| {
713 if let Some(xdg) = sh.get_xdg_surface_mut(xdg_surface_id) {
714 xdg.ack_configure(serial);
715 }
716 });
717 Ok(Vec::new())
718 }
719 shell::XDG_SURFACE_SET_WINDOW_GEOMETRY => {
720 if msg.args.len() >= 4 {
722 let extract_i32 = |idx: usize| -> i32 {
723 match &msg.args[idx] {
724 protocol::Argument::Int(v) => *v,
725 protocol::Argument::Uint(v) => *v as i32,
726 _ => 0,
727 }
728 };
729 let x = extract_i32(0);
730 let y = extract_i32(1);
731 let w = extract_i32(2) as u32;
732 let h = extract_i32(3) as u32;
733
734 let xdg_surface_id = msg.object_id;
735 shell::with_xdg_shell_mut(|sh| {
736 if let Some(xdg) = sh.get_xdg_surface_mut(xdg_surface_id) {
737 xdg.set_geometry(x, y, w, h);
738 }
739 });
740 }
741 Ok(Vec::new())
742 }
743 _ => Ok(Vec::new()),
744 }
745 }
746
747 fn handle_xdg_toplevel(&self, msg: &WaylandMessage) -> Result<Vec<u8>, WaylandError> {
750 match msg.opcode {
751 shell::XDG_TOPLEVEL_SET_TITLE => {
752 let title_bytes = extract_string_from_raw_args(&msg.args);
756 let title = String::from_utf8_lossy(&title_bytes).into_owned();
757
758 let toplevel_id = msg.object_id;
759 shell::with_xdg_shell_mut(|sh| {
760 sh.with_toplevel_mut(toplevel_id, |tl| {
761 tl.set_title(title.clone());
762 });
763 });
764 Ok(Vec::new())
765 }
766 shell::XDG_TOPLEVEL_SET_APP_ID => {
767 let app_id_bytes = extract_string_from_raw_args(&msg.args);
768 let app_id = String::from_utf8_lossy(&app_id_bytes).into_owned();
769
770 let toplevel_id = msg.object_id;
771 shell::with_xdg_shell_mut(|sh| {
772 sh.with_toplevel_mut(toplevel_id, |tl| {
773 tl.set_app_id(app_id.clone());
774 });
775 });
776 Ok(Vec::new())
777 }
778 shell::XDG_TOPLEVEL_SET_MAXIMIZED => {
779 let toplevel_id = msg.object_id;
780 shell::with_xdg_shell_mut(|sh| {
781 sh.with_toplevel_mut(toplevel_id, |tl| tl.set_maximized());
782 });
783 Ok(Vec::new())
784 }
785 shell::XDG_TOPLEVEL_SET_FULLSCREEN => {
786 let toplevel_id = msg.object_id;
787 shell::with_xdg_shell_mut(|sh| {
788 sh.with_toplevel_mut(toplevel_id, |tl| tl.set_fullscreen());
789 });
790 Ok(Vec::new())
791 }
792 shell::XDG_TOPLEVEL_SET_MINIMIZED => {
793 let toplevel_id = msg.object_id;
794 shell::with_xdg_shell_mut(|sh| {
795 sh.with_toplevel_mut(toplevel_id, |tl| tl.set_minimized());
796 });
797 Ok(Vec::new())
798 }
799 _ => Ok(Vec::new()),
800 }
801 }
802
803 pub fn create_object(&self, interface: &str) -> ObjectId {
805 let id = self
806 .next_object_id
807 .fetch_add(1, core::sync::atomic::Ordering::Relaxed);
808
809 let object = Object {
810 id,
811 interface: String::from(interface),
812 };
813
814 self.objects.write().insert(id, object);
815 id
816 }
817
818 pub fn destroy_object(&self, object_id: ObjectId) {
820 self.objects.write().remove(&object_id);
821 }
822
823 pub fn queue_events(&self, events: &[u8]) {
825 self.event_queue.write().extend_from_slice(events);
826 }
827
828 pub fn drain_events(&self) -> Vec<u8> {
830 let mut queue = self.event_queue.write();
831 let events = queue.clone();
832 queue.clear();
833 events
834 }
835}
836
837fn extract_string_from_raw_args(args: &[protocol::Argument]) -> Vec<u8> {
843 if args.is_empty() {
844 return Vec::new();
845 }
846
847 let len = match &args[0] {
849 protocol::Argument::Uint(v) => *v as usize,
850 protocol::Argument::String(bytes) => return bytes.clone(),
851 _ => return Vec::new(),
852 };
853
854 if len == 0 || args.len() < 2 {
855 return Vec::new();
856 }
857
858 let mut bytes = Vec::with_capacity(len);
860 for arg in &args[1..] {
861 if let protocol::Argument::Uint(word) = arg {
862 bytes.extend_from_slice(&word.to_ne_bytes());
863 }
864 }
865
866 bytes.truncate(len);
868 while bytes.last() == Some(&0) {
869 bytes.pop();
870 }
871 bytes
872}
873
874#[derive(Debug, Clone)]
876struct Object {
877 id: ObjectId,
878 interface: String,
879}
880
881static WAYLAND_DISPLAY: GlobalState<WaylandDisplay> = GlobalState::new();
883
884pub fn init() -> Result<(), KernelError> {
886 buffer::init_shm_pools();
888 shell::init_xdg_shell();
889
890 WAYLAND_DISPLAY
891 .init(WaylandDisplay::new())
892 .map_err(|_| KernelError::InvalidState {
893 expected: "uninitialized",
894 actual: "initialized",
895 })?;
896
897 crate::println!("[WAYLAND] Wayland compositor initialized");
898 Ok(())
899}
900
901pub fn with_display<R, F: FnOnce(&WaylandDisplay) -> R>(f: F) -> Option<R> {
903 WAYLAND_DISPLAY.with(f)
904}
905
906pub fn connect_client() -> Result<usize, KernelError> {
912 with_display(|d| d.connect_client().map(|id| id as usize)).unwrap_or(Err(
913 KernelError::InvalidState {
914 expected: "wayland initialized",
915 actual: "not initialized",
916 },
917 ))
918}
919
920pub fn disconnect_client(client_id: u32) {
922 with_display(|d| {
923 let _ = d.disconnect_client(client_id);
924 });
925}
926
927pub fn handle_client_message(client_id: u32, data: &[u8]) -> Result<(), KernelError> {
929 with_display(|d| d.process_message(client_id, data).map(|_| ())).unwrap_or(Err(
930 KernelError::InvalidState {
931 expected: "wayland initialized",
932 actual: "not initialized",
933 },
934 ))
935}
936
937pub fn read_client_events(
941 _client_id: u32,
942 _buf_ptr: usize,
943 _buf_len: usize,
944) -> Result<usize, KernelError> {
945 Ok(0)
947}
948
949pub fn create_shm_pool(client_id: u32, size: usize) -> Result<usize, KernelError> {
953 with_display(|d| {
954 let clients = d.clients.read();
955 let client = clients.get(&client_id).ok_or(KernelError::NotFound {
956 resource: "client",
957 id: client_id as u64,
958 })?;
959
960 let pool_id = d.alloc_pool_id();
962 let pool = WlShmPool::new(pool_id, client_id, size);
963 buffer::register_pool(pool);
964
965 let obj_id = client.create_object("wl_shm_pool");
966
967 {
969 let mut objects = client.objects.write();
970 if let Some(obj) = objects.get_mut(&obj_id) {
971 obj.id = pool_id;
972 }
973 }
974
975 Ok(pool_id as usize)
976 })
977 .unwrap_or(Err(KernelError::InvalidState {
978 expected: "wayland initialized",
979 actual: "not initialized",
980 }))
981}
982
983pub fn create_surface(
987 client_id: u32,
988 _width: u32,
989 _height: u32,
990 _pool_id: u32,
991) -> Result<usize, KernelError> {
992 with_display(|d| {
993 let clients = d.clients.read();
994 let client = clients.get(&client_id).ok_or(KernelError::NotFound {
995 resource: "client",
996 id: client_id as u64,
997 })?;
998 let surface_id = client.create_object("wl_surface");
999
1000 let _ = d
1002 .wl_compositor
1003 .create_surface_for_client(surface_id, client_id);
1004
1005 Ok(surface_id as usize)
1006 })
1007 .unwrap_or(Err(KernelError::InvalidState {
1008 expected: "wayland initialized",
1009 actual: "not initialized",
1010 }))
1011}
1012
1013pub fn commit_surface(_client_id: u32, surface_id: u32) -> Result<(), KernelError> {
1015 with_display(|d| {
1016 d.wl_compositor.with_surface_mut(surface_id, |surface| {
1017 let _ = surface.commit();
1018 });
1019 d.wl_compositor.request_composite();
1020 });
1021 Ok(())
1022}
1023
1024pub fn get_client_events(
1028 _client_id: u32,
1029 _events_ptr: usize,
1030 _max_count: usize,
1031) -> Result<usize, KernelError> {
1032 Ok(0)
1033}
1034
1035#[cfg(test)]
1036mod tests {
1037 use super::*;
1038
1039 #[test]
1040 fn test_display_creation() {
1041 let display = WaylandDisplay::new();
1042 assert_eq!(display.globals.read().len(), 7); }
1049
1050 #[test]
1051 fn test_client_connection() {
1052 let display = WaylandDisplay::new();
1053 let client_id = display.connect_client().unwrap();
1054 assert!(client_id > 0);
1055
1056 assert!(display.disconnect_client(client_id).is_ok());
1057 }
1058
1059 #[test]
1060 fn test_object_creation() {
1061 let client = WaylandClient::new(1);
1062 let obj_id = client.create_object("wl_surface");
1063 assert_eq!(obj_id, 1);
1064
1065 client.destroy_object(obj_id);
1066 }
1067
1068 #[test]
1069 fn test_handle_empty_message() {
1070 let client = WaylandClient::new(1);
1071 let result = client.handle_message(&[]);
1072 assert!(result.is_ok());
1073 assert!(result.unwrap().is_empty());
1074 }
1075}