Merge branch 'pop-os:master' into flags-not-clone
This commit is contained in:
commit
85bec29de5
9 changed files with 91 additions and 92 deletions
|
|
@ -128,6 +128,7 @@ optional = true
|
||||||
|
|
||||||
[dependencies.taffy]
|
[dependencies.taffy]
|
||||||
git = "https://github.com/DioxusLabs/taffy"
|
git = "https://github.com/DioxusLabs/taffy"
|
||||||
|
rev = "7781c70"
|
||||||
features = ["grid"]
|
features = ["grid"]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ publish = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
apply = "0.3.0"
|
apply = "0.3.0"
|
||||||
fraction = "0.13.0"
|
fraction = "0.13.0"
|
||||||
libcosmic = { path = "../..", features = ["debug", "winit", "tokio"] }
|
libcosmic = { path = "../..", features = ["debug", "winit", "tokio", "single-instance"] }
|
||||||
once_cell = "1.18"
|
once_cell = "1.18"
|
||||||
slotmap = "1.0.6"
|
slotmap = "1.0.6"
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
|
|
|
||||||
2
iced
2
iced
|
|
@ -1 +1 @@
|
||||||
Subproject commit 94f8772b2f05195506f7a454e41290afe02eaa40
|
Subproject commit b3ede4f9a72275cfeb29fac80a31546f728783fd
|
||||||
|
|
@ -63,7 +63,8 @@ pub struct Core {
|
||||||
#[cfg(feature = "applet")]
|
#[cfg(feature = "applet")]
|
||||||
pub applet: crate::applet::Context,
|
pub applet: crate::applet::Context,
|
||||||
|
|
||||||
pub single_instance: bool,
|
#[cfg(feature = "single-instance")]
|
||||||
|
pub(crate) single_instance: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Core {
|
impl Default for Core {
|
||||||
|
|
@ -106,6 +107,7 @@ impl Default for Core {
|
||||||
},
|
},
|
||||||
#[cfg(feature = "applet")]
|
#[cfg(feature = "applet")]
|
||||||
applet: crate::applet::Context::default(),
|
applet: crate::applet::Context::default(),
|
||||||
|
#[cfg(feature = "single-instance")]
|
||||||
single_instance: false,
|
single_instance: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,8 @@ where
|
||||||
super::Message::App(message) => self.app.update(message),
|
super::Message::App(message) => self.app.update(message),
|
||||||
super::Message::Cosmic(message) => self.cosmic_update(message),
|
super::Message::Cosmic(message) => self.cosmic_update(message),
|
||||||
super::Message::None => iced::Command::none(),
|
super::Message::None => iced::Command::none(),
|
||||||
|
#[cfg(feature = "single-instance")]
|
||||||
|
super::Message::DbusActivation(message) => self.app.dbus_activation(message),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,7 +186,7 @@ where
|
||||||
.core()
|
.core()
|
||||||
.single_instance
|
.single_instance
|
||||||
.then(|| super::single_instance_subscription::<T>())
|
.then(|| super::single_instance_subscription::<T>())
|
||||||
.unwrap_or_else(Subscription::none),
|
.unwrap_or_else(|| Subscription::none()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -364,11 +366,12 @@ impl<T: Application> Cosmic<T> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Activate(token) => {
|
Message::Activate(_token) => {
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
return iced_sctk::commands::activation::activate(
|
return iced_sctk::commands::activation::activate(
|
||||||
iced::window::Id::default(),
|
iced::window::Id::default(),
|
||||||
token,
|
#[allow(clippy::used_underscore_binding)]
|
||||||
|
_token,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
115
src/app/mod.rs
115
src/app/mod.rs
|
|
@ -19,6 +19,9 @@ pub mod message {
|
||||||
App(M),
|
App(M),
|
||||||
/// Internal messages to be handled by libcosmic.
|
/// Internal messages to be handled by libcosmic.
|
||||||
Cosmic(super::cosmic::Message),
|
Cosmic(super::cosmic::Message),
|
||||||
|
#[cfg(feature = "single-instance")]
|
||||||
|
/// Dbus activation messages
|
||||||
|
DbusActivation(super::DbusActivationMessage),
|
||||||
/// Do nothing
|
/// Do nothing
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
@ -36,8 +39,6 @@ pub mod message {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
pub use self::command::Command;
|
pub use self::command::Command;
|
||||||
pub use self::core::Core;
|
pub use self::core::Core;
|
||||||
pub use self::settings::Settings;
|
pub use self::settings::Settings;
|
||||||
|
|
@ -57,12 +58,11 @@ use {
|
||||||
std::collections::HashMap,
|
std::collections::HashMap,
|
||||||
zbus::{dbus_interface, dbus_proxy, zvariant::Value},
|
zbus::{dbus_interface, dbus_proxy, zvariant::Value},
|
||||||
};
|
};
|
||||||
/// Launch a COSMIC application with the given [`Settings`].
|
|
||||||
///
|
pub(crate) fn iced_settings<App: Application>(
|
||||||
/// # Errors
|
settings: Settings,
|
||||||
///
|
flags: App::Flags,
|
||||||
/// Returns error on application failure.
|
) -> iced::Settings<(Core, App::Flags)> {
|
||||||
pub fn run<App: Application>(settings: Settings, flags: App::Flags) -> iced::Result {
|
|
||||||
if let Some(icon_theme) = settings.default_icon_theme {
|
if let Some(icon_theme) = settings.default_icon_theme {
|
||||||
crate::icon_theme::set_default(icon_theme);
|
crate::icon_theme::set_default(icon_theme);
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,6 @@ pub fn run<App: Application>(settings: Settings, flags: App::Flags) -> iced::Res
|
||||||
core.set_scale_factor(settings.scale_factor);
|
core.set_scale_factor(settings.scale_factor);
|
||||||
core.set_window_width(settings.size.0);
|
core.set_window_width(settings.size.0);
|
||||||
core.set_window_height(settings.size.1);
|
core.set_window_height(settings.size.1);
|
||||||
core.single_instance = settings.single_instance;
|
|
||||||
|
|
||||||
THEME.with(move |t| {
|
THEME.with(move |t| {
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
let mut cosmic_theme = t.borrow_mut();
|
||||||
|
|
@ -120,8 +119,20 @@ pub fn run<App: Application>(settings: Settings, flags: App::Flags) -> iced::Res
|
||||||
iced.window.transparent = settings.transparent;
|
iced.window.transparent = settings.transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
cosmic::Cosmic::<App>::run(iced)
|
iced
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Launch a COSMIC application with the given [`Settings`].
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns error on application failure.
|
||||||
|
pub fn run<App: Application>(settings: Settings, flags: App::Flags) -> iced::Result {
|
||||||
|
let settings = iced_settings::<App>(settings, flags);
|
||||||
|
|
||||||
|
cosmic::Cosmic::<App>::run(settings)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "single-instance")]
|
#[cfg(feature = "single-instance")]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DbusActivationMessage<Action = String, Args = Vec<String>> {
|
pub struct DbusActivationMessage<Action = String, Args = Vec<String>> {
|
||||||
|
|
@ -160,7 +171,7 @@ impl DbusActivation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "single-instance")]
|
#[cfg(feature = "single-instance")]
|
||||||
#[dbus_proxy(interface = "org.freedesktop.DbusActivation")]
|
#[dbus_proxy(interface = "org.freedesktop.DbusActivation", assume_defaults = true)]
|
||||||
pub trait DbusActivationInterface {
|
pub trait DbusActivationInterface {
|
||||||
/// Activate the application.
|
/// Activate the application.
|
||||||
fn activate(&mut self, platform_data: HashMap<&str, Value<'_>>) -> zbus::Result<()>;
|
fn activate(&mut self, platform_data: HashMap<&str, Value<'_>>) -> zbus::Result<()>;
|
||||||
|
|
@ -182,7 +193,7 @@ pub trait DbusActivationInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "single-instance")]
|
#[cfg(feature = "single-instance")]
|
||||||
#[dbus_interface(interface = "org.freedesktop.DbusActivation")]
|
#[dbus_interface(name = "org.freedesktop.DbusActivation")]
|
||||||
impl DbusActivation {
|
impl DbusActivation {
|
||||||
async fn activate(&mut self, platform_data: HashMap<&str, Value<'_>>) {
|
async fn activate(&mut self, platform_data: HashMap<&str, Value<'_>>) {
|
||||||
if let Some(tx) = &mut self.0 {
|
if let Some(tx) = &mut self.0 {
|
||||||
|
|
@ -259,16 +270,16 @@ impl DbusActivation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "single-instance")]
|
#[cfg(feature = "single-instance")]
|
||||||
|
|
||||||
/// Launch a COSMIC application with the given [`Settings`].
|
/// Launch a COSMIC application with the given [`Settings`].
|
||||||
/// If the application is already running, the arguments will be passed to the
|
/// If the application is already running, the arguments will be passed to the
|
||||||
/// running instance.
|
/// running instance.
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// Returns error on application failure.
|
/// Returns error on application failure.
|
||||||
pub fn run_single_instance<App: Application>(
|
pub fn run_single_instance<App: Application>(settings: Settings, flags: App::Flags) -> iced::Result
|
||||||
mut settings: Settings,
|
where
|
||||||
flags: App::Flags,
|
App::Flags: CosmicFlags + Clone,
|
||||||
) -> iced::Result {
|
App::Message: Clone + std::fmt::Debug + Send + 'static,
|
||||||
|
{
|
||||||
let activation_token = std::env::var("XDG_ACTIVATION_TOKEN").ok();
|
let activation_token = std::env::var("XDG_ACTIVATION_TOKEN").ok();
|
||||||
|
|
||||||
let override_single = std::env::var("COSMIC_SINGLE_INSTANCE")
|
let override_single = std::env::var("COSMIC_SINGLE_INSTANCE")
|
||||||
|
|
@ -279,7 +290,6 @@ pub fn run_single_instance<App: Application>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let path: String = format!("/{}", App::APP_ID.replace('.', "/"));
|
let path: String = format!("/{}", App::APP_ID.replace('.', "/"));
|
||||||
settings.single_instance = true;
|
|
||||||
|
|
||||||
let Ok(conn) = zbus::blocking::Connection::session() else {
|
let Ok(conn) = zbus::blocking::Connection::session() else {
|
||||||
tracing::warn!("Failed to connect to dbus");
|
tracing::warn!("Failed to connect to dbus");
|
||||||
|
|
@ -322,13 +332,15 @@ pub fn run_single_instance<App: Application>(
|
||||||
tracing::info!("Another instance is running");
|
tracing::info!("Another instance is running");
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
run::<App>(settings, flags)
|
let mut settings = iced_settings::<App>(settings, flags);
|
||||||
|
settings.flags.0.single_instance = true;
|
||||||
|
cosmic::Cosmic::<App>::run(settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CosmicFlags {
|
pub trait CosmicFlags {
|
||||||
type SubCommand: FromStr + ToString + std::fmt::Debug + Clone + Send + 'static;
|
type SubCommand: ToString + std::fmt::Debug + Clone + Send + 'static;
|
||||||
type Args: TryFrom<Vec<String>> + Into<Vec<String>> + std::fmt::Debug + Clone + Send + 'static;
|
type Args: Into<Vec<String>> + std::fmt::Debug + Clone + Send + 'static;
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn action(&self) -> Option<&Self::SubCommand> {
|
fn action(&self) -> Option<&Self::SubCommand> {
|
||||||
None
|
None
|
||||||
|
|
@ -349,27 +361,9 @@ where
|
||||||
/// Default async executor to use with the app.
|
/// Default async executor to use with the app.
|
||||||
type Executor: iced_futures::Executor;
|
type Executor: iced_futures::Executor;
|
||||||
|
|
||||||
#[cfg(feature = "single-instance")]
|
|
||||||
/// Argument received [`Application::new`].
|
|
||||||
type Flags: Clone + CosmicFlags;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "single-instance"))]
|
|
||||||
/// Argument received [`Application::new`].
|
/// Argument received [`Application::new`].
|
||||||
type Flags;
|
type Flags;
|
||||||
|
|
||||||
#[cfg(feature = "single-instance")]
|
|
||||||
/// Message type specific to our app.
|
|
||||||
type Message: Clone
|
|
||||||
+ From<
|
|
||||||
DbusActivationDetails<
|
|
||||||
<Self::Flags as CosmicFlags>::SubCommand,
|
|
||||||
<Self::Flags as CosmicFlags>::Args,
|
|
||||||
>,
|
|
||||||
> + std::fmt::Debug
|
|
||||||
+ Send
|
|
||||||
+ 'static;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "single-instance"))]
|
|
||||||
/// Message type specific to our app.
|
/// Message type specific to our app.
|
||||||
type Message: Clone + std::fmt::Debug + Send + 'static;
|
type Message: Clone + std::fmt::Debug + Send + 'static;
|
||||||
|
|
||||||
|
|
@ -465,6 +459,15 @@ where
|
||||||
fn style(&self) -> Option<<crate::Theme as iced_style::application::StyleSheet>::Style> {
|
fn style(&self) -> Option<<crate::Theme as iced_style::application::StyleSheet>::Style> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles dbus activation messages
|
||||||
|
#[cfg(feature = "single-instance")]
|
||||||
|
fn dbus_activation(
|
||||||
|
&mut self,
|
||||||
|
msg: DbusActivationMessage,
|
||||||
|
) -> iced::Command<Message<Self::Message>> {
|
||||||
|
iced::Command::none()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Methods automatically derived for all types implementing [`Application`].
|
/// Methods automatically derived for all types implementing [`Application`].
|
||||||
|
|
@ -633,7 +636,7 @@ fn single_instance_subscription<App: ApplicationExt>() -> Subscription<Message<A
|
||||||
iced::subscription::channel(
|
iced::subscription::channel(
|
||||||
TypeId::of::<DbusActivation>(),
|
TypeId::of::<DbusActivation>(),
|
||||||
10,
|
10,
|
||||||
|mut output| async move {
|
move |mut output| async move {
|
||||||
let mut single_instance: DbusActivation = DbusActivation::new();
|
let mut single_instance: DbusActivation = DbusActivation::new();
|
||||||
let mut rx = single_instance.rx();
|
let mut rx = single_instance.rx();
|
||||||
if let Ok(builder) = zbus::ConnectionBuilder::session() {
|
if let Ok(builder) = zbus::ConnectionBuilder::session() {
|
||||||
|
|
@ -680,36 +683,8 @@ fn single_instance_subscription<App: ApplicationExt>() -> Subscription<Message<A
|
||||||
tracing::error!(?err, "Failed to send message");
|
tracing::error!(?err, "Failed to send message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(msg) = match msg.msg {
|
if let Err(err) = output.send(Message::DbusActivation(msg)).await {
|
||||||
DbusActivationDetails::Activate => {
|
tracing::error!(?err, "Failed to send message");
|
||||||
Some(DbusActivationDetails::Activate)
|
|
||||||
}
|
|
||||||
DbusActivationDetails::Open { url } => {
|
|
||||||
Some(DbusActivationDetails::Open { url })
|
|
||||||
}
|
|
||||||
DbusActivationDetails::ActivateAction { action, args } => {
|
|
||||||
if let (Ok(action), Ok(args)) = (
|
|
||||||
<App::Flags as CosmicFlags>::SubCommand::from_str(&action),
|
|
||||||
<App::Flags as CosmicFlags>::Args::try_from(args),
|
|
||||||
) {
|
|
||||||
Some(DbusActivationDetails::ActivateAction::<
|
|
||||||
<App::Flags as CosmicFlags>::SubCommand,
|
|
||||||
<App::Flags as CosmicFlags>::Args,
|
|
||||||
> {
|
|
||||||
action,
|
|
||||||
args,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
tracing::error!("Invalid action or args");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
if let Err(err) =
|
|
||||||
output.send(Message::App(App::Message::from(msg))).await
|
|
||||||
{
|
|
||||||
tracing::error!(?err, "Failed to send message");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,6 @@ pub struct Settings {
|
||||||
|
|
||||||
/// Whether the application should exit when there are no open windows
|
/// Whether the application should exit when there are no open windows
|
||||||
pub(crate) exit_on_close: bool,
|
pub(crate) exit_on_close: bool,
|
||||||
|
|
||||||
/// Only allow a single instance of the application to run
|
|
||||||
pub single_instance: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
|
|
@ -100,7 +97,6 @@ impl Default for Settings {
|
||||||
theme: crate::theme::system_preference(),
|
theme: crate::theme::system_preference(),
|
||||||
transparent: false,
|
transparent: false,
|
||||||
exit_on_close: true,
|
exit_on_close: true,
|
||||||
single_instance: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use iced_core::{Alignment, Length, Padding, Point, Size};
|
||||||
use taffy::geometry::{Line, Rect};
|
use taffy::geometry::{Line, Rect};
|
||||||
use taffy::style::{AlignItems, Dimension, Display, GridPlacement, Style};
|
use taffy::style::{AlignItems, Dimension, Display, GridPlacement, Style};
|
||||||
use taffy::style_helpers::{auto, length};
|
use taffy::style_helpers::{auto, length};
|
||||||
use taffy::Taffy;
|
use taffy::TaffyTree;
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub fn resolve<Message>(
|
pub fn resolve<Message>(
|
||||||
|
|
@ -30,7 +30,7 @@ pub fn resolve<Message>(
|
||||||
let mut leafs = Vec::with_capacity(items.len());
|
let mut leafs = Vec::with_capacity(items.len());
|
||||||
let mut nodes = Vec::with_capacity(items.len());
|
let mut nodes = Vec::with_capacity(items.len());
|
||||||
|
|
||||||
let mut taffy = Taffy::<()>::with_capacity(items.len() + 1);
|
let mut taffy = TaffyTree::<()>::with_capacity(items.len() + 1);
|
||||||
|
|
||||||
// Attach widgets as child nodes.
|
// Attach widgets as child nodes.
|
||||||
for (child, assignment) in items.iter().zip(assignments.iter()) {
|
for (child, assignment) in items.iter().zip(assignments.iter()) {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ use iced_core::mouse;
|
||||||
use iced_core::overlay;
|
use iced_core::overlay;
|
||||||
use iced_core::renderer;
|
use iced_core::renderer;
|
||||||
use iced_core::widget::{Operation, OperationOutputWrapper, Tree};
|
use iced_core::widget::{Operation, OperationOutputWrapper, Tree};
|
||||||
use iced_core::{Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Size, Widget};
|
use iced_core::{
|
||||||
|
Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Size, Vector, Widget,
|
||||||
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
pub use iced_style::container::{Appearance, StyleSheet};
|
pub use iced_style::container::{Appearance, StyleSheet};
|
||||||
|
|
@ -25,19 +27,26 @@ pub struct Popover<'a, Message, Renderer> {
|
||||||
content: Element<'a, Message, Renderer>,
|
content: Element<'a, Message, Renderer>,
|
||||||
// XXX Avoid refcell; improve iced overlay API?
|
// XXX Avoid refcell; improve iced overlay API?
|
||||||
popup: RefCell<Element<'a, Message, Renderer>>,
|
popup: RefCell<Element<'a, Message, Renderer>>,
|
||||||
|
position: Option<Point>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Renderer> Popover<'a, Message, Renderer> {
|
impl<'a, Message, Renderer> Popover<'a, Message, Renderer> {
|
||||||
fn new(
|
pub fn new(
|
||||||
content: impl Into<Element<'a, Message, Renderer>>,
|
content: impl Into<Element<'a, Message, Renderer>>,
|
||||||
popup: impl Into<Element<'a, Message, Renderer>>,
|
popup: impl Into<Element<'a, Message, Renderer>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
content: content.into(),
|
content: content.into(),
|
||||||
popup: RefCell::new(popup.into()),
|
popup: RefCell::new(popup.into()),
|
||||||
|
position: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn position(mut self, position: Point) -> Self {
|
||||||
|
self.position = Some(position);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
// TODO More options for positioning similar to GdkPopup, xdg_popup
|
// TODO More options for positioning similar to GdkPopup, xdg_popup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,9 +154,20 @@ where
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
) -> Option<overlay::Element<'b, Message, Renderer>> {
|
) -> Option<overlay::Element<'b, Message, Renderer>> {
|
||||||
// Set position to center of bottom edge
|
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
let position = Point::new(bounds.x + bounds.width / 2.0, bounds.y + bounds.height);
|
let (position, centered) = match self.position {
|
||||||
|
Some(relative) => (
|
||||||
|
bounds.position() + Vector::new(relative.x, relative.y),
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
None => {
|
||||||
|
// Set position to center of bottom edge
|
||||||
|
(
|
||||||
|
Point::new(bounds.x + bounds.width / 2.0, bounds.y + bounds.height),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// XXX needed to use RefCell to get &mut for popup element
|
// XXX needed to use RefCell to get &mut for popup element
|
||||||
Some(overlay::Element::new(
|
Some(overlay::Element::new(
|
||||||
|
|
@ -155,6 +175,7 @@ where
|
||||||
Box::new(Overlay {
|
Box::new(Overlay {
|
||||||
tree: &mut tree.children[1],
|
tree: &mut tree.children[1],
|
||||||
content: &self.popup,
|
content: &self.popup,
|
||||||
|
centered,
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
@ -171,9 +192,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Overlay<'a, 'b, Message, Renderer> {
|
pub struct Overlay<'a, 'b, Message, Renderer> {
|
||||||
tree: &'a mut Tree,
|
tree: &'a mut Tree,
|
||||||
content: &'a RefCell<Element<'b, Message, Renderer>>,
|
content: &'a RefCell<Element<'b, Message, Renderer>>,
|
||||||
|
centered: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, Message, Renderer> overlay::Overlay<Message, Renderer>
|
impl<'a, 'b, Message, Renderer> overlay::Overlay<Message, Renderer>
|
||||||
|
|
@ -182,13 +204,13 @@ where
|
||||||
Renderer: iced_core::Renderer,
|
Renderer: iced_core::Renderer,
|
||||||
{
|
{
|
||||||
fn layout(&self, renderer: &Renderer, bounds: Size, mut position: Point) -> layout::Node {
|
fn layout(&self, renderer: &Renderer, bounds: Size, mut position: Point) -> layout::Node {
|
||||||
// Position is set to the center bottom of the lower widget
|
|
||||||
|
|
||||||
let limits = layout::Limits::new(Size::UNIT, bounds);
|
let limits = layout::Limits::new(Size::UNIT, bounds);
|
||||||
let mut node = self.content.borrow().as_widget().layout(renderer, &limits);
|
let mut node = self.content.borrow().as_widget().layout(renderer, &limits);
|
||||||
|
if self.centered {
|
||||||
let width = node.size().width;
|
// Position is set to the center bottom of the lower widget
|
||||||
position.x = (position.x - width / 2.0).clamp(0.0, bounds.width - width);
|
let width = node.size().width;
|
||||||
|
position.x = (position.x - width / 2.0).clamp(0.0, bounds.width - width);
|
||||||
|
}
|
||||||
node.move_to(position);
|
node.move_to(position);
|
||||||
|
|
||||||
node
|
node
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue