diff --git a/wayland-backend/CHANGELOG.md b/wayland-backend/CHANGELOG.md index c7c674668a8..9fdb27fa695 100644 --- a/wayland-backend/CHANGELOG.md +++ b/wayland-backend/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +### Additions +- backend: Added a `destroy_object` method + ## 0.3.3 -- 2024-01-29 ### Additions diff --git a/wayland-backend/src/client_api.rs b/wayland-backend/src/client_api.rs index a8633657e5c..eca7c8d8314 100644 --- a/wayland-backend/src/client_api.rs +++ b/wayland-backend/src/client_api.rs @@ -209,6 +209,17 @@ impl Backend { self.backend.info(id) } + /// Destroy an object + /// + /// For most protocols, this is handled automatically when a destructor + /// message is sent or received. + /// + /// This corresponds to `wl_proxy_destroy` in the C API. Or a `_destroy` + /// method generated for an object without a destructor request. + pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> { + self.backend.destroy_object(id) + } + /// Sends a request to the server /// /// Returns an error if the sender ID of the provided message is no longer valid. diff --git a/wayland-backend/src/rs/client_impl/mod.rs b/wayland-backend/src/rs/client_impl/mod.rs index 2e1f841a373..07e630b8dc4 100644 --- a/wayland-backend/src/rs/client_impl/mod.rs +++ b/wayland-backend/src/rs/client_impl/mod.rs @@ -299,6 +299,19 @@ impl InnerBackend { ObjectId { id: InnerObjectId { serial: 0, id: 0, interface: &ANONYMOUS_INTERFACE } } } + pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> { + let mut guard = self.state.lock_protocol(); + let object = guard.get_object(id.id.clone())?; + guard + .map + .with(id.id.id, |obj| { + obj.data.client_destroyed = true; + }) + .unwrap(); + object.data.user_data.destroyed(id.clone()); + Ok(()) + } + pub fn send_request( &self, Message { sender_id: ObjectId { id }, opcode, args }: Message, diff --git a/wayland-backend/src/rs/server_impl/client.rs b/wayland-backend/src/rs/server_impl/client.rs index 44c216db6de..62179510f43 100644 --- a/wayland-backend/src/rs/server_impl/client.rs +++ b/wayland-backend/src/rs/server_impl/client.rs @@ -99,6 +99,17 @@ impl Client { InnerObjectId { id, serial, client_id: self.id.clone(), interface } } + pub(crate) fn destroy_object( + &mut self, + id: InnerObjectId, + pending_destructors: &mut Vec>, + ) -> Result<(), InvalidId> { + let object = self.get_object(id.clone())?; + pending_destructors.push((object.data.user_data.clone(), self.id.clone(), id.clone())); + self.send_delete_id(id.clone()); + Ok(()) + } + pub(crate) fn object_info(&self, id: InnerObjectId) -> Result { let object = self.get_object(id.clone())?; Ok(ObjectInfo { id: id.id, interface: object.interface, version: object.version }) @@ -199,7 +210,6 @@ impl Client { // Handle destruction if relevant if message_desc.is_destructor { - self.map.remove(object_id.id.id); if let Some(vec) = pending_destructors { vec.push((object.data.user_data.clone(), self.id.clone(), object_id.id.clone())); } @@ -376,7 +386,7 @@ impl Client { } } - fn get_object(&self, id: InnerObjectId) -> Result>, InvalidId> { + pub(crate) fn get_object(&self, id: InnerObjectId) -> Result>, InvalidId> { let object = self.map.find(id.id).ok_or(InvalidId)?; if object.data.serial != id.serial { return Err(InvalidId); diff --git a/wayland-backend/src/rs/server_impl/handle.rs b/wayland-backend/src/rs/server_impl/handle.rs index 7eb284acb91..107a2865a7b 100644 --- a/wayland-backend/src/rs/server_impl/handle.rs +++ b/wayland-backend/src/rs/server_impl/handle.rs @@ -162,6 +162,15 @@ impl InnerHandle { Ok(ObjectId { id: client.create_object(interface, version, data) }) } + pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> { + let mut state = self.state.lock().unwrap(); + let state = (&mut *state as &mut dyn ErasedState) + .downcast_mut::>() + .expect("Wrong type parameter passed to Handle::destroy_object()."); + let client = state.clients.get_client_mut(id.id.client_id.clone())?; + client.destroy_object(id.id.clone(), &mut state.pending_destructors) + } + pub fn null_id() -> ObjectId { ObjectId { id: InnerObjectId { diff --git a/wayland-backend/src/server_api.rs b/wayland-backend/src/server_api.rs index b3314870bd3..f1e14811199 100644 --- a/wayland-backend/src/server_api.rs +++ b/wayland-backend/src/server_api.rs @@ -357,6 +357,21 @@ impl Handle { self.handle.create_object(client_id.id, interface, version, data) } + /// Destroy an object + /// + /// For most protocols, this is handled automatically when a destructor + /// message is sent or received. + /// + /// This corresponds to `wl_resource_destroy` in the C API. + /// + /// # Panics + /// + /// This method will panic if the type parameter `D` is not same to the same type as the + /// one the backend was initialized with. + pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> { + self.handle.destroy_object::(id) + } + /// Send an event to the client /// /// Returns an error if the sender ID of the provided message is no longer valid. diff --git a/wayland-backend/src/sys/client_impl/mod.rs b/wayland-backend/src/sys/client_impl/mod.rs index dfd33703247..e4362907a6d 100644 --- a/wayland-backend/src/sys/client_impl/mod.rs +++ b/wayland-backend/src/sys/client_impl/mod.rs @@ -516,6 +516,37 @@ impl InnerBackend { } } + fn destroy_object_inner(&self, guard: &mut MutexGuard, id: &ObjectId) { + if let Some(ref alive) = id.id.alive { + let udata = unsafe { + Box::from_raw(ffi_dispatch!( + wayland_client_handle(), + wl_proxy_get_user_data, + id.id.ptr + ) as *mut ProxyUserData) + }; + unsafe { + ffi_dispatch!( + wayland_client_handle(), + wl_proxy_set_user_data, + id.id.ptr, + std::ptr::null_mut() + ); + } + alive.store(false, Ordering::Release); + udata.data.destroyed(id.clone()); + } + guard.known_proxies.remove(&id.id.ptr); + unsafe { + ffi_dispatch!(wayland_client_handle(), wl_proxy_destroy, id.id.ptr); + } + } + + pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> { + self.destroy_object_inner(&mut self.lock_state(), id); + Ok(()) + } + pub fn send_request( &self, Message { sender_id: ObjectId { id }, opcode, args }: Message, @@ -732,29 +763,7 @@ impl InnerBackend { }; if message_desc.is_destructor { - if let Some(ref alive) = id.alive { - let udata = unsafe { - Box::from_raw(ffi_dispatch!( - wayland_client_handle(), - wl_proxy_get_user_data, - id.ptr - ) as *mut ProxyUserData) - }; - unsafe { - ffi_dispatch!( - wayland_client_handle(), - wl_proxy_set_user_data, - id.ptr, - std::ptr::null_mut() - ); - } - alive.store(false, Ordering::Release); - udata.data.destroyed(ObjectId { id: id.clone() }); - } - guard.known_proxies.remove(&id.ptr); - unsafe { - ffi_dispatch!(wayland_client_handle(), wl_proxy_destroy, id.ptr); - } + self.destroy_object_inner(&mut guard, &ObjectId { id }) } Ok(child_id) diff --git a/wayland-backend/src/sys/server_impl/mod.rs b/wayland-backend/src/sys/server_impl/mod.rs index f0d9c7c545f..e7df8aa51e3 100644 --- a/wayland-backend/src/sys/server_impl/mod.rs +++ b/wayland-backend/src/sys/server_impl/mod.rs @@ -565,6 +565,20 @@ impl InnerHandle { Ok(ObjectId { id: unsafe { init_resource(resource, interface, Some(data)).0 } }) } + pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> { + let mut state = self.state.lock().unwrap(); + // Keep this guard alive while the code is run to protect the C state + let state = (&mut *state as &mut dyn ErasedState) + .downcast_mut::>() + .expect("Wrong type parameter passed to Handle::destroy_object()."); + + PENDING_DESTRUCTORS.set(&(&mut state.pending_destructors as *mut _ as *mut _), || unsafe { + ffi_dispatch!(wayland_server_handle(), wl_resource_destroy, id.id.ptr); + }); + + Ok(()) + } + pub fn null_id() -> ObjectId { ObjectId { id: InnerObjectId { diff --git a/wayland-client/wayland.xml b/wayland-client/wayland.xml index 10e039d6ecc..e3fa6191054 100644 --- a/wayland-client/wayland.xml +++ b/wayland-client/wayland.xml @@ -46,7 +46,7 @@ compositor after the callback is fired and as such the client must not attempt to use it after that point. - The callback_data passed in the callback is the event serial. + The callback_data passed in the callback is undefined and should be ignored. @@ -212,7 +212,7 @@ - + The wl_shm_pool object encapsulates a piece of memory shared between the compositor and client. Through the wl_shm_pool @@ -262,17 +262,17 @@ created, but using the new size. This request can only be used to make the pool bigger. - This request only changes the amount of bytes that are mmapped - by the server and does not touch the file corresponding to the - file descriptor passed at creation time. It is the client's - responsibility to ensure that the file is at least as big as - the new pool size. + This request only changes the amount of bytes that are mmapped + by the server and does not touch the file corresponding to the + file descriptor passed at creation time. It is the client's + responsibility to ensure that the file is at least as big as + the new pool size. - + A singleton global object that provides support for shared memory. @@ -419,6 +419,21 @@ + + + + + + + + + + + + + + + @@ -442,6 +457,17 @@ + + + + + + Using this request a client can tell the server that it is not going to + use the shm object anymore. + + Objects created via this interface remain unaffected. + + @@ -453,9 +479,11 @@ client provides and updates the contents is defined by the buffer factory interface. - If the buffer uses a format that has an alpha channel, the alpha channel - is assumed to be premultiplied in the color channels unless otherwise - specified. + Color channels are assumed to be electrical rather than optical (in other + words, encoded with a transfer function) unless otherwise specified. If + the buffer uses a format that has an alpha channel, the alpha channel is + assumed to be premultiplied into the electrical color channel values + (after transfer function encoding) unless otherwise specified. Note, because wl_buffer objects are created from multiple independent factory interfaces, the wl_buffer interface is frozen at version 1. @@ -847,6 +875,7 @@ + @@ -868,7 +897,7 @@ The icon surface is an optional (can be NULL) surface that provides an icon to be moved around with the cursor. Initially, the top-left corner of the icon surface is placed at the cursor - hotspot, but subsequent wl_surface.attach request can move the + hotspot, but subsequent wl_surface.offset requests can move the relative position. Attach requests must be confirmed with wl_surface.commit as usual. The icon surface is given the role of a drag-and-drop icon. If the icon surface already has another role, @@ -876,6 +905,10 @@ The input region is ignored for wl_surfaces with the role of a drag-and-drop icon. + + The given source may not be used in any further set_selection or + start_drag requests. Attempting to reuse a previously-used source + may send a used_source error. @@ -889,6 +922,10 @@ to the data from the source on behalf of the client. To unset the selection, set the source to NULL. + + The given source may not be used in any further set_selection or + start_drag requests. Attempting to reuse a previously-used source + may send a used_source error. @@ -1411,7 +1448,7 @@ + summary="surface was destroyed before its role object"/> @@ -1440,9 +1477,9 @@ When the bound wl_surface version is 5 or higher, passing any non-zero x or y is a protocol violation, and will result in an - 'invalid_offset' error being raised. The x and y arguments are ignored - and do not change the pending state. To achieve equivalent semantics, - use wl_surface.offset. + 'invalid_offset' error being raised. The x and y arguments are ignored + and do not change the pending state. To achieve equivalent semantics, + use wl_surface.offset. Surface contents are double-buffered state, see wl_surface.commit. @@ -1477,8 +1514,9 @@ mutates the underlying buffer storage, the surface contents become undefined immediately. - If wl_surface.attach is sent with a NULL wl_buffer, the - following wl_surface.commit will remove the surface content. + If wl_surface.attach is sent with a NULL wl_buffer, or the pending + wl_buffer has been destroyed, the following wl_surface.commit will + remove the surface content. @@ -1666,10 +1704,12 @@ - This request sets an optional transformation on how the compositor - interprets the contents of the buffer attached to the surface. The - accepted values for the transform parameter are the values for - wl_output.transform. + This request sets the transformation that the client has already applied + to the content of the buffer. The accepted values for the transform + parameter are the values for wl_output.transform. + + The compositor applies the inverse of this transformation whenever it + uses the buffer contents. Buffer transform is double-buffered state, see wl_surface.commit. @@ -1725,11 +1765,11 @@ a buffer that is larger (by a factor of scale in each dimension) than the desired surface size. - If scale is not positive the invalid_scale protocol error is + If scale is not greater than 0 the invalid_scale protocol error is raised. + summary="scale for interpreting buffer contents"/> @@ -1802,10 +1842,15 @@ This event indicates the preferred buffer scale for this surface. It is sent whenever the compositor's preference changes. + Before receiving this event the preferred buffer scale for this surface + is 1. + It is intended that scaling aware clients use this event to scale their content and use wl_surface.set_buffer_scale to indicate the scale they have rendered with. This allows clients to supply a higher detail buffer. + + The compositor shall emit a scale value greater than 0. @@ -1815,9 +1860,12 @@ This event indicates the preferred buffer transform for this surface. It is sent whenever the compositor's preference changes. - It is intended that transform aware clients use this event to apply the - transform to their content and use wl_surface.set_buffer_transform to - indicate the transform they have rendered with. + Before receiving this event the preferred buffer transform for this + surface is normal. + + Applying this transformation to the surface buffer contents and using + wl_surface.set_buffer_transform might allow the compositor to use the + surface buffer more efficiently. @@ -1992,9 +2040,9 @@ where (x, y) are the coordinates of the pointer location, in surface-local coordinates. - On surface.attach requests to the pointer surface, hotspot_x + On wl_surface.offset requests to the pointer surface, hotspot_x and hotspot_y are decremented by the x and y parameters - passed to the request. Attach must be confirmed by + passed to the request. The offset must be applied by wl_surface.commit as usual. The hotspot can also be updated by passing the currently set @@ -2422,8 +2470,10 @@ The leave notification is sent before the enter notification for the new focus. - After this event client must assume that all keys, including modifiers, - are lifted and also it must stop key repeating if there's some going on. + After this event client must assume that no keys are pressed, + it must stop key repeating if there's some going on and until + it receives the next wl_keyboard.modifiers event, the client + must also assume no modifiers are active. @@ -2448,6 +2498,9 @@ If this event produces a change in modifiers, then the resulting wl_keyboard.modifiers event must be sent after this event. + + The compositor must not send this event without a surface of the client + having keyboard focus. @@ -2459,6 +2512,14 @@ Notifies clients that the modifier and/or group state has changed, and it should update its local state. + + The compositor may send this event without a surface of the client + having keyboard focus, for example to tie modifier information to + pointer focus instead. If a modifier event with pressed modifiers is sent + without a prior enter event, the client can assume the modifier state is + valid until it receives the next wl_keyboard.modifiers event. In order to + reset the modifier state again, the compositor can send a + wl_keyboard.modifiers event with no pressed modifiers. @@ -2566,6 +2627,8 @@ currently active on this client's surface. The client is responsible for finalizing the touch points, future touch points on this surface may reuse the touch point ID. + + No frame event is required after the cancel event. @@ -2665,10 +2728,9 @@ - - This describes the transform that a compositor will apply to a - surface to compensate for the rotation or mirroring of an - output device. + + This describes transformations that clients and compositors apply to + buffer contents. The flipped values correspond to an initial flip around a vertical axis followed by rotation. @@ -2700,6 +2762,10 @@ The geometry event will be followed by a done event (starting from version 2). + Clients should use wl_surface.preferred_buffer_transform instead of the + transform advertised by this event to find the preferred buffer + transform to use for a surface. + Note: wl_output only advertises partial information about the output position and identification. Some compositors, for instance those not implementing a desktop-style output layout or those exposing virtual @@ -2722,7 +2788,7 @@ + summary="additional transformation applied to buffer contents during presentation"/> @@ -2795,8 +2861,9 @@ This event contains scaling geometry information that is not in the geometry event. It may be sent after binding the output object or if the output scale changes - later. If it is not sent, the client should assume a - scale of 1. + later. The compositor will emit a non-zero, positive + value for scale. If it is not sent, the client should + assume a scale of 1. A scale larger than 1 means that the compositor will automatically scale surface buffers by this amount @@ -2804,12 +2871,9 @@ displays where applications rendering at the native resolution would be too small to be legible. - It is intended that scaling aware clients track the - current output of a surface, and if it is on a scaled - output it should use wl_surface.set_buffer_scale with - the scale of the output. That way the compositor can - avoid scaling the surface, and the client can supply - a higher detail image. + Clients should use wl_surface.preferred_buffer_scale + instead of this event to find the preferred buffer + scale to use for a surface. The scale event will be followed by a done event. @@ -3035,6 +3099,11 @@ If the parent wl_surface object is destroyed, the sub-surface is unmapped. + + A sub-surface never has the keyboard focus of any seat. + + The wl_surface.offset request is ignored: clients must use set_position + instead to move the sub-surface. @@ -3060,9 +3129,7 @@ surface area. Negative values are allowed. The scheduled coordinates will take effect whenever the state of the - parent surface is applied. When this happens depends on whether the - parent surface is in synchronized mode or not. See - wl_subsurface.set_sync and wl_subsurface.set_desync for details. + parent surface is applied. If more than one set_position request is invoked by the client before the commit of the parent surface, the position of a new request always @@ -3085,9 +3152,7 @@ The z-order is double-buffered. Requests are handled in order and applied immediately to a pending state. The final pending state is copied to the active state the next time the state of the parent - surface is applied. When this happens depends on whether the parent - surface is in synchronized mode or not. See wl_subsurface.set_sync and - wl_subsurface.set_desync for details. + surface is applied. A new sub-surface is initially added as the top-most in the stack of its siblings and parent. @@ -3148,4 +3213,31 @@ + + + This global fixes problems with other core-protocol interfaces that + cannot be fixed in these interfaces themselves. + + + + + + + + + This request destroys a wl_registry object. + + The client should no longer use the wl_registry after making this + request. + + The compositor will emit a wl_display.delete_id event with the object ID + of the registry and will no longer emit any events on the registry. The + client should re-use the object ID once it receives the + wl_display.delete_id event. + + + + + diff --git a/wayland-scanner/src/server_gen.rs b/wayland-scanner/src/server_gen.rs index af13af35e52..a562be9c8e7 100644 --- a/wayland-scanner/src/server_gen.rs +++ b/wayland-scanner/src/server_gen.rs @@ -12,7 +12,7 @@ pub fn generate_server_objects(protocol: &Protocol) -> TokenStream { protocol .interfaces .iter() - .filter(|iface| iface.name != "wl_display" && iface.name != "wl_registry") + .filter(|iface| iface.name != "wl_display") .map(generate_objects_for) .collect() } @@ -39,7 +39,11 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { &interface.events, ); - let parse_body = crate::common::gen_parse_body(interface, Side::Server); + let parse_body = if interface.name == "wl_registry" { + quote! { unimplemented!("`wl_registry` is implemented internally in `wayland-server`") } + } else { + crate::common::gen_parse_body(interface, Side::Server) + }; let write_body = crate::common::gen_write_body(interface, Side::Server); let methods = gen_methods(interface); diff --git a/wayland-scanner/tests/scanner_assets/test-server-code.rs b/wayland-scanner/tests/scanner_assets/test-server-code.rs index 495fe6d5eaa..b600075f918 100644 --- a/wayland-scanner/tests/scanner_assets/test-server-code.rs +++ b/wayland-scanner/tests/scanner_assets/test-server-code.rs @@ -1,3 +1,210 @@ +#[doc = "global registry object\n\nThe singleton global registry object. The server has a number of\nglobal objects that are available to all clients. These objects\ntypically represent an actual object in the server (for example,\nan input device) or they are singleton objects that provide\nextension functionality.\n\nWhen a client creates a registry object, the registry object\nwill emit a global event for each global currently in the\nregistry. Globals come and go as a result of device or\nmonitor hotplugs, reconfiguration or other events, and the\nregistry will send out global and global_remove events to\nkeep the client up to date with the changes. To mark the end\nof the initial burst of events, the client can use the\nwl_display.sync request immediately after calling\nwl_display.get_registry.\n\nA client can bind to a global object by using the bind\nrequest. This creates a client-side handle that lets the object\nemit events to the client and lets the client invoke requests on\nthe object."] +pub mod wl_registry { + use super::wayland_server::{ + backend::{ + protocol::{same_interface, Argument, Interface, Message, WEnum}, + smallvec, InvalidId, ObjectData, ObjectId, WeakHandle, + }, + Dispatch, DispatchError, DisplayHandle, New, Resource, ResourceData, Weak, + }; + use std::os::unix::io::OwnedFd; + use std::sync::Arc; + #[doc = r" The minimal object version supporting this request"] + pub const REQ_BIND_SINCE: u32 = 1u32; + #[doc = r" The wire opcode for this request"] + pub const REQ_BIND_OPCODE: u16 = 0u16; + #[doc = r" The minimal object version supporting this event"] + pub const EVT_GLOBAL_SINCE: u32 = 1u32; + #[doc = r" The wire opcode for this event"] + pub const EVT_GLOBAL_OPCODE: u16 = 0u16; + #[doc = r" The minimal object version supporting this event"] + pub const EVT_GLOBAL_REMOVE_SINCE: u32 = 1u32; + #[doc = r" The wire opcode for this event"] + pub const EVT_GLOBAL_REMOVE_OPCODE: u16 = 1u16; + #[derive(Debug)] + #[non_exhaustive] + pub enum Request { + #[doc = "bind an object to the display\n\nBinds a new, client-created object to the server using the\nspecified name as the identifier."] + Bind { + #[doc = "unique numeric name of the object"] + name: u32, + #[doc = "bounded object"] + id: (String, u32, super::wayland_server::ObjectId), + }, + } + impl Request { + #[doc = "Get the opcode number of this message"] + pub fn opcode(&self) -> u16 { + match *self { + Request::Bind { .. } => 0u16, + } + } + } + #[derive(Debug)] + #[non_exhaustive] + pub enum Event<'a> { + #[doc = "announce global object\n\nNotify the client of global objects.\n\nThe event notifies the client that a global object with\nthe given name is now available, and it implements the\ngiven version of the given interface."] + Global { + #[doc = "numeric name of the global object"] + name: u32, + #[doc = "interface implemented by the object"] + interface: String, + #[doc = "interface version"] + version: u32, + }, + #[doc = "announce removal of global object\n\nNotify the client of removed global objects.\n\nThis event notifies the client that the global identified\nby name is no longer available. If the client bound to\nthe global using the bind request, the client should now\ndestroy that object.\n\nThe object remains valid and requests to the object will be\nignored until the client destroys it, to avoid races between\nthe global going away and a client sending a request to it."] + GlobalRemove { + #[doc = "numeric name of the global object"] + name: u32, + }, + #[doc(hidden)] + __phantom_lifetime { + phantom: std::marker::PhantomData<&'a ()>, + never: std::convert::Infallible, + }, + } + impl<'a> Event<'a> { + #[doc = "Get the opcode number of this message"] + pub fn opcode(&self) -> u16 { + match *self { + Event::Global { .. } => 0u16, + Event::GlobalRemove { .. } => 1u16, + Event::__phantom_lifetime { never, .. } => match never {}, + } + } + } + #[doc = "global registry object\n\nThe singleton global registry object. The server has a number of\nglobal objects that are available to all clients. These objects\ntypically represent an actual object in the server (for example,\nan input device) or they are singleton objects that provide\nextension functionality.\n\nWhen a client creates a registry object, the registry object\nwill emit a global event for each global currently in the\nregistry. Globals come and go as a result of device or\nmonitor hotplugs, reconfiguration or other events, and the\nregistry will send out global and global_remove events to\nkeep the client up to date with the changes. To mark the end\nof the initial burst of events, the client can use the\nwl_display.sync request immediately after calling\nwl_display.get_registry.\n\nA client can bind to a global object by using the bind\nrequest. This creates a client-side handle that lets the object\nemit events to the client and lets the client invoke requests on\nthe object.\n\nSee also the [Request] enum for this interface."] + #[derive(Debug, Clone)] + pub struct WlRegistry { + id: ObjectId, + version: u32, + data: Option>, + handle: WeakHandle, + } + impl std::cmp::PartialEq for WlRegistry { + #[inline] + fn eq(&self, other: &WlRegistry) -> bool { + self.id == other.id + } + } + impl std::cmp::Eq for WlRegistry {} + impl PartialEq> for WlRegistry { + #[inline] + fn eq(&self, other: &Weak) -> bool { + self.id == other.id() + } + } + impl std::borrow::Borrow for WlRegistry { + #[inline] + fn borrow(&self) -> &ObjectId { + &self.id + } + } + impl std::hash::Hash for WlRegistry { + #[inline] + fn hash(&self, state: &mut H) { + self.id.hash(state) + } + } + impl super::wayland_server::Resource for WlRegistry { + type Request = Request; + type Event<'event> = Event<'event>; + #[inline] + fn interface() -> &'static Interface { + &super::WL_REGISTRY_INTERFACE + } + #[inline] + fn id(&self) -> ObjectId { + self.id.clone() + } + #[inline] + fn version(&self) -> u32 { + self.version + } + #[inline] + fn data(&self) -> Option<&U> { + self.data + .as_ref() + .and_then(|arc| (&**arc).downcast_ref::>()) + .map(|data| &data.udata) + } + #[inline] + fn object_data(&self) -> Option<&Arc> { + self.data.as_ref() + } + fn handle(&self) -> &WeakHandle { + &self.handle + } + #[inline] + fn from_id(conn: &DisplayHandle, id: ObjectId) -> Result { + if !same_interface(id.interface(), Self::interface()) && !id.is_null() { + return Err(InvalidId); + } + let version = conn.object_info(id.clone()).map(|info| info.version).unwrap_or(0); + let data = conn.get_object_data(id.clone()).ok(); + Ok(WlRegistry { id, data, version, handle: conn.backend_handle().downgrade() }) + } + fn send_event(&self, evt: Self::Event<'_>) -> Result<(), InvalidId> { + let handle = DisplayHandle::from(self.handle.upgrade().ok_or(InvalidId)?); + handle.send_event(self, evt) + } + fn parse_request( + conn: &DisplayHandle, + msg: Message, + ) -> Result<(Self, Self::Request), DispatchError> { + unimplemented!("`wl_registry` is implemented internally in `wayland-server`") + } + fn write_event<'a>( + &self, + conn: &DisplayHandle, + msg: Self::Event<'a>, + ) -> Result>, InvalidId> { + match msg { + Event::Global { name, interface, version } => Ok(Message { + sender_id: self.id.clone(), + opcode: 0u16, + args: { + let mut vec = smallvec::SmallVec::new(); + vec.push(Argument::Uint(name)); + vec.push(Argument::Str(Some(Box::new( + std::ffi::CString::new(interface).unwrap(), + )))); + vec.push(Argument::Uint(version)); + vec + }, + }), + Event::GlobalRemove { name } => Ok(Message { + sender_id: self.id.clone(), + opcode: 1u16, + args: { + let mut vec = smallvec::SmallVec::new(); + vec.push(Argument::Uint(name)); + vec + }, + }), + Event::__phantom_lifetime { never, .. } => match never {}, + } + } + fn __set_object_data( + &mut self, + odata: std::sync::Arc, + ) { + self.data = Some(odata); + } + } + impl WlRegistry { + #[doc = "announce global object\n\nNotify the client of global objects.\n\nThe event notifies the client that a global object with\nthe given name is now available, and it implements the\ngiven version of the given interface."] + #[allow(clippy::too_many_arguments)] + pub fn global(&self, name: u32, interface: String, version: u32) { + let _ = self.send_event(Event::Global { name, interface, version }); + } + #[doc = "announce removal of global object\n\nNotify the client of removed global objects.\n\nThis event notifies the client that the global identified\nby name is no longer available. If the client bound to\nthe global using the bind request, the client should now\ndestroy that object.\n\nThe object remains valid and requests to the object will be\nignored until the client destroys it, to avoid races between\nthe global going away and a client sending a request to it."] + #[allow(clippy::too_many_arguments)] + pub fn global_remove(&self, name: u32) { + let _ = self.send_event(Event::GlobalRemove { name }); + } + } +} #[doc = "callback object\n\nClients can handle the 'done' event to get notified when\nthe related request is done."] pub mod wl_callback { use super::wayland_server::{ diff --git a/wayland-server/wayland.xml b/wayland-server/wayland.xml index 10e039d6ecc..e3fa6191054 100644 --- a/wayland-server/wayland.xml +++ b/wayland-server/wayland.xml @@ -46,7 +46,7 @@ compositor after the callback is fired and as such the client must not attempt to use it after that point. - The callback_data passed in the callback is the event serial. + The callback_data passed in the callback is undefined and should be ignored. @@ -212,7 +212,7 @@ - + The wl_shm_pool object encapsulates a piece of memory shared between the compositor and client. Through the wl_shm_pool @@ -262,17 +262,17 @@ created, but using the new size. This request can only be used to make the pool bigger. - This request only changes the amount of bytes that are mmapped - by the server and does not touch the file corresponding to the - file descriptor passed at creation time. It is the client's - responsibility to ensure that the file is at least as big as - the new pool size. + This request only changes the amount of bytes that are mmapped + by the server and does not touch the file corresponding to the + file descriptor passed at creation time. It is the client's + responsibility to ensure that the file is at least as big as + the new pool size. - + A singleton global object that provides support for shared memory. @@ -419,6 +419,21 @@ + + + + + + + + + + + + + + + @@ -442,6 +457,17 @@ + + + + + + Using this request a client can tell the server that it is not going to + use the shm object anymore. + + Objects created via this interface remain unaffected. + + @@ -453,9 +479,11 @@ client provides and updates the contents is defined by the buffer factory interface. - If the buffer uses a format that has an alpha channel, the alpha channel - is assumed to be premultiplied in the color channels unless otherwise - specified. + Color channels are assumed to be electrical rather than optical (in other + words, encoded with a transfer function) unless otherwise specified. If + the buffer uses a format that has an alpha channel, the alpha channel is + assumed to be premultiplied into the electrical color channel values + (after transfer function encoding) unless otherwise specified. Note, because wl_buffer objects are created from multiple independent factory interfaces, the wl_buffer interface is frozen at version 1. @@ -847,6 +875,7 @@ + @@ -868,7 +897,7 @@ The icon surface is an optional (can be NULL) surface that provides an icon to be moved around with the cursor. Initially, the top-left corner of the icon surface is placed at the cursor - hotspot, but subsequent wl_surface.attach request can move the + hotspot, but subsequent wl_surface.offset requests can move the relative position. Attach requests must be confirmed with wl_surface.commit as usual. The icon surface is given the role of a drag-and-drop icon. If the icon surface already has another role, @@ -876,6 +905,10 @@ The input region is ignored for wl_surfaces with the role of a drag-and-drop icon. + + The given source may not be used in any further set_selection or + start_drag requests. Attempting to reuse a previously-used source + may send a used_source error. @@ -889,6 +922,10 @@ to the data from the source on behalf of the client. To unset the selection, set the source to NULL. + + The given source may not be used in any further set_selection or + start_drag requests. Attempting to reuse a previously-used source + may send a used_source error. @@ -1411,7 +1448,7 @@ + summary="surface was destroyed before its role object"/> @@ -1440,9 +1477,9 @@ When the bound wl_surface version is 5 or higher, passing any non-zero x or y is a protocol violation, and will result in an - 'invalid_offset' error being raised. The x and y arguments are ignored - and do not change the pending state. To achieve equivalent semantics, - use wl_surface.offset. + 'invalid_offset' error being raised. The x and y arguments are ignored + and do not change the pending state. To achieve equivalent semantics, + use wl_surface.offset. Surface contents are double-buffered state, see wl_surface.commit. @@ -1477,8 +1514,9 @@ mutates the underlying buffer storage, the surface contents become undefined immediately. - If wl_surface.attach is sent with a NULL wl_buffer, the - following wl_surface.commit will remove the surface content. + If wl_surface.attach is sent with a NULL wl_buffer, or the pending + wl_buffer has been destroyed, the following wl_surface.commit will + remove the surface content. @@ -1666,10 +1704,12 @@ - This request sets an optional transformation on how the compositor - interprets the contents of the buffer attached to the surface. The - accepted values for the transform parameter are the values for - wl_output.transform. + This request sets the transformation that the client has already applied + to the content of the buffer. The accepted values for the transform + parameter are the values for wl_output.transform. + + The compositor applies the inverse of this transformation whenever it + uses the buffer contents. Buffer transform is double-buffered state, see wl_surface.commit. @@ -1725,11 +1765,11 @@ a buffer that is larger (by a factor of scale in each dimension) than the desired surface size. - If scale is not positive the invalid_scale protocol error is + If scale is not greater than 0 the invalid_scale protocol error is raised. + summary="scale for interpreting buffer contents"/> @@ -1802,10 +1842,15 @@ This event indicates the preferred buffer scale for this surface. It is sent whenever the compositor's preference changes. + Before receiving this event the preferred buffer scale for this surface + is 1. + It is intended that scaling aware clients use this event to scale their content and use wl_surface.set_buffer_scale to indicate the scale they have rendered with. This allows clients to supply a higher detail buffer. + + The compositor shall emit a scale value greater than 0. @@ -1815,9 +1860,12 @@ This event indicates the preferred buffer transform for this surface. It is sent whenever the compositor's preference changes. - It is intended that transform aware clients use this event to apply the - transform to their content and use wl_surface.set_buffer_transform to - indicate the transform they have rendered with. + Before receiving this event the preferred buffer transform for this + surface is normal. + + Applying this transformation to the surface buffer contents and using + wl_surface.set_buffer_transform might allow the compositor to use the + surface buffer more efficiently. @@ -1992,9 +2040,9 @@ where (x, y) are the coordinates of the pointer location, in surface-local coordinates. - On surface.attach requests to the pointer surface, hotspot_x + On wl_surface.offset requests to the pointer surface, hotspot_x and hotspot_y are decremented by the x and y parameters - passed to the request. Attach must be confirmed by + passed to the request. The offset must be applied by wl_surface.commit as usual. The hotspot can also be updated by passing the currently set @@ -2422,8 +2470,10 @@ The leave notification is sent before the enter notification for the new focus. - After this event client must assume that all keys, including modifiers, - are lifted and also it must stop key repeating if there's some going on. + After this event client must assume that no keys are pressed, + it must stop key repeating if there's some going on and until + it receives the next wl_keyboard.modifiers event, the client + must also assume no modifiers are active. @@ -2448,6 +2498,9 @@ If this event produces a change in modifiers, then the resulting wl_keyboard.modifiers event must be sent after this event. + + The compositor must not send this event without a surface of the client + having keyboard focus. @@ -2459,6 +2512,14 @@ Notifies clients that the modifier and/or group state has changed, and it should update its local state. + + The compositor may send this event without a surface of the client + having keyboard focus, for example to tie modifier information to + pointer focus instead. If a modifier event with pressed modifiers is sent + without a prior enter event, the client can assume the modifier state is + valid until it receives the next wl_keyboard.modifiers event. In order to + reset the modifier state again, the compositor can send a + wl_keyboard.modifiers event with no pressed modifiers. @@ -2566,6 +2627,8 @@ currently active on this client's surface. The client is responsible for finalizing the touch points, future touch points on this surface may reuse the touch point ID. + + No frame event is required after the cancel event. @@ -2665,10 +2728,9 @@ - - This describes the transform that a compositor will apply to a - surface to compensate for the rotation or mirroring of an - output device. + + This describes transformations that clients and compositors apply to + buffer contents. The flipped values correspond to an initial flip around a vertical axis followed by rotation. @@ -2700,6 +2762,10 @@ The geometry event will be followed by a done event (starting from version 2). + Clients should use wl_surface.preferred_buffer_transform instead of the + transform advertised by this event to find the preferred buffer + transform to use for a surface. + Note: wl_output only advertises partial information about the output position and identification. Some compositors, for instance those not implementing a desktop-style output layout or those exposing virtual @@ -2722,7 +2788,7 @@ + summary="additional transformation applied to buffer contents during presentation"/> @@ -2795,8 +2861,9 @@ This event contains scaling geometry information that is not in the geometry event. It may be sent after binding the output object or if the output scale changes - later. If it is not sent, the client should assume a - scale of 1. + later. The compositor will emit a non-zero, positive + value for scale. If it is not sent, the client should + assume a scale of 1. A scale larger than 1 means that the compositor will automatically scale surface buffers by this amount @@ -2804,12 +2871,9 @@ displays where applications rendering at the native resolution would be too small to be legible. - It is intended that scaling aware clients track the - current output of a surface, and if it is on a scaled - output it should use wl_surface.set_buffer_scale with - the scale of the output. That way the compositor can - avoid scaling the surface, and the client can supply - a higher detail image. + Clients should use wl_surface.preferred_buffer_scale + instead of this event to find the preferred buffer + scale to use for a surface. The scale event will be followed by a done event. @@ -3035,6 +3099,11 @@ If the parent wl_surface object is destroyed, the sub-surface is unmapped. + + A sub-surface never has the keyboard focus of any seat. + + The wl_surface.offset request is ignored: clients must use set_position + instead to move the sub-surface. @@ -3060,9 +3129,7 @@ surface area. Negative values are allowed. The scheduled coordinates will take effect whenever the state of the - parent surface is applied. When this happens depends on whether the - parent surface is in synchronized mode or not. See - wl_subsurface.set_sync and wl_subsurface.set_desync for details. + parent surface is applied. If more than one set_position request is invoked by the client before the commit of the parent surface, the position of a new request always @@ -3085,9 +3152,7 @@ The z-order is double-buffered. Requests are handled in order and applied immediately to a pending state. The final pending state is copied to the active state the next time the state of the parent - surface is applied. When this happens depends on whether the parent - surface is in synchronized mode or not. See wl_subsurface.set_sync and - wl_subsurface.set_desync for details. + surface is applied. A new sub-surface is initially added as the top-most in the stack of its siblings and parent. @@ -3148,4 +3213,31 @@ + + + This global fixes problems with other core-protocol interfaces that + cannot be fixed in these interfaces themselves. + + + + + + + + + This request destroys a wl_registry object. + + The client should no longer use the wl_registry after making this + request. + + The compositor will emit a wl_display.delete_id event with the object ID + of the registry and will no longer emit any events on the registry. The + client should re-use the object ID once it receives the + wl_display.delete_id event. + + + + +