1 #include "kernel/debug.h"
2 #include "kernel/openbox.h"
3 #include "kernel/dispatch.h"
4 #include "kernel/frame.h"
5 #include "kernel/client.h"
6 #include "kernel/screen.h"
7 #include "parser/parse.h"
15 #define PLACED (1 << 0)
17 #define HAVE_POSITION (1 << 1)
18 #define HAVE_SIZE (1 << 2)
19 #define HAVE_DESKTOP (1 << 3)
33 static GSList *history_list = NULL;
34 static char *history_path = NULL;
36 static struct HistoryItem *history_find(const char *name, const char *class,
40 struct HistoryItem *hi = NULL;
43 for (it = history_list; it != NULL; it = it->next) {
45 if (!strcmp(hi->name, name) &&
46 !strcmp(hi->class, class) &&
47 !strcmp(hi->role, role))
53 gboolean place_history(ObClient *c)
55 struct HistoryItem *hi;
58 hi = history_find(c->name, c->class, c->role);
60 if (hi && !(hi->flags & PLACED)) {
62 if (ob_state() != OB_STATE_STARTING) {
63 if (hi->flags & HAVE_POSITION ||
64 hi->flags & HAVE_SIZE) {
65 if (hi->flags & HAVE_POSITION) {
68 /* get where the client should be */
69 frame_frame_gravity(c->frame, &x, &y);
74 if (hi->flags & HAVE_SIZE) {
75 w = hi->w * c->size_inc.width;
76 h = hi->h * c->size_inc.height;
81 client_configure(c, OB_CORNER_TOPLEFT, x, y, w, h,
84 if (hi->flags & HAVE_DESKTOP) {
85 client_set_desktop(c, hi->desk, FALSE);
88 return hi->flags & HAVE_POSITION;
94 static void set_history(ObClient *c)
96 struct HistoryItem *hi;
98 hi = history_find(c->name, c->class, c->role);
101 hi = g_new(struct HistoryItem, 1);
102 history_list = g_slist_append(history_list, hi);
103 hi->name = g_strdup(c->name);
104 hi->class = g_strdup(c->class);
105 hi->role = g_strdup(c->role);
106 hi->flags = HAVE_POSITION;
109 if (hi->flags & HAVE_POSITION) {
110 hi->x = c->frame->area.x;
111 hi->y = c->frame->area.y;
114 hi->flags &= ~PLACED;
117 static void event(ObEvent *e, void *foo)
119 g_assert(e->type == Event_Client_Destroy);
121 set_history(e->data.c.client);
126 <entry name="name" class="class" role="role">
136 static void save_history()
139 xmlNodePtr root, node;
143 doc = xmlNewDoc(NULL);
144 root = xmlNewNode(NULL, (const xmlChar*) "openbox_history");
145 xmlDocSetRootElement(doc, root);
147 for (it = history_list; it; it = g_slist_next(it)) {
148 struct HistoryItem *hi = it->data;
149 ob_debug("adding %s\n", hi->name);
150 node = xmlNewChild(root, NULL, (const xmlChar*) "entry", NULL);
151 xmlNewProp(node, (const xmlChar*) "name", (const xmlChar*) hi->name);
152 xmlNewProp(node, (const xmlChar*) "class", (const xmlChar*) hi->class);
153 xmlNewProp(node, (const xmlChar*) "role", (const xmlChar*) hi->role);
154 if (hi->flags & HAVE_POSITION) {
155 s = g_strdup_printf("%d", hi->x);
156 xmlNewTextChild(node, NULL,
157 (const xmlChar*) "x", (const xmlChar*) s);
159 s = g_strdup_printf("%d", hi->y);
160 xmlNewTextChild(node, NULL,
161 (const xmlChar*) "y", (const xmlChar*) s);
164 if (hi->flags & HAVE_SIZE) {
165 s = g_strdup_printf("%d", hi->w);
166 xmlNewTextChild(node, NULL,
167 (const xmlChar*) "width", (const xmlChar*) s);
169 s = g_strdup_printf("%d", hi->h);
170 xmlNewTextChild(node, NULL,
171 (const xmlChar*) "height", (const xmlChar*) s);
174 if (hi->flags & HAVE_DESKTOP) {
175 s = g_strdup_printf("%d", hi->desk < 0 ? hi->desk : hi->desk + 1);
176 xmlNewTextChild(node, NULL,
177 (const xmlChar*) "desktop", (const xmlChar*) s);
182 xmlIndentTreeOutput = 1;
183 xmlSaveFormatFile(history_path, doc, 1);
188 static void load_history()
195 struct HistoryItem *hi;
197 if (!parse_load(history_path, "openbox_history", &doc, &node))
200 node = parse_find_node("entry", node->xmlChildrenNode);
202 name = class = role = NULL;
203 if (parse_attr_string("name", node, &name) &&
204 parse_attr_string("class", node, &class) &&
205 parse_attr_string("role", node, &role)) {
207 hi = history_find(name, class, role);
209 hi = g_new(struct HistoryItem, 1);
210 hi->name = g_strdup(name);
211 hi->class = g_strdup(class);
212 hi->role = g_strdup(role);
215 if ((n = parse_find_node("x", node->xmlChildrenNode))) {
216 hi->x = parse_int(doc, n);
217 if ((n = parse_find_node("y", node->xmlChildrenNode))) {
218 hi->y = parse_int(doc, n);
219 hi->flags |= HAVE_POSITION;
222 if ((n = parse_find_node("width", node->xmlChildrenNode))) {
223 hi->w = parse_int(doc, n);
224 if ((n = parse_find_node("height", node->xmlChildrenNode))) {
225 hi->h = parse_int(doc, n);
226 hi->flags |= HAVE_SIZE;
229 if ((n = parse_find_node("desktop", node->xmlChildrenNode))) {
230 hi->desk = parse_int(doc, n);
231 if (hi->desk > 0) --hi->desk;
232 hi->flags |= HAVE_DESKTOP;
235 history_list = g_slist_append(history_list, hi);
237 g_free(name); g_free(class); g_free(role);
238 node = parse_find_node("entry", node->next);
243 void history_startup()
249 path = g_build_filename(g_get_home_dir(), ".openbox", "history", NULL);
250 history_path = g_strdup_printf("%s.%d", path, ob_screen);
253 /*load_history(); /* load from the historydb file */
255 dispatch_register(Event_Client_Destroy, (EventHandler)event, NULL);
258 void history_shutdown()
262 /*save_history(); /* save to the historydb file */
263 for (it = history_list; it != NULL; it = it->next) {
264 struct HistoryItem *hi = it->data;
270 g_slist_free(history_list);
272 dispatch_register(0, (EventHandler)event, NULL);
274 g_free(history_path);