GNOME Goal: Applets Dbus Migration

Introduccion

Gnome Panel drop the libbonobo dependency recently (see bug #572131). The objective of this GnomeGoal is to port all Gnome applets to the new DBUS api.

Guidelines

Application code

  • libpanel-applet now uses GTK+3 so the first thing you need to do is porting your applet to GTK+3.
  • Factory macro: change PANEL_APPLET_BONOBO_FACTORY with PANEL_APPLET_OUT_PROCESS_FACTORY. New macro has the same parameters except version that has been removed. Remove the prefix 'OAFIID:GNOME_' from the factory name. See the example:

Old macro:

PANEL_APPLET_BONOBO_FACTORY ("OAFIID:GNOME_Wncklet_Factory",
                             PANEL_TYPE_APPLET,
                             "WindowNavigationApplets",
                             "0",
                             wncklet_factory,
                             NULL)

The new version of the macro should be:

PANEL_APPLET_OUT_PROCESS_FACTORY ("WnckletFactory",
                                  PANEL_TYPE_APPLET,
                                  wncklet_factory,
                                  NULL)
  • Remove the prefix 'OAFIID:GNOME_' from the factory method too:

Old factory method:

static gboolean
wncklet_factory (PanelApplet *applet,
                 const char  *iid,
                 gpointer     data)
{
        gboolean retval = FALSE;
        static gboolean type_registered = FALSE;

        if (!type_registered) {
                wnck_set_client_type (WNCK_CLIENT_TYPE_PAGER);
                type_registered = TRUE;
        }

        if (!strcmp (iid, "OAFIID:GNOME_WindowMenuApplet"))
                retval = window_menu_applet_fill (applet);

        else if (!strcmp (iid, "OAFIID:GNOME_WorkspaceSwitcherApplet")||
                 !strcmp (iid, "OAFIID:GNOME_PagerApplet"))
                retval = workspace_switcher_applet_fill (applet);

        else if (!strcmp (iid, "OAFIID:GNOME_WindowListApplet") ||
                 !strcmp (iid, "OAFIID:GNOME_TasklistApplet"))
                retval = window_list_applet_fill (applet);

        else if (!strcmp (iid, "OAFIID:GNOME_ShowDesktopApplet"))
                retval = show_desktop_applet_fill (applet);

        return retval;
}

The new one it's the same without the 'OAFIID:GNOME_' prefix

static gboolean 
wncklet_factory (PanelApplet *applet,
                 const char  *iid,
                 gpointer     data)
{
        gboolean retval = FALSE;
        static gboolean type_registered = FALSE;

        if (!type_registered) {
                wnck_set_client_type (WNCK_CLIENT_TYPE_PAGER);
                type_registered = TRUE;
        }

        if (!strcmp (iid, "WindowMenuApplet"))
                retval = window_menu_applet_fill (applet);

        else if (!strcmp (iid, "WorkspaceSwitcherApplet")||
                 !strcmp (iid, "PagerApplet"))
                retval = workspace_switcher_applet_fill (applet);

        else if (!strcmp (iid, "WindowListApplet") ||
                 !strcmp (iid, "TasklistApplet"))
                retval = window_list_applet_fill (applet);

        else if (!strcmp (iid, "ShowDesktopApplet"))
                retval = show_desktop_applet_fill (applet);

        return retval;
}
  • Applet menu: the new API uses GtkAction to build the menu, so we need to define GtkActionEntry instead of BonoboUIVerb. See the example:

Old menu verbs definition:

static const BonoboUIVerb show_desktop_menu_verbs [] = {
        BONOBO_UI_UNSAFE_VERB ("ShowDesktopHelp",        display_help_dialog),
        BONOBO_UI_UNSAFE_VERB ("ShowDesktopAbout",       display_about_dialog),
        BONOBO_UI_VERB_END
};

New menu actions definition should be:

static const GtkActionEntry show_desktop_menu_actions [] = {
        { "ShowDesktopHelp", GTK_STOCK_HELP, N_("_Help"),
          NULL, NULL,
          G_CALLBACK (display_help_dialog) },
        { "ShowDesktopAbout", GTK_STOCK_ABOUT, N_("_About"),
          NULL, NULL,
          G_CALLBACK (display_about_dialog) }
};

If you have toggle action you need to define GtkToggleActionEntry actions too:

static const GtkToggleActionEntry toggle_actions[] = {
    { "Mute", NULL, N_("Mu_te"),
      NULL, NULL,
      G_CALLBACK (cb_verb), FALSE }
  };
  • Callbacks should be changed to match the GtkAction callback prototype:

Old callback:

static void
display_help_dialog (BonoboUIComponent *uic,
                     ShowDesktopData   *sdd,
                     const gchar       *verbname)

The new version would be:

static void
display_help_dialog (GtkAction       *action,
                     ShowDesktopData *sdd)
  • To setup the menu we use panel_applet_setup_menu_from_file() which has a new API. It takes the file with the ui definitions and a GtkActionGroup, so we need to build a new action group first:

Old code for setting up the menu:

panel_applet_setup_menu_from_file (PANEL_APPLET (sdd->applet),
                                   NULL,
                                   "GNOME_ShowDesktopApplet.xml",
                                   NULL,
                                   show_desktop_menu_verbs,
                                   sdd);

The new code should be something like:

action_group = gtk_action_group_new ("ShowDesktop Applet Actions");
gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
gtk_action_group_add_actions (action_group,
                              show_desktop_menu_actions,
                              G_N_ELEMENTS (show_desktop_menu_actions),
                              sdd);
ui_path = g_build_filename (WNCK_MENU_UI_DIR, "showdesktop-menu.xml", NULL);
panel_applet_setup_menu_from_file (PANEL_APPLET (sdd->applet),
                                   ui_path, action_group);
g_free (ui_path);
g_object_unref (action_group);

If the applet has toggle actions you have to call gtk_action_group_add_toggle_actions() to add toggle actions to the action group:

gtk_action_group_add_toggle_actions (action_group,
                                       toggle_actions,
                                       G_N_ELEMENTS (toggle_actions),
                                       applet);

If you need to change any property of a menu item, for example when applet is locked down, you can just get the action from the action group:

if (panel_applet_get_locked_down (PANEL_APPLET (tasklist->applet))) {
        GtkAction *action;

        action = gtk_action_group_get_action (action_group, "TasklistPreferences");
        gtk_action_set_visible (action, FALSE);
}

The new menu xml file is a normal GtkUIManager ui file. It should contain just menutiem entries and separators. See the example:

<menuitem name="Mute"     action="Mute" />
<menuitem name="RunMixer" action="RunMixer" />
<separator/>
<menuitem name="Pref"     action="Pref" />
<menuitem name="Help"     action="Help" />
<menuitem name="About"    action="About" />

Panel Applet File

It's a key file with information about the applet. Most of the information can be copied from the old .server.in.in file. It must contain a group called 'Applet Factory' with information about the factory and one group for every applet with the applet identifier as the name of the group.

Applet Factory group keys:

  • Id: it's the name of the factory, it must be the same name used as the first parameter in PANEL_APPLET_OUT_PROCESS_FACTORY macro
  • Location: the path to the applet executable
  • Name: factory name (it can be copy-pasted from the .server.in.in file)
  • Description: factory description (it can be copy-pasted from the .server.in.in file)

Applet groups keys:

  • Name: applet name
  • Description: applet description
  • Icon: applet icon name
  • BonoboId: old bonobo identifier, for compatibility. It allows the panel to load applets using the current configuration. It can be a single string or a list of strings in case of applets with more than one identifier.

  • Bugzilla fields

All of these keys can be copy-pasted from the .server.in.in file. See the example:

org.gnome.panel.Wncklet.panel-applet.in.in

[Applet Factory]
Id=WnckletFactory
Location=@LOCATION@
_Name=Window Navigation Applet Factory
_Description=Factory for the window navigation related applets

[WindowMenuApplet]
_Name=Window Selector
_Description=Switch between open windows using a menu
Icon=gnome-panel-window-menu
BonoboId=OAFIID:GNOME_WindowMenuApplet
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-panel
X-GNOME-Bugzilla-Component=window selector
X-GNOME-Bugzilla-Version=@VERSION@
X-GNOME-Bugzilla-OtherBinaries=wnck-applet

[WorkspaceSwitcherApplet]
_Name=Workspace Switcher
_Description=Switch between workspaces
Icon=gnome-panel-workspace-switcher
BonoboId=OAFIID:GNOME_WorkspaceSwitcherApplet;OAFIID:GNOME_PagerApplet
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-panel
X-GNOME-Bugzilla-Component=workspace switcher
X-GNOME-Bugzilla-Version=@VERSION@
X-GNOME-Bugzilla-OtherBinaries=wnck-applet

[WindowListApplet]
_Name=Window List
_Description=Switch between open windows using buttons
Icon=gnome-panel-window-list
BonoboId=OAFIID:GNOME_TasklistApplet;OAFIID:GNOME_WindowListApplet
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-panel
X-GNOME-Bugzilla-Component=window list
X-GNOME-Bugzilla-Version=@VERSION@
X-GNOME-Bugzilla-OtherBinaries=wnck-applet

[ShowDesktopApplet]
_Name=Show Desktop
_Description=Hide application windows and show the desktop
Icon=user-desktop
BonoboId=OAFIID:GNOME_ShowDesktopApplet
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-panel
X-GNOME-Bugzilla-Component=Show Desktop Button
X-GNOME-Bugzilla-Version=@VERSION@
X-GNOME-Bugzilla-OtherBinaries=wnck-applet

D-Bus service file

In addition to the panel-applet file we use a D-Bus service file so that applets can be started by the session bus. It's a normal D-Bus file

org.gnome.panel.applet.WnckletFactory.service.in

[D-BUS Service]
Name=org.gnome.panel.applet.WnckletFactory
Exec=@LOCATION@

Build system (configure)

  • Check for libpanel-applet-4 in your configure file, and get the directory where .panel-applet files should go from the pkg-config file, with something like:

LIBPANEL_APPLET_DIR=`$PKG_CONFIG --variable=libpanel_applet_dir libpanelapplet-4.0`

Build system (Makefile.am)

  • Add the ui xml path to the CFLAGS:

-DWNCK_MENU_UI_DIR=\""$(xmluidir)"\" \

This is the macro you use when setting up the applet menu

  • Panel-applet file:

appletdir       = $(LIBPANEL_APPLET_DIR)
applet_in_files = GNOME_MixerApplet.panel-applet.in
applet_DATA     = $(applet_in_files:.panel-applet.in=.panel-applet)

$(applet_in_files): $(applet_in_files).in Makefile
        $(AM_V_GEN)sed \                                                                                                                                     
            -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \                                                                                                           
            -e "s|\@VERSION\@|$(PACKAGE_VERSION)|" \                                                                                                         
            $< > $@

%.panel-applet: %.panel-applet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache

This rule should probably be moved to intltool as something like:

INTLTOOL_PANEL_APPLET_RULE='%.panel-applet: %.panel-applet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(AM_V_GEN) LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
  • D-Bus service file:

servicedir       = $(datadir)/dbus-1/services
service_in_files = org.gnome.panel.applet.FishAppletFactory.service.in
service_DATA     = $(service_in_files:.service.in=.service)

org.gnome.panel.applet.FishAppletFactory.service: $(service_in_files)
        $(AM_V_GEN)sed \
            -e "s|\@LOCATION\@|$(APPLET_LOCATION)|" \
            $< > $@
  • Add panel-applet .in.in and service file to EXTRA_DIST and $(applet_DATA) $(applet_DATA).in to CLEANFILES

EXTRA_DIST =                                            \
        GNOME_MixerApplet.panel-applet.in.in            \
        $(service_in_files)                             \
        $(ui_DATA)                                      \
        $(schemas_in_files)
CLEANFILES = $(applet_DATA) $(applet_DATA).in $(service_DATA) $(schemas_DATA)
  • Remove all references to bonobo, orbit, etc, from configure script. Remove references to .server files and INTLTOOL_SERVER_RULE from Makefile.am and remove .server.in.in file.

Comments before approval

{i} Add your comments to this goal proposal here

Status of this goal

{i} Tip: If you choose to work on a module, create the bug report on the GNOME bugzilla for the relevant module, and make it block bug 620830. This way people will know someone already works on it, and won't duplicate the work you're doing.

State

Markup

todo

<: #ff8080> todo

patch

<: #ffcc50> [[GnomeBug:xxxxx|patch]]

done

<: #80ff80> [[GnomeBug:xxxxx|done]]

not needed

<: #80ff80> not needed

Above are the states and corresponding markup to update the modules state table below.

Tarball

Status

Desktop

bug-buddy

to do

gdm

done

gnome-applets

done

gnome-control-center

to do

gnome-netstatus

to do

gnome-panel

done

gnome-power-manager

done and done

gnome-python-desktop

not needed

gnome-utils

to do

mousetweaks

done

seahorse-plugins

done

tomboy

to do

vinagre

to do

Admin

pessulus

to do

sabayon

to do

Development Tools

glade3

to do

Bindings (python)

gnome-python

to do

Bindings (mono)

gnome-sharp

to do

External Dependencies

tracker

done

Other

apt-watch-gnome

to do

balsa

to do

byzanz

done

bubblemon

to do

fast-user-switch-applet

to do

gnote-main-menu

to do

gnome-pilot

done

gnote

to do

netspeed

patch

OnTV

to do

pnee

to do

sensors-applet

done

workrave

to do

Initiatives/GnomeGoals/AppletsDbusMigration (last edited 2013-12-18 13:44:47 by LuisMenina)