Properly handle rotated outputs

Fixes #160
This commit is contained in:
Shawn Wallace 2025-05-27 19:35:10 -04:00
parent 572fa4a2bf
commit 5c0351ff33
2 changed files with 75 additions and 6 deletions

View file

@ -551,6 +551,12 @@ impl HandleEvent for Pointer {
warn!("could not move pointer to surface ({serial}): stale surface");
}
} else {
trace!(
target: "pointer_position",
"pointer motion {} {}",
surface_x * self.scale,
surface_y * self.scale
);
self.server
.motion(time, surface_x * self.scale, surface_y * self.scale);
}
@ -795,6 +801,7 @@ pub struct Output {
pub(super) dimensions: OutputDimensions,
name: String,
scale: i32,
swap_dimensions: bool,
}
impl Output {
@ -820,6 +827,7 @@ impl Output {
},
name: "<unknown>".to_string(),
scale: 1,
swap_dimensions: false,
}
}
@ -993,6 +1001,24 @@ impl Output {
model,
convert_wenum(transform),
);
self.swap_dimensions = transform.into_result().is_ok_and(|t| {
matches!(
t,
client::wl_output::Transform::_90
| client::wl_output::Transform::_270
| client::wl_output::Transform::Flipped90
| client::wl_output::Transform::Flipped270
)
});
if let Some(xdg) = &self.xdg {
if self.swap_dimensions {
xdg.server
.logical_size(self.dimensions.height, self.dimensions.width);
} else {
xdg.server
.logical_size(self.dimensions.width, self.dimensions.height);
}
}
}
Event::Mode {
flags,
@ -1000,11 +1026,9 @@ impl Output {
height,
refresh,
} => {
if matches!(self.dimensions.source, OutputDimensionsSource::Wl { .. }) {
self.dimensions.width = width;
self.dimensions.height = height;
debug!("{} dimensions: {width}x{height} (wl)", self.server.id());
}
self.dimensions.width = width;
self.dimensions.height = height;
debug!("{} dimensions: {width}x{height}", self.server.id());
self.server
.mode(convert_wenum(flags), width, height, refresh);
}
@ -1065,7 +1089,11 @@ impl Output {
);
}
Event::LogicalSize { .. } => {
xdg.logical_size(self.dimensions.width, self.dimensions.height);
if self.swap_dimensions {
xdg.logical_size(self.dimensions.height, self.dimensions.width);
} else {
xdg.logical_size(self.dimensions.width, self.dimensions.height);
}
}
_ => simple_event_shunt! {
xdg, event: zxdg_output_v1::Event => [

View file

@ -14,6 +14,7 @@ use std::time::{Duration, Instant};
use wayland_protocols::xdg::{
decoration::zv1::server::zxdg_toplevel_decoration_v1, shell::server::xdg_toplevel,
};
use wayland_server::protocol::wl_output;
use wayland_server::Resource;
use xcb::{x, Xid};
use xwayland_satellite as xwls;
@ -1892,3 +1893,43 @@ fn xsettings_switch_owner() {
owner
);
}
#[test]
fn rotated_output() {
let mut f = Fixture::new_preset(|testwl| {
testwl.enable_xdg_output_manager();
testwl.new_output(0, 0);
});
let mut connection = Connection::new(&f.display);
connection
.send_and_check_request(&x::ChangeWindowAttributes {
window: connection.root,
value_list: &[x::Cw::EventMask(x::EventMask::STRUCTURE_NOTIFY)],
})
.unwrap();
let output = f.testwl.get_output("WL-1").unwrap();
output.mode(wl_output::Mode::Current, 100, 1000, 60);
output.geometry(
0,
0,
50,
50,
wl_output::Subpixel::Unknown,
"satellite".to_string(),
"WL-1".to_string(),
wl_output::Transform::_90,
);
output.done();
f.testwl.dispatch();
match connection.await_event() {
xcb::Event::X(x::Event::ConfigureNotify(e)) => {
assert_eq!(e.window(), connection.root);
assert_eq!(e.width(), 1000);
assert_eq!(e.height(), 100);
}
other => panic!("unexpected event {other:?}"),
}
}