diff --git a/wayland-client/src/proxy.rs b/wayland-client/src/proxy.rs index 08630665ff2..c8d8ceffe73 100644 --- a/wayland-client/src/proxy.rs +++ b/wayland-client/src/proxy.rs @@ -1,7 +1,7 @@ -use wayland_commons::{Implementation, Interface}; +use wayland_commons::{Implementation, Interface, MessageGroup}; #[cfg(feature = "native_lib")] -use wayland_sys::client::wl_proxy; +use wayland_sys::client::*; use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; @@ -28,6 +28,36 @@ pub struct Proxy { } impl Proxy { + pub fn send(&self, msg: I::Requests) { + #[cfg(not(feature = "native_lib"))] + { + if !self.internal.alive.load(Ordering::Acquire) { + // don't send message to dead objects ! + return; + } + unimplemented!() + } + #[cfg(feature = "native_lib")] + { + if let Some(ref internal) = self.internal { + // object is managed + if !internal.alive.load(Ordering::Acquire) { + // don't send message to dead objects ! + return; + } + } + msg.as_raw_c_in(|opcode, args| unsafe { + ffi_dispatch!( + WAYLAND_CLIENT_HANDLE, + wl_proxy_marshal_array, + self.ptr, + opcode, + args.as_ptr() as *mut _ + ); + }); + } + } + // returns false is external pub fn is_alive(&self) -> bool { #[cfg(not(feature = "native_lib"))] @@ -85,12 +115,38 @@ impl Proxy { } #[doc(hidden)] - #[cfg(feature = "native_lib")] pub unsafe fn new_null() -> Proxy { Proxy { _i: ::std::marker::PhantomData, internal: None, - ptr: ::std::ptr::null_mut(), + ptr: ::std::ptr::null_mut() + } + } + + pub fn child(&self) -> NewProxy { + #[cfg(feature = "native_lib")] + { + let ptr = unsafe { ffi_dispatch!( + WAYLAND_CLIENT_HANDLE, + wl_proxy_create, + self.ptr, + C::c_interface() + ) }; + NewProxy { + _i: ::std::marker::PhantomData, + ptr: ptr, + } + } + } +} + +#[cfg(feature = "native_lib")] +impl Proxy<::protocol::wl_display::WlDisplay> { + pub(crate) fn from_display(d: *mut wl_display) -> Proxy<::protocol::wl_display::WlDisplay> { + Proxy { + _i: ::std::marker::PhantomData, + internal: None, + ptr: d as *mut wl_proxy } } } @@ -139,6 +195,11 @@ impl NewProxy { } } + #[cfg(feature = "native_lib")] + pub fn c_ptr(&self) -> *mut wl_proxy { + self.ptr + } + #[cfg(feature = "native_lib")] pub unsafe fn from_c_ptr(ptr: *mut wl_proxy) -> Self { NewProxy { diff --git a/wayland-scanner/src/c_code_gen.rs b/wayland-scanner/src/c_code_gen.rs index 56e9cf9b9f1..96b49fe4a7c 100644 --- a/wayland-scanner/src/c_code_gen.rs +++ b/wayland-scanner/src/c_code_gen.rs @@ -354,17 +354,7 @@ pub fn write_messagegroup_impl( } Type::NewId => { if a.interface.is_some() { - if side == Side::Server { - // serialize like a regular object - if a.allow_null { - writeln!(out, "_args_array[{}].o = {}.map(|o| o.c_ptr() as *mut _).unwrap_or(::std::ptr::null_mut());", j, a.name)?; - } else { - writeln!(out, "_args_array[{}].o = {}.c_ptr() as *mut _;", j, a.name)?; - } - } else { - // this must be a NULL, ignore the dummy object received - writeln!(out, "_args_array[{}].o = ::std::ptr::null_mut();", j)?; - } + writeln!(out, "_args_array[{}].o = {}.c_ptr() as *mut _;", j, a.name)?; } else { if side == Side::Server { panic!("Cannot serialize anonymous NewID from server."); @@ -459,6 +449,16 @@ fn write_client_methods(name: &str, messages: &[Message], out: &mut O) writeln!(out, " return;")?; } writeln!(out, " }}")?; + // prepare the proxies if applicable + let mut has_newp = false; + for a in &msg.args { + if a.typ == Type::NewId { + if let Some(ref iface) = a.interface { + writeln!(out, " let _arg_{}_newproxy = self.child::();", a.name, iface, snake_to_camel(&iface))?; + has_newp = true; + } + } + } // actually send the stuff write!( out, @@ -466,55 +466,36 @@ fn write_client_methods(name: &str, messages: &[Message], out: &mut O) snake_to_camel(&msg.name) )?; if msg.args.len() > 0 { - write!(out, " {{ ")?; + writeln!(out, " {{ ")?; for a in &msg.args { + write!(out, " ")?; if a.typ == Type::NewId { if let Some(ref iface) = a.interface { - write!( + writeln!( out, - "{}: unsafe {{ Proxy::::new_null() }}, ", + "{}: unsafe {{ Proxy::::from_c_ptr(_arg_{0}_newproxy.c_ptr()) }}, ", a.name, iface, snake_to_camel(&iface) )?; } else { - write!(out, "{}: (T::NAME.into(), version, unsafe {{ Proxy::::new_null() }}),", a.name)?; + writeln!(out, "{}: (T::NAME.into(), version, unsafe {{ Proxy::::new_null() }}),", a.name)?; } } else if a.typ == Type::Object { if a.allow_null { - write!(out, "{0} : {0}.map(|o| o.clone()), ", a.name)?; + writeln!(out, "{0} : {0}.map(|o| o.clone()), ", a.name)?; } else { - write!(out, "{0}: {0}.clone(), ", a.name)?; + writeln!(out, "{0}: {0}.clone(), ", a.name)?; } } else { - write!(out, "{}, ", a.name)?; + writeln!(out, "{0}: {0}, ", a.name)?; } } - write!(out, " }}")?; + write!(out, " }}")?; } writeln!(out, ";")?; - if let Some(ret_type) = return_type { - if let Some(ref iface) = ret_type.interface { - writeln!( - out, - r#" - unsafe {{ - let ret = msg.as_raw_c_in(|opcode, args| {{ - ffi_dispatch!( - WAYLAND_CLIENT_HANDLE, - wl_proxy_marshal_array_constructor, - self.c_ptr(), - opcode, - args.as_mut_ptr(), - super::{0}::{1}::c_interface() - ) - }}); - Ok(NewProxy::::from_c_ptr(ret)) - }}"#, - iface, - snake_to_camel(iface) - )?; - } else { + match return_type { + Some(ret_type) if ret_type.interface.is_none() => { writeln!( out, r#" @@ -533,25 +514,24 @@ fn write_client_methods(name: &str, messages: &[Message], out: &mut O) Ok(NewProxy::::from_c_ptr(ret)) }}"# )?; + }, + _ => { + writeln!( + out, + " self.send(msg);" + )?; + if has_newp { + for a in &msg.args { + if a.typ == Type::NewId { + if let Some(ref iface) = a.interface { + writeln!(out, " Ok(_arg_{}_newproxy)", a.name)?; + } + } + } + } } - } else { - writeln!( - out, - r#" - unsafe {{ - msg.as_raw_c_in(|opcode, args| {{ - ffi_dispatch!( - WAYLAND_CLIENT_HANDLE, - wl_proxy_marshal_array, - self.c_ptr(), - opcode, - args.as_mut_ptr() - ); - }}); - }}"# - )?; } - writeln!(out, " }}")?; + writeln!(out, " }}\n")?; } writeln!(out, " }}")?;