I can call getSelection() directly from my code, but if I make a modify listener and call getSelection() after the event is broadcast, Write hangs. It never returns to my code from the listener. I think this is a bug in OpenOffice, but if anyone can refute that, I'd be glad to hear it. Here's the code:
Code: Select all
/******************************************************************************
Header
******************************************************************************/
// $Header$
/******************************************************************************
Include others
******************************************************************************/
#include "sdkBeg.hpp"
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/lang/EventObject.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/text/XTextDocument.hpp>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <com/sun/star/util/XModifyListener.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <cppuhelper/bootstrap.hxx>
#include <cppuhelper/implbase1.hxx>
#include <sal/main.h> // Required for this to be a free-standing executable.
#include "sdkEnd.hpp"
#include <iostream>
/******************************************************************************
Using
******************************************************************************/
using namespace com::sun::star::beans;
using namespace com::sun::star::container;
using namespace com::sun::star::frame;
using namespace com::sun::star::lang;
using namespace com::sun::star::text;
using namespace com::sun::star::uno;
using namespace com::sun::star::util;
using namespace com::sun::star::view;
/******************************************************************************
ModifyBug
******************************************************************************/
class ModifyBug: public cppu::WeakImplHelper1<com::sun::star::util::XModifyListener> {
protected:
Reference<XComponent> savedXComponent; // needed for testing listener
virtual void SAL_CALL modified(const com::sun::star::lang::EventObject& event)
throw (com::sun::star::uno::RuntimeException);
virtual void SAL_CALL disposing(const com::sun::star::lang::EventObject& event)
throw (com::sun::star::uno::RuntimeException);
Reference<XComponentContext> newXComponentContext();
Reference<XInterface> newDesktop(Reference<XComponentContext> xComponentContext);
Reference<XTextDocument> newXTextDocument(Reference<XInterface> desktop);
public:
ModifyBug() {
}
void run();
};
void SAL_CALL ModifyBug::disposing(const com::sun::star::lang::EventObject& event)
throw (com::sun::star::uno::RuntimeException) {
// TODO: remove listener
}
void getSelections(Reference<XComponent> xComponent) {
Reference<XModel> xModel(xComponent, UNO_QUERY);
Reference<XController> xController = xModel->getCurrentController();
Reference<XSelectionSupplier> xSelectionSupplier(xController, UNO_QUERY);
xSelectionSupplier->getSelection(); // Including this like makes it hang!
}
void SAL_CALL ModifyBug::modified(const com::sun::star::lang::EventObject& event)
throw (com::sun::star::uno::RuntimeException) {
getSelections(savedXComponent);
}
Reference<XComponentContext> ModifyBug::newXComponentContext() {
Reference<XComponentContext> xComponentContext(cppu::bootstrap());
return xComponentContext;
}
Reference<XInterface> ModifyBug::newDesktop(Reference<XComponentContext> xComponentContext) {
Reference<XMultiComponentFactory> xMultiComponentFactory(xComponentContext->getServiceManager(), UNO_QUERY);
Reference<XInterface> desktop = xMultiComponentFactory->createInstanceWithContext(
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")), xComponentContext);
return desktop;
}
Reference<XTextDocument> ModifyBug::newXTextDocument(Reference<XInterface> desktop) {
Reference<XComponentLoader> xComponentLoader(desktop, UNO_QUERY);
Reference<XComponent> document = xComponentLoader->loadComponentFromURL(
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/swriter")),
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, Sequence<PropertyValue>());
Reference<XTextDocument> xTextDocument(document, UNO_QUERY);
return xTextDocument;
}
void ModifyBug::run() {
try {
Reference<XComponentContext> xComponentContext = newXComponentContext();
Reference<XInterface> desktop = newDesktop(xComponentContext);
Reference<XDesktop> xDesktop(desktop, UNO_QUERY);
{
Reference<XTextDocument> xTextDocument = newXTextDocument(desktop);
Reference<XText> xText = xTextDocument->getText();
Reference<XComponent> xComponent(xTextDocument, UNO_QUERY);
Reference<XModifiable> xModifiable(xComponent, UNO_QUERY);
Reference<XModifyBroadcaster> xModifyBroadcaster(xComponent, UNO_QUERY);
savedXComponent = xComponent;
xModifyBroadcaster->addModifyListener(this);
getSelections(savedXComponent); // It (getSelection) can be called directly
getSelections(savedXComponent); // and repeatedly
xText->setString(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("hello"))); // It can _not_ be called indirectly
xModifiable->setModified(sal_True); // It can't be called indirectly like this, either.
xModifyBroadcaster->removeModifyListener(this);
savedXComponent = Reference<XComponent>();
xTextDocument->dispose();
}
xDesktop->terminate();
}
catch (...) {
std::cerr << "Exception..." << std::endl;
}
}
SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
ModifyBug modifyBug;
modifyBug.run();
return 0;
}
/*****************************************************************************/