lokdialog: Changed dialog painting to allow for modal dialogs

Split IDialogNotifier from IDialogRenderable and make SfxViewShell
implement it.

We now just send the dialog UNO command to the backend and wait for core
to emit a 'created' dialog callback which signals dialog creation in the
backend. The client is then supposed to send the paint commands for
rendering the dialog.

Change-Id: I1bfbce83c17955fa0212408376d6bcd1b2d2d1dd
This commit is contained in:
Pranav Kant 2017-11-22 22:25:20 +05:30 committed by Jan Holesovsky
parent 2d508dcc9d
commit 871eb68e14
11 changed files with 138 additions and 131 deletions

View file

@ -44,7 +44,7 @@ public:
/// Emits a LOK_CALLBACK_DIALOG
static void notifyDialog(const OUString& rDialogId,
const OUString& rAction,
const std::vector<vcl::LOKPayloadItem>& rPayload);
const std::vector<vcl::LOKPayloadItem>& rPayload = std::vector<vcl::LOKPayloadItem>());
/// Emits a LOK_CALLBACK_DIALOG_CHILD
static void notifyDialogChild(const OUString& rDialogID, const OUString& rAction, const Point& rPos);
/// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed.

View file

@ -34,6 +34,8 @@
#include <cppuhelper/interfacecontainer.hxx>
#include <sfx2/shell.hxx>
#include <tools/gen.hxx>
#include <vcl/dialog.hxx>
#include <vcl/IDialogRenderable.hxx>
#include <vcl/errcode.hxx>
#include <vcl/jobset.hxx>
#include <o3tl/typed_flags_set.hxx>
@ -140,7 +142,7 @@ template<class T> bool checkSfxViewShell(const SfxViewShell* pShell)
return dynamic_cast<const T*>(pShell) != nullptr;
}
class SFX2_DLLPUBLIC SfxViewShell: public SfxShell, public SfxListener, public OutlinerViewShell
class SFX2_DLLPUBLIC SfxViewShell: public SfxShell, public SfxListener, public OutlinerViewShell, public vcl::IDialogNotifier
{
friend class SfxViewFrame;
friend class SfxBaseController;
@ -151,6 +153,7 @@ friend class SfxPrinterController;
VclPtr<vcl::Window> pWindow;
bool bNoNewWindow;
bool mbPrinterSettingsModified;
std::vector<std::pair<vcl::DialogID, VclPtr<Dialog> > > maOpenedDialogs;
protected:
virtual void Activate(bool IsMDIActivate) override;
@ -219,6 +222,14 @@ public:
virtual SfxShell* GetFormShell() { return nullptr; };
virtual const SfxShell* GetFormShell() const { return nullptr; };
void RegisterDlg(const vcl::DialogID& rDialogId, VclPtr<Dialog> pDlg);
VclPtr<Dialog> GetOpenedDlg(const vcl::DialogID& rDialogId);
void UnregisterDlg(const vcl::DialogID& rDialogId);
// IDialogNotifier
virtual void notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction, const std::vector<vcl::LOKPayloadItem>& rPayload = std::vector<vcl::LOKPayloadItem>()) override;
virtual void notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos) override;
// Focus, KeyInput, Cursor
virtual void ShowCursor( bool bOn = true );
virtual bool KeyInput( const KeyEvent &rKeyEvent );

View file

@ -48,6 +48,7 @@ public:
long& A() { return nA; }
long& B() { return nB; }
TOOLS_DLLPUBLIC rtl::OString toString() const;
TOOLS_DLLPUBLIC friend SvStream& ReadPair( SvStream& rIStream, Pair& rPair );
TOOLS_DLLPUBLIC friend SvStream& WritePair( SvStream& rOStream, const Pair& rPair );

View file

@ -45,6 +45,12 @@ public:
virtual void postDialogChildMouseEvent(const DialogID& rDialogID, int nType, int nX, int nY,
int nCount, int nButtons, int nModifier) = 0;
};
class VCL_DLLPUBLIC IDialogNotifier
{
public:
virtual ~IDialogNotifier() {}
// Callbacks
virtual void notifyDialog(const DialogID& rDialogID,

View file

@ -57,7 +57,7 @@ private:
VclPtr<VclButtonBox> mpActionArea;
VclPtr<VclBox> mpContentArea;
vcl::IDialogRenderable* mpDialogRenderable; // to emit LOK callbacks
vcl::IDialogNotifier* mpDialogNotifier; // to emit LOK callbacks
SAL_DLLPRIVATE void ImplInitDialogData();
SAL_DLLPRIVATE void ImplInitSettings();
@ -73,8 +73,10 @@ private:
protected:
using Window::ImplInit;
SAL_DLLPRIVATE void ImplInit( vcl::Window* pParent, WinBits nStyle, InitFlag eFlag = InitFlag::Default );
OUString maID; // Dialog ID (UNO name) for this dialog (set
// and used by LOK for now)
/// Dialog ID (UNO name) for this dialog
OUString maID;
/// Necessary to register dialog notifier instance to emit LOK callbacks
void registerDialogNotifier(vcl::IDialogNotifier* pDialogNotifier);
public:
SAL_DLLPRIVATE bool IsInClose() const { return mbInClose; }
@ -84,8 +86,6 @@ public:
void CloseFloatingWindow();
Size PaintActiveFloatingWindow(VirtualDevice& rDevice) const;
/// Necessary to register dialog renderable instance to emit LOK callbacks
void registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable, const OUString& aDialogId);
/// Paints the current dialog to the given virtual device
void paintDialog(VirtualDevice& rDevice);
void LogicMouseButtonDown(const MouseEvent& rMouseEvent);

View file

@ -23,6 +23,7 @@
#include <algorithm>
#include <vcl/builder.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/IDialogRenderable.hxx>
#include <unotools/viewoptions.hxx>
#include <appdata.hxx>
@ -36,6 +37,7 @@
#include <sfx2/bindings.hxx>
#include <sfx2/sfxdlg.hxx>
#include <sfx2/itemconnect.hxx>
#include <sfx2/viewsh.hxx>
#include <uitest/sfx_uiobject.hxx>
@ -508,6 +510,18 @@ short SfxTabDialog::Execute()
if ( !m_pTabCtrl->GetPageCount() )
return RET_CANCEL;
Start_Impl();
SfxViewShell* pViewShell = SfxViewShell::Current();
if (pViewShell)
{
pViewShell->RegisterDlg(maID, this);
registerDialogNotifier(static_cast<vcl::IDialogNotifier*>(pViewShell));
const Size aSize = GetOptimalSize();
std::vector<vcl::LOKPayloadItem> aItems;
aItems.emplace_back(std::make_pair("size", aSize.toString()));
pViewShell->notifyDialog(maID, "created", aItems);
}
return TabDialog::Execute();
}

View file

@ -1948,6 +1948,50 @@ Reference< view::XRenderable > SfxViewShell::GetRenderable()
return xRender;
}
void SfxViewShell::notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction, const std::vector<vcl::LOKPayloadItem>& rPayload)
{
SfxLokHelper::notifyDialog(rDialogID, rAction, rPayload);
}
void SfxViewShell::notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos)
{
SfxLokHelper::notifyDialog(rDialogID, rAction);
}
void SfxViewShell::RegisterDlg(const vcl::DialogID& rDialogId, VclPtr<Dialog> pDlg)
{
if (pDlg)
maOpenedDialogs.push_back(std::make_pair(rName, pDlg));
}
VclPtr<Dialog> SfxViewShell::GetOpenedDlg(const vcl::DialogID& rDialogId)
{
if (rName.startsWith(".uno:"))
rName = rName.replaceFirst(".uno:", "");
const auto it = std::find_if(maOpenedDialogs.begin(),
maOpenedDialogs.end(),
[&rDialogId](const std::pair<vcl::DialogID, VclPtr<Dialog>> aItem) {
return rDialogId == aItem.first;
});
Dialog* ret = nullptr;
if (it != maOpenedDialogs.end())
{
ret = it->second;
}
return ret;
}
void SfxViewShell::UnregisterDlg(const OUString& rName)
{
maOpenedDialogs.erase(std::remove_if(maOpenedDialogs.begin(),
maOpenedDialogs.end(),
[&rDialogId](const std::pair<vcl::DialogID, VclPtr<Dialog>> aItem) {
return aItem.first == rDialogId;
}));
}
uno::Reference< datatransfer::clipboard::XClipboardNotifier > SfxViewShell::GetClipboardNotifier()
{
uno::Reference< datatransfer::clipboard::XClipboardNotifier > xClipboardNotifier;

View file

@ -443,12 +443,6 @@ public:
void postDialogChildMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
int nCount, int nButtons, int nModifier) override;
void notifyDialog(const vcl::DialogID& rDialogID,
const OUString& rAction,
const std::vector<vcl::LOKPayloadItem>& rPayload = std::vector<vcl::LOKPayloadItem>()) override;
void notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos) override;
// css::tiledrendering::XTiledRenderable
virtual void SAL_CALL paintTile( const ::css::uno::Any& Parent, ::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, ::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight ) override;

View file

@ -3641,70 +3641,33 @@ void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, ::sal_I
void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice)
{
SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
const SfxSlot* pSlot = pSlotPool->GetUnoSlot(rDialogID);
if (!pSlot)
{
SAL_WARN("lok.dialog", "No slot found for " << rDialogID);
return;
}
SfxChildWindow* pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
if (!pChild)
{
pViewFrame->ToggleChildWindow(pSlot->GetSlotId());
pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
if (!pChild)
{
SAL_WARN("lok.dialog", "Dialog " << rDialogID << " is not supported");
return;
}
}
Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
// register the instance so that vcl::Dialog can emit LOK callbacks
pDlg->registerDialogRenderable(this, rDialogID);
pDlg->paintDialog(rDevice);
SfxViewShell* pViewShell = SfxViewShell::Current();
VclPtr<Dialog> pDlg = pViewShell->GetOpenedDlg(rDialogID);
if (pDlg)
pDlg->paintDialog(rDevice);
}
void SwXTextDocument::getDialogInfo(const vcl::DialogID& rDialogID, OUString& rDialogTitle, int& rWidth, int& rHeight)
{
SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
const SfxSlot* pSlot = pSlotPool->GetUnoSlot(rDialogID);
if (!pSlot)
SfxViewShell* pViewShell = SfxViewShell::Current();
VclPtr<Dialog> pDlg = pViewShell->GetOpenedDlg(rDialogID);
if (pDlg)
{
SAL_WARN("lok.dialog", "No slot found for " << rDialogID);
return;
rDialogTitle = pDlg->GetText();
const Size aSize = pDlg->GetOptimalSize();
rWidth = aSize.getWidth();
rHeight = aSize.getHeight();
}
SfxChildWindow* pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
if (!pChild)
return;
Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
rDialogTitle = pDlg->GetText();
const Size aSize = pDlg->GetOptimalSize();
rWidth = aSize.getWidth();
rHeight = aSize.getHeight();
}
void SwXTextDocument::postDialogKeyEvent(const vcl::DialogID& rDialogID, int nType, int nCharCode, int nKeyCode)
{
SolarMutexGuard aGuard;
// check if dialog is already open
SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
const SfxSlot* pSlot = pSlotPool->GetUnoSlot(rDialogID);
if (!pSlot)
SfxViewShell* pViewShell = SfxViewShell::Current();
VclPtr<Dialog> pDialog = pViewShell->GetOpenedDlg(rDialogID);
if (pDialog)
{
SAL_WARN("lok.dialog", "No slot found for " << rDialogID);
return;
}
SfxChildWindow* pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
if (pChild)
{
Dialog* pDialog = static_cast<Dialog*>(pChild->GetWindow());
KeyEvent aEvent(nCharCode, nKeyCode, 0);
switch (nType)
@ -3727,19 +3690,10 @@ void SwXTextDocument::postDialogMouseEvent(const vcl::DialogID& rDialogID, int n
{
SolarMutexGuard aGuard;
// check if dialog is already open
SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
const SfxSlot* pSlot = pSlotPool->GetUnoSlot(rDialogID);
if (!pSlot)
SfxViewShell* pViewShell = SfxViewShell::Current();
VclPtr<Dialog> pDialog = pViewShell->GetOpenedDlg(rDialogID);
if (pDialog)
{
SAL_WARN("lok.dialog", "No slot found for " << rDialogID);
return;
}
SfxChildWindow* pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
if (pChild)
{
Dialog* pDialog = static_cast<Dialog*>(pChild->GetWindow());
Point aPos(nX , nY);
MouseEvent aEvent(aPos, nCount, MouseEventModifiers::SIMPLECLICK, nButtons, nModifier);
@ -3767,19 +3721,10 @@ void SwXTextDocument::postDialogChildMouseEvent(const vcl::DialogID& rDialogID,
{
SolarMutexGuard aGuard;
// check if dialog is already open
SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
const SfxSlot* pSlot = pSlotPool->GetUnoSlot(rDialogID);
if (!pSlot)
SfxViewShell* pViewShell = SfxViewShell::Current();
VclPtr<Dialog> pDialog = pViewShell->GetOpenedDlg(rDialogID);
if (pDialog)
{
SAL_WARN("lok.dialog", "No slot found for " << rDialogID);
return;
}
SfxChildWindow* pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
if (pChild)
{
Dialog* pDialog = static_cast<Dialog*>(pChild->GetWindow());
Point aPos(nX , nY);
MouseEvent aEvent(aPos, nCount, MouseEventModifiers::SIMPLECLICK, nButtons, nModifier);
@ -3801,36 +3746,16 @@ void SwXTextDocument::postDialogChildMouseEvent(const vcl::DialogID& rDialogID,
}
}
void SwXTextDocument::notifyDialog(const vcl::DialogID& rDialogID,
const OUString& rAction,
const std::vector<vcl::LOKPayloadItem>& rPayload)
{
SfxLokHelper::notifyDialog(rDialogID, rAction, rPayload);
}
void SwXTextDocument::notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos)
{
SfxLokHelper::notifyDialogChild(rDialogID, rAction, rPos);
}
void SwXTextDocument::paintActiveFloatingWindow(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight)
{
SfxViewFrame* pViewFrame = pDocShell->GetView()->GetViewFrame();
SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
const SfxSlot* pSlot = pSlotPool->GetUnoSlot(rDialogID);
if (!pSlot)
SfxViewShell* pViewShell = SfxViewShell::Current();
VclPtr<Dialog> pDialog = pViewShell->GetOpenedDlg(rDialogID);
if (pDialog)
{
SAL_WARN("lok.dialog", "No slot found for " << rDialogID);
return;
const Size aSize = pDialog->PaintActiveFloatingWindow(rDevice);
nWidth = aSize.getWidth();
nHeight = aSize.getHeight();
}
SfxChildWindow* pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
if (!pChild)
return;
Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
const Size aSize = pDlg->PaintActiveFloatingWindow(rDevice);
nWidth = aSize.getWidth();
nHeight = aSize.getHeight();
}
void * SAL_CALL SwXTextDocument::operator new( size_t t) throw()

View file

@ -41,6 +41,16 @@ SvStream& WritePair( SvStream& rOStream, const Pair& rPair )
return rOStream;
}
rtl::OString Pair::toString() const
{
std::stringstream ss;
// Note that this is not just used for debugging output but the
// format is parsed by external code (passed in callbacks to
// LibreOfficeKit clients). So don't change.
ss << A() << ", " << B();
return ss.str().c_str();
}
void tools::Rectangle::SetSize( const Size& rSize )
{
if ( rSize.Width() < 0 )

View file

@ -346,7 +346,7 @@ struct DialogImpl
void Dialog::ImplInitDialogData()
{
mpDialogRenderable = nullptr;
mpDialogNotifier = nullptr;
mpWindowImpl->mbDialog = true;
mpPrevExecuteDlg = nullptr;
mbInExecute = false;
@ -594,9 +594,9 @@ void Dialog::dispose()
xEventBroadcaster->documentEventOccured(aObject);
UITestLogger::getInstance().log("DialogClosed");
if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable)
if (comphelper::LibreOfficeKit::isActive() && mpDialogNotifier)
{
mpDialogRenderable->notifyDialog(maID, "close");
mpDialogNotifier->notifyDialog(maID, "close");
}
SystemWindow::dispose();
@ -789,6 +789,9 @@ bool Dialog::ImplStartExecuteModal()
case Application::DialogCancelMode::Off:
break;
case Application::DialogCancelMode::Silent:
if (ImplGetDialogText(this) == "Character")
break;
SAL_INFO(
"vcl",
"Dialog \"" << ImplGetDialogText(this)
@ -874,12 +877,11 @@ bool Dialog::selectPageByUIXMLDescription(const OString& /*rUIXMLDescription*/)
return true;
}
void Dialog::registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable, const OUString& aDialogId)
void Dialog::registerDialogNotifier(vcl::IDialogNotifier* pDialogNotifier)
{
if (pDialogRenderable && !mpDialogRenderable)
if (pDialogNotifier && !mpDialogNotifier)
{
mpDialogRenderable = pDialogRenderable;
maID = aDialogId;
mpDialogNotifier = pDialogNotifier;
}
}
@ -955,29 +957,29 @@ void Dialog::LogicMouseMoveChild(const MouseEvent& rMouseEvent)
void Dialog::InvalidateFloatingWindow(const Point& rPos)
{
if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable && !maID.isEmpty())
if (comphelper::LibreOfficeKit::isActive() && mpDialogNotifier && !maID.isEmpty())
{
mpDialogRenderable->notifyDialogChild(maID, "invalidate", rPos);
mpDialogNotifier->notifyDialogChild(maID, "invalidate", rPos);
}
}
void Dialog::CloseFloatingWindow()
{
if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable && !maID.isEmpty())
if (comphelper::LibreOfficeKit::isActive() && mpDialogNotifier && !maID.isEmpty())
{
mpDialogRenderable->notifyDialogChild(maID, "close", Point(0, 0));
mpDialogNotifier->notifyDialogChild(maID, "close", Point(0, 0));
}
}
void Dialog::LogicInvalidate(const tools::Rectangle* pRectangle)
{
if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogRenderable && !maID.isEmpty())
if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogNotifier && !maID.isEmpty())
{
std::vector<vcl::LOKPayloadItem> aPayload;
if (pRectangle)
aPayload.push_back(std::make_pair(OString("rectangle"), pRectangle->toString()));
mpDialogRenderable->notifyDialog(maID, "invalidate", aPayload);
mpDialogNotifier->notifyDialog(maID, "invalidate", aPayload);
}
}
@ -1023,9 +1025,9 @@ void Dialog::LOKCursor(const OUString& rAction, const std::vector<vcl::LOKPayloa
{
assert(comphelper::LibreOfficeKit::isActive());
if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogRenderable && !maID.isEmpty())
if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogNotifier && !maID.isEmpty())
{
mpDialogRenderable->notifyDialog(maID, rAction, rPayload);
mpDialogNotifier->notifyDialog(maID, rAction, rPayload);
}
}
@ -1346,9 +1348,9 @@ void Dialog::Resize()
SystemWindow::Resize();
// inform LOK clients
if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogRenderable && !maID.isEmpty())
if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogNotifier && !maID.isEmpty())
{
mpDialogRenderable->notifyDialog(maID, "invalidate");
mpDialogNotifier->notifyDialog(maID, "invalidate");
}
}