ui manager: Update state and calculate new size on ouptut change
This commit is contained in:
@ -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,
|
||||||
|
|||||||
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user