Skip to content
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

Merged
merged 10 commits into from
Sep 17, 2019
Merged

multiple windows, round two #149

merged 10 commits into from
Sep 17, 2019

Conversation

cmyr
Copy link
Member

@cmyr cmyr commented Sep 12, 2019

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. 馃し鈥嶁檪

@cmyr cmyr force-pushed the multi_win2 branch 3 times, most recently from 4b7a73f to 1df5997 Compare September 13, 2019 12:42
raphlinus and others added 9 commits September 13, 2019 13:45
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.
Copy link
Contributor

@raphlinus raphlinus left a 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];
Copy link
Contributor

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.

Copy link
Member Author

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();
Copy link
Contributor

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() {
Copy link
Contributor

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) {
Copy link
Contributor

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.

Copy link
Member Author

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>>,
Copy link
Contributor

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...

Copy link
Member Author

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..

src/command.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
src/win_handler.rs Outdated Show resolved Hide resolved
@cmyr
Copy link
Member Author

cmyr commented Sep 16, 2019

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.

@raphlinus
Copy link
Contributor

Yeah, I'm fine with that. I'll mark this as approved.

Copy link
Contributor

@raphlinus raphlinus left a 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants