[gnome-builder/wip/gtk4-port] libide/webkit: add rudimentary URL bar



commit 766b5f7aa0c6797cca34cbb8e8b01ce4120b5e22
Author: Christian Hergert <chergert redhat com>
Date:   Fri Jun 3 10:14:54 2022 -0700

    libide/webkit: add rudimentary URL bar
    
    Lots to do here to make it more functional, but this just gets something
    into place to iterate from.

 .../scalable/actions/lock-small-open-symbolic.svg  |   2 +
 .../scalable/actions/lock-small-symbolic.svg       |   2 +
 src/libide/webkit/ide-url-bar.c                    | 227 +++++++++++++++++++++
 src/libide/webkit/ide-url-bar.h                    |  37 ++++
 src/libide/webkit/ide-url-bar.ui                   |  59 ++++++
 src/libide/webkit/ide-webkit-page.c                |   4 +
 src/libide/webkit/ide-webkit-page.ui               |  20 +-
 src/libide/webkit/libide-webkit.gresource.xml      |   1 +
 src/libide/webkit/meson.build                      |   1 +
 9 files changed, 345 insertions(+), 8 deletions(-)
---
diff --git a/data/icons/hicolor/scalable/actions/lock-small-open-symbolic.svg 
b/data/icons/hicolor/scalable/actions/lock-small-open-symbolic.svg
new file mode 100644
index 000000000..8ab38a177
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lock-small-open-symbolic.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"; height="16px" viewBox="0 0 16 16" width="16px"><g 
fill="#2e3436"><path d="m 5 7.007812 c -0.554688 0.015626 -1 0.464844 -1 1.023438 v 3.96875 h 8 v -3.96875 c 
0 -0.558594 -0.445312 -1.007812 -1 -1.023438 z m 0 0"/><path d="m 12 3.023438 c -1.644531 0 -2.992188 
1.367187 -2.992188 3.015624 v 1.460938 h 2 v -1.460938 c 0 -0.585937 0.429688 -1.015624 0.992188 -1.015624 c 
0.566406 0 1 0.429687 1 1.015624 v 0.960938 h 2 v -0.960938 c 0 -1.648437 -1.351562 -3.015624 -3 -3.015624 z 
m 0 0"/></g></svg>
diff --git a/data/icons/hicolor/scalable/actions/lock-small-symbolic.svg 
b/data/icons/hicolor/scalable/actions/lock-small-symbolic.svg
new file mode 100644
index 000000000..8ac246c75
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/lock-small-symbolic.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"; height="16px" viewBox="0 0 16 16" width="16px"><path d="m 8 3 c 
-0.519531 0 -1.035156 0.132812 -1.5 0.402344 c -0.925781 0.535156 -1.5 1.523437 -1.5 2.59375 v 0.003906 v 
1.007812 c -0.554688 0.015626 -1 0.464844 -1 1.023438 v 3.96875 h 8 v -3.96875 c 0 -0.558594 -0.445312 
-1.007812 -1 -1.023438 v -1.011718 c 0 -1.070313 -0.574219 -2.058594 -1.5 -2.59375 c -0.464844 -0.269532 
-0.980469 -0.402344 -1.5 -0.402344 z m 0 1.644531 c 0.253906 0 0.503906 0.0625 0.730469 0.191407 c 0.453125 
0.261718 0.730469 0.746093 0.730469 1.269531 v 0.894531 h -2.921876 v -0.902344 c 0 -0.519531 0.277344 -1 
0.730469 -1.261718 c 0.226563 -0.128907 0.476563 -0.191407 0.730469 -0.191407 z m 0 0" fill="#2e3436"/></svg>
diff --git a/src/libide/webkit/ide-url-bar.c b/src/libide/webkit/ide-url-bar.c
new file mode 100644
index 000000000..a10a2336c
--- /dev/null
+++ b/src/libide/webkit/ide-url-bar.c
@@ -0,0 +1,227 @@
+/* ide-url-bar.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-url-bar"
+
+#include "ide-url-bar.h"
+
+struct _IdeUrlBar
+{
+  GtkWidget      parent_instance;
+
+  /* Owned references */
+  WebKitWebView *web_view;
+  GBindingGroup *web_view_bindings;
+
+  /* Template references */
+  GtkStack      *stack;
+  GtkLabel      *url_display;
+  GtkText       *url_editable;
+};
+
+enum {
+  PROP_0,
+  PROP_WEB_VIEW,
+  N_PROPS
+};
+
+G_DEFINE_FINAL_TYPE (IdeUrlBar, ide_url_bar, GTK_TYPE_WIDGET)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+on_editable_focus_enter_cb (IdeUrlBar               *self,
+                            GtkEventControllerFocus *focus)
+{
+  const char *uri;
+
+  g_assert (IDE_IS_URL_BAR (self));
+  g_assert (GTK_IS_EVENT_CONTROLLER_FOCUS (focus));
+
+  if (self->web_view == NULL)
+    return;
+
+  uri = webkit_web_view_get_uri (self->web_view);
+  gtk_editable_set_text (GTK_EDITABLE (self->url_editable), uri);
+  gtk_editable_select_region (GTK_EDITABLE (self->url_editable), 0, -1);
+}
+
+static void
+on_editable_focus_leave_cb (IdeUrlBar               *self,
+                            GtkEventControllerFocus *focus)
+{
+  g_assert (IDE_IS_URL_BAR (self));
+  g_assert (GTK_IS_EVENT_CONTROLLER_FOCUS (focus));
+
+  gtk_stack_set_visible_child_name (self->stack, "display");
+}
+
+static void
+on_editable_activate_cb (IdeUrlBar   *self,
+                         GtkEditable *editable)
+{
+  g_assert (IDE_IS_URL_BAR (self));
+  g_assert (GTK_IS_EDITABLE (editable));
+
+  if (self->web_view == NULL)
+    return;
+
+  webkit_web_view_load_uri (self->web_view,
+                            gtk_editable_get_text (editable));
+  gtk_widget_grab_focus (GTK_WIDGET (self->web_view));
+}
+
+static void
+on_click_gesture_pressed_cb (IdeUrlBar       *self,
+                             int              n_presses,
+                             double           x,
+                             double           y,
+                             GtkGestureClick *click)
+{
+  const char *name;
+
+  g_assert (IDE_IS_URL_BAR (self));
+  g_assert (GTK_IS_GESTURE_CLICK (click));
+
+  if (self->web_view == NULL)
+    return;
+
+  name = gtk_stack_get_visible_child_name (self->stack);
+  if (g_strcmp0 (name, "edit") == 0)
+    return;
+
+  gtk_gesture_set_state (GTK_GESTURE (click), GTK_EVENT_SEQUENCE_CLAIMED);
+  gtk_stack_set_visible_child_name (self->stack, "edit");
+  gtk_widget_grab_focus (GTK_WIDGET (self->url_editable));
+}
+
+static void
+ide_url_bar_dispose (GObject *object)
+{
+  IdeUrlBar *self = (IdeUrlBar *)object;
+
+  g_clear_object (&self->web_view_bindings);
+  g_clear_object (&self->web_view);
+
+  g_clear_pointer ((GtkWidget **)&self->stack, gtk_widget_unparent);
+
+  G_OBJECT_CLASS (ide_url_bar_parent_class)->dispose (object);
+}
+
+static void
+ide_url_bar_get_property (GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+  IdeUrlBar *self = IDE_URL_BAR (object);
+
+  switch (prop_id)
+    {
+    case PROP_WEB_VIEW:
+      g_value_set_object (value, ide_url_bar_get_web_view (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_url_bar_set_property (GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  IdeUrlBar *self = IDE_URL_BAR (object);
+
+  switch (prop_id)
+    {
+    case PROP_WEB_VIEW:
+      ide_url_bar_set_web_view (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_url_bar_class_init (IdeUrlBarClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose = ide_url_bar_dispose;
+  object_class->get_property = ide_url_bar_get_property;
+  object_class->set_property = ide_url_bar_set_property;
+
+  properties [PROP_WEB_VIEW] =
+    g_param_spec_object ("web-view", NULL, NULL,
+                         WEBKIT_TYPE_WEB_VIEW,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  gtk_widget_class_set_css_name (widget_class, "entry");
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+  gtk_widget_class_set_template_from_resource (widget_class, "/plugins/webkit/ide-url-bar.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdeUrlBar, url_display);
+  gtk_widget_class_bind_template_child (widget_class, IdeUrlBar, url_editable);
+  gtk_widget_class_bind_template_child (widget_class, IdeUrlBar, stack);
+  gtk_widget_class_bind_template_callback (widget_class, on_click_gesture_pressed_cb);
+  gtk_widget_class_bind_template_callback (widget_class, on_editable_focus_enter_cb);
+  gtk_widget_class_bind_template_callback (widget_class, on_editable_focus_leave_cb);
+  gtk_widget_class_bind_template_callback (widget_class, on_editable_activate_cb);
+}
+
+static void
+ide_url_bar_init (IdeUrlBar *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  self->web_view_bindings = g_binding_group_new ();
+  g_binding_group_bind (self->web_view_bindings, "uri",
+                        self->url_display, "label",
+                        G_BINDING_SYNC_CREATE);
+}
+
+WebKitWebView *
+ide_url_bar_get_web_view (IdeUrlBar *self)
+{
+  g_return_val_if_fail (IDE_IS_URL_BAR (self), NULL);
+
+  return self->web_view;
+}
+
+void
+ide_url_bar_set_web_view (IdeUrlBar     *self,
+                          WebKitWebView *web_view)
+{
+  g_return_if_fail (IDE_IS_URL_BAR (self));
+  g_return_if_fail (!web_view || WEBKIT_IS_WEB_VIEW (web_view));
+
+  if (g_set_object (&self->web_view, web_view))
+    {
+      g_binding_group_set_source (self->web_view_bindings, web_view);
+      gtk_widget_set_can_focus (GTK_WIDGET (self), web_view != NULL);
+      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WEB_VIEW]);
+    }
+}
diff --git a/src/libide/webkit/ide-url-bar.h b/src/libide/webkit/ide-url-bar.h
new file mode 100644
index 000000000..dd0d68a21
--- /dev/null
+++ b/src/libide/webkit/ide-url-bar.h
@@ -0,0 +1,37 @@
+/* ide-url-bar.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_URL_BAR (ide_url_bar_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeUrlBar, ide_url_bar, IDE, URL_BAR, GtkWidget)
+
+IdeUrlBar     *ide_url_bar_new          (void);
+WebKitWebView *ide_url_bar_get_web_view (IdeUrlBar *self);
+void           ide_url_bar_set_web_view (IdeUrlBar     *self,
+                                         WebKitWebView *web_view);
+
+G_END_DECLS
diff --git a/src/libide/webkit/ide-url-bar.ui b/src/libide/webkit/ide-url-bar.ui
new file mode 100644
index 000000000..7a4e0984a
--- /dev/null
+++ b/src/libide/webkit/ide-url-bar.ui
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="IdeUrlBar" parent="GtkWidget">
+    <child>
+      <object class="GtkGestureClick">
+        <property name="propagation-phase">capture</property>
+        <signal name="pressed" handler="on_click_gesture_pressed_cb" swapped="true" object="IdeUrlBar"/>
+      </object>
+    </child>
+    <child>
+      <object class="GtkStack" id="stack">
+        <property name="hexpand">true</property>
+        <child>
+          <object class="GtkStackPage">
+            <property name="name">display</property>
+            <property name="child">
+              <object class="GtkBox">
+                <child>
+                  <object class="GtkImage">
+                    <property name="margin-start">6</property>
+                    <property name="margin-end">6</property>
+                    <property name="icon-name">lock-small-open-symbolic</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="url_display">
+                    <property name="hexpand">true</property>
+                    <property name="xalign">0</property>
+                  </object>
+                </child>
+              </object>
+            </property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStackPage">
+            <property name="name">edit</property>
+            <property name="child">
+              <object class="GtkBox">
+                <child>
+                  <object class="GtkText" id="url_editable">
+                    <property name="hexpand">true</property>
+                    <signal name="activate" handler="on_editable_activate_cb" swapped="true" 
object="IdeUrlBar"/>
+                    <child>
+                      <object class="GtkEventControllerFocus">
+                        <signal name="enter" handler="on_editable_focus_enter_cb" swapped="true" 
object="IdeUrlBar"/>
+                        <signal name="leave" handler="on_editable_focus_leave_cb" swapped="true" 
object="IdeUrlBar"/>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/libide/webkit/ide-webkit-page.c b/src/libide/webkit/ide-webkit-page.c
index f9a5b1463..3b6a5b201 100644
--- a/src/libide/webkit/ide-webkit-page.c
+++ b/src/libide/webkit/ide-webkit-page.c
@@ -25,10 +25,12 @@
 #include <webkit2/webkit2.h>
 
 #include "ide-webkit-page.h"
+#include "ide-url-bar.h"
 
 typedef struct
 {
   GtkCenterBox  *toolbar;
+  IdeUrlBar     *url_bar;
   WebKitWebView *web_view;
 } IdeWebkitPagePrivate;
 
@@ -179,10 +181,12 @@ ide_webkit_page_class_init (IdeWebkitPageClass *klass)
   gtk_widget_class_set_template_from_resource (widget_class, "/plugins/webkit/ide-webkit-page.ui");
 
   gtk_widget_class_bind_template_child_private (widget_class, IdeWebkitPage, toolbar);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeWebkitPage, url_bar);
   gtk_widget_class_bind_template_child_private (widget_class, IdeWebkitPage, web_view);
   gtk_widget_class_bind_template_callback (widget_class, toolbar_notify_visible_cb);
 
   g_type_ensure (WEBKIT_TYPE_WEB_VIEW);
+  g_type_ensure (IDE_TYPE_URL_BAR);
 }
 
 static void
diff --git a/src/libide/webkit/ide-webkit-page.ui b/src/libide/webkit/ide-webkit-page.ui
index 4b9a3ee8f..d98c4c214 100644
--- a/src/libide/webkit/ide-webkit-page.ui
+++ b/src/libide/webkit/ide-webkit-page.ui
@@ -4,6 +4,12 @@
     <child>
       <object class="GtkBox">
         <property name="orientation">vertical</property>
+        <child>
+          <object class="WebKitWebView" id="web_view">
+            <property name="hexpand">true</property>
+            <property name="vexpand">true</property>
+          </object>
+        </child>
         <child>
           <object class="GtkCenterBox" id="toolbar">
             <signal name="notify::visible" handler="toolbar_notify_visible_cb" swapped="true" 
object="IdeWebkitPage"/>
@@ -15,6 +21,7 @@
               <object class="GtkBox">
                 <property name="orientation">horizontal</property>
                 <property name="spacing">3</property>
+                <property name="valign">center</property>
                 <child>
                   <object class="GtkButton">
                     <property name="icon-name">go-previous-symbolic</property>
@@ -27,18 +34,15 @@
                 </child>
               </object>
             </child>
-            <child>
-              <object class="GtkEntry">
+            <child type="center">
+              <object class="IdeUrlBar" id="url_bar">
+                <property name="hexpand">true</property>
+                <property name="valign">center</property>
+                <property name="web_view">web_view</property>
               </object>
             </child>
           </object>
         </child>
-        <child>
-          <object class="WebKitWebView" id="web_view">
-            <property name="hexpand">true</property>
-            <property name="vexpand">true</property>
-          </object>
-        </child>
       </object>
     </child>
   </template>
diff --git a/src/libide/webkit/libide-webkit.gresource.xml b/src/libide/webkit/libide-webkit.gresource.xml
index ee10c7d54..b665760ee 100644
--- a/src/libide/webkit/libide-webkit.gresource.xml
+++ b/src/libide/webkit/libide-webkit.gresource.xml
@@ -3,5 +3,6 @@
   <gresource prefix="/plugins/webkit">
     <file>webkit.plugin</file>
     <file preprocess="xml-stripblanks">ide-webkit-page.ui</file>
+    <file preprocess="xml-stripblanks">ide-url-bar.ui</file>
   </gresource>
 </gresources>
diff --git a/src/libide/webkit/meson.build b/src/libide/webkit/meson.build
index 21fa7e101..88b869b31 100644
--- a/src/libide/webkit/meson.build
+++ b/src/libide/webkit/meson.build
@@ -12,6 +12,7 @@ libide_include_directories += include_directories('.')
 
 libide_webkit_private_sources = [
   'ide-webkit-plugin.c',
+  'ide-url-bar.c',
 ]
 
 #


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