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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix macOS mouse events with multiple windows and active states. #907

Merged
merged 1 commit into from
May 26, 2020

Conversation

xStrom
Copy link
Member

@xStrom xStrom commented May 8, 2020

This PR replaces acceptsMouseMovedEvents with NSTrackingArea. This fixes a bunch of issues with not receiving mouse events in a multiple window situation.

The behavior is perhaps best testable with the multiwin example with the hot glow option turned on via the context menu. For example on master if you overlap multiple druid windows partially and then move the mouse not-too-fast over both of them, the window that's not active might get the hot status and remain stuck with it.

For another example:

  • Position the two druid windows partially on top of each other.
  • Press and hold a mouse button on the active window where the windows would overlap.
  • Cmd+` to the bottom window so that it becomes the top window and is below the mouse cursor.
  • Move the mouse a tiny bit, but not out of the area where it's on top of the new bottom window but in an obscured manner.
  • Release the mouse button and move the mouse away.

On master the bottom window gets stuck in a hot state, while there's a custom fix for it in this PR.

@xStrom xStrom added shell/mac concerns the macOS backend S-needs-review waits for review labels May 8, 2020
@xStrom xStrom force-pushed the mac-mouse branch 3 times, most recently from 7953a17 to 4205339 Compare May 11, 2020 15:58
@cmyr
Copy link
Member

cmyr commented May 11, 2020

I have some preliminary thoughts & questions:

  • on mac, windows that are not active are generally not interactive; we don't want them to be drawing hover state etc. I think the way to handle this overall is with some sort of "enabled" flag, but I'm not sure how that interacts with this work?

for the second example you mention, this does seem like a bug; the issue as far as I can tell is that the second window isn't receiving the mouse up event, and it should be? I presume we're just dropping this somewhere?

@xStrom
Copy link
Member Author

xStrom commented May 11, 2020

The second example bug on master is because non-active windows don't receive mouse events when no mouse buttons are held down. The bug persists even with visible tracking areas because they still won't receive events when the mouse leaves via an obscured part. That's why it needed special attention.


As for non-active windows drawing hot state, I did a short survey of apps on macOS Catalina.

App Hot state description When active When not active
Calculator None - -
Calendar None - -
Contacts When hovering over lines of info they either get colored background or an icon appears. Top titlebar gets extra edit button that appears on hover. Yes Yes
Dictionary Top toolbar tabs change color behind text on hover. Yes Yes
Finder On the left sidebar Favourites/Tags show Hide button Yes Yes
Notes Hovering over top toolbar icons changes their color No !! Yes
Photos On the left sidebar Library / Albums / Projects show Hide button, and My Albums / My Projects show a + button Yes Hide buttons
Reminders Hovering over items shows a blue icon Yes No
Safari Address bar shows plus sign on left side when hovered, and when hovering that plus sign the text Add page to reading list appears Yes Yes
TextEdit Cursor changes over text Yes No
  • Of the 10 apps tested, 8 had some sort of hot effect.
  • Of the 8 apps with hot effects, 6 of them had hot effects even when the window is not active.
  • One of them had hot effects only when not active!

Based on my testing it seems that although hover effects aren't used nearly as often in macOS apps as say Windows apps, they are still widely used in most apps, even if sparingly. Also the majority of them had hover effects even when the window is not active.

Thus to have a macOS app that does not have hot effects when hovering would put it into the minority. I'm not sure how 3rd party apps on macOS tend to behave, but the apps I tested came with macOS Catalina and are promoted in the bottom toolbar so I assume Apple considers them well enough designed.

I think the case is rather clear that hot state for non-active windows should be there.

Now what I will say is that during my survey I also noticed that several apps change their design based on whether the window is active or not. To do that the app needs to know whether the window is active or not.

Thus I think for druid to be powerful enough to mimic the behavior of say the Notes app on macOS, it needs to have both non-active mouse events that this PR here provides, but also an additional capability added via a different PR that allows the app to know whether the window is currently active - or I guess focus in druid's parlance.

@cmyr
Copy link
Member

cmyr commented May 13, 2020

Okay, I think that's a good argument for keeping these concepts separated. Thanks for the survey; I'll do a review focused on the implementation when I have a few window.

Copy link
Member

@cmyr cmyr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some observations, happy to get this in; sorry for the wait!

}
}

pub trait NSTrackingArea: Sized {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider trying to upstream any of this if we want it. I've also personally found that these abstractions around cocoa stuff really aren't super helpful, and generally I lean towards just using msg_send! directly everywhere. (this is fine, though)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah the appkit.rs stuff I would like to get upstreamed. I've done very minimal macOS Rust programming to have an opinion on what's helpful or not, but the stuff I wrote here mimics the servo appkit crate so at least it's consistent.

owner: id,
userInfo: id,
) -> id {
msg_send![self, initWithRect:rect options:options owner:owner userInfo:userInfo]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's possible we want an autorelease call on this, would have to run the memory profiler.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The autorelease stuff I'm least familiar with because the Apple documentation doesn't directly translate to the Rust world. Anyway for this case I did add an autorelease call in window.rs after calling this method. In my testing adding that autorelease at least doesn't seem to cause any issues.

@xStrom xStrom merged commit 1318947 into linebender:master May 26, 2020
@xStrom xStrom deleted the mac-mouse branch May 26, 2020 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
shell/mac concerns the macOS backend
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants