-
Notifications
You must be signed in to change notification settings - Fork 913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for creating child windows #159
Comments
@Boscop I can successfully do this on mac os, using cocoa-rs, but haven't started on winit yet, just making raw cocoa framework calls at the moment. Can we share knowledge? I've come to similar conclusions - PR on winit to accept child windows + conrod is the best way to get all of this going. |
fwiw, this functionality isn't that niche: |
Rust sciter has it too. |
Can winit give us some official stance on this? Many of us at the rust-dsp group have had hacked/forked versions of winit for a while now to get this going but it's become very tiresome keeping up with the changes. If winit is willing to accept a "parent" functionality, could you provide us with some kind of api guideline (eg. what the calls should look like, an interface) and we will PR the feature. I think the main point of confusion for us is not knowing if it's worth the trouble of PR-ing, if it is unlikely to be wanted by the winit project. I'll put the time into the mac side (I've already done it many times before for previous winit versions, though the latest makes it more complicated). What do you guys think? |
Yes, I would like to have this in winit itself.. |
I don't see any reason why this wouldn't be accepted, so long as it doesn't cause issues with the existing functionality/ergonomics or have a prohibitive hit on complexity/maintainability. I'd even be willing to implement this on X11, time permitting. As far as what the API should be, that's hard to determine without me knowing what's required. Since both of you understand what you need, that's a good starting point to work with. Once it's implemented, we'll know exactly how things differ between platforms, and what impact the implementation has on existing structure. From there, it would be much easier to develop an effective interface than it would be to try to develop one now. In the short term, I should mention there's a caveat here. We have a shortage of reviewers, so depending on how extensive/intrusive the changes would be, it could take a while to get them merged. |
Given it's quite a bit of work, I'd really want someone to weigh in with merge permissions before we started this. If the project slips too far, particularly eyeing off PR #237 then the entire codebase changes significantly and we'd basically have to start again. I think the safest way to do this is to bypass any kind of Builder pattern and just request a Window object directly from the Window class, supplying a handle as a c_void pointer. The problem with supplying builder objects is that a lot of it becomes kind of redundant. Setup stuff isn't required as the window is already constructed and has attributes. The other primary issue with winit is the way the mac codebase will implement Drop to free up the pointer to the window after the window closes. This is not desired at all and is too heavy handed for any applications wishing to just 'attach' to an unowned window. It will crash any host software you're trying to run under. This may be a radical suggestion - but is winit actually becoming too complicated? Window creation and event loop management are so opinionated but separate that combining them in my opinion is creating a fairly bloated little environment. I know this might be the wrong place to raise this point, but to me, this whole issue being so complicated is a code smell of a god-problem with the library - it knows and controls a little too much and it doesn't really have to. |
@RobSaunders well, I do have merge permissions. You can wait for someone else if you'd like, but I have the most free time. I've been thinking more about this, and no real guarantees can be made about whether or not a PR that doesn't exist yet will be merged. You're giving me the impression that the changes required are quite substantial (the more you elaborate on this, the easier it is to for an assessment to be made). If it were merged, would you be around to fix any regressions reported, and advise other contributors about how to understand the new code if needed, including on how to rebase existing PRs? Bypassing the builder makes sense, right. As far as For your decoupling suggestion, I'd recommend creating a thorough proposal about 1) the intended API, 2) the implementation/architectural changes required, and 3) the pros and cons for both all users (but especially the average user) and for maintainers/contributors (basically, the impact it would have on Rust's graphical application story as a whole). |
@francesca64 perfect! That's basically what I was asking, without trying to be rude :) thank you for putting the time into this issue. The rust-dsp community (https://github.com/rust-dsp) reeeeally want this merged as it's kind of halting a lot of progress for us as we continually attempt to re-invent the wheel for a graphics solution, so I hope I'm portraying this correctly, but I want to be as explicit and honest as possible about what's required. The scope of the issue is primarily hampered by the assumptions winit makes about windows you'll be managing, mainly on the MacOS side though. The Linux and Windows sides seem to be a much more straightforward implementation. This is because MacOS's event delegation system creates more choices for how to 'listen' to events, and because MacOS has an ARC for any created objects which must be catered for. I don't foresee huge problems as long as we can bypass Builder and somehow remove the automatic ability to nuke the window (and call NSApp:terminate). A simple unowned_window parameter could alert winit to treat the contexts it does not own as read-only. Fundamentally, I agree that we would not want to change winit in a way that any user not desiring these features would even notice they are there. Just quickly on the last point about decoupling. I would foresee a library that concentrates purely on window generation, which winit could then depend upon. So users of winit would be completely unaware, but perhaps users like us would be able to interact with the smaller module directly. This last point may actually solve both of our problems and also allow for new plugin/host architecture systems to use winit. For example, I could use a library that sits on top of this window library that wraps the window in a WebKit or WebView control (depending on OS) and rely on the smaller library purely for window generation, which as of now I have to roll my own and understand how the Rust/FFI/ObjC bridge works - I've gone this route and it is HEAVY learning, no normal user would want to do this. Winit "takes over" so you can't do the above scenario at all, and then it provides an event loop that I have ZERO use for as these subsystems have their own eventing and callbacks. Or, I could introduce a library that purely, for example, wraps some MacOS control such as a NSTimer or system control, and users could bundle together the support they needed to build a simple app without having to drag around the event management stuff of winit. The winit system has chosen to abstract away events for a good reason - it becomes platform agnostic even to game systems like OpenGL, which is where it is most useful. But for regular desktop use or libraries that don't wish to go down this path, there's really no options in rust-land for them and it's holding them back in my opinion. But again, even if the project were split out, I think users of winit should be largely unaffected as winit would just rely on this lib. |
@RobSaunders alright, There are some pending API changes / reworks to be mindful of:
On the decoupling issue, I can definitely see the merits in the idea. However, I have some reasons for why I don't think it can be a priority at present:
My current objective is to try to improve project health, and I think that when winit becomes healthier, a proposal like this is much more realistic. On that note, how would you feel about being pinged to review macOS PRs? It would be a great help. |
@francesca64 I can review MacOS PR's, sure. If you check my github you'll see I've done a lot of work in this area (Rust-MacOS FFI stuff). Would be happy to help out where I can, time permitting. Decoupling, I did assume this was the reason so far. I think breaking off into libraries can simplify testing and merging PRs though. As libraries grow they often decouple to modularise teams and complexity. But I do see that it's no simple feat. I do think that one approach would be for someone to actually write this smaller library, and perhaps once it reaches a level of stability and maturity, winit could consider consuming it in a future version and shedding its internal complexity on window generation and act as a wrapper for that plus eventing and the other benefits it provides. I will need some time to fully go through those issues you linked, I am aware of them but I think I will chat with @Boscop and come up with a general game plan. |
I'll give you some updates. For the 2 PRs I linked, this is where discussion on the underlying issues is moving: #459 (comment) |
As I'm interested in writing audio plugins in Rust, I very much hope that this becomes a reality sooner rather than later. However, the current coupling of event handling and the |
Okay, so I just skimmed this and I'm not sure what exactly is wanted.... Based on these two things that @conundrumer linked, can the https://docs.rs/glutin/0.22.0-alpha1/x86_64-pc-windows-msvc/glutin/platform/windows/trait.RawContextExt.html |
If not, what exactly is missing? If I understand this issue correctly, you folks are looking to separate the window handling from the opengl context creation code it self. This, afaik, is handled by that glutin extension. This extension, of course, assumes the window is externally managed by some other library. (The window can even be managed by winit itself, fwiw.) If the goal is to have the externally managed window somehow also partially managed by winit, can you explain to me what parts you want managed? |
@zegentzy I don't believe it would, no. We don't have control over the parent |
No, OpenGL context creation is a separate issue. I may not event want to use OpenGL. The goal isn't really to partially manage an external window with winit, but rather to create a child window within an externally managed window for which we can get events, draw into, etc. In win32 terms, we want to create a child Maybe have a look at what IPlug2 does in |
As I mentioned in my first comment, the current A new PR or shouldn't it maybe be an "RFC"-style issue? |
https://github.com/rust-dsp/rtb-rs/blob/master/examples/window.rs seems to be going in such a direction, but the implementation is currently mostly non-existent |
Either works. The PR doesn't have to actually implement the backends, it just needs to show what new API you want and come with a little explanation. |
1: Plugins need to attach to a parent window. The VST API/"protocol" does this by giving you the parent window's handle:
What happens under the hood is that the host (DAW) is creating the window for you, which you need to attach to in order for the DAW-plugin interaction to work correctly. I have an implementation for X11 here, and here is the specific example of attaching to the parent window in X11 systems. (Sorry for the messy, probably incorrect code; I'm not really a GUI dev. This code does work well enough to spawn a window in Linux and get events back to vst-rs, though.) I think it was designed this way because of some limitations in OS X needing to handle all events in the parent window (main thread?)? 2: (This part I'm super fuzzy on, because Linux handles it differently than the other two OSes, and again I'm not really a GUI dev so I have no idea what I'm doing. I'm sure I'm going to say something wrong here.) The system needs to use the parent window's event loop, instead of creating its own (again, I think because of OS X?). Nevertheless, we need to be able to handle the events from within the plugin, somehow. It's been a while since I touched my In the linux world, you can spawn the entire child window context (and event handler) in its own thread, and let it handle events that way. So the idea of passing in your own event handler to the hypothetical There's also a little context in our wiki under the GUI section. I'm really kicking myself for not keeping the I'll follow this and #1044 and see if I can contribute anywhere. |
@crsaracco Part 1 seems to be partially done, as
So, yeah, this would appear to be a restriction on OS X (or is that macOS now?), as you get an In windows an |
@l0calh05t Ah, yep, indeed. Seems like the Unix and MacOS versions doesn't have |
@crsaracco Does #1508 satisfy requirement 2 on Windows? |
Hey @Osspial I'm trying to get a vst running using #1508, but I'm getting following error:
I don't think this is my fault, but the code for the vst is here if that's useful: Apologies if this isn't the right place for this |
Hmm, the link above seems dead. |
Sorry, fixed it now |
Good to know that this is a step in the right direction!
Don't worry, that indeed is not your fault. There's actually some commented-out code right next to that panic that handles its branch properly - I think the assumption was that only Winit developers would ever see that panic - so I've uncommented said code and removed the panic in #1496. That should be fixed in #1508 once #1496 gets merged and I rebase #1508 onto |
Sorry Osspial for sleeping on this for a while, I sorta ragequit working on VST GUIs for a while 😅. I feel my interest coming back around a little, so I might look into this again pretty soon. Although I will say, I'm mainly interested in Linux right now, so we'll see I guess. |
Just to (semi-)clarify the current state of this issue for those, who are watching for it: |
I made an example for the "child window" on macOS. It uses winit and Iced. There're some issues though. Contributions are very welcome. For VST you would use |
…dowing#166) * fix(macos): Fix incorrect Redo accelerator * fix(macos): Fix incorrect CloseWindow accelerator (rust-windowing#159)
X11 support was added for that. |
Is this not completely covered by If yes we could close this and open a new tracking issue where we clarify what's missing. |
It all boils down to what kind of child windows we want here, it's either subviews (the ones constrained inside the parent) or when you just attach on-top of arbitrary window which may not even come from winit. In general, both are not complete(subviews are not present at all). And both possible on Wayland, though child window is a bit limited there(not suvbiews). |
If you're on the same |
It would be very useful to have support for creating child windows with a given parent handle.
I implemented support for child windows on Windows in my glutin fork like half a year ago:
https://github.com/Boscop/glutin/blob/master/src/window.rs#L205
https://github.com/Boscop/glutin/blob/master/src/api/win32/init.rs#L76-L84
https://github.com/Boscop/glutin/blob/master/src/api/win32/callback.rs#L23
https://github.com/Boscop/glutin/blob/master/src/api/win32/mod.rs#L471-L473
(Child windows have to run in the same thread as the parent window, so I'm using a HashMap with HWND as key for event dispatching of all the windows in the same thread.)
It would also be useful to have support for timers on the window.
Either via callback:
https://github.com/Boscop/glutin/blob/master/src/window.rs#L508-L516
Or events:
https://github.com/Boscop/glutin/blob/master/src/events.rs#L61
https://github.com/Boscop/glutin/blob/master/src/api/win32/callback.rs#L342-L346
I implemented this because it's necessary to create a child window for writing GUIs for VST plugins. The plugin host creates a window and passes it to the plugin, which has to create a child window on that for it's GUI and register a timer on the HWND so that it refreshes it's GUI every few milliseconds.
This is what I do in the plugin:
Unfortunately I only know how to do this on windows. .
It would be very useful to have this in winit, maybe even in a cross-platform way.
So that winit with conrod can be used to write GUIs for VST plugins, completely in Rust :)
Btw, at the time, conrod didn't have a winit (or glium) backend, so I also forked piston so I could pass the parent all the way down from my plugin to PistonWindow in conrod down to glutin.
Btw, here is a screenshot of an old version of one of my plugins: https://i.imgur.com/4BQ1tCQ.gifv
In the future I would like to use conrod with winit/glium backend for this.
The text was updated successfully, but these errors were encountered: