From afe8fd64f496872ad6990def9c9c6a5bf96e96ac Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Sat, 19 Oct 2019 20:45:27 +0000 Subject: [PATCH] output: Take transform into account Without handling transform, the surface was created with the wrong size on rotated displays, causing flicker before the .configure event arrived. With, it will attempt to set the right size from the start. --- src/outputs.rs | 133 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 101 insertions(+), 32 deletions(-) diff --git a/src/outputs.rs b/src/outputs.rs index 38326013..9692e954 100644 --- a/src/outputs.rs +++ b/src/outputs.rs @@ -59,6 +59,36 @@ pub mod c { } } + /// Map to `wl_output.transform` values + #[derive(Clone)] + pub enum Transform { + Normal = 0, + Rotated90 = 1, + Rotated180 = 2, + Rotated270 = 3, + Flipped = 4, + FlippedRotated90 = 5, + FlippedRotated180 = 6, + FlippedRotated270 = 7, + } + + impl Transform { + fn from_u32(v: u32) -> Option { + use self::Transform::*; + match v { + 0 => Some(Normal), + 1 => Some(Rotated90), + 2 => Some(Rotated180), + 3 => Some(Rotated270), + 4 => Some(Flipped), + 5 => Some(FlippedRotated90), + 6 => Some(FlippedRotated180), + 7 => Some(FlippedRotated270), + _ => None, + } + } + } + extern "C" { // Rustc wrongly assumes // that COutputs allows C direct access to the underlying RefCell @@ -75,16 +105,32 @@ pub mod c { // Defined in Rust extern fn outputs_handle_geometry( - _outputs: COutputs, - _wl_output: WlOutput, + outputs: COutputs, + wl_output: WlOutput, _x: i32, _y: i32, _phys_width: i32, _phys_height: i32, _subpixel: i32, _make: *const c_char, _model: *const c_char, - _transform: i32, + transform: i32, ) { - //println!("geometry handled {},{}", x, y); - // Totally unused + let transform = Transform::from_u32(transform as u32).unwrap_or_else( + || { + eprintln!( + "Warning: received invalid wl_output.transform value" + ); + Transform::Normal + } + ); + + let outputs = outputs.clone_ref(); + let mut collection = outputs.borrow_mut(); + let output_state: Option<&mut OutputState> + = find_output_mut(&mut collection, wl_output) + .map(|o| &mut o.pending); + match output_state { + Some(state) => { state.transform = Some(transform) }, + None => eprintln!("Wayland error: Got mode on unknown output"), + }; } extern fn outputs_handle_mode( @@ -100,14 +146,12 @@ pub mod c { Mode::NONE }); let outputs = outputs.clone_ref(); - let mut outputs = outputs.borrow_mut(); - let mut output_state: Option<&mut OutputState> = outputs.outputs - .iter_mut() - .find_map(|o| - if o.output == wl_output { Some(&mut o.pending) } else { None } - ); + let mut collection = outputs.borrow_mut(); + let output_state: Option<&mut OutputState> + = find_output_mut(&mut collection, wl_output) + .map(|o| &mut o.pending); match output_state { - Some(ref mut state) => { + Some(state) => { if flags.contains(Mode::CURRENT) { state.current_mode = Some(super::Mode { width, height}); } @@ -121,12 +165,10 @@ pub mod c { wl_output: WlOutput, ) { let outputs = outputs.clone_ref(); - let mut outputs = outputs.borrow_mut(); - let mut output = outputs.outputs - .iter_mut() - .find(|o| o.output == wl_output); + let mut collection = outputs.borrow_mut(); + let output = find_output_mut(&mut collection, wl_output); match output { - Some(ref mut output) => { output.current = output.pending.clone(); } + Some(output) => { output.current = output.pending.clone(); } None => eprintln!("Wayland error: Got done on unknown output"), }; } @@ -137,12 +179,10 @@ pub mod c { factor: i32, ) { let outputs = outputs.clone_ref(); - let mut outputs = outputs.borrow_mut(); - let output_state = outputs.outputs - .iter_mut() - .find_map(|o| - if o.output == wl_output { Some(&mut o.pending) } else { None } - ); + let mut collection = outputs.borrow_mut(); + let output_state: Option<&mut OutputState> + = find_output_mut(&mut collection, wl_output) + .map(|o| &mut o.pending); match output_state { Some(state) => { state.scale = factor; } None => eprintln!("Wayland error: Got done on unknown output"), @@ -201,24 +241,51 @@ pub mod c { let collection = raw_collection.clone_ref(); let collection = collection.borrow(); - let output_state = collection.outputs - .iter() - .find_map(|o| - if o.output == wl_output { Some(&o.current) } else { None } - ); - + let output_state = find_output(&collection, wl_output) + .map(|o| &o.current); match output_state { Some(OutputState { - current_mode: Some(super::Mode { width, height: _ } ), + current_mode: Some(super::Mode { width, height } ), + transform: Some(transform), scale, - }) => width / scale, + }) => { + match transform { + Transform::Normal + | Transform::Rotated180 + | Transform::Flipped + | Transform::FlippedRotated180 => width / scale, + _ => height / scale, + } + }, _ => { - eprintln!("No width registered on output"); + eprintln!("Not enough info registered on output"); 0 }, } } // TODO: handle unregistration + + fn find_output( + collection: &Outputs, + wl_output: WlOutput, + ) -> Option<&Output> { + collection.outputs + .iter() + .find_map(|o| + if o.output == wl_output { Some(o) } else { None } + ) + } + + fn find_output_mut( + collection: &mut Outputs, + wl_output: WlOutput, + ) -> Option<&mut Output> { + collection.outputs + .iter_mut() + .find_map(|o| + if o.output == wl_output { Some(o) } else { None } + ) + } } #[derive(Clone)] @@ -230,6 +297,7 @@ struct Mode { #[derive(Clone)] pub struct OutputState { current_mode: Option, + transform: Option, scale: i32, } @@ -237,6 +305,7 @@ impl OutputState { fn uninitialized() -> OutputState { OutputState { current_mode: None, + transform: None, scale: 1, } }