mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Fix multi-monitor fullscreen rendering and pointer input
This commit is contained in:
parent
f8d1e59c06
commit
31172c5a4e
6 changed files with 73 additions and 70 deletions
|
@ -121,7 +121,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 +159,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 +181,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 +203,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;
|
||||
};
|
||||
|
@ -749,7 +744,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}");
|
||||
}
|
||||
|
|
|
@ -402,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
14
src/input.rs
14
src/input.rs
|
@ -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);
|
||||
|
@ -465,7 +469,7 @@ impl State {
|
|||
|
||||
pointer.motion(
|
||||
self,
|
||||
self.surface_under(pointer_loc),
|
||||
self.focus_target_under(pointer_loc),
|
||||
&MotionEvent {
|
||||
location: pointer_loc,
|
||||
serial,
|
||||
|
@ -499,7 +503,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(
|
||||
|
|
|
@ -157,12 +157,7 @@ where
|
|||
.iter()
|
||||
.rev() // rev because I treat the focus stack backwards vs how the renderer orders it
|
||||
.filter(|win| {
|
||||
let output_tags = output.with_state(|state| state.focused_tags().cloned().collect::<Vec<_>>());
|
||||
let win_tags = win.with_state(|state| state.tags.clone());
|
||||
|
||||
output_tags.into_iter().any(|tag| win_tags.iter().any(|tg| &tag == tg))
|
||||
|
||||
// win.is_on_active_tag(space.outputs())
|
||||
win.is_on_active_tag(space.outputs())
|
||||
})
|
||||
.map(|win| {
|
||||
// subtract win.geometry().loc to align decorations correctly
|
||||
|
@ -176,6 +171,7 @@ where
|
|||
|
||||
(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| {
|
||||
|
@ -187,8 +183,6 @@ where
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
tracing::debug!(elem_count = elements.len());
|
||||
|
||||
elements
|
||||
}
|
||||
|
||||
|
@ -223,15 +217,6 @@ where
|
|||
|
||||
let (windows, override_redirect_windows) = windows
|
||||
.iter()
|
||||
// TODO: copy pasted from tag_render_elements
|
||||
.filter(|win| {
|
||||
let output_tags = output.with_state(|state| state.focused_tags().cloned().collect::<Vec<_>>());
|
||||
let win_tags = win.with_state(|state| state.tags.clone());
|
||||
|
||||
output_tags.into_iter().any(|tag| win_tags.iter().any(|tg| &tag == tg))
|
||||
|
||||
// win.is_on_active_tag(space.outputs())
|
||||
})
|
||||
.cloned()
|
||||
.partition::<Vec<_>, _>(|win| !win.is_x11_override_redirect());
|
||||
|
||||
|
@ -320,22 +305,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
|
||||
|
|
Loading…
Reference in a new issue