summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Ruiz <alberto.ruiz@codethink.co.uk>2011-03-31 19:49:02 +0200
committerBjoern Michaelsen <bjoern.michaelsen@canonical.com>2011-03-31 21:05:22 +0200
commitec176090c881c6d6b85606c6711ed621c5af7531 (patch)
treee1f158b151746f207c59c2939e898b1c625af407
parent9d306a777bbd79169bd61108ab89a097223ce9b8 (diff)
initial import of lomenubar
* from http://bazaar.launchpad.net/~lo-menubar-team/lo-menubar/trunk/changes * fixed indent to keep git hooks happy, otherwise a vanilla copy
-rw-r--r--framework/source/lomenubar/AwtKeyToDbusmenuString.cxx145
-rw-r--r--framework/source/lomenubar/AwtKeyToDbusmenuString.h33
-rw-r--r--framework/source/lomenubar/DesktopJob.cxx157
-rw-r--r--framework/source/lomenubar/DesktopJob.h90
-rw-r--r--framework/source/lomenubar/FrameHelper.cxx826
-rw-r--r--framework/source/lomenubar/FrameHelper.h139
-rw-r--r--framework/source/lomenubar/FrameJob.cxx393
-rw-r--r--framework/source/lomenubar/FrameJob.h101
-rw-r--r--framework/source/lomenubar/MenuItemInfo.cxx103
-rw-r--r--framework/source/lomenubar/MenuItemInfo.h54
-rw-r--r--framework/source/lomenubar/MenuItemStatusListener.cxx82
-rw-r--r--framework/source/lomenubar/MenuItemStatusListener.h35
-rw-r--r--framework/source/lomenubar/exports.cxx119
13 files changed, 2277 insertions, 0 deletions
diff --git a/framework/source/lomenubar/AwtKeyToDbusmenuString.cxx b/framework/source/lomenubar/AwtKeyToDbusmenuString.cxx
new file mode 100644
index 0000000000..4fd377db75
--- /dev/null
+++ b/framework/source/lomenubar/AwtKeyToDbusmenuString.cxx
@@ -0,0 +1,145 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#define XK_MISCELLANY
+#define XK_LATIN1
+#define XK_PUBLISHING
+
+#include <X11/Xlib.h>
+#include <X11/keysymdef.h>
+
+#include <glib.h>
+
+#include <com/sun/star/awt/Key.hpp>
+
+using namespace ::com::sun::star;
+
+KeySym MapAwtToXKey (guint16 aKeyCode);
+
+gchar*
+AwtKeyToDbusmenuString (guint16 aKeyCode)
+{
+ KeySym code = (KeySym)0;
+
+ if (!aKeyCode)
+ return NULL;
+
+ //We try the consecutive ranges first, if the code is not there
+ //we use MapAwtToXKey(), se below
+ if (aKeyCode >= awt::Key::A && aKeyCode <= awt::Key::Z)
+ code = (KeySym)aKeyCode - (KeySym)awt::Key::A + XK_A;
+ else if (aKeyCode >= awt::Key::F1 && aKeyCode <= awt::Key::F26)
+ code = (KeySym)aKeyCode - (KeySym)awt::Key::F1 + XK_F1;
+ else if (aKeyCode >= awt::Key::NUM0 && aKeyCode <= awt::Key::NUM9)
+ code = (KeySym)aKeyCode - (KeySym)awt::Key::NUM0 + XK_0;
+ else
+ code = MapAwtToXKey (aKeyCode);
+
+ if (code == 0)
+ return NULL;
+
+ return XKeysymToString (code);;
+}
+
+
+//This is a 1-1 mapper between com::sun::star::awt:Key values and X11 KeySyms
+//note that some symbols are missing
+KeySym
+MapAwtToXKey (guint16 aKeyCode)
+{
+ switch (aKeyCode)
+ {
+ case awt::Key::UP:
+ return XK_Up;
+ case awt::Key::DOWN:
+ return XK_Down;
+ case awt::Key::LEFT:
+ return XK_Left;
+ case awt::Key::RIGHT:
+ return XK_Right;
+ case awt::Key::HOME:
+ return XK_Home;
+ case awt::Key::END:
+ return XK_End;
+ case awt::Key::PAGEUP:
+ return XK_Page_Up;
+ case awt::Key::PAGEDOWN:
+ return XK_Page_Down;
+ case awt::Key::RETURN:
+ return XK_Return;
+ case awt::Key::ESCAPE:
+ return XK_Escape;
+ case awt::Key::TAB:
+ return XK_Tab;
+ case awt::Key::BACKSPACE:
+ return XK_BackSpace;
+ case awt::Key::SPACE:
+ return XK_space;
+ case awt::Key::INSERT:
+ return XK_Insert;
+ case awt::Key::DELETE:
+ return XK_Delete;
+ case awt::Key::ADD:
+ return XK_plus;
+ case awt::Key::SUBTRACT:
+ return XK_minus;
+ case awt::Key::MULTIPLY:
+ return XK_asterisk;
+ case awt::Key::DIVIDE:
+ return XK_slash;
+ case awt::Key::POINT:
+ return XK_period;
+ case awt::Key::COMMA:
+ return XK_comma;
+ case awt::Key::LESS:
+ return XK_less;
+ case awt::Key::GREATER:
+ return XK_greater;
+ case awt::Key::EQUAL:
+ return XK_equal;
+ case awt::Key::UNDO:
+ return XK_Undo;
+ case awt::Key::REPEAT:
+ return XK_Redo;
+ case awt::Key::FIND:
+ return XK_Find;
+ case awt::Key::DECIMAL:
+ return XK_decimalpoint;
+ case awt::Key::TILDE:
+ return XK_asciitilde;
+ case awt::Key::QUOTELEFT:
+ return XK_leftsinglequotemark;
+ //Sun keys and other unsupported symbols
+ case awt::Key::OPEN:
+ case awt::Key::CUT:
+ case awt::Key::COPY:
+ case awt::Key::PASTE:
+ case awt::Key::PROPERTIES:
+ case awt::Key::FRONT:
+ case awt::Key::CONTEXTMENU:
+ case awt::Key::HELP:
+ case awt::Key::MENU:
+ default:
+ return 0;
+ }
+}
diff --git a/framework/source/lomenubar/AwtKeyToDbusmenuString.h b/framework/source/lomenubar/AwtKeyToDbusmenuString.h
new file mode 100644
index 0000000000..acedc908ac
--- /dev/null
+++ b/framework/source/lomenubar/AwtKeyToDbusmenuString.h
@@ -0,0 +1,33 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef __AWT_KEY_TO_DBUSMENU_STRING_H__
+#define __AWT_KEY_TO_DBUSMENU_STRING_H__
+#include <X11/X.h>
+#include <glib.h>
+
+gchar*
+AwtKeyToDbusmenuString (guint16 aKeyCode);
+
+
+#endif //__AWT_KEY_TO_DBUSMENU_STRING_H__
diff --git a/framework/source/lomenubar/DesktopJob.cxx b/framework/source/lomenubar/DesktopJob.cxx
new file mode 100644
index 0000000000..1ac56c2f5a
--- /dev/null
+++ b/framework/source/lomenubar/DesktopJob.cxx
@@ -0,0 +1,157 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "DesktopJob.h"
+#include "FrameJob.h"
+
+#include <gio/gio.h>
+#include <libdbusmenu-glib/server.h>
+
+#include <rtl/process.h>
+#include <osl/diagnose.h>
+#include <cppuhelper/implbase1.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XEventBroadcaster.hpp>
+#include <com/sun/star/document/XEventListener.hpp>
+#include <com/sun/star/document/EventObject.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
+#include <com/sun/star/frame/XFrameActionListener.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+
+using rtl::OUString;
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::beans::NamedValue;
+using com::sun::star::document::XEventListener;
+using com::sun::star::document::XEventBroadcaster;
+using com::sun::star::frame::XFrame;
+using com::sun::star::frame::XFramesSupplier;
+using com::sun::star::frame::XFrameActionListener;
+using com::sun::star::frame::XModel;
+using com::sun::star::frame::XLayoutManager;
+using com::sun::star::frame::FrameActionEvent;
+using com::sun::star::frame::XFrameActionListener;
+using com::sun::star::lang::IllegalArgumentException;
+using com::sun::star::lang::XMultiServiceFactory;
+using com::sun::star::lang::EventObject;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Exception;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::RuntimeException;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::UNO_QUERY_THROW;
+using com::sun::star::uno::XInterface;
+
+//-------------------------- D-Bus Callbacks ----------------------------------
+static void
+on_bus (GDBusConnection * connection,
+ const gchar * name,
+ gpointer user_data)
+{
+ //TODO: Should we actually do something here?
+ return;
+}
+
+static void
+name_lost (GDBusConnection * connection, const gchar * name, gpointer user_data)
+{
+ g_error ("Unable to get name '%s' on DBus", name);
+ return;
+}
+
+// --------------------------- DesktopJob ----------------------------------
+Any SAL_CALL DesktopJob::execute( const Sequence< NamedValue >& aArguments )
+ throw ( IllegalArgumentException, Exception, RuntimeException )
+{
+ g_type_init ();
+
+ g_bus_own_name(G_BUS_TYPE_SESSION,
+ LIBREOFFICE_BUSNAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus,
+ NULL,
+ name_lost,
+ NULL,
+ NULL);
+
+ return Any ();
+}
+
+OUString
+DesktopJob_getImplementationName ()
+ throw (RuntimeException)
+{
+ return OUString ( RTL_CONSTASCII_USTRINGPARAM ( DESKTOPJOB_IMPLEMENTATION_NAME ) );
+}
+
+sal_Bool SAL_CALL
+DesktopJob_supportsService( const OUString& ServiceName )
+ throw (RuntimeException)
+{
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( DESKTOPJOB_SERVICE_NAME ) );
+}
+
+Sequence< OUString > SAL_CALL
+DesktopJob_getSupportedServiceNames( )
+ throw (RuntimeException)
+{
+ Sequence < OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( DESKTOPJOB_SERVICE_NAME ) );
+ return aRet;
+}
+
+Reference< XInterface > SAL_CALL
+DesktopJob_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
+ throw( Exception )
+{
+ return (cppu::OWeakObject*) new DesktopJob(rSMgr);
+}
+
+// XServiceInfo
+OUString SAL_CALL
+DesktopJob::getImplementationName()
+ throw (RuntimeException)
+{
+ return DesktopJob_getImplementationName();
+}
+
+sal_Bool SAL_CALL
+DesktopJob::supportsService( const OUString& rServiceName )
+ throw (RuntimeException)
+{
+ return DesktopJob_supportsService( rServiceName );
+}
+
+Sequence< OUString > SAL_CALL
+DesktopJob::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ return DesktopJob_getSupportedServiceNames();
+}
diff --git a/framework/source/lomenubar/DesktopJob.h b/framework/source/lomenubar/DesktopJob.h
new file mode 100644
index 0000000000..9dd3024a05
--- /dev/null
+++ b/framework/source/lomenubar/DesktopJob.h
@@ -0,0 +1,90 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef __DESKTOP_JOB_H__
+#define __DESKTOP_JOB_H__
+
+#include <glib.h>
+#include <libdbusmenu-glib/menuitem.h>
+
+#include <com/sun/star/task/XJob.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase2.hxx>
+
+#define LIBREOFFICE_BUSNAME "org.libreoffice.dbusmenu"
+#define DESKTOPJOB_IMPLEMENTATION_NAME "org.libreoffice.desktop.AppMenuJob"
+#define DESKTOPJOB_SERVICE_NAME "org.libreoffice.desktop.AppMenuJob"
+
+namespace css = ::com::sun::star;
+using css::uno::Reference;
+using css::uno::Sequence;
+using css::uno::Any;
+using css::uno::Exception;
+using css::uno::RuntimeException;
+using css::lang::IllegalArgumentException;
+
+class DesktopJob : public cppu::WeakImplHelper2 < css::task::XJob, css::lang::XServiceInfo >
+{
+ private:
+ Reference< css::lang::XMultiServiceFactory > mxMSF;
+
+ public:
+ DesktopJob( const Reference< css::lang::XMultiServiceFactory > &rxMSF)
+ : mxMSF( rxMSF ) {}
+
+ virtual ~DesktopJob() {}
+
+ // XJob
+ virtual Any SAL_CALL execute(const css::uno::Sequence< css::beans::NamedValue >& Arguments)
+ throw (IllegalArgumentException, Exception, RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName()
+ throw (RuntimeException);
+
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
+ throw (RuntimeException);
+
+ virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
+ throw (RuntimeException);
+};
+
+
+::rtl::OUString
+DesktopJob_getImplementationName()
+ throw ( RuntimeException );
+
+sal_Bool SAL_CALL
+DesktopJob_supportsService( const ::rtl::OUString& ServiceName )
+ throw ( RuntimeException );
+
+Sequence< ::rtl::OUString > SAL_CALL
+DesktopJob_getSupportedServiceNames()
+ throw ( RuntimeException );
+
+Reference< css::uno::XInterface >
+SAL_CALL DesktopJob_createInstance( const css::uno::Reference< css::lang::XMultiServiceFactory > & rSMgr)
+ throw ( Exception );
+
+#endif //__DESKTOP_JOB_H__
+
diff --git a/framework/source/lomenubar/FrameHelper.cxx b/framework/source/lomenubar/FrameHelper.cxx
new file mode 100644
index 0000000000..4c4550e3dd
--- /dev/null
+++ b/framework/source/lomenubar/FrameHelper.cxx
@@ -0,0 +1,826 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "FrameHelper.h"
+#include "AwtKeyToDbusmenuString.h"
+#include "MenuItemInfo.h"
+#include "MenuItemStatusListener.h"
+
+#include <com/sun/star/awt/KeyEvent.hpp>
+#include <com/sun/star/awt/SystemDependentXWindow.hpp>
+#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/awt/Key.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/awt/MenuEvent.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/awt/XPopupMenu.hpp>
+#include <com/sun/star/awt/XMenuExtended.hpp>
+#include <com/sun/star/awt/XMenuListener.hpp>
+#include <com/sun/star/awt/XPopupMenuExtended.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XDispatchHelper.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XModuleManager.hpp>
+#include <com/sun/star/frame/XPopupMenuController.hpp>
+#include <com/sun/star/frame/FrameAction.hpp>
+#include <com/sun/star/frame/FrameActionEvent.hpp>
+#include <com/sun/star/lang/SystemDependent.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/ui/XUIElement.hpp>
+#include <com/sun/star/ui/XUIConfigurationManager.hpp>
+#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/ui/XAcceleratorConfiguration.hpp>
+#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
+#include <rtl/process.h>
+
+#include <gio/gio.h>
+#include <libdbusmenu-glib/client.h>
+#include <libdbusmenu-gtk/menuitem.h>
+
+using rtl::OUString;
+using rtl::OString;
+using rtl::OUStringToOString;
+
+using namespace ::com::sun::star;
+
+using com::sun::star::awt::KeyEvent;
+using com::sun::star::awt::MenuEvent;
+using com::sun::star::awt::SystemDependentXWindow;
+using com::sun::star::awt::XMenuListener;
+using com::sun::star::awt::XMenuExtended;
+using com::sun::star::awt::XMenuListener;
+using com::sun::star::awt::MenuEvent;
+using com::sun::star::awt::XPopupMenu;
+using com::sun::star::awt::XPopupMenuExtended;
+using com::sun::star::awt::XSystemDependentWindowPeer;
+using com::sun::star::awt::XWindow2;
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::beans::PropertyValue;
+using com::sun::star::container::XNameAccess;
+using com::sun::star::container::NoSuchElementException;
+using com::sun::star::frame::XController;
+using com::sun::star::frame::XComponentLoader;
+using com::sun::star::frame::XDispatch;
+using com::sun::star::frame::XDispatchProvider;
+using com::sun::star::frame::XDispatchHelper;
+using com::sun::star::frame::XModel;
+using com::sun::star::frame::XModuleManager;
+using com::sun::star::frame::XLayoutManager;
+using com::sun::star::frame::XPopupMenuController;
+using com::sun::star::lang::SystemDependent::SYSTEM_XWINDOW;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::UNO_QUERY_THROW;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::uno::XInterface;
+using com::sun::star::ui::XUIElement;
+using com::sun::star::ui::XUIConfigurationManager;
+using com::sun::star::ui::XUIConfigurationManagerSupplier;
+using com::sun::star::ui::XAcceleratorConfiguration;
+using com::sun::star::ui::XModuleUIConfigurationManagerSupplier;
+using com::sun::star::util::URL;
+using com::sun::star::util::XURLTransformer;
+
+// ------------------------ Item callbacks ---------------------------
+// Item activated. It distpatches the command associated to a given menu item.
+void
+item_activated (DbusmenuMenuitem *item, guint timestamp, gpointer user_data)
+{
+ FrameHelper *helper = (FrameHelper*)user_data;
+ OUString command = OUString::createFromAscii(dbusmenu_menuitem_property_get (item, "CommandURL"));
+ helper->dispatchCommand (command);
+}
+
+// Rebuilds the submenu
+gboolean
+item_about_to_show (DbusmenuMenuitem *item, gpointer user_data)
+{
+ //Get the XMenu interface for the MenuBar UIElement
+ FrameHelper *helper = (FrameHelper*)user_data;
+ Reference < XFrame > xFrame = helper->getFrame ();
+ Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
+ Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString::createFromAscii("LayoutManager")),
+ UNO_QUERY);
+ Reference < XUIElement > menuBar(xLayoutManager->getElement (OUString::createFromAscii("private:resource/menubar/menubar")),
+ UNO_QUERY);
+ Reference < XPropertySet > menuPropSet (menuBar, UNO_QUERY);
+
+ if (!menuPropSet.is ())
+ {
+ return FALSE;
+ }
+
+ Reference < XMenu > xMenu(menuPropSet->getPropertyValue(OUString::createFromAscii("XMenuBar")),
+ UNO_QUERY);
+ if (!xMenu.is())
+ {
+ return FALSE;
+ }
+
+ //Find xMenu for the first level item
+ Reference < XMenu > xSubMenu;
+ Reference < XMenuExtended > xMenuEx (xMenu, UNO_QUERY);
+ guint16 root_count = xMenu->getItemCount();
+ for (guint16 i = 0; i<root_count ;i++)
+ {
+
+ guint16 id = xMenu->getItemId (i);
+ if (id == 0)
+ continue;
+
+ OUString command = xMenuEx->getCommand (id);
+
+ //We must find the element with the same command URL
+ if (! OUString::createFromAscii (dbusmenu_menuitem_property_get (item, "CommandURL")).equals (command))
+ continue;
+
+ Reference <XPopupMenu> subPopup (xMenu->getPopupMenu (id), UNO_QUERY);
+ xSubMenu = Reference <XMenu> (subPopup, UNO_QUERY);
+ break;
+ }
+
+ //We only do this for toplevel items
+ if (xSubMenu.is ())
+ {
+ helper->rebuildMenu (xSubMenu, item);
+ return FALSE;
+ }
+
+ //If it is not a toplevel item we stop trying to rebuild
+ return TRUE;
+}
+
+void
+destroy_menuitem (gpointer data)
+{
+ g_object_unref (G_OBJECT (data));
+}
+
+void
+destroy_menu_item_info (gpointer data)
+{
+ delete (MenuItemInfo*)data;
+}
+
+// ------------------------ FrameHelper Class -------------------------------
+FrameHelper::FrameHelper(const Reference< XMultiServiceFactory >& rServiceManager,
+ const Reference< XFrame >& xFrame,
+ DbusmenuServer* server)
+{
+ xMSF = rServiceManager;
+ this->xFrame = xFrame;
+ this->server = server;
+
+ //Get xUICommands database (to retrieve labels, see FrameJob::getLabelFromCommandURL ())
+ Reference < XNameAccess > xNameAccess (xMSF->createInstance(OUString::createFromAscii("com.sun.star.frame.UICommandDescription")),
+ UNO_QUERY);
+ xMM = Reference < XModuleManager> (xMSF->createInstance(OUString::createFromAscii("com.sun.star.frame.ModuleManager")),
+ UNO_QUERY);
+ xNameAccess->getByName(xMM->identify(xFrame)) >>= xUICommands;
+
+ xdp = Reference < XDispatchProvider > (xFrame, UNO_QUERY);
+ xTrans = Reference < XURLTransformer > (xMSF->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY);
+
+ xSL = (XStatusListener*)new MenuItemStatusListener (this);
+
+ // This initializes the shortcut database
+ getAcceleratorConfigurations (xFrame->getController()->getModel (), xMM);
+
+ // This information is needed for the dynamic submenus
+ xPCF = Reference < XMultiComponentFactory > (xMSF->createInstance(OUString::createFromAscii("com.sun.star.frame.PopupMenuControllerFactory")),
+ UNO_QUERY);
+
+
+ // This is a hash table that maps Command URLs to MenuItemInfo classes
+ // to cache command information
+ commandsInfo = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ destroy_menu_item_info);
+
+ // These are the arguments needed for the XPopupMenuController
+ args = Sequence < Any > (2);
+ PropertyValue item;
+
+ item.Name = OUString::createFromAscii("ModuleName");
+ item.Value <<= xMM->identify (xFrame);
+ args[0] <<= item;
+
+ item.Name = OUString::createFromAscii("Frame");
+ item.Value <<= xFrame;
+ args[1] <<= item;
+
+ root = NULL;
+ watcher_set = FALSE;
+
+ //This variable prevents the helper from being disconnected from the frame
+ //for special cases of component dettaching like print preview
+ blockDetach = FALSE;
+}
+
+void SAL_CALL
+FrameHelper::disposing (const EventObject& aEvent) throw (RuntimeException)
+{}
+
+FrameHelper::~FrameHelper()
+{
+ if (server)
+ g_object_unref (server);
+
+ if (watcher_set)
+ g_bus_unwatch_name (watcher);
+
+ g_hash_table_destroy (commandsInfo);
+}
+
+void
+FrameHelper::setRootItem (DbusmenuMenuitem *root)
+{
+ this->root = root;
+}
+
+void
+FrameHelper::setRegistrarWatcher (guint watcher)
+{
+ watcher_set = TRUE;
+ this->watcher = watcher;
+}
+
+void
+FrameHelper::setServer (DbusmenuServer *server)
+{
+ this->server = server;
+}
+
+//Getters
+Reference < XFrame >
+FrameHelper::getFrame ()
+{
+ return xFrame;
+}
+
+XStatusListener*
+FrameHelper::getStatusListener ()
+{
+ return xSL;
+}
+
+GHashTable*
+FrameHelper::getCommandsInfo ()
+{
+ return commandsInfo;
+}
+
+unsigned long
+FrameHelper::getXID ()
+{
+ Reference< XSystemDependentWindowPeer > xWin( xFrame->getContainerWindow(), UNO_QUERY );
+
+ if (!xWin.is())
+ return 0;
+
+ sal_Int8 processID[16];
+ rtl_getGlobalProcessId( (sal_uInt8*)processID );
+ Sequence <signed char> pidSeq (processID, 16);
+
+ SystemDependentXWindow xWindow;
+ xWin->getWindowHandle (pidSeq, SYSTEM_XWINDOW) >>= xWindow;
+
+ return xWindow.WindowHandle;
+}
+
+void SAL_CALL
+FrameHelper::frameAction(const FrameActionEvent& action) throw (RuntimeException)
+{
+ //If theh component is detached from the frame, remove this action listener,
+ //it is then disposed and destroyed by the frame. We deregister the window
+ //from the AppMenu Registrar
+
+ //This is a special case, .uno:printPreview detaches the component but we are
+ //not actually switching to another document.
+ if (blockDetach)
+ {
+ blockDetach = TRUE;
+ return;
+ }
+
+ if (action.Action == frame::FrameAction_COMPONENT_DETACHING)
+ {
+ GError *error = NULL;
+
+
+ xFrame->removeFrameActionListener (this);
+ Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
+ Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString::createFromAscii("LayoutManager")),
+ UNO_QUERY);
+ xLayoutManager->showElement (OUString::createFromAscii("private:resource/menubar/menubar"));
+
+ unsigned long xid = getXID();
+
+ GDBusProxy *proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "com.canonical.AppMenu.Registrar",
+ "/com/canonical/AppMenu/Registrar",
+ "com.canonical.AppMenu.Registrar",
+ NULL,
+ &error);
+ if (error)
+ {
+ g_warning ("Couldn't get /com/canonical/AppMenu/Registrar proxy");
+ g_error_free (error);
+ return;
+ }
+
+ //TODO: Check if window is registered already
+ g_dbus_proxy_call_sync (proxy,
+ "UnregisterWindow",
+ g_variant_new ("(u)", (guint32)xid),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (error)
+ {
+ g_warning ("Couldn't call /com/canonical/AppMenu/Registrar.UnregisterWindow");
+ g_error_free (error);
+ }
+
+ if (server)
+ {
+ g_object_unref (server);
+ server = NULL;
+ root = NULL;
+ }
+
+ if (watcher_set)
+ {
+ g_bus_unwatch_name (watcher);
+ watcher_set = FALSE;
+ }
+
+ return;
+ }
+}
+
+//This function rebuilds (or builds from scratch) a DbusmenuMenuitem structure
+//from a given pair of XMenu/Dbusmenuitem.
+void
+FrameHelper::rebuildMenu (Reference < XMenu > xMenu,
+ DbusmenuMenuitem *parent)
+{
+ g_return_if_fail (parent != NULL);
+ GList *items = dbusmenu_menuitem_get_children (parent);
+ guint nitems = g_list_length (items); //number of available Dbusmenuitems
+ guint16 count = xMenu->getItemCount (); //number of real menu items
+
+ // One item does not represent always the same command.
+ // We do this for performance reasons, as it's really hard to match a command with
+ // a single dbusmenuitem given the lack of information provided by the status listener
+ if (count > nitems)
+ {
+ // Add enough Dbusmenuitems to replicate all
+ for (guint16 i = 0; i < (count - nitems); i++)
+ {
+ DbusmenuMenuitem *item = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_child_append (parent, item);
+ g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(item_activated), this);
+ }
+ items = dbusmenu_menuitem_get_children (parent);
+ }
+ if (count < nitems)
+ {
+ // If there is an excess of Dbusmenuitems we make them invisible
+ for (guint16 i = nitems - 1; i >= count; i--)
+ {
+ DbusmenuMenuitem *item = DBUSMENU_MENUITEM (g_list_nth_data(items, i));
+ dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
+ }
+ }
+
+ for (guint16 i = 0; i<count; i++)
+ {
+ Reference < XMenuExtended > xMenuEx (xMenu, UNO_QUERY);
+ guint16 id = xMenu->getItemId (i);
+ OUString oUCommand = xMenuEx->getCommand (id);
+ OString command = OUStringToOString (oUCommand, RTL_TEXTENCODING_ASCII_US);
+
+ DbusmenuMenuitem *item = DBUSMENU_MENUITEM(g_list_nth_data(items, i));
+
+ if (!item)
+ continue;
+
+ if (!DBUSMENU_IS_MENUITEM (item))
+ continue;
+
+ // We drop the WindowList, doesn't work properly and it's useless anyhow
+ if (oUCommand.equals (OUString::createFromAscii (".uno:WindowList")))
+ continue;
+
+ //We set the default properties (in case it was not visible or a separator)
+ dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_DEFAULT);
+ dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+
+ if (id == 0)
+ {
+ dbusmenu_menuitem_property_set (item, "CommandURL", "slot:0");
+ dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ //Getting rid of any possible children
+ g_list_free_full (dbusmenu_menuitem_take_children (item), destroy_menuitem);
+ continue;
+ }
+
+ //Setting the command
+ dbusmenu_menuitem_property_set (item, "CommandURL", command.getStr());
+
+ //Getting a shortcut
+ KeyEvent kev = findShortcutForCommand (oUCommand);
+
+ if (kev.KeyCode != 0) //KeyCode must have a value
+ {
+ GVariantBuilder builder;
+ const gchar* keystring = AwtKeyToDbusmenuString(kev.KeyCode);
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+
+ //We map KeyEvent.Modifiers with Dbusmenu modifiers strings
+ if (awt::KeyModifier::SHIFT & kev.Modifiers)
+ g_variant_builder_add(&builder, "s", DBUSMENU_MENUITEM_SHORTCUT_SHIFT);
+ if (awt::KeyModifier::MOD2 & kev.Modifiers)
+ g_variant_builder_add(&builder, "s", DBUSMENU_MENUITEM_SHORTCUT_ALT);
+ if (awt::KeyModifier::MOD1 & kev.Modifiers || awt::KeyModifier::MOD3 & kev.Modifiers)
+ g_variant_builder_add(&builder, "s", DBUSMENU_MENUITEM_SHORTCUT_CONTROL);
+
+ g_variant_builder_add(&builder, "s", keystring);
+
+ GVariant * inside = g_variant_builder_end(&builder);
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_add_value(&builder, inside);
+
+ GVariant * outsidevariant = g_variant_builder_end(&builder);
+ dbusmenu_menuitem_property_set_variant(item, DBUSMENU_MENUITEM_PROP_SHORTCUT, outsidevariant);
+ }
+
+ // Lookup for a MenuItemInfo object for this menuitem, create one if it doesn't exist
+ // this object caches the values that change on status updates.
+ MenuItemInfo* commInfo = (MenuItemInfo*)g_hash_table_lookup (commandsInfo, (gconstpointer)command.getStr());
+ if (!commInfo)
+ {
+ commInfo = new MenuItemInfo ();
+ g_hash_table_insert (commandsInfo, g_strdup (command.getStr()), commInfo);
+
+ OUString oULabel = getLabelFromCommandURL(oUCommand);
+ if (oULabel.getLength() == 0)
+ {
+ oULabel = xMenu->getItemText (id);
+ }
+
+ //Replace tilde with underscore for Dbusmenu Alt accelerators
+ oULabel = oULabel.replace ((sal_Unicode)0x007e, (sal_Unicode)0x005f);
+ // GLib behaves better than OUStringToOString wrt encoding transformation
+ gchar* label = g_utf16_to_utf8 (oULabel.getStr(),
+ oULabel.getLength(),
+ NULL, NULL, NULL);
+ commInfo->setLabel (label);
+ g_free (label);
+ }
+
+ //Update the check state directly from the data, this is more reliable
+ Reference < XPopupMenu > popUp (xMenu, UNO_QUERY);
+ if (popUp.is() && popUp->isItemChecked (id))
+ {
+ commInfo->setCheckState (DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED);
+ }
+
+ dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_LABEL, commInfo->getLabel ());
+ dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, commInfo->getEnabled ());
+
+ //TODO: Find a selection of which commands are radio toggle type
+ if (commInfo->getCheckState () != DBUSMENU_MENUITEM_TOGGLE_STATE_UNKNOWN)
+ {
+ dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, commInfo->getCheckType ());
+ dbusmenu_menuitem_property_set_int (item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, commInfo->getCheckState ());
+ }
+
+ // Adding status listener
+ URL commandURL;
+ commandURL.Complete = oUCommand;
+ xTrans->parseStrict (commandURL);
+
+ Reference < XDispatch > xDispatch = xdp->queryDispatch (commandURL, OUString(), 0);
+ if (xDispatch.is())
+ xDispatch->addStatusListener (xSL, commandURL);
+
+ Reference < XPopupMenu > subPopMenu (xMenu->getPopupMenu (id), UNO_QUERY);
+
+ //Some menus do not provide the information available through the normal XMenu interface,
+ //we need to access that info through a special XPopupMenuController
+ if (isSpecialSubmenu (oUCommand))
+ {
+ Reference < XPropertySet > xMSFProps (xMSF, UNO_QUERY);
+ Reference <XComponentContext> xContext (xMSFProps->getPropertyValue (OUString::createFromAscii ("DefaultContext")),
+ UNO_QUERY);
+
+ Reference < XPopupMenuController > xRFC (xPCF->createInstanceWithArgumentsAndContext(oUCommand,
+ args,
+ xContext),
+ UNO_QUERY);
+
+ Reference < XPopupMenu > xPO (xMSF->createInstance(OUString::createFromAscii ("stardiv.Toolkit.VCLXPopupMenu")),
+ UNO_QUERY);
+
+ if (xRFC.is () && xPO.is ())
+ {
+ xRFC->setPopupMenu (xPO);
+ xRFC->updatePopupMenu ();
+ Reference < XMenu > subMenu (xPO, UNO_QUERY);
+ rebuildMenu (subMenu, item);
+ }
+ else if (subPopMenu.is ())
+ {
+ Reference <XMenu> subMenu (subPopMenu, UNO_QUERY);
+ rebuildMenu (subMenu, item);
+ }
+ }
+
+ // Introspect submenus
+ else if (subPopMenu.is ())
+ {
+ Reference <XMenu> subMenu (subPopMenu, UNO_QUERY);
+ g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, G_CALLBACK(item_about_to_show), this);
+ rebuildMenu (subMenu, item);
+ }
+ else
+ {
+ //Getting rid of any possible children
+ g_list_free_full (dbusmenu_menuitem_take_children (item), destroy_menuitem);
+ }
+ }
+
+ return;
+}
+
+//Gets the menu item Label given a CommandURL
+//This is a work around for bug: https://bugs.freedesktop.org/show_bug.cgi?id=34127
+OUString
+FrameHelper::getLabelFromCommandURL (OUString commandURL)
+{
+ OUString label;
+
+ Sequence < PropertyValue > commandProps;
+
+ if (commandURL.getLength () < 1)
+ return label;
+
+ if (!xUICommands.is())
+ return label;
+
+ try
+ {
+ xUICommands->getByName (commandURL) >>= commandProps;
+ }
+ catch (com::sun::star::container::NoSuchElementException e)
+ {
+ return label;
+ }
+
+ for (sal_Int32 i = 0; i < commandProps.getLength(); i++)
+ {
+ if ( commandProps[i].Name.equalsAsciiL (RTL_CONSTASCII_STRINGPARAM ("Label")))
+ {
+ commandProps[i].Value >>= label;
+ label = label.replace ((sal_Unicode)0x007e, (sal_Unicode)0x005f);
+ //break;
+ }
+ }
+
+ return label;
+}
+
+//This method is a facility to bootstrap the Dbusmenuitem strcuture from the menubar
+void
+FrameHelper::rebuildMenuFromRoot ()
+{
+ Reference < XFrame > xFrame = getFrame ();
+ Reference < XPropertySet > frameProps (xFrame, UNO_QUERY);
+ Reference < XLayoutManager > xLayoutManager (frameProps->getPropertyValue(OUString::createFromAscii("LayoutManager")),
+ UNO_QUERY);
+ Reference < XUIElement > menuBar (xLayoutManager->getElement (OUString::createFromAscii("private:resource/menubar/menubar")),
+ UNO_QUERY);
+ Reference < XPropertySet > menuPropSet (menuBar, UNO_QUERY);
+
+ if (!menuPropSet.is ())
+ return;
+
+ Reference < XMenu > xMenu (menuPropSet->getPropertyValue(OUString::createFromAscii("XMenuBar")),
+ UNO_QUERY);
+ if (!xMenu.is ())
+ return;
+
+ rebuildMenu (xMenu, root);
+}
+
+//Some menus are special, this is the list of them
+gboolean
+FrameHelper::isSpecialSubmenu (OUString command)
+{
+ const gchar * specialSubmenus[11] = {".uno:CharFontName",
+ ".uno:FontHeight",
+ ".uno:ObjectMenue",
+ ".uno:InsertPageHeader",
+ ".uno:InsertPageFooter",
+ ".uno:ChangeControlType",
+ ".uno:AvailableToolbars",
+ ".uno:ScriptOrganizer",
+ ".uno:RecentFileList",
+ ".uno:AddDirect",
+ ".uno:AutoPilotMenu"};
+
+ for (gint i = 0; i < 11; i++)
+ {
+ if (command.equals (OUString::createFromAscii (specialSubmenus[i])))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+FrameHelper::dispatchCommand (OUString command)
+{
+ OUString target = OUString::createFromAscii ("");
+ Reference < XDispatchHelper > xdh (xMSF->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.DispatchHelper"))),
+ UNO_QUERY);
+
+ //g_debug ("%s", OUStringToOString (command, RTL_TEXTENCODING_ASCII_US).getStr());
+
+ // This is a special case, we don't want the helper to be disconnected from the frame
+ // when PrintPreview dettaches. See the frameAction method.
+ if (command.equals (OUString::createFromAscii (".uno:PrintPreview")))
+ {
+ blockDetach = TRUE;
+ }
+
+ // This is a special case for the recentfilelist
+ if (command.matchAsciiL ("vnd.sun.star.popup:RecentFileList", 33, 0))
+ {
+ target = OUString::createFromAscii ("_default");
+
+ Reference < XPropertySet > xMSFProps (xMSF, UNO_QUERY);
+ Reference <XComponentContext> xContext (xMSFProps->getPropertyValue (OUString::createFromAscii ("DefaultContext")),
+ UNO_QUERY);
+ Reference < XPopupMenuController > xRFC (xPCF->createInstanceWithArgumentsAndContext(OUString::createFromAscii (".uno:RecentFileList"),
+ args,
+ xContext),
+ UNO_QUERY);
+ Reference < XMenuListener > xML (xRFC, UNO_QUERY);
+
+ Reference < XPopupMenu > xPO (xMSF->createInstance(OUString::createFromAscii ("stardiv.Toolkit.VCLXPopupMenu")),
+ UNO_QUERY);
+
+ if (xRFC.is () && xPO.is ())
+ {
+ xRFC->setPopupMenu (xPO);
+ xRFC->updatePopupMenu ();
+ Reference < XMenu > subMenu (xPO, UNO_QUERY);
+ Reference < XMenuExtended > subMenuEx (xPO, UNO_QUERY);
+
+ //We need to find the item idd
+ for (int i = 0; i < subMenu->getItemCount (); i++)
+ {
+ int id = subMenu->getItemId (i);
+
+ if (subMenuEx->getCommand (id).equals (command))
+ {
+ MenuEvent mev;
+ mev.MenuId = id;
+
+ xML->select (mev);
+ }
+ }
+ }
+
+ return;
+ }
+
+ if (command.matchAsciiL ("private:factory/", 16, 0))
+ target = OUString::createFromAscii ("_blank");
+
+ xdh->executeDispatch (Reference < XDispatchProvider > (xFrame, UNO_QUERY),
+ command,
+ target,
+ 0,
+ Sequence < PropertyValue > ());
+}
+
+//Set all the accelerator configuration sources
+void
+FrameHelper::getAcceleratorConfigurations (Reference < XModel > xModel,
+ Reference < XModuleManager> xModuleManager)
+{
+ //Get document shortcut database
+ Reference< XUIConfigurationManagerSupplier > docUISupplier(xModel, UNO_QUERY);
+ Reference< XUIConfigurationManager > docUIManager = docUISupplier->getUIConfigurationManager();
+ Reference< XAcceleratorConfiguration > docAccelConf(docUIManager->getShortCutManager(), UNO_QUERY);
+ this->docAccelConf = docAccelConf;
+
+ //Get module shurtcut database
+ Reference< XModuleUIConfigurationManagerSupplier > modUISupplier(xMSF->createInstance(OUString::createFromAscii("com.sun.star.ui.ModuleUIConfigurationManagerSupplier")),
+ UNO_QUERY);
+ Reference< XUIConfigurationManager > modUIManager = modUISupplier->getUIConfigurationManager(xModuleManager->identify(xFrame));
+ Reference< XAcceleratorConfiguration > modAccelConf(modUIManager->getShortCutManager(), UNO_QUERY);
+ this->modAccelConf = modAccelConf;
+
+ //Get global shortcut database
+ Reference< XAcceleratorConfiguration > globAccelConf(xMSF->createInstance(OUString::createFromAscii("com.sun.star.ui.GlobalAcceleratorConfiguration")),
+ UNO_QUERY);
+ this->globAccelConf = globAccelConf;
+}
+
+
+//This function finds a KeyEvent with the shortcut information for each command
+KeyEvent
+FrameHelper::findShortcutForCommand (OUString command)
+
+{
+ KeyEvent kev;
+
+ Sequence < OUString > commands (1);
+ commands[0] = command;
+
+ try
+ {
+ Sequence < Any > evs = docAccelConf->getPreferredKeyEventsForCommandList (commands);
+
+ for (int j = 0; j < evs.getLength (); j++)
+ {
+ KeyEvent ev;
+ if (evs[j] >>= ev)
+ return ev;
+ }
+ }
+ catch (...)
+ {}
+ try
+ {
+ Sequence < Any > evs = modAccelConf->getPreferredKeyEventsForCommandList (commands);
+
+ for (int j = 0; j < evs.getLength (); j++)
+ {
+ KeyEvent ev;
+ if (evs[j] >>= ev)
+ return ev;
+ }
+ }
+ catch (...)
+ {}
+ try
+ {
+ Sequence < Any > evs = globAccelConf->getPreferredKeyEventsForCommandList (commands);
+
+ for (int j = 0; j < evs.getLength (); j++)
+ {
+ KeyEvent ev;
+ if (evs[j] >>= ev)
+ return ev;
+ }
+ }
+ catch (...)
+ {}
+
+ //NOTE: For some reason this item does not return its shortcut. Setting manually:
+ if (command.equals (OUString::createFromAscii (".uno:HelpIndex")))
+ {
+ kev.KeyCode = awt::Key::F1;
+ }
+
+ return kev;
+}
diff --git a/framework/source/lomenubar/FrameHelper.h b/framework/source/lomenubar/FrameHelper.h
new file mode 100644
index 0000000000..d3e00c6400
--- /dev/null
+++ b/framework/source/lomenubar/FrameHelper.h
@@ -0,0 +1,139 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef __FRAME_HELPER_H__
+#define __FRAME_HELPER_H__
+
+#include <com/sun/star/awt/KeyEvent.hpp>
+#include <com/sun/star/awt/XMenu.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/frame/XFrameActionListener.hpp>
+#include <com/sun/star/frame/XStatusListener.hpp>
+#include <com/sun/star/frame/FrameAction.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XModuleManager.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/ui/XAcceleratorConfiguration.hpp>
+
+#include <libdbusmenu-glib/server.h>
+#include <libdbusmenu-glib/menuitem.h>
+
+using com::sun::star::awt::KeyEvent;
+using com::sun::star::awt::XMenu;
+using com::sun::star::beans::PropertyValue;
+using com::sun::star::container::XNameAccess;
+using com::sun::star::frame::FrameActionEvent;
+using com::sun::star::frame::XFrame;
+using com::sun::star::frame::XFramesSupplier;
+using com::sun::star::frame::XFrameActionListener;
+using com::sun::star::frame::XStatusListener;
+using com::sun::star::frame::XDispatchProvider;
+using com::sun::star::frame::XModuleManager;
+using com::sun::star::frame::XModel;
+using com::sun::star::lang::EventObject;
+using com::sun::star::lang::XMultiServiceFactory;
+using com::sun::star::lang::XMultiComponentFactory;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::RuntimeException;
+using com::sun::star::util::XURLTransformer;
+using com::sun::star::ui::XAcceleratorConfiguration;
+using rtl::OUString;
+
+/* This class is a helper in charge of closing the dbusmenu server when a frame is closed,
+ * and also allows the menuitem callbacks to dispatch commands.
+ */
+
+class FrameHelper : public cppu::WeakImplHelper1 < XFrameActionListener >
+{
+ private:
+ Reference < XFrame > xFrame;
+ Reference < XMultiServiceFactory > xMSF;
+ Reference < XNameAccess > xUICommands;
+ DbusmenuServer *server;
+ DbusmenuMenuitem *root;
+ gboolean watcher_set;
+ guint watcher;
+ XStatusListener *xSL;
+ Reference < XURLTransformer > xTrans;
+ Reference < XDispatchProvider > xdp;
+ GHashTable *commandsInfo;
+ gboolean blockDetach;
+
+ //These object/methods are used to recreate dynamic popupmenus
+ Reference < XMultiComponentFactory > xPCF;
+ Reference < XModuleManager> xMM;
+ Sequence < Any > args;
+
+ gboolean isSpecialSubmenu (OUString command);
+
+ //This is to build the shortcut database
+ Reference< XAcceleratorConfiguration > docAccelConf;
+ Reference< XAcceleratorConfiguration > modAccelConf;
+ Reference< XAcceleratorConfiguration > globAccelConf;
+
+ void getAcceleratorConfigurations (Reference < XModel >,
+ Reference < XModuleManager>);
+
+ KeyEvent findShortcutForCommand (OUString);
+
+ public:
+ FrameHelper(const Reference< XMultiServiceFactory >&,
+ const Reference< XFrame >&,
+ DbusmenuServer*);
+
+ virtual ~FrameHelper();
+ virtual void SAL_CALL frameAction(const FrameActionEvent& action)
+ throw (RuntimeException);
+
+ virtual void SAL_CALL disposing(const EventObject& aEvent)
+ throw (RuntimeException);
+
+ //Setters
+ void setRootItem (DbusmenuMenuitem *);
+ void setRegistrarWatcher (guint watcher);
+ void setServer (DbusmenuServer *);
+
+ //Getters
+ Reference < XFrame > getFrame ();
+ unsigned long getXID ();
+ GHashTable* getCommandsInfo ();
+ XStatusListener* getStatusListener ();
+ ::rtl::OUString getLabelFromCommandURL (::rtl::OUString);
+
+ //Menu Related actions
+ void dispatchCommand (OUString);
+ void rebuildMenu (Reference < XMenu >, DbusmenuMenuitem*);
+ void rebuildMenuFromRoot ();
+ void populateWindowList (DbusmenuMenuitem *);
+};
+#endif // __FRAME_HELPER_H__
diff --git a/framework/source/lomenubar/FrameJob.cxx b/framework/source/lomenubar/FrameJob.cxx
new file mode 100644
index 0000000000..7e84d6c911
--- /dev/null
+++ b/framework/source/lomenubar/FrameJob.cxx
@@ -0,0 +1,393 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "FrameJob.h"
+#include "DesktopJob.h"
+#include "FrameHelper.h"
+
+#define OBJ_PATH_PREFIX "/com/canonical/menu/"
+
+#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
+#include <com/sun/star/awt/SystemDependentXWindow.hpp>
+#include <com/sun/star/awt/XMenu.hpp>
+#include <com/sun/star/awt/XMenuExtended.hpp>
+#include <com/sun/star/awt/XMenuBar.hpp>
+#include <com/sun/star/awt/XPopupMenu.hpp>
+#include <com/sun/star/awt/XPopupMenuExtended.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/document/XEventBroadcaster.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XLayoutManager.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XDispatchHelper.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XFrameActionListener.hpp>
+#include <com/sun/star/frame/XStatusListener.hpp>
+#include <com/sun/star/frame/FrameAction.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/lang/SystemDependent.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/ui/XUIConfigurationManager.hpp>
+#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/ui/XUIElementSettings.hpp>
+#include <com/sun/star/ui/XUIElement.hpp>
+#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+
+#include <iostream>
+#include <fstream>
+
+#include <gio/gio.h>
+#include <libdbusmenu-glib/server.h>
+#include <libdbusmenu-glib/client.h>
+
+#include <rtl/process.h>
+#include <osl/diagnose.h>
+
+using rtl::OUString;
+using rtl::OString;
+using rtl::OUStringToOString;
+
+using com::sun::star::awt::KeyEvent;
+using com::sun::star::awt::SystemDependentXWindow;
+using com::sun::star::awt::XMenu;
+using com::sun::star::awt::XMenuExtended;
+using com::sun::star::awt::XPopupMenu;
+using com::sun::star::awt::XPopupMenuExtended;
+using com::sun::star::awt::XMenuBar;
+using com::sun::star::awt::XSystemDependentWindowPeer;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::WeakReference;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::XInterface;
+using com::sun::star::uno::Exception;
+using com::sun::star::uno::RuntimeException;
+using com::sun::star::uno::XInterface;
+using com::sun::star::lang::IllegalArgumentException;
+using com::sun::star::lang::XMultiServiceFactory;
+using com::sun::star::lang::SystemDependent::SYSTEM_XWINDOW;
+using com::sun::star::lang::EventObject;
+using com::sun::star::beans::NamedValue;
+using com::sun::star::beans::PropertyValue;
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::document::XEventBroadcaster;
+using com::sun::star::frame::XFrame;
+using com::sun::star::frame::XFrameActionListener;
+using com::sun::star::frame::FrameActionEvent;
+using com::sun::star::frame::XController;
+using com::sun::star::frame::XLayoutManager;
+using com::sun::star::frame::XModel;
+using com::sun::star::frame::XModuleManager;
+using com::sun::star::frame::XDispatch;
+using com::sun::star::frame::XDispatchProvider;
+using com::sun::star::frame::XDispatchHelper;
+using com::sun::star::frame::XStatusListener;
+using com::sun::star::frame::FeatureStateEvent;
+using com::sun::star::ui::XUIElement;
+using com::sun::star::ui::XUIElementSettings;
+using com::sun::star::ui::XUIConfigurationManagerSupplier;
+using com::sun::star::ui::XUIConfigurationManager;
+using com::sun::star::ui::XModuleUIConfigurationManagerSupplier;
+using com::sun::star::ui::XAcceleratorConfiguration;
+using com::sun::star::util::URL;
+using com::sun::star::util::XURLTransformer;
+using com::sun::star::container::XIndexContainer;
+using com::sun::star::container::XIndexAccess;
+using com::sun::star::container::XNameAccess;
+using com::sun::star::container::NoSuchElementException;
+
+
+// This is a helper utility to transform an xid to a /com/canonical/menu/<XID>
+// DBUS object path
+OString
+xid_to_object_path (unsigned long xid)
+{
+
+ GString *xid_str = g_string_new ("");
+ g_string_printf (xid_str, "%d", (guint32)xid);
+ OString object_path = OUStringToOString (OUString::createFromAscii (OBJ_PATH_PREFIX).concat (OUString::createFromAscii(xid_str->str)),
+ RTL_TEXTENCODING_ASCII_US);
+ g_string_free (xid_str, TRUE);
+ return object_path;
+}
+
+//-------------------------- GObject callbacks -------------------------------//
+//This is called when a registrar becomes available. It registers the hides the menubar.
+static void
+on_registrar_available (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GDBusProxy *proxy;
+
+ FrameHelper *helper = (FrameHelper*)user_data;
+ unsigned long xid = helper->getXID();
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "com.canonical.AppMenu.Registrar",
+ "/com/canonical/AppMenu/Registrar",
+ "com.canonical.AppMenu.Registrar",
+ NULL,
+ &error);
+ if (error)
+ {
+ g_warning ("Couldn't get /com/canonical/AppMenu/Registrar proxy");
+ return;
+ }
+
+
+ //TODO: Check if window is registered already
+ g_dbus_proxy_call_sync (proxy,
+ "RegisterWindow",
+ g_variant_new ("(uo)",
+ (guint32)xid,
+ xid_to_object_path (xid).getStr()),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (error)
+ {
+ g_warning ("Couldn't call /com/canonical/AppMenu/Registrar.RegisterWindow");
+ return;
+ }
+
+ //Hide menubar
+ Reference < XFrame > xFrame = helper->getFrame ();
+ Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
+ Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString::createFromAscii("LayoutManager")),
+ UNO_QUERY);
+ xLayoutManager->hideElement (OUString::createFromAscii("private:resource/menubar/menubar"));
+
+ return;
+}
+
+//This is called when the registrar becomes unavailable. It shows the menubar.
+static void
+on_registrar_unavailable (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ //TODO: Unregister window?
+
+ // Show menubar
+ FrameHelper *helper = (FrameHelper*)user_data;
+ Reference < XFrame > xFrame = helper->getFrame ();
+ Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
+ Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString::createFromAscii("LayoutManager")),
+ UNO_QUERY);
+ xLayoutManager->showElement (OUString::createFromAscii("private:resource/menubar/menubar"));
+ return;
+}
+// ------------------------------- FrameJob --------------------------------------------
+Any SAL_CALL FrameJob::execute( const Sequence< NamedValue >& aArguments )
+ throw ( IllegalArgumentException, Exception, RuntimeException )
+{
+ Sequence< NamedValue > lEnv;
+ Reference< XModel > xModel;
+ sal_Int32 len = aArguments.getLength();
+
+ for (int i = 0; i<len; i++)
+ {
+ if (aArguments[i].Name.equalsAscii("Environment"))
+ {
+ aArguments[i].Value >>= lEnv;
+ break;
+ }
+ }
+
+ len = lEnv.getLength ();
+ for (int i = 0; i<len; i++)
+ {
+ if (lEnv[i].Name.equalsAscii("Model"))
+ {
+ lEnv[i].Value >>= xModel;
+ }
+ }
+
+ //If we didn't get the model we have to quit
+ if (!xModel.is())
+ return Any();
+
+
+ Reference< XController > xController( xModel->getCurrentController(), UNO_QUERY);
+ if (!xController.is())
+ return Any();
+
+ xFrame = Reference< XFrame > ( xController->getFrame(), UNO_QUERY);
+ if (!xFrame.is ())
+ return Any();
+
+ exportMenus (xFrame);
+ return Any();
+}
+
+// This function crates a DbusmenuServer and starts the watcher for the AppMenu Registrar bus name
+void
+FrameJob::exportMenus (Reference < XFrame > xFrame)
+{
+ //Set the xFrame for this object
+
+ this->xFrame = xFrame;
+
+ //Create dbusmenu server object path string
+ DbusmenuServer *server = dbusmenu_server_new (xid_to_object_path(getXID (xFrame)).getStr());
+
+
+ Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
+ Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString::createFromAscii("LayoutManager")),
+ UNO_QUERY);
+ if (!xLayoutManager.is())
+ {
+ g_object_unref (server);
+ return;
+ }
+
+ Reference < XUIElement > menuBar(xLayoutManager->getElement (OUString::createFromAscii("private:resource/menubar/menubar")),
+ UNO_QUERY);
+ Reference < XPropertySet > menuPropSet (menuBar, UNO_QUERY);
+
+ if (!menuPropSet.is())
+ {
+ g_object_unref (server);
+ return;
+ }
+
+ Reference < XMenu > xMenu (menuPropSet->getPropertyValue(OUString::createFromAscii("XMenuBar")),
+ UNO_QUERY);
+
+ if (!xMenu.is ())
+ {
+ g_object_unref (server);
+ return;
+ }
+
+ //Create a new frame helper to close the server when needed
+ FrameHelper *helper = new FrameHelper (mxMSF, xFrame, server);
+ xFrame->addFrameActionListener (Reference < XFrameActionListener > (helper));
+
+ //Populate dbusmenu items and start the server
+ DbusmenuMenuitem *root = getRootMenuitem (xMenu, (gpointer)helper);
+ dbusmenu_server_set_root (server, root);
+
+ //Listen to the availability of the registrar
+ guint watcher = g_bus_watch_name (G_BUS_TYPE_SESSION,
+ "com.canonical.AppMenu.Registrar",
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ on_registrar_available,
+ on_registrar_unavailable,
+ helper,
+ NULL);
+ helper->setRegistrarWatcher (watcher);
+}
+
+
+//Gets the XID for a given XFrame
+unsigned long
+FrameJob::getXID (css::uno::Reference < css::frame::XFrame > xFrame)
+{
+ Reference< XSystemDependentWindowPeer > xWin( xFrame->getContainerWindow(), UNO_QUERY);
+
+ if (!xWin.is())
+ return 0;
+
+ sal_Int8 processID[16];
+ rtl_getGlobalProcessId( (sal_uInt8*)processID );
+ Sequence <signed char> pidSeq (processID, 16);
+
+ SystemDependentXWindow xWindow;
+ xWin->getWindowHandle (pidSeq, SYSTEM_XWINDOW) >>= xWindow;
+
+ return xWindow.WindowHandle;
+}
+
+// Builds a Dbusmenuitem structure from an XMenu object
+DbusmenuMenuitem*
+FrameJob::getRootMenuitem (Reference < XMenu > xMenu, gpointer helper)
+{
+
+ DbusmenuMenuitem *root = dbusmenu_menuitem_new_with_id (0);
+ ((FrameHelper*)helper)->setRootItem(root);
+ ((FrameHelper*)helper)->rebuildMenu (xMenu, root);
+
+ return root;
+}
+
+// XJob
+OUString FrameJob_getImplementationName ()
+ throw (RuntimeException)
+{
+ return OUString ( RTL_CONSTASCII_USTRINGPARAM ( FRAMEJOB_IMPLEMENTATION_NAME ) );
+}
+
+sal_Bool SAL_CALL FrameJob_supportsService( const OUString& ServiceName )
+ throw (RuntimeException)
+{
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( FRAMEJOB_SERVICE_NAME ) );
+}
+
+Sequence< OUString > SAL_CALL FrameJob_getSupportedServiceNames( )
+ throw (RuntimeException)
+{
+ Sequence < OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( FRAMEJOB_SERVICE_NAME ) );
+ return aRet;
+}
+
+Reference< XInterface > SAL_CALL FrameJob_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
+ throw( Exception )
+{
+ return (cppu::OWeakObject*) new FrameJob(rSMgr);
+}
+
+// XServiceInfo
+OUString SAL_CALL FrameJob::getImplementationName()
+ throw (RuntimeException)
+{
+ return FrameJob_getImplementationName();
+}
+
+sal_Bool SAL_CALL FrameJob::supportsService( const OUString& rServiceName )
+ throw (RuntimeException)
+{
+ return FrameJob_supportsService( rServiceName );
+}
+
+Sequence< OUString > SAL_CALL FrameJob::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ return FrameJob_getSupportedServiceNames();
+}
+
diff --git a/framework/source/lomenubar/FrameJob.h b/framework/source/lomenubar/FrameJob.h
new file mode 100644
index 0000000000..d209a0966f
--- /dev/null
+++ b/framework/source/lomenubar/FrameJob.h
@@ -0,0 +1,101 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef __FRAME_JOB_HXX__
+#define __MRAME_JOB_HXX__
+
+#include <com/sun/star/task/XJob.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase2.hxx>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XModuleManager.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/ui/XAcceleratorConfiguration.hpp>
+#include <com/sun/star/awt/XMenu.hpp>
+#include <com/sun/star/awt/KeyEvent.hpp>
+
+#include <glib.h>
+#include <libdbusmenu-glib/menuitem.h>
+
+#define FRAMEJOB_IMPLEMENTATION_NAME "com.sun.star.comp.Office.MyJob"
+#define FRAMEJOB_SERVICE_NAME "com.sun.star.task.Job"
+
+namespace css = ::com::sun::star;
+using css::uno::Reference;
+
+class FrameJob : public cppu::WeakImplHelper2 < css::task::XJob, css::lang::XServiceInfo >
+{
+ private:
+ Reference < css::lang::XMultiServiceFactory > mxMSF;
+ Reference < css::container::XNameAccess > xUICommands;
+ Reference < css::frame::XFrame > xFrame;
+
+ unsigned long xid;
+
+ //Private methods
+ unsigned long getXID (Reference < css::frame::XFrame >);
+ DbusmenuMenuitem* getRootMenuitem (Reference < css::awt::XMenu >,
+ gpointer);
+
+ public:
+ FrameJob( const css::uno::Reference< css::lang::XMultiServiceFactory > &rxMSF)
+ : mxMSF( rxMSF ) {};
+
+ void exportMenus (Reference < css::frame::XFrame > xFrame);
+
+ virtual ~FrameJob() {}
+
+ // XJob
+ virtual css::uno::Any SAL_CALL execute(const css::uno::Sequence< css::beans::NamedValue >& Arguments)
+ throw (css::lang::IllegalArgumentException, css::uno::Exception, css::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName()
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
+ throw (css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
+ throw (css::uno::RuntimeException);
+};
+
+
+::rtl::OUString FrameJob_getImplementationName()
+ throw ( css::uno::RuntimeException );
+
+sal_Bool SAL_CALL FrameJob_supportsService( const ::rtl::OUString& ServiceName )
+ throw ( css::uno::RuntimeException );
+
+css::uno::Sequence< ::rtl::OUString > SAL_CALL FrameJob_getSupportedServiceNames()
+ throw ( css::uno::RuntimeException );
+
+css::uno::Reference< css::uno::XInterface >
+SAL_CALL FrameJob_createInstance( const css::uno::Reference< css::lang::XMultiServiceFactory > & rSMgr)
+ throw ( css::uno::Exception );
+
+#endif
+
diff --git a/framework/source/lomenubar/MenuItemInfo.cxx b/framework/source/lomenubar/MenuItemInfo.cxx
new file mode 100644
index 0000000000..eab5c5bc75
--- /dev/null
+++ b/framework/source/lomenubar/MenuItemInfo.cxx
@@ -0,0 +1,103 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "MenuItemInfo.h"
+#include <libdbusmenu-gtk/menuitem.h>
+
+MenuItemInfo::MenuItemInfo ()
+{
+ label = NULL;
+ check_state = DBUSMENU_MENUITEM_TOGGLE_STATE_UNKNOWN;
+ check_type = (gchar*)DBUSMENU_MENUITEM_TOGGLE_CHECK;
+
+ is_visible = TRUE;
+ is_enabled = TRUE;
+}
+
+MenuItemInfo::~MenuItemInfo ()
+{
+ if (label)
+ g_free(label);
+}
+
+//Setters
+void
+MenuItemInfo::setLabel (gchar* label)
+{
+ this->label = g_strdup (label);
+}
+
+void
+MenuItemInfo::setEnabled (gboolean is_enabled)
+{
+ this->is_enabled = is_enabled;
+}
+
+void
+MenuItemInfo::setCheckState (gint check_state)
+{
+ this->check_state = check_state;
+}
+
+void
+MenuItemInfo::setCheckType (const gchar* check_type)
+{
+ this->check_type = (gchar*)check_type;
+}
+
+void
+MenuItemInfo::setVisible (gboolean is_visible)
+{
+ this->is_visible = is_visible;
+}
+
+//Getters
+gchar*
+MenuItemInfo::getLabel ()
+{
+ return label;
+}
+
+gboolean
+MenuItemInfo::getEnabled ()
+{
+ return is_enabled;
+}
+
+gint
+MenuItemInfo::getCheckState ()
+{
+ return check_state;
+}
+
+const gchar*
+MenuItemInfo::getCheckType ()
+{
+ return check_type;
+}
+
+gboolean
+MenuItemInfo::getVisible ()
+{
+ return is_visible;
+}
diff --git a/framework/source/lomenubar/MenuItemInfo.h b/framework/source/lomenubar/MenuItemInfo.h
new file mode 100644
index 0000000000..9239625f58
--- /dev/null
+++ b/framework/source/lomenubar/MenuItemInfo.h
@@ -0,0 +1,54 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef __MENU_ITEM_INFO_H__
+#define __MENU_ITEM_INFO_H__
+#include <glib.h>
+
+// This is used in a hash table with commandurls as keys
+class MenuItemInfo {
+ gchar* label; //Label text in UTF-8 with tildes subst by underscores
+ gint check_state;
+ gchar* check_type;
+ gboolean is_enabled;
+ gboolean is_visible;
+
+ public:
+ MenuItemInfo ();
+ ~MenuItemInfo ();
+
+ //Setters
+ void setLabel (gchar* label);
+ void setEnabled (gboolean is_enabled);
+ void setCheckState (gint check_state);
+ void setCheckType (const gchar* check_type);
+ void setVisible (gboolean is_visible);
+
+ //Getters
+ gchar* getLabel ();
+ gboolean getEnabled ();
+ gint getCheckState ();
+ const gchar* getCheckType ();
+ gboolean getVisible ();
+};
+#endif // __MENU_ITEM_INFO_H__
diff --git a/framework/source/lomenubar/MenuItemStatusListener.cxx b/framework/source/lomenubar/MenuItemStatusListener.cxx
new file mode 100644
index 0000000000..68ca3de8d4
--- /dev/null
+++ b/framework/source/lomenubar/MenuItemStatusListener.cxx
@@ -0,0 +1,82 @@
+#include "MenuItemStatusListener.h"
+#include "MenuItemInfo.h"
+
+#include <com/sun/star/frame/status/Visibility.hpp>
+
+using com::sun::star::frame::status::Visibility;
+
+MenuItemStatusListener::MenuItemStatusListener (FrameHelper *helper)
+{
+ if (!helper) throw ("FrameHelper cannot be NULL");
+ this->helper = helper;
+}
+
+void SAL_CALL
+MenuItemStatusListener::statusChanged(const FeatureStateEvent& Event)
+ throw (RuntimeException)
+{
+ sal_Bool isChecked;
+ Visibility visible;
+ OUString url = Event.FeatureURL.Complete;
+ OUString oULabel;
+
+ gchar* c_url = g_utf16_to_utf8 (url.getStr(),
+ url.getLength(),
+ NULL, NULL, NULL);
+
+ GHashTable *commandsInfo = helper->getCommandsInfo ();
+ MenuItemInfo *info = (MenuItemInfo*)g_hash_table_lookup (commandsInfo, (gpointer)c_url);
+ if (!info)
+ {
+ info = new MenuItemInfo ();
+ g_hash_table_insert (commandsInfo, c_url, info);
+
+ //Set the default label
+ oULabel = helper->getLabelFromCommandURL(url);
+ // Replace tilde with underscore for Dbusmenu Alt accelerators
+ oULabel = oULabel.replace ((sal_Unicode)0x007e, (sal_Unicode)0x005f);
+
+ // GLib behaves better than OUStringToOString wrt encoding transformation
+ gchar* label = g_utf16_to_utf8 (oULabel.getStr(),
+ oULabel.getLength(),
+ NULL, NULL, NULL);
+ info->setLabel (label);
+ g_free (label);
+ }
+ else
+ {
+ //Since we're not introducing it in the hash table, we get rid of this string
+ g_free (c_url);
+ }
+
+ //We set the enabled/disabled state
+ info->setEnabled ((gboolean)Event.IsEnabled);
+
+ //We find out what the new state is by casting
+
+ //For some reason, URLs can slip through as labels, we make sure
+ //this doesn't happen.
+ if ((Event.State >>= oULabel) &&
+ !oULabel.matchAsciiL ("private:", 8, 0) &&
+ !oULabel.matchAsciiL (".uno:", 5, 0) &&
+ !oULabel.matchAsciiL ("slot:", 5, 0) &&
+ !oULabel.matchAsciiL ("service:", 8, 0) &&
+ !oULabel.matchAsciiL (".cmd:", 5, 0) &&
+ !oULabel.matchAsciiL ("macro:///", 5, 0))
+ {
+ oULabel = oULabel.replace ((sal_Unicode)0x007e, (sal_Unicode)0x005f);
+ gchar* label = g_utf16_to_utf8 (oULabel.getStr(),
+ oULabel.getLength(),
+ NULL, NULL, NULL);
+ info->setLabel (label);
+ g_free (label);
+ }
+ else if (Event.State >>= isChecked)
+ {
+ info->setCheckState (isChecked);
+ }
+ else if (Event.State >>= visible)
+ {
+ info->setVisible (visible.bVisible);
+ }
+}
diff --git a/framework/source/lomenubar/MenuItemStatusListener.h b/framework/source/lomenubar/MenuItemStatusListener.h
new file mode 100644
index 0000000000..56cf5e8332
--- /dev/null
+++ b/framework/source/lomenubar/MenuItemStatusListener.h
@@ -0,0 +1,35 @@
+#ifndef __MENU_ITEM_STATUS_LISTENER_H__
+#define __MENU_ITEM_STATUS_LISTENER_H__
+
+#include "FrameHelper.h"
+
+#include <glib.h>
+
+#include <com/sun/star/frame/XStatusListener.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+#include <rtl/process.h>
+
+using com::sun::star::frame::FeatureStateEvent;
+using com::sun::star::frame::XStatusListener;
+using com::sun::star::lang::EventObject;
+
+// This class listens for changes in each menuitem and notifies FrameHelper about it
+class MenuItemStatusListener : public cppu::WeakImplHelper1 < XStatusListener >
+{
+ private:
+ guint16 id;
+ FrameHelper *helper;
+
+ public:
+ MenuItemStatusListener (FrameHelper *helper);
+ ~MenuItemStatusListener () {}
+
+ virtual void SAL_CALL
+ statusChanged(const FeatureStateEvent& Event)
+ throw (RuntimeException);
+
+ virtual void SAL_CALL disposing(const EventObject& aEvent)
+ throw (RuntimeException) {}
+};
+#endif
diff --git a/framework/source/lomenubar/exports.cxx b/framework/source/lomenubar/exports.cxx
new file mode 100644
index 0000000000..e581a2c55c
--- /dev/null
+++ b/framework/source/lomenubar/exports.cxx
@@ -0,0 +1,119 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * A LibreOffice extension to send the menubar structure through DBusMenu
+ *
+ * Copyright 2011 Canonical, Ltd.
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@codethink.co.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the the GNU Lesser General Public License version 3, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE. See the applicable
+ * version of the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <stdio.h>
+
+#include <osl/mutex.hxx>
+#include <osl/thread.h>
+#include <cppuhelper/factory.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/types.h>
+
+#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#endif
+
+#include "DesktopJob.h"
+#include "FrameJob.h"
+
+namespace css = ::com::sun::star;
+
+static void writeInfo(const css::uno::Reference< css::registry::XRegistryKey >& xRegistryKey ,
+ const char* pImplementationName,
+ const char* pServiceName )
+{
+ ::rtl::OUStringBuffer sKey(256);
+ sKey.append (::rtl::OUString::createFromAscii(pImplementationName));
+ sKey.appendAscii("/UNO/SERVICES/");
+ sKey.append (::rtl::OUString::createFromAscii(pServiceName));
+
+ xRegistryKey->createKey(sKey.makeStringAndClear());
+}
+
+extern "C"
+{
+//==================================================================================================
+SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(const sal_Char** ppEnvTypeName,
+ uno_Environment** ppEnv )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+
+//==================================================================================================
+SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo(void* pServiceManager,
+ void* pRegistryKey )
+{
+ if (!pRegistryKey)
+ return sal_False;
+
+ try
+ {
+ css::uno::Reference< css::registry::XRegistryKey > xKey(reinterpret_cast< css::registry::XRegistryKey* >(pRegistryKey), css::uno::UNO_QUERY);
+
+ writeInfo( xKey, DESKTOPJOB_IMPLEMENTATION_NAME, DESKTOPJOB_SERVICE_NAME);
+ writeInfo( xKey, FRAMEJOB_IMPLEMENTATION_NAME, FRAMEJOB_SERVICE_NAME);
+
+ return sal_True;
+ }
+ catch(const css::registry::InvalidRegistryException&)
+ { OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); }
+
+ return sal_False;
+}
+
+//==================================================================================================
+SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory(const sal_Char* pImplName ,
+ void* pServiceManager,
+ void* pRegistryKey )
+{
+ if ( !pServiceManager || !pImplName )
+ return 0;
+
+ css::uno::Reference< css::lang::XSingleServiceFactory > xFactory ;
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR (reinterpret_cast< css::lang::XMultiServiceFactory* >(pServiceManager), css::uno::UNO_QUERY);
+ ::rtl::OUString sImplName = ::rtl::OUString::createFromAscii(pImplName);
+
+ if (sImplName.equalsAscii(DESKTOPJOB_IMPLEMENTATION_NAME))
+ {
+ css::uno::Sequence< ::rtl::OUString > lNames(1);
+ lNames[0] = ::rtl::OUString::createFromAscii(DESKTOPJOB_IMPLEMENTATION_NAME);
+ xFactory = ::cppu::createSingleFactory(xSMGR, sImplName, DesktopJob_createInstance, lNames);
+ }
+ if (sImplName.equalsAscii(FRAMEJOB_IMPLEMENTATION_NAME))
+ {
+ css::uno::Sequence< ::rtl::OUString > lNames(1);
+ lNames[0] = ::rtl::OUString::createFromAscii(FRAMEJOB_IMPLEMENTATION_NAME);
+ xFactory = ::cppu::createSingleFactory(xSMGR, sImplName, FrameJob_createInstance, lNames);
+ }
+
+
+ if (!xFactory.is())
+ return 0;
+
+ xFactory->acquire();
+ return xFactory.get();
+}
+
+} // extern C