Merge branch 'saver' into 'master'
popover: Deactivate settings button when lock screen is on See merge request World/Phosh/squeekboard!582
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
# Dependencies which change based on build flags
|
||||
# Dependencies and tools which change based on build flags
|
||||
# For the newer-than-Byzantium config
|
||||
|
||||
bitflags = "1.3.*"
|
||||
clap = { version = "3.2.*", features=["std"], default-features = false }
|
||||
zbus = "1.9.*"
|
||||
|
||||
@ -23,6 +23,7 @@ path = "@path@/examples/find_orphan_layouts.rs"
|
||||
|
||||
[features]
|
||||
glib_v0_14 = []
|
||||
zbus_v1_5 = []
|
||||
|
||||
# Dependencies which don't change based on build flags
|
||||
[dependencies]
|
||||
|
||||
@ -99,7 +99,7 @@ cargo_toml_base = configure_file(
|
||||
cargo_patch = []
|
||||
|
||||
if get_option('newer') == true
|
||||
cargo_build_flags += ['--features', 'glib_v0_14']
|
||||
cargo_build_flags += ['--features', 'glib_v0_14,zbus_v1_5']
|
||||
cargo_deps = files('Cargo.deps.newer')
|
||||
cargo_lock = files('Cargo.lock.newer')
|
||||
else
|
||||
|
||||
9
src/debug.rs → src/actors/external/debug.rs
vendored
9
src/debug.rs → src/actors/external/debug.rs
vendored
@ -3,12 +3,13 @@
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
use std::thread;
|
||||
use zbus::{Connection, ObjectServer, dbus_interface, fdo};
|
||||
|
||||
use crate::main;
|
||||
use crate::state;
|
||||
|
||||
use std::thread;
|
||||
use zbus::{Connection, ObjectServer, dbus_interface, fdo};
|
||||
|
||||
use super::Void;
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
@ -37,7 +38,7 @@ impl Manager {
|
||||
}
|
||||
}
|
||||
|
||||
fn start(mgr: Manager) -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn start(mgr: Manager) -> Result<Void, Box<dyn std::error::Error>> {
|
||||
let connection = Connection::new_session()?;
|
||||
fdo::DBusProxy::new(&connection)?.request_name(
|
||||
"sm.puri.SqueekDebug",
|
||||
14
src/actors/external/mod.rs
vendored
Normal file
14
src/actors/external/mod.rs
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Purism SPC
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/*! Contains actors with custom event loops, not based off of the event_loop module. */
|
||||
|
||||
pub mod debug;
|
||||
#[cfg(feature = "zbus_v1_5")]
|
||||
pub mod screensaver;
|
||||
|
||||
/// The uninhabited type. Cannot be created or returned; means "will never return" as return type. Useful for infinite loops.
|
||||
enum Void {}
|
||||
57
src/actors/external/screensaver.rs
vendored
Normal file
57
src/actors/external/screensaver.rs
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Purism SPC
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
use crate::actors::Destination;
|
||||
use crate::actors::popover;
|
||||
use crate::logging;
|
||||
use std::thread;
|
||||
use zbus::{Connection, dbus_proxy};
|
||||
|
||||
use super::Void;
|
||||
|
||||
|
||||
#[dbus_proxy(
|
||||
interface = "org.freedesktop.ScreenSaver",
|
||||
default_service = "org.freedesktop.ScreenSaver",
|
||||
default_path = "/org/freedesktop/ScreenSaver"
|
||||
)]
|
||||
pub trait Manager {
|
||||
#[dbus_proxy(signal)]
|
||||
fn active_changed(&self, active: bool) -> fdo::Result<()>;
|
||||
}
|
||||
|
||||
/// Listens to screensaver (screen lock) changes
|
||||
pub fn init(destination: popover::Destination) {
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = start(destination) {
|
||||
log_print!(
|
||||
logging::Level::Surprise,
|
||||
"Could not track screensaver status, giving up: {:?}",
|
||||
e,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn start(destination: popover::Destination) -> Result<Void, zbus::Error> {
|
||||
let conn = Connection::new_session()?;
|
||||
let manager = ManagerProxy::new(&conn)?;
|
||||
|
||||
manager.connect_active_changed(move |m| {
|
||||
destination.send(popover::Event::ScreensaverActive(m));
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
loop {
|
||||
match manager.next_signal() {
|
||||
Ok(None) => {}
|
||||
other => log_print!(
|
||||
logging::Level::Bug,
|
||||
"Encountered unhandled event: {:?}",
|
||||
other,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -20,4 +20,14 @@ and by receiving updates from it.
|
||||
// Panel contains state and logic to protect the main state from getting flooded
|
||||
// with low-level wayland and gtk sizing events.
|
||||
|
||||
pub mod external;
|
||||
pub mod popover;
|
||||
|
||||
/// The implementing actor is able to receive and handle messages.
|
||||
/// Typically, it's the sending end of the channel,
|
||||
/// whose other end is inside an event loop.
|
||||
// TODO: implement for remaning actors and make the event loop refer to this.
|
||||
pub trait Destination {
|
||||
type Event;
|
||||
fn send(&self, event: Self::Event);
|
||||
}
|
||||
|
||||
@ -11,30 +11,66 @@ but it cannot get the user-selected overlay, because it's stored in state.
|
||||
To solve this, overlay will be cached in the popover actor,
|
||||
and updated by main state every time it changes.
|
||||
*/
|
||||
use crate::logging;
|
||||
use std::borrow::BorrowMut;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub mod c {
|
||||
use super::*;
|
||||
use crate::util::c::Wrapped;
|
||||
/// The mutable instance of state
|
||||
pub type Actor = Wrapped<State>;
|
||||
use crate::util::c::ArcWrapped;
|
||||
/// The mutable instance of state.
|
||||
/// Thread-safe because this actor does not get its own event loop,
|
||||
/// and therefore can't have a channel to receive messages,
|
||||
/// so instead messages will be passed directly to the mutexed actor.
|
||||
pub type Actor = ArcWrapped<State>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub type Destination = Arc<Mutex<State>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Event {
|
||||
Overlay(Option<String>),
|
||||
ScreensaverActive(bool),
|
||||
}
|
||||
|
||||
impl super::Destination for Destination {
|
||||
type Event = Event;
|
||||
fn send(&self, event: Self::Event) {
|
||||
let actor = self.lock();
|
||||
match actor {
|
||||
Ok(mut actor) => {
|
||||
let actor = actor.borrow_mut();
|
||||
**actor = actor.clone().handle_event(event);
|
||||
},
|
||||
Err(e) => log_print!(
|
||||
logging::Level::Bug,
|
||||
"Cannot lock popover state: {:?}",
|
||||
e,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct State {
|
||||
pub overlay: Option<String>,
|
||||
/// Settings button active
|
||||
pub settings_active: bool,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> Self {
|
||||
Self { overlay: None }
|
||||
pub fn new(settings_active: bool) -> Self {
|
||||
Self {
|
||||
overlay: None,
|
||||
settings_active,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_overlay(
|
||||
actor: &c::Actor,
|
||||
overlay: Option<String>,
|
||||
) {
|
||||
let actor = actor.clone_ref();
|
||||
let mut actor = actor.borrow_mut();
|
||||
actor.overlay = overlay;
|
||||
fn handle_event(mut self, event: Event) -> Self {
|
||||
match event {
|
||||
Event::Overlay(overlay) => { self.overlay = overlay; },
|
||||
Event::ScreensaverActive(lock_active) => { self.settings_active = !lock_active; },
|
||||
};
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -23,10 +23,9 @@ mod assert_matches;
|
||||
mod logging;
|
||||
|
||||
mod action;
|
||||
mod actors;
|
||||
pub mod actors;
|
||||
mod animation;
|
||||
pub mod data;
|
||||
mod debug;
|
||||
mod drawing;
|
||||
mod event_loop;
|
||||
pub mod float_ord;
|
||||
|
||||
19
src/main.rs
19
src/main.rs
@ -4,8 +4,8 @@
|
||||
|
||||
/*! Glue for the main loop. */
|
||||
use crate::actors;
|
||||
use crate::actors::external::debug;
|
||||
use crate::animation;
|
||||
use crate::debug;
|
||||
use crate::data::loading;
|
||||
use crate::event_loop;
|
||||
use crate::panel;
|
||||
@ -21,6 +21,8 @@ mod c {
|
||||
use std::rc::Rc;
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::actors::Destination;
|
||||
use crate::actors::popover;
|
||||
use crate::event_loop::driver;
|
||||
use crate::imservice::IMService;
|
||||
use crate::imservice::c::InputMethod;
|
||||
@ -28,7 +30,7 @@ mod c {
|
||||
use crate::outputs::Outputs;
|
||||
use crate::state;
|
||||
use crate::submission::Submission;
|
||||
use crate::util::c::Wrapped;
|
||||
use crate::util::c::{ArcWrapped, Wrapped};
|
||||
use crate::vkeyboard::c::ZwpVirtualKeyboardV1;
|
||||
|
||||
/// DbusHandler*
|
||||
@ -121,12 +123,17 @@ mod c {
|
||||
};
|
||||
let submission = Submission::new(vk, imservice);
|
||||
|
||||
let popover = ArcWrapped::new(actors::popover::State::new(true));
|
||||
|
||||
#[cfg(feature = "zbus_v1_5")]
|
||||
crate::actors::external::screensaver::init(popover.clone_ref());
|
||||
|
||||
RsObjects {
|
||||
submission: Wrapped::new(submission),
|
||||
state_manager: Wrapped::new(state_manager),
|
||||
receiver: Wrapped::new(receiver),
|
||||
wayland: Box::into_raw(wayland),
|
||||
popover: Wrapped::new(actors::popover::State::new()),
|
||||
popover,
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +159,7 @@ mod c {
|
||||
main_loop_handle_message(
|
||||
msg,
|
||||
panel_manager.clone(),
|
||||
&popover,
|
||||
&popover.clone_ref(),
|
||||
hint_manager,
|
||||
dbus_handler,
|
||||
);
|
||||
@ -170,7 +177,7 @@ mod c {
|
||||
fn main_loop_handle_message(
|
||||
msg: Commands,
|
||||
panel_manager: Wrapped<panel::Manager>,
|
||||
popover: &actors::popover::c::Actor,
|
||||
popover: &actors::popover::Destination,
|
||||
hint_manager: HintManager,
|
||||
dbus_handler: *const DBusHandler,
|
||||
) {
|
||||
@ -191,7 +198,7 @@ mod c {
|
||||
overlay_name,
|
||||
purpose,
|
||||
} = description;
|
||||
actors::popover::set_overlay(popover, overlay_name.clone());
|
||||
popover.send(popover::Event::Overlay(overlay_name.clone()));
|
||||
let layout = loading::load_layout(&name, kind, purpose, &overlay_name);
|
||||
let layout = Box::into_raw(Box::new(layout));
|
||||
// CSS can't express "+" in the class
|
||||
|
||||
@ -364,6 +364,7 @@ pub fn show(
|
||||
};
|
||||
|
||||
let settings_action = gio::SimpleAction::new("settings", None);
|
||||
settings_action.set_enabled(popover.settings_active);
|
||||
settings_action.connect_activate(move |_, _| {
|
||||
let s = CString::new("region").unwrap();
|
||||
unsafe { c::popover_open_settings_panel(s.as_ptr()) };
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
/*! Application-wide state is stored here.
|
||||
* It's driven by the loop defined in the loop module. */
|
||||
|
||||
use crate::actors::external::debug;
|
||||
use crate::animation;
|
||||
use crate::debug;
|
||||
use crate::event_loop;
|
||||
use crate::event_loop::ActorState;
|
||||
use crate::imservice::{ ContentHint, ContentPurpose };
|
||||
|
||||
48
src/util.rs
48
src/util.rs
@ -15,6 +15,7 @@ pub mod c {
|
||||
use std::os::raw::c_char;
|
||||
use std::rc::Rc;
|
||||
use std::str::Utf8Error;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
// traits
|
||||
|
||||
@ -128,6 +129,53 @@ pub mod c {
|
||||
}
|
||||
|
||||
impl<T> COpaquePtr for Wrapped<T> {}
|
||||
|
||||
/// Similar to Wrapped, except thread-safe.
|
||||
#[repr(transparent)]
|
||||
pub struct ArcWrapped<T>(*const Mutex<T>);
|
||||
|
||||
impl<T> ArcWrapped<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
Self::wrap(Arc::new(Mutex::new(value)))
|
||||
}
|
||||
pub fn wrap(state: Arc<Mutex<T>>) -> Self {
|
||||
Self(Arc::into_raw(state))
|
||||
}
|
||||
/// Extracts the reference to the data.
|
||||
/// It may cause problems if attempted in more than one place
|
||||
pub unsafe fn unwrap(self) -> Arc<Mutex<T>> {
|
||||
Arc::from_raw(self.0)
|
||||
}
|
||||
|
||||
/// Creates a new Rc reference to the same data.
|
||||
/// Use for accessing the underlying data as a reference.
|
||||
pub fn clone_ref(&self) -> Arc<Mutex<T>> {
|
||||
// A bit dangerous: the Rc may be in use elsewhere
|
||||
let used_rc = unsafe { Arc::from_raw(self.0) };
|
||||
let rc = used_rc.clone();
|
||||
Arc::into_raw(used_rc); // prevent dropping the original reference
|
||||
rc
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for ArcWrapped<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self::wrap(self.clone_ref())
|
||||
}
|
||||
}
|
||||
|
||||
/// ToOwned won't work here
|
||||
impl<T: Clone> CloneOwned for ArcWrapped<T> {
|
||||
type Owned = T;
|
||||
|
||||
fn clone_owned(&self) -> T {
|
||||
let rc = self.clone_ref();
|
||||
// FIXME: this panic here is inelegant.
|
||||
// It will only happen in case of crashes elsewhere, but still.
|
||||
let r = rc.lock().unwrap();
|
||||
r.to_owned()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Clones the underlying data structure, like ToOwned.
|
||||
|
||||
Reference in New Issue
Block a user