event_loop: Separate and use for physical keyboard presence
Extra included: Change of naked Submission pointers to Wrapped.
This commit is contained in:
124
src/main.rs
124
src/main.rs
@ -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>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user