Menu parsing updates for plugins.
authorScott Moynes <smoynes@nexus.carleton.ca>
Thu, 17 Jul 2003 01:40:27 +0000 (01:40 +0000)
committerScott Moynes <smoynes@nexus.carleton.ca>
Thu, 17 Jul 2003 01:40:27 +0000 (01:40 +0000)
FIFO menus are the only plugin that takes advantage of this.
Example:
<menu id="root" label="Openbox 3">
  <menu id="fonk" label="fonk" plugin="fifo_menu">
  </menu>
</menu>

This creates a FIFO ~/.openbox/fifo_menu/fonk to which you can send
menus to. The menus sent to it must be like
<fifo>
  <item>
   etc...
</fifo>

I think. If my memory serves me right.

It is all hideous, but I just wanted to experiment and see if it was
possible.

openbox/menu.c
openbox/menu.h
openbox/plugin.c
openbox/plugin.h
plugins/menu/fifo_menu.c

index a8a5111..e2c55c6 100644 (file)
@@ -18,28 +18,51 @@ GSList *menu_visible = NULL;
 
 static void parse_menu(xmlDocPtr doc, xmlNodePtr node, void *data)
 {
+    parse_menu_full(doc, node, data, TRUE);
+}
+
+
+void parse_menu_full(xmlDocPtr doc, xmlNodePtr node, void *data,
+                       gboolean newmenu)
+{
     Action *act;
     xmlNodePtr nact;
-    gchar *id = NULL, *title = NULL, *label = NULL;
-    ObMenu *menu, *parent;
 
-    if (!parse_attr_string("id", node->parent, &id))
-        goto parse_menu_fail;
-    if (!parse_attr_string("label", node->parent, &title))
-        goto parse_menu_fail;
+    gchar *id = NULL, *title = NULL, *label = NULL, *plugin;
+    ObMenu *menu = NULL, *parent;
+
+    if (newmenu == TRUE) {
+        if (!parse_attr_string("id", node->parent, &id))
+            goto parse_menu_fail;
+        if (!parse_attr_string("label", node->parent, &title))
+            goto parse_menu_fail;
 
-    g_message("menu label %s", title);
+        g_message("menu label %s", title);
 
-    menu = menu_new(title, id, data ? *((ObMenu**)data) : NULL);
-    if (data)
-        *((ObMenu**)data) = menu;
+        menu = menu_new(title, id, data ? *((ObMenu**)data) : NULL);
 
+        if (data)
+            *((ObMenu**)data) = menu;
+    } else {
+        menu = (ObMenu *)data;
+    }
+    
     while (node) {
         if (!xmlStrcasecmp(node->name, (const xmlChar*) "menu")) {
-            parent = menu;
-            parse_menu(doc, node->xmlChildrenNode, &parent);
-            menu_add_entry(menu, menu_entry_new_submenu(parent->label,
-                                                        parent));
+            if (parse_attr_string("plugin", node, &plugin)) {
+                PluginMenuCreateData data = {
+                    .doc = doc,
+                    .node = node,
+                    .parent = menu
+                };
+                parent = plugin_create(plugin, &data);
+            } else {
+                parent = menu;
+                parse_menu(doc, node->xmlChildrenNode, &parent);
+                menu_add_entry(menu, menu_entry_new_submenu(parent->label,
+                                                            parent));
+            }
+
         }
         else if (!xmlStrcasecmp(node->name, (const xmlChar*) "item")) {
             if (parse_attr_string("label", node, &label)) {
index 72a7ed2..2f3f9ac 100644 (file)
@@ -96,7 +96,14 @@ struct _ObMenuEntry
     RrAppearance *a_hilite;
     gint y;
     gint min_w;
-};
+} MenuEntry;
+
+typedef struct PluginMenuCreateData{
+    xmlDocPtr doc;
+    xmlNodePtr node;
+    ObMenu *parent;
+} PluginMenuCreateData;
+
 
 void menu_startup();
 void menu_shutdown();
@@ -147,5 +154,7 @@ void menu_entry_fire(ObMenuEntry *self);
 void menu_render(ObMenu *self);
 void menu_render_full(ObMenu *self);
 
+//so plugins can call it?
+void parse_menu_full(xmlDocPtr doc, xmlNodePtr node, void *data, gboolean new);
 void menu_control_mouseover(ObMenuEntry *entry, gboolean enter);
 #endif
index 747bde6..cd17d21 100644 (file)
@@ -176,7 +176,7 @@ void plugin_loadall()
     }
 }
 
-void *plugin_create(char *name /* TODO */)
+void *plugin_create(char *name, void *data)
 {
     Plugin *p = (Plugin *)g_datalist_get_data(&plugins, name);
 
@@ -190,7 +190,7 @@ void *plugin_create(char *name /* TODO */)
        return NULL;
     }
 
-    return p->create();
+    return p->create(data);
 }
 
 void plugin_destroy(char *name, void *data)
index 733f564..38da208 100644 (file)
@@ -14,7 +14,7 @@ gboolean plugin_open_reopen(char *name);
 void plugin_close(char *name);
 
 /* call plugin's generic constructor */
-void *plugin_create(char *name /* TODO */);
+void *plugin_create(char *name, void *data);
 /* free memory allocated by plugin_create() */
 void plugin_destroy(char *name, void *object);
 
index e5580b0..a05989f 100644 (file)
@@ -73,7 +73,8 @@ void fifo_menu_handler(int fd, void *d) {
         FIFO_MENU_DATA(menu)->buf = tmpbuf;
     
         num_read = read(fd,
-                        FIFO_MENU_DATA(menu)->buf + FIFO_MENU_DATA(menu)->buflen,
+                        FIFO_MENU_DATA(menu)->buf +
+                        FIFO_MENU_DATA(menu)->buflen,
                         num_realloc);
 
         if (num_read == 0) { /* eof */
@@ -83,24 +84,25 @@ void fifo_menu_handler(int fd, void *d) {
             menu->invalid = TRUE;
             menu_clear(menu);
 
-            /* TEMP: list them */
-            while (NULL !=
-                   (found = strchr(&FIFO_MENU_DATA(menu)->buf[count], '\n'))) {
-                FIFO_MENU_DATA(menu)->buf
-                    [found - FIFO_MENU_DATA(menu)->buf] = '\0';
-                menu_add_entry(menu,
-                               menu_entry_new_separator
-                               (&FIFO_MENU_DATA(menu)->buf[count]));
-                count = found - FIFO_MENU_DATA(menu)->buf + 1;
-            }
-
             FIFO_MENU_DATA(menu)->buf[FIFO_MENU_DATA(menu)->buflen] = '\0';
-            fifo_menu_clean_up(menu);
 
+            xmlDocPtr doc = xmlParseMemory(FIFO_MENU_DATA(menu)->buf,
+                                           FIFO_MENU_DATA(menu)->buflen);
+
+            xmlNodePtr node = xmlDocGetRootElement(doc);
+
+            if (!xmlStrcasecmp(node->name, (const xmlChar*) "fifo")) {
+                if ((node = parse_find_node("item", node->xmlChildrenNode)))
+                    parse_menu_full(doc, node, menu, FALSE);
+            }
+            
+            fifo_menu_clean_up(menu);
+            
             event_remove_fd(FIFO_MENU_DATA(menu)->handler->fd);
         
             if ((FIFO_MENU_DATA(menu)->fd =
-                 open(FIFO_MENU_DATA(menu)->fifo, O_NONBLOCK | O_RDONLY)) == -1) {
+                 open(FIFO_MENU_DATA(menu)->fifo,
+                      O_NONBLOCK | O_RDONLY)) == -1) {
                 g_warning("Can't reopen FIFO");
                 fifo_menu_clean_up(menu);
                 return;
@@ -134,15 +136,31 @@ void plugin_destroy (ObMenu *m)
     menu_free(m->name);
 }
 
-void *plugin_create() /* TODO: need config */
+void *plugin_create(PluginMenuCreateData *data)
+
+
 {
     char *fifo;
     char *dir;
     event_fd_handler *h;
-    
-    Fifo_Menu_Data *d = g_new(Fifo_Menu_Data, 1);
-    ObMenu *m = menu_new("", PLUGIN_NAME, NULL);
+    Fifo_Menu_Data *d;
+    ObMenu *m;
+    char *label = NULL, *id = NULL;
+        
+    d = g_new(Fifo_Menu_Data, 1);
+
+    parse_attr_string("id", data->node, &id);
+    parse_attr_string("label", data->node, &label);
+
+    m = menu_new( (label != NULL ? label : ""),
+                 (id != NULL ? id : PLUGIN_NAME),
+                 data->parent);
+    menu_add_entry(data->parent, menu_entry_new_submenu(
+                       (label != NULL ? label : ""),
+                       m));
 
+    g_free(label);
+    g_free(id);
     d->fd = -1;
     d->buf = NULL;
     d->buflen = 0;
@@ -154,7 +172,8 @@ void *plugin_create() /* TODO: need config */
     
     m->plugin_data = (void *)d;
 
-    dir = g_build_filename(g_get_home_dir(), ".openbox", PLUGIN_NAME, NULL);
+    dir = g_build_filename(g_get_home_dir(), ".openbox",
+                          PLUGIN_NAME, NULL);
 
     if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) == -1 && errno != EEXIST) {
 /* technically, if ~/.openbox/fifo_menu exists and isn't a directory
@@ -166,7 +185,8 @@ void *plugin_create() /* TODO: need config */
         return NULL;
     }
 
-    fifo = g_build_filename(g_get_home_dir(), ".openbox", PLUGIN_NAME,
+    fifo = g_build_filename(g_get_home_dir(), ".openbox",
+                            PLUGIN_NAME,
                             m->name, NULL);
     if (mkfifo(fifo, S_IRUSR | S_IWUSR |
                S_IRGRP | S_IWGRP | /* let umask do its thing */