ryanmcgrath/cacao

Wrap an external app to send messages to it

Opened this issue · 0 comments

Is it possible for an extension to an external app to control windows attached to an external window received from such app (so there is no cacao-created App, and the main Window is created from an external pointer)?

"Architecture":

  • external app with lua extensions (outside of my control)
  • lua extension
  • Rust library using your framework that attaches its own modal Window chiled to the main app's Window parent

I'd like to show some modal windows driven by the extension, there is a Swift tutorial on how to do that, but that tutorial relies on the fact that the main window parent is available to the extension-generated view, so there is a simple way to close the modal

private func closeWindow() {
  guard let sheetWindow = view.window else { return }
  sheetWindow.sheetParent?.endSheet(sheetWindow)
}

However, your library doesn't have this OO relationship and instead of references uses message passing, which are driven from the top-level App. But I don't have access to the app.

So what would be the best way to be able to close a modal attached to the main Window?

  • Add some extra method to the the external app that I could call to pass messages to the main Window? (is it possible?)
  • Try to somehow overcome the circular reference and store a reference to the Window in the modal so that WinDelegate on_cancel event can ask the main window to close the sheet?
  • create a new channel passing messages?
  • something much simpler and obvious I've missed?
  • so far I'm using a static thread-local window manager which can then be used inside modals
thread_local! {pub static WM:LazyCell<WinMgr> = LazyCell::new(|| {WinMgr::default()});}
#[derive(Default)] pub struct WinMgr {
  pub appxt:RwLock<Option<Window>>,
  pub modal:RwLock<Option<Window<MyModalWin>>>,}

A bit more detailed description of what I'm currently doing:

The app allows the lua extension to send a pointer to the Window to the Rust library:

LightUserData, equivalent to an unmanaged raw pointer

The Swift way to convert it to a window object is

nswin = Unmanaged<NSWindow>.fromOpaque(nsWindowPtr).takeUnretainedValue();

In Rust I get *mut c_void and convert it to cacao's Window like so:

  1. Convert pointer to ShareId
  fn get_win_id_objc(nswin_lua:&LuaLightUserData) -> Result<ShareId<Object>> {
    let ptr_r:*mut c_void	= nswin_lua.0;
    if ptr_r.is_null() {return Err(anyhow!("err"))}
    let ptr_objc:id = ptr_r.cast(); //type id = *mut Object;
    let win_id_objc:ShareId<Object> = unsafe{ ShareId::from_ptr(ptr_objc) };
    Ok(win_id_objc)
  }
let win_id_objc:ShareId<Object> = get_win_id_objc(&nswin_lua)?; //nswin_lua comes from the app API
  1. Create cacao's Window
let win_marta:Window = Window {objc:win_id_objc, delegate:None};

So far so good (unless there is some unsound pointer conversion), I can now use this Window to open a modal begin_sheet
But I can't close it :( since there is no message passing mechanism due to the fact that I don't create an App, and since the modal is the child of Window, I can't really get a reference to it either due to cyclical depndency