When removing output global, use disable_global, remove with timer
This should fix an issue where output hotplug can sometimes cause clients (including XWayland) to crash with a protocol error trying to bind the output. Using a timer doesn't seem ideal, but seems to be the correct way to do this at present. Wlroots `wlr_global_destroy_safe` is basically the same as this. Adding a `LoopHandle` argument to `OutputConfigurationState::new` seems awkward, but maybe better than a handler method for removing globals. (`IdleNotifierState::new` also takes a `LoopHandle`). Perhaps Smithay could provide some kind of helper for this.
This commit is contained in:
parent
7ac204ee79
commit
1118aa2877
2 changed files with 40 additions and 5 deletions
|
|
@ -499,7 +499,8 @@ impl State {
|
||||||
let fractional_scale_state = FractionalScaleManagerState::new::<State>(dh);
|
let fractional_scale_state = FractionalScaleManagerState::new::<State>(dh);
|
||||||
let keyboard_shortcuts_inhibit_state = KeyboardShortcutsInhibitState::new::<Self>(dh);
|
let keyboard_shortcuts_inhibit_state = KeyboardShortcutsInhibitState::new::<Self>(dh);
|
||||||
let output_state = OutputManagerState::new_with_xdg_output::<Self>(dh);
|
let output_state = OutputManagerState::new_with_xdg_output::<Self>(dh);
|
||||||
let output_configuration_state = OutputConfigurationState::new(dh, client_is_privileged);
|
let output_configuration_state =
|
||||||
|
OutputConfigurationState::new(dh, handle.clone(), client_is_privileged);
|
||||||
let output_power_state = OutputPowerState::new::<Self, _>(dh, client_is_privileged);
|
let output_power_state = OutputPowerState::new::<Self, _>(dh, client_is_privileged);
|
||||||
let overlap_notify_state =
|
let overlap_notify_state =
|
||||||
OverlapNotifyState::new::<Self, _>(dh, client_has_no_security_context);
|
OverlapNotifyState::new::<Self, _>(dh, client_has_no_security_context);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use calloop::{
|
||||||
|
timer::{TimeoutAction, Timer},
|
||||||
|
LoopHandle,
|
||||||
|
};
|
||||||
use cosmic_protocols::output_management::v1::server::{
|
use cosmic_protocols::output_management::v1::server::{
|
||||||
zcosmic_output_configuration_head_v1::ZcosmicOutputConfigurationHeadV1,
|
zcosmic_output_configuration_head_v1::ZcosmicOutputConfigurationHeadV1,
|
||||||
zcosmic_output_configuration_v1::ZcosmicOutputConfigurationV1,
|
zcosmic_output_configuration_v1::ZcosmicOutputConfigurationV1,
|
||||||
|
|
@ -25,7 +29,7 @@ use smithay::{
|
||||||
utils::{Logical, Physical, Point, Size, Transform},
|
utils::{Logical, Physical, Point, Size, Transform},
|
||||||
wayland::output::WlOutputData,
|
wayland::output::WlOutputData,
|
||||||
};
|
};
|
||||||
use std::{convert::TryFrom, sync::Mutex};
|
use std::{convert::TryFrom, sync::Mutex, time::Duration};
|
||||||
|
|
||||||
mod handlers;
|
mod handlers;
|
||||||
|
|
||||||
|
|
@ -45,6 +49,7 @@ pub struct OutputConfigurationState<D> {
|
||||||
global: GlobalId,
|
global: GlobalId,
|
||||||
extension_global: GlobalId,
|
extension_global: GlobalId,
|
||||||
dh: DisplayHandle,
|
dh: DisplayHandle,
|
||||||
|
event_loop_handle: LoopHandle<'static, D>,
|
||||||
_dispatch: std::marker::PhantomData<D>,
|
_dispatch: std::marker::PhantomData<D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +173,11 @@ where
|
||||||
+ OutputConfigurationHandler
|
+ OutputConfigurationHandler
|
||||||
+ 'static,
|
+ 'static,
|
||||||
{
|
{
|
||||||
pub fn new<F>(dh: &DisplayHandle, client_filter: F) -> OutputConfigurationState<D>
|
pub fn new<F>(
|
||||||
|
dh: &DisplayHandle,
|
||||||
|
event_loop_handle: LoopHandle<'static, D>,
|
||||||
|
client_filter: F,
|
||||||
|
) -> OutputConfigurationState<D>
|
||||||
where
|
where
|
||||||
F: for<'a> Fn(&'a Client) -> bool + Clone + Send + Sync + 'static,
|
F: for<'a> Fn(&'a Client) -> bool + Clone + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
|
@ -194,6 +203,7 @@ where
|
||||||
global,
|
global,
|
||||||
extension_global,
|
extension_global,
|
||||||
dh: dh.clone(),
|
dh: dh.clone(),
|
||||||
|
event_loop_handle: event_loop_handle.clone(),
|
||||||
_dispatch: std::marker::PhantomData,
|
_dispatch: std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +250,7 @@ where
|
||||||
let mut inner = inner.lock().unwrap();
|
let mut inner = inner.lock().unwrap();
|
||||||
inner.enabled = false;
|
inner.enabled = false;
|
||||||
if let Some(global) = inner.global.take() {
|
if let Some(global) = inner.global.take() {
|
||||||
self.dh.remove_global::<D>(global);
|
remove_global_with_timer(&self.dh, &self.event_loop_handle, global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -292,7 +302,11 @@ where
|
||||||
inner.global = Some(output.create_global::<D>(&self.dh));
|
inner.global = Some(output.create_global::<D>(&self.dh));
|
||||||
}
|
}
|
||||||
if !inner.enabled && inner.global.is_some() {
|
if !inner.enabled && inner.global.is_some() {
|
||||||
self.dh.remove_global::<D>(inner.global.take().unwrap());
|
remove_global_with_timer(
|
||||||
|
&self.dh,
|
||||||
|
&self.event_loop_handle,
|
||||||
|
inner.global.take().unwrap(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for manager in self.instances.iter_mut() {
|
for manager in self.instances.iter_mut() {
|
||||||
|
|
@ -493,6 +507,26 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove_global_with_timer<D: 'static>(
|
||||||
|
dh: &DisplayHandle,
|
||||||
|
event_loop_handle: &LoopHandle<D>,
|
||||||
|
id: GlobalId,
|
||||||
|
) {
|
||||||
|
dh.disable_global::<D>(id.clone());
|
||||||
|
let source = Timer::from_duration(Duration::from_secs(5));
|
||||||
|
let dh = dh.clone();
|
||||||
|
let res = event_loop_handle.insert_source(source, move |_, _, _state| {
|
||||||
|
dh.remove_global::<D>(id.clone());
|
||||||
|
TimeoutAction::Drop
|
||||||
|
});
|
||||||
|
if let Err(err) = res {
|
||||||
|
tracing::error!(
|
||||||
|
"failed to insert timer source to destroy output global: {}",
|
||||||
|
err
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! delegate_output_configuration {
|
macro_rules! delegate_output_configuration {
|
||||||
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
|
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
|
||||||
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue