ui manager: Update state and calculate new size on ouptut change

This commit is contained in:
Dorota Czaplejewicz
2020-03-02 14:15:53 +00:00
parent f6fc6c83dc
commit 7dd2866b17
2 changed files with 79 additions and 29 deletions

View File

@ -22,7 +22,7 @@ pub mod c {
// Defined in C // Defined in C
#[repr(transparent)] #[repr(transparent)]
#[derive(Clone, PartialEq, Copy)] #[derive(Clone, PartialEq, Copy, Hash)]
pub struct WlOutput(*const c_void); pub struct WlOutput(*const c_void);
#[repr(C)] #[repr(C)]
@ -68,7 +68,7 @@ pub mod c {
} }
/// Map to `wl_output.transform` values /// Map to `wl_output.transform` values
#[derive(Clone)] #[derive(Clone, PartialEq)]
pub enum Transform { pub enum Transform {
Normal = 0, Normal = 0,
Rotated90 = 1, Rotated90 = 1,
@ -126,6 +126,10 @@ pub mod c {
let outputs = outputs.borrow(); let outputs = outputs.borrow();
find_output(&outputs, self.wl_output.clone()).map(|o| o.current.clone()) find_output(&outputs, self.wl_output.clone()).map(|o| o.current.clone())
} }
pub fn get_id(&self) -> OutputId {
OutputId { wl_output: self.wl_output }
}
} }
// Defined in Rust // Defined in Rust
@ -330,20 +334,20 @@ pub struct Size {
pub height: u32, pub height: u32,
} }
#[derive(Clone)] #[derive(Clone, PartialEq)]
pub struct SizeMM { pub struct SizeMM {
pub width: i32, pub width: i32,
pub height: i32, pub height: i32,
} }
/// wl_output mode /// wl_output mode
#[derive(Clone)] #[derive(Clone, PartialEq)]
struct Mode { struct Mode {
width: i32, width: i32,
height: i32, height: i32,
} }
#[derive(Clone)] #[derive(Clone, PartialEq)]
pub struct OutputState { pub struct OutputState {
current_mode: Option<Mode>, current_mode: Option<Mode>,
phys_size: Option<SizeMM>, phys_size: Option<SizeMM>,
@ -423,6 +427,14 @@ impl OutputState {
} }
} }
/// A comparable ID of an output
#[derive(Clone, PartialEq, Hash)]
pub struct OutputId {
// WlOutput is a unique pointer, so it will not repeat
// even if there are multiple output managers.
wl_output: c::WlOutput,
}
pub struct Output { pub struct Output {
output: c::WlOutput, output: c::WlOutput,
pending: OutputState, pending: OutputState,

View File

@ -12,9 +12,12 @@ use std::cmp::min;
use std::rc::Rc; use std::rc::Rc;
use ::logging; use ::logging;
use ::outputs::{ Outputs, OutputState}; use ::outputs::{ OutputId, Outputs, OutputState};
use ::outputs::c::OutputHandle; use ::outputs::c::OutputHandle;
// Traits
use ::logging::Warn;
mod c { mod c {
use super::*; use super::*;
use ::outputs::c::COutputs; use ::outputs::c::COutputs;
@ -23,7 +26,7 @@ mod c {
#[no_mangle] #[no_mangle]
pub extern "C" pub extern "C"
fn squeek_uiman_new(outputs: COutputs) -> Wrapped<Manager> { fn squeek_uiman_new(outputs: COutputs) -> Wrapped<Manager> {
let uiman_raw = Wrapped::new(Manager { output: None }); let uiman_raw = Wrapped::new(Manager::new());
if !outputs.is_null() { if !outputs.is_null() {
let uiman = uiman_raw.clone_ref(); let uiman = uiman_raw.clone_ref();
let outputs = outputs.clone_ref(); let outputs = outputs.clone_ref();
@ -42,7 +45,7 @@ mod c {
let uiman = uiman.clone_ref(); let uiman = uiman.clone_ref();
let uiman = uiman.borrow(); let uiman = uiman.borrow();
// TODO: what to do when there's no output? // TODO: what to do when there's no output?
uiman.get_perceptual_height().unwrap_or(0) uiman.state.get_perceptual_height().unwrap_or(0)
} }
#[no_mangle] #[no_mangle]
@ -58,18 +61,14 @@ mod c {
} }
/// Stores current state of all things influencing what the UI should look like. /// Stores current state of all things influencing what the UI should look like.
pub struct Manager { #[derive(Clone, PartialEq)]
/// Shared output handle, current state updated whenever it's needed. pub struct ManagerState {
// TODO: Stop assuming that the output never changes. current_output: Option<(OutputId, OutputState)>,
// (There's no way for the output manager to update the ui manager.)
// FIXME: Turn into an OutputState and apply relevant connections elsewhere.
// Otherwise testability and predictablity is low.
output: Option<OutputHandle>,
//// Pixel size of the surface. Needs explicit updating. //// Pixel size of the surface. Needs explicit updating.
//surface_size: Option<Size>, //surface_size: Option<Size>,
} }
impl Manager { impl ManagerState {
/// The largest ideal heigth for the keyboard as a whole /// The largest ideal heigth for the keyboard as a whole
/// judged by the ease of hitting targets within. /// judged by the ease of hitting targets within.
/// Ideally related to finger size, the crammedness of the layout, /// Ideally related to finger size, the crammedness of the layout,
@ -106,12 +105,11 @@ impl Manager {
} }
fn get_perceptual_height(&self) -> Option<u32> { fn get_perceptual_height(&self) -> Option<u32> {
let output_info = (&self.output).as_ref() let output_info = (&self.current_output).as_ref()
.and_then(|o| o.get_state()) .map(|(_id, os)| (
.map(|os| (
os.scale as u32, os.scale as u32,
os.get_pixel_size(), os.get_pixel_size(),
Manager::get_max_target_height(&os), ManagerState::get_max_target_height(&os),
)); ));
match output_info { match output_info {
Some((scale, Some(px_size), target_height)) => Some({ Some((scale, Some(px_size), target_height)) => Some({
@ -133,20 +131,60 @@ impl Manager {
None => None, None => None,
} }
} }
}
pub struct Manager {
state: ManagerState,
}
impl Manager {
fn new() -> Manager {
Manager {
state: ManagerState { current_output: None },
}
}
fn set_output(&mut self, output: OutputHandle) { fn set_output(&mut self, output: OutputHandle) {
self.output = Some(output); let output_state = output.get_state()
.or_warn(
&mut logging::Print,
logging::Problem::Bug,
// This is really bad. It only happens when the layer surface
// is placed, and it happens once.
// The layer surface is on an output that can't be tracked.
"Tried to set output that's not known to exist. Ignoring.",
);
self.state.current_output = output_state.map(
|state| (output.get_id(), state)
);
// TODO: At the time of writing, this function is only used once,
// before the layer surface is initialized.
// Therefore it doesn't update anything. Maybe it should in the future,
// if it sees more use.
} }
fn handle_output_change(&mut self, output: OutputHandle) { fn handle_output_change(&mut self, output: OutputHandle) {
match output.get_state() { let (id, output_state) = match &self.state.current_output {
Some(os) => { Some((id, state)) => {
println!("{:?}", os.get_pixel_size()); if *id != output.get_id() { return } // Not the current output.
else { (id, state) }
},
None => return, // Keyboard isn't on any output.
};
if let Some(new_output_state) = output.get_state() {
if new_output_state != *output_state {
let new_state = ManagerState {
current_output: Some((id.clone(), new_output_state)),
..self.state.clone()
};
let new_height = new_state.get_perceptual_height();
if new_height != self.state.get_perceptual_height() {
println!("New height: {:?}", new_height);
//update_layer_surface_height(new_height);
// TODO: here hard-size the keyboard and suggestion box too.
}
self.state = new_state;
} }
None => { };
println!("gone");
}
}
} }
} }