mirror of
https://github.com/danbulant/cushy
synced 2026-06-18 14:01:10 +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::transparent`
|
||||
- `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
|
||||
|
||||
|
|
|
|||
6
Cargo.lock
generated
6
Cargo.lock
generated
|
|
@ -124,8 +124,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
|||
[[package]]
|
||||
name = "appit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a158c9d2660ce603c741d513b44cdd97a4553e0749d4e49e45b9480fc72c162"
|
||||
source = "git+https://github.com/khonsulabs/appit#4cab6aedd10d179ed730397dc48ca6b23af6a431"
|
||||
dependencies = [
|
||||
"winit",
|
||||
]
|
||||
|
|
@ -1310,8 +1309,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
|||
[[package]]
|
||||
name = "kludgine"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bc8757e03860f7a9a15e9616060ed620a12500a61c9ff9b457cccfc5f20af1f"
|
||||
source = "git+https://github.com/khonsulabs/kludgine#a468845f84cbee812778f91fe55cf02716efebd8"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"alot",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ tokio = ["dep:tokio"]
|
|||
tokio-multi-thread = ["tokio", "tokio/rt-multi-thread"]
|
||||
|
||||
[dependencies]
|
||||
kludgine = { version = "0.10.0", features = ["app"] }
|
||||
kludgine = { git = "https://github.com/khonsulabs/kludgine", features = [
|
||||
"app",
|
||||
] }
|
||||
figures = { version = "0.4.0" }
|
||||
alot = "0.3"
|
||||
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::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
use arboard::Clipboard;
|
||||
use kludgine::app::{AppEvent, AsApplication};
|
||||
use kludgine::app::{AppEvent, AsApplication, Monitors};
|
||||
use parking_lot::{Mutex, MutexGuard};
|
||||
|
||||
use crate::animation;
|
||||
|
|
@ -30,6 +31,30 @@ impl PendingApp {
|
|||
pub const fn 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 {
|
||||
|
|
@ -293,6 +318,17 @@ pub struct App {
|
|||
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 {
|
||||
fn 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::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.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum ConstraintLimit {
|
||||
|
|
|
|||
Loading…
Reference in a new issue