visibility: Forward panel height information to window creation

This commit is contained in:
Dorota Czaplejewicz
2022-01-30 16:19:57 +00:00
parent a4b67c65ff
commit 697be64418
5 changed files with 62 additions and 31 deletions

View File

@ -14,6 +14,9 @@ pub const HIDING_TIMEOUT: Duration = Duration::from_millis(200);
/// The outwardly visible state of visibility /// The outwardly visible state of visibility
#[derive(PartialEq, Debug, Clone)] #[derive(PartialEq, Debug, Clone)]
pub enum Outcome { pub enum Outcome {
Visible(OutputId), Visible {
output: OutputId,
height: u32,
},
Hidden, Hidden,
} }

View File

@ -176,7 +176,7 @@ mod test {
let l = State::new(state, now); let l = State::new(state, now);
let (l, commands) = handle_event(l, InputMethod::InactiveSince(now).into(), now); let (l, commands) = handle_event(l, InputMethod::InactiveSince(now).into(), now);
assert_matches!(commands.panel_visibility, Some(PanelCommand::Show(_))); assert_matches!(commands.panel_visibility, Some(PanelCommand::Show{..}));
assert_eq!(l.scheduled_wakeup, Some(now + animation::HIDING_TIMEOUT)); assert_eq!(l.scheduled_wakeup, Some(now + animation::HIDING_TIMEOUT));
now += animation::HIDING_TIMEOUT; now += animation::HIDING_TIMEOUT;

View File

@ -75,7 +75,7 @@ mod c {
extern "C" { extern "C" {
#[allow(improper_ctypes)] #[allow(improper_ctypes)]
fn init_wayland(wayland: *mut Wayland); fn init_wayland(wayland: *mut Wayland);
fn server_context_service_real_show_keyboard(service: *const UIManager, output: WlOutput); fn server_context_service_real_show_keyboard(service: *const UIManager, output: WlOutput, height: u32);
fn server_context_service_real_hide_keyboard(service: *const UIManager); fn server_context_service_real_hide_keyboard(service: *const UIManager);
fn server_context_service_set_hint_purpose(service: *const UIManager, hint: u32, purpose: u32); fn server_context_service_set_hint_purpose(service: *const UIManager, hint: u32, purpose: u32);
// This should probably only get called from the gtk main loop, // This should probably only get called from the gtk main loop,
@ -149,8 +149,8 @@ mod c {
dbus_handler: *const DBusHandler, dbus_handler: *const DBusHandler,
) { ) {
match msg.panel_visibility { match msg.panel_visibility {
Some(PanelCommand::Show(output)) => unsafe { Some(PanelCommand::Show { output, height }) => unsafe {
server_context_service_real_show_keyboard(ui_manager, output.0); server_context_service_real_show_keyboard(ui_manager, output.0, height);
}, },
Some(PanelCommand::Hide) => unsafe { Some(PanelCommand::Hide) => unsafe {
server_context_service_real_hide_keyboard(ui_manager); server_context_service_real_hide_keyboard(ui_manager);
@ -176,7 +176,10 @@ mod c {
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub enum PanelCommand { pub enum PanelCommand {
Show(OutputId), Show {
output: OutputId,
height: u32,
},
Hide, Hide,
} }

View File

@ -141,14 +141,12 @@ on_surface_configure(ServerContextService *self, PhoshLayerSurface *surface)
} }
static void static void
make_window (ServerContextService *self, struct wl_output *output) make_window (ServerContextService *self, struct wl_output *output, uint32_t height)
{ {
if (self->window) { if (self->window) {
g_error("Window already present"); g_error("Window already present");
} }
uint32_t height = squeek_uiman_get_perceptual_height(self->manager);
self->window = g_object_new ( self->window = g_object_new (
PHOSH_TYPE_LAYER_SURFACE, PHOSH_TYPE_LAYER_SURFACE,
"layer-shell", squeek_wayland->layer_shell, "layer-shell", squeek_wayland->layer_shell,
@ -204,10 +202,10 @@ make_widget (ServerContextService *self)
// Called from rust // Called from rust
void void
server_context_service_real_show_keyboard (ServerContextService *self, struct wl_output *output) server_context_service_real_show_keyboard (ServerContextService *self, struct wl_output *output, uint32_t height)
{ {
if (!self->window) { if (!self->window) {
make_window (self, output); make_window (self, output, height);
} }
if (!self->widget) { if (!self->widget) {
make_widget (self); make_widget (self);

View File

@ -10,6 +10,7 @@ use crate::imservice::{ ContentHint, ContentPurpose };
use crate::main::{ Commands, PanelCommand }; use crate::main::{ Commands, PanelCommand };
use crate::outputs; use crate::outputs;
use crate::outputs::{OutputId, OutputState}; use crate::outputs::{OutputId, OutputState};
use std::cmp;
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Instant; use std::time::Instant;
@ -93,12 +94,12 @@ impl Outcome {
pub fn get_commands_to_reach(&self, new_state: &Self) -> Commands { pub fn get_commands_to_reach(&self, new_state: &Self) -> Commands {
let layout_hint_set = match new_state { let layout_hint_set = match new_state {
Outcome { Outcome {
visibility: animation::Outcome::Visible(_), visibility: animation::Outcome::Visible{..},
im: InputMethod::Active(hints), im: InputMethod::Active(hints),
} => Some(hints.clone()), } => Some(hints.clone()),
Outcome { Outcome {
visibility: animation::Outcome::Visible(_), visibility: animation::Outcome::Visible{..},
im: InputMethod::InactiveSince(_), im: InputMethod::InactiveSince(_),
} => Some(InputMethodDetails { } => Some(InputMethodDetails {
hint: ContentHint::NONE, hint: ContentHint::NONE,
@ -112,7 +113,8 @@ impl Outcome {
}; };
// FIXME: handle switching outputs // FIXME: handle switching outputs
let (dbus_visible_set, panel_visibility) = match new_state.visibility { let (dbus_visible_set, panel_visibility) = match new_state.visibility {
animation::Outcome::Visible(output) => (Some(true), Some(PanelCommand::Show(output))), animation::Outcome::Visible{output, height}
=> (Some(true), Some(PanelCommand::Show{output, height})),
animation::Outcome::Hidden => (Some(false), Some(PanelCommand::Hide)), animation::Outcome::Hidden => (Some(false), Some(PanelCommand::Hide)),
}; };
@ -236,23 +238,48 @@ impl Application {
} }
} }
fn get_preferred_height(output: &OutputState) -> Option<u32> {
output.get_pixel_size()
.map(|px_size| {
if px_size.width > px_size.height {
px_size.width / 5
} else {
if (px_size.width < 540) & (px_size.width > 0) {
px_size.width * 7 / 12 // to match 360×210
} else {
// Here we switch to wide layout, less height needed
px_size.width * 7 / 22
}
}
})
}
pub fn get_outcome(&self, now: Instant) -> Outcome { pub fn get_outcome(&self, now: Instant) -> Outcome {
// FIXME: include physical keyboard presence // FIXME: include physical keyboard presence
Outcome { Outcome {
visibility: match self.preferred_output { visibility: match self.preferred_output {
None => animation::Outcome::Hidden, None => animation::Outcome::Hidden,
Some(output) => match (self.physical_keyboard, self.visibility_override) { Some(output) => {
// Hoping that this will get optimized out on branches not using `visible`.
let height = Self::get_preferred_height(self.outputs.get(&output).unwrap())
.unwrap_or(0);
// TODO: Instead of setting size to 0 when the output is invalid,
// simply go invisible.
let visible = animation::Outcome::Visible{output, height};
match (self.physical_keyboard, self.visibility_override) {
(_, visibility::State::ForcedHidden) => animation::Outcome::Hidden, (_, visibility::State::ForcedHidden) => animation::Outcome::Hidden,
(_, visibility::State::ForcedVisible) => animation::Outcome::Visible(output), (_, visibility::State::ForcedVisible) => visible,
(Presence::Present, visibility::State::NotForced) => animation::Outcome::Hidden, (Presence::Present, visibility::State::NotForced) => animation::Outcome::Hidden,
(Presence::Missing, visibility::State::NotForced) => match self.im { (Presence::Missing, visibility::State::NotForced) => match self.im {
InputMethod::Active(_) => animation::Outcome::Visible(output), InputMethod::Active(_) => visible,
InputMethod::InactiveSince(since) => { InputMethod::InactiveSince(since) => {
if now < since + animation::HIDING_TIMEOUT { animation::Outcome::Visible(output) } if now < since + animation::HIDING_TIMEOUT { visible }
else { animation::Outcome::Hidden } else { animation::Outcome::Hidden }
}, },
}, },
}, }
}
}, },
im: self.im.clone(), im: self.im.clone(),
} }
@ -331,7 +358,7 @@ pub mod test {
now += Duration::from_millis(1); now += Duration::from_millis(1);
assert_matches!( assert_matches!(
state.get_outcome(now).visibility, state.get_outcome(now).visibility,
animation::Outcome::Visible(_), animation::Outcome::Visible{..},
"Hidden when it should remain visible: {:?}", "Hidden when it should remain visible: {:?}",
now.saturating_duration_since(start), now.saturating_duration_since(start),
) )
@ -339,7 +366,7 @@ pub mod test {
let state = state.apply_event(Event::InputMethod(InputMethod::Active(imdetails_new())), now); let state = state.apply_event(Event::InputMethod(InputMethod::Active(imdetails_new())), now);
assert_matches!(state.get_outcome(now).visibility, animation::Outcome::Visible(_)); assert_matches!(state.get_outcome(now).visibility, animation::Outcome::Visible{..});
} }
/// Make sure that hiding works when input method goes away /// Make sure that hiding works when input method goes away
@ -356,7 +383,7 @@ pub mod test {
let state = state.apply_event(Event::InputMethod(InputMethod::InactiveSince(now)), now); let state = state.apply_event(Event::InputMethod(InputMethod::InactiveSince(now)), now);
while let animation::Outcome::Visible(_) = state.get_outcome(now).visibility { while let animation::Outcome::Visible{..} = state.get_outcome(now).visibility {
now += Duration::from_millis(1); now += Duration::from_millis(1);
assert!( assert!(
now < start + Duration::from_millis(250), now < start + Duration::from_millis(250),
@ -386,7 +413,7 @@ pub mod test {
let state = state.apply_event(Event::InputMethod(InputMethod::Active(imdetails_new())), now); let state = state.apply_event(Event::InputMethod(InputMethod::Active(imdetails_new())), now);
let state = state.apply_event(Event::InputMethod(InputMethod::InactiveSince(now)), now); let state = state.apply_event(Event::InputMethod(InputMethod::InactiveSince(now)), now);
while let animation::Outcome::Visible(_) = state.get_outcome(now).visibility { while let animation::Outcome::Visible{..} = state.get_outcome(now).visibility {
now += Duration::from_millis(1); now += Duration::from_millis(1);
assert!( assert!(
now < start + Duration::from_millis(250), now < start + Duration::from_millis(250),
@ -422,7 +449,7 @@ pub mod test {
let state = state.apply_event(Event::Visibility(visibility::Event::ForceVisible), now); let state = state.apply_event(Event::Visibility(visibility::Event::ForceVisible), now);
assert_matches!( assert_matches!(
state.get_outcome(now).visibility, state.get_outcome(now).visibility,
animation::Outcome::Visible(_), animation::Outcome::Visible{..},
"Failed to show: {:?}", "Failed to show: {:?}",
now.saturating_duration_since(start), now.saturating_duration_since(start),
); );
@ -478,7 +505,7 @@ pub mod test {
assert_matches!( assert_matches!(
state.get_outcome(now).visibility, state.get_outcome(now).visibility,
animation::Outcome::Visible(_), animation::Outcome::Visible{..},
"Failed to appear: {:?}", "Failed to appear: {:?}",
now.saturating_duration_since(start), now.saturating_duration_since(start),
); );