mirror of
https://github.com/obhq/obliteration.git
synced 2026-10-11 21:39:55 +00:00
Extracts handle and xdg_toplevel methods from WinitWindow into DesktopWindow (#1263)
This commit is contained in:
@@ -0,0 +1 @@
|
||||
*.svg binary
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
Obliteration is a free and open-source PlayStation 4 kernel rewritten in Rust. Our goal is not running on the PlayStation 4 but to run the dumped PlayStation 4 system software on Windows, Linux and macOS using a custom made virtualization stack optimized specifically for Obliteration.
|
||||
|
||||
<p align="center"><img alt="Architecture" src="architecture.svg"></p>
|
||||
|
||||
This project started as a hard-fork from [Kyty](https://github.com/InoriRus/Kyty). Then we decided to rewrite the whole project from scratch by using Kyty and [Uplift](https://github.com/idc/uplift) as a reference to help us getting started with the project.
|
||||
|
||||
Our ultimate goal is to become a permissive free and open-source operating system optimized for gaming that can run on a variety of hardware. The reason we want to built this because:
|
||||
@@ -21,7 +23,9 @@ The project logo and icon was designed by [VocalFan](https://github.com/VocalFan
|
||||
|
||||
## Status
|
||||
|
||||
Currently we cannot run any games yet. The reason it take so long is because we try to implement things without stubbing as much as possible.
|
||||
Currently we cannot run any games yet. What we have is a working [64-bit](https://en.wikipedia.org/wiki/Long_mode) kernel and the VMM to run it. The kernel has been successfully setup [GDT](https://en.wikipedia.org/wiki/Global_Descriptor_Table), [TSS](https://en.wikipedia.org/wiki/Task_state_segment), [IDT](https://en.wikipedia.org/wiki/Interrupt_descriptor_table) and [syscall](https://en.wikipedia.org/wiki/System_call) instruction. Right now we are working on [UMA](https://man.freebsd.org/cgi/man.cgi?query=uma) system. Once this finished we will start migrating code from our [legacy user-mode kernel](https://github.com/obhq/obliteration/tree/main/legacy/src) then execute `mini-syscore.elf`.
|
||||
|
||||
The reason it take so long is because we try to implement the kernel without stubbing as much as possible.
|
||||
|
||||
## Key features
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 130 KiB |
@@ -1,5 +1,6 @@
|
||||
use super::Metal;
|
||||
use crate::rt::{Hook, WindowHandler, WinitWindow};
|
||||
use crate::ui::DesktopWindow;
|
||||
use metal::{CAMetalLayer, MetalLayer};
|
||||
use objc::runtime::{Object, NO, YES};
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
@@ -56,11 +57,10 @@ impl WinitWindow for MetalWindow {
|
||||
fn id(&self) -> WindowId {
|
||||
self.window.id()
|
||||
}
|
||||
}
|
||||
|
||||
fn handle(&self) -> impl HasWindowHandle + '_
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
impl DesktopWindow for MetalWindow {
|
||||
fn handle(&self) -> impl HasWindowHandle + '_ {
|
||||
&self.window
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::engine::Vulkan;
|
||||
use super::GraphicsError;
|
||||
use crate::rt::{Hook, WindowHandler, WinitWindow};
|
||||
use crate::ui::DesktopWindow;
|
||||
use ash::vk::SurfaceKHR;
|
||||
use raw_window_handle::HasWindowHandle;
|
||||
use std::error::Error;
|
||||
@@ -50,11 +51,10 @@ impl WinitWindow for VulkanWindow {
|
||||
fn id(&self) -> WindowId {
|
||||
self.window.id()
|
||||
}
|
||||
}
|
||||
|
||||
fn handle(&self) -> impl HasWindowHandle + '_
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
impl DesktopWindow for VulkanWindow {
|
||||
fn handle(&self) -> impl HasWindowHandle + '_ {
|
||||
&self.window
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ use self::log::LogWriter;
|
||||
use self::profile::{DisplayResolution, Profile};
|
||||
use self::setup::{run_setup, SetupError};
|
||||
use self::ui::{
|
||||
DesktopWindow, MainWindow, ProfileModel, ResolutionModel, RuntimeExt, SlintBackend,
|
||||
DesktopExt, MainWindow, ProfileModel, ResolutionModel, RuntimeExt, SlintBackend,
|
||||
WaitForDebugger,
|
||||
};
|
||||
use self::vmm::{CpuError, Vmm, VmmError, VmmEvent};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use raw_window_handle::HasWindowHandle;
|
||||
use std::error::Error;
|
||||
use winit::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use winit::event::{DeviceId, ElementState, InnerSizeWriter, MouseButton};
|
||||
@@ -34,9 +33,4 @@ pub trait WindowHandler: WinitWindow {
|
||||
/// Provides method to return winit properties.
|
||||
pub trait WinitWindow {
|
||||
fn id(&self) -> WindowId;
|
||||
fn handle(&self) -> impl HasWindowHandle + '_
|
||||
where
|
||||
Self: Sized;
|
||||
#[cfg(target_os = "linux")]
|
||||
fn xdg_toplevel(&self) -> *mut std::ffi::c_void;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ use self::data::{read_data_root, write_data_root};
|
||||
use crate::data::{DataError, DataMgr};
|
||||
use crate::rt::yield_now;
|
||||
use crate::ui::{
|
||||
error, open_dir, open_file, spawn_handler, DesktopWindow, FileType, InstallFirmware,
|
||||
RuntimeExt, SetupWizard,
|
||||
error, open_dir, open_file, spawn_handler, DesktopExt, FileType, InstallFirmware, RuntimeExt,
|
||||
SetupWizard,
|
||||
};
|
||||
use crate::vfs::{FsType, FS_TYPE};
|
||||
use erdp::ErrorDisplay;
|
||||
|
||||
@@ -57,6 +57,10 @@ impl Window {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn winit(&self) -> &winit::window::Window {
|
||||
&self.winit
|
||||
}
|
||||
|
||||
pub fn hidden(&self) -> &Signal<()> {
|
||||
&self.hidden
|
||||
}
|
||||
@@ -66,20 +70,6 @@ impl WinitWindow for Window {
|
||||
fn id(&self) -> WindowId {
|
||||
self.winit.id()
|
||||
}
|
||||
|
||||
fn handle(&self) -> impl HasWindowHandle + '_
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
&self.winit
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn xdg_toplevel(&self) -> *mut std::ffi::c_void {
|
||||
use winit::platform::wayland::WindowExtWayland;
|
||||
|
||||
self.winit.xdg_toplevel()
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowHandler for Window {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::rt::{global, WinitWindow};
|
||||
use crate::ui::{FileType, SlintBackend};
|
||||
use crate::rt::global;
|
||||
use crate::ui::{DesktopWindow, FileType, SlintBackend};
|
||||
use ashpd::desktop::file_chooser::{FileFilter, SelectedFiles};
|
||||
use ashpd::desktop::ResponseError;
|
||||
use ashpd::WindowIdentifier;
|
||||
@@ -11,7 +11,7 @@ use wayland_client::protocol::wl_surface::WlSurface;
|
||||
use wayland_client::Proxy;
|
||||
use wayland_protocols::xdg::foreign::zv2::client::zxdg_exported_v2::ZxdgExportedV2;
|
||||
|
||||
pub async fn open_file<T: WinitWindow>(
|
||||
pub async fn open_file<T: DesktopWindow>(
|
||||
parent: &T,
|
||||
title: impl AsRef<str>,
|
||||
ty: FileType,
|
||||
@@ -46,7 +46,7 @@ pub async fn open_file<T: WinitWindow>(
|
||||
Some(resp.uris().first().unwrap().to_file_path().unwrap())
|
||||
}
|
||||
|
||||
pub async fn open_dir<T: WinitWindow>(parent: &T, title: impl AsRef<str>) -> Option<PathBuf> {
|
||||
pub async fn open_dir<T: DesktopWindow>(parent: &T, title: impl AsRef<str>) -> Option<PathBuf> {
|
||||
// Send the request
|
||||
let parent = get_parent_id(parent);
|
||||
let req = SelectedFiles::open_file()
|
||||
@@ -74,7 +74,7 @@ pub async fn open_dir<T: WinitWindow>(parent: &T, title: impl AsRef<str>) -> Opt
|
||||
|
||||
fn get_parent_id<P>(parent: &P) -> Parent
|
||||
where
|
||||
P: WinitWindow,
|
||||
P: DesktopWindow,
|
||||
{
|
||||
// Check window type.
|
||||
let parent = parent.handle();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
pub use self::dialogs::*;
|
||||
|
||||
use self::modal::Modal;
|
||||
use super::{DesktopWindow, SlintBackend};
|
||||
use crate::rt::{global, WinitWindow};
|
||||
use super::{DesktopExt, DesktopWindow, SlintBackend};
|
||||
use crate::rt::global;
|
||||
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -10,11 +10,11 @@ mod dialogs;
|
||||
mod modal;
|
||||
mod wayland;
|
||||
|
||||
impl<T: WinitWindow> DesktopWindow for T {
|
||||
impl<T: DesktopWindow> DesktopExt for T {
|
||||
type Modal<'a, P>
|
||||
= Modal<'a, Self, P>
|
||||
where
|
||||
P: WinitWindow + 'a;
|
||||
P: DesktopWindow + 'a;
|
||||
|
||||
fn set_center(&self) -> Result<(), PlatformError> {
|
||||
let win = self.handle();
|
||||
@@ -33,7 +33,7 @@ impl<T: WinitWindow> DesktopWindow for T {
|
||||
|
||||
fn set_modal<P>(self, parent: &P) -> Result<Modal<Self, P>, PlatformError>
|
||||
where
|
||||
P: WinitWindow,
|
||||
P: DesktopWindow,
|
||||
Self: Sized,
|
||||
{
|
||||
let back = global::<SlintBackend>().unwrap();
|
||||
@@ -49,7 +49,7 @@ impl<T: WinitWindow> DesktopWindow for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// Linux-specific error for [`PlatformExt`].
|
||||
/// Linux-specific error for [`DesktopExt`].
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PlatformError {
|
||||
#[error("couldn't create xdg_dialog_v1")]
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use crate::rt::{block, Blocker, WinitWindow};
|
||||
use crate::rt::{block, Blocker};
|
||||
use crate::ui::DesktopWindow;
|
||||
use std::ops::Deref;
|
||||
use wayland_protocols::xdg::dialog::v1::client::xdg_dialog_v1::XdgDialogV1;
|
||||
|
||||
/// Encapsulates a modal window and its parent.
|
||||
///
|
||||
/// This struct forces the modal window to be dropped before its parent.
|
||||
pub struct Modal<'a, W, P: WinitWindow> {
|
||||
pub struct Modal<'a, W, P: DesktopWindow> {
|
||||
window: W,
|
||||
wayland: Option<XdgDialogV1>,
|
||||
#[allow(dead_code)]
|
||||
blocker: Blocker<'a, P>,
|
||||
}
|
||||
|
||||
impl<'a, W, P: WinitWindow> Modal<'a, W, P> {
|
||||
impl<'a, W, P: DesktopWindow> Modal<'a, W, P> {
|
||||
pub fn new(window: W, parent: &'a P, wayland: Option<XdgDialogV1>) -> Self {
|
||||
Self {
|
||||
window,
|
||||
@@ -22,7 +23,7 @@ impl<'a, W, P: WinitWindow> Modal<'a, W, P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W, P: WinitWindow> Drop for Modal<'a, W, P> {
|
||||
impl<'a, W, P: DesktopWindow> Drop for Modal<'a, W, P> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(v) = self.wayland.take() {
|
||||
v.destroy();
|
||||
@@ -30,7 +31,7 @@ impl<'a, W, P: WinitWindow> Drop for Modal<'a, W, P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W, P: WinitWindow> Deref for Modal<'a, W, P> {
|
||||
impl<'a, W, P: DesktopWindow> Deref for Modal<'a, W, P> {
|
||||
type Target = W;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use super::PlatformError;
|
||||
use crate::rt::WinitWindow;
|
||||
use crate::ui::Wayland;
|
||||
use crate::ui::{DesktopWindow, Wayland};
|
||||
use wayland_backend::sys::client::ObjectId;
|
||||
use wayland_client::Proxy;
|
||||
use wayland_protocols::xdg::dialog::v1::client::xdg_dialog_v1::XdgDialogV1;
|
||||
@@ -10,8 +9,8 @@ use wayland_protocols::xdg::shell::client::xdg_toplevel::XdgToplevel;
|
||||
/// `parent` must outlive `target`.
|
||||
pub unsafe fn set_modal(
|
||||
wayland: &Wayland,
|
||||
target: &impl WinitWindow,
|
||||
parent: &impl WinitWindow,
|
||||
target: &impl DesktopWindow,
|
||||
parent: &impl DesktopWindow,
|
||||
) -> Result<XdgDialogV1, PlatformError> {
|
||||
// Get xdg_toplevel for parent.
|
||||
let mut queue = wayland.queue().borrow_mut();
|
||||
@@ -40,7 +39,7 @@ pub unsafe fn set_modal(
|
||||
|
||||
/// # Safety
|
||||
/// `win` must outlive the returned [`XdgToplevel`].
|
||||
unsafe fn get_xdg_toplevel(wayland: &Wayland, win: &impl WinitWindow) -> XdgToplevel {
|
||||
unsafe fn get_xdg_toplevel(wayland: &Wayland, win: &impl DesktopWindow) -> XdgToplevel {
|
||||
let obj = win.xdg_toplevel();
|
||||
let obj = ObjectId::from_ptr(XdgToplevel::interface(), obj.cast()).unwrap();
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::rt::WinitWindow;
|
||||
use crate::ui::FileType;
|
||||
use crate::ui::{DesktopWindow, FileType};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub async fn open_file<T: WinitWindow>(
|
||||
pub async fn open_file<T: DesktopWindow>(
|
||||
parent: &T,
|
||||
title: impl AsRef<str>,
|
||||
ty: FileType,
|
||||
@@ -10,6 +9,6 @@ pub async fn open_file<T: WinitWindow>(
|
||||
todo!();
|
||||
}
|
||||
|
||||
pub async fn open_dir<T: WinitWindow>(parent: &T, title: impl AsRef<str>) -> Option<PathBuf> {
|
||||
pub async fn open_dir<T: DesktopWindow>(parent: &T, title: impl AsRef<str>) -> Option<PathBuf> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@ pub use self::dialogs::*;
|
||||
|
||||
use self::modal::Modal;
|
||||
use self::view::with_window;
|
||||
use super::DesktopWindow;
|
||||
use crate::rt::WinitWindow;
|
||||
use super::{DesktopExt, DesktopWindow};
|
||||
use block::ConcreteBlock;
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
use std::ffi::c_long;
|
||||
@@ -14,11 +13,11 @@ mod dialogs;
|
||||
mod modal;
|
||||
mod view;
|
||||
|
||||
impl<T: WinitWindow> DesktopWindow for T {
|
||||
impl<T: DesktopWindow> DesktopExt for T {
|
||||
type Modal<'a, P>
|
||||
= Modal<'a, Self, P>
|
||||
where
|
||||
P: WinitWindow + 'a;
|
||||
P: DesktopWindow + 'a;
|
||||
|
||||
fn set_center(&self) -> Result<(), PlatformError> {
|
||||
with_window::<()>(self.handle(), |win| unsafe { msg_send![win, center] });
|
||||
@@ -28,7 +27,7 @@ impl<T: WinitWindow> DesktopWindow for T {
|
||||
|
||||
fn set_modal<P>(self, parent: &P) -> Result<Modal<Self, P>, PlatformError>
|
||||
where
|
||||
P: WinitWindow,
|
||||
P: DesktopWindow,
|
||||
Self: Sized,
|
||||
{
|
||||
// Setup completionHandler.
|
||||
@@ -45,6 +44,6 @@ impl<T: WinitWindow> DesktopWindow for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// macOS-specific error for [`DesktopWindow`].
|
||||
/// macOS-specific error for [`DesktopExt`].
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PlatformError {}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
use crate::rt::{block, Blocker, WinitWindow};
|
||||
use crate::rt::{block, Blocker};
|
||||
use crate::ui::DesktopWindow;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// Encapsulates a modal window and its parent.
|
||||
///
|
||||
/// This struct forces the modal window to be dropped before its parent.
|
||||
pub struct Modal<'a, W, P: WinitWindow> {
|
||||
pub struct Modal<'a, W, P: DesktopWindow> {
|
||||
window: W,
|
||||
#[allow(dead_code)]
|
||||
blocker: Blocker<'a, P>,
|
||||
}
|
||||
|
||||
impl<'a, W, P: WinitWindow> Modal<'a, W, P> {
|
||||
impl<'a, W, P: DesktopWindow> Modal<'a, W, P> {
|
||||
pub(super) fn new(window: W, parent: &'a P) -> Self {
|
||||
Self {
|
||||
window,
|
||||
@@ -19,7 +20,7 @@ impl<'a, W, P: WinitWindow> Modal<'a, W, P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W, P: WinitWindow> Deref for Modal<'a, W, P> {
|
||||
impl<'a, W, P: DesktopWindow> Deref for Modal<'a, W, P> {
|
||||
type Target = W;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
||||
+20
-7
@@ -31,7 +31,7 @@ where
|
||||
spawn_blocker(w, f);
|
||||
}
|
||||
|
||||
pub async fn error<P: WinitWindow>(parent: Option<&P>, msg: impl Into<SharedString>) {
|
||||
pub async fn error<P: DesktopWindow>(parent: Option<&P>, msg: impl Into<SharedString>) {
|
||||
let win = ErrorWindow::new().unwrap();
|
||||
|
||||
win.set_message(msg.into());
|
||||
@@ -55,27 +55,40 @@ pub async fn error<P: WinitWindow>(parent: Option<&P>, msg: impl Into<SharedStri
|
||||
impl<T: ComponentHandle> WinitWindow for T {
|
||||
fn id(&self) -> WindowId {
|
||||
let win = WindowInner::from_pub(self.window()).window_adapter();
|
||||
let win = Window::from_adapter(win.as_ref());
|
||||
|
||||
Window::from_adapter(win.as_ref()).id()
|
||||
win.id()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ComponentHandle> DesktopWindow for T {
|
||||
fn handle(&self) -> impl HasWindowHandle + '_ {
|
||||
self.window().window_handle()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn xdg_toplevel(&self) -> *mut std::ffi::c_void {
|
||||
let win = WindowInner::from_pub(self.window()).window_adapter();
|
||||
use winit::platform::wayland::WindowExtWayland;
|
||||
|
||||
Window::from_adapter(win.as_ref()).xdg_toplevel()
|
||||
let win = WindowInner::from_pub(self.window()).window_adapter();
|
||||
let win = Window::from_adapter(win.as_ref());
|
||||
|
||||
win.winit().xdg_toplevel()
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides methods to operate on a desktop window.
|
||||
/// Provides methods to return platform-specific handle for a desktop window.
|
||||
pub trait DesktopWindow: WinitWindow {
|
||||
fn handle(&self) -> impl HasWindowHandle + '_;
|
||||
#[cfg(target_os = "linux")]
|
||||
fn xdg_toplevel(&self) -> *mut std::ffi::c_void;
|
||||
}
|
||||
|
||||
/// Provides methods to operate on a [`DesktopWindow`].
|
||||
pub trait DesktopExt: DesktopWindow {
|
||||
type Modal<'a, P>: Deref<Target = Self>
|
||||
where
|
||||
P: WinitWindow + 'a;
|
||||
P: DesktopWindow + 'a;
|
||||
|
||||
/// Center window on the screen.
|
||||
///
|
||||
@@ -84,7 +97,7 @@ pub trait DesktopWindow: WinitWindow {
|
||||
fn set_center(&self) -> Result<(), PlatformError>;
|
||||
fn set_modal<P>(self, parent: &P) -> Result<Self::Modal<'_, P>, PlatformError>
|
||||
where
|
||||
P: WinitWindow,
|
||||
P: DesktopWindow,
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::rt::WinitWindow;
|
||||
use crate::ui::FileType;
|
||||
use crate::ui::{DesktopWindow, FileType};
|
||||
use futures::channel::oneshot;
|
||||
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
|
||||
use std::future::Future;
|
||||
@@ -11,31 +10,7 @@ use windows_sys::Win32::UI::Shell::{
|
||||
SHBrowseForFolderW, SHGetPathFromIDListW, BIF_NEWDIALOGSTYLE, BIF_RETURNONLYFSDIRS, BROWSEINFOW,
|
||||
};
|
||||
|
||||
fn get_hwnd<T: WinitWindow>(parent: &T) -> NonZero<isize> {
|
||||
let parent = parent.handle();
|
||||
let parent = parent.window_handle().unwrap();
|
||||
let RawWindowHandle::Win32(win) = parent.as_ref() else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
win.hwnd
|
||||
}
|
||||
|
||||
fn spawn_dialog<F>(dialog_fn: F) -> impl Future<Output = Option<PathBuf>>
|
||||
where
|
||||
F: Send + 'static + FnOnce() -> Option<PathBuf>,
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let res = dialog_fn();
|
||||
tx.send(res).unwrap();
|
||||
});
|
||||
|
||||
async move { rx.await.unwrap_or(None) }
|
||||
}
|
||||
|
||||
pub async fn open_file<T: WinitWindow>(
|
||||
pub async fn open_file<T: DesktopWindow>(
|
||||
parent: &T,
|
||||
title: impl AsRef<str>,
|
||||
ty: FileType,
|
||||
@@ -43,7 +18,7 @@ pub async fn open_file<T: WinitWindow>(
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn open_dir<T: WinitWindow>(parent: &T, title: impl AsRef<str>) -> Option<PathBuf> {
|
||||
pub async fn open_dir<T: DesktopWindow>(parent: &T, title: impl AsRef<str>) -> Option<PathBuf> {
|
||||
let hwnd = get_hwnd(parent);
|
||||
|
||||
let title_wide: Vec<u16> = title
|
||||
@@ -81,3 +56,27 @@ pub async fn open_dir<T: WinitWindow>(parent: &T, title: impl AsRef<str>) -> Opt
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
fn get_hwnd<T: DesktopWindow>(parent: &T) -> NonZero<isize> {
|
||||
let parent = parent.handle();
|
||||
let parent = parent.window_handle().unwrap();
|
||||
let RawWindowHandle::Win32(win) = parent.as_ref() else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
win.hwnd
|
||||
}
|
||||
|
||||
fn spawn_dialog<F>(dialog_fn: F) -> impl Future<Output = Option<PathBuf>>
|
||||
where
|
||||
F: Send + 'static + FnOnce() -> Option<PathBuf>,
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let res = dialog_fn();
|
||||
tx.send(res).unwrap();
|
||||
});
|
||||
|
||||
async move { rx.await.unwrap_or(None) }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
pub use self::dialogs::*;
|
||||
|
||||
use self::modal::Modal;
|
||||
use super::DesktopWindow;
|
||||
use crate::rt::WinitWindow;
|
||||
use super::{DesktopExt, DesktopWindow};
|
||||
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
|
||||
use std::io::Error;
|
||||
use std::mem::zeroed;
|
||||
@@ -16,11 +15,11 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
mod dialogs;
|
||||
mod modal;
|
||||
|
||||
impl<T: WinitWindow> DesktopWindow for T {
|
||||
impl<T: DesktopWindow> DesktopExt for T {
|
||||
type Modal<'a, P>
|
||||
= Modal<'a, Self, P>
|
||||
where
|
||||
P: WinitWindow + 'a;
|
||||
P: DesktopWindow + 'a;
|
||||
|
||||
fn set_center(&self) -> Result<(), PlatformError> {
|
||||
// Get HWND.
|
||||
@@ -69,14 +68,14 @@ impl<T: WinitWindow> DesktopWindow for T {
|
||||
|
||||
fn set_modal<P>(self, parent: &P) -> Result<Modal<Self, P>, PlatformError>
|
||||
where
|
||||
P: WinitWindow,
|
||||
P: DesktopWindow,
|
||||
Self: Sized,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Windows-specific error for [`DesktopWindow`].
|
||||
/// Windows-specific error for [`DesktopExt`].
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PlatformError {
|
||||
#[error("couldn't get window rectangle")]
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
use crate::rt::{block, Blocker, WinitWindow};
|
||||
use crate::rt::{block, Blocker};
|
||||
use crate::ui::DesktopWindow;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// Encapsulates a modal window and its parent.
|
||||
///
|
||||
/// This struct forces the modal window to be dropped before its parent.
|
||||
pub struct Modal<'a, W, P: WinitWindow> {
|
||||
pub struct Modal<'a, W, P: DesktopWindow> {
|
||||
window: W,
|
||||
#[allow(dead_code)]
|
||||
blocker: Blocker<'a, P>,
|
||||
}
|
||||
|
||||
impl<'a, W, P: WinitWindow> Modal<'a, W, P> {
|
||||
impl<'a, W, P: DesktopWindow> Modal<'a, W, P> {
|
||||
pub(super) fn new(window: W, parent: &'a P) -> Self {
|
||||
Self {
|
||||
window,
|
||||
@@ -19,7 +20,7 @@ impl<'a, W, P: WinitWindow> Modal<'a, W, P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W, P: WinitWindow> Deref for Modal<'a, W, P> {
|
||||
impl<'a, W, P: DesktopWindow> Deref for Modal<'a, W, P> {
|
||||
type Target = W;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
||||
Reference in New Issue
Block a user