From 0a6aa2f8e33577de76eab40c153c65b915f9a8f4 Mon Sep 17 00:00:00 2001 From: Alexander Mikhaylenko Date: Mon, 7 Dec 2020 19:09:45 +0500 Subject: [PATCH 01/11] swipe-away-bin: Add hide() and reveal() Support programmatic revealing and not just removing. --- src/swipe-away-bin.c | 24 ++++++++++++++++++++++++ src/swipe-away-bin.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/src/swipe-away-bin.c b/src/swipe-away-bin.c index dca4723c4..629805161 100644 --- a/src/swipe-away-bin.c +++ b/src/swipe-away-bin.c @@ -262,6 +262,30 @@ phosh_swipe_away_bin_swipeable_init (HdySwipeableInterface *iface) } +void +phosh_swipe_away_bin_hide (PhoshSwipeAwayBin *self) +{ + g_return_if_fail (PHOSH_IS_SWIPE_AWAY_BIN (self)); + + if (self->animation) + phosh_animation_stop (self->animation); + + set_progress (self, 1); +} + + +void +phosh_swipe_away_bin_reveal (PhoshSwipeAwayBin *self) +{ + g_return_if_fail (PHOSH_IS_SWIPE_AWAY_BIN (self)); + + if (self->animation) + phosh_animation_stop (self->animation); + + animate (self, 200, 0, PHOSH_ANIMATION_TYPE_EASE_OUT_CUBIC); +} + + void phosh_swipe_away_bin_remove (PhoshSwipeAwayBin *self) { diff --git a/src/swipe-away-bin.h b/src/swipe-away-bin.h index 67930046e..2f37d8557 100644 --- a/src/swipe-away-bin.h +++ b/src/swipe-away-bin.h @@ -13,5 +13,7 @@ G_DECLARE_FINAL_TYPE (PhoshSwipeAwayBin, phosh_swipe_away_bin, PHOSH, SWIPE_AWAY_BIN, GtkEventBox) +void phosh_swipe_away_bin_hide (PhoshSwipeAwayBin *self); +void phosh_swipe_away_bin_reveal (PhoshSwipeAwayBin *self); void phosh_swipe_away_bin_remove (PhoshSwipeAwayBin *self); void phosh_swipe_away_bin_undo (PhoshSwipeAwayBin *self); -- GitLab From 39bc8796eccadc72a9745372592f5341dddeed41 Mon Sep 17 00:00:00 2001 From: Alexander Mikhaylenko Date: Tue, 8 Dec 2020 12:51:29 +0500 Subject: [PATCH 02/11] swipe-away-bin: Make orientable --- src/swipe-away-bin.c | 114 +++++++++++++++++++++++++++++++++++++++++-- src/ui/activity.ui | 1 + 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/src/swipe-away-bin.c b/src/swipe-away-bin.c index 629805161..61103a5af 100644 --- a/src/swipe-away-bin.c +++ b/src/swipe-away-bin.c @@ -18,10 +18,21 @@ enum { }; static guint signals[N_SIGNALS] = { 0 }; + +enum { + PROP_0, + PROP_ORIENTATION, + + LAST_PROP = PROP_ORIENTATION +}; + + struct _PhoshSwipeAwayBin { GtkEventBox parent_instance; + GtkOrientation orientation; + double progress; HdySwipeTracker *tracker; PhoshAnimation *animation; @@ -30,6 +41,7 @@ struct _PhoshSwipeAwayBin static void phosh_swipe_away_bin_swipeable_init (HdySwipeableInterface *iface); G_DEFINE_TYPE_WITH_CODE (PhoshSwipeAwayBin, phosh_swipe_away_bin, GTK_TYPE_EVENT_BOX, + G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL) G_IMPLEMENT_INTERFACE (HDY_TYPE_SWIPEABLE, phosh_swipe_away_bin_swipeable_init)) @@ -118,6 +130,19 @@ end_swipe_cb (PhoshSwipeAwayBin *self, } +static void +update_orientation (PhoshSwipeAwayBin *self) +{ + gboolean reversed = + self->orientation == GTK_ORIENTATION_HORIZONTAL && + gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL; + + hdy_swipe_tracker_set_reversed (self->tracker, reversed); + + gtk_widget_queue_allocate (GTK_WIDGET (self)); +} + + static void phosh_swipe_away_bin_finalize (GObject *object) { @@ -130,6 +155,51 @@ phosh_swipe_away_bin_finalize (GObject *object) } +static void +phosh_swipe_away_bin_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (object); + + switch (prop_id) { + case PROP_ORIENTATION: + g_value_set_enum (value, self->orientation); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + + +static void +phosh_swipe_away_bin_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (object); + + switch (prop_id) { + case PROP_ORIENTATION: + { + GtkOrientation orientation = g_value_get_enum (value); + if (orientation != self->orientation) { + self->orientation = orientation; + update_orientation (self); + g_object_notify (G_OBJECT (self), "orientation"); + } + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + + static void phosh_swipe_away_bin_size_allocate (GtkWidget *widget, GtkAllocation *alloc) @@ -143,8 +213,18 @@ phosh_swipe_away_bin_size_allocate (GtkWidget *widget, if (!child || !gtk_widget_get_visible (child)) return; - child_alloc.x = alloc->x; - child_alloc.y = alloc->y - (int) (self->progress * alloc->height); + if (self->orientation == GTK_ORIENTATION_HORIZONTAL) { + if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL) + child_alloc.x = alloc->x + (int) (self->progress * alloc->width); + else + child_alloc.x = alloc->x - (int) (self->progress * alloc->width); + + child_alloc.y = alloc->y; + } else { + child_alloc.x = alloc->x; + child_alloc.y = alloc->y - (int) (self->progress * alloc->height); + } + child_alloc.width = alloc->width; child_alloc.height = alloc->height; @@ -152,6 +232,16 @@ phosh_swipe_away_bin_size_allocate (GtkWidget *widget, } +static void +phosh_swipe_away_bin_direction_changed (GtkWidget *widget, + GtkTextDirection previous_direction) +{ + PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (widget); + + update_orientation (self); +} + + static void phosh_swipe_away_bin_class_init (PhoshSwipeAwayBinClass *klass) { @@ -159,7 +249,14 @@ phosh_swipe_away_bin_class_init (PhoshSwipeAwayBinClass *klass) GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->finalize = phosh_swipe_away_bin_finalize; + object_class->get_property = phosh_swipe_away_bin_get_property; + object_class->set_property = phosh_swipe_away_bin_set_property; widget_class->size_allocate = phosh_swipe_away_bin_size_allocate; + widget_class->direction_changed = phosh_swipe_away_bin_direction_changed; + + g_object_class_override_property (object_class, + PROP_ORIENTATION, + "orientation"); signals[REMOVED] = g_signal_new ("removed", @@ -179,9 +276,11 @@ phosh_swipe_away_bin_init (PhoshSwipeAwayBin *self) { self->tracker = hdy_swipe_tracker_new (HDY_SWIPEABLE (self)); - gtk_orientable_set_orientation (GTK_ORIENTABLE (self->tracker), - GTK_ORIENTATION_VERTICAL); + g_object_bind_property (self, "orientation", + self->tracker, "orientation", + G_BINDING_SYNC_CREATE); hdy_swipe_tracker_set_allow_mouse_drag (self->tracker, TRUE); + update_orientation (self); g_signal_connect_object (self->tracker, "begin-swipe", G_CALLBACK (begin_swipe_cb), self, @@ -207,7 +306,12 @@ phosh_swipe_away_bin_get_swipe_tracker (HdySwipeable *swipeable) static double phosh_swipe_away_bin_get_distance (HdySwipeable *swipeable) { - return (double) gtk_widget_get_allocated_height (GTK_WIDGET (swipeable)); + PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (swipeable); + + if (self->orientation == GTK_ORIENTATION_HORIZONTAL) + return (double) gtk_widget_get_allocated_width (GTK_WIDGET (self)); + else + return (double) gtk_widget_get_allocated_height (GTK_WIDGET (self)); } diff --git a/src/ui/activity.ui b/src/ui/activity.ui index 6749c5e25..4a140b2d4 100644 --- a/src/ui/activity.ui +++ b/src/ui/activity.ui @@ -8,6 +8,7 @@ True + vertical -- GitLab From 42c7eaf1eb0ddc52fc68c8f582f682323603ff44 Mon Sep 17 00:00:00 2001 From: Alexander Mikhaylenko Date: Tue, 8 Dec 2020 13:23:16 +0500 Subject: [PATCH 03/11] swipe-away-bin: Add property to allow swipes in the other direction --- src/swipe-away-bin.c | 61 +++++++++++++++++++++++++++++++++++++++++--- src/swipe-away-bin.h | 4 +++ 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/swipe-away-bin.c b/src/swipe-away-bin.c index 61103a5af..f29e84e77 100644 --- a/src/swipe-away-bin.c +++ b/src/swipe-away-bin.c @@ -21,10 +21,12 @@ static guint signals[N_SIGNALS] = { 0 }; enum { PROP_0, + PROP_ALLOW_NEGATIVE, PROP_ORIENTATION, LAST_PROP = PROP_ORIENTATION }; +static GParamSpec *props[LAST_PROP]; struct _PhoshSwipeAwayBin @@ -32,6 +34,7 @@ struct _PhoshSwipeAwayBin GtkEventBox parent_instance; GtkOrientation orientation; + gboolean allow_negative; double progress; HdySwipeTracker *tracker; @@ -164,6 +167,10 @@ phosh_swipe_away_bin_get_property (GObject *object, PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (object); switch (prop_id) { + case PROP_ALLOW_NEGATIVE: + g_value_set_boolean (value, phosh_swipe_away_bin_get_allow_negative (self)); + break; + case PROP_ORIENTATION: g_value_set_enum (value, self->orientation); break; @@ -183,6 +190,10 @@ phosh_swipe_away_bin_set_property (GObject *object, PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (object); switch (prop_id) { + case PROP_ALLOW_NEGATIVE: + phosh_swipe_away_bin_set_allow_negative (self, g_value_get_boolean (value)); + break; + case PROP_ORIENTATION: { GtkOrientation orientation = g_value_get_enum (value); @@ -254,6 +265,15 @@ phosh_swipe_away_bin_class_init (PhoshSwipeAwayBinClass *klass) widget_class->size_allocate = phosh_swipe_away_bin_size_allocate; widget_class->direction_changed = phosh_swipe_away_bin_direction_changed; + props[PROP_ALLOW_NEGATIVE] = + g_param_spec_boolean ("allow-negative", + "Allow Negative", + "Use [-1:1] progress range instead of [0:1]", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + g_object_class_install_properties (object_class, LAST_PROP, props); + g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation"); @@ -335,12 +355,21 @@ static double * phosh_swipe_away_bin_get_snap_points (HdySwipeable *swipeable, int *n_snap_points) { - double *points = g_new0 (double, 2); + PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (swipeable); + int n = self->allow_negative ? 3 : 2; + double *points; - points[1] = 1; + points = g_new0 (double, n); + + if (self->allow_negative) { + points[0] = -1; + points[2] = 1; + } else { + points[1] = 1; + } if (n_snap_points) - *n_snap_points = 2; + *n_snap_points = n; return points; } @@ -366,6 +395,32 @@ phosh_swipe_away_bin_swipeable_init (HdySwipeableInterface *iface) } +gboolean +phosh_swipe_away_bin_get_allow_negative (PhoshSwipeAwayBin *self) +{ + g_return_val_if_fail (PHOSH_IS_SWIPE_AWAY_BIN (self), FALSE); + + return self->allow_negative; +} + + +void +phosh_swipe_away_bin_set_allow_negative (PhoshSwipeAwayBin *self, + gboolean allow_negative) +{ + g_return_if_fail (PHOSH_IS_SWIPE_AWAY_BIN (self)); + + allow_negative = !!allow_negative; + + if (allow_negative == self->allow_negative) + return; + + self->allow_negative = allow_negative; + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALLOW_NEGATIVE]); +} + + void phosh_swipe_away_bin_hide (PhoshSwipeAwayBin *self) { diff --git a/src/swipe-away-bin.h b/src/swipe-away-bin.h index 2f37d8557..6a72b996c 100644 --- a/src/swipe-away-bin.h +++ b/src/swipe-away-bin.h @@ -13,6 +13,10 @@ G_DECLARE_FINAL_TYPE (PhoshSwipeAwayBin, phosh_swipe_away_bin, PHOSH, SWIPE_AWAY_BIN, GtkEventBox) +gboolean phosh_swipe_away_bin_get_allow_negative (PhoshSwipeAwayBin *self); +void phosh_swipe_away_bin_set_allow_negative (PhoshSwipeAwayBin *self, + gboolean allow_negative); + void phosh_swipe_away_bin_hide (PhoshSwipeAwayBin *self); void phosh_swipe_away_bin_reveal (PhoshSwipeAwayBin *self); void phosh_swipe_away_bin_remove (PhoshSwipeAwayBin *self); -- GitLab From 56e22ad8d7563a9e462b58631403a8229d9b1881 Mon Sep 17 00:00:00 2001 From: Alexander Mikhaylenko Date: Tue, 8 Dec 2020 17:56:23 +0500 Subject: [PATCH 04/11] swipe-away-bin: Add reserve-size property --- src/swipe-away-bin.c | 126 +++++++++++++++++++++++++++++++++++++++---- src/swipe-away-bin.h | 4 ++ 2 files changed, 119 insertions(+), 11 deletions(-) diff --git a/src/swipe-away-bin.c b/src/swipe-away-bin.c index f29e84e77..46ccf565f 100644 --- a/src/swipe-away-bin.c +++ b/src/swipe-away-bin.c @@ -22,6 +22,7 @@ static guint signals[N_SIGNALS] = { 0 }; enum { PROP_0, PROP_ALLOW_NEGATIVE, + PROP_RESERVE_SIZE, PROP_ORIENTATION, LAST_PROP = PROP_ORIENTATION @@ -35,8 +36,10 @@ struct _PhoshSwipeAwayBin GtkOrientation orientation; gboolean allow_negative; + gboolean reserve_size; double progress; + int distance; HdySwipeTracker *tracker; PhoshAnimation *animation; }; @@ -171,6 +174,10 @@ phosh_swipe_away_bin_get_property (GObject *object, g_value_set_boolean (value, phosh_swipe_away_bin_get_allow_negative (self)); break; + case PROP_RESERVE_SIZE: + g_value_set_boolean (value, phosh_swipe_away_bin_get_reserve_size (self)); + break; + case PROP_ORIENTATION: g_value_set_enum (value, self->orientation); break; @@ -194,6 +201,10 @@ phosh_swipe_away_bin_set_property (GObject *object, phosh_swipe_away_bin_set_allow_negative (self, g_value_get_boolean (value)); break; + case PROP_RESERVE_SIZE: + phosh_swipe_away_bin_set_reserve_size (self, g_value_get_boolean (value)); + break; + case PROP_ORIENTATION: { GtkOrientation orientation = g_value_get_enum (value); @@ -224,25 +235,84 @@ phosh_swipe_away_bin_size_allocate (GtkWidget *widget, if (!child || !gtk_widget_get_visible (child)) return; + child_alloc.y = alloc->y; + child_alloc.x = alloc->x; + child_alloc.width = alloc->width; + child_alloc.height = alloc->height; + if (self->orientation == GTK_ORIENTATION_HORIZONTAL) { + if (self->reserve_size) { + self->distance = alloc->width / 3; + + child_alloc.width = self->distance; + child_alloc.x += self->distance; + } else { + self->distance = alloc->width; + } + if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL) - child_alloc.x = alloc->x + (int) (self->progress * alloc->width); + child_alloc.x += (int) (self->progress * self->distance); else - child_alloc.x = alloc->x - (int) (self->progress * alloc->width); + child_alloc.x -= (int) (self->progress * self->distance); - child_alloc.y = alloc->y; } else { - child_alloc.x = alloc->x; - child_alloc.y = alloc->y - (int) (self->progress * alloc->height); + if (self->reserve_size) { + self->distance = alloc->height / 3; + + child_alloc.height = self->distance; + child_alloc.y += self->distance; + } else { + self->distance = alloc->height; + } + + child_alloc.y -= (int) (self->progress * self->distance); } - child_alloc.width = alloc->width; - child_alloc.height = alloc->height; gtk_widget_size_allocate (child, &child_alloc); } +static void +phosh_swipe_away_bin_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (widget); + + GTK_WIDGET_CLASS (phosh_swipe_away_bin_parent_class)->get_preferred_width (widget, minimum, natural); + + if (self->reserve_size && + self->orientation == GTK_ORIENTATION_HORIZONTAL) { + if (minimum) + *minimum *= 3; + + if (natural) + *natural *= 3; + } +} + + +static void +phosh_swipe_away_bin_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (widget); + + GTK_WIDGET_CLASS (phosh_swipe_away_bin_parent_class)->get_preferred_height (widget, minimum, natural); + + if (self->reserve_size && + self->orientation == GTK_ORIENTATION_VERTICAL) { + if (minimum) + *minimum *= 3; + + if (natural) + *natural *= 3; + } +} + + static void phosh_swipe_away_bin_direction_changed (GtkWidget *widget, GtkTextDirection previous_direction) @@ -263,6 +333,8 @@ phosh_swipe_away_bin_class_init (PhoshSwipeAwayBinClass *klass) object_class->get_property = phosh_swipe_away_bin_get_property; object_class->set_property = phosh_swipe_away_bin_set_property; widget_class->size_allocate = phosh_swipe_away_bin_size_allocate; + widget_class->get_preferred_width = phosh_swipe_away_bin_get_preferred_width; + widget_class->get_preferred_height = phosh_swipe_away_bin_get_preferred_height; widget_class->direction_changed = phosh_swipe_away_bin_direction_changed; props[PROP_ALLOW_NEGATIVE] = @@ -272,6 +344,13 @@ phosh_swipe_away_bin_class_init (PhoshSwipeAwayBinClass *klass) FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + props[PROP_RESERVE_SIZE] = + g_param_spec_boolean ("reserve-size", + "Reserve Size", + "Allocate larger size than the child so that the child is never clipped when animating", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + g_object_class_install_properties (object_class, LAST_PROP, props); g_object_class_override_property (object_class, @@ -328,10 +407,7 @@ phosh_swipe_away_bin_get_distance (HdySwipeable *swipeable) { PhoshSwipeAwayBin *self = PHOSH_SWIPE_AWAY_BIN (swipeable); - if (self->orientation == GTK_ORIENTATION_HORIZONTAL) - return (double) gtk_widget_get_allocated_width (GTK_WIDGET (self)); - else - return (double) gtk_widget_get_allocated_height (GTK_WIDGET (self)); + return self->distance; } @@ -421,6 +497,34 @@ phosh_swipe_away_bin_set_allow_negative (PhoshSwipeAwayBin *self, } +gboolean +phosh_swipe_away_bin_get_reserve_size (PhoshSwipeAwayBin *self) +{ + g_return_val_if_fail (PHOSH_IS_SWIPE_AWAY_BIN (self), FALSE); + + return self->reserve_size; +} + + +void +phosh_swipe_away_bin_set_reserve_size (PhoshSwipeAwayBin *self, + gboolean reserve_size) +{ + g_return_if_fail (PHOSH_IS_SWIPE_AWAY_BIN (self)); + + reserve_size = !!reserve_size; + + if (reserve_size == self->reserve_size) + return; + + self->reserve_size = reserve_size; + + gtk_widget_queue_resize (GTK_WIDGET (self)); + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RESERVE_SIZE]); +} + + void phosh_swipe_away_bin_hide (PhoshSwipeAwayBin *self) { diff --git a/src/swipe-away-bin.h b/src/swipe-away-bin.h index 6a72b996c..73ab3e96e 100644 --- a/src/swipe-away-bin.h +++ b/src/swipe-away-bin.h @@ -17,6 +17,10 @@ gboolean phosh_swipe_away_bin_get_allow_negative (PhoshSwipeAwayBin *self); void phosh_swipe_away_bin_set_allow_negative (PhoshSwipeAwayBin *self, gboolean allow_negative); +gboolean phosh_swipe_away_bin_get_reserve_size (PhoshSwipeAwayBin *self); +void phosh_swipe_away_bin_set_reserve_size (PhoshSwipeAwayBin *self, + gboolean reserve_size); + void phosh_swipe_away_bin_hide (PhoshSwipeAwayBin *self); void phosh_swipe_away_bin_reveal (PhoshSwipeAwayBin *self); void phosh_swipe_away_bin_remove (PhoshSwipeAwayBin *self); -- GitLab From 2fe2cabe2b8dafbe7eca546f564dad044767c2c9 Mon Sep 17 00:00:00 2001 From: Alexander Mikhaylenko Date: Tue, 8 Dec 2020 18:26:01 +0500 Subject: [PATCH 05/11] panel: Use GtkGestureMultiPress and released signal for closing Make sure we don't interfere with swipes in future. --- src/panel.c | 17 ++++++++--------- src/ui/top-panel.ui | 4 ++++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/panel.c b/src/panel.c index 055a04707..a60a2f79a 100644 --- a/src/panel.c +++ b/src/panel.c @@ -59,6 +59,8 @@ typedef struct { GdkSeat *seat; GSimpleActionGroup *actions; + + GtkGesture *click_gesture; /* needed so that the gesture isn't destroyed immediately */ } PhoshPanelPrivate; typedef struct _PhoshPanel @@ -259,12 +261,11 @@ on_key_press_event (PhoshPanel *self, GdkEventKey *event, gpointer data) } -static gboolean -on_button_press_event (PhoshPanel *self, GdkEventKey *event, gpointer data) +static void +released (PhoshPanel *self) { - phosh_trigger_feedback ("button-pressed"); + phosh_trigger_feedback ("button-released"); phosh_panel_fold (self); - return FALSE; } @@ -331,15 +332,11 @@ phosh_panel_constructed (GObject *object) } /* Settings menu and it's top-bar / menu */ - gtk_widget_add_events (GTK_WIDGET (self), GDK_KEY_PRESS_MASK); + gtk_widget_add_events (GTK_WIDGET (self), GDK_ALL_EVENTS_MASK); g_signal_connect (G_OBJECT (self), "key-press-event", G_CALLBACK (on_key_press_event), NULL); - g_signal_connect (G_OBJECT (self), - "button-press-event", - G_CALLBACK (on_button_press_event), - NULL); priv->actions = g_simple_action_group_new (); gtk_widget_insert_action_group (GTK_WIDGET (self), "panel", @@ -397,6 +394,8 @@ phosh_panel_class_init (PhoshPanelClass *klass) gtk_widget_class_bind_template_child_private (widget_class, PhoshPanel, box); gtk_widget_class_bind_template_child_private (widget_class, PhoshPanel, stack); gtk_widget_class_bind_template_child_private (widget_class, PhoshPanel, settings); + gtk_widget_class_bind_template_child_private (widget_class, PhoshPanel, click_gesture); + gtk_widget_class_bind_template_callback (widget_class, released); } diff --git a/src/ui/top-panel.ui b/src/ui/top-panel.ui index f896a65c0..698795dc4 100644 --- a/src/ui/top-panel.ui +++ b/src/ui/top-panel.ui @@ -259,4 +259,8 @@ + + PhoshPanel + + -- GitLab From b32109b848ba24b31c2db42e500834d2f08203ce Mon Sep 17 00:00:00 2001 From: Alexander Mikhaylenko Date: Wed, 9 Dec 2020 14:02:10 +0500 Subject: [PATCH 06/11] notification-frame: Reimplement activation via GtkGestureMultiPress Unfortunately, in GTK 3 it's not possible to use single click row activation together with swipes; they will interfere. Meanwhile, we still need activation for keynav, so switch to double click activation and implement it manually instead. Use this chance to unify click handling with the header. --- src/notifications/notification-frame.c | 135 +++++++++++++++++++++++-- src/ui/notification-frame.ui | 18 +++- tests/test-notification-frame.c | 35 ------- 3 files changed, 140 insertions(+), 48 deletions(-) diff --git a/src/notifications/notification-frame.c b/src/notifications/notification-frame.c index 861a5a8dd..23db3533b 100644 --- a/src/notifications/notification-frame.c +++ b/src/notifications/notification-frame.c @@ -15,6 +15,8 @@ #include "util.h" #include "timestamp-label.h" +#include + /** * SECTION:notification-frame * @short_description: A frame containing one or more notifications @@ -36,6 +38,14 @@ struct _PhoshNotificationFrame { GtkWidget *img_icon; GtkWidget *list_notifs; GtkWidget *updated; + + /* needed so that the gestures aren't immediately destroyed */ + GtkGesture *header_click_gesture; + GtkGesture *list_click_gesture; + + int start_x; + int start_y; + GtkListBoxRow *active_row; }; typedef struct _PhoshNotificationFrame PhoshNotificationFrame; @@ -43,6 +53,9 @@ typedef struct _PhoshNotificationFrame PhoshNotificationFrame; G_DEFINE_TYPE (PhoshNotificationFrame, phosh_notification_frame, GTK_TYPE_BOX) +#define DRAG_THRESHOLD_DISTANCE 16 + + enum { SIGNAL_EMPTY, N_SIGNALS @@ -65,22 +78,118 @@ phosh_notification_frame_finalize (GObject *object) } -/* When the title row is clicked we proxy it to the first item */ static gboolean -header_activated (PhoshNotificationFrame *self, GdkEventButton *event) +motion_notify (PhoshNotificationFrame *self, + GdkEventMotion *event) { - g_autoptr (PhoshNotification) notification = NULL; + if (self->start_x >= 0 && self->start_y >= 0) { + int current_x, current_y; + double dx, dy; + + gtk_widget_translate_coordinates (GTK_WIDGET (self), + gtk_widget_get_toplevel (GTK_WIDGET (self)), + event->x, event->y, + ¤t_x, ¤t_y); + + dx = current_x - self->start_x; + dy = current_y - self->start_y; + + if (sqrt (dx * dx + dy * dy) > DRAG_THRESHOLD_DISTANCE) { + gtk_gesture_set_state (self->header_click_gesture, GTK_EVENT_SEQUENCE_DENIED); + gtk_gesture_set_state (self->list_click_gesture, GTK_EVENT_SEQUENCE_DENIED); + } + } - g_return_val_if_fail (PHOSH_IS_NOTIFICATION_FRAME (self), FALSE); + return GDK_EVENT_PROPAGATE; +} - notification = g_list_model_get_item (self->model, 0); - g_return_val_if_fail (PHOSH_IS_NOTIFICATION (notification), FALSE); +static void +pressed (PhoshNotificationFrame *self, + int n_press, + double x, + double y, + GtkGesture *gesture, + GtkGesture *other_gesture) +{ + GdkEventSequence *sequence = + gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture)); + + if (n_press != 1) { + gtk_gesture_set_sequence_state (gesture, sequence, GTK_EVENT_SEQUENCE_DENIED); + + return; + } + + gtk_widget_translate_coordinates (self->box, + gtk_widget_get_toplevel (GTK_WIDGET (self)), + x, y, + &self->start_x, &self->start_y); + + /* When the title row is clicked we proxy it to the first item */ + self->active_row = + gtk_list_box_get_row_at_y (GTK_LIST_BOX (self->list_notifs), + gesture == self->header_click_gesture ? 0 : y); + + gtk_gesture_set_sequence_state (other_gesture, sequence, GTK_EVENT_SEQUENCE_DENIED); +} + +static void +header_pressed (PhoshNotificationFrame *self, + int n_press, + double x, + double y) +{ + pressed (self, n_press, x, y, + self->header_click_gesture, + self->list_click_gesture); +} + + +static void +list_pressed (PhoshNotificationFrame *self, + int n_press, + double x, + double y) +{ + pressed (self, n_press, x, y, + self->list_click_gesture, + self->header_click_gesture); +} + + +static void +released (PhoshNotificationFrame *self, + int n_press, + double x, + double y, + GtkGesture *gesture) +{ + GtkListBoxRow *pressed_row = self->active_row; + GtkListBoxRow *active_row; + PhoshNotificationContent *content; + PhoshNotification *notification; + + /* When the title row is clicked we proxy it to the first item */ + active_row = + gtk_list_box_get_row_at_y (GTK_LIST_BOX (self->list_notifs), + gesture == self->header_click_gesture ? 0 : y); + + self->active_row = NULL; + self->start_x = -1; + self->start_y = -1; + + if (pressed_row != active_row) { + gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED); + + return; + } + + content = PHOSH_NOTIFICATION_CONTENT (active_row); + notification = phosh_notification_content_get_notification (content); phosh_notification_activate (notification, PHOSH_NOTIFICATION_DEFAULT_ACTION); - - return FALSE; } @@ -127,8 +236,13 @@ phosh_notification_frame_class_init (PhoshNotificationFrameClass *klass) gtk_widget_class_bind_template_child (widget_class, PhoshNotificationFrame, img_icon); gtk_widget_class_bind_template_child (widget_class, PhoshNotificationFrame, list_notifs); gtk_widget_class_bind_template_child (widget_class, PhoshNotificationFrame, updated); + gtk_widget_class_bind_template_child (widget_class, PhoshNotificationFrame, header_click_gesture); + gtk_widget_class_bind_template_child (widget_class, PhoshNotificationFrame, list_click_gesture); - gtk_widget_class_bind_template_callback (widget_class, header_activated); + gtk_widget_class_bind_template_callback (widget_class, motion_notify); + gtk_widget_class_bind_template_callback (widget_class, header_pressed); + gtk_widget_class_bind_template_callback (widget_class, list_pressed); + gtk_widget_class_bind_template_callback (widget_class, released); gtk_widget_class_bind_template_callback (widget_class, notification_activated); gtk_widget_class_set_css_name (widget_class, "phosh-notification-frame"); @@ -138,6 +252,9 @@ phosh_notification_frame_class_init (PhoshNotificationFrameClass *klass) static void phosh_notification_frame_init (PhoshNotificationFrame *self) { + self->start_x = -1; + self->start_y = -1; + gtk_widget_init_template (GTK_WIDGET (self)); } diff --git a/src/ui/notification-frame.ui b/src/ui/notification-frame.ui index bbb1e3f7f..2a1789c29 100644 --- a/src/ui/notification-frame.ui +++ b/src/ui/notification-frame.ui @@ -5,12 +5,12 @@ True vertical start + - + True False - GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK - + GDK_ALL_EVENTS_MASK True @@ -75,10 +75,20 @@ True - True + False none + + header + + + + + list_notifs + + + diff --git a/tests/test-notification-frame.c b/tests/test-notification-frame.c index e7b69b934..f8de55394 100644 --- a/tests/test-notification-frame.c +++ b/tests/test-notification-frame.c @@ -50,40 +50,6 @@ test_phosh_notification_frame_new (void) } -static void -test_phosh_notification_frame_header_activated (void) -{ - g_autoptr (PhoshNotification) noti = NULL; - GtkWidget *frame = NULL; - g_autoptr (GDateTime) now = g_date_time_new_now_local (); - - noti = phosh_notification_new (0, - NULL, - NULL, - "Hey", - "Testing", - NULL, - NULL, - PHOSH_NOTIFICATION_URGENCY_NORMAL, - NULL, - FALSE, - FALSE, - NULL, - now); - - frame = phosh_notification_frame_new (); - phosh_notification_frame_bind_notification (PHOSH_NOTIFICATION_FRAME (frame), - noti); - g_signal_connect (noti, "actioned", G_CALLBACK (actioned), NULL); - - actioned_called = FALSE; - - header_activated (PHOSH_NOTIFICATION_FRAME (frame), - (GdkEventButton *) gdk_event_new (GDK_BUTTON_PRESS)); - g_assert_true (actioned_called); -} - - static void test_phosh_notification_frame_notification_activated (void) { @@ -130,7 +96,6 @@ main (int argc, char **argv) gtk_test_init (&argc, &argv, NULL); g_test_add_func ("/phosh/notification-frame/new", test_phosh_notification_frame_new); - g_test_add_func ("/phosh/notification-frame/header-activated", test_phosh_notification_frame_header_activated); g_test_add_func ("/phosh/notification-frame/notification-activated", test_phosh_notification_frame_notification_activated); return g_test_run (); -- GitLab From 789214c0e420f3780e9200a6bd43a872dca84b60 Mon Sep 17 00:00:00 2001 From: Alexander Mikhaylenko Date: Mon, 7 Dec 2020 18:01:27 +0500 Subject: [PATCH 07/11] notification-banner: Use template --- src/notifications/notification-banner.c | 9 +++++---- src/phosh.gresources.xml | 1 + src/ui/notification-banner.ui | 10 ++++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 src/ui/notification-banner.ui diff --git a/src/notifications/notification-banner.c b/src/notifications/notification-banner.c index 297ab8ade..e843d968b 100644 --- a/src/notifications/notification-banner.c +++ b/src/notifications/notification-banner.c @@ -250,6 +250,9 @@ phosh_notification_banner_class_init (PhoshNotificationBannerClass *klass) g_object_class_install_properties (object_class, LAST_PROP, props); + gtk_widget_class_set_template_from_resource (widget_class, + "/sm/puri/phosh/ui/notification-banner.ui"); + gtk_widget_class_set_css_name (widget_class, "phosh-notification-banner"); } @@ -258,6 +261,8 @@ static void phosh_notification_banner_init (PhoshNotificationBanner *self) { self->animation.progress = 0.0; + + gtk_widget_init_template (GTK_WIDGET (self)); } @@ -275,12 +280,8 @@ phosh_notification_banner_new (PhoshNotification *notification) "margin-top", -300, "layer-shell", phosh_wayland_get_zwlr_layer_shell_v1 (wl), "anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, - "height", 50, "width", MIN (width, 450), "layer", ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, - "kbd-interactivity", FALSE, - "exclusive-zone", 0, - "namespace", "phosh notification", NULL); } diff --git a/src/phosh.gresources.xml b/src/phosh.gresources.xml index c6478786a..e4ff7a90c 100644 --- a/src/phosh.gresources.xml +++ b/src/phosh.gresources.xml @@ -8,6 +8,7 @@ ui/home.ui ui/lockscreen.ui ui/media-player.ui + ui/notification-banner.ui ui/notification-content.ui ui/notification-frame.ui ui/polkit-auth-prompt.ui diff --git a/src/ui/notification-banner.ui b/src/ui/notification-banner.ui new file mode 100644 index 000000000..c1308ea65 --- /dev/null +++ b/src/ui/notification-banner.ui @@ -0,0 +1,10 @@ + + + + + -- GitLab From 8eb15b68ee5297e0b8a6c3f2b799c4f551e72fea Mon Sep 17 00:00:00 2001 From: Alexander Mikhaylenko Date: Wed, 9 Dec 2020 15:10:33 +0500 Subject: [PATCH 08/11] notification-frame: Support swipe-to-remove --- src/notifications/notification-frame.c | 28 ++++- src/notifications/notification-frame.h | 2 +- src/style.css | 4 +- src/ui/notification-frame.ui | 136 ++++++++++++++----------- 4 files changed, 104 insertions(+), 66 deletions(-) diff --git a/src/notifications/notification-frame.c b/src/notifications/notification-frame.c index 23db3533b..644f3c5da 100644 --- a/src/notifications/notification-frame.c +++ b/src/notifications/notification-frame.c @@ -12,6 +12,7 @@ #include "notification-content.h" #include "notification-frame.h" #include "notification-source.h" +#include "swipe-away-bin.h" #include "util.h" #include "timestamp-label.h" @@ -25,7 +26,7 @@ struct _PhoshNotificationFrame { - GtkBox parent; + GtkEventBox parent; GListModel *model; gulong model_watch; @@ -34,6 +35,7 @@ struct _PhoshNotificationFrame { GBinding *bind_icon; GBinding *bind_timestamp; + GtkWidget *box; GtkWidget *lbl_app_name; GtkWidget *img_icon; GtkWidget *list_notifs; @@ -50,7 +52,7 @@ struct _PhoshNotificationFrame { typedef struct _PhoshNotificationFrame PhoshNotificationFrame; -G_DEFINE_TYPE (PhoshNotificationFrame, phosh_notification_frame, GTK_TYPE_BOX) +G_DEFINE_TYPE (PhoshNotificationFrame, phosh_notification_frame, GTK_TYPE_EVENT_BOX) #define DRAG_THRESHOLD_DISTANCE 16 @@ -86,7 +88,7 @@ motion_notify (PhoshNotificationFrame *self, int current_x, current_y; double dx, dy; - gtk_widget_translate_coordinates (GTK_WIDGET (self), + gtk_widget_translate_coordinates (GTK_WIDGET (self->box), gtk_widget_get_toplevel (GTK_WIDGET (self)), event->x, event->y, ¤t_x, ¤t_y); @@ -211,6 +213,22 @@ notification_activated (PhoshNotificationFrame *self, } +static void +removed (PhoshNotificationFrame *self) +{ + guint i, n; + + n = g_list_model_get_n_items (self->model); + for (i = 0; i < n; i++) { + g_autoptr (PhoshNotification) notification = NULL; + + notification = g_list_model_get_item (self->model, 0); + + phosh_notification_close (notification, PHOSH_NOTIFICATION_REASON_CLOSED); + } +} + + static void phosh_notification_frame_class_init (PhoshNotificationFrameClass *klass) { @@ -232,6 +250,7 @@ phosh_notification_frame_class_init (PhoshNotificationFrameClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/sm/puri/phosh/ui/notification-frame.ui"); + gtk_widget_class_bind_template_child (widget_class, PhoshNotificationFrame, box); gtk_widget_class_bind_template_child (widget_class, PhoshNotificationFrame, lbl_app_name); gtk_widget_class_bind_template_child (widget_class, PhoshNotificationFrame, img_icon); gtk_widget_class_bind_template_child (widget_class, PhoshNotificationFrame, list_notifs); @@ -244,6 +263,7 @@ phosh_notification_frame_class_init (PhoshNotificationFrameClass *klass) gtk_widget_class_bind_template_callback (widget_class, list_pressed); gtk_widget_class_bind_template_callback (widget_class, released); gtk_widget_class_bind_template_callback (widget_class, notification_activated); + gtk_widget_class_bind_template_callback (widget_class, removed); gtk_widget_class_set_css_name (widget_class, "phosh-notification-frame"); } @@ -255,6 +275,8 @@ phosh_notification_frame_init (PhoshNotificationFrame *self) self->start_x = -1; self->start_y = -1; + g_type_ensure (PHOSH_TYPE_SWIPE_AWAY_BIN); + gtk_widget_init_template (GTK_WIDGET (self)); } diff --git a/src/notifications/notification-frame.h b/src/notifications/notification-frame.h index a799d434b..c1e3578de 100644 --- a/src/notifications/notification-frame.h +++ b/src/notifications/notification-frame.h @@ -18,7 +18,7 @@ G_BEGIN_DECLS #define PHOSH_TYPE_NOTIFICATION_FRAME (phosh_notification_frame_get_type ()) -G_DECLARE_FINAL_TYPE (PhoshNotificationFrame, phosh_notification_frame, PHOSH, NOTIFICATION_FRAME, GtkBox) +G_DECLARE_FINAL_TYPE (PhoshNotificationFrame, phosh_notification_frame, PHOSH, NOTIFICATION_FRAME, GtkEventBox) GtkWidget *phosh_notification_frame_new (void); diff --git a/src/style.css b/src/style.css index c279e946f..84a1904db 100644 --- a/src/style.css +++ b/src/style.css @@ -293,13 +293,13 @@ phosh-notification-content:last-child .actions-area button:last-child { border-bottom: none; } -phosh-notification-frame { +phosh-notification-frame .notification-container { border-radius: 6px; background-color: #282828; margin: 12px; } -phosh-notification-banner > phosh-notification-frame { +phosh-notification-banner .notification-container { box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.33), 0px 5px 6px 0px rgba(0, 0, 0, 0.07), 0px 0px 0px 1px rgba(0, 0, 0, 0.2); diff --git a/src/ui/notification-frame.ui b/src/ui/notification-frame.ui index 2a1789c29..3397e41b1 100644 --- a/src/ui/notification-frame.ui +++ b/src/ui/notification-frame.ui @@ -1,85 +1,101 @@ -