Kaydet (Commit) f7e0297b authored tarafından Tor Lillqvist's avatar Tor Lillqvist

Work in progress related to invoking events in Automation clients

XConnectable interfaces need a second IID, for the interface "itself",
not the coclass. (I am sure there is some catchy short term for that,
I just can't find it right now.)

Allow several simultaneous sinks for a SwVbaApplication. Not sure in
what case such would be needed, but you never know about 3rd-party
client code, and it's trivial to handle anyway, so why not.

Lots of FIXMEs still. There is likely also a lot of leaks. But at
least an event handler in a simple VBScript script does get invoked.

Note that the changed and added code in extensions/source/ole is
totally unaware of what outgoing ("event") interfaces Writer or Calc
implements, it is all handled generically through the UNO interfaces I
added recently.

One particular thing that needs doing is to actually make Writer (and
Calc) raise this kind of events when necessary. The current code to
invoke events handlers in StarBasic (including StarBasic code running
in "VBA" compaibility) is very much tied to having StarBasic running
(not surprisingly), which of course is not at all the case when it is
an Automation client that is manipulating a Writer or Calc instance
and wants events.

There is demonstration-only code in SwVbaApplication::Documents() to
raise the "Quit" event. (I would have put that in the SwVbaApplication
destructor but that doesn't seem to get called.) That should of course
go away once we invoke other relevant events in appropriate places.
And the "Quit" event needs to be invoked when the application is
quitting.

The whole callback mechanism with IConnectionPoint etc is still partly
a mystery to me. It is entirely possible that even if this now works
for a simple VBScript client, it won't work for (for instance) a VB6
client that might exercise the APIs of the COM interfaces we provide
in a different way.

Add XSinkCaller, for something that perhaps calls one or several
XSinks.

Change-Id: Ica03344010e374542f4aceff5ec032c78579f937
Reviewed-on: https://gerrit.libreoffice.org/55093Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarTor Lillqvist <tml@collabora.com>
üst 63e65d17
......@@ -24,7 +24,9 @@
#include "servprov.hxx"
#include "unoobjw.hxx"
#include "oleobjw.hxx"
#include <com/sun/star/script/CannotConvertException.hpp>
#include <comphelper/windowsdebugoutput.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <o3tl/any.hxx>
......@@ -44,7 +46,8 @@ using namespace com::sun::star::bridge::ModelDependent;
// {82154420-0FBF-11d4-8313-005004526AB4}
DEFINE_GUID(OID_ServiceManager, 0x82154420, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
// FIXME: This GUID is just the above with the initial part bumped by one. Is that good enough?
// FIXME: This GUID is just the above OID_ServiceManager with the
// initial part bumped by one. Is that good enough?
// {82154421-0FBF-11d4-8313-005004526AB4}
DEFINE_GUID(OID_LibreOfficeWriterApplication, 0x82154421, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50, 0x4, 0x52, 0x6a, 0xb4);
......@@ -129,6 +132,8 @@ STDMETHODIMP OneInstanceOleWrapper::CreateInstance(IUnknown FAR* punkOuter,
REFIID riid,
void FAR* FAR* ppv)
{
SAL_INFO("extensions.olebridge", "OneInstanceOleWrapper::CreateInstance(" << riid << ")");
HRESULT ret = ResultFromScode(E_UNEXPECTED);
punkOuter = nullptr;
......@@ -150,6 +155,7 @@ STDMETHODIMP OneInstanceOleWrapper::CreateInstance(IUnknown FAR* punkOuter,
if ((pVariant->vt == VT_UNKNOWN) || (pVariant->vt == VT_DISPATCH))
{
SAL_INFO("extensions.olebridge", "OneInstanceOleWrapper::Createbridge: punkVal=" << pVariant->punkVal);
ret = pVariant->punkVal->QueryInterface(riid, ppv);
}
......
......@@ -78,21 +78,21 @@ typedef std::unordered_map
class InterfaceOleWrapper : public WeakImplHelper<XBridgeSupplier2, XInitialization>,
public IDispatchEx,
public IProvideClassInfo,
public IConnectionPointContainer,
public UnoConversionUtilities<InterfaceOleWrapper>,
public IUnoObjectWrapper
{
public:
InterfaceOleWrapper(Reference<XMultiServiceFactory> const & xFactory, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass);
~InterfaceOleWrapper() override;
/* IUnknown methods */
// IUnknown
STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR * ppvObj) override;
STDMETHOD_(ULONG, AddRef)() override;
STDMETHOD_(ULONG, Release)() override;
/* IDispatch methods */
// IDispatch
STDMETHOD( GetTypeInfoCount )( unsigned int * pctinfo ) override;
STDMETHOD( GetTypeInfo )( unsigned int itinfo, LCID lcid, ITypeInfo ** pptinfo ) override;
STDMETHOD( GetIDsOfNames )( REFIID riid, OLECHAR ** rgszNames, unsigned int cNames,
......@@ -101,8 +101,7 @@ public:
DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
unsigned int * puArgErr ) override;
/* IDispatchEx methods */
// IDispatchEx
virtual HRESULT STDMETHODCALLTYPE GetDispID(
/* [in] */ BSTR bstrName,
/* [in] */ DWORD grfdex,
......@@ -141,13 +140,24 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetNameSpaceParent(
/* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk) override;
// XBridgeSupplier2 ---------------------------------------------------
// IProvideClassInfo
virtual HRESULT STDMETHODCALLTYPE GetClassInfo(
/* [out] */ ITypeInfo **ppTI) override;
// IConnectionPointContainer
virtual HRESULT STDMETHODCALLTYPE EnumConnectionPoints(
/* [out] */ IEnumConnectionPoints **ppEnum) override;
virtual HRESULT STDMETHODCALLTYPE FindConnectionPoint(
/* [in] */ REFIID riid,
/* [out] */ IConnectionPoint **ppCP) override;
// XBridgeSupplier2
virtual Any SAL_CALL createBridge(const Any& modelDepObject,
const Sequence<sal_Int8>& ProcessId,
sal_Int16 sourceModelType,
sal_Int16 destModelType) override;
//XInitialization -----------------------------------------------------
// XInitialization
virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
// IUnoObjectWrapper
......
......@@ -44,6 +44,7 @@ $(eval $(call gb_UnoApi_add_idlfiles_noheader,oovbaapi,ooo/vba/excel,\
$(eval $(call gb_UnoApi_add_idlfiles,oovbaapi,ooo/vba,\
FormShowConstants \
TypeAndIID \
VbAppWinStyle \
VbCalendar \
VbCallType \
......@@ -70,6 +71,8 @@ $(eval $(call gb_UnoApi_add_idlfiles,oovbaapi,ooo/vba,\
XCommandBarControls \
XCommandBarPopup \
XCommandBars \
XConnectable \
XConnectionPoint \
XControlProvider \
XDialogBase \
XDialogsBase \
......@@ -82,8 +85,11 @@ $(eval $(call gb_UnoApi_add_idlfiles,oovbaapi,ooo/vba,\
XFontBase \
XGlobalsBase \
XHelperInterface \
XInterfaceWithIID \
XPageSetupBase \
XPropValue \
XSink \
XSinkCaller \
XVBAToOOEventDescGen \
XWindowBase \
))
......@@ -1028,6 +1034,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,oovbaapi,ooo/vba/word,\
XAddin \
XAddins \
XApplication \
XApplicationOutgoing \
XAutoTextEntries \
XAutoTextEntry \
XBookmark \
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __ooo_vba_TypeAndIID_idl__
#define __ooo_vba_TypeAndIID_idl__
module ooo { module vba {
// Despite being here in ooo::vba, this has nothing to do with "VBA" (Visual Basic for
// Applications), or the VBA compatibility in StarBasic. This is related to using LibreOffice from
// (OLE) Automation clients. It is here anyway because much of the API available to such clients
// is identical to that offered to StarBasic code written in a VBA-like fashion.
struct TypeAndIID
{
type Type;
string IID;
};
}; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __ooo_vba_XConnectable_idl__
#define __ooo_vba_XConnectable_idl__
module ooo { module vba {
// Despite being here in ooo::vba, this has nothing to do with "VBA" (Visual Basic for
// Applications), or the VBA compatibility in StarBasic. This is related to using LibreOffice from
// (OLE) Automation clients. It is here anyway because much of the API available to such clients
// is identical to that offered to StarBasic code written in a VBA-like fashion.
// An object that implements this interface should intend to be usable from an Automation client
// that wants the object to do callbacks, i.e. generate "events" in the client (for instance
// implemented in VBScript, VB6, or even C++).
interface XConnectable
{
interface XInterfaceWithIID;
// Silly name yes, but I can't find what the proper term for this thing is. This is not a
// published interface anyway.
string GetIIDForClassItselfNotCoclass();
TypeAndIID GetConnectionPoint();
XConnectionPoint FindConnectionPoint();
};
}; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __ooo_vba_XConnectionPoint_idl__
#define __ooo_vba_XConnectionPoint_idl__
module ooo { module vba {
// Despite being here in ooo::vba, this has nothing to do with "VBA" (Visual Basic for
// Applications), or the VBA compatibility in StarBasic. This is related to using LibreOffice from
// (OLE) Automation clients. It is here anyway because much of the API available to such clients
// is identical to that offered to StarBasic code written in a VBA-like fashion.
// This is quite different from css::lang::XConnectionPoint.
// This is tailored to be slimmer and match the use case from Automation clients much better.
interface XConnectionPoint
{
unsigned long Advise([in] XSink Sink);
void Unadvise([in] unsigned long Cookie);
};
}; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __ooo_vba_XInterfaceWithIID_idl__
#define __ooo_vba_XInterfaceWithIID_idl__
module ooo { module vba {
// Despite being here in ooo::vba, this has nothing to do with "VBA" (Visual Basic for
// Applications), or the VBA compatibility in StarBasic. This is related to using LibreOffice from
// (OLE) Automation clients. It is here anyway because much of the API available to such clients
// is identical to that offered to StarBasic code written in a VBA-like fashion.
// An interface that has an IID.
interface XInterfaceWithIID : com::sun::star::uno::XInterface
{
// The IID of the interface, in the string form with braces, as
// accepted by IIDFromString, for instance
// "{82154421-0fbf-11d4-8313-005004526ab4}"
[attribute, readonly] string IID;
};
}; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __ooo_vba_XConnectionPointSink_idl__
#define __ooo_vba_XConnectionPointSink_idl__
module ooo { module vba {
// Despite being here in ooo::vba, this has nothing to do with "VBA" (Visual Basic for
// Applications), or the VBA compatibility in StarBasic. This is related to using LibreOffice from
// (OLE) Automation clients. It is here anyway because much of the API available to such clients
// is identical to that offered to StarBasic code written in a VBA-like fashion.
// This is the interface LibreOffice code actually uses when doing "outgoing" calls to Automation
// clients (for events).
interface XSink
{
// This will be massaged by the Automation-UNO bridge into a call into the sink provided by the
// Automation client.
// FIXME: Add "out" arguments, and perhaps exceptions?
void Call([in] string Method, [in] sequence<any> Arguments);
};
}; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __ooo_vba_XSinkCaller_idl__
#define __ooo_vba_XSinkCaller_idl__
module ooo { module vba {
// Despite being here in ooo::vba, this has nothing to do with "VBA" (Visual Basic for
// Applications), or the VBA compatibility in StarBasic. This is related to using LibreOffice from
// (OLE) Automation clients. It is here anyway because much of the API available to such clients
// is identical to that offered to StarBasic code written in a VBA-like fashion.
interface XSinkCaller
{
void CallSinks([in] string Method, [in] sequence<any> Arguments);
};
}; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -29,7 +29,7 @@ interface XWindow;
interface XSystem;
interface XOptions;
interface XSelection;
interface XApplication : com::sun::star::uno::XInterface
interface XApplication : XConnectable
{
[attribute, readonly] XDocument ActiveDocument;
[attribute, readonly] XWindow ActiveWindow;
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __ooo_vba_word_XApplicationOutgoing_idl__
#define __ooo_vba_word_XApplicationOutgoing_idl__
module ooo { module vba { module word {
// Despite being here in ooo::vba, this has nothing to do with "VBA" (Visual Basic for
// Applications), or the VBA compatibility in StarBasic. This is related to using LibreOffice from
// (OLE) Automation clients. It is here anyway because much of the API available to such clients
// is identical to that offered to StarBasic code written in a VBA-like fashion.
// This interface exists for technical reasons only, we don't actually have any UNO object that
// would implemenrt (inherit from) this. We just advertise the type of this interface from Writer to
// the Automation-UNO bridge code (in extensions/source/ole) so that it can tell the Automation
// client what the Automation server expects and construct a corresponding COM interface that can
// receive the callbacks. Or something like that.
interface XApplicationOutgoing : XInterfaceWithIID
{
void DocumentChange();
void Quit();
};
}; }; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -27,7 +27,9 @@
#include "vbadocuments.hxx"
#include "vbaaddins.hxx"
#include "vbadialogs.hxx"
#include <ooo/vba/XConnectionPoint.hpp>
#include <ooo/vba/word/WdEnableCancelKey.hpp>
#include <ooo/vba/word/XApplicationOutgoing.hpp>
#include <basic/sbuno.hxx>
#include <editeng/acorrcfg.hxx>
#include "wordvbahelper.hxx"
......@@ -38,12 +40,48 @@ using namespace ::ooo;
using namespace ::ooo::vba;
using namespace ::com::sun::star;
SwVbaApplication::SwVbaApplication( uno::Reference<uno::XComponentContext >& xContext ): SwVbaApplication_BASE( xContext )
class SwVbaApplicationOutgoingConnectionPoint : public cppu::WeakImplHelper<XConnectionPoint>
{
private:
SwVbaApplication* mpApp;
public:
SwVbaApplicationOutgoingConnectionPoint( SwVbaApplication* pApp );
// XConnectionPoint
sal_uInt32 SAL_CALL Advise(const uno::Reference< XSink >& Sink ) override;
void SAL_CALL Unadvise( sal_uInt32 Cookie ) override;
};
SwVbaApplication::SwVbaApplication( uno::Reference<uno::XComponentContext >& xContext ):
SwVbaApplication_BASE( xContext )
{
}
SwVbaApplication::~SwVbaApplication()
{
// FIXME: Sadly this is not the place to do this, this dtor is never called, it seems
for (auto& i : mvSinks)
{
if (i.is())
i->Call("Quit", uno::Sequence<uno::Any>());
}
}
sal_uInt32
SwVbaApplication::AddSink( const css::uno::Reference< XSink >& xSink )
{
mvSinks.push_back(xSink);
return mvSinks.size();;
}
void
SwVbaApplication::RemoveSink( sal_uInt32 nNumber )
{
if (nNumber < 1 || nNumber > mvSinks.size())
return;
mvSinks[nNumber-1] = uno::Reference< XSink >();
}
OUString SAL_CALL
......@@ -94,6 +132,13 @@ SwVbaApplication::getSelection()
uno::Any SAL_CALL
SwVbaApplication::Documents( const uno::Any& index )
{
// FIXME DUMMY just to test calling this somewhere... the dtor is never called
for (auto& i : mvSinks)
{
if (i.is())
i->Call("Quit", uno::Sequence<uno::Any>());
}
uno::Reference< XCollection > xCol( new SwVbaDocuments( this, mxContext ) );
if ( index.hasValue() )
return xCol->Item( index, uno::Any() );
......@@ -159,12 +204,48 @@ void SAL_CALL SwVbaApplication::ShowMe()
// No idea what we should or could do
}
// XInterfaceWithIID
OUString SAL_CALL
SwVbaApplication::getIID()
{
return OUString("{82154421-0FBF-11d4-8313-005004526AB4}");
}
uno::Reference< frame::XModel >
SwVbaApplication::getCurrentDocument()
{
return getCurrentWordDoc( mxContext );
}
// XConnectable
OUString SAL_CALL
SwVbaApplication::GetIIDForClassItselfNotCoclass()
{
return OUString("{82154423-0FBF-11D4-8313-005004526AB4}");
}
TypeAndIID SAL_CALL
SwVbaApplication::GetConnectionPoint()
{
TypeAndIID aResult =
{ word::XApplicationOutgoing::static_type(),
"{82154422-0FBF-11D4-8313-005004526AB4}"
};
return aResult;
}
uno::Reference<XConnectionPoint> SAL_CALL
SwVbaApplication::FindConnectionPoint()
{
uno::Reference<XConnectionPoint> xCP(new SwVbaApplicationOutgoingConnectionPoint(this));
return xCP;
}
// XHelperInterface
OUString
SwVbaApplication::getServiceImplName()
{
......@@ -183,4 +264,24 @@ SwVbaApplication::getServiceNames()
return aServiceNames;
}
SwVbaApplicationOutgoingConnectionPoint::SwVbaApplicationOutgoingConnectionPoint( SwVbaApplication* pApp ) :
mpApp(pApp)
{
}
// SwVbaApplicationOutgoingConnectionPoint
// XConnectionPoint
sal_uInt32 SAL_CALL
SwVbaApplicationOutgoingConnectionPoint::Advise( const uno::Reference< XSink >& Sink )
{
return mpApp->AddSink(Sink);
}
void SAL_CALL
SwVbaApplicationOutgoingConnectionPoint::Unadvise( sal_uInt32 Cookie )
{
mpApp->RemoveSink( Cookie );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
......@@ -19,6 +19,9 @@
#ifndef INCLUDED_SW_SOURCE_UI_VBA_VBAAPPLICATION_HXX
#define INCLUDED_SW_SOURCE_UI_VBA_VBAAPPLICATION_HXX
#include <vector>
#include <ooo/vba/XSink.hpp>
#include <ooo/vba/word/XApplication.hpp>
#include <ooo/vba/word/XDocument.hpp>
#include <ooo/vba/word/XWindow.hpp>
......@@ -34,10 +37,16 @@ typedef cppu::ImplInheritanceHelper< VbaApplicationBase, ooo::vba::word::XApplic
class SwVbaApplication : public SwVbaApplication_BASE
{
// FIXME: We allow just one sink at a time
std::vector<css::uno::Reference< ooo::vba::XSink >> mvSinks;
public:
explicit SwVbaApplication( css::uno::Reference< css::uno::XComponentContext >& m_xContext );
virtual ~SwVbaApplication() override;
sal_uInt32 AddSink( const css::uno::Reference< ooo::vba::XSink >& xSink );
void RemoveSink( sal_uInt32 nNumber );
// XApplication
virtual OUString SAL_CALL getName() override;
virtual css::uno::Reference< ooo::vba::word::XSystem > SAL_CALL getSystem() override;
......@@ -56,6 +65,15 @@ public:
virtual void SAL_CALL setEnableCancelKey( sal_Int32 _enableCancelKey ) override;
virtual float SAL_CALL CentimetersToPoints( float Centimeters ) override;
virtual void SAL_CALL ShowMe() override;
// XInterfaceWithIID
virtual OUString SAL_CALL getIID() override;
// XConnectable
virtual OUString SAL_CALL GetIIDForClassItselfNotCoclass() override;
virtual ov::TypeAndIID SAL_CALL GetConnectionPoint() override;
virtual css::uno::Reference<ov::XConnectionPoint> SAL_CALL FindConnectionPoint() override;
// XHelperInterface
virtual OUString getServiceImplName() override;
virtual css::uno::Sequence<OUString> getServiceNames() override;
......
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