event_loop: Separate and use for physical keyboard presence

Extra included: Change of naked Submission pointers to Wrapped.
This commit is contained in:
Dorota Czaplejewicz
2021-12-03 14:29:02 +00:00
parent 53137fd2e2
commit 4cc7017e1c
19 changed files with 953 additions and 774 deletions

View File

@ -4,17 +4,23 @@
/*! Glue for the main loop. */
use crate::animation::Outcome as Message;
use glib::{Continue, MainContext, PRIORITY_DEFAULT, Receiver, Sender};
use std::thread;
use std::time::Duration;
use crate::state;
use glib::{Continue, MainContext, PRIORITY_DEFAULT, Receiver};
mod c {
use super::*;
use std::os::raw::c_void;
use std::rc::Rc;
use std::time::Instant;
use ::util::c::{ ArcWrapped, Wrapped };
use crate::event_loop::driver;
use crate::imservice::IMService;
use crate::imservice::c::InputMethod;
use crate::state;
use crate::submission::Submission;
use crate::util::c::Wrapped;
use crate::vkeyboard::c::ZwpVirtualKeyboardV1;
/// ServerContextService*
#[repr(transparent)]
@ -24,56 +30,56 @@ mod c {
#[repr(transparent)]
pub struct DBusHandler(*const c_void);
/// Corresponds to main.c::channel
/// Holds the Rust structures that are interesting from C.
#[repr(C)]
pub struct Channel {
sender: ArcWrapped<Sender<Message>>,
receiver: Wrapped<Receiver<Message>>,
pub struct RsObjects {
receiver: Wrapped<Receiver<Commands>>,
state_manager: Wrapped<driver::Threaded>,
submission: Wrapped<Submission>,
}
extern "C" {
pub fn server_context_service_real_show_keyboard(imservice: *const UIManager);
pub fn server_context_service_real_hide_keyboard(imservice: *const UIManager);
fn server_context_service_real_show_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);
// This should probably only get called from the gtk main loop,
// given that dbus handler is using glib.
pub fn dbus_handler_set_visible(dbus: *const DBusHandler, visible: u8);
fn dbus_handler_set_visible(dbus: *const DBusHandler, visible: u8);
}
/// Creates what's possible in Rust to eliminate as many FFI calls as possible,
/// because types aren't getting checked across their boundaries,
/// and that leads to suffering.
#[no_mangle]
pub extern "C"
fn main_loop_channel_new() -> Channel {
fn squeek_rsobjects_new(
im: *mut InputMethod,
vk: ZwpVirtualKeyboardV1,
) -> RsObjects {
let (sender, receiver) = MainContext::channel(PRIORITY_DEFAULT);
let sender = ArcWrapped::new(sender);
let receiver = Wrapped::new(receiver);
let channel = Channel {
sender,
receiver,
let now = Instant::now();
let state_manager = driver::Threaded::new(sender, state::Application::new(now));
let imservice = if im.is_null() {
None
} else {
Some(IMService::new(im, state_manager.clone()))
};
let submission = Submission::new(vk, imservice);
//start_work(channel.sender.clone());
channel
}
/// testing only
fn start_work(sender: ArcWrapped<Sender<Message>>) {
let sender = sender.clone_ref();
thread::spawn(move || {
let sender = sender.lock().unwrap();
thread::sleep(Duration::from_secs(3));
sender.send(Message::Visible).unwrap();
thread::sleep(Duration::from_secs(3));
sender.send(Message::Hidden).unwrap();
thread::sleep(Duration::from_secs(3));
sender.send(Message::Visible).unwrap();
});
RsObjects {
submission: Wrapped::new(submission),
state_manager: Wrapped::new(state_manager),
receiver: Wrapped::new(receiver),
}
}
/// Places the UI loop callback in the glib main loop.
#[no_mangle]
pub extern "C"
fn register_ui_loop_handler(
receiver: Wrapped<Receiver<Message>>,
receiver: Wrapped<Receiver<Commands>>,
ui_manager: *const UIManager,
dbus_handler: *const DBusHandler,
) {
@ -97,23 +103,47 @@ mod c {
/// This is the outest layer of the imperative shell,
/// and doesn't lend itself to testing other than integration.
fn main_loop_handle_message(
msg: Message,
msg: Commands,
ui_manager: *const UIManager,
dbus_handler: *const DBusHandler,
) {
match msg {
Message::Visible => unsafe {
// FIXME: reset layout to default if no IM field is active
// Ideally: anim state stores the current IM hints,
// Message::Visible(hints) is received here
// and applied to layout
match msg.panel_visibility {
Some(PanelCommand::Show) => unsafe {
server_context_service_real_show_keyboard(ui_manager);
dbus_handler_set_visible(dbus_handler, 1);
},
Message::Hidden => unsafe {
Some(PanelCommand::Hide) => unsafe {
server_context_service_real_hide_keyboard(ui_manager);
dbus_handler_set_visible(dbus_handler, 0);
},
None => {},
};
if let Some(visible) = msg.dbus_visible_set {
unsafe { dbus_handler_set_visible(dbus_handler, visible as u8) };
}
if let Some(hints) = msg.layout_hint_set {
unsafe {
server_context_service_set_hint_purpose(
ui_manager,
hints.hint.bits(),
hints.purpose.clone() as u32,
)
};
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub enum PanelCommand {
Show,
Hide,
}
/// The commands consumed by the main loop,
/// to be sent out to external components.
#[derive(Clone)]
pub struct Commands {
pub panel_visibility: Option<PanelCommand>,
pub layout_hint_set: Option<state::InputMethodDetails>,
pub dbus_visible_set: Option<bool>,
}