/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * 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 * * 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 * */ #include "FrameJob.hxx" #include "DesktopJob.hxx" #include "FrameHelper.hxx" #define OBJ_PATH_PREFIX "/com/canonical/menu/" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wignored-qualifiers" #include #include #pragma GCC diagnostic error "-Wignored-qualifiers" //#pragma GCC diagnostic pop #include #include 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/ // 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 = static_cast(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(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))), UNO_QUERY); xLayoutManager->hideElement (OUString(RTL_CONSTASCII_USTRINGPARAM("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 = static_cast(user_data); Reference < XFrame > xFrame = helper->getFrame (); Reference< XPropertySet > frameProps (xFrame, UNO_QUERY); Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))), UNO_QUERY); xLayoutManager->showElement (OUString(RTL_CONSTASCII_USTRINGPARAM("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>= lEnv; break; } } len = lEnv.getLength (); for (int i = 0; i>= 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(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))), UNO_QUERY); if (!xLayoutManager.is()) { g_object_unref (server); return; } Reference < XUIElement > menuBar(xLayoutManager->getElement (OUString(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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 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* fHelper = static_cast(helper); fHelper->setRootItem(root); fHelper->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(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */