[gnome-builder/wip/gtk4-port] libide/gui: attach shortcut controllers to global search popover



commit 093229e82a94b631d2ef5082bbec7c4424eaf4ca
Author: Christian Hergert <chergert redhat com>
Date:   Thu May 12 15:18:50 2022 -0700

    libide/gui: attach shortcut controllers to global search popover
    
    This is a bit of a workaround because the shortcut controllers do not do
    capture/bubble semantics properly up to the GtkRoot (our IdeWorkspace).

 src/libide/gui/ide-shortcut-bundle-private.h |  3 ++
 src/libide/gui/ide-workbench.c               | 33 +-------------
 src/libide/gui/ide-workspace-private.h       |  2 +
 src/libide/gui/ide-workspace.c               | 68 ++++++++++++++++++++++++++++
 4 files changed, 74 insertions(+), 32 deletions(-)
---
diff --git a/src/libide/gui/ide-shortcut-bundle-private.h b/src/libide/gui/ide-shortcut-bundle-private.h
index 826f0f0ca..1f8ec5183 100644
--- a/src/libide/gui/ide-shortcut-bundle-private.h
+++ b/src/libide/gui/ide-shortcut-bundle-private.h
@@ -33,4 +33,7 @@ gboolean           ide_shortcut_bundle_parse (IdeShortcutBundle  *self,
                                               GFile              *file,
                                               GError            **error);
 
+#define ide_shortcut_is_phase(obj,pha) \
+  (g_object_get_data(G_OBJECT(obj), "PHASE") == pha)
+
 G_END_DECLS
diff --git a/src/libide/gui/ide-workbench.c b/src/libide/gui/ide-workbench.c
index a690a30ca..4ede7df30 100644
--- a/src/libide/gui/ide-workbench.c
+++ b/src/libide/gui/ide-workbench.c
@@ -745,21 +745,6 @@ insert_action_groups_foreach_cb (IdeWorkspace *workspace,
     }
 }
 
-static gboolean
-shortcut_phase_filter (gpointer item,
-                       gpointer user_data)
-{
-  return g_object_get_data (item, "PHASE") == user_data;
-}
-
-static GtkFilter *
-create_shortcut_filter (GtkPropagationPhase phase)
-{
-  return GTK_FILTER (gtk_custom_filter_new (shortcut_phase_filter,
-                                            GINT_TO_POINTER (phase),
-                                            NULL));
-}
-
 /**
  * ide_workbench_add_workspace:
  * @self: an #IdeWorkbench
@@ -775,7 +760,6 @@ ide_workbench_add_workspace (IdeWorkbench *self,
   g_autoptr(GtkFilterListModel) capture = NULL;
   g_autoptr(GtkFilterListModel) bubble = NULL;
   IdeShortcutManager *shortcuts;
-  GtkEventController *controller;
   IdeCommandManager *command_manager;
   GList *mru_link;
 
@@ -821,22 +805,7 @@ ide_workbench_add_workspace (IdeWorkbench *self,
 
   /* Setup capture shortcut controller for workspace */
   shortcuts = ide_shortcut_manager_from_context (self->context);
-  capture = gtk_filter_list_model_new (g_object_ref (G_LIST_MODEL (shortcuts)),
-                                       create_shortcut_filter (GTK_PHASE_CAPTURE));
-  controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (g_steal_pointer (&capture)));
-  gtk_event_controller_set_name (controller, "ide-shortcuts-capture");
-  gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
-  gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
-  gtk_widget_add_controller (GTK_WIDGET (workspace), controller);
-
-  /* Setup bubble shortcut controller for workspace */
-  bubble = gtk_filter_list_model_new (g_object_ref (G_LIST_MODEL (shortcuts)),
-                                      create_shortcut_filter (GTK_PHASE_BUBBLE));
-  controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (g_steal_pointer (&bubble)));
-  gtk_event_controller_set_name (controller, "ide-shortcuts-bubble");
-  gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_BUBBLE);
-  gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
-  gtk_widget_add_controller (GTK_WIDGET (workspace), controller);
+  _ide_workspace_set_shortcut_model (workspace, G_LIST_MODEL (shortcuts));
 
   /* Track toplevel focus changes to maintain a most-recently-used queue. */
   g_signal_connect_object (workspace,
diff --git a/src/libide/gui/ide-workspace-private.h b/src/libide/gui/ide-workspace-private.h
index 79b9fc2be..691d303ba 100644
--- a/src/libide/gui/ide-workspace-private.h
+++ b/src/libide/gui/ide-workspace-private.h
@@ -51,5 +51,7 @@ PanelFrame *_ide_workspace_find_frame          (IdeWorkspace        *workspace,
                                                 PanelPaned          *dock_end,
                                                 PanelPaned          *dock_bottom,
                                                 IdeGrid             *grid);
+void        _ide_workspace_set_shortcut_model  (IdeWorkspace        *self,
+                                                GListModel          *shortcuts);
 
 G_END_DECLS
diff --git a/src/libide/gui/ide-workspace.c b/src/libide/gui/ide-workspace.c
index 955ec7944..28f739091 100644
--- a/src/libide/gui/ide-workspace.c
+++ b/src/libide/gui/ide-workspace.c
@@ -27,6 +27,7 @@
 
 #include "ide-gui-global.h"
 #include "ide-search-popover-private.h"
+#include "ide-shortcut-bundle-private.h"
 #include "ide-workspace-addin.h"
 #include "ide-workspace-private.h"
 #include "ide-workbench-private.h"
@@ -65,6 +66,10 @@ typedef struct
   /* The global search for the workspace, if any */
   IdeSearchPopover *search_popover;
 
+  /* GListModel of GtkShortcut w/ capture/bubble filters */
+  GtkFilterListModel *shortcut_model_bubble;
+  GtkFilterListModel *shortcut_model_capture;
+
   /* A MRU that is updated as pages are focused. It allows us to move through
    * the pages in the order they've been most-recently focused.
    */
@@ -101,6 +106,31 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (IdeWorkspace, ide_workspace, ADW_TYPE_APPLICAT
 static GParamSpec *properties [N_PROPS];
 static GSettings *settings;
 
+static void
+ide_workspace_attach_shortcuts (IdeWorkspace *self,
+                                GtkWidget    *widget)
+{
+  IdeWorkspacePrivate *priv = ide_workspace_get_instance_private (self);
+  GtkEventController *controller;
+
+  g_assert (IDE_IS_WORKSPACE (self));
+  g_assert (GTK_IS_WIDGET (widget));
+  g_assert (G_IS_LIST_MODEL (priv->shortcut_model_bubble));
+  g_assert (G_IS_LIST_MODEL (priv->shortcut_model_capture));
+
+  controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (priv->shortcut_model_capture));
+  gtk_event_controller_set_name (controller, "ide-shortcuts-capture");
+  gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
+  gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
+  gtk_widget_add_controller (widget, g_steal_pointer (&controller));
+
+  controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (priv->shortcut_model_bubble));
+  gtk_event_controller_set_name (controller, "ide-shortcuts-bubble");
+  gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_BUBBLE);
+  gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
+  gtk_widget_add_controller (widget, g_steal_pointer (&controller));
+}
+
 static IdePage *
 ide_workspace_get_focus_page (IdeWorkspace *self)
 {
@@ -1280,6 +1310,12 @@ _ide_workspace_begin_global_search (IdeWorkspace *self)
 
       priv->search_popover = IDE_SEARCH_POPOVER (ide_search_popover_new (search_engine));
       gtk_widget_set_parent (GTK_WIDGET (priv->search_popover), GTK_WIDGET (self));
+
+      /* Popovers don't appear (as of GTK 4.7) to capture/bubble from the GtkRoot
+       * when running controllers. So we need to manually attach them for the popovers
+       * that are important enough to care about.
+       */
+      ide_workspace_attach_shortcuts (self, GTK_WIDGET (priv->search_popover));
     }
 
   if (!gtk_widget_get_visible (GTK_WIDGET (priv->search_popover)))
@@ -1314,3 +1350,35 @@ ide_workspace_remove_overlay (IdeWorkspace *self,
   else
     IDE_WORKSPACE_GET_CLASS (self)->remove_overlay (self, overlay);
 }
+
+static gboolean
+shortcut_phase_filter (gpointer item,
+                       gpointer user_data)
+{
+  return ide_shortcut_is_phase (item, user_data);
+}
+
+void
+_ide_workspace_set_shortcut_model (IdeWorkspace *self,
+                                   GListModel   *model)
+{
+  IdeWorkspacePrivate *priv = ide_workspace_get_instance_private (self);
+  static GtkCustomFilter *bubble_filter;
+  static GtkCustomFilter *capture_filter;
+
+  g_return_if_fail (IDE_IS_WORKSPACE (self));
+  g_return_if_fail (G_IS_LIST_MODEL (model));
+
+  if (bubble_filter == NULL)
+    bubble_filter = gtk_custom_filter_new (shortcut_phase_filter, GINT_TO_POINTER (GTK_PHASE_BUBBLE), NULL);
+
+  if (capture_filter == NULL)
+    capture_filter = gtk_custom_filter_new (shortcut_phase_filter, GINT_TO_POINTER (GTK_PHASE_CAPTURE), 
NULL);
+
+  priv->shortcut_model_capture = gtk_filter_list_model_new (g_object_ref (model),
+                                                            g_object_ref (GTK_FILTER (capture_filter)));
+  priv->shortcut_model_bubble = gtk_filter_list_model_new (g_object_ref (model),
+                                                           g_object_ref (GTK_FILTER (bubble_filter)));
+
+  ide_workspace_attach_shortcuts (self, GTK_WIDGET (self));
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]