void
csd_keyboard_xkb_init (CsdKeyboardManager * kbd_manager)
{
	Display *display =
	    GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
	sagarmatha_settings_profile_start (NULL);

	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
					   DATADIR G_DIR_SEPARATOR_S
					   "icons");

	manager = kbd_manager;
	sagarmatha_settings_profile_start ("xkl_engine_get_instance");
	xkl_engine = xkl_engine_get_instance (display);
	sagarmatha_settings_profile_end ("xkl_engine_get_instance");
	if (xkl_engine) {
		inited_ok = TRUE;

		gkbd_desktop_config_init (&current_config, xkl_engine);
		gkbd_keyboard_config_init (&current_kbd_config,
					   xkl_engine);
		xkl_engine_backup_names_prop (xkl_engine);
		csd_keyboard_xkb_analyze_sysconfig ();

		settings_desktop = g_settings_new (GKBD_DESKTOP_SCHEMA);
		settings_keyboard = g_settings_new (GKBD_KEYBOARD_SCHEMA);
		g_signal_connect (settings_desktop, "changed",
				  (GCallback) apply_desktop_settings,
				  NULL);
		g_signal_connect (settings_keyboard, "changed",
				  (GCallback) apply_xkb_settings, NULL);

		gdk_window_add_filter (NULL, (GdkFilterFunc)
				       csd_keyboard_xkb_evt_filter, NULL);

		if (xkl_engine_get_features (xkl_engine) &
		    XKLF_DEVICE_DISCOVERY)
			g_signal_connect (xkl_engine, "X-new-device",
					  G_CALLBACK
					  (csd_keyboard_new_device), NULL);

		sagarmatha_settings_profile_start ("xkl_engine_start_listen");
		xkl_engine_start_listen (xkl_engine,
					 XKLL_MANAGE_LAYOUTS |
					 XKLL_MANAGE_WINDOW_STATES);
		sagarmatha_settings_profile_end ("xkl_engine_start_listen");

		sagarmatha_settings_profile_start ("apply_desktop_settings");
		apply_desktop_settings ();
		sagarmatha_settings_profile_end ("apply_desktop_settings");
		sagarmatha_settings_profile_start ("apply_xkb_settings");
		apply_xkb_settings ();
		sagarmatha_settings_profile_end ("apply_xkb_settings");
	}
	preview_dialogs = g_hash_table_new (g_direct_hash, g_direct_equal);

	sagarmatha_settings_profile_end (NULL);
}
static void
csd_keyboard_xkb_analyze_sysconfig (void)
{
	if (!inited_ok)
		return;

	gkbd_keyboard_config_init (&initial_sys_kbd_config, xkl_engine);
	gkbd_keyboard_config_load_from_x_initial (&initial_sys_kbd_config,
						  NULL);
}
static void
reset_to_defaults (GtkWidget * button, GtkBuilder * dialog)
{
	GkbdKeyboardConfig empty_kbd_config;

	gkbd_keyboard_config_init (&empty_kbd_config, engine);
	gkbd_keyboard_config_save (&empty_kbd_config);
	gkbd_keyboard_config_term (&empty_kbd_config);

	g_settings_reset (xkb_desktop_settings,
			  GKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP);

	/* all the rest is g-s-d's business */
}
void
enable_disable_restoring (GtkBuilder * dialog)
{
	GkbdKeyboardConfig gswic;
	gboolean enable;

	gkbd_keyboard_config_init (&gswic, engine);
	gkbd_keyboard_config_load (&gswic, NULL);

	enable = !gkbd_keyboard_config_equals (&gswic, &initial_config);

	gkbd_keyboard_config_term (&gswic);
	gtk_widget_set_sensitive (WID ("xkb_reset_to_defaults"), enable);
}
static void
gsd_keyboard_xkb_analyze_sysconfig (void)
{
	GConfClient *conf_client;

	if (!inited_ok)
		return;

	conf_client = gconf_client_get_default ();
	gkbd_keyboard_config_init (&initial_sys_kbd_config,
				   conf_client, xkl_engine);
	gkbd_keyboard_config_load_from_x_initial (&initial_sys_kbd_config,
						  NULL);
	g_object_unref (conf_client);
}
static void
apply_xkb_settings (void)
{
	GkbdKeyboardConfig current_sys_kbd_config;

	if (!inited_ok)
		return;

	gkbd_keyboard_config_init (&current_sys_kbd_config, xkl_engine);

	gkbd_keyboard_config_load (&current_kbd_config,
				   &initial_sys_kbd_config);

	gkbd_keyboard_config_load_from_x_current (&current_sys_kbd_config,
						  NULL);

	if (!try_activating_xkb_config_if_new (&current_sys_kbd_config)) {
		if (filter_xkb_config ()) {
			if (!try_activating_xkb_config_if_new
			    (&current_sys_kbd_config)) {
				g_warning
				    ("Could not activate the filtered XKB configuration");
				activation_error ();
			}
		} else {
			g_warning
			    ("Could not activate the XKB configuration");
			activation_error ();
		}
	} else
		xkl_debug (100,
			   "Actual KBD configuration was not changed: redundant notification\n");

	gkbd_keyboard_config_term (&current_sys_kbd_config);
	show_hide_icon ();
}
void
gsd_keyboard_xkb_init (GConfClient * client)
{
	gnome_settings_profile_start (NULL);
#ifdef GSDKX
	xkl_set_debug_level (200);
	logfile = fopen ("/tmp/gsdkx.log", "a");
	xkl_set_log_appender (gsd_keyboard_log_appender);
#endif
	gnome_settings_profile_start ("xkl_engine_get_instance");
	xkl_engine = xkl_engine_get_instance (GDK_DISPLAY ());
	gnome_settings_profile_end ("xkl_engine_get_instance");
	if (xkl_engine) {
		inited_ok = TRUE;

		gdm_keyboard_layout = g_getenv ("GDM_KEYBOARD_LAYOUT");

		gkbd_desktop_config_init (&current_config,
					  client, xkl_engine);
		gkbd_keyboard_config_init (&current_kbd_config,
					   client, xkl_engine);
		xkl_engine_backup_names_prop (xkl_engine);
		gsd_keyboard_xkb_analyze_sysconfig ();
		gnome_settings_profile_start
		    ("gsd_keyboard_xkb_chk_lcl_xmm");
		gsd_keyboard_xkb_chk_lcl_xmm ();
		gnome_settings_profile_end
		    ("gsd_keyboard_xkb_chk_lcl_xmm");

		notify_desktop =
		    register_config_callback (client,
					      GKBD_DESKTOP_CONFIG_DIR,
					      (GConfClientNotifyFunc)
					      apply_desktop_settings);

		notify_keyboard =
		    register_config_callback (client,
					      GKBD_KEYBOARD_CONFIG_DIR,
					      (GConfClientNotifyFunc)
					      apply_xkb_settings);

		gdk_window_add_filter (NULL, (GdkFilterFunc)
				       gsd_keyboard_xkb_evt_filter, NULL);

		if (xkl_engine_get_features (xkl_engine) &
		    XKLF_DEVICE_DISCOVERY)
			g_signal_connect (xkl_engine, "X-new-device",
					  G_CALLBACK
					  (gsd_keyboard_new_device), NULL);

		gnome_settings_profile_start ("xkl_engine_start_listen");
		xkl_engine_start_listen (xkl_engine,
					 XKLL_MANAGE_LAYOUTS |
					 XKLL_MANAGE_WINDOW_STATES);
		gnome_settings_profile_end ("xkl_engine_start_listen");

		gnome_settings_profile_start ("apply_desktop_settings");
		apply_desktop_settings ();
		gnome_settings_profile_end ("apply_desktop_settings");
		gnome_settings_profile_start ("apply_xkb_settings");
		apply_xkb_settings ();
		gnome_settings_profile_end ("apply_xkb_settings");
	}
	preview_dialogs = g_hash_table_new (g_direct_hash, g_direct_equal);
	gnome_settings_profile_end (NULL);
}
static void
apply_xkb_settings (void)
{
	GConfClient *conf_client;
	GkbdKeyboardConfig current_sys_kbd_config;
	int group_to_activate = -1;
	char *gdm_layout;
	char *s;

	if (!inited_ok)
		return;

	conf_client = gconf_client_get_default ();

	/* With GDM the user can already set a layout from the login
	 * screen. Try to keep that setting.
	 * We clear gdm_keyboard_layout early, so we don't risk
	 * recursion from gconf notification.
	 */
	gdm_layout = g_strdup (gdm_keyboard_layout);
	gdm_keyboard_layout = NULL;

	/* gdm's configuration and $GDM_KEYBOARD_LAYOUT separates layout and
	 * variant with a space, but gconf uses tabs; so convert to be robust
	 * with both */
	for (s = gdm_layout; s && *s; ++s) {
		if (*s == ' ') {
			*s = '\t';
		}
	}

	if (gdm_layout != NULL) {
		GSList *layouts;
		GSList *found_node;
		int max_groups;

		max_groups = xkl_engine_get_max_num_groups (xkl_engine);
		layouts = gconf_client_get_list (conf_client,
						 GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS,
						 GCONF_VALUE_STRING, NULL);

		/* Add the layout if it doesn't already exist. XKB limits the
		 * total number of layouts. If we already have the maximum
		 * number of layouts configured, we replace the last one. This
		 * prevents the list from becoming full if the user has a habit
		 * of selecting many different keyboard layouts in GDM. */

		found_node =
		    g_slist_find_custom (layouts, gdm_layout,
					 (GCompareFunc) g_strcmp0);

		if (!found_node) {
			/* Insert at the last valid place, or at the end of
			 * list, whichever comes first */
			layouts =
			    g_slist_insert (layouts, g_strdup (gdm_layout),
					    max_groups - 1);
			if (g_slist_length (layouts) > max_groups) {
				GSList *last;
				GSList *free_layouts;

				last =
				    g_slist_nth (layouts, max_groups - 1);
				free_layouts = last->next;
				last->next = NULL;

				g_slist_foreach (free_layouts,
						 (GFunc) g_free, NULL);
				g_slist_free (free_layouts);
			}

			gconf_client_set_list (conf_client,
					       GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS,
					       GCONF_VALUE_STRING, layouts,
					       NULL);
		}

		g_slist_foreach (layouts, (GFunc) g_free, NULL);
		g_slist_free (layouts);
	}

	gkbd_keyboard_config_init (&current_sys_kbd_config,
				   conf_client, xkl_engine);

	gkbd_keyboard_config_load_from_gconf (&current_kbd_config,
					      &initial_sys_kbd_config);

	gkbd_keyboard_config_load_from_x_current (&current_sys_kbd_config,
						  NULL);

	if (!try_activating_xkb_config_if_new (&current_sys_kbd_config)) {
		if (filter_xkb_config ()) {
			if (!try_activating_xkb_config_if_new
			    (&current_sys_kbd_config)) {
				g_warning
				    ("Could not activate the filtered XKB configuration");
				activation_error ();
			}
		} else {
			g_warning
			    ("Could not activate the XKB configuration");
			activation_error ();
		}
	} else
		xkl_debug (100,
			   "Actual KBD configuration was not changed: redundant notification\n");

	if (gdm_layout != NULL) {
		/* If there are multiple layouts,
		 * try to find the one closest to the gdm layout
		 */
		GSList *l;
		int i;
		size_t len = strlen (gdm_layout);
		for (i = 0, l = current_kbd_config.layouts_variants; l;
		     i++, l = l->next) {
			char *lv = l->data;
			if (strncmp (lv, gdm_layout, len) == 0
			    && (lv[len] == '\0' || lv[len] == '\t')) {
				group_to_activate = i;
				break;
			}
		}
	}

	g_free (gdm_layout);

	if (group_to_activate != -1)
		xkl_engine_lock_group (current_config.engine,
				       group_to_activate);
	gkbd_keyboard_config_term (&current_sys_kbd_config);
}
void
setup_xkb_tabs (GtkBuilder * dialog)
{
	GtkWidget *widget;
	GtkStyleContext *context;
	GtkWidget *chk_new_windows_inherit_layout;

	chk_new_windows_inherit_layout = WID ("chk_new_windows_inherit_layout");

	xkb_desktop_settings = g_settings_new (GKBD_DESKTOP_SCHEMA);
	xkb_keyboard_settings = g_settings_new (GKBD_KEYBOARD_SCHEMA);

	engine =
	    xkl_engine_get_instance (GDK_DISPLAY_XDISPLAY
				     (gdk_display_get_default ()));
	config_registry = xkl_config_registry_get_instance (engine);

	gkbd_desktop_config_init (&desktop_config, engine);
	gkbd_desktop_config_load (&desktop_config);

	xkl_config_registry_load (config_registry,
				  desktop_config.load_extra_items);

	gkbd_keyboard_config_init (&initial_config, engine);
	gkbd_keyboard_config_load_from_x_initial (&initial_config, NULL);

	/* Set initial state */
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("chk_separate_group_per_window")),
				      g_settings_get_boolean (xkb_desktop_settings,
							      GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW));
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chk_new_windows_inherit_layout),
				      xkb_get_default_group () < 0);

	g_settings_bind (xkb_desktop_settings,
			 GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
			 WID ("chk_separate_group_per_window"), "active",
			 G_SETTINGS_BIND_DEFAULT);
	g_settings_bind (xkb_desktop_settings,
			 GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
			 WID ("chk_new_windows_inherit_layout"), "sensitive",
			 G_SETTINGS_BIND_DEFAULT);
	g_settings_bind (xkb_desktop_settings,
			 GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
			 WID ("chk_new_windows_default_layout"), "sensitive",
			 G_SETTINGS_BIND_DEFAULT);

	xkb_layouts_prepare_selected_tree (dialog);
	xkb_layouts_fill_selected_tree (dialog);

	xkb_layouts_register_buttons_handlers (dialog);
	g_signal_connect (G_OBJECT (WID ("xkb_reset_to_defaults")),
			  "clicked", G_CALLBACK (reset_to_defaults),
			  dialog);

	g_signal_connect (G_OBJECT (chk_new_windows_inherit_layout),
			  "toggled",
			  G_CALLBACK
			  (chk_new_windows_inherit_layout_toggled),
			  dialog);

	g_signal_connect_swapped (G_OBJECT (WID ("xkb_layout_options")),
				  "clicked",
				  G_CALLBACK (xkb_options_popup_dialog),
				  dialog);

	xkb_layouts_register_conf_listener (dialog);
	xkb_options_register_conf_listener (dialog);

	g_object_weak_ref (G_OBJECT (WID ("region_notebook")),
			   (GWeakNotify) cleanup_xkb_tabs, dialog);

	enable_disable_restoring (dialog);

	/* Setup junction between toolbar and treeview */
	widget = WID ("xkb_layouts_swindow");
	context = gtk_widget_get_style_context (widget);
	gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
	widget = WID ("layouts-toolbar");
	context = gtk_widget_get_style_context (widget);
	gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
}