/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ /* Copyright (C) 1998 Redhat Software Inc. * Code available under the Gnu GPL. * Authors: Owen Taylor , * Bradford Hovinen */ #include #include #include #include #include #include #include #include "wm-properties.h" #define CONFIG_PREFIX "/desktop/gnome/applications/window_manager" /* Current list of window managers */ GList *window_managers = NULL; /* List on startup */ static GList *window_managers_save = NULL; /* Current window manager */ static WindowManager *current_wm = NULL; /* Window manager on startup */ static WindowManager *current_wm_save = NULL; static gboolean xml_read_bool (xmlNodePtr node); static xmlNodePtr xml_write_bool (gchar *name, gboolean value); gboolean is_blank (gchar *str) { while (*str) { if (!isspace(*str)) return FALSE; str++; } return TRUE; } static gint wm_compare (gconstpointer a, gconstpointer b) { const WindowManager *wm_a = (const WindowManager *)a; const WindowManager *wm_b = (const WindowManager *)b; return g_ascii_strcasecmp (gnome_desktop_item_get_string (wm_a->dentry, GNOME_DESKTOP_ITEM_NAME), gnome_desktop_item_get_string (wm_b->dentry, GNOME_DESKTOP_ITEM_NAME)); } static void wm_free (WindowManager *wm) { gnome_desktop_item_unref (wm->dentry); g_free (wm->config_exec); g_free (wm->config_tryexec);; g_free (wm); } void wm_check_present (WindowManager *wm) { gchar *path; if (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC)) { if (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_TRY_EXEC)) { path = gnome_is_program_in_path (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_TRY_EXEC)); wm->is_present = (path != NULL); if (path) g_free (path); } else wm->is_present = TRUE; } else wm->is_present = FALSE; if (wm->config_exec) { if (wm->config_tryexec) { path = gnome_is_program_in_path (wm->config_tryexec); wm->is_config_present = (path != NULL); if (path) g_free (path); } else { path = gnome_is_program_in_path (wm->config_exec); wm->is_config_present = (path != NULL); if (path) g_free (path); } } else wm->is_config_present = FALSE; } static WindowManager * wm_copy (WindowManager *wm) { WindowManager *result = g_new (WindowManager, 1); result->dentry = gnome_desktop_item_copy (wm->dentry); result->config_exec = g_strdup (wm->config_exec); result->config_tryexec = g_strdup (wm->config_tryexec); result->session_managed = wm->session_managed; result->is_user = wm->is_user; result->is_present = wm->is_present; result->is_config_present = wm->is_config_present; return result; } static WindowManager * wm_list_find (GList *list, const char *name) { GList *tmp_list = list; while (tmp_list) { WindowManager *wm = tmp_list->data; if (strcmp (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC), name) == 0) return wm; tmp_list = tmp_list->next; } return NULL; } static WindowManager * wm_list_find_exec (GList *list, const char *name) { GList *tmp_list = list; while (tmp_list) { WindowManager *wm = tmp_list->data; if (!gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC)) continue; if (strcmp (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC), name) == 0) return wm; tmp_list = tmp_list->next; } return NULL; } static GList * wm_list_find_files (gchar *directory) { DIR *dir; struct dirent *child; GList *result = NULL; gchar *suffix; dir = opendir (directory); if (dir == NULL) return NULL; while ((child = readdir (dir)) != NULL) { /* Ignore files without .desktop suffix, and ignore * .desktop files with no prefix */ suffix = child->d_name + strlen (child->d_name) - 8; /* strlen(".desktop") == 8 */ if (suffix <= child->d_name || strcmp (suffix, ".desktop") != 0) continue; result = g_list_prepend (result, g_concat_dir_and_file (directory, child->d_name)); } closedir (dir); return result; } static void wm_list_read_dir (gchar *directory, gboolean is_user) { WindowManager *wm; GList *tmp_list; GList *files; gchar *prefix; files = wm_list_find_files (directory); tmp_list = files; while (tmp_list) { wm = g_new (WindowManager, 1); wm->dentry = gnome_desktop_item_new_from_file (tmp_list->data, GNOME_DESKTOP_ITEM_TYPE_APPLICATION, NULL); gnome_desktop_item_set_entry_type (wm->dentry, GNOME_DESKTOP_ITEM_TYPE_APPLICATION); if (!wm->dentry) { g_free (wm); tmp_list = tmp_list->next; continue; } prefix = g_strconcat ("=", gnome_desktop_item_get_location (wm->dentry), "=/Window Manager/", NULL); gnome_config_push_prefix (prefix); g_free (prefix); wm->config_exec = gnome_config_get_string ("ConfigExec"); wm->config_tryexec = gnome_config_get_string ("ConfigTryExec"); wm->session_managed = gnome_config_get_bool ("SessionManaged=0"); wm->is_user = is_user; if (wm->config_exec && is_blank (wm->config_exec)) { g_free (wm->config_exec); wm->config_exec = NULL; } if (wm->config_tryexec && is_blank (wm->config_tryexec)) { g_free (wm->config_tryexec); wm->config_tryexec = NULL; } gnome_config_pop_prefix (); wm_check_present (wm); if (gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_NAME) && gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC) && (wm->is_user || wm->is_present)) { window_managers = g_list_insert_sorted (window_managers, wm, wm_compare); window_managers_save = g_list_insert_sorted (window_managers_save, wm_copy (wm), wm_compare); } else { wm_free (wm); } tmp_list = tmp_list->next; } g_list_free (files); } void wm_list_init (void) { gchar *tempdir; gchar *name; GConfClient *client; tempdir = gnome_unconditional_datadir_file ("gnome/wm-properties/"); wm_list_read_dir (tempdir, FALSE); g_free (tempdir); tempdir = gnome_util_home_file("wm-properties/"); wm_list_read_dir (tempdir, TRUE); g_free (tempdir); client = gconf_client_get_default (); name = gconf_client_get_string (client, CONFIG_PREFIX "/current", NULL); if (name) { current_wm = wm_list_find (window_managers, name); g_free (name); } if (!current_wm) { name = gconf_client_get_string (client, CONFIG_PREFIX "/default", NULL); if (name) { current_wm = wm_list_find_exec (window_managers, name); g_free (name); } } if (!current_wm) { gchar *wmfile, *prefix; wmfile = gnome_unconditional_datadir_file ("default.wm"); prefix = g_strconcat ("=", wmfile, "=/Default/WM", NULL); name = gnome_config_get_string (prefix); g_free (wmfile); g_free (prefix); if (name) { current_wm = wm_list_find_exec (window_managers, name); g_free (name); } } if (!current_wm && window_managers) current_wm = window_managers->data; if(current_wm) current_wm_save = wm_list_find (window_managers_save, gnome_desktop_item_get_string (current_wm->dentry, GNOME_DESKTOP_ITEM_NAME)); g_object_unref (G_OBJECT (client)); } void wm_list_save (void) { GList *old_files; GList *tmp_list; gchar *tempdir; gchar *prefix; WindowManager *wm; /* Clean out the current contents of .gnome/wm-desktops */ tempdir = gnome_util_home_file("wm-properties/"); old_files = wm_list_find_files (tempdir); g_free (tempdir); tmp_list = old_files; while (tmp_list) { prefix = g_strconcat ("=", tmp_list->data, "=", NULL); gnome_config_clean_file (prefix); gnome_config_sync_file (prefix); g_free (prefix); tmp_list = tmp_list->next; } g_list_free (old_files); /* Save the user's desktops */ tmp_list = window_managers; while (tmp_list) { wm = tmp_list->data; if (wm->is_user) { gnome_desktop_item_save (wm->dentry, NULL, TRUE, NULL); prefix = g_strconcat ("=", gnome_desktop_item_get_location (wm->dentry), "=/Window Manager/", NULL); gnome_config_push_prefix (prefix); g_free (prefix); if (wm->config_exec) gnome_config_set_string ("ConfigExec", wm->config_exec); if (wm->config_tryexec) gnome_config_set_string ("ConfigTryExec", wm->config_tryexec); gnome_config_set_bool ("SessionManaged=0", wm->session_managed); gnome_config_pop_prefix (); } tmp_list = tmp_list->next; } /* Save the current window manager */ if(current_wm) { GConfClient *client = gconf_client_get_default (); gconf_client_set_string (client, CONFIG_PREFIX "/current", gnome_desktop_item_get_string (current_wm->dentry, GNOME_DESKTOP_ITEM_EXEC), NULL); g_object_unref (G_OBJECT (client)); } gnome_config_sync (); } void wm_list_revert (void) { GList *tmp_list; gchar *old_name = NULL; if(current_wm) old_name = g_strdup (gnome_desktop_item_get_string (current_wm->dentry, GNOME_DESKTOP_ITEM_NAME)); g_list_foreach (window_managers, (GFunc)wm_free, NULL); g_list_free (window_managers); window_managers = NULL; tmp_list = window_managers_save; while (tmp_list) { window_managers = g_list_prepend (window_managers, wm_copy (tmp_list->data)); tmp_list = tmp_list->next; } window_managers = g_list_reverse (window_managers); current_wm = wm_list_find (window_managers, old_name); g_free (old_name); } void wm_list_add (WindowManager *wm) { g_return_if_fail (wm != NULL); window_managers = g_list_insert_sorted (window_managers, wm, wm_compare); } void wm_list_delete (WindowManager *wm) { GList *node; g_return_if_fail (wm != NULL); g_return_if_fail (wm != current_wm); node = g_list_find (window_managers, wm); g_return_if_fail (node != NULL); window_managers = g_list_remove_link (window_managers, node); g_list_free_1 (node); wm_free (wm); } void wm_list_set_current (WindowManager *wm) { current_wm = wm; } WindowManager * wm_list_get_current (void) { return current_wm; } WindowManager * wm_list_get_revert (void) { if(current_wm_save) return wm_list_find (window_managers, gnome_desktop_item_get_string (current_wm_save->dentry, GNOME_DESKTOP_ITEM_NAME)); else return NULL; } static WindowManager * wm_read_from_xml (xmlNodePtr wm_node) { xmlNodePtr node; WindowManager *wm; gboolean is_current = FALSE; if (strcmp (wm_node->name, "window-manager")) return NULL; wm = g_new0 (WindowManager, 1); wm->dentry = gnome_desktop_item_new_from_file (xmlGetProp (wm_node, "desktop-entry"), GNOME_DESKTOP_ITEM_TYPE_APPLICATION, NULL); gnome_desktop_item_set_entry_type (wm->dentry, GNOME_DESKTOP_ITEM_TYPE_APPLICATION); for (node = wm_node->children; node; node = node->next) { if (!strcmp (node->name, "config-exec")) wm->config_exec = xmlNodeGetContent (node); else if (!strcmp (node->name, "config-tryexec")) wm->config_tryexec = xmlNodeGetContent (node); else if (!strcmp (node->name, "session-managed")) wm->session_managed = xml_read_bool (node); else if (!strcmp (node->name, "is-user")) wm->is_user = xml_read_bool (node); else if (!strcmp (node->name, "is-current")) is_current = xml_read_bool (node); /* FIXME: sanity check */ } wm_check_present (wm); if (wm->dentry == NULL || (wm->config_exec != NULL && is_blank (wm->config_exec)) || gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_NAME) == NULL || gnome_desktop_item_get_string (wm->dentry, GNOME_DESKTOP_ITEM_EXEC) == NULL || !(wm->is_user || wm->is_present)) { g_free (wm); return NULL; } if (is_current) current_wm = wm; return wm; } void wm_list_read_from_xml (xmlDocPtr doc) { xmlNodePtr root_node, node; WindowManager *wm; root_node = xmlDocGetRootElement (doc); if (strcmp (root_node->name, "wm-prefs")) return; for (node = root_node; node; node = node->next) { if (!strcmp (node->name, "window-manager")) { wm = wm_read_from_xml (node); if (wm) window_managers = g_list_insert_sorted (window_managers, wm, wm_compare); } } } static xmlNodePtr wm_write_to_xml (WindowManager *wm) { xmlNodePtr node; node = xmlNewNode (NULL, "window-manager"); xmlNewProp (node, "desktop-entry", gnome_desktop_item_get_location (wm->dentry)); if (wm->config_exec != NULL) xmlNewChild (node, NULL, "config-exec", wm->config_exec); xmlAddChild (node, xml_write_bool ("session-managed", wm->session_managed)); xmlAddChild (node, xml_write_bool ("is-user", wm->is_user)); xmlAddChild (node, xml_write_bool ("is-current", wm == current_wm)); return node; } xmlDocPtr wm_list_write_to_xml (void) { xmlDocPtr doc; xmlNodePtr root_node, node; GList *wm_node; doc = xmlNewDoc ("1.0"); root_node = xmlNewDocNode (doc, NULL, "wm-prefs", NULL); for (wm_node = window_managers; wm_node; wm_node = wm_node->next) { node = wm_write_to_xml ((WindowManager *) wm_node->data); if (node) xmlAddChild (root_node, node); } xmlDocSetRootElement (doc, root_node); return doc; } /* Read a boolean value from a node */ static gboolean xml_read_bool (xmlNodePtr node) { char *text; text = xmlNodeGetContent (node); if (!g_ascii_strcasecmp (text, "true")) return TRUE; else return FALSE; } /* Write out a boolean value in a node */ static xmlNodePtr xml_write_bool (gchar *name, gboolean value) { xmlNodePtr node; g_return_val_if_fail (name != NULL, NULL); node = xmlNewNode (NULL, name); if (value) xmlNodeSetContent (node, "true"); else xmlNodeSetContent (node, "false"); return node; }