Merge branch 'handling' into 'master'
Centralize handling release events See merge request Librem5/squeekboard!289
This commit is contained in:
		@ -6,8 +6,8 @@ use std::ffi::CString;
 | 
				
			|||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
pub struct KeySym(pub String);
 | 
					pub struct KeySym(pub String);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Use to switch layouts
 | 
					/// Use to switch views
 | 
				
			||||||
type Level = String;
 | 
					type View = String;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Use to send modified keypresses
 | 
					/// Use to send modified keypresses
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
@ -20,12 +20,12 @@ pub enum Modifier {
 | 
				
			|||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
pub enum Action {
 | 
					pub enum Action {
 | 
				
			||||||
    /// Switch to this view
 | 
					    /// Switch to this view
 | 
				
			||||||
    SetLevel(Level),
 | 
					    SetView(View),
 | 
				
			||||||
    /// Switch to a view and latch
 | 
					    /// Switch to a view and latch
 | 
				
			||||||
    LockLevel {
 | 
					    LockView {
 | 
				
			||||||
        lock: Level,
 | 
					        lock: View,
 | 
				
			||||||
        /// When unlocked by pressing it or emitting a key
 | 
					        /// When unlocked by pressing it or emitting a key
 | 
				
			||||||
        unlock: Level,
 | 
					        unlock: View,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /// Set this modifier TODO: release?
 | 
					    /// Set this modifier TODO: release?
 | 
				
			||||||
    SetModifier(Modifier),
 | 
					    SetModifier(Modifier),
 | 
				
			||||||
 | 
				
			|||||||
@ -522,7 +522,7 @@ fn create_action<H: WarningHandler>(
 | 
				
			|||||||
    match submission {
 | 
					    match submission {
 | 
				
			||||||
        SubmitData::Action(
 | 
					        SubmitData::Action(
 | 
				
			||||||
            Action::SetView(view_name)
 | 
					            Action::SetView(view_name)
 | 
				
			||||||
        ) => ::action::Action::SetLevel(
 | 
					        ) => ::action::Action::SetView(
 | 
				
			||||||
            filter_view_name(
 | 
					            filter_view_name(
 | 
				
			||||||
                name, view_name.clone(), &view_names,
 | 
					                name, view_name.clone(), &view_names,
 | 
				
			||||||
                warning_handler,
 | 
					                warning_handler,
 | 
				
			||||||
@ -530,7 +530,7 @@ fn create_action<H: WarningHandler>(
 | 
				
			|||||||
        ),
 | 
					        ),
 | 
				
			||||||
        SubmitData::Action(Action::Locking {
 | 
					        SubmitData::Action(Action::Locking {
 | 
				
			||||||
            lock_view, unlock_view
 | 
					            lock_view, unlock_view
 | 
				
			||||||
        }) => ::action::Action::LockLevel {
 | 
					        }) => ::action::Action::LockView {
 | 
				
			||||||
            lock: filter_view_name(
 | 
					            lock: filter_view_name(
 | 
				
			||||||
                name,
 | 
					                name,
 | 
				
			||||||
                lock_view.clone(),
 | 
					                lock_view.clone(),
 | 
				
			||||||
 | 
				
			|||||||
@ -17,16 +17,39 @@ pub enum PressType {
 | 
				
			|||||||
    Pressed = 1,
 | 
					    Pressed = 1,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type KeyCode = u32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub struct KeyState {
 | 
					pub struct KeyState {
 | 
				
			||||||
    pub pressed: PressType,
 | 
					    pub pressed: PressType,
 | 
				
			||||||
    pub locked: bool,
 | 
					    pub locked: bool,
 | 
				
			||||||
    /// A cache of raw keycodes derived from Action::Sumbit given a keymap
 | 
					    /// A cache of raw keycodes derived from Action::Sumbit given a keymap
 | 
				
			||||||
    pub keycodes: Vec<u32>,
 | 
					    pub keycodes: Vec<KeyCode>,
 | 
				
			||||||
    /// Static description of what the key does when pressed or released
 | 
					    /// Static description of what the key does when pressed or released
 | 
				
			||||||
    pub action: Action,
 | 
					    pub action: Action,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl KeyState {
 | 
				
			||||||
 | 
					    #[must_use]
 | 
				
			||||||
 | 
					    pub fn into_activated(self) -> KeyState {
 | 
				
			||||||
 | 
					        match self.action {
 | 
				
			||||||
 | 
					            Action::LockView { lock: _, unlock: _ } => KeyState {
 | 
				
			||||||
 | 
					                locked: self.locked ^ true,
 | 
				
			||||||
 | 
					                ..self
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            _ => self,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[must_use]
 | 
				
			||||||
 | 
					    pub fn into_released(self) -> KeyState {
 | 
				
			||||||
 | 
					        KeyState {
 | 
				
			||||||
 | 
					            pressed: PressType::Released,
 | 
				
			||||||
 | 
					            ..self
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Sorts an iterator by converting it to a Vector and back
 | 
					/// Sorts an iterator by converting it to a Vector and back
 | 
				
			||||||
fn sorted<'a, I: Iterator<Item=&'a str>>(
 | 
					fn sorted<'a, I: Iterator<Item=&'a str>>(
 | 
				
			||||||
    iter: I
 | 
					    iter: I
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										264
									
								
								src/layout.rs
									
									
									
									
									
								
							
							
						
						
									
										264
									
								
								src/layout.rs
									
									
									
									
									
								
							@ -265,6 +265,11 @@ pub mod c {
 | 
				
			|||||||
            let time = Timestamp(time);
 | 
					            let time = Timestamp(time);
 | 
				
			||||||
            let layout = unsafe { &mut *layout };
 | 
					            let layout = unsafe { &mut *layout };
 | 
				
			||||||
            let virtual_keyboard = VirtualKeyboard(virtual_keyboard);
 | 
					            let virtual_keyboard = VirtualKeyboard(virtual_keyboard);
 | 
				
			||||||
 | 
					            let ui_backend = UIBackend {
 | 
				
			||||||
 | 
					                widget_to_layout,
 | 
				
			||||||
 | 
					                keyboard: ui_keyboard,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // The list must be copied,
 | 
					            // The list must be copied,
 | 
				
			||||||
            // because it will be mutated in the loop
 | 
					            // because it will be mutated in the loop
 | 
				
			||||||
            for key in layout.pressed_keys.clone() {
 | 
					            for key in layout.pressed_keys.clone() {
 | 
				
			||||||
@ -272,17 +277,16 @@ pub mod c {
 | 
				
			|||||||
                seat::handle_release_key(
 | 
					                seat::handle_release_key(
 | 
				
			||||||
                    layout,
 | 
					                    layout,
 | 
				
			||||||
                    &virtual_keyboard,
 | 
					                    &virtual_keyboard,
 | 
				
			||||||
                    &widget_to_layout,
 | 
					                    Some(&ui_backend),
 | 
				
			||||||
                    time,
 | 
					                    time,
 | 
				
			||||||
                    ui_keyboard,
 | 
					                    Some(manager),
 | 
				
			||||||
                    manager,
 | 
					 | 
				
			||||||
                    key,
 | 
					                    key,
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            drawing::queue_redraw(ui_keyboard);
 | 
					            drawing::queue_redraw(ui_keyboard);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// Release all buittons but don't redraw
 | 
					        /// Release all buttons but don't redraw
 | 
				
			||||||
        #[no_mangle]
 | 
					        #[no_mangle]
 | 
				
			||||||
        pub extern "C"
 | 
					        pub extern "C"
 | 
				
			||||||
        fn squeek_layout_release_all_only(
 | 
					        fn squeek_layout_release_all_only(
 | 
				
			||||||
@ -296,10 +300,13 @@ pub mod c {
 | 
				
			|||||||
            // because it will be mutated in the loop
 | 
					            // because it will be mutated in the loop
 | 
				
			||||||
            for key in layout.pressed_keys.clone() {
 | 
					            for key in layout.pressed_keys.clone() {
 | 
				
			||||||
                let key: &Rc<RefCell<KeyState>> = key.borrow();
 | 
					                let key: &Rc<RefCell<KeyState>> = key.borrow();
 | 
				
			||||||
                layout.release_key(
 | 
					                seat::handle_release_key(
 | 
				
			||||||
 | 
					                    layout,
 | 
				
			||||||
                    &virtual_keyboard,
 | 
					                    &virtual_keyboard,
 | 
				
			||||||
 | 
					                    None, // don't update UI
 | 
				
			||||||
 | 
					                    Timestamp(time),
 | 
				
			||||||
 | 
					                    None, // don't switch layouts
 | 
				
			||||||
                    &mut key.clone(),
 | 
					                    &mut key.clone(),
 | 
				
			||||||
                    Timestamp(time)
 | 
					 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -353,8 +360,11 @@ pub mod c {
 | 
				
			|||||||
            let time = Timestamp(time);
 | 
					            let time = Timestamp(time);
 | 
				
			||||||
            let layout = unsafe { &mut *layout };
 | 
					            let layout = unsafe { &mut *layout };
 | 
				
			||||||
            let virtual_keyboard = VirtualKeyboard(virtual_keyboard);
 | 
					            let virtual_keyboard = VirtualKeyboard(virtual_keyboard);
 | 
				
			||||||
 | 
					            let ui_backend = UIBackend {
 | 
				
			||||||
            let point = widget_to_layout.forward(
 | 
					                widget_to_layout,
 | 
				
			||||||
 | 
					                keyboard: ui_keyboard,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            let point = ui_backend.widget_to_layout.forward(
 | 
				
			||||||
                Point { x: x_widget, y: y_widget }
 | 
					                Point { x: x_widget, y: y_widget }
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
@ -379,10 +389,9 @@ pub mod c {
 | 
				
			|||||||
                        seat::handle_release_key(
 | 
					                        seat::handle_release_key(
 | 
				
			||||||
                            layout,
 | 
					                            layout,
 | 
				
			||||||
                            &virtual_keyboard,
 | 
					                            &virtual_keyboard,
 | 
				
			||||||
                            &widget_to_layout,
 | 
					                            Some(&ui_backend),
 | 
				
			||||||
                            time,
 | 
					                            time,
 | 
				
			||||||
                            ui_keyboard,
 | 
					                            Some(manager),
 | 
				
			||||||
                            manager,
 | 
					 | 
				
			||||||
                            key,
 | 
					                            key,
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -397,10 +406,9 @@ pub mod c {
 | 
				
			|||||||
                    seat::handle_release_key(
 | 
					                    seat::handle_release_key(
 | 
				
			||||||
                        layout,
 | 
					                        layout,
 | 
				
			||||||
                        &virtual_keyboard,
 | 
					                        &virtual_keyboard,
 | 
				
			||||||
                        &widget_to_layout,
 | 
					                        Some(&ui_backend),
 | 
				
			||||||
                        time,
 | 
					                        time,
 | 
				
			||||||
                        ui_keyboard,
 | 
					                        Some(manager),
 | 
				
			||||||
                        manager,
 | 
					 | 
				
			||||||
                        key,
 | 
					                        key,
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -612,6 +620,7 @@ pub struct LayoutData {
 | 
				
			|||||||
    pub margins: Margins,
 | 
					    pub margins: Margins,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
struct NoSuchView;
 | 
					struct NoSuchView;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Unfortunately, changes are not atomic due to mutability :(
 | 
					// Unfortunately, changes are not atomic due to mutability :(
 | 
				
			||||||
@ -644,84 +653,22 @@ impl Layout {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn release_key(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        virtual_keyboard: &VirtualKeyboard,
 | 
					 | 
				
			||||||
        mut key: &mut Rc<RefCell<KeyState>>,
 | 
					 | 
				
			||||||
        time: Timestamp,
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        if !self.pressed_keys.remove(&::util::Pointer(key.clone())) {
 | 
					 | 
				
			||||||
            eprintln!("Warning: key {:?} was not pressed", key);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        virtual_keyboard.switch(
 | 
					 | 
				
			||||||
            &mut key.borrow_mut(),
 | 
					 | 
				
			||||||
            PressType::Released,
 | 
					 | 
				
			||||||
            time,
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        self.set_level_from_press(&mut key);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    fn press_key(
 | 
					    fn press_key(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        virtual_keyboard: &VirtualKeyboard,
 | 
					        virtual_keyboard: &VirtualKeyboard,
 | 
				
			||||||
        key: &mut Rc<RefCell<KeyState>>,
 | 
					        rckey: &mut Rc<RefCell<KeyState>>,
 | 
				
			||||||
        time: Timestamp,
 | 
					        time: Timestamp,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        if !self.pressed_keys.insert(::util::Pointer(key.clone())) {
 | 
					        if !self.pressed_keys.insert(::util::Pointer(rckey.clone())) {
 | 
				
			||||||
            eprintln!("Warning: key {:?} was already pressed", key);
 | 
					            eprintln!("Warning: key {:?} was already pressed", rckey);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        let mut key = rckey.borrow_mut();
 | 
				
			||||||
        virtual_keyboard.switch(
 | 
					        virtual_keyboard.switch(
 | 
				
			||||||
            &mut key.borrow_mut(),
 | 
					            &key.keycodes,
 | 
				
			||||||
            PressType::Pressed,
 | 
					            PressType::Pressed,
 | 
				
			||||||
            time,
 | 
					            time,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					        key.pressed = PressType::Pressed;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn set_level_from_press(&mut self, key: &Rc<RefCell<KeyState>>) {
 | 
					 | 
				
			||||||
        let keys = self.locked_keys.clone();
 | 
					 | 
				
			||||||
        for key in &keys {
 | 
					 | 
				
			||||||
            self.locked_keys.remove(key);
 | 
					 | 
				
			||||||
            self.set_state_from_press(key.borrow());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Don't handle the same key twice, but handle it at least once,
 | 
					 | 
				
			||||||
        // because its press is the reason we're here
 | 
					 | 
				
			||||||
        if !keys.contains(&::util::Pointer(key.clone())) {
 | 
					 | 
				
			||||||
            self.set_state_from_press(key);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn set_state_from_press(&mut self, key: &Rc<RefCell<KeyState>>) {
 | 
					 | 
				
			||||||
        // Action should not hold a reference to key,
 | 
					 | 
				
			||||||
        // because key is later borrowed for mutation. So action is cloned.
 | 
					 | 
				
			||||||
        // RefCell::borrow() is covered up by (dyn Borrow)::borrow()
 | 
					 | 
				
			||||||
        // if used like key.borrow() :(
 | 
					 | 
				
			||||||
        let action = RefCell::borrow(key).action.clone();
 | 
					 | 
				
			||||||
        let view_name = match action {
 | 
					 | 
				
			||||||
            Action::SetLevel(name) => {
 | 
					 | 
				
			||||||
                Some(name.clone())
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            Action::LockLevel { lock, unlock } => {
 | 
					 | 
				
			||||||
                let locked = {
 | 
					 | 
				
			||||||
                    let mut key = key.borrow_mut();
 | 
					 | 
				
			||||||
                    key.locked ^= true;
 | 
					 | 
				
			||||||
                    key.locked
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if locked {
 | 
					 | 
				
			||||||
                    self.locked_keys.insert(::util::Pointer(key.clone()));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                Some(if locked { lock } else { unlock }.clone())
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            _ => None,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if let Some(view_name) = view_name {
 | 
					 | 
				
			||||||
            if let Err(_e) = self.set_view(view_name.clone()) {
 | 
					 | 
				
			||||||
                eprintln!("No such view: {}, ignoring switch", view_name)
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Calculates size without margins
 | 
					    /// Calculates size without margins
 | 
				
			||||||
@ -848,44 +795,161 @@ mod procedures {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct UIBackend {
 | 
				
			||||||
 | 
					    widget_to_layout: c::Transformation,
 | 
				
			||||||
 | 
					    keyboard: c::EekGtkKeyboard,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Top level procedures, dispatching to everything
 | 
					/// Top level procedures, dispatching to everything
 | 
				
			||||||
mod seat {
 | 
					mod seat {
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: turn into release_button
 | 
					    fn try_set_view(layout: &mut Layout, view_name: String) {
 | 
				
			||||||
 | 
					        layout.set_view(view_name.clone())
 | 
				
			||||||
 | 
					            .map_err(|e|
 | 
				
			||||||
 | 
					                eprintln!("Bad view {} ({:?}), ignoring", view_name, e)
 | 
				
			||||||
 | 
					            ).ok();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// A vessel holding an obligation to switch view.
 | 
				
			||||||
 | 
					    /// Use with #[must_use]
 | 
				
			||||||
 | 
					    struct ViewChange<'a> {
 | 
				
			||||||
 | 
					        layout: &'a mut Layout,
 | 
				
			||||||
 | 
					        view_name: Option<String>,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    impl<'a> ViewChange<'a> {
 | 
				
			||||||
 | 
					        fn choose_view(self, view_name: String) -> ViewChange<'a> {
 | 
				
			||||||
 | 
					            ViewChange {
 | 
				
			||||||
 | 
					                view_name: Some(view_name),
 | 
				
			||||||
 | 
					                ..self
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        fn apply(self) {
 | 
				
			||||||
 | 
					            if let Some(name) = self.view_name {
 | 
				
			||||||
 | 
					                try_set_view(self.layout, name);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Find all impermanent view changes and undo them in an arbitrary order.
 | 
				
			||||||
 | 
					    /// Return an obligation to actually switch the view.
 | 
				
			||||||
 | 
					    /// The final view is the "unlock" view
 | 
				
			||||||
 | 
					    /// from one of the currently stuck keys.
 | 
				
			||||||
 | 
					    // As long as only one stuck button is used, this should be fine.
 | 
				
			||||||
 | 
					    // This is guaranteed because pressing a lock button unlocks all others.
 | 
				
			||||||
 | 
					    // TODO: Make some broader guarantee about the resulting view,
 | 
				
			||||||
 | 
					    // e.g. by maintaining a stack of stuck keys.
 | 
				
			||||||
 | 
					    #[must_use]
 | 
				
			||||||
 | 
					    fn unstick_locks(layout: &mut Layout) -> ViewChange {
 | 
				
			||||||
 | 
					        let mut new_view = None;
 | 
				
			||||||
 | 
					        for key in layout.locked_keys.clone() {
 | 
				
			||||||
 | 
					            let key: &Rc<RefCell<KeyState>> = key.borrow();
 | 
				
			||||||
 | 
					            let mut key = RefCell::borrow_mut(key);
 | 
				
			||||||
 | 
					            match &key.action {
 | 
				
			||||||
 | 
					                Action::LockView { lock: _, unlock: view } => {
 | 
				
			||||||
 | 
					                    new_view = Some(view.clone());
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                a => eprintln!(
 | 
				
			||||||
 | 
					                    "BUG: action {:?} was found inside locked keys",
 | 
				
			||||||
 | 
					                    a
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            key.locked = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        ViewChange {
 | 
				
			||||||
 | 
					            layout,
 | 
				
			||||||
 | 
					            view_name: new_view,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn handle_release_key(
 | 
					    pub fn handle_release_key(
 | 
				
			||||||
        layout: &mut Layout,
 | 
					        layout: &mut Layout,
 | 
				
			||||||
        virtual_keyboard: &VirtualKeyboard,
 | 
					        virtual_keyboard: &VirtualKeyboard,
 | 
				
			||||||
        widget_to_layout: &c::Transformation,
 | 
					        ui: Option<&UIBackend>,
 | 
				
			||||||
        time: Timestamp,
 | 
					        time: Timestamp,
 | 
				
			||||||
        ui_keyboard: c::EekGtkKeyboard,
 | 
					        manager: Option<manager::c::Manager>,
 | 
				
			||||||
        manager: manager::c::Manager,
 | 
					        rckey: &Rc<RefCell<KeyState>>,
 | 
				
			||||||
        key: &Rc<RefCell<KeyState>>,
 | 
					 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        layout.release_key(virtual_keyboard, &mut key.clone(), time);
 | 
					        let key: KeyState = {
 | 
				
			||||||
 | 
					            RefCell::borrow(rckey).clone()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        let action = key.action.clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let view = layout.get_current_view();
 | 
					        // update
 | 
				
			||||||
        let action = RefCell::borrow(key).action.clone();
 | 
					        let key = key.into_released();
 | 
				
			||||||
        if let Action::ShowPreferences = action {
 | 
					        let key = match action {
 | 
				
			||||||
            let places = ::layout::procedures::find_key_places(
 | 
					            Action::LockView { lock: _, unlock: _ } => key.into_activated(),
 | 
				
			||||||
                view, key
 | 
					            _ => key,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // process changes
 | 
				
			||||||
 | 
					        match action {
 | 
				
			||||||
 | 
					            Action::Submit { text: _, keys: _ } => {
 | 
				
			||||||
 | 
					                unstick_locks(layout).apply();
 | 
				
			||||||
 | 
					                virtual_keyboard.switch(
 | 
				
			||||||
 | 
					                    &key.keycodes,
 | 
				
			||||||
 | 
					                    PressType::Released,
 | 
				
			||||||
 | 
					                    time,
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            // getting first item will cause mispositioning
 | 
					            },
 | 
				
			||||||
 | 
					            Action::SetView(view) => {
 | 
				
			||||||
 | 
					                try_set_view(layout, view)
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            Action::LockView { lock, unlock } => {
 | 
				
			||||||
 | 
					                // The button that triggered this will be in the right state
 | 
				
			||||||
 | 
					                // due to commit at the end.
 | 
				
			||||||
 | 
					                unstick_locks(layout)
 | 
				
			||||||
 | 
					                    // It doesn't matter what the resulting view should be,
 | 
				
			||||||
 | 
					                    // it's getting changed anyway.
 | 
				
			||||||
 | 
					                    .choose_view(
 | 
				
			||||||
 | 
					                        match key.locked {
 | 
				
			||||||
 | 
					                            true => lock.clone(),
 | 
				
			||||||
 | 
					                            false => unlock.clone(),
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .apply()
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            // only show when UI is present
 | 
				
			||||||
 | 
					            Action::ShowPreferences => if let Some(ui) = &ui {
 | 
				
			||||||
 | 
					                // only show when layout manager is available
 | 
				
			||||||
 | 
					                if let Some(manager) = manager {
 | 
				
			||||||
 | 
					                    let view = layout.get_current_view();
 | 
				
			||||||
 | 
					                    let places = ::layout::procedures::find_key_places(
 | 
				
			||||||
 | 
					                        view, &rckey,
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                    // Getting first item will cause mispositioning
 | 
				
			||||||
                    // with more than one button with the same key
 | 
					                    // with more than one button with the same key
 | 
				
			||||||
            // on the keyboard
 | 
					                    // on the keyboard.
 | 
				
			||||||
            if let Some((offset, button)) = places.get(0) {
 | 
					                    if let Some((position, button)) = places.get(0) {
 | 
				
			||||||
                        let bounds = c::Bounds {
 | 
					                        let bounds = c::Bounds {
 | 
				
			||||||
                    x: offset.x, y: offset.y,
 | 
					                            x: position.x,
 | 
				
			||||||
 | 
					                            y: position.y,
 | 
				
			||||||
                            width: button.size.width,
 | 
					                            width: button.size.width,
 | 
				
			||||||
                            height: button.size.height,
 | 
					                            height: button.size.height,
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
                        ::popover::show(
 | 
					                        ::popover::show(
 | 
				
			||||||
                    ui_keyboard,
 | 
					                            ui.keyboard,
 | 
				
			||||||
                    widget_to_layout.reverse_bounds(bounds),
 | 
					                            ui.widget_to_layout.reverse_bounds(bounds),
 | 
				
			||||||
                            manager,
 | 
					                            manager,
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            Action::SetModifier(_) => eprintln!("Modifiers unsupported"),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let pointer = ::util::Pointer(rckey.clone());
 | 
				
			||||||
 | 
					        // Apply state changes
 | 
				
			||||||
 | 
					        layout.pressed_keys.remove(&pointer);
 | 
				
			||||||
 | 
					        if key.locked {
 | 
				
			||||||
 | 
					            layout.locked_keys.insert(pointer);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            layout.locked_keys.remove(&pointer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // Commit activated button state changes
 | 
				
			||||||
 | 
					        RefCell::replace(rckey, key);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -900,7 +964,7 @@ mod test {
 | 
				
			|||||||
            pressed: PressType::Released,
 | 
					            pressed: PressType::Released,
 | 
				
			||||||
            locked: false,
 | 
					            locked: false,
 | 
				
			||||||
            keycodes: Vec::new(),
 | 
					            keycodes: Vec::new(),
 | 
				
			||||||
            action: Action::SetLevel("default".into()),
 | 
					            action: Action::SetView("default".into()),
 | 
				
			||||||
        }))
 | 
					        }))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
/*! Managing the events belonging to virtual-keyboard interface. */
 | 
					/*! Managing the events belonging to virtual-keyboard interface. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use ::keyboard::{ KeyState, PressType };
 | 
					use ::keyboard::{ KeyCode, PressType };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Gathers stuff defined in C or called by C
 | 
					/// Gathers stuff defined in C or called by C
 | 
				
			||||||
pub mod c {
 | 
					pub mod c {
 | 
				
			||||||
@ -33,16 +33,14 @@ impl VirtualKeyboard {
 | 
				
			|||||||
    // TODO: split out keyboard state management
 | 
					    // TODO: split out keyboard state management
 | 
				
			||||||
    pub fn switch(
 | 
					    pub fn switch(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        key: &mut KeyState,
 | 
					        keycodes: &Vec<KeyCode>,
 | 
				
			||||||
        action: PressType,
 | 
					        action: PressType,
 | 
				
			||||||
        timestamp: Timestamp,
 | 
					        timestamp: Timestamp,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        key.pressed = action.clone();
 | 
					        let keycodes_count = keycodes.len();
 | 
				
			||||||
 | 
					        for keycode in keycodes.iter() {
 | 
				
			||||||
        let keycodes_count = key.keycodes.len();
 | 
					 | 
				
			||||||
        for keycode in key.keycodes.iter() {
 | 
					 | 
				
			||||||
            let keycode = keycode - 8;
 | 
					            let keycode = keycode - 8;
 | 
				
			||||||
            match (&key.pressed, keycodes_count) {
 | 
					            match (action, keycodes_count) {
 | 
				
			||||||
                // Pressing a key made out of a single keycode is simple:
 | 
					                // Pressing a key made out of a single keycode is simple:
 | 
				
			||||||
                // press on press, release on release.
 | 
					                // press on press, release on release.
 | 
				
			||||||
                (_, 1) => unsafe {
 | 
					                (_, 1) => unsafe {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user