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