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
|
# For the newer-than-Byzantium config
|
||||||
|
|
||||||
bitflags = "1.3.*"
|
bitflags = "1.3.*"
|
||||||
clap = { version = "3.2.*", features=["std"], default-features = false }
|
clap = { version = "3.2.*", features=["std"], default-features = false }
|
||||||
zbus = "1.9.*"
|
zbus = "1.9.*"
|
||||||
|
|||||||
@ -23,6 +23,7 @@ path = "@path@/examples/find_orphan_layouts.rs"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
glib_v0_14 = []
|
glib_v0_14 = []
|
||||||
|
zbus_v1_5 = []
|
||||||
|
|
||||||
# Dependencies which don't change based on build flags
|
# Dependencies which don't change based on build flags
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -99,7 +99,7 @@ cargo_toml_base = configure_file(
|
|||||||
cargo_patch = []
|
cargo_patch = []
|
||||||
|
|
||||||
if get_option('newer') == true
|
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_deps = files('Cargo.deps.newer')
|
||||||
cargo_lock = files('Cargo.lock.newer')
|
cargo_lock = files('Cargo.lock.newer')
|
||||||
else
|
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
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
use std::thread;
|
|
||||||
use zbus::{Connection, ObjectServer, dbus_interface, fdo};
|
|
||||||
|
|
||||||
use crate::main;
|
use crate::main;
|
||||||
use crate::state;
|
use crate::state;
|
||||||
|
|
||||||
|
use std::thread;
|
||||||
|
use zbus::{Connection, ObjectServer, dbus_interface, fdo};
|
||||||
|
|
||||||
|
use super::Void;
|
||||||
|
|
||||||
use std::convert::TryInto;
|
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()?;
|
let connection = Connection::new_session()?;
|
||||||
fdo::DBusProxy::new(&connection)?.request_name(
|
fdo::DBusProxy::new(&connection)?.request_name(
|
||||||
"sm.puri.SqueekDebug",
|
"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
|
// Panel contains state and logic to protect the main state from getting flooded
|
||||||
// with low-level wayland and gtk sizing events.
|
// with low-level wayland and gtk sizing events.
|
||||||
|
|
||||||
pub mod popover;
|
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,
|
To solve this, overlay will be cached in the popover actor,
|
||||||
and updated by main state every time it changes.
|
and updated by main state every time it changes.
|
||||||
*/
|
*/
|
||||||
|
use crate::logging;
|
||||||
|
use std::borrow::BorrowMut;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
pub mod c {
|
pub mod c {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::util::c::Wrapped;
|
use crate::util::c::ArcWrapped;
|
||||||
/// The mutable instance of state
|
/// The mutable instance of state.
|
||||||
pub type Actor = Wrapped<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>>;
|
||||||
pub struct State {
|
|
||||||
pub overlay: Option<String>,
|
#[derive(Debug)]
|
||||||
|
pub enum Event {
|
||||||
|
Overlay(Option<String>),
|
||||||
|
ScreensaverActive(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl super::Destination for Destination {
|
||||||
pub fn new() -> Self {
|
type Event = Event;
|
||||||
Self { overlay: None }
|
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,
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_overlay(
|
#[derive(Clone, Debug)]
|
||||||
actor: &c::Actor,
|
pub struct State {
|
||||||
overlay: Option<String>,
|
pub overlay: Option<String>,
|
||||||
) {
|
/// Settings button active
|
||||||
let actor = actor.clone_ref();
|
pub settings_active: bool,
|
||||||
let mut actor = actor.borrow_mut();
|
}
|
||||||
actor.overlay = overlay;
|
|
||||||
}
|
impl State {
|
||||||
|
pub fn new(settings_active: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
overlay: None,
|
||||||
|
settings_active,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 logging;
|
||||||
|
|
||||||
mod action;
|
mod action;
|
||||||
mod actors;
|
pub mod actors;
|
||||||
mod animation;
|
mod animation;
|
||||||
pub mod data;
|
pub mod data;
|
||||||
mod debug;
|
|
||||||
mod drawing;
|
mod drawing;
|
||||||
mod event_loop;
|
mod event_loop;
|
||||||
pub mod float_ord;
|
pub mod float_ord;
|
||||||
|
|||||||
19
src/main.rs
19
src/main.rs
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
/*! Glue for the main loop. */
|
/*! Glue for the main loop. */
|
||||||
use crate::actors;
|
use crate::actors;
|
||||||
|
use crate::actors::external::debug;
|
||||||
use crate::animation;
|
use crate::animation;
|
||||||
use crate::debug;
|
|
||||||
use crate::data::loading;
|
use crate::data::loading;
|
||||||
use crate::event_loop;
|
use crate::event_loop;
|
||||||
use crate::panel;
|
use crate::panel;
|
||||||
@ -21,6 +21,8 @@ mod c {
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use crate::actors::Destination;
|
||||||
|
use crate::actors::popover;
|
||||||
use crate::event_loop::driver;
|
use crate::event_loop::driver;
|
||||||
use crate::imservice::IMService;
|
use crate::imservice::IMService;
|
||||||
use crate::imservice::c::InputMethod;
|
use crate::imservice::c::InputMethod;
|
||||||
@ -28,7 +30,7 @@ mod c {
|
|||||||
use crate::outputs::Outputs;
|
use crate::outputs::Outputs;
|
||||||
use crate::state;
|
use crate::state;
|
||||||
use crate::submission::Submission;
|
use crate::submission::Submission;
|
||||||
use crate::util::c::Wrapped;
|
use crate::util::c::{ArcWrapped, Wrapped};
|
||||||
use crate::vkeyboard::c::ZwpVirtualKeyboardV1;
|
use crate::vkeyboard::c::ZwpVirtualKeyboardV1;
|
||||||
|
|
||||||
/// DbusHandler*
|
/// DbusHandler*
|
||||||
@ -121,12 +123,17 @@ mod c {
|
|||||||
};
|
};
|
||||||
let submission = Submission::new(vk, imservice);
|
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 {
|
RsObjects {
|
||||||
submission: Wrapped::new(submission),
|
submission: Wrapped::new(submission),
|
||||||
state_manager: Wrapped::new(state_manager),
|
state_manager: Wrapped::new(state_manager),
|
||||||
receiver: Wrapped::new(receiver),
|
receiver: Wrapped::new(receiver),
|
||||||
wayland: Box::into_raw(wayland),
|
wayland: Box::into_raw(wayland),
|
||||||
popover: Wrapped::new(actors::popover::State::new()),
|
popover,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +159,7 @@ mod c {
|
|||||||
main_loop_handle_message(
|
main_loop_handle_message(
|
||||||
msg,
|
msg,
|
||||||
panel_manager.clone(),
|
panel_manager.clone(),
|
||||||
&popover,
|
&popover.clone_ref(),
|
||||||
hint_manager,
|
hint_manager,
|
||||||
dbus_handler,
|
dbus_handler,
|
||||||
);
|
);
|
||||||
@ -170,7 +177,7 @@ mod c {
|
|||||||
fn main_loop_handle_message(
|
fn main_loop_handle_message(
|
||||||
msg: Commands,
|
msg: Commands,
|
||||||
panel_manager: Wrapped<panel::Manager>,
|
panel_manager: Wrapped<panel::Manager>,
|
||||||
popover: &actors::popover::c::Actor,
|
popover: &actors::popover::Destination,
|
||||||
hint_manager: HintManager,
|
hint_manager: HintManager,
|
||||||
dbus_handler: *const DBusHandler,
|
dbus_handler: *const DBusHandler,
|
||||||
) {
|
) {
|
||||||
@ -191,7 +198,7 @@ mod c {
|
|||||||
overlay_name,
|
overlay_name,
|
||||||
purpose,
|
purpose,
|
||||||
} = description;
|
} = 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 = loading::load_layout(&name, kind, purpose, &overlay_name);
|
||||||
let layout = Box::into_raw(Box::new(layout));
|
let layout = Box::into_raw(Box::new(layout));
|
||||||
// CSS can't express "+" in the class
|
// CSS can't express "+" in the class
|
||||||
|
|||||||
@ -364,6 +364,7 @@ pub fn show(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let settings_action = gio::SimpleAction::new("settings", None);
|
let settings_action = gio::SimpleAction::new("settings", None);
|
||||||
|
settings_action.set_enabled(popover.settings_active);
|
||||||
settings_action.connect_activate(move |_, _| {
|
settings_action.connect_activate(move |_, _| {
|
||||||
let s = CString::new("region").unwrap();
|
let s = CString::new("region").unwrap();
|
||||||
unsafe { c::popover_open_settings_panel(s.as_ptr()) };
|
unsafe { c::popover_open_settings_panel(s.as_ptr()) };
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
/*! Application-wide state is stored here.
|
/*! Application-wide state is stored here.
|
||||||
* It's driven by the loop defined in the loop module. */
|
* It's driven by the loop defined in the loop module. */
|
||||||
|
|
||||||
|
use crate::actors::external::debug;
|
||||||
use crate::animation;
|
use crate::animation;
|
||||||
use crate::debug;
|
|
||||||
use crate::event_loop;
|
use crate::event_loop;
|
||||||
use crate::event_loop::ActorState;
|
use crate::event_loop::ActorState;
|
||||||
use crate::imservice::{ ContentHint, ContentPurpose };
|
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::os::raw::c_char;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
// traits
|
// traits
|
||||||
|
|
||||||
@ -128,6 +129,53 @@ pub mod c {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> COpaquePtr for Wrapped<T> {}
|
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.
|
/// Clones the underlying data structure, like ToOwned.
|
||||||
|
|||||||
Reference in New Issue
Block a user