From a88f20ae0a6f30e9a3c3afb17f1cd864f64c861b Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Fri, 26 Apr 2019 01:08:12 -0700 Subject: [PATCH 1/2] Implement list of window class names that default to each layout --- panel-plugin/xkb-dialog.c | 51 +++++++++++++++++++++ panel-plugin/xkb-keyboard.c | 24 +++++++++- panel-plugin/xkb-properties.h | 5 +++ panel-plugin/xkb-xfconf.c | 84 +++++++++++++++++++++++++++++++++++ panel-plugin/xkb-xfconf.h | 1 + 5 files changed, 164 insertions(+), 1 deletion(-) diff --git a/panel-plugin/xkb-dialog.c b/panel-plugin/xkb-dialog.c index b604407..fd28210 100644 --- a/panel-plugin/xkb-dialog.c +++ b/panel-plugin/xkb-dialog.c @@ -86,6 +86,21 @@ xkb_dialog_set_style_warning_tooltip (GtkWidget *widget, +static gboolean +xkb_dialog_layoutdefault_tooltip (GtkWidget *widget, + gint x, + gint y, + gboolean keyboard_mode, + GtkTooltip *tooltip) +{ + gtk_tooltip_set_text ( + tooltip, + _("Enter a comma-separated list of window classes which will default to this layout.")); + return TRUE; +} + + + void xkb_dialog_configure_plugin (XfcePanelPlugin *plugin, XkbXfconf *config) @@ -97,8 +112,16 @@ xkb_dialog_configure_plugin (XfcePanelPlugin *plugin, GtkWidget *caps_lock_indicator_switch; GtkWidget *display_tooltip_icon_switch; GtkWidget *group_policy_combo; + GtkWidget *layoutdefault_entry[MAX_LAYOUTS]; GtkWidget *vbox, *frame, *bin, *grid, *label; + GString *labtext; gint grid_vertical; + guint i; + const gchar *prop_names[MAX_LAYOUTS]; + + prop_names[1] = LAYOUT1_DEFAULTS; + prop_names[2] = LAYOUT2_DEFAULTS; + prop_names[3] = LAYOUT3_DEFAULTS; xfce_panel_plugin_block_menu (plugin); @@ -217,6 +240,25 @@ xkb_dialog_configure_plugin (XfcePanelPlugin *plugin, gtk_widget_set_size_request (group_policy_combo, 230, -1); gtk_grid_attach (GTK_GRID (grid), group_policy_combo, 1, grid_vertical, 1, 1); + grid_vertical++; + + label = gtk_label_new (_("Window classes which default to ...")); + gtk_label_set_xalign (GTK_LABEL (label), 0.f); + gtk_grid_attach (GTK_GRID (grid), label, 0, grid_vertical, 2, 1); + + grid_vertical++; + for (i = 1; i < MAX_LAYOUTS; ++i,++grid_vertical) { + labtext = g_string_new (_("... layout ")); + g_string_append_printf (labtext, "%d:", i); + label = gtk_label_new (labtext->str); + g_string_free (labtext, TRUE); + gtk_label_set_xalign (GTK_LABEL (label), 0.1f); + gtk_grid_attach (GTK_GRID (grid), label, 0, grid_vertical, 1, 1); + layoutdefault_entry[i] = gtk_entry_new(); + gtk_widget_set_hexpand (layoutdefault_entry[i], TRUE); + gtk_grid_attach (GTK_GRID (grid), layoutdefault_entry[i], 1, grid_vertical, 1, 1); + } + gtk_widget_show_all (vbox); g_signal_connect_swapped (settings_dialog, "response", @@ -260,6 +302,15 @@ xkb_dialog_configure_plugin (XfcePanelPlugin *plugin, xkb_dialog_transform_scale_range_for_caps_lock_indicator, NULL, NULL, NULL); + for (i = 1; i < MAX_LAYOUTS; ++i) { + g_object_bind_property (G_OBJECT (config), prop_names[i], + G_OBJECT (layoutdefault_entry[i]), "text", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + gtk_widget_set_has_tooltip (layoutdefault_entry[i], TRUE); + g_signal_connect (layoutdefault_entry[i], "query-tooltip", + G_CALLBACK (xkb_dialog_layoutdefault_tooltip), NULL); + } + gtk_widget_set_has_tooltip (display_scale_range, TRUE); g_signal_connect (display_scale_range, "query-tooltip", G_CALLBACK (xkb_dialog_set_style_warning_tooltip), NULL); diff --git a/panel-plugin/xkb-keyboard.c b/panel-plugin/xkb-keyboard.c index a7fb88b..5eec10a 100644 --- a/panel-plugin/xkb-keyboard.c +++ b/panel-plugin/xkb-keyboard.c @@ -574,6 +574,12 @@ xkb_keyboard_active_window_changed (WnckScreen *screen, guint id = 0; WnckWindow *window; guint window_id, application_id; + const gchar *classname; + const gchar *layoutdefaults; + guint trygroup; + gchar **defclasses; + gchar **aclass; + gboolean matched_default = FALSE; g_return_if_fail (IS_XKB_KEYBOARD (keyboard)); @@ -605,8 +611,24 @@ xkb_keyboard_active_window_changed (WnckScreen *screen, if (g_hash_table_lookup_extended (hashtable, GINT_TO_POINTER (id), &key, &value)) group = GPOINTER_TO_INT (value); - else + else { + classname = wnck_window_get_class_group_name (window); + for (trygroup = 1; trygroup < MAX_LAYOUTS; ++trygroup) { + layoutdefaults = xkb_xfconf_get_layout_defaults (keyboard->config, trygroup); + defclasses = g_strsplit (layoutdefaults, ",", -1); + for (aclass = defclasses; *aclass; ++aclass) { + if (g_strcmp0 (*aclass, classname) == 0) { + matched_default = TRUE; + group = trygroup; + break; + } + } + g_strfreev (defclasses); + if (matched_default) break; + } + g_hash_table_insert (hashtable, GINT_TO_POINTER (id), GINT_TO_POINTER (group)); + } xkb_keyboard_set_group (keyboard, group); } diff --git a/panel-plugin/xkb-properties.h b/panel-plugin/xkb-properties.h index c80971c..285bf99 100644 --- a/panel-plugin/xkb-properties.h +++ b/panel-plugin/xkb-properties.h @@ -32,6 +32,11 @@ #define CAPS_LOCK_INDICATOR "caps-lock-indicator" #define DISPLAY_TOOLTIP_ICON "display-tooltip-icon" #define GROUP_POLICY "group-policy" +#define LAYOUT1_DEFAULTS "layout1-defaults" +#define LAYOUT2_DEFAULTS "layout2-defaults" +#define LAYOUT3_DEFAULTS "layout3-defaults" +#define MAX_LAYOUTS 4 + typedef enum { diff --git a/panel-plugin/xkb-xfconf.c b/panel-plugin/xkb-xfconf.c index e7390f5..dc9bc1d 100644 --- a/panel-plugin/xkb-xfconf.c +++ b/panel-plugin/xkb-xfconf.c @@ -36,6 +36,7 @@ #define DEFAULT_CAPS_LOCK_INDICATOR TRUE #define DEFAULT_DISPLAY_TOOLTIP_ICON TRUE #define DEFAULT_GROUP_POLICY GROUP_POLICY_PER_APPLICATION +#define DEFAULT_LAYOUT_DEFAULTS "" static void xkb_xfconf_finalize (GObject *object); static void xkb_xfconf_get_property (GObject *object, @@ -62,6 +63,7 @@ struct _XkbXfconf gboolean caps_lock_indicator; gboolean display_tooltip_icon; XkbGroupPolicy group_policy; + GString *layout_defaults[MAX_LAYOUTS]; }; enum @@ -73,6 +75,9 @@ enum PROP_CAPS_LOCK_INDICATOR, PROP_DISPLAY_TOOLTIP_ICON, PROP_GROUP_POLICY, + PROP_LAYOUT1_DEFAULTS, + PROP_LAYOUT2_DEFAULTS, + PROP_LAYOUT3_DEFAULTS, N_PROPERTIES, }; @@ -136,6 +141,21 @@ xkb_xfconf_class_init (XkbXfconfClass *klass) DEFAULT_GROUP_POLICY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_LAYOUT1_DEFAULTS, + g_param_spec_string (LAYOUT1_DEFAULTS, NULL, NULL, + DEFAULT_LAYOUT_DEFAULTS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_LAYOUT2_DEFAULTS, + g_param_spec_string (LAYOUT2_DEFAULTS, NULL, NULL, + DEFAULT_LAYOUT_DEFAULTS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_LAYOUT3_DEFAULTS, + g_param_spec_string (LAYOUT3_DEFAULTS, NULL, NULL, + DEFAULT_LAYOUT_DEFAULTS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + xkb_xfconf_signals[CONFIGURATION_CHANGED] = g_signal_new (g_intern_static_string ("configuration-changed"), G_TYPE_FROM_CLASS (gobject_class), @@ -150,12 +170,18 @@ xkb_xfconf_class_init (XkbXfconfClass *klass) static void xkb_xfconf_init (XkbXfconf *config) { + guint i; + config->display_type = DEFAULT_DISPLAY_TYPE; config->display_name = DEFAULT_DISPLAY_NAME; config->display_scale = DEFAULT_DISPLAY_SCALE; config->caps_lock_indicator = DEFAULT_CAPS_LOCK_INDICATOR; config->display_tooltip_icon = DEFAULT_DISPLAY_TOOLTIP_ICON; config->group_policy = DEFAULT_GROUP_POLICY; + for (i=1; i < MAX_LAYOUTS; ++i) { + config->layout_defaults[i] = g_string_sized_new(256); + g_string_assign (config->layout_defaults[i], DEFAULT_LAYOUT_DEFAULTS); + } } @@ -163,7 +189,13 @@ xkb_xfconf_init (XkbXfconf *config) static void xkb_xfconf_finalize (GObject *object) { + XkbXfconf *config = XKB_XFCONF (object); + guint i; + xfconf_shutdown (); + for (i=1; i < MAX_LAYOUTS; ++i) { + g_string_free (config->layout_defaults[i], TRUE); + } G_OBJECT_CLASS (xkb_xfconf_parent_class)->finalize (object); } @@ -203,6 +235,18 @@ xkb_xfconf_get_property (GObject *object, g_value_set_uint (value, config->group_policy); break; + case PROP_LAYOUT1_DEFAULTS: + g_value_set_string (value, config->layout_defaults[1]->str); + break; + + case PROP_LAYOUT2_DEFAULTS: + g_value_set_string (value, config->layout_defaults[2]->str); + break; + + case PROP_LAYOUT3_DEFAULTS: + g_value_set_string (value, config->layout_defaults[3]->str); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -220,6 +264,14 @@ xkb_xfconf_set_property (GObject *object, XkbXfconf *config = XKB_XFCONF (object); guint val_uint; gboolean val_boolean; + guint layout; + GString *val_string; + const gchar *prop_names[MAX_LAYOUTS]; + + layout = 1; + prop_names[1] = LAYOUT1_DEFAULTS; + prop_names[2] = LAYOUT2_DEFAULTS; + prop_names[3] = LAYOUT3_DEFAULTS; switch (prop_id) { @@ -283,6 +335,20 @@ xkb_xfconf_set_property (GObject *object, } break; + case PROP_LAYOUT3_DEFAULTS: + ++layout; /* FALL THROUGH */ + case PROP_LAYOUT2_DEFAULTS: + ++layout; /* FALL THROUGH */ + case PROP_LAYOUT1_DEFAULTS: + val_string = g_string_new (g_value_get_string (value)); + if (!g_string_equal (val_string, config->layout_defaults[layout])) { + g_string_assign (config->layout_defaults[layout], val_string->str); + g_object_notify (G_OBJECT (config), prop_names[layout]); + g_signal_emit (G_OBJECT (config), xkb_xfconf_signals[CONFIGURATION_CHANGED], 0); + } + g_string_free (val_string, TRUE); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -344,6 +410,12 @@ xkb_xfconf_get_group_policy (XkbXfconf *config) } +const gchar * +xkb_xfconf_get_layout_defaults (XkbXfconf *config, guint layout) +{ + g_return_val_if_fail (IS_XKB_XFCONF (config), DEFAULT_LAYOUT_DEFAULTS); + return config->layout_defaults[layout]->str; +} XkbXfconf * xkb_xfconf_new (const gchar *property_base) @@ -381,6 +453,18 @@ xkb_xfconf_new (const gchar *property_base) property = g_strconcat (property_base, "/" GROUP_POLICY, NULL); xfconf_g_property_bind (channel, property, G_TYPE_UINT, config, GROUP_POLICY); g_free (property); + + property = g_strconcat (property_base, "/" LAYOUT1_DEFAULTS, NULL); + xfconf_g_property_bind (channel, property, G_TYPE_STRING, config, LAYOUT1_DEFAULTS); + g_free (property); + + property = g_strconcat (property_base, "/" LAYOUT2_DEFAULTS, NULL); + xfconf_g_property_bind (channel, property, G_TYPE_STRING, config, LAYOUT2_DEFAULTS); + g_free (property); + + property = g_strconcat (property_base, "/" LAYOUT3_DEFAULTS, NULL); + xfconf_g_property_bind (channel, property, G_TYPE_STRING, config, LAYOUT3_DEFAULTS); + g_free (property); } return config; diff --git a/panel-plugin/xkb-xfconf.h b/panel-plugin/xkb-xfconf.h index 7a8b2c1..1a3fd07 100644 --- a/panel-plugin/xkb-xfconf.h +++ b/panel-plugin/xkb-xfconf.h @@ -48,6 +48,7 @@ guint xkb_xfconf_get_display_scale (XkbXfconf *confi gboolean xkb_xfconf_get_caps_lock_indicator (XkbXfconf *config); gboolean xkb_xfconf_get_display_tooltip_icon (XkbXfconf *config); XkbGroupPolicy xkb_xfconf_get_group_policy (XkbXfconf *config); +const gchar * xkb_xfconf_get_layout_defaults (XkbXfconf *config, guint layout); G_END_DECLS From f103313697a1404832f63dc30d5171eacf20e934 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Fri, 26 Apr 2019 01:17:33 -0700 Subject: [PATCH 2/2] Update documentation in README --- README | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/README b/README index 83f3fb1..e69694b 100644 --- a/README +++ b/README @@ -11,10 +11,12 @@ use to switch between the layouts, the actual keyboard layouts, the way in which the current layout is being displayed (country flag image or text) and the layout policy, which is whether to store the layout globally (for all windows), per application or -per window. +per window. If the policy is per application or per window, then +for each layout you can specify a comma-separated list of window +class names which will default to using that layout. -If a certain flag is missing, the plugin will fallback to -displaying the layout as text. +If a certain country's flag is missing, the plugin will fallback +to displaying the layout as text. The plugin detects any change in the layout configuration (e.g. setxkbmap invocations) and reconfigures itself to use @@ -26,16 +28,6 @@ current layout is the second variant configured for some language. If the display mode is set to "text" then a little dot is displayed as a subscript of the layout text. -There is a hidden (not available in the GUI) setting - -"never_modify_config". If this setting is set to "true" in -the configuration file, then the plugin will not modify the -layout configuration under any circumstances (currently -even when the configuration is modified through the settings -dialog). This option is for users who wish to configure -some XKB options, which are not present in the GUI and thus -are limited by the plugin. These users can use the plugin -so that it only displays the active layouts. - Known limitations and bugs ==========================