X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=plugins%2Fplacement%2Fhistory.c;h=f2b4ea632a77790eadb57eb4592f55e91ff12c1d;hb=276b2be581c6cb138b439537761ff2ca42201805;hp=ea3d60dfb5cf9a7b2d2d0b7d7b438390946dd543;hpb=3e55e63f5d7fc4389e9c8b8646a5647dc5510f84;p=chaz%2Fopenbox diff --git a/plugins/placement/history.c b/plugins/placement/history.c index ea3d60df..f2b4ea63 100644 --- a/plugins/placement/history.c +++ b/plugins/placement/history.c @@ -3,41 +3,47 @@ #include "kernel/frame.h" #include "kernel/client.h" #include "kernel/screen.h" +#include "parser/parse.h" +#include "history.h" #include #include #ifdef HAVE_STDLIB_H # include #endif +#define PLACED (1 << 0) + +#define HAVE_POSITION (1 << 1) +#define HAVE_SIZE (1 << 2) +#define HAVE_DESKTOP (1 << 3) + struct HistoryItem { char *name; char *class; char *role; - int x; - int y; - gboolean placed; + + int flags; + + int x, y; + int w, h; + guint desk; }; -static GSList *history = NULL; +static GSList *history_list = NULL; static char *history_path = NULL; -static struct HistoryItem *find_history(Client *c) +static struct HistoryItem *history_find(const char *name, const char *class, + const char *role) { GSList *it; struct HistoryItem *hi = NULL; /* find the client */ - for (it = history; it != NULL; it = it->next) { + for (it = history_list; it != NULL; it = it->next) { hi = it->data; - g_assert(hi->name != NULL); - g_assert(hi->class != NULL); - g_assert(hi->role != NULL); - g_assert(c->name != NULL); - g_assert(c->class != NULL); - g_assert(c->role != NULL); - if (!strcmp(hi->name, c->name) && - !strcmp(hi->class, c->class) && - !strcmp(hi->role, c->role)) + if (!strcmp(hi->name, name) && + !strcmp(hi->class, class) && + !strcmp(hi->role, role)) return hi; } return NULL; @@ -46,57 +52,65 @@ static struct HistoryItem *find_history(Client *c) gboolean place_history(Client *c) { struct HistoryItem *hi; - int x, y; - - hi = find_history(c); - - if (hi != NULL && !hi->placed) { - hi->placed = TRUE; - if (ob_state != State_Starting) { - x = hi->x; - y = hi->y; - - frame_frame_gravity(c->frame, &x, &y); /* get where the client - should be */ - client_configure(c, Corner_TopLeft, x, y, - c->area.width, c->area.height, - TRUE, TRUE); + int x, y, w, h; + + hi = history_find(c->name, c->class, c->role); + + if (hi && !(hi->flags & PLACED)) { + hi->flags |= PLACED; + if (ob_state != OB_STATE_STARTING) { + if (hi->flags & HAVE_POSITION || + hi->flags & HAVE_SIZE) { + if (hi->flags & HAVE_POSITION) { + x = hi->x; + y = hi->y; + /* get where the client should be */ + frame_frame_gravity(c->frame, &x, &y); + } else { + x = c->area.x; + y = c->area.y; + } + if (hi->flags & HAVE_SIZE) { + w = hi->w * c->size_inc.width; + h = hi->h * c->size_inc.height; + } else { + w = c->area.width; + h = c->area.height; + } + client_configure(c, OB_CORNER_TOPLEFT, x, y, w, h, + TRUE, TRUE); + } + if (hi->flags & HAVE_DESKTOP) { + client_set_desktop(c, hi->desk, FALSE); + } } - return TRUE; + return hi->flags & HAVE_POSITION; } return FALSE; } -static void strip_tabs(char *s) -{ - while (*s != '\0') { - if (*s == '\t') - *s = ' '; - ++s; - } -} - static void set_history(Client *c) { struct HistoryItem *hi; - hi = find_history(c); + hi = history_find(c->name, c->class, c->role); if (hi == NULL) { hi = g_new(struct HistoryItem, 1); - history = g_slist_append(history, hi); + history_list = g_slist_append(history_list, hi); hi->name = g_strdup(c->name); - strip_tabs(hi->name); hi->class = g_strdup(c->class); - strip_tabs(hi->class); hi->role = g_strdup(c->role); - strip_tabs(hi->role); + hi->flags = HAVE_POSITION; + } + + if (hi->flags & HAVE_POSITION) { + hi->x = c->frame->area.x; + hi->y = c->frame->area.y; } - hi->x = c->frame->area.x; - hi->y = c->frame->area.y; - hi->placed = FALSE; + hi->flags &= ~PLACED; } static void event(ObEvent *e, void *foo) @@ -106,104 +120,130 @@ static void event(ObEvent *e, void *foo) set_history(e->data.c.client); } +/* + + + 0 + 0 + 300 + 200 + 1 + + +*/ + static void save_history() { - GError *err = NULL; - GIOChannel *io; - GString *buf; + xmlDocPtr doc; + xmlNodePtr root, node; + char *s; GSList *it; - struct HistoryItem *hi; - gsize ret; - - io = g_io_channel_new_file(history_path, "w", &err); - if (io != NULL) { - for (it = history; it != NULL; it = it->next) { - hi = it->data; - buf = g_string_sized_new(0); - buf=g_string_append(buf, hi->name); - g_string_append_c(buf, '\t'); - buf=g_string_append(buf, hi->class); - g_string_append_c(buf, '\t'); - buf=g_string_append(buf, hi->role); - g_string_append_c(buf, '\t'); - g_string_append_printf(buf, "%d", hi->x); - buf=g_string_append_c(buf, '\t'); - g_string_append_printf(buf, "%d", hi->y); - buf=g_string_append_c(buf, '\n'); - if (g_io_channel_write_chars(io, buf->str, buf->len, &ret, &err) != - G_IO_STATUS_NORMAL) - break; - g_string_free(buf, TRUE); + + doc = xmlNewDoc(NULL); + root = xmlNewNode(NULL, (const xmlChar*) "openbox_history"); + xmlDocSetRootElement(doc, root); + + for (it = history_list; it; it = g_slist_next(it)) { + struct HistoryItem *hi = it->data; + g_message("adding %s", hi->name); + node = xmlNewChild(root, NULL, (const xmlChar*) "entry", NULL); + xmlNewProp(node, (const xmlChar*) "name", (const xmlChar*) hi->name); + xmlNewProp(node, (const xmlChar*) "class", (const xmlChar*) hi->class); + xmlNewProp(node, (const xmlChar*) "role", (const xmlChar*) hi->role); + if (hi->flags & HAVE_POSITION) { + s = g_strdup_printf("%d", hi->x); + xmlNewTextChild(node, NULL, + (const xmlChar*) "x", (const xmlChar*) s); + g_free(s); + s = g_strdup_printf("%d", hi->y); + xmlNewTextChild(node, NULL, + (const xmlChar*) "y", (const xmlChar*) s); + g_free(s); + } + if (hi->flags & HAVE_SIZE) { + s = g_strdup_printf("%d", hi->w); + xmlNewTextChild(node, NULL, + (const xmlChar*) "width", (const xmlChar*) s); + g_free(s); + s = g_strdup_printf("%d", hi->h); + xmlNewTextChild(node, NULL, + (const xmlChar*) "height", (const xmlChar*) s); + g_free(s); + } + if (hi->flags & HAVE_DESKTOP) { + s = g_strdup_printf("%d", hi->desk < 0 ? hi->desk : hi->desk + 1); + xmlNewTextChild(node, NULL, + (const xmlChar*) "desktop", (const xmlChar*) s); + g_free(s); } - g_io_channel_unref(io); } + + xmlIndentTreeOutput = 1; + xmlSaveFormatFile(history_path, doc, 1); + + xmlFree(doc); } static void load_history() { - GError *err = NULL; - GIOChannel *io; - char *buf = NULL; - char *b, *c; - struct HistoryItem *hi = NULL; - - io = g_io_channel_new_file(history_path, "r", &err); - if (io != NULL) { - while (g_io_channel_read_line(io, &buf, NULL, NULL, &err) == - G_IO_STATUS_NORMAL) { - hi = g_new0(struct HistoryItem, 1); - - b = buf; - if ((c = strchr(b, '\t')) == NULL) break; - *c = '\0'; - hi->name = g_strdup(b); - - b = c + 1; - if ((c = strchr(b, '\t')) == NULL) break; - *c = '\0'; - hi->class = g_strdup(b); - - b = c + 1; - if ((c = strchr(b, '\t')) == NULL) break; - *c = '\0'; - hi->role = g_strdup(b); - - b = c + 1; - if ((c = strchr(b, '\t')) == NULL) break; - *c = '\0'; - hi->x = atoi(b); - - b = c + 1; - if ((c = strchr(b, '\n')) == NULL) break; - *c = '\0'; - hi->y = atoi(b); - - hi->placed = FALSE; - - g_free(buf); - buf = NULL; + xmlDocPtr doc; + xmlNodePtr node, n; + char *name; + char *class; + char *role; + struct HistoryItem *hi; - history = g_slist_append(history, hi); - hi = NULL; + if (!parse_load(history_path, "openbox_history", &doc, &node)) + return; + + node = parse_find_node("entry", node->xmlChildrenNode); + while (node) { + name = class = role = NULL; + if (parse_attr_string("name", node, &name) && + parse_attr_string("class", node, &class) && + parse_attr_string("role", node, &role)) { + + hi = history_find(name, class, role); + if (!hi) { + hi = g_new(struct HistoryItem, 1); + hi->name = g_strdup(name); + hi->class = g_strdup(class); + hi->role = g_strdup(role); + hi->flags = 0; + } + if ((n = parse_find_node("x", node->xmlChildrenNode))) { + hi->x = parse_int(doc, n); + if ((n = parse_find_node("y", node->xmlChildrenNode))) { + hi->y = parse_int(doc, n); + hi->flags |= HAVE_POSITION; + } + } + if ((n = parse_find_node("width", node->xmlChildrenNode))) { + hi->w = parse_int(doc, n); + if ((n = parse_find_node("height", node->xmlChildrenNode))) { + hi->h = parse_int(doc, n); + hi->flags |= HAVE_SIZE; + } + } + if ((n = parse_find_node("desktop", node->xmlChildrenNode))) { + hi->desk = parse_int(doc, n); + if (hi->desk > 0) --hi->desk; + hi->flags |= HAVE_DESKTOP; + } + + history_list = g_slist_append(history_list, hi); } - g_io_channel_unref(io); + g_free(name); g_free(class); g_free(role); + node = parse_find_node("entry", node->next); } - - g_free(buf); - - if (hi != NULL) { - g_free(hi->name); - g_free(hi->class); - g_free(hi->role); - } - g_free(hi); + xmlFree(doc); } void history_startup() { char *path; - history = NULL; + history_list = NULL; path = g_build_filename(g_get_home_dir(), ".openbox", "history", NULL); history_path = g_strdup_printf("%s.%d", path, ob_screen); @@ -219,9 +259,14 @@ void history_shutdown() GSList *it; save_history(); /* save to the historydb file */ - for (it = history; it != NULL; it = it->next) - g_free(it->data); - g_slist_free(history); + for (it = history_list; it != NULL; it = it->next) { + struct HistoryItem *hi = it->data; + g_free(hi->name); + g_free(hi->class); + g_free(hi->role); + g_free(hi); + } + g_slist_free(history_list); dispatch_register(0, (EventHandler)event, NULL);