Skip to content

Commit 86ab66e

Browse files
danieldgvberger
authored andcommittedAug 20, 2022
client: Make object creation infallible
1 parent 3a09b09 commit 86ab66e

20 files changed

+173
-154
lines changed
 

‎wayland-client/CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## Unreleased
44

5+
#### Breaking changes
6+
7+
- Requests that create new objects now produce inert proxies when called on
8+
objects with invalid IDs of failing with `InvalidId`. This matches the
9+
behavior of non-object-creating requests (which also ignore the error).
10+
511
## 0.1.0-beta.8
612

713
#### Breaking changes

‎wayland-client/examples/list_globals.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn main() {
5252
// This method takes two arguments: a handle to the queue the newly created
5353
// wl_registry will be assigned to, and the user-data that should be associated
5454
// with this registry (here it is () as we don't need user-data).
55-
let _registry = display.get_registry(&qh, ()).unwrap();
55+
let _registry = display.get_registry(&qh, ());
5656

5757
// At this point everything is ready, and we just need to wait to receive the events
5858
// from the wl_registry, our callback will print the advertized globals.

‎wayland-client/examples/simple_window.rs

+21-26
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn main() {
1717
let qhandle = event_queue.handle();
1818

1919
let display = conn.display();
20-
display.get_registry(&qhandle, ()).unwrap();
20+
display.get_registry(&qhandle, ());
2121

2222
let mut state = State {
2323
running: true,
@@ -56,37 +56,33 @@ impl Dispatch<wl_registry::WlRegistry, ()> for State {
5656
if let wl_registry::Event::Global { name, interface, .. } = event {
5757
match &interface[..] {
5858
"wl_compositor" => {
59-
let compositor = registry
60-
.bind::<wl_compositor::WlCompositor, _, _>(name, 1, qh, ())
61-
.unwrap();
62-
let surface = compositor.create_surface(qh, ()).unwrap();
59+
let compositor =
60+
registry.bind::<wl_compositor::WlCompositor, _, _>(name, 1, qh, ());
61+
let surface = compositor.create_surface(qh, ());
6362
state.base_surface = Some(surface);
6463

6564
if state.wm_base.is_some() && state.xdg_surface.is_none() {
6665
state.init_xdg_surface(qh);
6766
}
6867
}
6968
"wl_shm" => {
70-
let shm = registry.bind::<wl_shm::WlShm, _, _>(name, 1, qh, ()).unwrap();
69+
let shm = registry.bind::<wl_shm::WlShm, _, _>(name, 1, qh, ());
7170

7271
let (init_w, init_h) = (320, 240);
7372

7473
let mut file = tempfile::tempfile().unwrap();
7574
draw(&mut file, (init_w, init_h));
76-
let pool = shm
77-
.create_pool(file.as_raw_fd(), (init_w * init_h * 4) as i32, qh, ())
78-
.unwrap();
79-
let buffer = pool
80-
.create_buffer(
81-
0,
82-
init_w as i32,
83-
init_h as i32,
84-
(init_w * 4) as i32,
85-
wl_shm::Format::Argb8888,
86-
qh,
87-
(),
88-
)
89-
.unwrap();
75+
let pool =
76+
shm.create_pool(file.as_raw_fd(), (init_w * init_h * 4) as i32, qh, ());
77+
let buffer = pool.create_buffer(
78+
0,
79+
init_w as i32,
80+
init_h as i32,
81+
(init_w * 4) as i32,
82+
wl_shm::Format::Argb8888,
83+
qh,
84+
(),
85+
);
9086
state.buffer = Some(buffer.clone());
9187

9288
if state.configured {
@@ -96,11 +92,10 @@ impl Dispatch<wl_registry::WlRegistry, ()> for State {
9692
}
9793
}
9894
"wl_seat" => {
99-
registry.bind::<wl_seat::WlSeat, _, _>(name, 1, qh, ()).unwrap();
95+
registry.bind::<wl_seat::WlSeat, _, _>(name, 1, qh, ());
10096
}
10197
"xdg_wm_base" => {
102-
let wm_base =
103-
registry.bind::<xdg_wm_base::XdgWmBase, _, _>(name, 1, qh, ()).unwrap();
98+
let wm_base = registry.bind::<xdg_wm_base::XdgWmBase, _, _>(name, 1, qh, ());
10499
state.wm_base = Some(wm_base);
105100

106101
if state.base_surface.is_some() && state.xdg_surface.is_none() {
@@ -200,8 +195,8 @@ impl State {
200195
let wm_base = self.wm_base.as_ref().unwrap();
201196
let base_surface = self.base_surface.as_ref().unwrap();
202197

203-
let xdg_surface = wm_base.get_xdg_surface(base_surface, qh, ()).unwrap();
204-
let toplevel = xdg_surface.get_toplevel(qh, ()).unwrap();
198+
let xdg_surface = wm_base.get_xdg_surface(base_surface, qh, ());
199+
let toplevel = xdg_surface.get_toplevel(qh, ());
205200
toplevel.set_title("A fantastic window!".into());
206201

207202
base_surface.commit();
@@ -272,7 +267,7 @@ impl Dispatch<wl_seat::WlSeat, ()> for State {
272267
) {
273268
if let wl_seat::Event::Capabilities { capabilities: WEnum::Value(capabilities) } = event {
274269
if capabilities.contains(wl_seat::Capability::Keyboard) {
275-
seat.get_keyboard(qh, ()).unwrap();
270+
seat.get_keyboard(qh, ());
276271
}
277272
}
278273
}

‎wayland-client/src/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
//! // This method takes two arguments: a handle to the queue the newly created
107107
//! // wl_registry will be assigned to, and the user-data that should be associated
108108
//! // with this registry (here it is () as we don't need user-data).
109-
//! let _registry = display.get_registry(&qh, ()).unwrap();
109+
//! let _registry = display.get_registry(&qh, ());
110110
//!
111111
//! // At this point everything is ready, and we just need to wait to receive the events
112112
//! // from the wl_registry, our callback will print the advertized globals.
@@ -255,6 +255,12 @@ pub trait Proxy: Sized {
255255
/// used by code generated by wayland-scanner.
256256
fn from_id(conn: &Connection, id: ObjectId) -> Result<Self, InvalidId>;
257257

258+
/// Create an inert object proxy
259+
///
260+
/// **Note:** This method is mostly meant as an implementation detail to be
261+
/// used by code generated by wayland-scanner.
262+
fn inert(backend: backend::WeakBackend) -> Self;
263+
258264
/// Send a request for this object.
259265
///
260266
/// It is an error to use this function on requests that create objects; use

‎wayland-scanner/src/client_gen.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ fn generate_objects_for(interface: &Interface) -> TokenStream {
137137
Ok(#iface_name { id, data, version, backend })
138138
}
139139

140+
#[inline]
141+
fn inert(backend: WeakBackend) -> Self {
142+
#iface_name { id: ObjectId::null(), data: None, version: 0, backend }
143+
}
144+
140145
fn parse_event(conn: &Connection, msg: Message<ObjectId>) -> Result<(Self, Self::Event), DispatchError> {
141146
#parse_body
142147
}
@@ -237,16 +242,13 @@ fn gen_methods(interface: &Interface) -> TokenStream {
237242
quote! {
238243
#doc_attr
239244
#[allow(clippy::too_many_arguments)]
240-
pub fn #method_name<U: Send + Sync + 'static, D: Dispatch<super::#created_iface_mod::#created_iface_type, U> + 'static>(&self, #(#fn_args,)* qh: &QueueHandle<D>, udata: U) -> Result<super::#created_iface_mod::#created_iface_type, InvalidId> {
241-
let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?);
242-
let ret = conn.send_request(
243-
self,
245+
pub fn #method_name<U: Send + Sync + 'static, D: Dispatch<super::#created_iface_mod::#created_iface_type, U> + 'static>(&self, #(#fn_args,)* qh: &QueueHandle<D>, udata: U) -> super::#created_iface_mod::#created_iface_type {
246+
self.send_constructor(
244247
Request::#enum_variant {
245248
#(#enum_args),*
246249
},
247-
Some(qh.make_data::<super::#created_iface_mod::#created_iface_type, U>(udata))
248-
)?;
249-
Proxy::from_id(&conn, ret)
250+
qh.make_data::<super::#created_iface_mod::#created_iface_type, U>(udata),
251+
).unwrap_or_else(|_| Proxy::inert(self.backend.clone()))
250252
}
251253
}
252254
},
@@ -255,16 +257,13 @@ fn gen_methods(interface: &Interface) -> TokenStream {
255257
quote! {
256258
#doc_attr
257259
#[allow(clippy::too_many_arguments)]
258-
pub fn #method_name<I: Proxy + 'static, U: Send + Sync + 'static, D: Dispatch<I, U> + 'static>(&self, #(#fn_args,)* qh: &QueueHandle<D>, udata: U) -> Result<I, InvalidId> {
259-
let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?);
260-
let ret = conn.send_request(
261-
self,
260+
pub fn #method_name<I: Proxy + 'static, U: Send + Sync + 'static, D: Dispatch<I, U> + 'static>(&self, #(#fn_args,)* qh: &QueueHandle<D>, udata: U) -> I {
261+
self.send_constructor(
262262
Request::#enum_variant {
263263
#(#enum_args),*
264264
},
265-
Some(qh.make_data::<I, U>(udata)),
266-
)?;
267-
Proxy::from_id(&conn, ret)
265+
qh.make_data::<I, U>(udata),
266+
).unwrap_or_else(|_| Proxy::inert(self.backend.clone()))
268267
}
269268
}
270269
},

‎wayland-scanner/tests/scanner_assets/test-client-code.rs

+58-42
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ pub mod wl_display {
145145
let backend = conn.backend().downgrade();
146146
Ok(WlDisplay { id, data, version, backend })
147147
}
148+
#[inline]
149+
fn inert(backend: WeakBackend) -> Self {
150+
WlDisplay { id: ObjectId::null(), data: None, version: 0, backend }
151+
}
148152
fn parse_event(
149153
conn: &Connection,
150154
msg: Message<ObjectId>,
@@ -219,14 +223,12 @@ pub mod wl_display {
219223
&self,
220224
qh: &QueueHandle<D>,
221225
udata: U,
222-
) -> Result<super::wl_callback::WlCallback, InvalidId> {
223-
let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?);
224-
let ret = conn.send_request(
225-
self,
226+
) -> super::wl_callback::WlCallback {
227+
self.send_constructor(
226228
Request::Sync {},
227-
Some(qh.make_data::<super::wl_callback::WlCallback, U>(udata)),
228-
)?;
229-
Proxy::from_id(&conn, ret)
229+
qh.make_data::<super::wl_callback::WlCallback, U>(udata),
230+
)
231+
.unwrap_or_else(|_| Proxy::inert(self.backend.clone()))
230232
}
231233
#[doc = "get global registry object\n\nThis request creates a registry object that allows the client\nto list and bind the global objects available from the\ncompositor.\n\nIt should be noted that the server side resources consumed in\nresponse to a get_registry request can only be released when the\nclient disconnects, not when the client side proxy is destroyed.\nTherefore, clients should invoke get_registry as infrequently as\npossible to avoid wasting memory."]
232234
#[allow(clippy::too_many_arguments)]
@@ -237,14 +239,12 @@ pub mod wl_display {
237239
&self,
238240
qh: &QueueHandle<D>,
239241
udata: U,
240-
) -> Result<super::wl_registry::WlRegistry, InvalidId> {
241-
let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?);
242-
let ret = conn.send_request(
243-
self,
242+
) -> super::wl_registry::WlRegistry {
243+
self.send_constructor(
244244
Request::GetRegistry {},
245-
Some(qh.make_data::<super::wl_registry::WlRegistry, U>(udata)),
246-
)?;
247-
Proxy::from_id(&conn, ret)
245+
qh.make_data::<super::wl_registry::WlRegistry, U>(udata),
246+
)
247+
.unwrap_or_else(|_| Proxy::inert(self.backend.clone()))
248248
}
249249
}
250250
}
@@ -363,6 +363,10 @@ pub mod wl_registry {
363363
let backend = conn.backend().downgrade();
364364
Ok(WlRegistry { id, data, version, backend })
365365
}
366+
#[inline]
367+
fn inert(backend: WeakBackend) -> Self {
368+
WlRegistry { id: ObjectId::null(), data: None, version: 0, backend }
369+
}
366370
fn parse_event(
367371
conn: &Connection,
368372
msg: Message<ObjectId>,
@@ -429,14 +433,12 @@ pub mod wl_registry {
429433
version: u32,
430434
qh: &QueueHandle<D>,
431435
udata: U,
432-
) -> Result<I, InvalidId> {
433-
let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?);
434-
let ret = conn.send_request(
435-
self,
436+
) -> I {
437+
self.send_constructor(
436438
Request::Bind { name, id: (I::interface(), version) },
437-
Some(qh.make_data::<I, U>(udata)),
438-
)?;
439-
Proxy::from_id(&conn, ret)
439+
qh.make_data::<I, U>(udata),
440+
)
441+
.unwrap_or_else(|_| Proxy::inert(self.backend.clone()))
440442
}
441443
}
442444
}
@@ -530,6 +532,10 @@ pub mod wl_callback {
530532
let backend = conn.backend().downgrade();
531533
Ok(WlCallback { id, data, version, backend })
532534
}
535+
#[inline]
536+
fn inert(backend: WeakBackend) -> Self {
537+
WlCallback { id: ObjectId::null(), data: None, version: 0, backend }
538+
}
533539
fn parse_event(
534540
conn: &Connection,
535541
msg: Message<ObjectId>,
@@ -726,6 +732,10 @@ pub mod test_global {
726732
let backend = conn.backend().downgrade();
727733
Ok(TestGlobal { id, data, version, backend })
728734
}
735+
#[inline]
736+
fn inert(backend: WeakBackend) -> Self {
737+
TestGlobal { id: ObjectId::null(), data: None, version: 0, backend }
738+
}
729739
fn parse_event(
730740
conn: &Connection,
731741
msg: Message<ObjectId>,
@@ -954,14 +964,12 @@ pub mod test_global {
954964
&self,
955965
qh: &QueueHandle<D>,
956966
udata: U,
957-
) -> Result<super::secondary::Secondary, InvalidId> {
958-
let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?);
959-
let ret = conn.send_request(
960-
self,
967+
) -> super::secondary::Secondary {
968+
self.send_constructor(
961969
Request::GetSecondary {},
962-
Some(qh.make_data::<super::secondary::Secondary, U>(udata)),
963-
)?;
964-
Proxy::from_id(&conn, ret)
970+
qh.make_data::<super::secondary::Secondary, U>(udata),
971+
)
972+
.unwrap_or_else(|_| Proxy::inert(self.backend.clone()))
965973
}
966974
#[allow(clippy::too_many_arguments)]
967975
pub fn get_tertiary<
@@ -971,14 +979,12 @@ pub mod test_global {
971979
&self,
972980
qh: &QueueHandle<D>,
973981
udata: U,
974-
) -> Result<super::tertiary::Tertiary, InvalidId> {
975-
let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?);
976-
let ret = conn.send_request(
977-
self,
982+
) -> super::tertiary::Tertiary {
983+
self.send_constructor(
978984
Request::GetTertiary {},
979-
Some(qh.make_data::<super::tertiary::Tertiary, U>(udata)),
980-
)?;
981-
Proxy::from_id(&conn, ret)
985+
qh.make_data::<super::tertiary::Tertiary, U>(udata),
986+
)
987+
.unwrap_or_else(|_| Proxy::inert(self.backend.clone()))
982988
}
983989
#[doc = "link a secondary and a tertiary"]
984990
#[allow(clippy::too_many_arguments)]
@@ -1037,14 +1043,12 @@ pub mod test_global {
10371043
ter: &super::tertiary::Tertiary,
10381044
qh: &QueueHandle<D>,
10391045
udata: U,
1040-
) -> Result<super::quad::Quad, InvalidId> {
1041-
let conn = Connection::from_backend(self.backend.upgrade().ok_or(InvalidId)?);
1042-
let ret = conn.send_request(
1043-
self,
1046+
) -> super::quad::Quad {
1047+
self.send_constructor(
10441048
Request::NewidAndAllowNull { sec: sec.cloned(), ter: ter.clone() },
1045-
Some(qh.make_data::<super::quad::Quad, U>(udata)),
1046-
)?;
1047-
Proxy::from_id(&conn, ret)
1049+
qh.make_data::<super::quad::Quad, U>(udata),
1050+
)
1051+
.unwrap_or_else(|_| Proxy::inert(self.backend.clone()))
10481052
}
10491053
}
10501054
}
@@ -1134,6 +1138,10 @@ pub mod secondary {
11341138
let backend = conn.backend().downgrade();
11351139
Ok(Secondary { id, data, version, backend })
11361140
}
1141+
#[inline]
1142+
fn inert(backend: WeakBackend) -> Self {
1143+
Secondary { id: ObjectId::null(), data: None, version: 0, backend }
1144+
}
11371145
fn parse_event(
11381146
conn: &Connection,
11391147
msg: Message<ObjectId>,
@@ -1255,6 +1263,10 @@ pub mod tertiary {
12551263
let backend = conn.backend().downgrade();
12561264
Ok(Tertiary { id, data, version, backend })
12571265
}
1266+
#[inline]
1267+
fn inert(backend: WeakBackend) -> Self {
1268+
Tertiary { id: ObjectId::null(), data: None, version: 0, backend }
1269+
}
12581270
fn parse_event(
12591271
conn: &Connection,
12601272
msg: Message<ObjectId>,
@@ -1376,6 +1388,10 @@ pub mod quad {
13761388
let backend = conn.backend().downgrade();
13771389
Ok(Quad { id, data, version, backend })
13781390
}
1391+
#[inline]
1392+
fn inert(backend: WeakBackend) -> Self {
1393+
Quad { id: ObjectId::null(), data: None, version: 0, backend }
1394+
}
13791395
fn parse_event(
13801396
conn: &Connection,
13811397
msg: Message<ObjectId>,

0 commit comments

Comments
 (0)
Please sign in to comment.