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.
This commit is contained in:
133
src/outputs.rs
133
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<Transform> {
|
||||||
|
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" {
|
extern "C" {
|
||||||
// Rustc wrongly assumes
|
// Rustc wrongly assumes
|
||||||
// that COutputs allows C direct access to the underlying RefCell
|
// that COutputs allows C direct access to the underlying RefCell
|
||||||
@ -75,16 +105,32 @@ pub mod c {
|
|||||||
// Defined in Rust
|
// Defined in Rust
|
||||||
|
|
||||||
extern fn outputs_handle_geometry(
|
extern fn outputs_handle_geometry(
|
||||||
_outputs: COutputs,
|
outputs: COutputs,
|
||||||
_wl_output: WlOutput,
|
wl_output: WlOutput,
|
||||||
_x: i32, _y: i32,
|
_x: i32, _y: i32,
|
||||||
_phys_width: i32, _phys_height: i32,
|
_phys_width: i32, _phys_height: i32,
|
||||||
_subpixel: i32,
|
_subpixel: i32,
|
||||||
_make: *const c_char, _model: *const c_char,
|
_make: *const c_char, _model: *const c_char,
|
||||||
_transform: i32,
|
transform: i32,
|
||||||
) {
|
) {
|
||||||
//println!("geometry handled {},{}", x, y);
|
let transform = Transform::from_u32(transform as u32).unwrap_or_else(
|
||||||
// Totally unused
|
|| {
|
||||||
|
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(
|
extern fn outputs_handle_mode(
|
||||||
@ -100,14 +146,12 @@ pub mod c {
|
|||||||
Mode::NONE
|
Mode::NONE
|
||||||
});
|
});
|
||||||
let outputs = outputs.clone_ref();
|
let outputs = outputs.clone_ref();
|
||||||
let mut outputs = outputs.borrow_mut();
|
let mut collection = outputs.borrow_mut();
|
||||||
let mut output_state: Option<&mut OutputState> = outputs.outputs
|
let output_state: Option<&mut OutputState>
|
||||||
.iter_mut()
|
= find_output_mut(&mut collection, wl_output)
|
||||||
.find_map(|o|
|
.map(|o| &mut o.pending);
|
||||||
if o.output == wl_output { Some(&mut o.pending) } else { None }
|
|
||||||
);
|
|
||||||
match output_state {
|
match output_state {
|
||||||
Some(ref mut state) => {
|
Some(state) => {
|
||||||
if flags.contains(Mode::CURRENT) {
|
if flags.contains(Mode::CURRENT) {
|
||||||
state.current_mode = Some(super::Mode { width, height});
|
state.current_mode = Some(super::Mode { width, height});
|
||||||
}
|
}
|
||||||
@ -121,12 +165,10 @@ pub mod c {
|
|||||||
wl_output: WlOutput,
|
wl_output: WlOutput,
|
||||||
) {
|
) {
|
||||||
let outputs = outputs.clone_ref();
|
let outputs = outputs.clone_ref();
|
||||||
let mut outputs = outputs.borrow_mut();
|
let mut collection = outputs.borrow_mut();
|
||||||
let mut output = outputs.outputs
|
let output = find_output_mut(&mut collection, wl_output);
|
||||||
.iter_mut()
|
|
||||||
.find(|o| o.output == wl_output);
|
|
||||||
match 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"),
|
None => eprintln!("Wayland error: Got done on unknown output"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -137,12 +179,10 @@ pub mod c {
|
|||||||
factor: i32,
|
factor: i32,
|
||||||
) {
|
) {
|
||||||
let outputs = outputs.clone_ref();
|
let outputs = outputs.clone_ref();
|
||||||
let mut outputs = outputs.borrow_mut();
|
let mut collection = outputs.borrow_mut();
|
||||||
let output_state = outputs.outputs
|
let output_state: Option<&mut OutputState>
|
||||||
.iter_mut()
|
= find_output_mut(&mut collection, wl_output)
|
||||||
.find_map(|o|
|
.map(|o| &mut o.pending);
|
||||||
if o.output == wl_output { Some(&mut o.pending) } else { None }
|
|
||||||
);
|
|
||||||
match output_state {
|
match output_state {
|
||||||
Some(state) => { state.scale = factor; }
|
Some(state) => { state.scale = factor; }
|
||||||
None => eprintln!("Wayland error: Got done on unknown output"),
|
None => eprintln!("Wayland error: Got done on unknown output"),
|
||||||
@ -201,24 +241,51 @@ pub mod c {
|
|||||||
let collection = raw_collection.clone_ref();
|
let collection = raw_collection.clone_ref();
|
||||||
let collection = collection.borrow();
|
let collection = collection.borrow();
|
||||||
|
|
||||||
let output_state = collection.outputs
|
let output_state = find_output(&collection, wl_output)
|
||||||
.iter()
|
.map(|o| &o.current);
|
||||||
.find_map(|o|
|
|
||||||
if o.output == wl_output { Some(&o.current) } else { None }
|
|
||||||
);
|
|
||||||
|
|
||||||
match output_state {
|
match output_state {
|
||||||
Some(OutputState {
|
Some(OutputState {
|
||||||
current_mode: Some(super::Mode { width, height: _ } ),
|
current_mode: Some(super::Mode { width, height } ),
|
||||||
|
transform: Some(transform),
|
||||||
scale,
|
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
|
0
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: handle unregistration
|
// 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)]
|
#[derive(Clone)]
|
||||||
@ -230,6 +297,7 @@ struct Mode {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct OutputState {
|
pub struct OutputState {
|
||||||
current_mode: Option<Mode>,
|
current_mode: Option<Mode>,
|
||||||
|
transform: Option<c::Transform>,
|
||||||
scale: i32,
|
scale: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +305,7 @@ impl OutputState {
|
|||||||
fn uninitialized() -> OutputState {
|
fn uninitialized() -> OutputState {
|
||||||
OutputState {
|
OutputState {
|
||||||
current_mode: None,
|
current_mode: None,
|
||||||
|
transform: None,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user