After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 731058 - Improve behavior of window menu buttons
Improve behavior of window menu buttons
Status: RESOLVED FIXED
Product: mutter
Classification: Core
Component: general
unspecified
Other All
: Normal normal
: ---
Assigned To: mutter-maint
mutter-maint
Depends on:
Blocks:
 
 
Reported: 2014-05-31 23:27 UTC by Florian Müllner
Modified: 2014-06-02 21:52 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
frames: Center menu coordinates horizontally to the menu button (1.67 KB, patch)
2014-05-31 23:27 UTC, Florian Müllner
accepted-commit_now Details | Review
frames: Fix pressed state of window menu buttons (2.98 KB, patch)
2014-05-31 23:27 UTC, Florian Müllner
committed Details | Review
frames: Sync hover after compositor grab has been released (6.40 KB, patch)
2014-05-31 23:27 UTC, Florian Müllner
reviewed Details | Review
windowMenu: Do a better job with faking the source actor (4.21 KB, patch)
2014-05-31 23:28 UTC, Florian Müllner
reviewed Details | Review
windowMenu: Ignore button release when opening the menu (1.18 KB, patch)
2014-05-31 23:29 UTC, Florian Müllner
accepted-commit_now Details | Review
frames: Only skip updating prelight when both control and state match (1.12 KB, patch)
2014-06-02 16:56 UTC, Florian Müllner
committed Details | Review
Pass button_rect when opening window menu from button (10.30 KB, patch)
2014-06-02 21:26 UTC, Florian Müllner
committed Details | Review
windowMenu: Implement new show_menu_for_rect() hook (6.74 KB, patch)
2014-06-02 21:28 UTC, Florian Müllner
committed Details | Review
windowMenu: Do a better job with faking the source actor (3.69 KB, patch)
2014-06-02 21:28 UTC, Florian Müllner
committed Details | Review

Description Florian Müllner 2014-05-31 23:27:22 UTC
See patches.
Comment 1 Florian Müllner 2014-05-31 23:27:26 UTC
Created attachment 277638 [details] [review]
frames: Center menu coordinates horizontally to the menu button

Aligning the window menu with the left/right side of the titlebar
button made sense with the old GTK-based popups, but nowadays the
menu coordinates define the spot the menu's arrow points to - in
the shell, all other menus point to the center of their source, so
do the same for the window menu.
Comment 2 Florian Müllner 2014-05-31 23:27:33 UTC
Created attachment 277639 [details] [review]
frames: Fix pressed state of window menu buttons

Since window menus have been moved to the compositor, the pressed
state of the corresponding window buttons is messed up, as it is
reset immediately when getting a LeaveNotify event due to the
compositor taking a grab. Fix this by ignoring that particular
event.
Comment 3 Florian Müllner 2014-05-31 23:27:38 UTC
Created attachment 277640 [details] [review]
frames: Sync hover after compositor grab has been released

During compositor grabs, frames don't receive events to update the
prelit/pressed state of frame decorations. This is particularly
visible now that compositor grabs can happen as direct result of
interaction with frame decorations, so sync decorations' hover
state after the grab is released.
Comment 4 Florian Müllner 2014-05-31 23:28:27 UTC
Created attachment 277642 [details] [review]
windowMenu: Do a better job with faking the source actor

The 0x0 dummyCursor works well when the menu pops up directly underneath
the pointer (e.g. when triggered by right-clicking the titlebar) or by
keyboard, but not when triggered by the menu button -  unless the user
keeps holding the mouse button while moving into the menu, the menu will
be dismissed immediately on button release. Address this by overlaying
the menu button with an appropriately sized actor, to make the window
menu behavior consistent with other shell menus.
Comment 5 Jasper St. Pierre (not reading bugmail) 2014-05-31 23:29:29 UTC
Review of attachment 277638 [details] [review]:

OK.
Comment 6 Florian Müllner 2014-05-31 23:29:46 UTC
Created attachment 277643 [details] [review]
windowMenu: Ignore button release when opening the menu

When the menu is triggered by clicking a titlebar button, it won't
pop up directly underneath the pointer and close immediately on
button release if the user does not move into the menu while
holding the button. Ignoring the first button release fixes the
common case, though it does not quite work as expected when
the pointer is neither on the menu nor the window button.

This patch is a much simpler alternative to the previous one, though as noted, the behavior is not quite correct in all cases.
Comment 7 Jasper St. Pierre (not reading bugmail) 2014-05-31 23:30:46 UTC
Review of attachment 277639 [details] [review]:

Can we just ignore any event with GDK_NOTIFY_GRAB instead?
Comment 8 Jasper St. Pierre (not reading bugmail) 2014-05-31 23:32:04 UTC
Review of attachment 277640 [details] [review]:

Hm, the X server should send us an EnterNotify with NotifyUngrab and the correct X/Y position. Is that not happening?
Comment 9 Jasper St. Pierre (not reading bugmail) 2014-05-31 23:34:46 UTC
Review of attachment 277642 [details] [review]:

Not too happy about this, especially because the keynav is still sort of broken. I can't think of anything better, though.

::: js/ui/windowMenu.js
@@ +190,3 @@
+        // Pick the height of the frame decoration as size
+        let rect = window.get_frame_rect();
+        let size = y - rect.y;

I recently added meta_window_get_titlebar_rect here. Could that be used?
Comment 10 Jasper St. Pierre (not reading bugmail) 2014-05-31 23:35:29 UTC
Review of attachment 277643 [details] [review]:

OK.
Comment 11 Florian Müllner 2014-06-02 16:56:00 UTC
Created attachment 277741 [details] [review]
frames: Only skip updating prelight when both control and state match

(In reply to comment #7)
> Can we just ignore any event with GDK_NOTIFY_GRAB instead?

I don't think that is correct - for instance when hovering the close button and hitting alt-f2, the current behavior of removing the prelight makes sense to me. It's just in case of the window menus where there's a direct relation between button state and grab where keeping the state is better IMHO.
Regarding the NotifyGrab, I did initially try using event->mode, but for some reason it is always NORMAL in case of a compositor grab.


(In reply to comment #8)
> Hm, the X server should send us an EnterNotify with NotifyUngrab and the
> correct X/Y position. Is that not happening?

Yeah, this can be addressed a lot simpler, see updated patch.


(In reply to comment #9)
> +        let rect = window.get_frame_rect();
> +        let size = y - rect.y;
> 
> I recently added meta_window_get_titlebar_rect here. Could that be used?

I did see that, but not sure if it would be better. Ideally we'd match the actual visible button, but we don't have that. Next best thing would be to use the corresponding button_rect - I've considered adding width/height or replacing the coordinates with a rectangle, but both options make for rather confusing API. Now the above assumes that 'y' is below the button (e.g. it would still include the button when pointing 20px below the titlebar for some reason), while get_titlebar_rect() also assumes that it points to the bottom edge or inside the titlebar. This doesn't look like a terrible assumption, so if you feel it'd be more readable, I'll make get_titlebar_rect() introspecable and switch to that.
Comment 12 Jasper St. Pierre (not reading bugmail) 2014-06-02 17:44:49 UTC
Review of attachment 277741 [details] [review]:

I'm not sure what this is fixing. There are three callers for update_prelit_control: motion, enter, and leave. Motion only calls it in prelit, so that doesn't change anything here. The other two always change the control, so we don't hit the early return.

Any hints?
Comment 13 Jasper St. Pierre (not reading bugmail) 2014-06-02 17:46:53 UTC
(In reply to comment #11)
> I did see that, but not sure if it would be better. Ideally we'd match the
> actual visible button, but we don't have that. Next best thing would be to use
> the corresponding button_rect - I've considered adding width/height or
> replacing the coordinates with a rectangle, but both options make for rather
> confusing API.

I would be fine with proper button rect geometry in show_window_menu -- it would make it so that if the window menu button was near-offscreen, the menu would be flipped properly to be on top. We could have two APIs -- meta_window_show_window_menu for the common case and meta_window_show_window_menu_for_rect otherwise.
Comment 14 Florian Müllner 2014-06-02 17:50:23 UTC
(In reply to comment #12)
> I'm not sure what this is fixing. There are three callers for
> update_prelit_control: motion, enter, and leave. Motion only calls it in
> prelit, so that doesn't change anything here. The other two always change the
> control, so we don't hit the early return.

It may be hit in the enter case after applying attachment 277639 [details] [review]. when a leave event is ignored and the control is stilled hovered after dismissing the menu.
Comment 15 Florian Müllner 2014-06-02 17:58:15 UTC
(In reply to comment #13)
> I would be fine with proper button rect geometry in show_window_menu -- it
> would make it so that if the window menu button was near-offscreen, the menu
> would be flipped properly to be on top.

Seems to be working fine already, but sure, I'll add API.


> We could have two APIs -- meta_window_show_window_menu for the common case and
> meta_window_show_window_menu_for_rect otherwise.

Sigh, adding API like that would be much nicer if it didn't involve going through 1000 layers between UI and compositor :-(
Comment 16 Jasper St. Pierre (not reading bugmail) 2014-06-02 18:07:11 UTC
I've been meaning to clean that up for a while, and just make meta_compositor_* call the MetaPlugin vfuncs directly. That would remove a few of the layers. Really, the majority of code should stay as-is, with only the plugin interface changing, and a new piece of code to access it.
Comment 17 Jasper St. Pierre (not reading bugmail) 2014-06-02 19:31:40 UTC
(If you want to push these commits now and then fix up and add the API later, that's fine by me...)
Comment 18 Jasper St. Pierre (not reading bugmail) 2014-06-02 19:32:13 UTC
Review of attachment 277741 [details] [review]:

Ah, right, that makes sense then.
Comment 19 Florian Müllner 2014-06-02 21:26:59 UTC
Created attachment 277767 [details] [review]
Pass button_rect when opening window menu from button

When opening the window menu without an associated control - e.g.
by right-clicking the titlebar or by keyboard - using coordinates
for the menu position is appropriate. However when the menu is
associated with a window button, the expected behavior in the
shell can be implemented much easier with the full button geometry:
the menu will point to the center of the button's bottom edge
rather than align to the left/right side of the titlebar as it
does now, and the clickable area where a release event does not
dismiss the menu will match the actual clickable area in mutter.

So add an additional show_window_menu_for_rect() function and
use it when opening the menu from a button.
Comment 20 Florian Müllner 2014-06-02 21:28:18 UTC
Created attachment 277768 [details] [review]
windowMenu: Implement new show_menu_for_rect() hook

Having the full geometry of the menu's source button (if any) will
allow us to address several misbehaviors of window menus, so use
that instead of show_menu().
Comment 21 Florian Müllner 2014-06-02 21:28:35 UTC
Created attachment 277769 [details] [review]
windowMenu: Do a better job with faking the source actor

The 0x0 dummyCursor works well when the menu pops up directly underneath
the pointer (e.g. when triggered by right-clicking the titlebar) or by
keyboard, but not when triggered by the menu button - the menu does not
point to the center of the button's bottom edge, and unless the user
keeps holding the mouse button while moving into the menu, the menu will
be dismissed immediately on button release.
Address these issues by using the button geometry to overlay the window
button with an appropriately sized actor that acts as a proper sourceActor,
to make the window menu behavior consistent with other shell menus.
Comment 22 Jasper St. Pierre (not reading bugmail) 2014-06-02 21:35:13 UTC
Review of attachment 277768 [details] [review]:

Oh, I was imagining that we'd just fake a 1x1 rectangle in mutter and pass that through its hooks, but I guess this works too.
Comment 23 Jasper St. Pierre (not reading bugmail) 2014-06-02 21:37:13 UTC
Review of attachment 277767 [details] [review]:

::: src/ui/frames.c
@@ +1228,3 @@
 
+          /* relies on both structs being identical */
+          root_rect = *((MetaRectangle *)rect);

Yuck. I'd just do:

    int win_x = event->x_root - event->x;

    root_rect.x = win_x + rect.x;
    ...
    root_rect.width = rect.width;
Comment 24 Jasper St. Pierre (not reading bugmail) 2014-06-02 21:38:05 UTC
Review of attachment 277769 [details] [review]:

OK.
Comment 25 Florian Müllner 2014-06-02 21:51:34 UTC
Attachment 277639 [details] pushed as e2105dc - frames: Fix pressed state of window menu buttons
Attachment 277741 [details] pushed as a7f0838 - frames: Only skip updating prelight when both control and state match
Attachment 277767 [details] pushed as b64548e - Pass button_rect when opening window menu from button
Comment 26 Florian Müllner 2014-06-02 21:52:36 UTC
Attachment 277768 [details] pushed as 5b61f2d - windowMenu: Implement new show_menu_for_rect() hook
Attachment 277769 [details] pushed as e51eb72 - windowMenu: Do a better job with faking the source actor