output: Add userdata to wayland output object

Anvil's output map has a wrapper type `Output`, that largely stores
information of the wayland `Output` type, that is just not accessible.
Lets change that and make it possible to associate userdata with the
output to remove the need to use another wrapper type.
This commit is contained in:
Victor Brekenfeld 2021-11-27 20:10:41 +01:00
parent 569783655a
commit 55ec6dc7cb
3 changed files with 61 additions and 24 deletions

View File

@ -45,6 +45,7 @@
- Add support for the zxdg-foreign-v2 protocol. - Add support for the zxdg-foreign-v2 protocol.
- Support for `xdg_wm_base` protocol version 3 - Support for `xdg_wm_base` protocol version 3
- Added the option to initialize the dmabuf global with a client filter - Added the option to initialize the dmabuf global with a client filter
- `wayland::output::Output` now has user data attached to it and more functions to query its properties
#### Backends #### Backends

View File

@ -61,7 +61,7 @@ use wayland_server::protocol::{
}; };
use wayland_server::{ use wayland_server::{
protocol::wl_output::{Mode as WMode, WlOutput}, protocol::wl_output::{Mode as WMode, WlOutput},
Client, Display, Filter, Global, Main, Client, Display, Filter, Global, Main, UserDataMap,
}; };
use slog::{info, o, trace, warn}; use slog::{info, o, trace, warn};
@ -115,6 +115,8 @@ struct Inner {
xdg_output: Option<XdgOutput>, xdg_output: Option<XdgOutput>,
} }
type InnerType = Arc<(Mutex<Inner>, UserDataMap)>;
impl Inner { impl Inner {
fn new_global(&mut self, output: WlOutput) { fn new_global(&mut self, output: WlOutput) {
trace!(self.log, "New global instantiated."); trace!(self.log, "New global instantiated.");
@ -166,9 +168,9 @@ impl Inner {
/// ///
/// This handle is stored in the event loop, and allows you to notify clients /// This handle is stored in the event loop, and allows you to notify clients
/// about any change in the properties of this output. /// about any change in the properties of this output.
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Output { pub struct Output {
inner: Arc<Mutex<Inner>>, inner: InnerType,
} }
impl Output { impl Output {
@ -190,7 +192,8 @@ impl Output {
info!(log, "Creating new wl_output"; "name" => &name); info!(log, "Creating new wl_output"; "name" => &name);
let inner = Arc::new(Mutex::new(Inner { let inner = Arc::new((
Mutex::new(Inner {
name, name,
log, log,
instances: Vec::new(), instances: Vec::new(),
@ -202,7 +205,9 @@ impl Output {
current_mode: None, current_mode: None,
preferred_mode: None, preferred_mode: None,
xdg_output: None, xdg_output: None,
})); }),
UserDataMap::default(),
));
let output = Output { inner: inner.clone() }; let output = Output { inner: inner.clone() };
@ -210,8 +215,9 @@ impl Output {
3, 3,
Filter::new(move |(output, _version): (Main<WlOutput>, _), _, _| { Filter::new(move |(output, _version): (Main<WlOutput>, _), _, _| {
output.assign_destructor(Filter::new(|output: WlOutput, _, _| { output.assign_destructor(Filter::new(|output: WlOutput, _, _| {
let inner = output.as_ref().user_data().get::<Arc<Mutex<Inner>>>().unwrap(); let inner = output.as_ref().user_data().get::<InnerType>().unwrap();
inner inner
.0
.lock() .lock()
.unwrap() .unwrap()
.instances .instances
@ -221,7 +227,7 @@ impl Output {
let inner = inner.clone(); let inner = inner.clone();
move || inner move || inner
}); });
inner.lock().unwrap().new_global(output.deref().clone()); inner.0.lock().unwrap().new_global(output.deref().clone());
}), }),
); );
@ -233,7 +239,7 @@ impl Output {
output output
.as_ref() .as_ref()
.user_data() .user_data()
.get::<Arc<Mutex<Inner>>>() .get::<InnerType>()
.cloned() .cloned()
.map(|inner| Output { inner }) .map(|inner| Output { inner })
} }
@ -243,7 +249,7 @@ impl Output {
/// If the provided mode was not previously known to this output, it is added to its /// If the provided mode was not previously known to this output, it is added to its
/// internal list. /// internal list.
pub fn set_preferred(&self, mode: Mode) { pub fn set_preferred(&self, mode: Mode) {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.0.lock().unwrap();
inner.preferred_mode = Some(mode); inner.preferred_mode = Some(mode);
if inner.modes.iter().all(|&m| m != mode) { if inner.modes.iter().all(|&m| m != mode) {
inner.modes.push(mode); inner.modes.push(mode);
@ -252,18 +258,33 @@ impl Output {
/// Adds a mode to the list of known modes to this output /// Adds a mode to the list of known modes to this output
pub fn add_mode(&self, mode: Mode) { pub fn add_mode(&self, mode: Mode) {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.0.lock().unwrap();
if inner.modes.iter().all(|&m| m != mode) { if inner.modes.iter().all(|&m| m != mode) {
inner.modes.push(mode); inner.modes.push(mode);
} }
} }
/// Returns the currently advertised mode of the output
pub fn current_mode(&self) -> Option<Mode> {
self.inner.0.lock().unwrap().current_mode
}
/// Returns the currently advertised transformation of the output
pub fn current_transform(&self) -> Transform {
self.inner.0.lock().unwrap().transform
}
/// Returns the name of the output
pub fn name(&self) -> String {
self.inner.0.lock().unwrap().name.clone()
}
/// Removes a mode from the list of known modes /// Removes a mode from the list of known modes
/// ///
/// It will not de-advertise it from existing clients (the protocol does not /// It will not de-advertise it from existing clients (the protocol does not
/// allow it), but it won't be advertised to now clients from now on. /// allow it), but it won't be advertised to now clients from now on.
pub fn delete_mode(&self, mode: Mode) { pub fn delete_mode(&self, mode: Mode) {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.0.lock().unwrap();
inner.modes.retain(|&m| m != mode); inner.modes.retain(|&m| m != mode);
if inner.current_mode == Some(mode) { if inner.current_mode == Some(mode) {
inner.current_mode = None; inner.current_mode = None;
@ -289,7 +310,7 @@ impl Output {
new_scale: Option<i32>, new_scale: Option<i32>,
new_location: Option<Point<i32, Logical>>, new_location: Option<Point<i32, Logical>>,
) { ) {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.0.lock().unwrap();
if let Some(mode) = new_mode { if let Some(mode) = new_mode {
if inner.modes.iter().all(|&m| m != mode) { if inner.modes.iter().all(|&m| m != mode) {
inner.modes.push(mode); inner.modes.push(mode);
@ -337,6 +358,7 @@ impl Output {
/// Check is given [`wl_output`](WlOutput) instance is managed by this [`Output`]. /// Check is given [`wl_output`](WlOutput) instance is managed by this [`Output`].
pub fn owns(&self, output: &WlOutput) -> bool { pub fn owns(&self, output: &WlOutput) -> bool {
self.inner self.inner
.0
.lock() .lock()
.unwrap() .unwrap()
.instances .instances
@ -351,6 +373,7 @@ impl Output {
F: FnMut(&WlOutput), F: FnMut(&WlOutput),
{ {
self.inner self.inner
.0
.lock() .lock()
.unwrap() .unwrap()
.instances .instances
@ -377,4 +400,17 @@ impl Output {
self.with_client_outputs(client, |output| surface.leave(output)) self.with_client_outputs(client, |output| surface.leave(output))
} }
} }
/// Returns the user data of this output
pub fn user_data(&self) -> &UserDataMap {
&self.inner.1
}
} }
impl PartialEq for Output {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
impl Eq for Output {}

View File

@ -159,7 +159,7 @@ where
output: wl_output, output: wl_output,
} => { } => {
let output = Output::from_resource(&wl_output).unwrap(); let output = Output::from_resource(&wl_output).unwrap();
let mut inner = output.inner.lock().unwrap(); let mut inner = output.inner.0.lock().unwrap();
if inner.xdg_output.is_none() { if inner.xdg_output.is_none() {
inner.xdg_output = Some(XdgOutput::new(&inner, log.clone())); inner.xdg_output = Some(XdgOutput::new(&inner, log.clone()));