FrapMenu change notification (was Re: xfdesktop menu is getting awesomer)

Brian J. Tarricone bjt23 at cornell.edu
Tue Mar 20 22:27:18 CET 2007


On Tue, 20 Mar 2007 21:14:40 +0100 Jannis Pohlmann wrote:

>On Mon, 19 Mar 2007 17:40:51 -0700, Brian J. Tarricone wrote:
>
>> If you want to do that in FrapMenu, perhaps offer the ability via API
>> to set a function vtable for doing monitoring?  Sorta like how with
>> glib you can set threading or memory functions.  So something like:
>>
>> struct FrapMenuMonitorVtable
>> {
>>     gpointer (*monitor_file)(FrapMenu *menu,
>>                              const gchar *filename,
>>                              gpointer user_data);
>>
>>     gpointer (*monitor_directory)(FrapMenu *menu,
>>                                   const gchar *filename,
>>                                   gpointer user_data);
>>
>>     void (*cancel_monitor)(FrapMenu *menu,
>>                            gpointer monitor_handle);
>> };
>>
>> So then I could plug in my own implementation using thunar-vfs, or
>> inotify, or FAM/gamin, or whatever, and frapmenu would just handle
>> knowing what files/directories need to be watched, and provide some
>> kind of function like
>>
>> frap_menu_monitor_notify_change(FrapMenu *menu,
>>                                 const gchar *path);
>>
>> or whatever so the monitor implementation can tell FrapMenu that
>> something changed.  That way you're not forcing dependence on any
>> particular file monitoring system, and users could just not make use
>> of it if they didn't want to.
>>
>> Barring this approach, it would be nice to have the FrapMenu be able
>> to emit some kind of "contents-changed" signal so I could know when
>> to regenerate particular menus.  Since overall menu generation is
>> pretty fast, maybe it makes more sense complexity-wise just to
>> regenerate the entire menu from the root any time anything changes.
>> I dunno.
>>
>> Anyway, there's probably more to it; just an idea to get the ball
>> rolling.  Let me know how it turns out ^_^.
>
>I really like this idea. xfdesktop and Thunar will be the most
>important FrapMenu users and both already use thunar-vfs which includes
>monitoring support. This would make integrating FrapMenu pretty easy -
>and would save me a lot of time, hehe.

Also it avoids a circular dependency if you wanted to use thunar-vfs,
since it's possible thunar proper would want to use the menu, but since
thunar-vfs is in the same tarball, it would need to be built before the
menu... and after the menu... argh.  This way FrapMenu doesn't actually
depend on *anything* extra.

>Would it be ok to call the cancel_monitor function in
>frap_menu_item_finalize and frap_menu_finalize? Because this is the
>best solution at my end.

I don't see why not; that sounds ok to me.

BTW, how were you planning on doing the signals?  Based on how I think
xfdesktop might use this, I'd want to know the following things:

1.  When a new FrapMenuItem, FrapMenu, or FrapMenuSeparator gets added
to an existing FrapMenu.

2.  When a FMItem, FMenu, or FMSeparator gets removed from an existing
FMenu.  So the same as #1, just the reverse.

3.  When an existing FrapMenu{,Item} is changed somehow (name, icon
name, command, etc.). (Presumably, separators don't get changed; just
added or removed.)  So:

4.  When the root of the menu is destroyed.  Is this necessary?  Say the
user deletes all .menu files?  Eh, maybe not useful.

struct _FrapMenuClass
{
    /* ... */

    void (*item_added)(FrapMenu *menu, FrapMenuItem *item);
    void (*submenu_added)(FrapMenu *menu, FrapMenu *submenu);
    void (*separator_added)(FrapMenu *menu,
                            FrapMenuSeparator *separator);

    void (*item_removed)(FrapMenu *menu, FrapMenuItem *item);
    void (*submenu_removed)(FrapMenu *menu, FrapMenu *submenu);
    void (*separator_removed)(FrapMenu *menu,
                              FrapMenuSeparator *separator);

    void (*changed)(FrapMenu *menu);

    /* useful? */
    void (*destroyed)(FrapMenu *menu);
};

struct _FrapMenuItemClass
{
    /* ... */

    void (*changed)(FrapMenuItem *item);
};

So we're talking 8 signals - does that make sense?  If you wanted to
mess around with your class hierarchy, and add something like
'FrapMenuElement', of which FrapMenu, FrapMenuItem, and
FrapMenuSeparator are subclasses, then you could replace all the
*-added and *-removed signals with 'element-added' and 'element-removed'
signals, and it would be up to the receiver of the signal to do:

void
my_frap_menu_element_added(FrapMenu *menu,
                           FrapMenuElement *element,
                           gpointer user_data)
{
    if(FRAP_IS_MENU(element)) {

    } else if(FRAP_IS_MENU_ITEM(element)) {

    } else if(FRAP_IS_MENU_SEPARATOR(element)) {

    }
}

in the signal handler.  Going this route, you could move a lot of the
common functions (e.g., frap_menu_get_name(),
frap_menu_item_get_name(), etc.) into FrapMenuElement.  Anyway, just an
idea - not sure if it's really worth it or makes all that much sense.

	-brian




More information about the Xfce4-dev mailing list