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
#[repr(transparent)]
#[derive(Clone, PartialEq, Copy)]
#[derive(Clone, PartialEq, Copy, Hash)]
pub struct WlOutput(*const c_void);
#[repr(C)]
@ -68,7 +68,7 @@ pub mod c {
}
/// Map to `wl_output.transform` values
#[derive(Clone)]
#[derive(Clone, PartialEq)]
pub enum Transform {
Normal = 0,
Rotated90 = 1,
@ -126,6 +126,10 @@ pub mod c {
let outputs = outputs.borrow();
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
@ -330,20 +334,20 @@ pub struct Size {
pub height: u32,
}
#[derive(Clone)]
#[derive(Clone, PartialEq)]
pub struct SizeMM {
pub width: i32,
pub height: i32,
}
/// wl_output mode
#[derive(Clone)]
#[derive(Clone, PartialEq)]
struct Mode {
width: i32,
height: i32,
}
#[derive(Clone)]
#[derive(Clone, PartialEq)]
pub struct OutputState {
current_mode: Option<Mode>,
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 {
output: c::WlOutput,
pending: OutputState,

View File

@ -12,9 +12,12 @@ use std::cmp::min;
use std::rc::Rc;
use ::logging;
use ::outputs::{ Outputs, OutputState};
use ::outputs::{ OutputId, Outputs, OutputState};
use ::outputs::c::OutputHandle;
// Traits
use ::logging::Warn;
mod c {
use super::*;
use ::outputs::c::COutputs;
@ -23,7 +26,7 @@ mod c {
#[no_mangle]
pub extern "C"
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() {
let uiman = uiman_raw.clone_ref();
let outputs = outputs.clone_ref();
@ -42,7 +45,7 @@ mod c {
let uiman = uiman.clone_ref();
let uiman = uiman.borrow();
// 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]
@ -58,18 +61,14 @@ mod c {
}
/// Stores current state of all things influencing what the UI should look like.
pub struct Manager {
/// Shared output handle, current state updated whenever it's needed.
// TODO: Stop assuming that the output never changes.
// (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>,
#[derive(Clone, PartialEq)]
pub struct ManagerState {
current_output: Option<(OutputId, OutputState)>,
//// Pixel size of the surface. Needs explicit updating.
//surface_size: Option<Size>,
}
impl Manager {
impl ManagerState {
/// The largest ideal heigth for the keyboard as a whole
/// judged by the ease of hitting targets within.
/// Ideally related to finger size, the crammedness of the layout,
@ -106,12 +105,11 @@ impl Manager {
}
fn get_perceptual_height(&self) -> Option<u32> {
let output_info = (&self.output).as_ref()
.and_then(|o| o.get_state())
.map(|os| (
let output_info = (&self.current_output).as_ref()
.map(|(_id, os)| (
os.scale as u32,
os.get_pixel_size(),
Manager::get_max_target_height(&os),
ManagerState::get_max_target_height(&os),
));
match output_info {
Some((scale, Some(px_size), target_height)) => Some({
@ -133,20 +131,60 @@ impl Manager {
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) {
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) {
match output.get_state() {
Some(os) => {
println!("{:?}", os.get_pixel_size());
let (id, output_state) = match &self.state.current_output {
Some((id, state)) => {
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");
}
}
};
}
}