mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-09-29 20:44:17 +00:00
window-slot: Rework and document grab_focus() call
We'v been relying on a gtk_widget_grab_focus() call to avoid broken focus states after view (re)loading. But there is one particular case where we must not do it: if the popover menu is shown. This is a rare situation which is currently only possible to trigger by pressing [Spacebar] while the "Show Hidden Files" menu item has focus. But this currently relies on the slot calling a NautilusWindow method, which is a layer violation which is getting in the way of reusing NautilusWindowSlot in the FileChooser window[4]. Let's use generic GTK/GDK API to assess wether the menu is shown, and drop the NautilusWindow method. Originally I've just removed the grab_focus() call, but came to realize it was still needed, so let's also document my findings here. Part of: https://gitlab.gnome.org/GNOME/nautilus/-/work_items/3402
This commit is contained in:
parent
c960cfa439
commit
6bd4e06faa
|
@ -2502,6 +2502,24 @@ nautilus_window_slot_update_for_new_location (NautilusWindowSlot *self)
|
|||
nautilus_location_banner_load (self->banner, new_location);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
focus_is_on_popup (GtkRoot *window)
|
||||
{
|
||||
GtkWidget *focus = gtk_root_get_focus (window);
|
||||
|
||||
if (focus != NULL)
|
||||
{
|
||||
GtkNative *native = gtk_widget_get_native (focus);
|
||||
|
||||
if (native != NULL)
|
||||
{
|
||||
return GDK_IS_POPUP (gtk_native_get_surface (native));
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
view_started_loading (NautilusWindowSlot *self,
|
||||
NautilusView *view)
|
||||
|
@ -2511,12 +2529,29 @@ view_started_loading (NautilusWindowSlot *self,
|
|||
nautilus_window_slot_set_allow_stop (self, TRUE);
|
||||
}
|
||||
|
||||
/* Only grab focus if the menu isn't showing. Otherwise the menu disappears
|
||||
* e.g. when the user toggles Show Hidden Files
|
||||
*/
|
||||
if (!nautilus_window_is_menu_visible (self->window))
|
||||
GtkRoot *window = gtk_widget_get_root (GTK_WIDGET (self));
|
||||
|
||||
if (!focus_is_on_popup (window))
|
||||
{
|
||||
gtk_widget_grab_focus (GTK_WIDGET (self->window));
|
||||
/* This mysterious gtk_widget_grab_focus() call has been carried over
|
||||
* many refactorings, along the way having been wrapped in multiple ways
|
||||
* (nautilus_view_grab_focus(), nautilus_window_pane_grab_focus(),
|
||||
* nautilus_view_grab_focus()). It's been added in a series of bugfixes
|
||||
* related to extra pane.[0] If I had to guess, I'd say it was to deal
|
||||
* with side effects of the grandparent commit[1], which removed a much
|
||||
* older bugfix[2].
|
||||
*
|
||||
* Regardless of its original purpose, we still rely on this call to
|
||||
* prevent a "lost focus" situation. This is easily reproduced, in a
|
||||
* build where this call is removed, by refreshing a view where nothing
|
||||
* is selected. This "lost focus" state means, e.g., some keybindings,
|
||||
* such as Ctrl+A, won't work.
|
||||
*
|
||||
* [0] Commit c69f3a2ba2d0bd23de5a218b8ce13d256481213a
|
||||
* [1] Commit 4efd42312584b46f248e2839582a87776a7baebe
|
||||
* [2] Commit 4f7ae827f7e13cf06965cc72ca60cf7801906a33
|
||||
*/
|
||||
gtk_widget_grab_focus (GTK_WIDGET (window));
|
||||
}
|
||||
|
||||
nautilus_window_slot_set_loading (self, TRUE);
|
||||
|
|
|
@ -95,7 +95,6 @@ struct _NautilusWindow
|
|||
{
|
||||
AdwApplicationWindow parent_instance;
|
||||
|
||||
GtkWidget *app_button;
|
||||
GMenuModel *undo_redo_section;
|
||||
|
||||
AdwTabView *tab_view;
|
||||
|
@ -2506,7 +2505,6 @@ nautilus_window_class_init (NautilusWindowClass *class)
|
|||
|
||||
gtk_widget_class_set_template_from_resource (wclass,
|
||||
"/org/gnome/nautilus/ui/nautilus-window.ui");
|
||||
gtk_widget_class_bind_template_child (wclass, NautilusWindow, app_button);
|
||||
gtk_widget_class_bind_template_child (wclass, NautilusWindow, undo_redo_section);
|
||||
gtk_widget_class_bind_template_child (wclass, NautilusWindow, toolbar);
|
||||
gtk_widget_class_bind_template_child (wclass, NautilusWindow, split_view);
|
||||
|
@ -2632,16 +2630,3 @@ nautilus_window_search (NautilusWindow *window,
|
|||
g_warning ("Trying search on a slot but no active slot present");
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
nautilus_window_is_menu_visible (NautilusWindow *self)
|
||||
{
|
||||
GtkWidget *menu;
|
||||
|
||||
g_return_val_if_fail (NAUTILUS_IS_WINDOW (self), FALSE);
|
||||
|
||||
menu = GTK_WIDGET (gtk_menu_button_get_popover (GTK_MENU_BUTTON (self->app_button)));
|
||||
g_return_val_if_fail (menu != NULL, FALSE);
|
||||
|
||||
return gtk_widget_is_visible (menu);
|
||||
}
|
||||
|
|
|
@ -89,8 +89,6 @@ AdwTabView * nautilus_window_get_tab_view (NautilusWindow *window);
|
|||
|
||||
void nautilus_window_show_about_dialog (NautilusWindow *window);
|
||||
|
||||
gboolean nautilus_window_is_menu_visible (NautilusWindow *toolbar);
|
||||
|
||||
/* sync window GUI with current slot. Used when changing slots,
|
||||
* and when updating the slot state.
|
||||
*/
|
||||
|
|
|
@ -136,7 +136,7 @@
|
|||
</object>
|
||||
</property>
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton" id="app_button">
|
||||
<object class="GtkMenuButton">
|
||||
<property name="tooltip-text" translatable="yes">Main Menu</property>
|
||||
<property name="icon_name">open-menu-symbolic</property>
|
||||
<property name="popover">
|
||||
|
|
Loading…
Reference in a new issue