select: use xdg_output logical_position for per-monitor surface origin
This commit is contained in:
parent
fa28415c7a
commit
0e910d73cc
1 changed files with 56 additions and 4 deletions
|
|
@ -19,6 +19,10 @@ use wayland_protocols::wp::cursor_shape::v1::client::{
|
||||||
wp_cursor_shape_device_v1::{Shape as CursorShape, WpCursorShapeDeviceV1},
|
wp_cursor_shape_device_v1::{Shape as CursorShape, WpCursorShapeDeviceV1},
|
||||||
wp_cursor_shape_manager_v1::WpCursorShapeManagerV1,
|
wp_cursor_shape_manager_v1::WpCursorShapeManagerV1,
|
||||||
};
|
};
|
||||||
|
use wayland_protocols::xdg::xdg_output::zv1::client::{
|
||||||
|
zxdg_output_manager_v1::ZxdgOutputManagerV1,
|
||||||
|
zxdg_output_v1::{self, ZxdgOutputV1},
|
||||||
|
};
|
||||||
use wayland_protocols_wlr::layer_shell::v1::client::{
|
use wayland_protocols_wlr::layer_shell::v1::client::{
|
||||||
zwlr_layer_shell_v1::ZwlrLayerShellV1,
|
zwlr_layer_shell_v1::ZwlrLayerShellV1,
|
||||||
zwlr_layer_surface_v1::{self, ZwlrLayerSurfaceV1},
|
zwlr_layer_surface_v1::{self, ZwlrLayerSurfaceV1},
|
||||||
|
|
@ -67,6 +71,7 @@ pub struct HintBox {
|
||||||
struct PendingOut {
|
struct PendingOut {
|
||||||
wl: wl_output::WlOutput,
|
wl: wl_output::WlOutput,
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
wl_name: u32,
|
||||||
ox: i32,
|
ox: i32,
|
||||||
oy: i32,
|
oy: i32,
|
||||||
scale: i32,
|
scale: i32,
|
||||||
|
|
@ -109,6 +114,8 @@ struct St {
|
||||||
keyboard: Option<wl_keyboard::WlKeyboard>,
|
keyboard: Option<wl_keyboard::WlKeyboard>,
|
||||||
cursor_shape: Option<WpCursorShapeManagerV1>,
|
cursor_shape: Option<WpCursorShapeManagerV1>,
|
||||||
|
|
||||||
|
_xdg_outputs: Vec<ZxdgOutputV1>,
|
||||||
|
|
||||||
pending: Vec<PendingOut>,
|
pending: Vec<PendingOut>,
|
||||||
surfs: Vec<Surf>,
|
surfs: Vec<Surf>,
|
||||||
configured: usize, // count of configure events received
|
configured: usize, // count of configure events received
|
||||||
|
|
@ -750,6 +757,29 @@ impl Dispatch<wl_shm::WlShm, ()> for St {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Dispatch<ZxdgOutputV1, u32> for St {
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
_: &ZxdgOutputV1,
|
||||||
|
event: zxdg_output_v1::Event,
|
||||||
|
wl_name: &u32,
|
||||||
|
_: &Connection,
|
||||||
|
_: &QueueHandle<Self>,
|
||||||
|
) {
|
||||||
|
let Some(p) = state.pending.iter_mut().find(|p| p.wl_name == *wl_name) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
match event {
|
||||||
|
zxdg_output_v1::Event::LogicalPosition { x, y } => {
|
||||||
|
p.ox = x;
|
||||||
|
p.oy = y;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate_noop!(St: ignore ZxdgOutputManagerV1);
|
||||||
delegate_noop!(St: ignore wl_compositor::WlCompositor);
|
delegate_noop!(St: ignore wl_compositor::WlCompositor);
|
||||||
delegate_noop!(St: ignore wl_surface::WlSurface);
|
delegate_noop!(St: ignore wl_surface::WlSurface);
|
||||||
delegate_noop!(St: ignore wl_shm_pool::WlShmPool);
|
delegate_noop!(St: ignore wl_shm_pool::WlShmPool);
|
||||||
|
|
@ -783,19 +813,25 @@ pub fn select_region(
|
||||||
.bind::<wl_seat::WlSeat, _, _>(&qh, 1..=8, ())
|
.bind::<wl_seat::WlSeat, _, _>(&qh, 1..=8, ())
|
||||||
.map_err(|e| BlastError::Selection(format!("seat: {e}")))?;
|
.map_err(|e| BlastError::Selection(format!("seat: {e}")))?;
|
||||||
|
|
||||||
let pending: Vec<PendingOut> = globals
|
let out_globals: Vec<(u32, u32)> = globals // (wl_global_name, version)
|
||||||
.contents()
|
.contents()
|
||||||
.clone_list()
|
.clone_list()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|g| g.interface == "wl_output")
|
.filter(|g| g.interface == "wl_output")
|
||||||
.map(|g| PendingOut {
|
.map(|g| (g.name, g.version))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let pending: Vec<PendingOut> = out_globals
|
||||||
|
.iter()
|
||||||
|
.map(|&(gname, ver)| PendingOut {
|
||||||
wl: globals.registry().bind::<wl_output::WlOutput, _, _>(
|
wl: globals.registry().bind::<wl_output::WlOutput, _, _>(
|
||||||
g.name,
|
gname,
|
||||||
g.version.min(4),
|
ver.min(4),
|
||||||
&qh,
|
&qh,
|
||||||
(),
|
(),
|
||||||
),
|
),
|
||||||
name: None,
|
name: None,
|
||||||
|
wl_name: gname,
|
||||||
ox: 0,
|
ox: 0,
|
||||||
oy: 0,
|
oy: 0,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
|
|
@ -822,6 +858,7 @@ pub fn select_region(
|
||||||
pointer: None,
|
pointer: None,
|
||||||
keyboard: None,
|
keyboard: None,
|
||||||
cursor_shape,
|
cursor_shape,
|
||||||
|
_xdg_outputs: Vec::new(),
|
||||||
pending,
|
pending,
|
||||||
surfs: Vec::new(),
|
surfs: Vec::new(),
|
||||||
configured: 0,
|
configured: 0,
|
||||||
|
|
@ -843,6 +880,21 @@ pub fn select_region(
|
||||||
st.roundtrip()?;
|
st.roundtrip()?;
|
||||||
st.roundtrip()?; // second pass to get pointer/keyboard from capabilities
|
st.roundtrip()?; // second pass to get pointer/keyboard from capabilities
|
||||||
|
|
||||||
|
// Fetch logical positions from xdg_output so that surfaces on non-primary
|
||||||
|
// monitors get the correct (lx, ly) origin. wl_output.geometry is unreliable
|
||||||
|
// on compositors with fractional scaling — they may always report (0, 0) there
|
||||||
|
// and only set the real position via xdg_output.logical_position.
|
||||||
|
if let Ok(xdg_mgr) = globals.bind::<ZxdgOutputManagerV1, _, _>(&st.qh, 2..=3, ()) {
|
||||||
|
let xdg_outputs: Vec<ZxdgOutputV1> = st
|
||||||
|
.pending
|
||||||
|
.iter()
|
||||||
|
.map(|p| xdg_mgr.get_xdg_output(&p.wl, &st.qh, p.wl_name))
|
||||||
|
.collect();
|
||||||
|
st._xdg_outputs = xdg_outputs;
|
||||||
|
st.roundtrip()?; // receive logical_position events, updating p.ox / p.oy
|
||||||
|
drop(xdg_mgr);
|
||||||
|
}
|
||||||
|
|
||||||
st.create_surfaces()?;
|
st.create_surfaces()?;
|
||||||
|
|
||||||
let expected = st.surfs.len();
|
let expected = st.surfs.len();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue