[gnome-todo] window: Add fullscreen button and plumbing



commit 480e329b9715711f3473ba85fd103fa02966da64
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue Apr 28 18:14:43 2020 -0300

    window: Add fullscreen button and plumbing
    
    It's not super useful right now, but it'll be in the future,
    specially with 2+ monitors.
    
    https://gitlab.gnome.org/GNOME/gnome-todo/-/issues/325

 src/gtd-window.c  | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gtd-window.ui | 27 +++++++++++++++-
 2 files changed, 123 insertions(+), 1 deletion(-)
---
diff --git a/src/gtd-window.c b/src/gtd-window.c
index 94f410d..d9864a8 100644
--- a/src/gtd-window.c
+++ b/src/gtd-window.c
@@ -59,18 +59,24 @@ struct _GtdWindow
   GtkApplicationWindow application;
 
   GtkHeaderBar       *headerbar;
+  GtkWidget          *headerbar_box;
+  GtkRevealer        *headerbar_overlay_revealer;
   GtkStack           *stack;
   GtkWidget          *workspace_box_end;
   GtkWidget          *workspace_box_start;
   GtkListBox         *workspaces_listbox;
   GtdMenuButton      *workspaces_menu_button;
 
+  GtkEventController *overlay_motion_controller;
+
   GtdNotificationWidget *notification_widget;
 
   GPtrArray          *workspace_header_widgets;
 
   GtdWorkspace       *current_workspace;
   GListStore         *workspaces;
+
+  guint               toggle_headerbar_revealer_id;
 };
 
 typedef struct
@@ -230,6 +236,18 @@ remove_all_workspace_header_widgets (GtdWindow *self)
  * Callbacks
  */
 
+static gboolean
+toggle_headerbar_overlay_cb (gpointer user_data)
+{
+  GtdWindow *self = GTD_WINDOW (user_data);
+
+  gtk_revealer_set_reveal_child (self->headerbar_overlay_revealer,
+                                 !gtk_revealer_get_reveal_child (self->headerbar_overlay_revealer));
+
+  self->toggle_headerbar_revealer_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
 
 static void
 on_action_activate_workspace_activated_cb (GSimpleAction *simple,
@@ -245,6 +263,79 @@ on_action_activate_workspace_activated_cb (GSimpleAction *simple,
   gtk_stack_set_visible_child_name (self->stack, workspace_id);
 }
 
+static void
+on_action_toggle_fullscreen_state_changed_cb (GSimpleAction *simple,
+                                              GVariant      *state,
+                                              gpointer       user_data)
+{
+  GtkContainer *parent;
+  GtdWindow *self;
+  gboolean fullscreen;
+
+  self = GTD_WINDOW (user_data);
+  fullscreen = g_variant_get_boolean (state);
+  parent = GTK_CONTAINER (gtk_widget_get_parent (GTK_WIDGET (self->headerbar)));
+
+  g_clear_handle_id (&self->toggle_headerbar_revealer_id, g_source_remove);
+
+  gtk_header_bar_set_show_title_buttons (self->headerbar, !fullscreen);
+
+  g_object_ref (self->headerbar);
+  gtk_container_remove (parent, GTK_WIDGET (self->headerbar));
+
+  if (fullscreen)
+    {
+      gtk_event_controller_set_propagation_phase (self->overlay_motion_controller, GTK_PHASE_BUBBLE);
+      gtk_container_add (GTK_CONTAINER (self->headerbar_overlay_revealer), GTK_WIDGET (self->headerbar));
+      gtk_revealer_set_reveal_child (self->headerbar_overlay_revealer, TRUE);
+      gtk_window_fullscreen (GTK_WINDOW (self));
+
+      self->toggle_headerbar_revealer_id = g_timeout_add_seconds (2, toggle_headerbar_overlay_cb, self);
+    }
+  else
+    {
+      gtk_event_controller_set_propagation_phase (self->overlay_motion_controller, GTK_PHASE_NONE);
+      gtk_revealer_set_reveal_child (self->headerbar_overlay_revealer, FALSE);
+      gtk_container_add (GTK_CONTAINER (self->headerbar_box), GTK_WIDGET (self->headerbar));
+      gtk_window_unfullscreen (GTK_WINDOW (self));
+    }
+  g_object_unref (self->headerbar);
+
+  g_simple_action_set_state (simple, state);
+}
+
+static void
+on_overlay_motion_controller_motion_cb (GtkEventControllerMotion *controller,
+                                        gdouble                   x,
+                                        gdouble                   y,
+                                        GtdWindow                *self)
+{
+  const gint y_threashold = 5;
+  GtkWidget *hovered_widget;
+
+  hovered_widget = gtk_widget_pick (GTK_WIDGET (self), x, y, GTK_PICK_DEFAULT);
+
+  /* Show headerbar when hovering it */
+  if (hovered_widget &&
+      gtk_widget_is_ancestor (hovered_widget, GTK_WIDGET (self->headerbar_overlay_revealer)))
+    {
+      gtk_revealer_set_reveal_child (self->headerbar_overlay_revealer, TRUE);
+      g_clear_handle_id (&self->toggle_headerbar_revealer_id, g_source_remove);
+      return;
+    }
+
+  if (y <= y_threashold)
+    {
+      gtk_revealer_set_reveal_child (self->headerbar_overlay_revealer, TRUE);
+      g_clear_handle_id (&self->toggle_headerbar_revealer_id, g_source_remove);
+    }
+  else if (self->toggle_headerbar_revealer_id == 0 &&
+           gtk_revealer_get_reveal_child (self->headerbar_overlay_revealer))
+    {
+      self->toggle_headerbar_revealer_id = g_timeout_add (500, toggle_headerbar_overlay_cb, self);
+    }
+}
+
 static gint
 compare_workspaced_func (gconstpointer a,
                          gconstpointer b,
@@ -438,6 +529,7 @@ gtd_window_dispose (GObject *object)
 {
   GtdWindow *self = GTD_WINDOW (object);
 
+  g_clear_handle_id (&self->toggle_headerbar_revealer_id, g_source_remove);
   g_clear_object (&self->workspaces);
 
   G_OBJECT_CLASS (gtd_window_parent_class)->dispose (object);
@@ -489,13 +581,17 @@ gtd_window_class_init (GtdWindowClass *klass)
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/todo/ui/gtd-window.ui");
 
   gtk_widget_class_bind_template_child (widget_class, GtdWindow, headerbar);
+  gtk_widget_class_bind_template_child (widget_class, GtdWindow, headerbar_box);
+  gtk_widget_class_bind_template_child (widget_class, GtdWindow, headerbar_overlay_revealer);
   gtk_widget_class_bind_template_child (widget_class, GtdWindow, notification_widget);
+  gtk_widget_class_bind_template_child (widget_class, GtdWindow, overlay_motion_controller);
   gtk_widget_class_bind_template_child (widget_class, GtdWindow, stack);
   gtk_widget_class_bind_template_child (widget_class, GtdWindow, workspace_box_end);
   gtk_widget_class_bind_template_child (widget_class, GtdWindow, workspace_box_start);
   gtk_widget_class_bind_template_child (widget_class, GtdWindow, workspaces_menu_button);
   gtk_widget_class_bind_template_child (widget_class, GtdWindow, workspaces_listbox);
 
+  gtk_widget_class_bind_template_callback (widget_class, on_overlay_motion_controller_motion_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_stack_visible_child_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_workspaces_listbox_row_activated_cb);
 }
@@ -505,6 +601,7 @@ gtd_window_init (GtdWindow *self)
 {
   static const GActionEntry entries[] = {
     { "activate-workspace", on_action_activate_workspace_activated_cb, "s" },
+    { "toggle-fullscreen", NULL, NULL, "false", on_action_toggle_fullscreen_state_changed_cb },
   };
 
   g_action_map_add_action_entries (G_ACTION_MAP (self),
diff --git a/src/gtd-window.ui b/src/gtd-window.ui
index 493926f..9be2aa3 100644
--- a/src/gtd-window.ui
+++ b/src/gtd-window.ui
@@ -17,6 +17,22 @@
           </object>
         </child>
 
+        <child type="overlay">
+          <object class="GtkRevealer" id="headerbar_overlay_revealer">
+            <property name="transition-type">slide-down</property>
+            <property name="transition-duration">750</property>
+            <property name="can_focus">False</property>
+            <property name="valign">start</property>
+          </object>
+        </child>
+
+        <child>
+          <object class="GtkEventControllerMotion" id="overlay_motion_controller">
+            <property name="propagation-phase">none</property>
+            <signal name="motion" handler="on_overlay_motion_controller_motion_cb" object="GtdWindow" 
swapped="no" />
+          </object>
+        </child>
+
         <!-- Main Stack -->
         <child>
           <object class="GtkStack" id="stack">
@@ -35,7 +51,7 @@
       </object>
     </child>
     <child type="titlebar">
-      <object class="GtkBox">
+      <object class="GtkBox" id="headerbar_box">
         <child>
           <object class="GtkHeaderBar" id="headerbar">
             <property name="hexpand">1</property>
@@ -60,6 +76,15 @@
                 <property name="direction">none</property>
               </object>
             </child>
+
+            <!-- Fullscreen Button -->
+            <child type="end">
+              <object class="GtkToggleButton">
+                <property name="action-name">win.toggle-fullscreen</property>
+                <property name="icon-name">view-fullscreen-symbolic</property>
+              </object>
+            </child>
+
             <child type="end">
               <object class="GtkBox" id="workspace_box_end">
                 <property name="spacing">6</property>


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