add copyright comments
[dana/obconf.git] / src / desktops.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    desktops.c for ObConf, the configuration tool for Openbox
4    Copyright (c) 2003-2007   Dana Jansens
5    Copyright (c) 2003        Tim Riley
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "main.h"
21 #include "tree.h"
22 #include "gettext.h"
23
24 #include <gdk/gdkx.h>
25
26 static gboolean mapping = FALSE;
27
28 static GtkListStore *desktop_store;
29 static int num_desktops;
30 static GList *desktop_names;
31
32 static void reset_desktop_names();
33 static void desktops_set_names();
34 static void desktops_set_number();
35 static void on_desktop_names_cell_edited(GtkCellRendererText *cell,
36                                          const gchar *path_string,
37                                          const gchar *new_text,
38                                          gpointer data);
39
40 void desktops_setup_num(GtkWidget *w)
41 {
42     mapping = TRUE;
43
44     num_desktops = tree_get_int("desktops/number", 4);
45     gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), num_desktops);
46
47     mapping = FALSE;
48 }
49
50 void desktops_setup_names(GtkWidget *w)
51 {
52     GtkCellRenderer *render;
53     GtkTreeViewColumn *column;
54
55     mapping = TRUE;
56
57     desktop_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN);
58     gtk_tree_view_set_model(GTK_TREE_VIEW(w), GTK_TREE_MODEL(desktop_store));
59     g_object_unref (desktop_store);
60
61     gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)),
62                                 GTK_SELECTION_SINGLE);
63
64     render = gtk_cell_renderer_text_new();
65     g_signal_connect(render, "edited",
66                      G_CALLBACK (on_desktop_names_cell_edited),
67                      NULL);
68
69     column = gtk_tree_view_column_new_with_attributes
70         ("Name", render, "text", 0, "editable", 1, NULL);
71     gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
72
73     reset_desktop_names();
74
75     mapping = FALSE;
76 }
77
78 void on_desktop_num_value_changed(GtkSpinButton *w, gpointer data)
79 {
80     if (mapping) return;
81
82     num_desktops = gtk_spin_button_get_value(w);
83
84     desktops_set_number();
85
86     reset_desktop_names();
87 }
88
89 static void on_desktop_names_cell_edited(GtkCellRendererText *cell,
90                                          const gchar *path_string,
91                                          const gchar *new_text,
92                                          gpointer data)
93 {
94     GtkTreePath *path;
95     GtkTreeIter it;
96     gchar *old_text;
97     GList *lit;
98     gint i;
99
100     if (mapping) return;
101
102     path = gtk_tree_path_new_from_string (path_string);
103     gtk_tree_model_get_iter(GTK_TREE_MODEL(desktop_store), &it, path);
104
105     gtk_tree_model_get(GTK_TREE_MODEL(desktop_store), &it, 0, &old_text, -1);
106     g_free(old_text);
107
108     i = gtk_tree_path_get_indices(path)[0];
109     lit = g_list_nth(desktop_names, i);
110
111     g_free(lit->data);
112     lit->data = g_strdup(new_text);
113     if (new_text[0]) /* not empty */
114         gtk_list_store_set(desktop_store, &it, 0, lit->data, -1);
115     else
116         gtk_list_store_set(desktop_store, &it, 0, _("(Unnamed desktop)"), -1);
117
118     desktops_set_names();
119 }
120
121 static void reset_desktop_names()
122 {
123     GtkTreeIter it;
124     xmlNodePtr n;
125     gint i;
126     GList *lit;
127
128     gtk_list_store_clear(desktop_store);
129
130     for (lit = desktop_names; lit; lit = g_list_next(lit))
131         g_free(lit->data);
132     g_list_free(desktop_names);
133     desktop_names = NULL;
134
135     i = 0;
136     n = tree_get_node("desktops/names", NULL)->children;
137     while (n) {
138         gchar *name;
139
140         if (!xmlStrcmp(n->name, (const xmlChar*)"name")) {
141             name = parse_string(doc, n);
142
143             desktop_names = g_list_append(desktop_names, name);
144
145             gtk_list_store_append(desktop_store, &it);
146             gtk_list_store_set(desktop_store, &it,
147                                0, (name[0] ? name : _("(Unnamed desktop)")),
148                                1, TRUE,
149                                -1);
150             ++i;
151         }
152
153         n = n->next;
154     }
155
156     while (i < num_desktops) {
157         gchar *name = g_strdup("");
158
159         desktop_names = g_list_append(desktop_names, name);
160
161         gtk_list_store_append(desktop_store, &it);
162         gtk_list_store_set(desktop_store, &it,
163                            0, _("(Unnamed desktop)"),
164                            1, TRUE,
165                            -1);
166         ++i;
167     }
168 }
169
170 static void desktops_set_names()
171 {
172     gchar **s;
173     GList *lit;
174     xmlNodePtr n, c;
175     gint num = 0, last = -1;
176
177     n = tree_get_node("desktops/names", NULL);
178     while ((c = n->children)) {
179         xmlUnlinkNode(c);
180         xmlFreeNode(c);
181     }
182
183     for (lit = desktop_names; lit; lit = g_list_next(lit)) {
184         if (((gchar*)lit->data)[0]) /* not empty */
185             last = num;
186         ++num;
187     }
188
189     num = 0;
190     for (lit = desktop_names; lit && num <= last; lit = g_list_next(lit)) {
191         xmlNewTextChild(n, NULL, "name", lit->data);
192         ++num;
193     }
194     tree_apply();
195
196     /* make openbox re-set the property */
197     XDeleteProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
198                     XInternAtom(GDK_DISPLAY(), "_NET_DESKTOP_NAMES", FALSE));
199 }
200
201 static void desktops_set_number()
202 {
203     XEvent ce;
204
205     tree_set_int("desktops/number", num_desktops);
206
207     ce.xclient.type = ClientMessage;
208     ce.xclient.message_type = XInternAtom(GDK_DISPLAY(),
209                                           "_NET_NUMBER_OF_DESKTOPS",
210                                           FALSE);
211     ce.xclient.display = GDK_DISPLAY();
212     ce.xclient.window = GDK_ROOT_WINDOW();
213     ce.xclient.format = 32;
214     ce.xclient.data.l[0] = num_desktops;
215     ce.xclient.data.l[1] = 0;
216     ce.xclient.data.l[2] = 0;
217     ce.xclient.data.l[3] = 0;
218     ce.xclient.data.l[4] = 0;
219     XSendEvent(GDK_DISPLAY(), GDK_ROOT_WINDOW(), FALSE,
220                SubstructureNotifyMask | SubstructureRedirectMask,
221                &ce);
222 }