From e6d3f3d91e8e511774bdbdae4e1c90f4ccbcdaac Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 23 Dec 2019 21:44:56 -0500 Subject: [PATCH 1/9] gtk-demo: Fix the application demo This was broken in d223752c55be49, when the support for internal children was removed from GtkInfoBar. --- demos/gtk-demo/application.ui | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/demos/gtk-demo/application.ui b/demos/gtk-demo/application.ui index ecceb997db..f457d89f32 100644 --- a/demos/gtk-demo/application.ui +++ b/demos/gtk-demo/application.ui @@ -43,25 +43,17 @@ 0 1 - - - - - 1 - - + + + 1 - - - - - center - _OK - 1 - - - + + + center + _OK + 1 + From 65769fd7a68b7a9bec11c8cff59cba0ba5986971 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 23 Dec 2019 21:58:45 -0500 Subject: [PATCH 2/9] gtk-demo: Cosmetic fixes to the assistant demo --- demos/gtk-demo/assistant.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/demos/gtk-demo/assistant.c b/demos/gtk-demo/assistant.c index 83879cf28d..3b1405932c 100644 --- a/demos/gtk-demo/assistant.c +++ b/demos/gtk-demo/assistant.c @@ -94,6 +94,7 @@ create_page1 (GtkWidget *assistant) GtkWidget *box, *label, *entry; box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + g_object_set (box, "margin", 12, NULL); label = gtk_label_new ("You must fill out this entry to continue:"); gtk_container_add (GTK_CONTAINER (box), label); @@ -115,10 +116,12 @@ create_page2 (GtkWidget *assistant) { GtkWidget *box, *checkbutton; - box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + g_object_set (box, "margin", 12, NULL); checkbutton = gtk_check_button_new_with_label ("This is optional data, you may continue " "even if you do not check this"); + gtk_widget_set_valign (checkbutton, GTK_ALIGN_CENTER); gtk_container_add (GTK_CONTAINER (box), checkbutton); gtk_assistant_append_page (GTK_ASSISTANT (assistant), box); From 33716d1e50f25a6a054c9a15aadcc20f19359982 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 23 Dec 2019 22:14:52 -0500 Subject: [PATCH 3/9] gtk-demo: Cosmetic fixes to the dnd demo --- demos/gtk-demo/dnd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/demos/gtk-demo/dnd.c b/demos/gtk-demo/dnd.c index b211bcede1..4ed6c9ce76 100644 --- a/demos/gtk-demo/dnd.c +++ b/demos/gtk-demo/dnd.c @@ -1,6 +1,8 @@ /* Drag-and-Drop * * I can't believe its not glade! + * + * Try right-clicking in the window. */ #include @@ -219,6 +221,7 @@ edit_cb (GtkWidget *child) g_object_set_data (G_OBJECT (entry), "label", child); gtk_editable_set_text (GTK_EDITABLE (entry), gtk_label_get_text (GTK_LABEL (child))); + gtk_editable_set_width_chars (GTK_EDITABLE (entry), 12); g_signal_connect (entry, "activate", G_CALLBACK (edit_label_done), NULL); gtk_fixed_put (GTK_FIXED (fixed), entry, x, y); gtk_widget_grab_focus (entry); From db42c23c0a90b72c421dc75d31789aa425175982 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 23 Dec 2019 22:33:02 -0500 Subject: [PATCH 4/9] gtk-demo: Fix a crash in the font explorer demo gtk_widget_add_controller is transfer-full. --- demos/gtk-demo/font_features.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/gtk-demo/font_features.c b/demos/gtk-demo/font_features.c index 1fc8e92d69..dbd22e0663 100644 --- a/demos/gtk-demo/font_features.c +++ b/demos/gtk-demo/font_features.c @@ -1228,7 +1228,7 @@ do_font_features (GtkWidget *do_widget) edit_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "edit_toggle")); controller = gtk_event_controller_key_new (); - g_object_set_data_full (G_OBJECT (entry), "controller", controller, g_object_unref); + g_object_set_data_full (G_OBJECT (entry), "controller", g_object_ref (controller), g_object_unref); g_signal_connect (controller, "key-pressed", G_CALLBACK (entry_key_press), entry); gtk_widget_add_controller (entry, controller); From 663fb93af77d3824e73ce9a8cf9432414ad03ac4 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 23 Dec 2019 22:35:44 -0500 Subject: [PATCH 5/9] gtk-demo: Fix font explore initial state --- demos/gtk-demo/font_features.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/demos/gtk-demo/font_features.c b/demos/gtk-demo/font_features.c index dbd22e0663..ad0e30e95c 100644 --- a/demos/gtk-demo/font_features.c +++ b/demos/gtk-demo/font_features.c @@ -1337,6 +1337,8 @@ do_font_features (GtkWidget *do_widget) G_CALLBACK (gtk_widget_destroyed), &window); g_object_unref (builder); + + update_display (); } if (!gtk_widget_get_visible (window)) From 58bc9452f6f89c37d26b020f99a18ba53da76b85 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 24 Dec 2019 03:12:30 -0500 Subject: [PATCH 6/9] paper dialog: Make this look less horrible --- gtk/gtkcustompaperunixdialog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gtk/gtkcustompaperunixdialog.c b/gtk/gtkcustompaperunixdialog.c index a607d417c8..56e9e3a4a5 100644 --- a/gtk/gtkcustompaperunixdialog.c +++ b/gtk/gtkcustompaperunixdialog.c @@ -1034,6 +1034,7 @@ populate_dialog (GtkCustomPaperUnixDialog *dialog) gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 18); + g_object_set (hbox, "margin", 20, NULL); gtk_container_add (GTK_CONTAINER (content_area), hbox); gtk_widget_show (hbox); From 72932d277616363c056a570c2061cf769de9e0ba Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 24 Dec 2019 03:13:58 -0500 Subject: [PATCH 7/9] cell renderer text: Fix this to work again We were showing the entry, and removing it right away when the focus moved to the text child. Avoid that. --- gtk/gtkcellrenderertext.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c index a5e662fd03..7ed41be696 100644 --- a/gtk/gtkcellrenderertext.c +++ b/gtk/gtkcellrenderertext.c @@ -21,6 +21,7 @@ #include "gtkeditable.h" #include "gtkentry.h" +#include "gtkentryprivate.h" #include "gtkintl.h" #include "gtkmarshalers.h" #include "gtkprivate.h" @@ -1782,7 +1783,6 @@ gtk_cell_renderer_text_editing_done (GtkCellEditable *entry, path = g_object_get_data (G_OBJECT (entry), GTK_CELL_RENDERER_TEXT_PATH); new_text = gtk_editable_get_text (GTK_EDITABLE (entry)); - g_signal_emit (data, text_cell_renderer_signals[EDITED], 0, path, new_text); } @@ -1791,7 +1791,8 @@ gtk_cell_renderer_text_focus_changed (GtkWidget *entry, GParamSpec *pspec, gpointer data) { - if (gtk_widget_has_focus (entry)) + if (gtk_widget_has_focus (entry) || + gtk_widget_has_focus (GTK_WIDGET (gtk_entry_get_text_widget (GTK_ENTRY (entry))))) return; g_object_set (entry, @@ -1815,7 +1816,7 @@ gtk_cell_renderer_text_start_editing (GtkCellRenderer *cell, gfloat xalign, yalign; /* If the cell isn't editable we return NULL. */ - if (priv->editable == FALSE) + if (!priv->editable) return NULL; gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); @@ -1840,14 +1841,11 @@ gtk_cell_renderer_text_start_editing (GtkCellRenderer *cell, priv->entry_menu_popdown_timeout = 0; } - g_signal_connect (priv->entry, - "editing-done", - G_CALLBACK (gtk_cell_renderer_text_editing_done), - celltext); + g_signal_connect (priv->entry, "editing-done", + G_CALLBACK (gtk_cell_renderer_text_editing_done), celltext); priv->focus_out_id = g_signal_connect_after (priv->entry, "notify::has-focus", G_CALLBACK (gtk_cell_renderer_text_focus_changed), celltext); - gtk_widget_show (priv->entry); return GTK_CELL_EDITABLE (priv->entry); } From cc3ecac6d8a68c8caa3e62ebe68dfe48afb9489f Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 24 Dec 2019 03:33:02 -0500 Subject: [PATCH 8/9] cell renderer spin: Bring this back GtkSpinButton lost its cell editable implementation when it stopped being a GtkEntry subclass. Add it back, and make it work. --- gtk/gtkcellrendererspin.c | 67 +++++++++++++++++++----------- gtk/gtkspinbutton.c | 87 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 126 insertions(+), 28 deletions(-) diff --git a/gtk/gtkcellrendererspin.c b/gtk/gtkcellrendererspin.c index 97c48a354c..43ee161458 100644 --- a/gtk/gtkcellrendererspin.c +++ b/gtk/gtkcellrendererspin.c @@ -66,6 +66,7 @@ struct _GtkCellRendererSpinClass struct _GtkCellRendererSpinPrivate { + GtkWidget *spin; GtkAdjustment *adjustment; gdouble climb_rate; guint digits; @@ -175,8 +176,8 @@ gtk_cell_renderer_spin_finalize (GObject *object) { GtkCellRendererSpinPrivate *priv = gtk_cell_renderer_spin_get_instance_private (GTK_CELL_RENDERER_SPIN (object)); - if (priv && priv->adjustment) - g_object_unref (priv->adjustment); + g_clear_object (&priv->adjustment); + g_clear_object (&priv->spin); G_OBJECT_CLASS (gtk_cell_renderer_spin_parent_class)->finalize (object); } @@ -258,9 +259,7 @@ gtk_cell_renderer_spin_focus_changed (GtkWidget *widget, if (gtk_widget_has_focus (widget)) return; - g_object_get (widget, - "editing-canceled", &canceled, - NULL); + g_object_get (widget, "editing-canceled", &canceled, NULL); g_signal_handlers_disconnect_by_func (widget, gtk_cell_renderer_spin_focus_changed, @@ -268,13 +267,12 @@ gtk_cell_renderer_spin_focus_changed (GtkWidget *widget, gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER (data), canceled); - if (!canceled) - { - path = g_object_get_data (G_OBJECT (widget), GTK_CELL_RENDERER_SPIN_PATH); + if (canceled) + return; - new_text = gtk_editable_get_text (GTK_EDITABLE (widget)); - g_signal_emit_by_name (data, "edited", path, new_text); - } + path = g_object_get_data (G_OBJECT (widget), GTK_CELL_RENDERER_SPIN_PATH); + new_text = gtk_editable_get_text (GTK_EDITABLE (widget)); + g_signal_emit_by_name (data, "edited", path, new_text); } static gboolean @@ -301,6 +299,28 @@ gtk_cell_renderer_spin_key_pressed (GtkEventControllerKey *controller, return FALSE; } +static void +gtk_cell_renderer_spin_editing_done (GtkSpinButton *spin, + GtkCellRendererSpin *cell) +{ + GtkCellRendererSpinPrivate *priv = gtk_cell_renderer_spin_get_instance_private (GTK_CELL_RENDERER_SPIN (cell)); + gboolean canceled; + const char *path; + const char *new_text; + + g_clear_object (&priv->spin); + + g_object_get (spin, "editing-canceled", &canceled, NULL); + gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER (cell), canceled); + + if (canceled) + return; + + path = g_object_get_data (G_OBJECT (spin), GTK_CELL_RENDERER_SPIN_PATH); + new_text = gtk_editable_get_text (GTK_EDITABLE (spin)); + g_signal_emit_by_name (cell, "edited", path, new_text); +} + static GtkCellEditable * gtk_cell_renderer_spin_start_editing (GtkCellRenderer *cell, GdkEvent *event, @@ -313,7 +333,6 @@ gtk_cell_renderer_spin_start_editing (GtkCellRenderer *cell, GtkCellRendererSpinPrivate *priv = gtk_cell_renderer_spin_get_instance_private (GTK_CELL_RENDERER_SPIN (cell)); GtkCellRendererText *cell_text = GTK_CELL_RENDERER_TEXT (cell); GtkEventController *key_controller; - GtkWidget *spin; gboolean editable; gchar *text; @@ -324,33 +343,31 @@ gtk_cell_renderer_spin_start_editing (GtkCellRenderer *cell, if (!priv->adjustment) return NULL; - spin = gtk_spin_button_new (priv->adjustment, - priv->climb_rate, priv->digits); + priv->spin = gtk_spin_button_new (priv->adjustment, priv->climb_rate, priv->digits); + g_object_ref_sink (priv->spin); g_object_get (cell_text, "text", &text, NULL); if (text) { - gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), - g_strtod (text, NULL)); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->spin), g_strtod (text, NULL)); g_free (text); } key_controller = gtk_event_controller_key_new (); g_signal_connect (key_controller, "key-pressed", - G_CALLBACK (gtk_cell_renderer_spin_key_pressed), - spin); - gtk_widget_add_controller (spin, key_controller); + G_CALLBACK (gtk_cell_renderer_spin_key_pressed), priv->spin); + gtk_widget_add_controller (priv->spin, key_controller); - g_object_set_data_full (G_OBJECT (spin), GTK_CELL_RENDERER_SPIN_PATH, + g_object_set_data_full (G_OBJECT (priv->spin), GTK_CELL_RENDERER_SPIN_PATH, g_strdup (path), g_free); - g_signal_connect (G_OBJECT (spin), "notify::has-focus", - G_CALLBACK (gtk_cell_renderer_spin_focus_changed), - cell); + g_signal_connect (priv->spin, "editing-done", + G_CALLBACK (gtk_cell_renderer_spin_editing_done), cell); - gtk_widget_show (spin); + g_signal_connect (priv->spin, "notify::has-focus", + G_CALLBACK (gtk_cell_renderer_spin_focus_changed), cell); - return GTK_CELL_EDITABLE (spin); + return GTK_CELL_EDITABLE (priv->spin); } /** diff --git a/gtk/gtkspinbutton.c b/gtk/gtkspinbutton.c index b7a460cfd3..9e16ac0d78 100644 --- a/gtk/gtkspinbutton.c +++ b/gtk/gtkspinbutton.c @@ -35,6 +35,7 @@ #include "gtkbutton.h" #include "gtkcssstylepropertyprivate.h" #include "gtkeditable.h" +#include "gtkcelleditable.h" #include "gtkimage.h" #include "gtktext.h" #include "gtkeventcontrollerkey.h" @@ -54,6 +55,7 @@ #include "gtkwidgetpath.h" #include "gtkwidgetprivate.h" #include "gtkboxlayout.h" +#include "gtktextprivate.h" #include "a11y/gtkspinbuttonaccessible.h" @@ -232,6 +234,7 @@ struct _GtkSpinButtonPrivate guint snap_to_ticks : 1; guint timer_calls : 3; guint wrap : 1; + guint editing_canceled : 1; }; typedef struct _GtkSpinButtonPrivate GtkSpinButtonPrivate; @@ -246,7 +249,8 @@ enum { PROP_UPDATE_POLICY, PROP_VALUE, NUM_SPINBUTTON_PROPS, - PROP_ORIENTATION = NUM_SPINBUTTON_PROPS + PROP_ORIENTATION = NUM_SPINBUTTON_PROPS, + PROP_EDITING_CANCELED }; /* Signals */ @@ -261,6 +265,7 @@ enum }; static void gtk_spin_button_editable_init (GtkEditableInterface *iface); +static void gtk_spin_button_cell_editable_init (GtkCellEditableIface *iface); static void gtk_spin_button_finalize (GObject *object); static void gtk_spin_button_set_property (GObject *object, guint prop_id, @@ -309,7 +314,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkSpinButton, gtk_spin_button, GTK_TYPE_WIDGET, G_ADD_PRIVATE (GtkSpinButton) G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL) G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, - gtk_spin_button_editable_init)) + gtk_spin_button_editable_init) + G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE, + gtk_spin_button_cell_editable_init)) #define add_spin_binding(binding_set, keyval, mask, scroll) \ gtk_binding_entry_add_signal (binding_set, keyval, mask, \ @@ -417,7 +424,8 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class) g_object_class_install_properties (gobject_class, NUM_SPINBUTTON_PROPS, spinbutton_props); g_object_class_override_property (gobject_class, PROP_ORIENTATION, "orientation"); - gtk_editable_install_properties (gobject_class, PROP_ORIENTATION + 1); + g_object_class_override_property (gobject_class, PROP_EDITING_CANCELED, "editing-canceled"); + gtk_editable_install_properties (gobject_class, PROP_EDITING_CANCELED + 1); /** * GtkSpinButton::input: @@ -572,6 +580,69 @@ gtk_spin_button_editable_init (GtkEditableInterface *iface) iface->insert_text = gtk_spin_button_insert_text; } +static void +gtk_cell_editable_spin_button_activated (GtkText *text, GtkSpinButton *spin) +{ + g_object_ref (spin); + gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (spin)); + gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (spin)); + g_object_unref (spin); +} + +static gboolean +gtk_cell_editable_spin_button_key_pressed (GtkEventControllerKey *key, + guint keyval, + guint keycode, + GdkModifierType modifiers, + GtkSpinButton *spin) +{ + GtkSpinButtonPrivate *priv = gtk_spin_button_get_instance_private (spin); + + if (keyval == GDK_KEY_Escape) + { + priv->editing_canceled = TRUE; + + g_object_ref (spin); + gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (spin)); + gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (spin)); + g_object_unref (spin); + + return GDK_EVENT_STOP; + } + + /* override focus */ + if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Down) + { + g_object_ref (spin); + gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (spin)); + gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (spin)); + g_object_unref (spin); + + return GDK_EVENT_STOP; + } + + return GDK_EVENT_PROPAGATE; +} + +static void +gtk_spin_button_start_editing (GtkCellEditable *cell_editable, + GdkEvent *event) +{ + GtkSpinButton *spin = GTK_SPIN_BUTTON (cell_editable); + GtkSpinButtonPrivate *priv = gtk_spin_button_get_instance_private (spin); + + g_signal_connect (priv->entry, "activate", + G_CALLBACK (gtk_cell_editable_spin_button_activated), cell_editable); + g_signal_connect (gtk_text_get_key_controller (GTK_TEXT (priv->entry)), "key-pressed", + G_CALLBACK (gtk_cell_editable_spin_button_key_pressed), cell_editable); +} + +static void +gtk_spin_button_cell_editable_init (GtkCellEditableIface *iface) +{ + iface->start_editing = gtk_spin_button_start_editing; +} + static void gtk_spin_button_set_property (GObject *object, guint prop_id, @@ -622,6 +693,13 @@ gtk_spin_button_set_property (GObject *object, case PROP_ORIENTATION: gtk_spin_button_set_orientation (spin_button, g_value_get_enum (value)); break; + case PROP_EDITING_CANCELED: + if (priv->editing_canceled != g_value_get_boolean (value)) + { + priv->editing_canceled = g_value_get_boolean (value); + g_object_notify (object, "editing-canceled"); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -669,6 +747,9 @@ gtk_spin_button_get_property (GObject *object, case PROP_ORIENTATION: g_value_set_enum (value, priv->orientation); break; + case PROP_EDITING_CANCELED: + g_value_set_boolean (value, priv->editing_canceled); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; From 9e3147f78d6588d67e1b8d8beb502b74b69a9357 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 24 Dec 2019 03:39:02 -0500 Subject: [PATCH 9/9] treeview: Fix embedding cell renderers We need to manually set up the css node, since the treeview has children whose css node is not a direct child of the treeview css node (header buttons). --- gtk/gtktreeview.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 76b24c08b4..291e7abc66 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -8195,6 +8195,9 @@ gtk_tree_view_put (GtkTreeView *tree_view, tree_view->priv->children = g_list_append (tree_view->priv->children, child); + gtk_css_node_insert_after (gtk_widget_get_css_node (GTK_WIDGET (tree_view)), + gtk_widget_get_css_node (child_widget), + tree_view->priv->header_node); gtk_widget_set_parent (child_widget, GTK_WIDGET (tree_view)); }