xwm: Don't do multiple

This commit is contained in:
Victoria Brekenfeld 2023-03-07 20:28:41 +01:00
parent 7caae686fe
commit 659933b039
14 changed files with 114 additions and 90 deletions

View file

@ -331,7 +331,6 @@ pub fn init_backend(
// Create relative pointer global // Create relative pointer global
RelativePointerManagerState::new::<State>(&dh); RelativePointerManagerState::new::<State>(&dh);
// TODO: Do multiple Xwaylands for better multigpu
state.launch_xwayland(Some(primary)); state.launch_xwayland(Some(primary));
for (dev, path) in udev_dispatcher.as_source_ref().device_list() { for (dev, path) in udev_dispatcher.as_source_ref().device_list() {

View file

@ -298,7 +298,7 @@ where
renderer, renderer,
output, output,
&state.shell.override_redirect_windows, &state.shell.override_redirect_windows,
state.xwayland_state.values_mut(), state.xwayland_state.as_mut(),
(!move_active && active_output).then_some(&last_active_seat), (!move_active && active_output).then_some(&last_active_seat),
exclude_workspace_overview, exclude_workspace_overview,
) )

View file

@ -11,6 +11,7 @@ use crate::{
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use smithay::{ use smithay::{
backend::{ backend::{
egl::EGLDevice,
renderer::{ renderer::{
damage::DamageTrackedRenderer, gles2::Gles2Renderbuffer, glow::GlowRenderer, ImportDma, damage::DamageTrackedRenderer, gles2::Gles2Renderbuffer, glow::GlowRenderer, ImportDma,
ImportEgl, ImportEgl,
@ -25,6 +26,7 @@ use smithay::{
wayland_server::DisplayHandle, wayland_server::DisplayHandle,
}, },
utils::Transform, utils::Transform,
wayland::dmabuf::DmabufFeedbackBuilder,
}; };
use std::cell::RefCell; use std::cell::RefCell;
use tracing::{error, info, warn}; use tracing::{error, info, warn};
@ -257,7 +259,6 @@ pub fn init_backend(
seats.iter().cloned(), seats.iter().cloned(),
&state.common.event_loop_handle, &state.common.event_loop_handle,
); );
state.launch_xwayland(None); state.launch_xwayland(None);
Ok(()) Ok(())
@ -269,21 +270,56 @@ fn init_egl_client_side(
renderer: &mut WinitGraphicsBackend<GlowRenderer>, renderer: &mut WinitGraphicsBackend<GlowRenderer>,
) -> Result<()> { ) -> Result<()> {
let bind_result = renderer.renderer().bind_wl_display(dh); let bind_result = renderer.renderer().bind_wl_display(dh);
match bind_result { let render_node = EGLDevice::device_for_display(renderer.renderer().egl_context().display())
Ok(_) => { .and_then(|device| device.try_get_render_node());
let dmabuf_formats = renderer
.renderer()
.dmabuf_formats()
.cloned()
.collect::<Vec<_>>();
let dmabuf_default_feedback = match render_node {
Ok(Some(node)) => {
let dmabuf_default_feedback =
DmabufFeedbackBuilder::new(node.dev_id(), dmabuf_formats.clone())
.build()
.unwrap();
Some(dmabuf_default_feedback)
}
Ok(None) => {
warn!("Failed to query render node, dmabuf protocol will only advertise v3");
None
}
Err(err) => {
warn!(
?err,
"Failed to egl device for display, dmabuf protocol will only advertise v3"
);
None
}
};
match dmabuf_default_feedback {
Some(feedback) => {
state
.common
.dmabuf_state
.create_global_with_default_feedback::<State>(dh, &feedback);
info!("EGL hardware-acceleration enabled."); info!("EGL hardware-acceleration enabled.");
let dmabuf_formats = renderer }
.renderer() None if bind_result.is_ok() => {
.dmabuf_formats()
.cloned()
.collect::<Vec<_>>();
state state
.common .common
.dmabuf_state .dmabuf_state
.create_global::<State>(dh, dmabuf_formats); .create_global::<State>(dh, dmabuf_formats);
info!("EGL hardware-acceleration enabled.");
} }
Err(err) => warn!(?err, "Unable to initialize bind display to EGL."), None => {
}; let err = bind_result.unwrap_err();
warn!(?err, "Unable to initialize bind display to EGL.")
}
}
Ok(()) Ok(())
} }

View file

@ -35,6 +35,7 @@ use smithay::{
wayland_server::DisplayHandle, wayland_server::DisplayHandle,
}, },
utils::{DeviceFd, Transform}, utils::{DeviceFd, Transform},
wayland::dmabuf::DmabufFeedbackBuilder,
}; };
use std::{cell::RefCell, os::unix::io::OwnedFd}; use std::{cell::RefCell, os::unix::io::OwnedFd};
use tracing::{debug, error, info, warn}; use tracing::{debug, error, info, warn};
@ -351,7 +352,7 @@ pub fn init_backend(
unsafe { GlowRenderer::new(context) }.with_context(|| "Failed to initialize renderer")?; unsafe { GlowRenderer::new(context) }.with_context(|| "Failed to initialize renderer")?;
init_shaders(&mut renderer).expect("Failed to initialize renderer"); init_shaders(&mut renderer).expect("Failed to initialize renderer");
init_egl_client_side(dh, state, &mut renderer)?; init_egl_client_side(dh, state, &drm_node, &mut renderer)?;
state.backend = BackendData::X11(X11State { state.backend = BackendData::X11(X11State {
handle, handle,
@ -381,7 +382,6 @@ pub fn init_backend(
seats.iter().cloned(), seats.iter().cloned(),
&state.common.event_loop_handle, &state.common.event_loop_handle,
); );
state.launch_xwayland(None); state.launch_xwayland(None);
event_loop event_loop
@ -475,22 +475,32 @@ pub fn init_backend(
Ok(()) Ok(())
} }
fn init_egl_client_side<R>(dh: &DisplayHandle, state: &mut State, renderer: &mut R) -> Result<()> fn init_egl_client_side<R>(
dh: &DisplayHandle,
state: &mut State,
render_node: &DrmNode,
renderer: &mut R,
) -> Result<()>
where where
R: ImportEgl + ImportDma, R: ImportEgl + ImportDma,
{ {
let bind_result = renderer.bind_wl_display(dh); if let Err(err) = renderer.bind_wl_display(dh) {
match bind_result { warn!(
Ok(_) => { ?err,
info!("EGL hardware-acceleration enabled."); "Unable to initialize bind display to EGL. Some older clients may not work correctly."
let dmabuf_formats = renderer.dmabuf_formats().cloned().collect::<Vec<_>>(); )
state }
.common let dmabuf_formats = renderer.dmabuf_formats().cloned().collect::<Vec<_>>();
.dmabuf_state
.create_global::<State>(dh, dmabuf_formats); let default_feedback = DmabufFeedbackBuilder::new(render_node.dev_id(), dmabuf_formats.clone())
} .build()
Err(err) => warn!(?err, "Unable to initialize bind display to EGL."), .unwrap();
}; state
.common
.dmabuf_state
.create_global_with_default_feedback::<State>(dh, &default_feedback);
info!("EGL hardware-acceleration enabled.");
Ok(()) Ok(())
} }

View file

@ -1017,8 +1017,7 @@ impl State {
&self &self
.common .common
.xwayland_state .xwayland_state
.values() .as_ref()
.next()
.map(|s| format!(":{}", s.display)) .map(|s| format!(":{}", s.display))
.unwrap_or(String::new()), .unwrap_or(String::new()),
) )

View file

@ -78,13 +78,7 @@ pub fn setup_socket(handle: LoopHandle<Data>, state: &State) -> Result<()> {
.into_string() .into_string()
.map_err(|_| anyhow!("wayland socket is no valid utf-8 string?"))?, .map_err(|_| anyhow!("wayland socket is no valid utf-8 string?"))?,
); );
if let Some(display) = state if let Some(display) = state.common.xwayland_state.as_ref().map(|s| s.display) {
.common
.xwayland_state
.values()
.next()
.map(|s| s.display)
{
env.insert(String::from("DISPLAY"), format!(":{}", display)); env.insert(String::from("DISPLAY"), format!(":{}", display));
} }
let message = serde_json::to_string(&Message::SetEnv { variables: env }) let message = serde_json::to_string(&Message::SetEnv { variables: env })

View file

@ -131,7 +131,7 @@ impl Shell {
fn update_active<'a, 'b>( fn update_active<'a, 'b>(
&mut self, &mut self,
seats: impl Iterator<Item = &'a Seat<State>>, seats: impl Iterator<Item = &'a Seat<State>>,
xwms: impl Iterator<Item = &'b mut XWaylandState>, mut xwm: Option<&'b mut XWaylandState>,
) { ) {
// update activate status // update activate status
let focused_windows = seats let focused_windows = seats
@ -144,16 +144,13 @@ impl Shell {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut xwms = xwms.collect::<Vec<_>>();
for output in self.outputs.iter() { for output in self.outputs.iter() {
let workspace = self.workspaces.active_mut(output); let workspace = self.workspaces.active_mut(output);
for focused in focused_windows.iter() { for focused in focused_windows.iter() {
if workspace.floating_layer.mapped().any(|m| m == focused) { if workspace.floating_layer.mapped().any(|m| m == focused) {
if let CosmicSurface::X11(window) = focused.active_window() { if let CosmicSurface::X11(window) = focused.active_window() {
for xwm in xwms.iter_mut().flat_map(|state| state.xwm.as_mut()) { if let Some(xwm) = xwm.as_mut().and_then(|state| state.xwm.as_mut()) {
if Some(xwm.id()) == window.xwm_id() { let _ = xwm.raise_window(&window);
let _ = xwm.raise_window(&window);
}
} }
} }
workspace.floating_layer.space.raise_element(focused, true); workspace.floating_layer.space.raise_element(focused, true);
@ -179,7 +176,7 @@ impl Common {
state state
.common .common
.shell .shell
.update_active(seats.iter(), state.common.xwayland_state.values_mut()); .update_active(seats.iter(), state.common.xwayland_state.as_mut());
} }
pub fn refresh_focus(state: &mut State) { pub fn refresh_focus(state: &mut State) {
@ -274,6 +271,6 @@ impl Common {
state state
.common .common
.shell .shell
.update_active(seats.iter(), state.common.xwayland_state.values_mut()) .update_active(seats.iter(), state.common.xwayland_state.as_mut())
} }
} }

View file

@ -1085,13 +1085,12 @@ impl Shell {
.map(mapped.clone(), &seat, focus_stack.iter()); .map(mapped.clone(), &seat, focus_stack.iter());
} }
if let CosmicSurface::X11(surface) = window { if let CosmicSurface::X11(_) = window {
if let Some(xwm) = state if let Some(xwm) = state
.common .common
.xwayland_state .xwayland_state
.values_mut() .as_mut()
.flat_map(|state| state.xwm.as_mut()) .and_then(|state| state.xwm.as_mut())
.find(|xwm| Some(xwm.id()) == surface.xwm_id())
{ {
if let Err(err) = xwm.update_stacking_order_downwards(workspace.mapped()) { if let Err(err) = xwm.update_stacking_order_downwards(workspace.mapped()) {
warn!(?err, "Failed to update Xwayland stacking order."); warn!(?err, "Failed to update Xwayland stacking order.");

View file

@ -437,7 +437,7 @@ impl Workspace {
renderer: &mut R, renderer: &mut R,
output: &Output, output: &Output,
override_redirect_windows: &[X11Surface], override_redirect_windows: &[X11Surface],
xwm_state: impl Iterator<Item = &'a mut XWaylandState>, xwm_state: Option<&'a mut XWaylandState>,
draw_focus_indicator: Option<&Seat<State>>, draw_focus_indicator: Option<&Seat<State>>,
exclude_workspace_overview: bool, exclude_workspace_overview: bool,
) -> Result<Vec<WorkspaceRenderElement<R>>, OutputNotMapped> ) -> Result<Vec<WorkspaceRenderElement<R>>, OutputNotMapped>
@ -502,7 +502,7 @@ impl Workspace {
fullscreen, renderer, (0, 0).into(), output_scale.into() fullscreen, renderer, (0, 0).into(), output_scale.into()
)); ));
for xwm in xwm_state.flat_map(|state| state.xwm.as_mut()) { if let Some(xwm) = xwm_state.and_then(|state| state.xwm.as_mut()) {
if let Err(err) = if let Err(err) =
xwm.update_stacking_order_upwards(render_elements.iter().rev().map(|e| e.id())) xwm.update_stacking_order_upwards(render_elements.iter().rev().map(|e| e.id()))
{ {
@ -584,7 +584,7 @@ impl Workspace {
.map(WorkspaceRenderElement::from), .map(WorkspaceRenderElement::from),
); );
for xwm in xwm_state.flat_map(|state| state.xwm.as_mut()) { if let Some(xwm) = xwm_state.and_then(|state| state.xwm.as_mut()) {
if let Err(err) = if let Err(err) =
xwm.update_stacking_order_upwards(render_elements.iter().rev().map(|e| e.id())) xwm.update_stacking_order_upwards(render_elements.iter().rev().map(|e| e.id()))
{ {

View file

@ -57,7 +57,7 @@ use smithay::{
}; };
use tracing::error; use tracing::error;
use std::{cell::RefCell, collections::HashMap, ffi::OsString, time::Duration}; use std::{cell::RefCell, ffi::OsString, time::Duration};
use std::{collections::VecDeque, time::Instant}; use std::{collections::VecDeque, time::Instant};
pub struct ClientState { pub struct ClientState {
@ -118,7 +118,7 @@ pub struct Common {
pub xdg_decoration_state: XdgDecorationState, pub xdg_decoration_state: XdgDecorationState,
// xwayland state // xwayland state
pub xwayland_state: HashMap<Option<DrmNode>, XWaylandState>, pub xwayland_state: Option<XWaylandState>,
} }
pub enum BackendData { pub enum BackendData {
@ -290,7 +290,7 @@ impl State {
kde_decoration_state, kde_decoration_state,
xdg_decoration_state, xdg_decoration_state,
xwayland_state: HashMap::new(), xwayland_state: None,
}, },
backend: BackendData::Unset, backend: BackendData::Unset,
} }

View file

@ -15,8 +15,7 @@ pub fn ready(state: &State) {
&state &state
.common .common
.xwayland_state .xwayland_state
.values() .as_ref()
.next()
.map(|s| format!(":{}", s.display)) .map(|s| format!(":{}", s.display))
.unwrap_or(String::new()), .unwrap_or(String::new()),
) )

View file

@ -58,8 +58,8 @@ impl DataDeviceHandler for State {
} }
fn new_selection(&mut self, source: Option<WlDataSource>) { fn new_selection(&mut self, source: Option<WlDataSource>) {
for xstate in self.common.xwayland_state.values_mut() { if let Some(state) = self.common.xwayland_state.as_mut() {
if let Some(xwm) = xstate.xwm.as_mut() { if let Some(xwm) = state.xwm.as_mut() {
if let Some(source) = &source { if let Some(source) = &source {
if let Ok(Err(err)) = with_source_metadata(source, |metadata| { if let Ok(Err(err)) = with_source_metadata(source, |metadata| {
xwm.new_selection( xwm.new_selection(
@ -80,14 +80,13 @@ impl DataDeviceHandler for State {
&mut self, &mut self,
mime_type: String, mime_type: String,
fd: OwnedFd, fd: OwnedFd,
user_data: &Self::SelectionUserData, _user_data: &Self::SelectionUserData,
) { ) {
if let Some(xwm) = self if let Some(xwm) = self
.common .common
.xwayland_state .xwayland_state
.values_mut() .as_mut()
.flat_map(|xstate| xstate.xwm.as_mut()) .and_then(|xstate| xstate.xwm.as_mut())
.find(|xwm| &xwm.id() == user_data)
{ {
if let Err(err) = xwm.send_selection( if let Err(err) = xwm.send_selection(
SelectionType::Clipboard, SelectionType::Clipboard,

View file

@ -17,8 +17,8 @@ impl PrimarySelectionHandler for State {
} }
fn new_selection(&mut self, source: Option<ZwpPrimarySelectionSourceV1>) { fn new_selection(&mut self, source: Option<ZwpPrimarySelectionSourceV1>) {
for xstate in self.common.xwayland_state.values_mut() { if let Some(state) = self.common.xwayland_state.as_mut() {
if let Some(xwm) = xstate.xwm.as_mut() { if let Some(xwm) = state.xwm.as_mut() {
if let Some(source) = &source { if let Some(source) = &source {
if let Ok(Err(err)) = with_source_metadata(source, |metadata| { if let Ok(Err(err)) = with_source_metadata(source, |metadata| {
xwm.new_selection(SelectionType::Primary, Some(metadata.mime_types.clone())) xwm.new_selection(SelectionType::Primary, Some(metadata.mime_types.clone()))
@ -36,14 +36,13 @@ impl PrimarySelectionHandler for State {
&mut self, &mut self,
mime_type: String, mime_type: String,
fd: OwnedFd, fd: OwnedFd,
user_data: &Self::SelectionUserData, _user_data: &Self::SelectionUserData,
) { ) {
if let Some(xwm) = self if let Some(xwm) = self
.common .common
.xwayland_state .xwayland_state
.values_mut() .as_mut()
.flat_map(|xstate| xstate.xwm.as_mut()) .and_then(|xstate| xstate.xwm.as_mut())
.find(|xwm| &xwm.id() == user_data)
{ {
if let Err(err) = xwm.send_selection( if let Err(err) = xwm.send_selection(
SelectionType::Primary, SelectionType::Primary,

View file

@ -37,8 +37,8 @@ pub struct XWaylandState {
} }
impl State { impl State {
pub fn launch_xwayland(&mut self, drm_node: Option<DrmNode>) { pub fn launch_xwayland(&mut self, render_node: Option<DrmNode>) {
if self.common.xwayland_state.contains_key(&drm_node) { if self.common.xwayland_state.is_some() {
return; return;
} }
@ -81,14 +81,11 @@ impl State {
); );
} }
let mut xwayland_state = let mut xwayland_state = data.state.common.xwayland_state.as_mut().unwrap();
data.state.common.xwayland_state.get_mut(&drm_node).unwrap();
xwayland_state.xwm = Some(wm); xwayland_state.xwm = Some(wm);
} }
XWaylandEvent::Exited => { XWaylandEvent::Exited => {
if let Some(mut xwayland_state) = if let Some(mut xwayland_state) = data.state.common.xwayland_state.take() {
data.state.common.xwayland_state.remove(&drm_node)
{
xwayland_state.xwm = None; xwayland_state.xwm = None;
} }
} }
@ -105,21 +102,18 @@ impl State {
None, None,
std::iter::empty::<(OsString, OsString)>(), std::iter::empty::<(OsString, OsString)>(),
//vec![("WAYLAND_DEBUG", "client")].into_iter(), //vec![("WAYLAND_DEBUG", "client")].into_iter(),
|map| { |user_data| {
if let Some(node) = drm_node { if let Some(node) = render_node {
map.insert_if_missing(|| node); user_data.insert_if_missing(|| node);
} }
}, },
) { ) {
Ok(display) => { Ok(display) => {
self.common.xwayland_state.insert( self.common.xwayland_state = Some(XWaylandState {
drm_node, xwayland,
XWaylandState { xwm: None,
xwayland, display,
xwm: None, });
display,
},
);
} }
Err(err) => { Err(err) => {
error!(?err, "Failed to start Xwayland."); error!(?err, "Failed to start Xwayland.");
@ -130,13 +124,12 @@ impl State {
} }
impl XwmHandler for Data { impl XwmHandler for Data {
fn xwm_state(&mut self, xwm: XwmId) -> &mut X11Wm { fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm {
self.state self.state
.common .common
.xwayland_state .xwayland_state
.values_mut() .as_mut()
.flat_map(|state| &mut state.xwm) .and_then(|state| state.xwm.as_mut())
.find(|wm| wm.id() == xwm)
.unwrap() .unwrap()
} }