Merge pull request #120 from pinnacle-comp/fix_outputs_udev

Fix output display on udev
This commit is contained in:
Ottatop 2023-12-25 19:56:26 -06:00 committed by GitHub
commit 1a085fab3f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 133 additions and 157 deletions

View file

@ -79,6 +79,7 @@ impl State {
surface.close().expect("failed to close x11 win");
}
WindowElement::X11OverrideRedirect(_) => (),
_ => unreachable!(),
}
}
}
@ -121,7 +122,8 @@ impl State {
FloatingOrTiled::Tiled(_) => FloatingOrTiled::Tiled(Some(rect)),
}
});
if let Some(output) = window.output(self) {
for output in self.space.outputs_for_element(&window) {
self.update_windows(&output);
self.schedule_render(&output);
}
@ -158,11 +160,6 @@ impl State {
let Some(output) = window.output(self) else { return };
self.update_windows(&output);
// Sometimes toggling won't change the window size,
// causing no commit.
//
// Schedule a render in case the window moves.
self.schedule_render(&output);
}
Msg::ToggleFullscreen { window_id } => {
@ -185,9 +182,8 @@ impl State {
self.config.window_rules.push((cond, rule));
}
Msg::WindowMoveGrab { button } => {
// TODO: in the future, there may be movable layer surfaces
let Some((FocusTarget::Window(window), _)) =
self.surface_under(self.pointer_location)
self.focus_target_under(self.pointer_location)
else {
return;
};
@ -208,7 +204,7 @@ impl State {
// TODO: in the future, there may be movable layer surfaces
let pointer_loc = self.pointer_location;
let Some((FocusTarget::Window(window), window_loc)) =
self.surface_under(pointer_loc)
self.focus_target_under(pointer_loc)
else {
return;
};
@ -513,6 +509,7 @@ impl State {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
(Some(surface.class()), Some(surface.title()))
}
_ => unreachable!(),
});
let focused = window.as_ref().and_then(|win| {
@ -749,7 +746,6 @@ impl State {
}
};
// This is not important enough to crash on error, so just print the error instead
if let Err(err) = self.async_scheduler.schedule(future) {
tracing::error!("Failed to schedule future: {err}");
}

View file

@ -133,6 +133,8 @@ impl Backend {
impl Udev {
/// Schedule a new render that will cause the compositor to redraw everything.
pub fn schedule_render(&mut self, loop_handle: &LoopHandle<CalloopData>, output: &Output) {
// tracing::debug!("schedule_render on output {}", output.name());
let Some(surface) = render_surface_for_output(output, &mut self.backends) else {
return;
};
@ -400,9 +402,9 @@ pub fn run_udev() -> anyhow::Result<()> {
data.state.connector_connected(node, connector, crtc);
}
}
// for output in data.state.space.outputs().cloned().collect::<Vec<_>>() {
// data.state.schedule_render(&output);
// }
for output in data.state.space.outputs().cloned().collect::<Vec<_>>() {
data.state.schedule_render(&output);
}
}
}
})

View file

@ -374,6 +374,7 @@ impl WaylandFocus for FocusTarget {
) => surface.same_client_as(object_id),
FocusTarget::Popup(popup) => popup.wl_surface().id().same_client_as(object_id),
FocusTarget::LayerSurface(surf) => surf.wl_surface().id().same_client_as(object_id),
_ => unreachable!(),
}
}
}

View file

@ -146,6 +146,11 @@ impl PointerGrab<State> for MoveSurfaceGrab {
.configure(new_geo)
.expect("failed to configure x11 win");
}
let outputs = state.space.outputs_for_element(&self.window);
for output in outputs {
state.schedule_render(&output);
}
}
}

View file

@ -179,6 +179,7 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
.expect("failed to configure x11 win");
}
WindowElement::X11OverrideRedirect(_) => (),
_ => unreachable!(),
}
}
@ -235,6 +236,7 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
});
}
WindowElement::X11OverrideRedirect(_) => (),
_ => unreachable!(),
}
}
}

View file

@ -10,7 +10,7 @@ use smithay::{
delegate_compositor, delegate_data_device, delegate_fractional_scale, delegate_layer_shell,
delegate_output, delegate_presentation, delegate_primary_selection, delegate_relative_pointer,
delegate_seat, delegate_shm, delegate_viewporter,
desktop::{self, find_popup_root_surface, layer_map_for_output, PopupKind, WindowSurfaceType},
desktop::{self, layer_map_for_output, PopupKind, WindowSurfaceType},
input::{pointer::CursorImageStatus, Seat, SeatHandler, SeatState},
output::Output,
reexports::{
@ -130,24 +130,33 @@ impl CompositorHandler for State {
crate::grab::resize_grab::handle_commit(self, surface);
let output = if let Some(output) = self
.window_for_surface(surface)
.and_then(|win| win.output(self))
{
output // surface is a window
} else if let Some(output) = self
.window_for_surface(&root)
.and_then(|win| win.output(self))
{
output // root is a window
} else if let Some(output) = self
.popup_manager
.find_popup(surface)
.and_then(|popup| find_popup_root_surface(&popup).ok())
.and_then(|surf| self.window_for_surface(&surf))
.and_then(|win| win.output(self))
{
output // surface is a popup
let outputs = if let Some(window) = self.window_for_surface(surface) {
let mut outputs = self.space.outputs_for_element(&window);
// When the window hasn't been mapped `outputs` is empty,
// so also trigger a render using the window's tags' output
if let Some(output) = window.output(self) {
outputs.push(output);
}
outputs // surface is a window
} else if let Some(window) = self.window_for_surface(&root) {
let mut outputs = self.space.outputs_for_element(&window);
if let Some(output) = window.output(self) {
outputs.push(output);
}
outputs // surface is a root window
} else if let Some(PopupKind::Xdg(surf)) = self.popup_manager.find_popup(surface) {
let geo = surf.with_pending_state(|state| state.geometry);
let outputs = self
.space
.outputs()
.filter_map(|output| {
let op_geo = self.space.output_geometry(output);
op_geo.and_then(|op_geo| op_geo.overlaps_or_touches(geo).then_some(output))
})
.cloned()
.collect::<Vec<_>>();
outputs
} else if let Some(output) = self
.space
.outputs()
@ -159,12 +168,14 @@ impl CompositorHandler for State {
})
.cloned()
{
output // surface is a layer surface
vec![output] // surface is a layer surface
} else {
return;
};
self.schedule_render(&output);
for output in outputs {
self.schedule_render(&output);
}
}
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {

View file

@ -77,7 +77,7 @@ impl State {
}
/// Get the [`FocusTarget`] under `point`.
pub fn surface_under<P>(&self, point: P) -> Option<(FocusTarget, Point<i32, Logical>)>
pub fn focus_target_under<P>(&self, point: P) -> Option<(FocusTarget, Point<i32, Logical>)>
where
P: Into<Point<f64, Logical>>,
{
@ -100,7 +100,11 @@ impl State {
let top_fullscreen_window = self.focus_state.focus_stack.iter().rev().find(|win| {
win.with_state(|state| {
state.fullscreen_or_maximized.is_fullscreen()
&& state.tags.iter().any(|tag| tag.active())
&& output.with_state(|op_state| {
op_state
.focused_tags()
.any(|op_tag| state.tags.contains(op_tag))
})
})
});
@ -290,7 +294,7 @@ impl State {
// If the button was clicked, focus on the window below if exists, else
// unfocus on windows.
if button_state == ButtonState::Pressed {
if let Some((focus, _)) = self.surface_under(pointer_loc) {
if let Some((focus, _)) = self.focus_target_under(pointer_loc) {
// Move window to top of stack.
if let FocusTarget::Window(window) = &focus {
self.space.raise_element(window, true);
@ -343,6 +347,7 @@ impl State {
// INFO: do i need to configure this?
}
WindowElement::X11OverrideRedirect(_) => (),
_ => unreachable!(),
});
keyboard.set_focus(self, None, serial);
}
@ -465,7 +470,7 @@ impl State {
pointer.motion(
self,
self.surface_under(pointer_loc),
self.focus_target_under(pointer_loc),
&MotionEvent {
location: pointer_loc,
serial,
@ -499,7 +504,7 @@ impl State {
}
}
let surface_under = self.surface_under(self.pointer_location);
let surface_under = self.focus_target_under(self.pointer_location);
if let Some(pointer) = self.seat.get_pointer() {
pointer.motion(

View file

@ -175,6 +175,7 @@ impl State {
// filtered out up there somewhere
unreachable!();
}
_ => unreachable!(),
}
}
});

View file

@ -78,6 +78,7 @@ where
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
surface.render_elements(renderer, location, scale, alpha)
}
_ => unreachable!(),
}
.into_iter()
.map(C::from)
@ -117,7 +118,7 @@ where
.map(|(surface, loc)| {
let render_elements = surface.render_elements::<WaylandSurfaceRenderElement<R>>(
renderer,
loc.to_physical((scale.x.round() as i32, scale.x.round() as i32)),
loc.to_physical((scale.x.round() as i32, scale.y.round() as i32)),
scale,
1.0,
);
@ -143,6 +144,7 @@ where
/// Get render elements for windows on active tags.
fn tag_render_elements<R>(
output: &Output,
windows: &[WindowElement],
space: &Space<WindowElement>,
renderer: &mut R,
@ -155,14 +157,22 @@ where
let elements = windows
.iter()
.rev() // rev because I treat the focus stack backwards vs how the renderer orders it
.filter(|win| win.is_on_active_tag(space.outputs()))
.filter(|win| {
win.is_on_active_tag(space.outputs())
})
.map(|win| {
// subtract win.geometry().loc to align decorations correctly
let loc = (space.element_location(win).unwrap_or((0, 0).into())
- win.geometry().loc)
let loc = (space.element_location(win).unwrap_or((0, 0).into()) - win.geometry().loc - output.current_location())
.to_physical((scale.x.round() as i32, scale.x.round() as i32));
(win.render_elements::<WaylandSurfaceRenderElement<R>>(renderer, loc, scale, 1.0), space.element_geometry(win))
let elem_geo = space.element_geometry(win).map(|mut geo| {
geo.loc -= output.current_location();
geo
});
(win.render_elements::<WaylandSurfaceRenderElement<R>>(renderer, loc, scale, 1.0), elem_geo)
}).flat_map(|(elems, rect)| {
// elems.into_iter().map(OutputRenderElements::from).collect::<Vec<_>>()
match rect {
Some(rect) => {
elems.into_iter().filter_map(|elem| {
@ -296,22 +306,26 @@ where
output_render_elements.extend(o_r_elements.map(OutputRenderElements::from));
let top_fullscreen_window = windows.iter().rev().find(|win| {
let is_wayland_actually_fullscreen = {
if let WindowElement::Wayland(window) = win {
window
.toplevel()
.current_state()
.states
.contains(xdg_toplevel::State::Fullscreen)
} else {
true
}
};
win.with_state(|state| {
let is_wayland_actually_fullscreen = {
if let WindowElement::Wayland(window) = win {
window
.toplevel()
.current_state()
.states
.contains(xdg_toplevel::State::Fullscreen)
} else {
true
}
};
state.fullscreen_or_maximized.is_fullscreen()
&& state.tags.iter().any(|tag| tag.active())
&& is_wayland_actually_fullscreen
})
&& output.with_state(|op_state| {
op_state
.focused_tags()
.any(|op_tag| state.tags.contains(op_tag))
})
}) && is_wayland_actually_fullscreen
});
// If fullscreen windows exist, render only the topmost one
@ -332,7 +346,8 @@ where
overlay,
} = layer_render_elements(output, renderer, scale);
let window_render_elements = tag_render_elements::<R>(&windows, space, renderer, scale);
let window_render_elements =
tag_render_elements::<R>(output, &windows, space, renderer, scale);
// Elements render from top to bottom

View file

@ -8,7 +8,6 @@ use std::{cell::RefCell, time::Duration};
use smithay::{
backend::input::KeyState,
desktop::{
space::SpaceElement,
utils::{
send_dmabuf_feedback_surface_tree, send_frames_surface_tree,
take_presentation_feedback_surface_tree, with_surfaces_surface_tree,
@ -26,7 +25,8 @@ use smithay::{
wayland_protocols::wp::presentation_time::server::wp_presentation_feedback,
wayland_server::protocol::wl_surface::WlSurface,
},
utils::{user_data::UserDataMap, IsAlive, Logical, Point, Rectangle, Serial},
space_elements,
utils::{user_data::UserDataMap, Logical, Rectangle, Serial},
wayland::{
compositor::{self, SurfaceData},
dmabuf::DmabufFeedback,
@ -42,15 +42,16 @@ use self::window_state::{LocationRequestState, WindowElementState};
pub mod window_state;
/// The different types of windows.
#[derive(Debug, Clone, PartialEq)]
pub enum WindowElement {
space_elements! {
/// The different types of windows.
#[derive(Debug, Clone, PartialEq)]
pub WindowElement;
/// This is a native Wayland window.
Wayland(Window),
Wayland = Window,
/// This is an Xwayland window.
X11(X11Surface),
X11 = X11Surface,
/// This is an Xwayland override redirect window, which should not be messed with.
X11OverrideRedirect(X11Surface),
X11OverrideRedirect = X11Surface,
}
impl WindowElement {
@ -65,6 +66,7 @@ impl WindowElement {
with_surfaces_surface_tree(&surface, processor);
}
}
_ => unreachable!(),
}
}
@ -93,6 +95,7 @@ impl WindowElement {
);
}
}
_ => unreachable!(),
}
}
@ -123,6 +126,7 @@ impl WindowElement {
);
}
}
_ => unreachable!(),
}
}
@ -153,6 +157,7 @@ impl WindowElement {
);
}
}
_ => unreachable!(),
}
}
@ -162,6 +167,7 @@ impl WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
surface.wl_surface()
}
_ => unreachable!(),
}
}
@ -171,6 +177,7 @@ impl WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
surface.user_data()
}
_ => unreachable!(),
}
}
@ -196,6 +203,7 @@ impl WindowElement {
.expect("failed to configure x11 win");
}
}
_ => unreachable!(),
}
self.with_state(|state| {
state.loc_request_state = LocationRequestState::Sent(new_geo.loc);
@ -219,6 +227,7 @@ impl WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
Some(surface.class())
}
_ => unreachable!(),
}
}
@ -239,6 +248,7 @@ impl WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
Some(surface.title())
}
_ => unreachable!(),
}
}
@ -317,17 +327,6 @@ impl WindowElement {
}
}
impl IsAlive for WindowElement {
fn alive(&self) -> bool {
match self {
WindowElement::Wayland(window) => window.alive(),
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
surface.alive()
}
}
}
}
impl PointerTarget<State> for WindowElement {
fn frame(&self, seat: &Seat<State>, data: &mut State) {
match self {
@ -335,6 +334,7 @@ impl PointerTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
surface.frame(seat, data)
}
_ => unreachable!(),
}
}
@ -345,6 +345,7 @@ impl PointerTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
PointerTarget::enter(surface, seat, data, event)
}
_ => unreachable!(),
}
}
@ -355,6 +356,7 @@ impl PointerTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
PointerTarget::motion(surface, seat, data, event)
}
_ => unreachable!(),
}
}
@ -372,6 +374,7 @@ impl PointerTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
PointerTarget::relative_motion(surface, seat, data, event);
}
_ => unreachable!(),
}
}
@ -387,6 +390,7 @@ impl PointerTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
PointerTarget::button(surface, seat, data, event)
}
_ => unreachable!(),
}
}
@ -397,6 +401,7 @@ impl PointerTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
PointerTarget::axis(surface, seat, data, frame)
}
_ => unreachable!(),
}
}
@ -409,6 +414,7 @@ impl PointerTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
PointerTarget::leave(surface, seat, data, serial, time)
}
_ => unreachable!(),
}
}
@ -500,6 +506,7 @@ impl KeyboardTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
KeyboardTarget::enter(surface, seat, data, keys, serial)
}
_ => unreachable!(),
}
}
@ -509,6 +516,7 @@ impl KeyboardTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
KeyboardTarget::leave(surface, seat, data, serial)
}
_ => unreachable!(),
}
}
@ -528,6 +536,7 @@ impl KeyboardTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
KeyboardTarget::key(surface, seat, data, key, state, serial, time);
}
_ => unreachable!(),
}
}
@ -545,83 +554,7 @@ impl KeyboardTarget<State> for WindowElement {
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
KeyboardTarget::modifiers(surface, seat, data, modifiers, serial);
}
}
}
}
impl SpaceElement for WindowElement {
fn geometry(&self) -> Rectangle<i32, Logical> {
// TODO: ssd
match self {
WindowElement::Wayland(window) => SpaceElement::geometry(window),
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
SpaceElement::geometry(surface)
}
}
}
fn bbox(&self) -> Rectangle<i32, Logical> {
// TODO: ssd
match self {
WindowElement::Wayland(window) => SpaceElement::bbox(window),
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
SpaceElement::bbox(surface)
}
}
}
fn is_in_input_region(&self, point: &Point<f64, Logical>) -> bool {
// TODO: ssd
match self {
WindowElement::Wayland(window) => SpaceElement::is_in_input_region(window, point),
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
SpaceElement::is_in_input_region(surface, point)
}
}
}
fn z_index(&self) -> u8 {
match self {
WindowElement::Wayland(window) => SpaceElement::z_index(window),
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
SpaceElement::z_index(surface)
}
}
}
fn set_activate(&self, activated: bool) {
match self {
WindowElement::Wayland(window) => SpaceElement::set_activate(window, activated),
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
SpaceElement::set_activate(surface, activated)
}
}
}
fn output_enter(&self, output: &Output, overlap: Rectangle<i32, Logical>) {
match self {
WindowElement::Wayland(window) => SpaceElement::output_enter(window, output, overlap),
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
SpaceElement::output_enter(surface, output, overlap)
}
}
}
fn output_leave(&self, output: &Output) {
match self {
WindowElement::Wayland(window) => SpaceElement::output_leave(window, output),
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
SpaceElement::output_leave(surface, output)
}
}
}
fn refresh(&self) {
match self {
WindowElement::Wayland(window) => SpaceElement::refresh(window),
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
SpaceElement::refresh(surface)
}
_ => unreachable!(),
}
}
}

View file

@ -52,6 +52,7 @@ impl TiledWindowBlocker {
})
}
WindowElement::X11(_) | WindowElement::X11OverrideRedirect(_) => true,
_ => unreachable!(),
});
tracing::debug!(

View file

@ -125,6 +125,7 @@ impl WindowElement {
.expect("failed to set x11 win to not fullscreen");
}
WindowElement::X11OverrideRedirect(_) => (),
_ => unreachable!(),
}
}
FullscreenOrMaximized::Fullscreen => {
@ -170,7 +171,8 @@ impl WindowElement {
.set_fullscreen(false)
.expect("failed to set x11 win to not fullscreen");
}
Self::X11OverrideRedirect(_) => (),
WindowElement::X11OverrideRedirect(_) => (),
_ => unreachable!(),
}
}
FullscreenOrMaximized::Maximized => {
@ -211,7 +213,8 @@ impl WindowElement {
.set_fullscreen(false)
.expect("failed to set x11 win to not fullscreen");
}
Self::X11OverrideRedirect(_) => (),
WindowElement::X11OverrideRedirect(_) => (),
_ => unreachable!(),
}
}
@ -238,6 +241,7 @@ impl WindowElement {
.expect("failed to set x11 win to not fullscreen");
}
WindowElement::X11OverrideRedirect(_) => (),
_ => unreachable!(),
}
}
}