-
Notifications
You must be signed in to change notification settings - Fork 568
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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
multiple windows, round two #149
Conversation
4b7a73f
to
1df5997
Compare
This is a squash of a bunch of wip commits: Starting on multi-window Most flow is in place, but not wired to actual window creation yet. Fix lifetime issues These only show up on Windows (DirectWrite backend). Wire window size propagation Events on window size need to be propagated to the WindowPod so they can be available during layout. There are other ways to do this. Instead of being in WindowPod, maybe the size info should be in WindowState (where prev_paint_time is, for similar reasons), then passed down through LayoutCtxRoot. But this way, at least the RootWidget gets notifications of window size changing, which seems potentially useful. Small progress towards working multi-window Get new window containers working Build the hello example using containers suitable for multi-window. Still WIP, there's no way to create new windows yet. Starting to plumb creation of multiple windows This is basically working but has a few rough spots. One missing feature is an event flow for closing windows, so their state can be cleaned up.
This removes WindowPod and bakes in the simplest case.
This might be leaking memory, but that beats a crash in the near-term.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested a bit on Windows as well (but see comment inline about key event matching which I had to bodge). The good news is that it seems pretty robust; I wasn't able to trigger any crashes. But there are signs it isn't quite right yet, I get this logged:
2019-09-14 13:52:18,273 ERROR [druid_shell::windows] dropped message 0x2, hwnd=0x220034, wparam=0x0, lparam=0x0
I did a modest (not incredibly deep) pass through the rest and it seems pretty good to me. I like that it's simpler than my PR (exposing less of the internal event dispatching) while also adding the Command abstraction. Basically I'm comfortable with this going in soon, seems like the major issue is stability around window lifetimes. Do we want to debug and fix that in this PR, or get the API in place and treat it as a separate bug?
//but if we don't set this we segfault after close. Maybe we should | ||
//have an appdelegate that handles the windowShouldClose notification? | ||
//See https://developer.apple.com/documentation/appkit/nswindow/1419062-releasedwhenclosed?language=objc | ||
msg_send![window, setReleasedWhenClosed: NO]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this stuff is really messy. Does this fix the segfault when the window is closed with the radio buttons. Ideally I'd like to solve this in a systematic way, but am willing to accept some leaking just to get things working for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't fix that segfault, which I haven't tried tracking down yet. It does fix a segfault that was happening when we called close()
ourselves, though.
@@ -224,6 +230,28 @@ pub fn init() { | |||
func(PROCESS_SYSTEM_DPI_AWARE); // TODO: per monitor (much harder) | |||
} | |||
} | |||
|
|||
unsafe { | |||
let class_name = CLASS_NAME.to_wide(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Orthogonal to the main point of this PR, but I think I'd like to converge on the wio wide trait instead of having our own. Note that we need the to_wide_null
variant (the default doesn't null-terminate).
data: &mut T, | ||
env: &Env, | ||
) -> Option<Action> { | ||
if !ctx.has_focus() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this becomes a standard druid widget, then I think always grabbing focus shouldn't be the behavior. I think the closure can actually do this if it likes.
|
||
EventInterceptor::new(wrapper, |event, ctx, _data, _env| { | ||
if let Event::KeyDown(e) = event { | ||
if HotKey::new(SysMods::Cmd, "n").matches(e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't work on Windows. The reason is that the event text is \u{000e}
(ie ASCII ctrl-N). This is orthogonal to multiple windows but gets in the way of testing. We should make sure to track this issue; it's quite tricky to get right in detail. In any case, I've locally modified my copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that's confusing, I guess I don't know enough about how WM_CHAR
and WM_KEYUP
work.
src/command.rs
Outdated
#[derive(Debug, Clone)] | ||
pub struct Command { | ||
pub selector: Selector, | ||
pub object: Option<Arc<dyn Any>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussion question: is the option dynamic or static (ie some selectors just don't need arguments)? In the latter case, it might be a convention to use ()
as the argument. On the other hand, that's maybe less efficient, as it would still need to be boxed...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My intention was that the expected type of the argument is determined by the selector. Also I'm not sure if this needs to be pub
; it should only be accessed through get_object
, I think..
Oops didn't notice this review come in, thanks! There are definitely some crashes to be teased out, by my inclination here is to merge and continue from there, as long as we think this is a reasonable general approach. |
Yeah, I'm fine with that. I'll mark this as approved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks!
- Remove PartialEq for Command/Selector - remove `pub` from Selector.object - rename send_ to do_ in win_handler - cleanup some comments & remove some dead code
This is my attempt to get very basic multi-win support working.
This is simpler and less flexible than the original approach in #127. My thinking is that we should do as little as possible, and then figure out what missing features we will need for runebender.
This will require some follow-up work; in particular I want to add a
NewWindow
event that announces a new window, and passes along the window id so that other windows can send that window messages.I'm not especially confident in this design; it's hard to really anticipate problems until I've used it more, but I hope it's a reasonable starting point.
I'm not totally sure I have the event/update logic correct.
In any case, I want to get this up now as a checkpoint. I'm going to start trying to weld menus onto this, and we'll see how that goes? If I'm having a lot of trouble I may need to reconsider some things here. 馃し鈥嶁檪