Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ winio-ui-gtk = { path = "winio-ui-gtk", version = "0.5.0" }
winio-ui-qt = { path = "winio-ui-qt", version = "0.5.0" }
winio-ui-app-kit = { path = "winio-ui-app-kit", version = "0.5.0" }

compio = { version = "0.18.0", default-features = false }
compio-runtime = "0.11.0"
compio = { version = "0.19.0-rc.1", default-features = false }
compio-log = "0.1.0"

bitflags = "2"
Expand Down
8 changes: 4 additions & 4 deletions winio-layout/src/stack_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ impl<'a, E> StackPanel<'a, E> {
style.size.width = match child.width {
Some(w) => length(w as f32),
None => match (self.orient, child.halign, child.grow) {
(Orient::Vertical, HAlign::Stretch, _) => percent(1.0),
(Orient::Vertical, HAlign::Stretch, _) => percent(1.0f32),
(Orient::Horizontal, _, true) => auto(),
_ => length(preferred_size.width as f32),
},
};
style.size.height = match child.height {
Some(h) => length(h as f32),
None => match (self.orient, child.valign, child.grow) {
(Orient::Horizontal, VAlign::Stretch, _) => percent(1.0),
(Orient::Horizontal, VAlign::Stretch, _) => percent(1.0f32),
(Orient::Vertical, _, true) => auto(),
_ => length(preferred_size.height as f32),
},
Expand Down Expand Up @@ -90,14 +90,14 @@ impl<'a, E> StackPanel<'a, E> {
}
}
if child.grow {
style.flex_grow = 1.0
style.flex_grow = 1.0f32
}
let node = tree.new_leaf(style)?;
nodes.push(node);
}
let root = tree.new_with_children(
Style {
size: taffy::Size::from_percent(1.0, 1.0),
size: taffy::Size::from_percent(1.0f32, 1.0f32),
flex_direction: match self.orient {
Orient::Horizontal => taffy::FlexDirection::Row,
Orient::Vertical => taffy::FlexDirection::Column,
Expand Down
5 changes: 4 additions & 1 deletion winio-pollable/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ license = { workspace = true }
repository = { workspace = true }

[dependencies]
compio = { workspace = true, features = ["runtime"], public = true }
compio = { workspace = true, features = ["runtime"] }

futures-util = { workspace = true }
scoped-tls = { workspace = true }

[target.'cfg(target_os = "linux")'.dependencies]
rustix = { version = "1", features = ["event"] }
105 changes: 87 additions & 18 deletions winio-pollable/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,21 @@
#[cfg(target_os = "linux")]
use std::os::fd::OwnedFd;
use std::{
cell::RefCell,
future::Future,
io,
ops::{Deref, DerefMut},
pin::Pin,
sync::Arc,
task::{Context, Poll, Waker},
time::Duration,
};

use compio::driver::{AsRawFd, RawFd};
use compio::{
driver::{AsRawFd, RawFd},
runtime::OptWaker,
};
use futures_util::FutureExt;

/// See [`Runtime`]
///
Expand Down Expand Up @@ -70,11 +78,16 @@ impl Runtime {
}

impl Runtime {
/// Run the scheduled tasks.
pub fn run(&self) -> bool {
self.runtime.run() | MAIN_TASK.with(|task| task.poll())
Comment thread
Berrysoft marked this conversation as resolved.
Outdated
}

/// Poll the runtime. Returns the next timeout.
pub fn poll_and_run(&self) -> Option<Duration> {
self.runtime.poll_with(Some(Duration::ZERO));

let remaining_tasks = self.runtime.run();
let remaining_tasks = self.run();

if remaining_tasks {
Some(Duration::ZERO)
Expand All @@ -83,25 +96,37 @@ impl Runtime {
}
}

/// Set the current main task and wait for it's completion.
Comment thread
Berrysoft marked this conversation as resolved.
Outdated
pub fn enter_block_on<F: Future<Output = ()>, T>(&self, future: F, f: impl FnOnce() -> T) -> T {
let opt_waker = self.runtime.opt_waker();
let task = unsafe { MainTask::new(future, opt_waker) };
MAIN_TASK.set(&task, f)
}

/// Block on the future till it completes. Users should enter the runtime
/// before calling this function, and poll the runtime themselves.
pub fn block_on<F: Future>(&self, future: F, poll: impl Fn(Option<Duration>)) -> F::Output {
let mut result = None;
unsafe {
self.runtime
.spawn_unchecked(async { result = Some(future.await) })
}
.detach();
loop {
let timeout = self.poll_and_run();
if let Some(result) = result.take() {
break result;
}

poll(timeout);

self.clear().ok();
}
let result = RefCell::new(None);

self.enter_block_on(
async {
let res = Some(future.await);
result.replace(res);
},
|| {
loop {
let timeout = self.poll_and_run();

if let Some(result) = result.take() {
break result;
}

poll(timeout);

self.clear().ok();
}
},
)
}
}

Expand Down Expand Up @@ -134,3 +159,47 @@ impl AsRawFd for Runtime {
}
}
}

struct MainTask {
future: RefCell<Pin<Box<dyn Future<Output = ()>>>>,
opt_waker: Arc<OptWaker>,
waker: Waker,
}

unsafe fn reduce_lifetime<'a>(
future: impl Future<Output = ()> + 'a,
) -> Pin<Box<dyn Future<Output = ()> + 'static>> {
let future = Box::pin(future) as Pin<Box<dyn Future<Output = ()> + 'a>>;
unsafe {
std::mem::transmute::<
Pin<Box<dyn Future<Output = ()> + 'a>>,
Pin<Box<dyn Future<Output = ()> + 'static>>,
>(future)
}
}
Comment thread
Berrysoft marked this conversation as resolved.

impl MainTask {
pub unsafe fn new(future: impl Future<Output = ()>, opt_waker: Arc<OptWaker>) -> Self {
let waker = Waker::from(opt_waker.clone());
Self {
future: RefCell::new(unsafe { reduce_lifetime(future.fuse()) }),
opt_waker,
waker,
}
}

pub fn poll(&self) -> bool {
let mut cx = Context::from_waker(&self.waker);
if let Ok(mut fut) = self.future.try_borrow_mut() {
if let Poll::Ready(()) = fut.as_mut().poll(&mut cx) {
true
Comment thread
Berrysoft marked this conversation as resolved.
} else {
self.opt_waker.reset()
}
} else {
false
}
}
}

scoped_tls::scoped_thread_local!(static MAIN_TASK: MainTask);
58 changes: 28 additions & 30 deletions winio-ui-win32/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,36 +141,36 @@ impl Runtime {
}

pub fn block_on<F: Future>(&self, future: F) -> F::Output {
let result = RefCell::new(None);
let future = async {
let res = future.await;
unsafe { PostQuitMessage(0) };
result.replace(Some(res));
};
self.enter(|| {
let mut result = None;
unsafe {
self.runtime.spawn_unchecked(async {
result = Some(future.await);
PostQuitMessage(0);
})
}
.detach();

loop {
let mut msg = MaybeUninit::uninit();
let res = unsafe { self.runtime.get_message(msg.as_mut_ptr(), null_mut(), 0, 0) };
if res > 0 {
let msg = unsafe { msg.assume_init() };
unsafe {
let root = GetAncestor(msg.hwnd, GA_ROOT);
let handled = !root.is_null() && (IsDialogMessageW(root, &msg) != 0);
if !handled {
TranslateMessage(&msg);
DispatchMessageW(&msg);
self.runtime.enter_block_on(future, || {
loop {
let mut msg = MaybeUninit::uninit();
let res =
unsafe { self.runtime.get_message(msg.as_mut_ptr(), null_mut(), 0, 0) };
if res > 0 {
let msg = unsafe { msg.assume_init() };
unsafe {
let root = GetAncestor(msg.hwnd, GA_ROOT);
let handled = !root.is_null() && (IsDialogMessageW(root, &msg) != 0);
if !handled {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
} else if res == 0 {
debug!("Received WM_QUIT");
break result.take().expect("received WM_QUIT but no result");
} else {
panic!("MsgWaitForMultipleObjectsEx: {:?}", Error::from_thread());
}
} else if res == 0 {
debug!("Received WM_QUIT");
break result.take().expect("received WM_QUIT but no result");
} else {
panic!("MsgWaitForMultipleObjectsEx: {:?}", Error::from_thread());
}
}
})
})
}

Expand Down Expand Up @@ -291,10 +291,8 @@ pub(crate) unsafe extern "system" fn window_proc(
return control_color_static(hwnd, hdc);
}
},
WM_CTLCOLORBTN => {
if is_dark_mode_allowed_for_app() {
return unsafe { GetStockObject(BLACK_BRUSH) as _ };
}
WM_CTLCOLORBTN if is_dark_mode_allowed_for_app() => {
return unsafe { GetStockObject(BLACK_BRUSH) as _ };
}
WM_CTLCOLOREDIT | WM_CTLCOLORLISTBOX => {
if let Some(res) = unsafe { control_color_edit(handle, lparam as HWND, wparam as HDC) }
Expand Down
8 changes: 3 additions & 5 deletions winio-ui-win32/src/ui/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,9 @@ unsafe extern "system" fn multiline_edit_wnd_proc(
WM_GETDLGCODE => {
res &= !(DLGC_WANTALLKEYS as isize);
}
WM_KEYUP => {
if wparam == VK_RETURN as _ {
const RETURN_TEXT: *const u16 = w!("\r\n");
unsafe { DefSubclassProc(hwnd, EM_REPLACESEL, 1, RETURN_TEXT as _) };
}
WM_KEYUP if wparam == VK_RETURN as _ => {
const RETURN_TEXT: *const u16 = w!("\r\n");
unsafe { DefSubclassProc(hwnd, EM_REPLACESEL, 1, RETURN_TEXT as _) };
}
_ => {}
}
Expand Down
14 changes: 5 additions & 9 deletions winio-ui-windows-common/src/darkmode/hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,11 +481,9 @@ unsafe extern "system" fn dark_draw_theme_background_ex(
&& let Some((_, ty)) = HTHEME_MAP.lock().unwrap().get(&htheme)
{
match ty {
ThemeType::Progress => {
if ipartid == PP_TRANSPARENTBAR {
unsafe { FillRect(hdc, prect, DLG_GRAY_BACK.0) };
return S_OK;
}
ThemeType::Progress if ipartid == PP_TRANSPARENTBAR => {
unsafe { FillRect(hdc, prect, DLG_GRAY_BACK.0) };
return S_OK;
}
ThemeType::Tab => match ipartid {
TABP_TABITEM
Expand Down Expand Up @@ -729,10 +727,8 @@ unsafe extern "system" fn task_dialog_subclass(
error!("task_dialog_refresh: {_e:?}");
}
}
WM_CTLCOLORDLG => {
if is_dark_mode_allowed_for_app() {
return DLG_DARK_BACK.0 as _;
}
WM_CTLCOLORDLG if is_dark_mode_allowed_for_app() => {
return DLG_DARK_BACK.0 as _;
}
_ => {}
}
Expand Down
15 changes: 10 additions & 5 deletions winio-ui-windows-common/src/filebox.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{panic::resume_unwind, path::PathBuf};
use std::path::PathBuf;

use compio::runtime::ResumeUnwind;
use widestring::{U16CStr, U16CString};
use windows::{
Win32::{
Expand Down Expand Up @@ -65,7 +66,8 @@ impl FileBox {
.result()
})
.await
.unwrap_or_else(|e| resume_unwind(e))
.resume_unwind()
.expect("task cancelled")
}

pub async fn open_multiple(self, parent: Option<impl AsWindow>) -> Result<Vec<PathBuf>> {
Expand All @@ -86,7 +88,8 @@ impl FileBox {
.results()
})
.await
.unwrap_or_else(|e| resume_unwind(e))
.resume_unwind()
.expect("task cancelled")
}

pub async fn open_folder(self, parent: Option<impl AsWindow>) -> Result<Option<PathBuf>> {
Expand All @@ -107,7 +110,8 @@ impl FileBox {
.result()
})
.await
.unwrap_or_else(|e| resume_unwind(e))
.resume_unwind()
.expect("task cancelled")
}

pub async fn save(self, parent: Option<impl AsWindow>) -> Result<Option<PathBuf>> {
Expand All @@ -128,7 +132,8 @@ impl FileBox {
.result()
})
.await
.unwrap_or_else(|e| resume_unwind(e))
.resume_unwind()
.expect("task cancelled")
}
}

Expand Down
9 changes: 4 additions & 5 deletions winio-ui-windows-common/src/msgbox.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::{
panic::resume_unwind,
ptr::{null, null_mut},
};
use std::ptr::{null, null_mut};

use compio::runtime::ResumeUnwind;
use widestring::U16CString;
use windows::core::HRESULT;
use windows_sys::Win32::{
Expand Down Expand Up @@ -84,7 +82,8 @@ async fn msgbox(
(res, result)
})
.await
.unwrap_or_else(|e| resume_unwind(e));
.resume_unwind()
.expect("task cancelled");

if res >= 0 {
let res = match result {
Expand Down
3 changes: 1 addition & 2 deletions winio-ui-winui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ winio-handle = { workspace = true, features = ["winui"] }
winio-callback = { workspace = true }
winio-ui-windows-common = { workspace = true, features = ["winui"] }

compio = { workspace = true }
compio-runtime = { workspace = true, features = ["notify-always"] }
compio = { workspace = true, features = ["notify-always"] }
compio-log = { workspace = true }

image = { workspace = true }
Expand Down
Loading
Loading