mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Fix serial handling, remove unwraps
This commit is contained in:
parent
34517fd111
commit
1f3a504387
5 changed files with 371 additions and 230 deletions
16
src/api.rs
16
src/api.rs
|
@ -1045,6 +1045,10 @@ impl output_service_server::OutputService for OutputService {
|
|||
);
|
||||
debug!("Mapping output {} to {loc:?}", output.name());
|
||||
state.pinnacle.request_layout(&output);
|
||||
state
|
||||
.pinnacle
|
||||
.output_management_manager_state
|
||||
.update::<State>();
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -1081,6 +1085,10 @@ impl output_service_server::OutputService for OutputService {
|
|||
None,
|
||||
);
|
||||
state.pinnacle.request_layout(&output);
|
||||
state
|
||||
.pinnacle
|
||||
.output_management_manager_state
|
||||
.update::<State>();
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -1135,6 +1143,10 @@ impl output_service_server::OutputService for OutputService {
|
|||
|
||||
state.pinnacle.request_layout(&output);
|
||||
state.schedule_render(&output);
|
||||
state
|
||||
.pinnacle
|
||||
.output_management_manager_state
|
||||
.update::<State>();
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -1178,6 +1190,10 @@ impl output_service_server::OutputService for OutputService {
|
|||
);
|
||||
state.pinnacle.request_layout(&output);
|
||||
state.schedule_render(&output);
|
||||
state
|
||||
.pinnacle
|
||||
.output_management_manager_state
|
||||
.update::<State>();
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
|
|
@ -670,53 +670,50 @@ impl BackendData for Udev {
|
|||
}
|
||||
|
||||
fn set_output_mode(&mut self, output: &Output, mode: smithay::output::Mode) {
|
||||
let drm_mode = self.backends.iter().find_map(|(_, backend)| {
|
||||
backend
|
||||
.drm_scanner
|
||||
.crtcs()
|
||||
.find(|(_, handle)| {
|
||||
output
|
||||
.user_data()
|
||||
.get::<UdevOutputData>()
|
||||
.is_some_and(|data| &data.crtc == handle)
|
||||
})
|
||||
.and_then(|(info, _)| {
|
||||
info.modes()
|
||||
.iter()
|
||||
.find(|m| smithay::output::Mode::from(**m) == mode)
|
||||
})
|
||||
.copied()
|
||||
});
|
||||
let drm_mode = self
|
||||
.backends
|
||||
.iter()
|
||||
.find_map(|(_, backend)| {
|
||||
backend
|
||||
.drm_scanner
|
||||
.crtcs()
|
||||
.find(|(_, handle)| {
|
||||
output
|
||||
.user_data()
|
||||
.get::<UdevOutputData>()
|
||||
.is_some_and(|data| &data.crtc == handle)
|
||||
})
|
||||
.and_then(|(info, _)| {
|
||||
info.modes()
|
||||
.iter()
|
||||
.find(|m| smithay::output::Mode::from(**m) == mode)
|
||||
})
|
||||
.copied()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
info!("Unknown mode for {}, creating new one", output.name());
|
||||
create_drm_mode(mode.size.w, mode.size.h, Some(mode.refresh as u32))
|
||||
});
|
||||
|
||||
if let Some(drm_mode) = drm_mode {
|
||||
if let Some(render_surface) = render_surface_for_output(output, &mut self.backends) {
|
||||
match render_surface.compositor.use_mode(drm_mode) {
|
||||
Ok(()) => {
|
||||
output.change_current_state(Some(mode), None, None, None);
|
||||
output.with_state_mut(|state| {
|
||||
if !state.modes.contains(&mode) {
|
||||
state.modes.push(mode);
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(err) => warn!("Failed to resize output: {err}"),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let new_mode = create_drm_mode(mode.size.w, mode.size.h, Some(mode.refresh as u32));
|
||||
|
||||
if let Some(render_surface) = render_surface_for_output(output, &mut self.backends) {
|
||||
match render_surface.compositor.use_mode(new_mode) {
|
||||
Ok(()) => {
|
||||
output.change_current_state(Some(mode), None, None, None);
|
||||
output.with_state_mut(|state| {
|
||||
if !state.modes.contains(&mode) {
|
||||
state.modes.push(mode);
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(err) => warn!("Failed to resize output: {err}"),
|
||||
if let Some(render_surface) = render_surface_for_output(output, &mut self.backends) {
|
||||
match render_surface.compositor.use_mode(drm_mode) {
|
||||
Ok(()) => {
|
||||
info!(
|
||||
"Set {}'s mode to {}x{}@{:.3}Hz",
|
||||
output.name(),
|
||||
mode.size.w,
|
||||
mode.size.h,
|
||||
mode.refresh as f64 / 1000.0
|
||||
);
|
||||
output.change_current_state(Some(mode), None, None, None);
|
||||
output.with_state_mut(|state| {
|
||||
// TODO: push or no?
|
||||
if !state.modes.contains(&mode) {
|
||||
state.modes.push(mode);
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(err) => warn!("Failed to set output mode for {}: {err}", output.name()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1169,6 +1166,8 @@ impl Udev {
|
|||
})
|
||||
});
|
||||
}
|
||||
|
||||
pinnacle.output_management_manager_state.update::<State>();
|
||||
}
|
||||
|
||||
/// A display was unplugged.
|
||||
|
@ -1227,6 +1226,7 @@ impl Udev {
|
|||
pinnacle
|
||||
.output_management_manager_state
|
||||
.remove_head(&output);
|
||||
pinnacle.output_management_manager_state.update::<State>();
|
||||
|
||||
if let Some(global) = pinnacle.outputs.remove(&output) {
|
||||
// TODO: disable ahead of time
|
||||
|
|
|
@ -998,6 +998,9 @@ impl OutputManagementHandler for State {
|
|||
}
|
||||
}
|
||||
}
|
||||
self.pinnacle
|
||||
.output_management_manager_state
|
||||
.update::<State>();
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -207,9 +207,6 @@ impl Pinnacle {
|
|||
|
||||
lock_surface.send_configure();
|
||||
}
|
||||
|
||||
self.output_management_manager_state
|
||||
.update_head::<State>(output);
|
||||
}
|
||||
|
||||
pub fn set_output_enabled(&mut self, output: &Output, enabled: bool) {
|
||||
|
@ -266,6 +263,7 @@ impl Pinnacle {
|
|||
self.gamma_control_manager_state.output_removed(output);
|
||||
|
||||
self.output_management_manager_state.remove_head(output);
|
||||
self.output_management_manager_state.update::<State>();
|
||||
|
||||
self.signal_state.output_disconnect.signal(|buffer| {
|
||||
buffer.push_back(OutputDisconnectResponse {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use anyhow::Context;
|
||||
use smithay::{
|
||||
output::Output,
|
||||
reexports::{
|
||||
|
@ -11,7 +12,12 @@ use smithay::{
|
|||
},
|
||||
utils::{Logical, Physical, Point, Size, Transform, SERIAL_COUNTER},
|
||||
};
|
||||
use std::{collections::HashMap, num::NonZeroU32, sync::Mutex};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
num::NonZeroU32,
|
||||
sync::Mutex,
|
||||
};
|
||||
use tracing::error;
|
||||
|
||||
use smithay::{
|
||||
output::Mode,
|
||||
|
@ -35,6 +41,7 @@ pub struct OutputManagementManagerState {
|
|||
display_handle: DisplayHandle,
|
||||
managers: HashMap<ZwlrOutputManagerV1, OutputManagerData>,
|
||||
outputs: HashMap<Output, OutputData>,
|
||||
removed_outputs: HashSet<Output>,
|
||||
}
|
||||
|
||||
struct OutputManagerData {
|
||||
|
@ -95,7 +102,6 @@ pub trait OutputManagementHandler {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OutputData {
|
||||
// modes: Vec<Mode>,
|
||||
enabled: bool,
|
||||
current_mode: Option<Mode>,
|
||||
position: Point<i32, Logical>,
|
||||
|
@ -117,7 +123,13 @@ impl OutputManagementManagerState {
|
|||
}
|
||||
|
||||
for (manager, manager_data) in self.managers.iter_mut() {
|
||||
let (head, modes) = advertise_output::<D>(&self.display_handle, manager, output);
|
||||
let (head, modes) = match advertise_output::<D>(&self.display_handle, manager, output) {
|
||||
Ok(ret) => ret,
|
||||
Err(err) => {
|
||||
error!("Failed to advertise output to output management: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
manager_data.heads.insert(head, modes);
|
||||
}
|
||||
|
||||
|
@ -134,33 +146,26 @@ impl OutputManagementManagerState {
|
|||
}
|
||||
|
||||
pub fn remove_head(&mut self, output: &Output) {
|
||||
self.outputs.remove(output);
|
||||
|
||||
for data in self.managers.values_mut() {
|
||||
let heads = data.heads.keys().cloned().collect::<Vec<_>>();
|
||||
for head in heads {
|
||||
if head.data::<Output>() == Some(output) {
|
||||
let modes = data.heads.remove(&head);
|
||||
if let Some(modes) = modes {
|
||||
for mode in modes {
|
||||
mode.finished();
|
||||
}
|
||||
}
|
||||
head.finished();
|
||||
}
|
||||
}
|
||||
if self.outputs.remove(output).is_some() {
|
||||
self.removed_outputs.insert(output.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_head_enabled(&mut self, output: &Output, enabled: bool) {
|
||||
pub fn set_head_enabled<D>(&mut self, output: &Output, enabled: bool)
|
||||
where
|
||||
D: Dispatch<ZwlrOutputHeadV1, Output>
|
||||
+ Dispatch<ZwlrOutputModeV1, Mode>
|
||||
+ OutputManagementHandler
|
||||
+ 'static,
|
||||
{
|
||||
let Some(output_data) = self.outputs.get_mut(output) else {
|
||||
return;
|
||||
};
|
||||
|
||||
output_data.enabled = enabled;
|
||||
|
||||
for manager_data in self.managers.values() {
|
||||
for (head, wlr_modes) in manager_data.heads.iter() {
|
||||
for manager_data in self.managers.values_mut() {
|
||||
for (head, wlr_modes) in manager_data.heads.iter_mut() {
|
||||
if head.data::<Output>() == Some(output) {
|
||||
head.enabled(enabled as i32);
|
||||
|
||||
|
@ -171,141 +176,163 @@ impl OutputManagementManagerState {
|
|||
.find(|wlr_mode| wlr_mode.data::<Mode>() == Some(¤t_mode));
|
||||
if let Some(wlr_current_mode) = wlr_current_mode {
|
||||
head.current_mode(wlr_current_mode);
|
||||
} else {
|
||||
let new_wlr_mode = create_mode_for_head::<D>(
|
||||
head,
|
||||
&self.display_handle,
|
||||
current_mode,
|
||||
output.preferred_mode() == Some(current_mode),
|
||||
);
|
||||
|
||||
match new_wlr_mode {
|
||||
Ok(new_wlr_current_mode) => {
|
||||
head.current_mode(&new_wlr_current_mode);
|
||||
wlr_modes.push(new_wlr_current_mode);
|
||||
}
|
||||
Err(err) => error!("Failed to create wlr mode: {err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
head.position(output.current_location().x, output.current_location().y);
|
||||
head.transform(output.current_transform().into());
|
||||
head.scale(output.current_scale().fractional_scale());
|
||||
let new_loc = output.current_location();
|
||||
head.position(new_loc.x, new_loc.y);
|
||||
output_data.position = new_loc;
|
||||
|
||||
let new_transform = output.current_transform();
|
||||
head.transform(new_transform.into());
|
||||
output_data.transform = new_transform;
|
||||
|
||||
let new_scale = output.current_scale().fractional_scale();
|
||||
head.scale(new_scale);
|
||||
output_data.scale = new_scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_head<D>(&mut self, output: &Output)
|
||||
pub fn update<D>(&mut self)
|
||||
where
|
||||
D: Dispatch<ZwlrOutputHeadV1, Output>
|
||||
+ Dispatch<ZwlrOutputModeV1, Mode>
|
||||
+ OutputManagementHandler
|
||||
+ 'static,
|
||||
{
|
||||
let Some(output_data) = self.outputs.get_mut(output) else {
|
||||
tracing::error!("Called `update_head` without `advertise_output`");
|
||||
return;
|
||||
};
|
||||
|
||||
for (manager, manager_data) in self.managers.iter_mut() {
|
||||
for (head, wlr_modes) in manager_data.heads.iter_mut() {
|
||||
if head.data::<Output>() != Some(output) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: modes
|
||||
let modes = output.with_state(|state| state.modes.clone());
|
||||
|
||||
wlr_modes.retain(|wlr_mode| {
|
||||
if !modes.contains(wlr_mode.data::<Mode>().unwrap()) {
|
||||
wlr_mode.finished();
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
for mode in modes {
|
||||
if !wlr_modes
|
||||
.iter()
|
||||
.any(|wlr_mode| wlr_mode.data::<Mode>().unwrap() == &mode)
|
||||
{
|
||||
if let Some(client) = head.client() {
|
||||
let new_wlr_mode = client
|
||||
.create_resource::<ZwlrOutputModeV1, _, D>(
|
||||
&self.display_handle,
|
||||
head.version(),
|
||||
mode,
|
||||
)
|
||||
.expect("TODO");
|
||||
|
||||
new_wlr_mode.size(mode.size.w, mode.size.h);
|
||||
new_wlr_mode.refresh(mode.refresh);
|
||||
|
||||
if Some(mode) == output.preferred_mode() {
|
||||
new_wlr_mode.preferred();
|
||||
}
|
||||
|
||||
head.mode(&new_wlr_mode);
|
||||
|
||||
wlr_modes.push(new_wlr_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// enabled handled in `set_head_enabled`
|
||||
|
||||
if output.current_mode() != output_data.current_mode {
|
||||
if let Some(new_cur_mode) = output.current_mode() {
|
||||
let new_cur_wlr_mode = wlr_modes
|
||||
.iter()
|
||||
.find(|wlr_mode| wlr_mode.data::<Mode>() == Some(&new_cur_mode));
|
||||
|
||||
match new_cur_wlr_mode {
|
||||
Some(new_cur_wlr_mode) => {
|
||||
head.current_mode(new_cur_wlr_mode);
|
||||
}
|
||||
// TODO: don't do this branch
|
||||
None => {
|
||||
if let Some(client) = head.client() {
|
||||
let new_cur_wlr_mode = client
|
||||
.create_resource::<ZwlrOutputModeV1, _, D>(
|
||||
&self.display_handle,
|
||||
head.version(),
|
||||
new_cur_mode,
|
||||
)
|
||||
.expect("TODO");
|
||||
|
||||
new_cur_wlr_mode.size(new_cur_mode.size.w, new_cur_mode.size.h);
|
||||
new_cur_wlr_mode.refresh(new_cur_mode.refresh);
|
||||
|
||||
if Some(new_cur_mode) == output.preferred_mode() {
|
||||
new_cur_wlr_mode.preferred();
|
||||
}
|
||||
|
||||
head.mode(&new_cur_wlr_mode);
|
||||
head.current_mode(&new_cur_wlr_mode);
|
||||
wlr_modes.push(new_cur_wlr_mode);
|
||||
}
|
||||
for output in self.removed_outputs.drain() {
|
||||
for data in self.managers.values_mut() {
|
||||
let heads = data.heads.keys().cloned().collect::<Vec<_>>();
|
||||
for head in heads {
|
||||
if head.data::<Output>() == Some(&output) {
|
||||
let modes = data.heads.remove(&head);
|
||||
if let Some(modes) = modes {
|
||||
for mode in modes {
|
||||
mode.finished();
|
||||
}
|
||||
}
|
||||
|
||||
output_data.current_mode = Some(new_cur_mode);
|
||||
head.finished();
|
||||
}
|
||||
}
|
||||
|
||||
if output.current_location() != output_data.position {
|
||||
let new_loc = output.current_location();
|
||||
head.position(new_loc.x, new_loc.y);
|
||||
output_data.position = new_loc;
|
||||
}
|
||||
|
||||
if output.current_transform() != output_data.transform {
|
||||
let new_transform = output.current_transform();
|
||||
head.transform(new_transform.into());
|
||||
output_data.transform = new_transform;
|
||||
}
|
||||
|
||||
if output.current_scale().fractional_scale() != output_data.scale {
|
||||
let new_scale = output.current_scale().fractional_scale();
|
||||
head.scale(new_scale);
|
||||
output_data.scale = new_scale;
|
||||
}
|
||||
|
||||
// TODO: adaptive sync
|
||||
}
|
||||
}
|
||||
|
||||
let serial = u32::from(SERIAL_COUNTER.next_serial());
|
||||
let serial = u32::from(SERIAL_COUNTER.next_serial());
|
||||
|
||||
manager_data.serial = serial;
|
||||
manager.done(serial);
|
||||
for (output, output_data) in self.outputs.iter_mut() {
|
||||
for (manager, manager_data) in self.managers.iter_mut() {
|
||||
for (head, wlr_modes) in manager_data.heads.iter_mut() {
|
||||
if head.data::<Output>() != Some(output) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let modes = output.with_state(|state| state.modes.clone());
|
||||
|
||||
wlr_modes.retain(|wlr_mode| {
|
||||
if !modes.contains(wlr_mode.data::<Mode>().unwrap()) {
|
||||
wlr_mode.finished();
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
for mode in modes {
|
||||
if !wlr_modes
|
||||
.iter()
|
||||
.any(|wlr_mode| wlr_mode.data::<Mode>().unwrap() == &mode)
|
||||
{
|
||||
let new_wlr_mode = create_mode_for_head::<D>(
|
||||
head,
|
||||
&self.display_handle,
|
||||
mode,
|
||||
output.preferred_mode() == Some(mode),
|
||||
);
|
||||
|
||||
match new_wlr_mode {
|
||||
Ok(new_wlr_current_mode) => wlr_modes.push(new_wlr_current_mode),
|
||||
Err(err) => error!("Failed to create wlr mode: {err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// enabled handled in `set_head_enabled`
|
||||
|
||||
if output_data.enabled {
|
||||
if output.current_mode() != output_data.current_mode {
|
||||
if let Some(new_cur_mode) = output.current_mode() {
|
||||
let new_cur_wlr_mode = wlr_modes.iter().find(|wlr_mode| {
|
||||
wlr_mode.data::<Mode>() == Some(&new_cur_mode)
|
||||
});
|
||||
|
||||
match new_cur_wlr_mode {
|
||||
Some(new_cur_wlr_mode) => {
|
||||
head.current_mode(new_cur_wlr_mode);
|
||||
}
|
||||
None => {
|
||||
let new_wlr_current_mode = create_mode_for_head::<D>(
|
||||
head,
|
||||
&self.display_handle,
|
||||
new_cur_mode,
|
||||
output.preferred_mode() == Some(new_cur_mode),
|
||||
);
|
||||
|
||||
match new_wlr_current_mode {
|
||||
Ok(new_wlr_current_mode) => {
|
||||
head.current_mode(&new_wlr_current_mode);
|
||||
wlr_modes.push(new_wlr_current_mode);
|
||||
}
|
||||
Err(err) => error!("Failed to create wlr mode: {err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output_data.current_mode = Some(new_cur_mode);
|
||||
}
|
||||
}
|
||||
|
||||
if output.current_location() != output_data.position {
|
||||
let new_loc = output.current_location();
|
||||
head.position(new_loc.x, new_loc.y);
|
||||
output_data.position = new_loc;
|
||||
}
|
||||
|
||||
if output.current_transform() != output_data.transform {
|
||||
let new_transform = output.current_transform();
|
||||
head.transform(new_transform.into());
|
||||
output_data.transform = new_transform;
|
||||
}
|
||||
|
||||
if output.current_scale().fractional_scale() != output_data.scale {
|
||||
let new_scale = output.current_scale().fractional_scale();
|
||||
head.scale(new_scale);
|
||||
output_data.scale = new_scale;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: adaptive sync
|
||||
}
|
||||
|
||||
manager_data.serial = serial;
|
||||
manager.done(serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -314,18 +341,22 @@ fn advertise_output<D>(
|
|||
display: &DisplayHandle,
|
||||
manager: &ZwlrOutputManagerV1,
|
||||
output: &Output,
|
||||
) -> (ZwlrOutputHeadV1, Vec<ZwlrOutputModeV1>)
|
||||
) -> anyhow::Result<(ZwlrOutputHeadV1, Vec<ZwlrOutputModeV1>)>
|
||||
where
|
||||
D: Dispatch<ZwlrOutputHeadV1, Output>
|
||||
+ Dispatch<ZwlrOutputModeV1, Mode>
|
||||
+ OutputManagementHandler
|
||||
+ 'static,
|
||||
{
|
||||
let client = manager.client().expect("TODO");
|
||||
let client = manager
|
||||
.client()
|
||||
.context("output manager has no owning client")?;
|
||||
|
||||
let head = client
|
||||
.create_resource::<ZwlrOutputHeadV1, _, D>(display, manager.version(), output.clone())
|
||||
.unwrap();
|
||||
let head = client.create_resource::<ZwlrOutputHeadV1, _, D>(
|
||||
display,
|
||||
manager.version(),
|
||||
output.clone(),
|
||||
)?;
|
||||
|
||||
manager.head(&head);
|
||||
|
||||
|
@ -337,16 +368,13 @@ where
|
|||
|
||||
let mut wlr_modes = Vec::new();
|
||||
for mode in output.with_state(|state| state.modes.clone()) {
|
||||
let wlr_mode = client
|
||||
.create_resource::<ZwlrOutputModeV1, _, D>(display, manager.version(), mode)
|
||||
.unwrap();
|
||||
head.mode(&wlr_mode);
|
||||
wlr_mode.size(mode.size.w, mode.size.h);
|
||||
wlr_mode.refresh(mode.refresh);
|
||||
if Some(mode) == output.preferred_mode() {
|
||||
wlr_mode.preferred();
|
||||
let wlr_mode =
|
||||
create_mode_for_head::<D>(&head, display, mode, output.preferred_mode() == Some(mode));
|
||||
|
||||
match wlr_mode {
|
||||
Ok(wlr_mode) => wlr_modes.push(wlr_mode),
|
||||
Err(err) => error!("Failed to create wlr mode: {err}"),
|
||||
}
|
||||
wlr_modes.push(wlr_mode);
|
||||
}
|
||||
|
||||
if head.version() >= zwlr_output_head_v1::EVT_MAKE_SINCE {
|
||||
|
@ -365,26 +393,64 @@ where
|
|||
// false => AdaptiveSyncState::Disabled,
|
||||
// });
|
||||
|
||||
// TODO:
|
||||
// head.enabled(data.enabled as i32);
|
||||
head.enabled(true as i32);
|
||||
if true
|
||||
/* data.enabled */
|
||||
{
|
||||
if let Some(current_mode) = output.current_mode() {
|
||||
let wlr_current_mode = wlr_modes
|
||||
.iter()
|
||||
.find(|wlr_mode| wlr_mode.data::<Mode>() == Some(¤t_mode));
|
||||
if let Some(wlr_current_mode) = wlr_current_mode {
|
||||
head.current_mode(wlr_current_mode);
|
||||
if let Some(current_mode) = output.current_mode() {
|
||||
let wlr_current_mode = wlr_modes
|
||||
.iter()
|
||||
.find(|wlr_mode| wlr_mode.data::<Mode>() == Some(¤t_mode));
|
||||
if let Some(wlr_current_mode) = wlr_current_mode {
|
||||
head.current_mode(wlr_current_mode);
|
||||
} else {
|
||||
let new_wlr_current_mode = create_mode_for_head::<D>(
|
||||
&head,
|
||||
display,
|
||||
current_mode,
|
||||
output.preferred_mode() == Some(current_mode),
|
||||
);
|
||||
|
||||
match new_wlr_current_mode {
|
||||
Ok(new_wlr_current_mode) => {
|
||||
head.current_mode(&new_wlr_current_mode);
|
||||
wlr_modes.push(new_wlr_current_mode);
|
||||
}
|
||||
Err(err) => error!("Failed to create wlr mode: {err}"),
|
||||
}
|
||||
}
|
||||
head.position(output.current_location().x, output.current_location().y);
|
||||
head.transform(output.current_transform().into());
|
||||
head.scale(output.current_scale().fractional_scale());
|
||||
}
|
||||
head.position(output.current_location().x, output.current_location().y);
|
||||
head.transform(output.current_transform().into());
|
||||
head.scale(output.current_scale().fractional_scale());
|
||||
|
||||
Ok((head, wlr_modes))
|
||||
}
|
||||
|
||||
fn create_mode_for_head<D>(
|
||||
head: &ZwlrOutputHeadV1,
|
||||
display_handle: &DisplayHandle,
|
||||
mode: Mode,
|
||||
is_preferred: bool,
|
||||
) -> anyhow::Result<ZwlrOutputModeV1>
|
||||
where
|
||||
D: Dispatch<ZwlrOutputHeadV1, Output>
|
||||
+ Dispatch<ZwlrOutputModeV1, Mode>
|
||||
+ OutputManagementHandler
|
||||
+ 'static,
|
||||
{
|
||||
let client = head.client().context("head has no owning client")?;
|
||||
let wlr_mode =
|
||||
client.create_resource::<ZwlrOutputModeV1, _, D>(display_handle, head.version(), mode)?;
|
||||
|
||||
// do not reorder or wlr-randr gets 0x0 modes
|
||||
head.mode(&wlr_mode);
|
||||
|
||||
wlr_mode.size(mode.size.w, mode.size.h);
|
||||
wlr_mode.refresh(mode.refresh);
|
||||
|
||||
if is_preferred {
|
||||
wlr_mode.preferred();
|
||||
}
|
||||
|
||||
(head, wlr_modes)
|
||||
Ok(wlr_mode)
|
||||
}
|
||||
|
||||
fn manager_for_configuration<'a, D>(
|
||||
|
@ -419,6 +485,7 @@ impl OutputManagementManagerState {
|
|||
display_handle: display.clone(),
|
||||
managers: HashMap::new(),
|
||||
outputs: HashMap::new(),
|
||||
removed_outputs: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +513,7 @@ where
|
|||
.output_management_manager_state()
|
||||
.outputs
|
||||
.keys()
|
||||
.map(|output| advertise_output::<D>(handle, &manager, output))
|
||||
.flat_map(|output| advertise_output::<D>(handle, &manager, output))
|
||||
.collect();
|
||||
|
||||
let serial = u32::from(SERIAL_COUNTER.next_serial());
|
||||
|
@ -523,7 +590,16 @@ where
|
|||
let correct_serial = manager_data.serial == serial;
|
||||
|
||||
if !correct_serial {
|
||||
tracing::info!(mgr_serial = manager_data.serial, cfg_serial = serial);
|
||||
tracing::info!("cancelled, incorrect serial 527");
|
||||
config.cancelled();
|
||||
config
|
||||
.data::<PendingOutputConfiguration>()
|
||||
.unwrap()
|
||||
.inner
|
||||
.lock()
|
||||
.unwrap()
|
||||
.cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -549,11 +625,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<D> Dispatch<ZwlrOutputHeadV1, Output, D> for OutputManagementManagerState {
|
||||
impl<D> Dispatch<ZwlrOutputHeadV1, Output, D> for OutputManagementManagerState
|
||||
where
|
||||
D: OutputManagementHandler + 'static,
|
||||
{
|
||||
fn request(
|
||||
_state: &mut D,
|
||||
state: &mut D,
|
||||
_client: &Client,
|
||||
_resource: &ZwlrOutputHeadV1,
|
||||
resource: &ZwlrOutputHeadV1,
|
||||
request: <ZwlrOutputHeadV1 as Resource>::Request,
|
||||
_data: &Output,
|
||||
_dhandle: &DisplayHandle,
|
||||
|
@ -561,18 +640,37 @@ impl<D> Dispatch<ZwlrOutputHeadV1, Output, D> for OutputManagementManagerState {
|
|||
) {
|
||||
match request {
|
||||
zwlr_output_head_v1::Request::Release => {
|
||||
// TODO:
|
||||
for manager_data in state
|
||||
.output_management_manager_state()
|
||||
.managers
|
||||
.values_mut()
|
||||
{
|
||||
manager_data.heads.remove(resource);
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn destroyed(state: &mut D, _client: ClientId, resource: &ZwlrOutputHeadV1, _data: &Output) {
|
||||
for manager_data in state
|
||||
.output_management_manager_state()
|
||||
.managers
|
||||
.values_mut()
|
||||
{
|
||||
manager_data.heads.remove(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> Dispatch<ZwlrOutputModeV1, Mode, D> for OutputManagementManagerState {
|
||||
impl<D> Dispatch<ZwlrOutputModeV1, Mode, D> for OutputManagementManagerState
|
||||
where
|
||||
D: OutputManagementHandler + 'static,
|
||||
{
|
||||
fn request(
|
||||
_state: &mut D,
|
||||
state: &mut D,
|
||||
_client: &Client,
|
||||
_resource: &ZwlrOutputModeV1,
|
||||
resource: &ZwlrOutputModeV1,
|
||||
request: <ZwlrOutputModeV1 as Resource>::Request,
|
||||
_data: &Mode,
|
||||
_dhandle: &DisplayHandle,
|
||||
|
@ -580,11 +678,31 @@ impl<D> Dispatch<ZwlrOutputModeV1, Mode, D> for OutputManagementManagerState {
|
|||
) {
|
||||
match request {
|
||||
zwlr_output_mode_v1::Request::Release => {
|
||||
// TODO:
|
||||
for manager_data in state
|
||||
.output_management_manager_state()
|
||||
.managers
|
||||
.values_mut()
|
||||
{
|
||||
for modes in manager_data.heads.values_mut() {
|
||||
modes.retain(|mode| mode != resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn destroyed(state: &mut D, _client: ClientId, resource: &ZwlrOutputModeV1, _data: &Mode) {
|
||||
for manager_data in state
|
||||
.output_management_manager_state()
|
||||
.managers
|
||||
.values_mut()
|
||||
{
|
||||
for modes in manager_data.heads.values_mut() {
|
||||
modes.retain(|mode| mode != resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> Dispatch<ZwlrOutputConfigurationV1, PendingOutputConfiguration, D>
|
||||
|
@ -610,15 +728,17 @@ where
|
|||
|
||||
let mut data = pending_data.inner.lock().unwrap();
|
||||
|
||||
if data.cancelled {
|
||||
return;
|
||||
}
|
||||
|
||||
let manager_serial =
|
||||
manager_for_configuration(state, resource).map(|(_, data)| data.serial);
|
||||
|
||||
if manager_serial != Some(pending_data.serial) {
|
||||
tracing::info!("cancelled, incorrect serial 661");
|
||||
resource.cancelled();
|
||||
data.cancelled = true;
|
||||
}
|
||||
|
||||
if data.cancelled {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -637,15 +757,17 @@ where
|
|||
zwlr_output_configuration_v1::Request::DisableHead { head } => {
|
||||
let mut data = pending_data.inner.lock().unwrap();
|
||||
|
||||
if data.cancelled {
|
||||
return;
|
||||
}
|
||||
|
||||
let manager_serial =
|
||||
manager_for_configuration(state, resource).map(|(_, data)| data.serial);
|
||||
|
||||
if manager_serial != Some(pending_data.serial) {
|
||||
tracing::info!("cancelled, incorrect serial 689");
|
||||
resource.cancelled();
|
||||
data.cancelled = true;
|
||||
}
|
||||
|
||||
if data.cancelled {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -665,15 +787,17 @@ where
|
|||
| zwlr_output_configuration_v1::Request::Test) => {
|
||||
let mut data = pending_data.inner.lock().unwrap();
|
||||
|
||||
if data.cancelled {
|
||||
return;
|
||||
}
|
||||
|
||||
let manager_serial =
|
||||
manager_for_configuration(state, resource).map(|(_, data)| data.serial);
|
||||
|
||||
if manager_serial != Some(pending_data.serial) {
|
||||
tracing::info!("cancelled, incorrect serial 718");
|
||||
resource.cancelled();
|
||||
data.cancelled = true;
|
||||
}
|
||||
|
||||
if data.cancelled {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue