diff options
Diffstat (limited to 'framework/source/lomenubar/FrameJob.cxx')
-rw-r--r-- | framework/source/lomenubar/FrameJob.cxx | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/framework/source/lomenubar/FrameJob.cxx b/framework/source/lomenubar/FrameJob.cxx new file mode 100644 index 000000000000..27b0350a2100 --- /dev/null +++ b/framework/source/lomenubar/FrameJob.cxx @@ -0,0 +1,397 @@ +/* + * 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.hxx" +#include "DesktopJob.hxx" +#include "FrameHelper.hxx" + +#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> +//#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wignored-qualifiers" +#include <libdbusmenu-glib/server.h> +#include <libdbusmenu-glib/client.h> +#pragma GCC diagnostic error "-Wignored-qualifiers" +//#pragma GCC diagnostic pop + +#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(); + + m_xFrame = Reference< XFrame > ( xController->getFrame(), UNO_QUERY); + if (!m_xFrame.is ()) + return Any(); + + exportMenus (m_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->m_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 (m_xMSF, 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(); +} + |