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 740682 - gtkapplication: Use actions from focused widget to activate accel
gtkapplication: Use actions from focused widget to activate accel
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Class: GtkApplication
unspecified
Other All
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2014-11-25 13:09 UTC by Carlos Soriano
Modified: 2014-12-09 09:22 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gtkapplication: Use actions from focused widget to activate accel (11.15 KB, patch)
2014-11-25 13:09 UTC, Carlos Soriano
none Details | Review
gtkapplication: Use actions from focused widget to activate accel (11.19 KB, patch)
2014-11-25 13:17 UTC, Carlos Soriano
needs-work Details | Review
gtkwindow: Use actions from focused widget to activate accel (6.57 KB, patch)
2014-12-03 10:29 UTC, Carlos Soriano
none Details | Review
gtkwindow: Use actions from focused widget to activate accel (6.58 KB, patch)
2014-12-03 10:31 UTC, Carlos Soriano
needs-work Details | Review
gtkwindow: Use actions from focused widget to activate accel (7.53 KB, patch)
2014-12-03 15:43 UTC, Carlos Soriano
reviewed Details | Review
gtkwindow: Use actions from focused widget to activate accel (7.11 KB, patch)
2014-12-07 02:44 UTC, Allison Karlitskaya (desrt)
reviewed Details | Review
gtkwindow: Use actions from focused widget to activate accel (7.19 KB, patch)
2014-12-08 12:31 UTC, Carlos Soriano
needs-work Details | Review
gtkwindow: Use actions from focused widget to activate accel (7.19 KB, patch)
2014-12-08 13:34 UTC, Carlos Soriano
committed Details | Review

Description Carlos Soriano 2014-11-25 13:09:19 UTC
Currently we only take into account the window GActionGroup for
activating the accels.

However, the application could have some custom GActionGroup in the
chain of focused widgets that could want to activate some action if
some accel is activated while that widget is focused.

To allow applications to set accels on widgets that use custom
GActionGroups, traverse from the focused widget until the window
following the chain and recollecting the GActionGroups found on those
widgets, the window inclusive, and fire the right action when an accel
is activated, following the widget chain order.
Comment 1 Carlos Soriano 2014-11-25 13:09:21 UTC
Created attachment 291449 [details] [review]
gtkapplication: Use actions from focused widget to activate accel
Comment 2 Carlos Soriano 2014-11-25 13:17:46 UTC
Created attachment 291451 [details] [review]
gtkapplication: Use actions from focused widget to activate accel

Currently we only take into account the window GActionGroup for
activating the accels.

However, the application could have some custom GActionGroup in the
chain of focused widgets that could want to activate some action if
some accel is activated while that widget is focused.

To allow applications to set accels on widgets that use custom
GActionGroups, traverse from the focused widget until the window
following the chain and recollecting the GActionGroups found on those
widgets, the window inclusive, and fire the right action when an accel
is activated, following the widget chain order.
Comment 3 Allison Karlitskaya (desrt) 2014-11-25 14:29:46 UTC
What is the usecase for this, in terms of specific actions and what widgets they're defined on?
Comment 4 Christian Hergert 2014-11-26 01:52:18 UTC
This would be really nice for me to have in Builder.

I have multiple editors (both in a stack, and side by side) and want to have the keyboard focus actions attached to the container of these side-by-side tabs (A "multi-notebook").

For example, I want <Control>J and <Control>K to move up and down within the editor stack, and <Control>H and <Control>L to move to the stack left or right.

Doing this at the toplevel only is unnecessarily complex when I don't want my toplevel widget to know about the details of its children.
Comment 5 Carlos Soriano 2014-11-26 10:06:17 UTC
(In reply to comment #3)
> What is the usecase for this, in terms of specific actions and what widgets
> they're defined on?

In Nautilus currently all actions are performed on the children using GtkUIManager.

Now, with the port to GAction I have multiple widgets (nautilus-view, nautilus-canvas-view, nautilus-desktop-view, nautilus-list-view) which they define it's own set of actions (that's the reason of that big inheritance). In the big case, nautilus-view, it have near 30 actions, so I defined a local GActionGroup which is attached both to the nautilus-view and nautilus-toolbar.

Most of the actions of nautilus-view use accelerators. In case I have to implement them on the app or window, I will have to have public API in nautilus-view for 30 actions, and some song and dance each time an item is activated which triggers an action of nautilus-view, like the toolbar menus and the right click menus.

Not only that, nautilus has a problem with implementing them on the window. Most of the actions in nautilus-view expect a window, to it's ok and they can be implemented on the window. But the desktop view doesn't use a window. So I will have to implement some of the nautilus-view actions in the window, and some of them in the app, which will make it confusing.
I know though that not having a window is not something very expected in a application.

So since GtkUIManager allowed that (because it was another beast indeed) and I think it makes sense to be able to have accelerators in local GActionGroups as it currently makes sense to have accelerators in the window (as a local widget of the application).
Comment 6 Allison Karlitskaya (desrt) 2014-12-02 15:39:28 UTC
Review of attachment 291451 [details] [review]:

I think it should be possible to just directly pass in the muxer of the focused widget.  Muxers chain to their parent internally, which would accomplish what I think you're trying to do here.

One thing to note: you should try to avoid creating muxers for widgets that do not already have them....
Comment 7 Carlos Soriano 2014-12-03 10:29:47 UTC
Created attachment 292058 [details] [review]
gtkwindow: Use actions from focused widget to activate accel

Currently we only take into account the window GActionGroup for
activating the accels.

However, the application could have some custom GActionGroup in the
chain of focused widgets that could want to activate some action if
some accel is activated while that widget is focused.

To allow applications to set accels on widgets that use custom
GActionGroups, simply use the muxer of the focused widget, which
already contains the actions of the parents.
Comment 8 Carlos Soriano 2014-12-03 10:31:54 UTC
Created attachment 292059 [details] [review]
gtkwindow: Use actions from focused widget to activate accel

Currently we only take into account the window GActionGroup for
activating the accels.

However, the application could have some custom GActionGroup in the
chain of focused widgets that could want to activate some action if
some accel is activated while that widget is focused.

To allow applications to set accels on widgets that use custom
GActionGroups, simply use the muxer of the focused widget, which
already contains the actions of the parents.
Comment 9 Allison Karlitskaya (desrt) 2014-12-03 13:01:59 UTC
Review of attachment 292059 [details] [review]:

For consistency, it seems like the code that follows widget-to-parent in search of the muxer should use the same algorithm for picking the parent as found in _gtk_widget_update_parent_muxer().  That suggests also that we should maybe do the logic inside of _gtk_widget_get_action_muxer() in the !create case.

What do we expect to happen in case of a popover, for example?  I'd imagine we want to go via its relative-to...

::: gtk/gtkwidget.c
@@ +16511,3 @@
 GtkActionMuxer *
+_gtk_widget_get_action_muxer (GtkWidget *widget,
+                              gboolean create_if_no_existent)

Please just call this 'create'.

::: gtk/gtkwidgetprivate.h
@@ +153,3 @@
 void              _gtk_widget_update_parent_muxer          (GtkWidget    *widget);
+GtkActionMuxer *  _gtk_widget_get_action_muxer             (GtkWidget    *widget,
+                                                            gboolean      create_if_no_existent);

'create' please.

::: gtk/gtkwindow.c
@@ +482,3 @@
 static GtkKeyHash *gtk_window_get_key_hash        (GtkWindow   *window);
 static void        gtk_window_free_key_hash       (GtkWindow   *window);
+static GtkActionMuxer* get_innermost_action_muxer (GtkWidget *origin);

Seems like maybe this is a bit of a style issue -- I'll let Gtk hackers comment about that.

@@ +11143,3 @@
+  muxer = _gtk_widget_get_action_muxer (widget, FALSE);
+
+  while (widget != NULL && muxer == NULL)

This loop will exit with a NULL muxer if you run out of widgets...

@@ +11239,2 @@
                   return gtk_application_activate_accel (window->priv->application,
                                                          G_ACTION_GROUP (muxer),

... but here you assume that muxer is non-NULL.
Comment 10 Carlos Soriano 2014-12-03 15:43:11 UTC
Created attachment 292073 [details] [review]
gtkwindow: Use actions from focused widget to activate accel

Currently we only take into account the window GActionGroup for
activating the accels.

However, the application could have some custom GActionGroup in the
chain of focused widgets that could want to activate some action if
some accel is activated while that widget is focused.

To allow applications to set accels on widgets that use custom
GActionGroups, simply use the muxer of the focused widget, which
already contains the actions of the parents.
Comment 11 Matthias Clasen 2014-12-05 04:13:35 UTC
this was fixed
Comment 12 Carlos Soriano 2014-12-05 09:53:24 UTC
where?(In reply to comment #11)
> this was fixed

where?
Comment 13 Matthias Clasen 2014-12-05 15:02:01 UTC
sorry - I was sure I had seen your patch go in. Fake memories...
Comment 14 Matthias Clasen 2014-12-05 21:08:25 UTC
Review of attachment 292073 [details] [review]:

::: gtk/gtkwidget.c
@@ +16494,3 @@
+          {
+            /* This always exists */
+            muxer = gtk_application_get_parent_muxer_for_window (GTK_WINDOW (widget));

Misleading comment: gtk_application_get_parent_muxer_for_window _can_ return NULL

::: gtk/gtkwindow.c
@@ +11218,3 @@
+                  GtkActionMuxer *muxer = _gtk_widget_get_action_muxer (focused_widget, FALSE);
+                  if (muxer == NULL)
+                    return FALSE;

Careful, gtk_window_get_focus can return NULL
Comment 15 Allison Karlitskaya (desrt) 2014-12-07 02:44:27 UTC
Created attachment 292247 [details] [review]
gtkwindow: Use actions from focused widget to activate accel

This is something like what I had in mind (note: doesn't duplicate the logic about how to find the parent widget).
Comment 16 Christian Hergert 2014-12-07 02:51:06 UTC
Review of attachment 292247 [details] [review]:

Other than the NULL check, LGTM.

::: gtk/gtkwindow.c
@@ +11215,3 @@
               if (window->priv->application)
                 {
+                  GtkWidget *focused_widget = gtk_window_get_focus (window);

As mentioned, this can return NULL.
Comment 17 Christian Hergert 2014-12-07 02:54:48 UTC
Tested this on my use case and it works as expected. If no objections from Matthias, I'd be thrilled to have this commited ASAP.
Comment 18 Carlos Soriano 2014-12-08 12:31:27 UTC
Created attachment 292298 [details] [review]
gtkwindow: Use actions from focused widget to activate accel

Currently we only take into account the window GActionGroup for
activating the accels.

However, the application could have some custom GActionGroup in the
chain of focused widgets that could want to activate some action if
some accel is activated while that widget is focused.

To allow applications to set accels on widgets that use custom
GActionGroups, simply use the muxer of the focused widget, which
already contains the actions of the parents.
Comment 19 Carlos Soriano 2014-12-08 12:32:52 UTC
(In reply to comment #15)
> Created an attachment (id=292247) [details] [review]
> gtkwindow: Use actions from focused widget to activate accel
> 
> This is something like what I had in mind (note: doesn't duplicate the logic
> about how to find the parent widget).

Oh, indeed, it's already recursive..., much better.

Thanks for the code!
Comment 20 Emmanuele Bassi (:ebassi) 2014-12-08 12:43:07 UTC
Review of attachment 292298 [details] [review]:

::: gtk/gtkwindow.c
@@ +11218,3 @@
+                  if (focused_widget = NULL)
+                    return FALSE;
+                  GtkActionMuxer *muxer = _gtk_widget_get_action_muxer (focused_widget, FALSE);

no declaration after statement: we are C89-compatible.

this should have triggered a compiler warning for you.
Comment 21 Carlos Soriano 2014-12-08 13:34:48 UTC
Created attachment 292299 [details] [review]
gtkwindow: Use actions from focused widget to activate accel

Currently we only take into account the window GActionGroup for
activating the accels.

However, the application could have some custom GActionGroup in the
chain of focused widgets that could want to activate some action if
some accel is activated while that widget is focused.

To allow applications to set accels on widgets that use custom
GActionGroups, simply use the muxer of the focused widget, which
already contains the actions of the parents.
Comment 22 Carlos Soriano 2014-12-08 13:36:54 UTC
(In reply to comment #20)
> Review of attachment 292298 [details] [review]:
> 
> ::: gtk/gtkwindow.c
> @@ +11218,3 @@
> +                  if (focused_widget = NULL)
> +                    return FALSE;
> +                  GtkActionMuxer *muxer = _gtk_widget_get_action_muxer
> (focused_widget, FALSE);
> 
> no declaration after statement: we are C89-compatible.
> 
> this should have triggered a compiler warning for you.

whoops... thinking it was an easy change I didn't even compiled. Sorry for that.
Comment 23 Matthias Clasen 2014-12-08 14:09:56 UTC
Review of attachment 292299 [details] [review]:

With that one fixup, good to go.

::: gtk/gtkwindow.c
@@ +11218,3 @@
+                  if (focused_widget == NULL)
+                    return FALSE;
+                  GtkActionMuxer *muxer = _gtk_widget_get_action_muxer (focused_widget, FALSE);

As mentioned: move the variable declaration to the beginning of the block.
Comment 24 Christian Hergert 2014-12-08 21:21:17 UTC
There is one other issue with this patch set that breaks an existing feature.

I can no longer use my accelerators registered with the GtkApplication (win.foo) unless a widget is focused.
Comment 25 Matthias Clasen 2014-12-09 03:10:26 UTC
sounds easily fixable. just rewrite it as

 if (focused_widget)
   muxer = _gtk_widget_get_action_muxer (focused_widget, FALSE);
 else
   muxer = _gtk_widget_get_action_muxer (window, FALSE);
Comment 26 Christian Hergert 2014-12-09 04:23:24 UTC
Comment on attachment 292299 [details] [review]
gtkwindow: Use actions from focused widget to activate accel

Committed with followup patch to fix c89 and fallback to window muxer.
Comment 27 Carlos Soriano 2014-12-09 09:20:07 UTC
(In reply to comment #24)
> There is one other issue with this patch set that breaks an existing feature.
> 
> I can no longer use my accelerators registered with the GtkApplication
> (win.foo) unless a widget is focused.

I thought a window or a children of the window should be focused to actually trigger an accel, if not, what's the point/use case? A no focused window/children activating an accel? Sounds wrong for me at first though.

Thanks for the review and push! =)
Comment 28 Carlos Soriano 2014-12-09 09:22:11 UTC
(In reply to comment #23)
> Review of attachment 292299 [details] [review]:
> 
> With that one fixup, good to go.
> 
> ::: gtk/gtkwindow.c
> @@ +11218,3 @@
> +                  if (focused_widget == NULL)
> +                    return FALSE;
> +                  GtkActionMuxer *muxer = _gtk_widget_get_action_muxer
> (focused_widget, FALSE);
> 
> As mentioned: move the variable declaration to the beginning of the block.

oh ok, misunderstood Emanuelle review. That was not trigering a warning for me thougth...