outputs: Handle removal

Currrently, Squeekboard doesn't do anything with this information.

It still expects one output to be present, or it will crash.
This commit is contained in:
Dorota Czaplejewicz
2022-01-24 19:04:18 +00:00
parent d3eb68ed5a
commit f15f97d4c9
3 changed files with 67 additions and 14 deletions

View File

@ -11,7 +11,8 @@ struct squeek_output_handle {
struct squeek_outputs *squeek_outputs_new(void);
void squeek_outputs_free(struct squeek_outputs*);
void squeek_outputs_register(struct squeek_outputs*, struct wl_output *output);
void squeek_outputs_register(struct squeek_outputs*, struct wl_output *output, uint32_t id);
struct wl_output *squeek_outputs_try_unregister(struct squeek_outputs*, uint32_t id);
struct squeek_output_handle squeek_outputs_get_current(struct squeek_outputs*);
int32_t squeek_outputs_get_perceptual_width(struct squeek_outputs*, struct wl_output *output);
#endif

View File

@ -16,6 +16,7 @@ pub mod c {
use super::*;
use std::os::raw::{ c_char, c_void };
use std::ptr;
use ::util::c::{COpaquePtr, Wrapped};
@ -25,6 +26,12 @@ pub mod c {
#[derive(Clone, PartialEq, Copy, Debug)]
pub struct WlOutput(*const c_void);
impl WlOutput {
fn null() -> Self {
Self(ptr::null())
}
}
#[repr(C)]
struct WlOutputListener<T: COpaquePtr> {
geometry: extern fn(
@ -257,14 +264,17 @@ pub mod c {
#[no_mangle]
pub extern "C"
fn squeek_outputs_register(raw_collection: COutputs, output: WlOutput) {
fn squeek_outputs_register(raw_collection: COutputs, output: WlOutput, id: u32) {
let collection = raw_collection.clone_ref();
let mut collection = collection.borrow_mut();
collection.outputs.push(Output {
output: output.clone(),
pending: OutputState::uninitialized(),
current: OutputState::uninitialized(),
});
collection.outputs.push((
Output {
output: output.clone(),
pending: OutputState::uninitialized(),
current: OutputState::uninitialized(),
},
id,
));
unsafe { squeek_output_add_listener(
output,
@ -277,14 +287,29 @@ pub mod c {
raw_collection,
)};
}
/// This will try to unregister the output, if the id matches a registered one.
#[no_mangle]
pub extern "C"
fn squeek_outputs_try_unregister(raw_collection: COutputs, id: u32) -> WlOutput {
let collection = raw_collection.clone_ref();
let mut collection = collection.borrow_mut();
collection.remove_output_by_global(id)
.map_err(|e| log_print!(
logging::Level::Debug,
"Tried to remove global {:x} but it is not registered as an output: {:?}",
id, e,
))
.unwrap_or(WlOutput::null())
}
#[no_mangle]
pub extern "C"
fn squeek_outputs_get_current(raw_collection: COutputs) -> OutputHandle {
let collection = raw_collection.clone_ref();
let collection = collection.borrow();
OutputHandle {
wl_output: collection.outputs[0].output.clone(),
wl_output: collection.outputs[0].0.output.clone(),
outputs: raw_collection.clone(),
}
}
@ -371,8 +396,13 @@ struct Output {
current: OutputState,
}
#[derive(Debug)]
struct NotFound;
type GlobalId = u32;
pub struct Outputs {
outputs: Vec<Output>,
outputs: Vec<(Output, GlobalId)>,
sender: event_loop::driver::Threaded,
}
@ -388,10 +418,27 @@ impl Outputs {
self.sender.send(event.into()).unwrap()
}
fn remove_output_by_global(&mut self, id: GlobalId)
-> Result<c::WlOutput, NotFound>
{
let index = self.outputs.iter()
.position(|(_o, global_id)| *global_id == id);
if let Some(index) = index {
let (output, _id) = self.outputs.remove(index);
self.send_event(Event {
change: ChangeType::Removed,
output: OutputId(output.output),
});
Ok(output.output)
} else {
Err(NotFound)
}
}
fn find_output(&self, wl_output: c::WlOutput) -> Option<&Output> {
self.outputs
.iter()
.find_map(|o|
.find_map(|(o, _global)|
if o.output == wl_output { Some(o) } else { None }
)
}
@ -401,7 +448,7 @@ impl Outputs {
{
self.outputs
.iter_mut()
.find_map(|o|
.find_map(|(o, _global)|
if o.output == wl_output { Some(o) } else { None }
)
}

View File

@ -126,7 +126,7 @@ registry_handle_global (void *data,
} else if (!strcmp (interface, "wl_output")) {
struct wl_output *output = wl_registry_bind (registry, name,
&wl_output_interface, 2);
squeek_outputs_register(wayland->outputs, output);
squeek_outputs_register(wayland->outputs, output, name);
} else if (!strcmp(interface, "wl_seat")) {
wayland->seat = wl_registry_bind(registry, name,
&wl_seat_interface, 1);
@ -138,7 +138,12 @@ registry_handle_global_remove (void *data,
struct wl_registry *registry,
uint32_t name)
{
// TODO: outputs
(void)registry;
struct squeek_wayland *wayland = data;
struct wl_output *output = squeek_outputs_try_unregister(wayland->outputs, name);
if (output) {
wl_output_destroy(output);
}
}
static const struct wl_registry_listener registry_listener = {