From 05ec02fadbc2b26daf30da250fa46871b0c5552f Mon Sep 17 00:00:00 2001 From: Hari Rana Date: Fri, 24 Apr 2026 09:04:23 -0400 Subject: [PATCH] event-editor/multi-choice: Replace GtkToggleButton with AdwBin Using GtkToggleButton in this case is not only overkill for our intended use case, it is also a hinderance, as the states and focus of the widget are handled by the widget itself, which can lead to unpredictable and undesired behavior. Using AdwBin solves this problem by allowing us to set the styles and states from the parent, provided that the CSS name is changed to "button". Switching to AdwBin also allows us to not override the `focus()`, `grab_focus()`, and `get_platform_state()` virtual methods. Part-of: --- src/gui/event-editor/gcal-multi-choice.blp | 14 ++- src/gui/event-editor/gcal-multi-choice.c | 114 +++++++-------------- src/theme/style.css | 1 - 3 files changed, 47 insertions(+), 82 deletions(-) diff --git a/src/gui/event-editor/gcal-multi-choice.blp b/src/gui/event-editor/gcal-multi-choice.blp index a6b60253..aee4b78d 100644 --- a/src/gui/event-editor/gcal-multi-choice.blp +++ b/src/gui/event-editor/gcal-multi-choice.blp @@ -1,4 +1,5 @@ using Gtk 4.0; +using Adw 1; template $GcalMultiChoice: Widget { accessible-role: spin_button; @@ -6,6 +7,10 @@ template $GcalMultiChoice: Widget { focusable: true; hexpand: true; + GestureClick { + released => $on_gesture_click_released(template); + } + PopoverBin popover_bin { child: Box { spacing: 6; @@ -23,9 +28,8 @@ template $GcalMultiChoice: Widget { ] } - ToggleButton button { - accessible-role: none; - toggled => $button_toggled_cb() swapped; + Adw.Bin button { + css-name: "button"; state-flags-changed => $gcal_multi_choice_state_flags_changed(template); styles [ @@ -34,7 +38,7 @@ template $GcalMultiChoice: Widget { "popup", ] - Stack stack { + child: Stack stack { hexpand: true; vexpand: true; @@ -49,7 +53,7 @@ template $GcalMultiChoice: Widget { child: Label label2 {}; } - } + }; } Button up_button { diff --git a/src/gui/event-editor/gcal-multi-choice.c b/src/gui/event-editor/gcal-multi-choice.c index 8b681302..8fb3ccc2 100644 --- a/src/gui/event-editor/gcal-multi-choice.c +++ b/src/gui/event-editor/gcal-multi-choice.c @@ -79,12 +79,9 @@ enum static guint signals[LAST_SIGNAL] = { 0, }; static GParamSpec *properties[N_PROPS] = { NULL, }; -static void gcal_multi_choice_accessible_init (GtkAccessibleInterface *iface); - static void gcal_multi_choice_accessible_range_init (GtkAccessibleRangeInterface *iface); G_DEFINE_FINAL_TYPE_WITH_CODE (GcalMultiChoice, gcal_multi_choice, GTK_TYPE_WIDGET, - G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE, gcal_multi_choice_accessible_init) G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE_RANGE, gcal_multi_choice_accessible_range_init)) /* @@ -223,33 +220,38 @@ update_sensitivity (GcalMultiChoice *self) } static void -button_toggled_cb (GcalMultiChoice *self) +on_widget_activated (GcalMultiChoice *self) { - const gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->button)); - if (gtk_popover_bin_get_popover (self->popover_bin)) { - if (active) - { - gtk_popover_bin_popup (self->popover_bin); - gtk_accessible_update_state (GTK_ACCESSIBLE (self), - GTK_ACCESSIBLE_STATE_EXPANDED, TRUE, - -1); - } - else - { - gtk_accessible_reset_state (GTK_ACCESSIBLE (self), - GTK_ACCESSIBLE_STATE_EXPANDED); - } + gtk_popover_bin_popup (self->popover_bin); + gtk_accessible_update_state (GTK_ACCESSIBLE (self), + GTK_ACCESSIBLE_STATE_EXPANDED, TRUE, + -1); + } + else + { + gtk_accessible_reset_state (GTK_ACCESSIBLE (self), + GTK_ACCESSIBLE_STATE_EXPANDED); } } -static gboolean -menu_deactivate_cb (GcalMultiChoice *self) +static void +on_gesture_click_released (GcalMultiChoice *self, + gint n_press, + double x, + double y, + GtkGestureClick *gesture) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->button), FALSE); + if (gtk_widget_contains (GTK_WIDGET (self), x, y)) + { + if (!gtk_widget_grab_focus (GTK_WIDGET (self))) + g_assert_not_reached (); - return TRUE; + gtk_widget_activate (GTK_WIDGET (self)); + } + + gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_NONE); } /* @@ -381,57 +383,28 @@ gcal_multi_choice_state_flags_changed (GtkWidget *widget, GtkStateFlags previous_state_flags) { GcalMultiChoice *self; - GtkStateFlags button_state_flags; + GtkStateFlags state_flags; GtkWidget *popover; g_assert (GCAL_IS_MULTI_CHOICE (widget)); self = GCAL_MULTI_CHOICE (widget); - button_state_flags = gtk_widget_get_state_flags (self->button); - if (button_state_flags & GTK_STATE_FLAG_FOCUSED) - button_state_flags |= GTK_STATE_FLAG_FOCUS_VISIBLE; - gtk_widget_set_state_flags (GTK_WIDGET (self), button_state_flags, TRUE); - - if (!gtk_widget_is_sensitive (widget)) + if ((popover = gtk_popover_bin_get_popover (self->popover_bin))) { - if ((popover = gtk_popover_bin_get_popover (self->popover_bin))) - gtk_widget_set_visible (popover, FALSE); + if (gtk_widget_get_mapped (popover)) + gtk_widget_set_state_flags (self->button, GTK_STATE_FLAG_CHECKED, FALSE); + else + gtk_widget_unset_state_flags (self->button, GTK_STATE_FLAG_CHECKED); } -} - -static gboolean -gcal_multi_choice_focus (GtkWidget *widget, - GtkDirectionType direction) -{ - GcalMultiChoice *self = GCAL_MULTI_CHOICE (widget); - GtkWidget *popover = gtk_popover_bin_get_popover (self->popover_bin); - - if (popover && gtk_widget_get_visible (popover)) - return gtk_widget_child_focus (popover, direction); else - return gtk_widget_child_focus (self->button, direction); -} + { + gtk_widget_set_state_flags (self->button, GTK_STATE_FLAG_NORMAL, TRUE); + } -static gboolean -gcal_multi_choice_grab_focus (GtkWidget *widget) -{ - GcalMultiChoice *self = GCAL_MULTI_CHOICE (widget); - - return gtk_widget_grab_focus (self->button); -} - -/* - * GtkAccessible overrides - */ - -static gboolean -gcal_multi_choice_accessible_get_platform_state (GtkAccessible *accessible, - GtkAccessiblePlatformState state) -{ - GcalMultiChoice *self = GCAL_MULTI_CHOICE (accessible); - - return gtk_accessible_get_platform_state (GTK_ACCESSIBLE (self->button), state); + state_flags = gtk_widget_get_state_flags (widget); + if (state_flags & GTK_STATE_FLAG_FOCUSED) + gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_FOCUS_VISIBLE, FALSE); } /* @@ -461,8 +434,6 @@ gcal_multi_choice_class_init (GcalMultiChoiceClass *class) object_class->get_property = gcal_multi_choice_get_property; widget_class->state_flags_changed = gcal_multi_choice_state_flags_changed; - widget_class->focus = gcal_multi_choice_focus; - widget_class->grab_focus = gcal_multi_choice_grab_focus; properties[PROP_VALUE] = g_param_spec_int ("value", "Value", "Value", @@ -533,20 +504,14 @@ gcal_multi_choice_class_init (GcalMultiChoiceClass *class) gtk_widget_class_bind_template_child (widget_class, GcalMultiChoice, label2); gtk_widget_class_bind_template_child (widget_class, GcalMultiChoice, popover_bin); + gtk_widget_class_bind_template_callback (widget_class, on_gesture_click_released); gtk_widget_class_bind_template_callback (widget_class, gcal_multi_choice_state_flags_changed); - gtk_widget_class_bind_template_callback (widget_class, button_toggled_cb); gtk_widget_class_set_css_name (widget_class, "navigator"); gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); } -static void -gcal_multi_choice_accessible_init (GtkAccessibleInterface *iface) -{ - iface->get_platform_state = gcal_multi_choice_accessible_get_platform_state; -} - static void gcal_multi_choice_accessible_range_init (GtkAccessibleRangeInterface *iface) { @@ -560,7 +525,7 @@ gcal_multi_choice_init (GcalMultiChoice *self) update_sensitivity (self); - g_signal_connect_swapped (self, "activate", (GCallback) button_toggled_cb, self); + g_signal_connect_swapped (self, "activate", (GCallback) on_widget_activated, self); } /* @@ -700,9 +665,6 @@ gcal_multi_choice_set_popover (GcalMultiChoice *self, gtk_popover_bin_set_popover (self->popover_bin, popover); - if (popover) - g_signal_connect_swapped (popover, "closed", G_CALLBACK (menu_deactivate_cb), self); - update_sensitivity (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_POPOVER]); diff --git a/src/theme/style.css b/src/theme/style.css index 59a8a87a..1628c2f7 100644 --- a/src/theme/style.css +++ b/src/theme/style.css @@ -122,7 +122,6 @@ datechooser navigator label { datechooser navigator button { padding: 0; - outline: unset; } /* week numbers, with a style resembling GNOME Shell's */