diff --git a/panels/keyboard/cc-keyboard-manager.c b/panels/keyboard/cc-keyboard-manager.c index a9809a91c..eb5e83191 100644 --- a/panels/keyboard/cc-keyboard-manager.c +++ b/panels/keyboard/cc-keyboard-manager.c @@ -84,6 +84,17 @@ free_key_array (GPtrArray *keys) } } +static const gchar* +get_binding_from_variant (GVariant *variant) +{ + if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) + return g_variant_get_string (variant, NULL); + else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING_ARRAY)) + return g_variant_get_strv (variant, NULL)[0]; + + return NULL; +} + static gboolean compare_keys_for_uniqueness (CcKeyboardItem *current_item, CcUniquenessData *data) @@ -937,3 +948,53 @@ cc_keyboard_manager_disable_shortcut (CcKeyboardManager *self, g_object_set (item, "binding", NULL, NULL); } + +/** + * cc_keyboard_manager_reset_shortcut: + * @self: a #CcKeyboardManager + * @item: a #CcKeyboardItem + * + * Resets the keyboard shortcut managed by @item, and eventually + * disables any shortcut that conflicts with the new shortcut's + * value. + */ +void +cc_keyboard_manager_reset_shortcut (CcKeyboardManager *self, + CcKeyboardItem *item) +{ + GVariant *default_value; + const gchar *default_binding; + + g_return_if_fail (CC_IS_KEYBOARD_MANAGER (self)); + g_return_if_fail (CC_IS_KEYBOARD_ITEM (item)); + + default_value = g_settings_get_default_value (item->settings, item->key); + default_binding = get_binding_from_variant (default_value); + + /* Disables any any shortcut that conflicts with the new shortcut's value */ + if (default_binding && *default_binding != '\0') + { + GdkModifierType mask; + CcKeyboardItem *collision; + guint *keycodes; + guint keyval; + + gtk_accelerator_parse_with_keycode (default_binding, &keyval, &keycodes, &mask); + + collision = cc_keyboard_manager_get_collision (self, + NULL, + keyval, + mask, + keycodes ? keycodes[0] : 0); + + if (collision) + cc_keyboard_manager_disable_shortcut (self, collision); + + g_free (keycodes); + } + + /* Resets the current item */ + cc_keyboard_item_reset (item); + + g_variant_unref (default_value); +} diff --git a/panels/keyboard/cc-keyboard-manager.h b/panels/keyboard/cc-keyboard-manager.h index b63ffa582..dde58c6e7 100644 --- a/panels/keyboard/cc-keyboard-manager.h +++ b/panels/keyboard/cc-keyboard-manager.h @@ -54,6 +54,9 @@ CcKeyboardItem* cc_keyboard_manager_get_collision (CcKeyboardMana void cc_keyboard_manager_disable_shortcut (CcKeyboardManager *self, CcKeyboardItem *item); +void cc_keyboard_manager_reset_shortcut (CcKeyboardManager *self, + CcKeyboardItem *item); + G_END_DECLS #endif /* CC_KEYBOARD_MANAGER_H */ diff --git a/panels/keyboard/cc-keyboard-panel.c b/panels/keyboard/cc-keyboard-panel.c index aca093184..124aea371 100644 --- a/panels/keyboard/cc-keyboard-panel.c +++ b/panels/keyboard/cc-keyboard-panel.c @@ -61,6 +61,11 @@ enum { PROP_PARAMETERS }; +static const gchar* custom_css = +"button.reset-shortcut-button {" +" padding: 0;" +"}"; + /* RowData functions */ static RowData * row_data_new (CcKeyboardItem *item, @@ -97,24 +102,67 @@ transform_binding_to_accel (GBinding *binding, item = CC_KEYBOARD_ITEM (g_binding_get_source (binding)); - accelerator = convert_keysym_state_to_string (item->keyval, item->mask, item->keycode); + /* Embolden the label when the shortcut is modified */ + if (!cc_keyboard_item_is_value_default (item)) + { + gchar *tmp; + + tmp = convert_keysym_state_to_string (item->keyval, + item->mask, + item->keycode); + + accelerator = g_strdup_printf ("%s", tmp); + + g_free (tmp); + } + else + { + accelerator = convert_keysym_state_to_string (item->keyval, + item->mask, + item->keycode); + } g_value_take_string (to_value, accelerator); return TRUE; } +static void +shortcut_modified_changed_cb (CcKeyboardItem *item, + GParamSpec *pspec, + GtkWidget *button) +{ + gtk_widget_set_child_visible (button, !cc_keyboard_item_is_value_default (item)); +} + +static void +reset_shortcut_cb (GtkWidget *reset_button, + CcKeyboardItem *item) +{ + CcKeyboardPanel *self; + + self = CC_KEYBOARD_PANEL (gtk_widget_get_ancestor (reset_button, CC_TYPE_KEYBOARD_PANEL)); + + cc_keyboard_manager_reset_shortcut (self->manager, item); +} + static void add_item (CcKeyboardPanel *self, CcKeyboardItem *item, const gchar *section_id, const gchar *section_title) { - GtkWidget *row, *box, *label; + GtkWidget *row, *box, *label, *reset_button; /* Horizontal box */ - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_container_set_border_width (GTK_CONTAINER (box), 6); + box = g_object_new (GTK_TYPE_BOX, + "orientation", GTK_ORIENTATION_HORIZONTAL, + "spacing", 18, + "margin-start", 6, + "margin-end", 6, + "margin-bottom", 4, + "margin-top", 4, + NULL); /* Shortcut title */ label = gtk_label_new (item->description); @@ -134,6 +182,7 @@ add_item (CcKeyboardPanel *self, /* Shortcut accelerator */ label = gtk_label_new (""); gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_label_set_use_markup (GTK_LABEL (label), TRUE); gtk_size_group_add_widget (self->accelerator_sizegroup, label); @@ -149,6 +198,31 @@ add_item (CcKeyboardPanel *self, gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label"); + /* Reset shortcut button */ + reset_button = gtk_button_new_from_icon_name ("window-close-symbolic", GTK_ICON_SIZE_BUTTON); + gtk_widget_set_valign (reset_button, GTK_ALIGN_CENTER); + + gtk_button_set_relief (GTK_BUTTON (reset_button), GTK_RELIEF_NONE); + gtk_widget_set_child_visible (reset_button, !cc_keyboard_item_is_value_default (item)); + + gtk_widget_set_tooltip_text (reset_button, _("Reset the shortcut to its default value")); + + gtk_container_add (GTK_CONTAINER (box), reset_button); + + gtk_style_context_add_class (gtk_widget_get_style_context (reset_button), "flat"); + gtk_style_context_add_class (gtk_widget_get_style_context (reset_button), "circular"); + gtk_style_context_add_class (gtk_widget_get_style_context (reset_button), "reset-shortcut-button"); + + g_signal_connect (item, + "notify::is-value-default", + G_CALLBACK (shortcut_modified_changed_cb), + reset_button); + + g_signal_connect (reset_button, + "clicked", + G_CALLBACK (reset_shortcut_cb), + item); + /* The row */ row = gtk_list_box_row_new (); gtk_container_add (GTK_CONTAINER (row), box); @@ -390,10 +464,23 @@ cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass) static void cc_keyboard_panel_init (CcKeyboardPanel *self) { + GtkCssProvider *provider; + g_resources_register (cc_keyboard_get_resource ()); gtk_widget_init_template (GTK_WIDGET (self)); + /* Custom CSS */ + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (provider, custom_css, -1, NULL); + + gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1); + + g_object_unref (provider); + + /* Shortcut manager */ self->manager = cc_keyboard_manager_new (); /* Use a sizegroup to make the accelerator labels the same width */ diff --git a/panels/keyboard/cc-keyboard-shortcut-editor.c b/panels/keyboard/cc-keyboard-shortcut-editor.c index 962eb8681..a68e853e7 100644 --- a/panels/keyboard/cc-keyboard-shortcut-editor.c +++ b/panels/keyboard/cc-keyboard-shortcut-editor.c @@ -43,6 +43,7 @@ struct _CcKeyboardShortcutEditor GtkWidget *new_shortcut_conflict_label; GtkWidget *remove_button; GtkWidget *replace_button; + GtkWidget *reset_button; GtkWidget *shortcut_accel_label; GtkWidget *shortcut_conflict_label; GtkWidget *stack; @@ -54,6 +55,7 @@ struct _CcKeyboardShortcutEditor CcKeyboardManager *manager; CcKeyboardItem *item; + GBinding *reset_item_binding; CcKeyboardItem *collision_item; @@ -402,6 +404,20 @@ replace_button_clicked_cb (CcKeyboardShortcutEditor *self) gtk_widget_hide (GTK_WIDGET (self)); } +static void +reset_item_clicked_cb (CcKeyboardShortcutEditor *self) +{ + gchar *accel; + + /* Reset first, then update the shortcut */ + cc_keyboard_manager_reset_shortcut (self->manager, self->item); + + accel = gtk_accelerator_name (self->item->keyval, self->item->mask); + gtk_shortcut_label_set_accelerator (GTK_SHORTCUT_LABEL (self->shortcut_accel_label), accel); + + g_free (accel); +} + static void setup_keyboard_item (CcKeyboardShortcutEditor *self, CcKeyboardItem *item) @@ -433,6 +449,13 @@ setup_keyboard_item (CcKeyboardShortcutEditor *self, gtk_shortcut_label_set_accelerator (GTK_SHORTCUT_LABEL (self->shortcut_accel_label), accel); gtk_shortcut_label_set_accelerator (GTK_SHORTCUT_LABEL (self->custom_shortcut_accel_label), accel); + g_clear_pointer (&self->reset_item_binding, g_binding_unbind); + self->reset_item_binding = g_object_bind_property (item, + "is-value-default", + self->reset_button, + "visible", + G_BINDING_DEFAULT | G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE); + /* Setup the custom entries */ if (is_custom) { @@ -468,6 +491,8 @@ cc_keyboard_shortcut_editor_finalize (GObject *object) g_clear_object (&self->item); g_clear_object (&self->manager); + g_clear_pointer (&self->reset_item_binding, g_binding_unbind); + G_OBJECT_CLASS (cc_keyboard_shortcut_editor_parent_class)->finalize (object); } @@ -660,6 +685,7 @@ cc_keyboard_shortcut_editor_class_init (CcKeyboardShortcutEditorClass *klass) gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, new_shortcut_conflict_label); gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, remove_button); gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, replace_button); + gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, reset_button); gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, shortcut_accel_label); gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, shortcut_conflict_label); gtk_widget_class_bind_template_child (widget_class, CcKeyboardShortcutEditor, stack); @@ -672,6 +698,7 @@ cc_keyboard_shortcut_editor_class_init (CcKeyboardShortcutEditorClass *klass) gtk_widget_class_bind_template_callback (widget_class, name_entry_changed_cb); gtk_widget_class_bind_template_callback (widget_class, remove_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, replace_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, reset_item_clicked_cb); } static void diff --git a/panels/keyboard/shortcut-editor.ui b/panels/keyboard/shortcut-editor.ui index 65dc2e370..81b5dc361 100644 --- a/panels/keyboard/shortcut-editor.ui +++ b/panels/keyboard/shortcut-editor.ui @@ -64,6 +64,7 @@ True True end +