mirror of
https://github.com/danbulant/cushy
synced 2026-07-05 11:10:34 +00:00
parent
a3c57d50d3
commit
bf78da333d
6 changed files with 114 additions and 6 deletions
|
|
@ -70,6 +70,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `Window::resize_increments`
|
- `Window::resize_increments`
|
||||||
- `Window::transparent`
|
- `Window::transparent`
|
||||||
- `Window::visible`
|
- `Window::visible`
|
||||||
|
- `run(&mut App)` is a new function that can provide a more concise way of
|
||||||
|
executing applications that would normally require using `PendingApp`.
|
||||||
|
- `PendingApp::on_startup` allows executing a function once the application's
|
||||||
|
event loop has begun.
|
||||||
|
- `App::monitors()` returns a snapshot of the currently configured monitors
|
||||||
|
attached to the device. A new example demonstrating this API is available at
|
||||||
|
`examples/monitors.rs`.
|
||||||
|
|
||||||
|
|
||||||
[139]: https://github.com/khonsulabs/cushy/issues/139
|
[139]: https://github.com/khonsulabs/cushy/issues/139
|
||||||
|
|
||||||
|
|
|
||||||
6
Cargo.lock
generated
6
Cargo.lock
generated
|
|
@ -124,8 +124,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "appit"
|
name = "appit"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/khonsulabs/appit#4cab6aedd10d179ed730397dc48ca6b23af6a431"
|
||||||
checksum = "7a158c9d2660ce603c741d513b44cdd97a4553e0749d4e49e45b9480fc72c162"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
@ -1310,8 +1309,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kludgine"
|
name = "kludgine"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/khonsulabs/kludgine#a468845f84cbee812778f91fe55cf02716efebd8"
|
||||||
checksum = "0bc8757e03860f7a9a15e9616060ed620a12500a61c9ff9b457cccfc5f20af1f"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"alot",
|
"alot",
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ tokio = ["dep:tokio"]
|
||||||
tokio-multi-thread = ["tokio", "tokio/rt-multi-thread"]
|
tokio-multi-thread = ["tokio", "tokio/rt-multi-thread"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
kludgine = { version = "0.10.0", features = ["app"] }
|
kludgine = { git = "https://github.com/khonsulabs/kludgine", features = [
|
||||||
|
"app",
|
||||||
|
] }
|
||||||
figures = { version = "0.4.0" }
|
figures = { version = "0.4.0" }
|
||||||
alot = "0.3"
|
alot = "0.3"
|
||||||
interner = "0.2.1"
|
interner = "0.2.1"
|
||||||
|
|
|
||||||
53
examples/monitors.rs
Normal file
53
examples/monitors.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
use cushy::widget::{MakeWidget, WidgetInstance, WidgetList};
|
||||||
|
use cushy::{Application, Open, PendingApp};
|
||||||
|
use kludgine::app::{Monitor, Monitors};
|
||||||
|
|
||||||
|
fn main() -> cushy::Result {
|
||||||
|
// Monitor information is only available through winit after the application
|
||||||
|
// has started up.
|
||||||
|
assert!(PendingApp::default().as_app().monitors().is_none());
|
||||||
|
|
||||||
|
cushy::run(|app| {
|
||||||
|
let monitors = app.monitors();
|
||||||
|
|
||||||
|
"Monitors"
|
||||||
|
.h1()
|
||||||
|
.and(list_monitors(monitors))
|
||||||
|
.into_rows()
|
||||||
|
.vertical_scroll()
|
||||||
|
.expand()
|
||||||
|
.open(app)
|
||||||
|
.expect("app running");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn list_monitors(monitors: Option<Monitors>) -> WidgetInstance {
|
||||||
|
if let Some(monitors) = monitors {
|
||||||
|
monitors
|
||||||
|
.available
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, monitor)| monitor_info(index, monitor, monitors.primary.as_ref()))
|
||||||
|
.collect::<WidgetList>()
|
||||||
|
.into_rows()
|
||||||
|
.make_widget()
|
||||||
|
} else {
|
||||||
|
"No monitor information available".make_widget()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn monitor_info(index: usize, monitor: Monitor, primary: Option<&Monitor>) -> impl MakeWidget {
|
||||||
|
let mut name = monitor
|
||||||
|
.name()
|
||||||
|
.unwrap_or_else(|| format!("Monitor {}", index + 1));
|
||||||
|
if primary.map_or(false, |primary| primary == &monitor) {
|
||||||
|
name.push_str(" (Primary)");
|
||||||
|
}
|
||||||
|
let region = monitor.region();
|
||||||
|
let region = format!(
|
||||||
|
"{},{} @ {}x{}",
|
||||||
|
region.origin.x, region.origin.y, region.size.width, region.size.height
|
||||||
|
);
|
||||||
|
|
||||||
|
name.h3().and(region).into_rows().contain()
|
||||||
|
}
|
||||||
38
src/app.rs
38
src/app.rs
|
|
@ -1,8 +1,9 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
use arboard::Clipboard;
|
use arboard::Clipboard;
|
||||||
use kludgine::app::{AppEvent, AsApplication};
|
use kludgine::app::{AppEvent, AsApplication, Monitors};
|
||||||
use parking_lot::{Mutex, MutexGuard};
|
use parking_lot::{Mutex, MutexGuard};
|
||||||
|
|
||||||
use crate::animation;
|
use crate::animation;
|
||||||
|
|
@ -30,6 +31,30 @@ impl PendingApp {
|
||||||
pub const fn cushy(&self) -> &Cushy {
|
pub const fn cushy(&self) -> &Cushy {
|
||||||
&self.cushy
|
&self.cushy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Executes `on_startup` once the application event loop has begun.
|
||||||
|
///
|
||||||
|
/// Some APIs are not available until after the application has started
|
||||||
|
/// running. For example, `App::monitors` requires the event loop to have
|
||||||
|
/// been started.
|
||||||
|
pub fn on_startup<F>(&mut self, on_startup: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut App) + Send + 'static,
|
||||||
|
{
|
||||||
|
let mut app = self.as_app();
|
||||||
|
self.app.on_startup(move |_app| {
|
||||||
|
// Accessing some information from this closure needs to use `_app`
|
||||||
|
// instead of `App`. For example, accessing monitor information
|
||||||
|
// requires the window thread to respond to a message. Trying to do
|
||||||
|
// that in this closure would cause the thread to block. So, we
|
||||||
|
// execute our on_startup callbacks in their own thread.
|
||||||
|
thread::spawn(move || {
|
||||||
|
let cushy = app.cushy.clone();
|
||||||
|
let _guard = cushy.enter_runtime();
|
||||||
|
on_startup(&mut app);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Run for PendingApp {
|
impl Run for PendingApp {
|
||||||
|
|
@ -293,6 +318,17 @@ pub struct App {
|
||||||
cushy: Cushy,
|
cushy: Cushy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl App {
|
||||||
|
/// Returns a snapshot of information about the monitors connected to this
|
||||||
|
/// device.
|
||||||
|
///
|
||||||
|
/// Returns None if the app is not currently running.
|
||||||
|
#[must_use]
|
||||||
|
pub fn monitors(&self) -> Option<Monitors> {
|
||||||
|
self.app.as_ref().and_then(kludgine::app::App::monitors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Application for App {
|
impl Application for App {
|
||||||
fn cushy(&self) -> &Cushy {
|
fn cushy(&self) -> &Cushy {
|
||||||
&self.cushy
|
&self.cushy
|
||||||
|
|
|
||||||
11
src/lib.rs
11
src/lib.rs
|
|
@ -45,6 +45,17 @@ pub use {figures, kludgine};
|
||||||
pub use self::graphics::Graphics;
|
pub use self::graphics::Graphics;
|
||||||
pub use self::tick::{InputState, Tick};
|
pub use self::tick::{InputState, Tick};
|
||||||
|
|
||||||
|
/// Starts running a Cushy application, invoking `app_init` after the event loop
|
||||||
|
/// has started.
|
||||||
|
pub fn run<F>(app_init: F) -> Result
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut App) + Send + 'static,
|
||||||
|
{
|
||||||
|
let mut app = PendingApp::default();
|
||||||
|
app.on_startup(app_init);
|
||||||
|
app.run()
|
||||||
|
}
|
||||||
|
|
||||||
/// A limit used when measuring a widget.
|
/// A limit used when measuring a widget.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
pub enum ConstraintLimit {
|
pub enum ConstraintLimit {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue