Kaydet (Commit) 2b242efd authored tarafından Alberto Ruiz's avatar Alberto Ruiz Kaydeden (comit) Bjoern Michaelsen

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
üst 41434439
/*
* 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;
}
}
/*
* 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__
/*
* 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();
}
/*
* 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__
/*
* 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;
}
/*
* 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__
/*
* 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();
}
/*
* 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
/*
* 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;
}
/*
* 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__
#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);
}
}
#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
/*
* 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment