[Libreoffice-commits] core.git: Branch 'feature/lok_dialog' - 197 commits - accessibility/inc accessibility/source basctl/source basegfx/source basegfx/test canvas/source canvas/workben chart2/source cli_ure/qa comphelper/source compilerplugins/clang config_host.mk.in configure.ac connectivity/source cppcanvas/inc cppcanvas/source cppuhelper/source cui/inc cui/source cui/uiconfig dbaccess/source desktop/qa desktop/source drawinglayer/inc drawinglayer/source dtrans/source editeng/source embeddedobj/source emfio/inc emfio/source extensions/source external/firebird external/libmspub external/libpng filter/source forms/source formula/source fpicker/source framework/source i18npool/source icon-themes/tango include/basegfx include/comphelper include/cppuhelper include/drawinglayer include/formula include/LibreOfficeKit include/oox include/sal include/sfx2 include/svx include/tools include/vcl ios/CustomTarget_Lo_Xcconfig.mk ios/CustomTarget_Prototype_app.mk ios/CustomTarget_setup.mk ios/DISCLAIMER_WARN ING ios/experimental ios/.gitignore ios/LibreOfficeKit ios/LibreOfficeLight ios/lo.xcconfig.in ios/Module_ios.mk ios/README libreofficekit/Executable_gtktiledviewer.mk libreofficekit/qa libreofficekit/source lingucomponent/source odk/examples odk/source offapi/com officecfg/README officecfg/registry oox/inc oox/source package/source postprocess/Module_postprocess.mk pyuno/Module_pyuno.mk pyuno/PythonTest_pytests.mk pyuno/qa pyuno/source qadevOOo/tests readlicense_oo/license reportdesign/source Repository.mk sal/osl sal/qa sal/rtl sal/textenc sc/inc sc/qa scripting/source sc/source sdext/source sd/inc sd/qa sd/source sd/uiconfig setup_native/source sfx2/source shell/source slideshow/inc slideshow/source slideshow/test solenv/bin soltools/cpp sot/qa sot/source stoc/source svgio/inc svgio/source svtools/source svx/sdi svx/source svx/uiconfig swext/mediawiki sw/inc sw/qa sw/sdi sw/source sw/uiconfig sw/UIConfig_sglobal.mk test/source toolkit/source tools/source ucb/source unoxml/source vbahelper/source vcl/headless vcl/inc vcl/Library_vcl.mk vcl/opengl vcl/osx vcl/qa vcl/README.scheduler vcl/source vcl/unx vcl/win vcl/workben winaccessibility/source wizards/com writerfilter/source writerperfect/qa writerperfect/source xmloff/source xmlscript/source xmlsecurity/source
Pranav Kant
pranavk at collabora.co.uk
Thu Sep 28 04:02:06 UTC 2017
Rebased ref, commits from common ancestor:
commit 937b2720393c4b1e42e39b6b7c796784343dfcd1
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Fri Aug 18 15:26:26 2017 +0530
lokdialog: lok header changes
Change-Id: I1947dc84c91e2e01072fbff3e97aa94d514ecb5a
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index 10e0f0f199d0..d4e891af218a 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -156,6 +156,25 @@ public:
}
/**
+ * Renders a dialog with give dialog id and writes the width and height of the rendered dialog
+ *
+ * Client must truncate pBuffer according to the nWidth and nHeight returned after the call.
+ *
+ * @param pDialogId Unique dialog id to be painted
+ * @param pBuffer Buffer with enough memory allocated to render any dialog
+ * @param nWidth output parameter returning the width of the rendered dialog.
+ * @param nHeight output parameter returning the height of the rendered dialog
+ */
+ void paintDialog(const char* pDialogId,
+ unsigned char* pBuffer,
+ int& nWidth,
+ int& nHeight)
+ {
+ return mpDoc->pClass->paintDialog(mpDoc, pDialogId, pBuffer,
+ &nWidth, &nHeight);
+ }
+
+ /**
* Gets the tile mode: the pixel format used for the pBuffer of paintTile().
*
* @return an element of the LibreOfficeKitTileMode enum.
@@ -236,6 +255,22 @@ public:
}
/**
+ * Posts a mouse event to the dialog with given id.
+ *
+ * @param aDialogId Dialog id where mouse event is to be posted
+ * @param nType Event type, like down, move or up.
+ * @param nX horizontal position in document coordinates
+ * @param nY vertical position in document coordinates
+ * @param nCount number of clicks: 1 for single click, 2 for double click
+ * @param nButtons: which mouse buttons: 1 for left, 2 for middle, 4 right
+ * @param nModifier: which keyboard modifier: (see include/vcl/vclenum.hxx for possible values)
+ */
+ void postDialogMouseEvent(const char* pDialogId, int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
+ {
+ mpDoc->pClass->postDialogMouseEvent(mpDoc, pDialogId, nType, nX, nY, nCount, nButtons, nModifier);
+ }
+
+ /**
* Posts an UNO command to the document.
*
* Example argument string:
commit df962e48a56b4a3ac81d0aca18cc326fb4e9f759
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Wed Aug 16 08:46:40 2017 +0530
CD_DIALOG_INVALIDATE -> DIALOG
Change-Id: Ifdda1c868e19700013a0742a0a547c0a4e040fba
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 936c4d13e244..49b2b62639f4 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -782,7 +782,7 @@ void CallbackFlushHandler::queue(const int type, const char* data)
case LOK_CALLBACK_SET_PART:
case LOK_CALLBACK_TEXT_VIEW_SELECTION:
case LOK_CALLBACK_INVALIDATE_HEADER:
- case LOK_CALLBACK_DIALOG_INVALIDATE:
+ case LOK_CALLBACK_DIALOG:
{
const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(),
[type] (const queue_type::value_type& elem) { return (elem.first == type); });
commit dc995d2262abb378d084e88baba0eacf3c6856ce
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Tue Aug 15 18:54:02 2017 +0530
lokdialog: Smoother mouse move on floating windows
Do away with an early hack to create the floating window with every
invalidate.
This gets rid of persistent blinking when moving the mouse over a
listbox, for example.
Change-Id: Ida9367156605edc9835529f83529363ad97beaee
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index b711c3bc034e..c7f5bfe39e10 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -598,34 +598,34 @@ void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY)
GtvLokDialogPrivate* priv = getPrivate(dialog);
// remove any existing floating windows, for now
- if (priv->pFloatingWin)
- gtk_widget_destroy(priv->pFloatingWin);
-
- priv->pFloatingWin = gtk_window_new(GTK_WINDOW_POPUP);
- GtkWidget* pDrawingArea = gtk_drawing_area_new();
- gtk_container_add(GTK_CONTAINER(priv->pFloatingWin), pDrawingArea);
-
- gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
- gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
-
- gtk_widget_add_events(pDrawingArea,
- GDK_BUTTON_PRESS_MASK
- |GDK_POINTER_MOTION_MASK
- |GDK_BUTTON_RELEASE_MASK
- |GDK_BUTTON_MOTION_MASK);
-
- g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
- g_signal_connect(G_OBJECT(pDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
- g_signal_connect(G_OBJECT(pDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
- g_signal_connect(G_OBJECT(pDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_motion), dialog);
-
- gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
- gtk_window_set_type_hint(GTK_WINDOW(priv->pFloatingWin), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
- gtk_window_set_screen(GTK_WINDOW(priv->pFloatingWin), gtk_window_get_screen(GTK_WINDOW(dialog)));
-
- gtk_widget_show_all(priv->pFloatingWin);
- gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
- gtk_widget_grab_focus(pDrawingArea);
+ if (!priv->pFloatingWin)
+ {
+ priv->pFloatingWin = gtk_window_new(GTK_WINDOW_POPUP);
+ GtkWidget* pDrawingArea = gtk_drawing_area_new();
+ gtk_container_add(GTK_CONTAINER(priv->pFloatingWin), pDrawingArea);
+
+ gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
+ gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
+
+ gtk_widget_add_events(pDrawingArea,
+ GDK_BUTTON_PRESS_MASK
+ |GDK_POINTER_MOTION_MASK
+ |GDK_BUTTON_RELEASE_MASK
+ |GDK_BUTTON_MOTION_MASK);
+
+ g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
+ g_signal_connect(G_OBJECT(pDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
+ g_signal_connect(G_OBJECT(pDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
+ g_signal_connect(G_OBJECT(pDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_motion), dialog);
+
+ gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
+ gtk_window_set_type_hint(GTK_WINDOW(priv->pFloatingWin), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
+ gtk_window_set_screen(GTK_WINDOW(priv->pFloatingWin), gtk_window_get_screen(GTK_WINDOW(dialog)));
+
+ gtk_widget_show_all(priv->pFloatingWin);
+ gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
+ gtk_widget_grab_focus(pDrawingArea);
+ }
// Get the root coords of our new floating window
GdkWindow* pGdkWin = gtk_widget_get_window(GTK_WIDGET(dialog));
@@ -633,6 +633,8 @@ void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY)
int nrY = 0;
gdk_window_get_root_coords(pGdkWin, nX, nY, &nrX, &nrY);
gtk_window_move(GTK_WINDOW(priv->pFloatingWin), nrX, nrY);
+
+ gtk_widget_queue_draw(priv->pFloatingWin);
}
void gtv_lok_dialog_child_close(GtvLokDialog* dialog)
commit 92b2d979e656171170e0449fdb8e73a822079f07
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Tue Aug 15 18:32:40 2017 +0530
lokdialog: Forward mouse button up/down events on border window
This now makes selection of items from list box possible.
Change-Id: I71d068aeb5a3933ef3cbec05eeccf39a87fc829a
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index bf58e214ac9d..989c519435aa 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -919,7 +919,7 @@ void Dialog::LogicMouseButtonDownChild(const MouseEvent& rMouseEvent)
FloatingWindow* pFirstFloat = pSVData->maWinData.mpFirstFloat;
if (pFirstFloat && pFirstFloat->GetParentDialog() == this)
{
- ImplWindowFrameProc(pFirstFloat, SalEvent::ExternalMouseButtonDown, &rMouseEvent);
+ ImplWindowFrameProc(pFirstFloat->ImplGetBorderWindow(), SalEvent::ExternalMouseButtonDown, &rMouseEvent);
}
}
@@ -931,7 +931,7 @@ void Dialog::LogicMouseButtonUpChild(const MouseEvent& rMouseEvent)
FloatingWindow* pFirstFloat = pSVData->maWinData.mpFirstFloat;
if (pFirstFloat && pFirstFloat->GetParentDialog() == this)
{
- ImplWindowFrameProc(pFirstFloat, SalEvent::ExternalMouseButtonUp, &rMouseEvent);
+ ImplWindowFrameProc(pFirstFloat->ImplGetBorderWindow(), SalEvent::ExternalMouseButtonUp, &rMouseEvent);
}
}
@@ -943,7 +943,7 @@ void Dialog::LogicMouseMoveChild(const MouseEvent& rMouseEvent)
FloatingWindow* pFirstFloat = pSVData->maWinData.mpFirstFloat;
if (pFirstFloat && pFirstFloat->GetParentDialog() == this)
{
- ImplWindowFrameProc(pFirstFloat, SalEvent::ExternalMouseMove, &rMouseEvent);
+ ImplWindowFrameProc(pFirstFloat->ImplGetBorderWindow(), SalEvent::ExternalMouseMove, &rMouseEvent);
}
}
commit a3ad63dfa78af0ec88661b8d6b6a903e9f23aea2
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Tue Aug 15 14:23:26 2017 +0530
lokdialog: button press type debug info
Change-Id: I193e0ab82e998905b670f7de73daae784de3ef00
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 1149f50230b6..b711c3bc034e 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -113,7 +113,14 @@ gtv_lok_dialog_signal_button(GtkWidget* pDialogDrawingArea, GdkEventButton* pEve
GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
- g_info("lok_dialog_signal_button: %d, %d (in twips: %d, %d)",
+ std::string aEventType = "unknown";
+ if (pEvent->type == GDK_BUTTON_PRESS)
+ aEventType = "BUTTON_PRESS";
+ else if (pEvent->type == GDK_BUTTON_RELEASE)
+ aEventType = "BUTTON_RELEASE";
+
+ g_info("lok_dialog_signal_button (type: %s): %d, %d (in twips: %d, %d)",
+ aEventType.c_str(),
(int)pEvent->x, (int)pEvent->y,
(int)pixelToTwip(pEvent->x),
(int)pixelToTwip(pEvent->y));
@@ -197,7 +204,7 @@ gtv_lok_dialog_signal_motion(GtkWidget* pDialogDrawingArea, GdkEventButton* pEve
GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
- g_info("lok_dialog_signal_button: %d, %d (in twips: %d, %d)",
+ g_info("lok_dialog_signal_motion: %d, %d (in twips: %d, %d)",
(int)pEvent->x, (int)pEvent->y,
(int)pixelToTwip(pEvent->x),
(int)pixelToTwip(pEvent->y));
@@ -478,7 +485,14 @@ gtv_lok_dialog_floating_win_signal_button(GtkWidget* /*pDialogChildDrawingArea*/
GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
- g_info("lok_dialog_floating_win_signal_button: %d, %d (in twips: %d, %d)",
+ std::string aEventType = "unknown";
+ if (pEvent->type == GDK_BUTTON_PRESS)
+ aEventType = "BUTTON_PRESS";
+ else if (pEvent->type == GDK_BUTTON_RELEASE)
+ aEventType = "BUTTON_RELEASE";
+
+ g_info("lok_dialog_floating_win_signal_button (type: %s): %d, %d (in twips: %d, %d)",
+ aEventType.c_str(),
(int)pEvent->x, (int)pEvent->y,
(int)pixelToTwip(pEvent->x),
(int)pixelToTwip(pEvent->y));
commit 83c80d7e1297d9eded9ad086ec2622d3df83dce1
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Tue Aug 15 14:04:46 2017 +0530
lokdialog: Proper floating window invalidation on mouse move
diff --git a/include/vcl/floatwin.hxx b/include/vcl/floatwin.hxx
index fc7df3ada424..f0faa3c3e260 100644
--- a/include/vcl/floatwin.hxx
+++ b/include/vcl/floatwin.hxx
@@ -129,6 +129,7 @@ public:
SAL_DLLPRIVATE tools::Rectangle& ImplGetItemEdgeClipRect();
SAL_DLLPRIVATE bool ImplIsInPrivatePopupMode() const { return mbInPopupMode; }
virtual void doDeferredInit(WinBits nBits) override;
+ virtual void LogicInvalidate(const tools::Rectangle* pRectangle) override;
public:
explicit FloatingWindow(vcl::Window* pParent, WinBits nStyle);
diff --git a/vcl/source/control/ctrl.cxx b/vcl/source/control/ctrl.cxx
index 3bd877ea7162..38509814f5b0 100644
--- a/vcl/source/control/ctrl.cxx
+++ b/vcl/source/control/ctrl.cxx
@@ -23,6 +23,7 @@
#include <vcl/svapp.hxx>
#include <vcl/event.hxx>
#include <vcl/ctrl.hxx>
+#include <vcl/floatwin.hxx>
#include <vcl/decoview.hxx>
#include <vcl/dialog.hxx>
#include <vcl/salnativewidgets.hxx>
@@ -420,7 +421,20 @@ void Control::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
// ignore all of those
if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isDialogPainting())
{
- // For now just invalidate the whole dialog
+ // If parent is a floating window, trigger an invalidate there
+ vcl::Window* pWindow = this;
+ while (pWindow)
+ {
+ if (pWindow->ImplIsFloatingWindow())
+ {
+ dynamic_cast<FloatingWindow*>(pWindow)->LogicInvalidate(nullptr);
+ return;
+ }
+
+ pWindow = pWindow->GetParent();
+ }
+
+ // otherwise, for now, just invalidate the whole dialog
Dialog* pParentDlg = GetParentDialog();
if (pParentDlg)
pParentDlg->LogicInvalidate(nullptr);
diff --git a/vcl/source/window/floatwin.cxx b/vcl/source/window/floatwin.cxx
index 44ce96c42843..2d117ca6e7e1 100644
--- a/vcl/source/window/floatwin.cxx
+++ b/vcl/source/window/floatwin.cxx
@@ -585,6 +585,17 @@ bool FloatingWindow::EventNotify( NotifyEvent& rNEvt )
return bRet;
}
+void FloatingWindow::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
+{
+ Dialog* pParentDlg = GetParentDialog();
+ SAL_DEBUG("FloatingWindow::LogicInvalidate");
+ if (pParentDlg)
+ {
+ SAL_DEBUG("emitiign FloatingWindow::LogicInvalidate");
+ pParentDlg->InvalidateFloatingWindow(mpImplData->maPos);
+ }
+}
+
void FloatingWindow::StateChanged( StateChangedType nType )
{
if (nType == StateChangedType::InitShow)
@@ -593,7 +604,6 @@ void FloatingWindow::StateChanged( StateChangedType nType )
}
SystemWindow::StateChanged( nType );
-
if (nType == StateChangedType::InitShow && IsVisible())
{
Dialog* pParentDlg = GetParentDialog();
commit f150bca5ccb077a365216c12207073b930077318
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Thu Aug 10 17:24:40 2017 +0530
lokdialog: Emit dialog close callback upon dialog close
Change-Id: I4ccef76cc3b2926dd8916f825671bb732e101027
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index 9fe49aaf350e..8ad25f42a98c 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -291,8 +291,8 @@ void LOKDocViewSigHandlers::dialog(LOKDocView* pDocView, gchar* pPayload, gpoint
//std::string aDialogId = aRoot.get<std::string>("dialogId");
std::string aAction = aRoot.get<std::string>("action");
- // we only understand 'invalidate' as of now
- if (aAction != "invalidate")
+ // we only understand 'invalidate' and 'close' as of now
+ if (aAction != "invalidate" && aAction != "close")
return;
// temporary hack to invalidate all open dialogs
@@ -300,43 +300,48 @@ void LOKDocViewSigHandlers::dialog(LOKDocView* pDocView, gchar* pPayload, gpoint
GList* pIt = nullptr;
for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
{
- gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data));
+ if (aAction == "close")
+ {
+ gtk_widget_destroy(GTK_WIDGET(pIt->data));
+ }
+ else if (aAction == "invalidate")
+ gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data));
}
}
void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, gpointer)
{
- GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
-
- std::stringstream aStream(pPayload);
- boost::property_tree::ptree aRoot;
- boost::property_tree::read_json(aStream, aRoot);
- //std::string aDialogId = aRoot.get<std::string>("dialogId");
- std::string aAction = aRoot.get<std::string>("action");
- std::string aPos = aRoot.get<std::string>("position");
- gchar** ppCoordinates = g_strsplit(aPos.c_str(), ", ", 2);
- gchar** ppCoordinate = ppCoordinates;
- int nX = 0;
- int nY = 0;
-
- if (*ppCoordinate)
- nX = atoi(*ppCoordinate);
- ++ppCoordinate;
- if (*ppCoordinate)
- nY = atoi(*ppCoordinate);
-
- g_strfreev(ppCoordinates);
-
- // temporary hack to invalidate/close floating window of all opened dialogs
- GList* pChildWins = gtv_application_window_get_all_child_windows(window);
- GList* pIt = nullptr;
- for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
- {
- if (aAction == "invalidate")
- gtv_lok_dialog_child_invalidate(GTV_LOK_DIALOG(pIt->data), nX, nY);
- else if (aAction == "close")
- gtv_lok_dialog_child_close(GTV_LOK_DIALOG(pIt->data));
- }
+ GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
+
+ std::stringstream aStream(pPayload);
+ boost::property_tree::ptree aRoot;
+ boost::property_tree::read_json(aStream, aRoot);
+ //std::string aDialogId = aRoot.get<std::string>("dialogId");
+ std::string aAction = aRoot.get<std::string>("action");
+ std::string aPos = aRoot.get<std::string>("position");
+ gchar** ppCoordinates = g_strsplit(aPos.c_str(), ", ", 2);
+ gchar** ppCoordinate = ppCoordinates;
+ int nX = 0;
+ int nY = 0;
+
+ if (*ppCoordinate)
+ nX = atoi(*ppCoordinate);
+ ++ppCoordinate;
+ if (*ppCoordinate)
+ nY = atoi(*ppCoordinate);
+
+ g_strfreev(ppCoordinates);
+
+ // temporary hack to invalidate/close floating window of all opened dialogs
+ GList* pChildWins = gtv_application_window_get_all_child_windows(window);
+ GList* pIt = nullptr;
+ for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
+ {
+ if (aAction == "invalidate")
+ gtv_lok_dialog_child_invalidate(GTV_LOK_DIALOG(pIt->data), nX, nY);
+ else if (aAction == "close")
+ gtv_lok_dialog_child_close(GTV_LOK_DIALOG(pIt->data));
+ }
}
gboolean LOKDocViewSigHandlers::configureEvent(GtkWidget* pWidget, GdkEventConfigure* /*pEvent*/, gpointer /*pData*/)
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
index b871d93667f9..6ca78a61a2b2 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-signal-handlers.cxx
@@ -293,6 +293,16 @@ void changePartMode( GtkWidget* pSelector, gpointer /* pItem */ )
static gboolean deleteLokDialog(GtkWidget* pWidget, GdkEvent* /*event*/, gpointer userdata)
{
GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(userdata);
+ g_info("deletLokDialog");
+ gtv_application_window_unregister_child_window(window, GTK_WINDOW(pWidget));
+
+ return FALSE;
+}
+
+static gboolean destroyLokDialog(GtkWidget* pWidget, gpointer userdata)
+{
+ GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(userdata);
+ g_info("destroyLokDialog");
gtv_application_window_unregister_child_window(window, GTK_WINDOW(pWidget));
return FALSE;
@@ -304,9 +314,11 @@ void openLokDialog( GtkWidget* pSelector, gpointer /*pItem*/ )
gchar* pDialogId = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(pSelector));
GtkWidget* pDialog = gtv_lok_dialog_new(LOK_DOC_VIEW(window->lokdocview), pDialogId);
gtv_application_window_register_child_window(window, GTK_WINDOW(pDialog));
+ g_signal_connect(pDialog, "destroy", G_CALLBACK(destroyLokDialog), window);
g_signal_connect(pDialog, "delete-event", G_CALLBACK(deleteLokDialog), window);
g_free(pDialogId);
+ g_info("openLokDialog");
gtk_window_set_resizable(GTK_WINDOW(pDialog), false);
gtk_widget_show_all(GTK_WIDGET(pDialog));
gtk_window_present(GTK_WINDOW(pDialog));
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index eed393f3e298..bf58e214ac9d 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -588,6 +588,11 @@ void Dialog::dispose()
xEventBroadcaster->documentEventOccured(aObject);
UITestLogger::getInstance().log("DialogClosed");
+ if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable)
+ {
+ mpDialogRenderable->notifyDialog(maID, "close");
+ }
+
SystemWindow::dispose();
}
commit 1a7e0da2ad84e75a6b53a0dcf2ff3ef00a71493d
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Thu Aug 10 16:44:06 2017 +0530
Change CB_DIALOG_INVALIDATE to CB_DIALOG
We can specify whether it is an invalidation or something else in the
payload.
Change-Id: I95c5fc0a0a88b5277eaa93c8d1f9b937bddce7b3
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 4c70560690da..62b9faf7ecb4 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -525,7 +525,7 @@ typedef enum
/**
* Dialog invalidation
*/
- LOK_CALLBACK_DIALOG_INVALIDATE = 36,
+ LOK_CALLBACK_DIALOG = 36,
/**
* Invalidation corresponding to dialog's children.
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index b57f30a0ccba..432628c89132 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -40,8 +40,8 @@ public:
static void notifyOtherViews(SfxViewShell* pThisView, int nType, const OString& rKey, const OString& rPayload);
/// Same as notifyOtherViews(), but works on a selected "other" view, not on all of them.
static void notifyOtherView(SfxViewShell* pThisView, SfxViewShell const* pOtherView, int nType, const OString& rKey, const OString& rPayload);
- /// Emits a LOK_CALLBACK_DIALOG_INVALIDATE
- static void notifyDialogInvalidation(const OUString& rPayload);
+ /// Emits a LOK_CALLBACK_DIALOG
+ static void notifyDialog(const OUString& rPayload, const OUString& rAction);
/// 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.
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index 561f910987c6..02e959ea6fad 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -46,7 +46,7 @@ public:
int nCount, int nButtons, int nModifier) = 0;
// Callbacks
- virtual void notifyDialogInvalidation(const DialogID& rDialogID) = 0;
+ virtual void notifyDialog(const DialogID& rDialogID, const OUString& rAction) = 0;
virtual void notifyDialogChild(const DialogID& rDialogID, const OUString& rAction, const Point& rPos) = 0;
};
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
index 8a5ff9a56d37..85c5b38466af 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
@@ -314,7 +314,7 @@ static void setupDocView(GtvApplicationWindow* window)
g_signal_connect(window->lokdocview, "formula-changed", G_CALLBACK(LOKDocViewSigHandlers::formulaChanged), nullptr);
g_signal_connect(window->lokdocview, "password-required", G_CALLBACK(LOKDocViewSigHandlers::passwordRequired), nullptr);
g_signal_connect(window->lokdocview, "comment", G_CALLBACK(LOKDocViewSigHandlers::comment), nullptr);
- g_signal_connect(window->lokdocview, "dialog-invalidate", G_CALLBACK(LOKDocViewSigHandlers::dialogInvalidate), nullptr);
+ g_signal_connect(window->lokdocview, "dialog", G_CALLBACK(LOKDocViewSigHandlers::dialog), nullptr);
g_signal_connect(window->lokdocview, "dialog-child", G_CALLBACK(LOKDocViewSigHandlers::dialogChild), nullptr);
g_signal_connect(window->lokdocview, "configure-event", G_CALLBACK(LOKDocViewSigHandlers::configureEvent), nullptr);
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index 3acd6b78e234..9fe49aaf350e 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -281,10 +281,19 @@ void LOKDocViewSigHandlers::comment(LOKDocView* pDocView, gchar* pComment, gpoin
}
}
-void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* pPayload, gpointer)
+void LOKDocViewSigHandlers::dialog(LOKDocView* pDocView, gchar* pPayload, gpointer)
{
GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
-// GtkWindow* pDialog = gtv_application_window_get_child_window_by_id(window, pDialogId);
+
+ std::stringstream aStream(pPayload);
+ boost::property_tree::ptree aRoot;
+ boost::property_tree::read_json(aStream, aRoot);
+ //std::string aDialogId = aRoot.get<std::string>("dialogId");
+ std::string aAction = aRoot.get<std::string>("action");
+
+ // we only understand 'invalidate' as of now
+ if (aAction != "invalidate")
+ return;
// temporary hack to invalidate all open dialogs
GList* pChildWins = gtv_application_window_get_all_child_windows(window);
@@ -293,11 +302,6 @@ void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* pPaylo
{
gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pIt->data));
}
-/* if (pDialog)
- {
- gtv_lok_dialog_invalidate(GTV_LOK_DIALOG(pDialog));
- }
-*/
}
void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, gpointer)
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
index a455c3f1fc4c..54f54b396bf3 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
@@ -25,7 +25,7 @@ namespace LOKDocViewSigHandlers {
void formulaChanged(LOKDocView* pDocView, char* pPayload, gpointer);
void passwordRequired(LOKDocView* pDocView, char* pUrl, gboolean bModify, gpointer);
void comment(LOKDocView* pDocView, gchar* pComment, gpointer);
- void dialogInvalidate(LOKDocView* pDocView, gchar* pDialogId, gpointer);
+ void dialog(LOKDocView* pDocView, gchar* pDialogId, gpointer);
void dialogChild(LOKDocView* pDocView, gchar* pPayload, gpointer);
gboolean configureEvent(GtkWidget* pWidget, GdkEventConfigure* pEvent, gpointer pData);
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 1bdb80c754ed..d2bfefcc089e 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -279,7 +279,7 @@ enum
PASSWORD_REQUIRED,
COMMENT,
RULER,
- DIALOG_INVALIDATE,
+ DIALOG,
DIALOG_CHILD,
LAST_SIGNAL
@@ -438,8 +438,8 @@ callbackTypeToString (int nType)
return "LOK_CALLBACK_COMMENT";
case LOK_CALLBACK_RULER_UPDATE:
return "LOK_CALLBACK_RULER_UPDATE";
- case LOK_CALLBACK_DIALOG_INVALIDATE:
- return "LOK_CALLBACK_DIALOG_INVALIDATE";
+ case LOK_CALLBACK_DIALOG:
+ return "LOK_CALLBACK_DIALOG";
case LOK_CALLBACK_DIALOG_CHILD:
return "LOK_CALLBACK_DIALOG_CHILD";
}
@@ -1414,8 +1414,9 @@ callback (gpointer pData)
break;
case LOK_CALLBACK_RULER_UPDATE:
g_signal_emit(pCallback->m_pDocView, doc_view_signals[RULER], 0, pCallback->m_aPayload.c_str());
- case LOK_CALLBACK_DIALOG_INVALIDATE:
- g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG_INVALIDATE], 0, pCallback->m_aPayload.c_str());
+ break;
+ case LOK_CALLBACK_DIALOG:
+ g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG], 0, pCallback->m_aPayload.c_str());
break;
case LOK_CALLBACK_DIALOG_CHILD:
g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG_CHILD], 0, pCallback->m_aPayload.c_str());
@@ -3222,8 +3223,8 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass)
* @pDocView: the #LOKDocView on which the signal is emitted
* @pDialogId: The uno command for the dialog (dialog ID)
*/
- doc_view_signals[DIALOG_INVALIDATE] =
- g_signal_new("dialog-invalidate",
+ doc_view_signals[DIALOG] =
+ g_signal_new("dialog",
G_TYPE_FROM_CLASS(pGObjectClass),
G_SIGNAL_RUN_FIRST,
0,
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index c6e9d57027b2..08a89eac49a8 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -144,15 +144,19 @@ void SfxLokHelper::notifyOtherViews(SfxViewShell* pThisView, int nType, const OS
}
}
-void SfxLokHelper::notifyDialogInvalidation(const OUString& rDialogID)
+void SfxLokHelper::notifyDialog(const OUString& rDialogID, const OUString& rAction)
{
if (SfxLokHelper::getViewsCount() <= 0)
return;
SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+ const OString aPayload = OString("{ \"dialogId\": \"") + OUStringToOString(rDialogID, RTL_TEXTENCODING_UTF8).getStr() +
+ OString("\", \"action\": \"") + OUStringToOString(rAction, RTL_TEXTENCODING_UTF8).getStr() +
+ + "\" }";
+
while (pViewShell)
{
- pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DIALOG_INVALIDATE, OUStringToOString(rDialogID, RTL_TEXTENCODING_UTF8).getStr());
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DIALOG, aPayload.getStr());
pViewShell = SfxViewShell::GetNext(*pViewShell);
}
}
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index a803a6aa8e16..868dbabbcb72 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -442,7 +442,7 @@ public:
void postDialogChildMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
int nCount, int nButtons, int nModifier) override;
- void notifyDialogInvalidation(const vcl::DialogID& rDialogID) override;
+ void notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction) override;
void notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos) override;
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 9b6a41effeab..b3dbe43df31d 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3783,9 +3783,9 @@ void SwXTextDocument::postDialogChildMouseEvent(const vcl::DialogID& rDialogID,
}
}
-void SwXTextDocument::notifyDialogInvalidation(const vcl::DialogID& rDialogID)
+void SwXTextDocument::notifyDialog(const vcl::DialogID& rDialogID, const OUString& rAction)
{
- SfxLokHelper::notifyDialogInvalidation(rDialogID);
+ SfxLokHelper::notifyDialog(rDialogID, rAction);
}
void SwXTextDocument::notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos)
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 6a2338e33494..eed393f3e298 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -964,7 +964,7 @@ void Dialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
{
if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogRenderable && !maID.isEmpty())
{
- mpDialogRenderable->notifyDialogInvalidation(maID);
+ mpDialogRenderable->notifyDialog(maID, "invalidate");
}
}
commit fccdf8749d9ac0cb22744e9b4ce502e9ecb80d96
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Fri Aug 4 11:17:06 2017 +0530
lokdialog: Mouse events for dialog floating child windows
It doesn't work as of now. The mosue events seems to hang the floating
window completely.
Change-Id: I06a081835d246f752e57f8cc289162ed31fc91d4
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index ca1c61cd84b9..936c4d13e244 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -561,6 +561,14 @@ static void doc_postDialogMouseEvent (LibreOfficeKitDocument* pThis,
int nCount,
int nButtons,
int nModifier);
+static void doc_postDialogChildMouseEvent (LibreOfficeKitDocument* pThis,
+ const char* pDialogId,
+ int nType,
+ int nX,
+ int nY,
+ int nCount,
+ int nButtons,
+ int nModifier);
static void doc_postUnoCommand(LibreOfficeKitDocument* pThis,
const char* pCommand,
const char* pArguments,
@@ -633,6 +641,7 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
m_pDocumentClass->postDialogKeyEvent = doc_postDialogKeyEvent;
m_pDocumentClass->postMouseEvent = doc_postMouseEvent;
m_pDocumentClass->postDialogMouseEvent = doc_postDialogMouseEvent;
+ m_pDocumentClass->postDialogChildMouseEvent = doc_postDialogChildMouseEvent;
m_pDocumentClass->postUnoCommand = doc_postUnoCommand;
m_pDocumentClass->setTextSelection = doc_setTextSelection;
m_pDocumentClass->getTextSelection = doc_getTextSelection;
@@ -2286,6 +2295,21 @@ static void doc_postDialogMouseEvent(LibreOfficeKitDocument* pThis, const char*
pDoc->postDialogMouseEvent(aDialogID, nType, nX, nY, nCount, nButtons, nModifier);
}
+static void doc_postDialogChildMouseEvent(LibreOfficeKitDocument* pThis, const char* pDialogId, int nType, int nX, int nY, int nCount, int nButtons, int nModifier)
+{
+ SolarMutexGuard aGuard;
+
+ IDialogRenderable* pDoc = getDialogRenderable(pThis);
+ if (!pDoc)
+ {
+ gImpl->maLastExceptionMsg = "Document doesn't support dialog rendering";
+ return;
+ }
+
+ vcl::DialogID aDialogID = OUString::createFromAscii(pDialogId);
+ pDoc->postDialogChildMouseEvent(aDialogID, nType, nX, nY, nCount, nButtons, nModifier);
+}
+
static void doc_setTextSelection(LibreOfficeKitDocument* pThis, int nType, int nX, int nY)
{
SolarMutexGuard aGuard;
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 529a1336ca76..05c8eff15316 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -288,6 +288,16 @@ struct _LibreOfficeKitDocumentClass
int nButtons,
int nModifier);
+ /// WIP
+ void (*postDialogChildMouseEvent) (LibreOfficeKitDocument* pThis,
+ const char* pDialogId,
+ int nType,
+ int nX,
+ int nY,
+ int nCount,
+ int nButtons,
+ int nModifier);
+
#endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
};
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index 351839e46d02..561f910987c6 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -42,6 +42,9 @@ public:
virtual void postDialogMouseEvent(const DialogID& rDialogID, int nType, int nX, int nY,
int nCount, int nButtons, int nModifier) = 0;
+ virtual void postDialogChildMouseEvent(const DialogID& rDialogID, int nType, int nX, int nY,
+ int nCount, int nButtons, int nModifier) = 0;
+
// Callbacks
virtual void notifyDialogInvalidation(const DialogID& rDialogID) = 0;
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index 5ab85be1842e..6cea3b193ec2 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -91,6 +91,9 @@ public:
void LogicMouseButtonDown(const MouseEvent& rMouseEvent);
void LogicMouseButtonUp(const MouseEvent& rMouseEvent);
void LogicMouseMove(const MouseEvent& rMouseEvent);
+ void LogicMouseButtonDownChild(const MouseEvent& rMouseEvent);
+ void LogicMouseButtonUpChild(const MouseEvent& rMouseEvent);
+ void LogicMouseMoveChild(const MouseEvent& rMouseEvent);
void LOKKeyInput(const KeyEvent& rKeyEvent);
void LOKKeyUp(const KeyEvent& rKeyEvent);
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index e37f9f274062..1149f50230b6 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -34,11 +34,18 @@ struct GtvLokDialogPrivate
GtkWidget* pDialogDrawingArea;
GtkWidget* pFloatingWin;
+ // state for dialog
guint32 m_nLastButtonPressTime;
guint32 m_nLastButtonReleaseTime;
guint32 m_nKeyModifier;
guint32 m_nLastButtonPressed;
+ // state for child floating windows
+ guint32 m_nChildLastButtonPressTime;
+ guint32 m_nChildLastButtonReleaseTime;
+ guint32 m_nChildKeyModifier;
+ guint32 m_nChildLastButtonPressed;
+
gchar* dialogid;
};
@@ -462,6 +469,115 @@ gtv_lok_dialog_invalidate(GtvLokDialog* dialog)
gtk_widget_queue_draw(priv->pDialogDrawingArea);
}
+static gboolean
+gtv_lok_dialog_floating_win_signal_button(GtkWidget* /*pDialogChildDrawingArea*/, GdkEventButton* pEvent, gpointer userdata)
+{
+ GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
+ GtvLokDialogPrivate* priv = getPrivate(pDialog);
+
+ GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
+ LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
+
+ g_info("lok_dialog_floating_win_signal_button: %d, %d (in twips: %d, %d)",
+ (int)pEvent->x, (int)pEvent->y,
+ (int)pixelToTwip(pEvent->x),
+ (int)pixelToTwip(pEvent->y));
+
+ switch (pEvent->type)
+ {
+ case GDK_BUTTON_PRESS:
+ {
+ int nCount = 1;
+ if ((pEvent->time - priv->m_nChildLastButtonPressTime) < 250)
+ nCount++;
+ priv->m_nChildLastButtonPressTime = pEvent->time;
+ int nEventButton = 0;
+ switch (pEvent->button)
+ {
+ case 1:
+ nEventButton = MOUSE_LEFT;
+ break;
+ case 2:
+ nEventButton = MOUSE_MIDDLE;
+ break;
+ case 3:
+ nEventButton = MOUSE_RIGHT;
+ break;
+ }
+ priv->m_nChildLastButtonPressed = nEventButton;
+ pDocument->pClass->postDialogChildMouseEvent(pDocument,
+ priv->dialogid,
+ LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ (pEvent->x),
+ (pEvent->y),
+ nCount,
+ nEventButton,
+ priv->m_nChildKeyModifier);
+
+ break;
+ }
+ case GDK_BUTTON_RELEASE:
+ {
+ int nCount = 1;
+ if ((pEvent->time - priv->m_nChildLastButtonReleaseTime) < 250)
+ nCount++;
+ priv->m_nChildLastButtonReleaseTime = pEvent->time;
+ int nEventButton = 0;
+ switch (pEvent->button)
+ {
+ case 1:
+ nEventButton = MOUSE_LEFT;
+ break;
+ case 2:
+ nEventButton = MOUSE_MIDDLE;
+ break;
+ case 3:
+ nEventButton = MOUSE_RIGHT;
+ break;
+ }
+ priv->m_nChildLastButtonPressed = nEventButton;
+ pDocument->pClass->postDialogChildMouseEvent(pDocument,
+ priv->dialogid,
+ LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ (pEvent->x),
+ (pEvent->y),
+ nCount,
+ nEventButton,
+ priv->m_nChildKeyModifier);
+ break;
+ }
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+gtv_lok_dialog_floating_win_signal_motion(GtkWidget* /*pDialogDrawingArea*/, GdkEventButton* pEvent, gpointer userdata)
+{
+ GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
+ GtvLokDialogPrivate* priv = getPrivate(pDialog);
+
+ GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
+ LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
+
+ g_info("lok_dialog_floating_win_signal_motion: %d, %d (in twips: %d, %d)",
+ (int)pEvent->x, (int)pEvent->y,
+ (int)pixelToTwip(pEvent->x),
+ (int)pixelToTwip(pEvent->y));
+
+ pDocument->pClass->postDialogChildMouseEvent(pDocument,
+ priv->dialogid,
+ LOK_MOUSEEVENT_MOUSEMOVE,
+ (pEvent->x),
+ (pEvent->y),
+ 1,
+ priv->m_nChildLastButtonPressed,
+ priv->m_nChildKeyModifier);
+
+ return FALSE;
+}
+
void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY)
{
g_info("Dialog's floating window invalidate");
@@ -477,7 +593,17 @@ void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY)
gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
+
+ gtk_widget_add_events(pDrawingArea,
+ GDK_BUTTON_PRESS_MASK
+ |GDK_POINTER_MOTION_MASK
+ |GDK_BUTTON_RELEASE_MASK
+ |GDK_BUTTON_MOTION_MASK);
+
g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
+ g_signal_connect(G_OBJECT(pDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
+ g_signal_connect(G_OBJECT(pDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
+ g_signal_connect(G_OBJECT(pDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_motion), dialog);
gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
gtk_window_set_type_hint(GTK_WINDOW(priv->pFloatingWin), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
@@ -485,6 +611,7 @@ void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY)
gtk_widget_show_all(priv->pFloatingWin);
gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
+ gtk_widget_grab_focus(pDrawingArea);
// Get the root coords of our new floating window
GdkWindow* pGdkWin = gtk_widget_get_window(GTK_WIDGET(dialog));
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index 3d269dcadc03..a803a6aa8e16 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -439,6 +439,9 @@ public:
void postDialogMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
int nCount, int nButtons, int nModifier) override;
+ void postDialogChildMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
+ int nCount, int nButtons, int nModifier) override;
+
void notifyDialogInvalidation(const vcl::DialogID& rDialogID) override;
void notifyDialogChild(const vcl::DialogID& rDialogID, const OUString& rAction, const Point& rPos) override;
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index aa685ac1ea72..9b6a41effeab 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3743,6 +3743,46 @@ void SwXTextDocument::postDialogMouseEvent(const vcl::DialogID& rDialogID, int n
}
}
+
+void SwXTextDocument::postDialogChildMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
+ int nCount, int nButtons, int nModifier)
+{
+ 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)
+ {
+ 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);
+
+ switch (nType)
+ {
+ case LOK_MOUSEEVENT_MOUSEBUTTONDOWN:
+ pDialog->LogicMouseButtonDownChild(aEvent);
+ break;
+ case LOK_MOUSEEVENT_MOUSEBUTTONUP:
+ pDialog->LogicMouseButtonUpChild(aEvent);
+ break;
+ case LOK_MOUSEEVENT_MOUSEMOVE:
+ pDialog->LogicMouseMoveChild(aEvent);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ }
+}
+
void SwXTextDocument::notifyDialogInvalidation(const vcl::DialogID& rDialogID)
{
SfxLokHelper::notifyDialogInvalidation(rDialogID);
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index b626f7a8cbd6..6a2338e33494 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -906,6 +906,42 @@ Size Dialog::PaintActiveFloatingWindow(VirtualDevice& rDevice)
return aRet;
}
+void Dialog::LogicMouseButtonDownChild(const MouseEvent& rMouseEvent)
+{
+ assert(comphelper::LibreOfficeKit::isActive());
+
+ ImplSVData* pSVData = ImplGetSVData();
+ FloatingWindow* pFirstFloat = pSVData->maWinData.mpFirstFloat;
+ if (pFirstFloat && pFirstFloat->GetParentDialog() == this)
+ {
+ ImplWindowFrameProc(pFirstFloat, SalEvent::ExternalMouseButtonDown, &rMouseEvent);
+ }
+}
+
+void Dialog::LogicMouseButtonUpChild(const MouseEvent& rMouseEvent)
+{
+ assert(comphelper::LibreOfficeKit::isActive());
+
+ ImplSVData* pSVData = ImplGetSVData();
+ FloatingWindow* pFirstFloat = pSVData->maWinData.mpFirstFloat;
+ if (pFirstFloat && pFirstFloat->GetParentDialog() == this)
+ {
+ ImplWindowFrameProc(pFirstFloat, SalEvent::ExternalMouseButtonUp, &rMouseEvent);
+ }
+}
+
+void Dialog::LogicMouseMoveChild(const MouseEvent& rMouseEvent)
+{
+ assert(comphelper::LibreOfficeKit::isActive());
+
+ ImplSVData* pSVData = ImplGetSVData();
+ FloatingWindow* pFirstFloat = pSVData->maWinData.mpFirstFloat;
+ if (pFirstFloat && pFirstFloat->GetParentDialog() == this)
+ {
+ ImplWindowFrameProc(pFirstFloat, SalEvent::ExternalMouseMove, &rMouseEvent);
+ }
+}
+
void Dialog::InvalidateFloatingWindow(const Point& rPos)
{
SAL_DEBUG("Dialog:: Invalidate Floating window");
commit e2c895e3a35acf70d3dae4d5538474eed5421ec5
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Fri Aug 4 00:02:48 2017 +0530
lokdialog: drawing area needs to have focus to capture key events
With this, key events successfully work now.
Change-Id: I6dc6aff91dea08fcbc7ab840a77e2542ab9048ce
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 6b19ddc506c0..e37f9f274062 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -110,7 +110,7 @@ gtv_lok_dialog_signal_button(GtkWidget* pDialogDrawingArea, GdkEventButton* pEve
(int)pEvent->x, (int)pEvent->y,
(int)pixelToTwip(pEvent->x),
(int)pixelToTwip(pEvent->y));
- gtk_widget_grab_focus(GTK_WIDGET(pDialog));
+ gtk_widget_grab_focus(pDialogDrawingArea);
switch (pEvent->type)
{
@@ -194,7 +194,6 @@ gtv_lok_dialog_signal_motion(GtkWidget* pDialogDrawingArea, GdkEventButton* pEve
(int)pEvent->x, (int)pEvent->y,
(int)pixelToTwip(pEvent->x),
(int)pixelToTwip(pEvent->y));
- gtk_widget_grab_focus(GTK_WIDGET(pDialog));
pDocument->pClass->postDialogMouseEvent(pDocument,
priv->dialogid,
@@ -216,6 +215,7 @@ gtv_lok_dialog_signal_key(GtkWidget* pDialogDrawingArea, GdkEventKey* pEvent)
GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
+ g_info("lok_dialog_signal_key");
int nCharCode = 0;
int nKeyCode = 0;
priv->m_nKeyModifier &= KEY_MOD2;
@@ -334,12 +334,14 @@ gtv_lok_dialog_init(GtvLokDialog* dialog)
priv->m_nKeyModifier = 0;
priv->m_nLastButtonPressed = 0;
- gtk_widget_add_events(GTK_WIDGET(priv->pDialogDrawingArea),
+ gtk_widget_add_events(priv->pDialogDrawingArea,
GDK_BUTTON_PRESS_MASK
|GDK_BUTTON_RELEASE_MASK
|GDK_BUTTON_MOTION_MASK
|GDK_KEY_PRESS_MASK
|GDK_KEY_RELEASE_MASK);
+ // This is required to be able to capture key events on the drawing area
+ gtk_widget_set_can_focus(priv->pDialogDrawingArea, true);
g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_draw), nullptr);
g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_signal_button), nullptr);
commit 71641d744925e06099ed0f66ce6e0f0df495492e
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Fri Aug 4 00:02:38 2017 +0530
lokdialog: Invalid free
Change-Id: I7713b8d025652770e7e46603edbaa86951588871
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index 1111d6774b4b..3acd6b78e234 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -311,14 +311,15 @@ void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, g
std::string aAction = aRoot.get<std::string>("action");
std::string aPos = aRoot.get<std::string>("position");
gchar** ppCoordinates = g_strsplit(aPos.c_str(), ", ", 2);
+ gchar** ppCoordinate = ppCoordinates;
int nX = 0;
int nY = 0;
- if (*ppCoordinates)
- nX = atoi(*ppCoordinates);
- ++ppCoordinates;
- if (*ppCoordinates)
- nY = atoi(*ppCoordinates);
+ if (*ppCoordinate)
+ nX = atoi(*ppCoordinate);
+ ++ppCoordinate;
+ if (*ppCoordinate)
+ nY = atoi(*ppCoordinate);
g_strfreev(ppCoordinates);
commit bdf6580022f9b69f3d58b3ddafc0d096ac176e9f
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Thu Aug 3 22:58:04 2017 +0530
lokdialog: Move the floating window to its actual position
gtk_window_move them to the position broadcasted to us by vcl
Change-Id: Id27b52a24e721b51d7a153cc7c0e03197a99ee2f
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 1bfb9d538ead..6b19ddc506c0 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -460,7 +460,7 @@ gtv_lok_dialog_invalidate(GtvLokDialog* dialog)
gtk_widget_queue_draw(priv->pDialogDrawingArea);
}
-void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog)
+void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY)
{
g_info("Dialog's floating window invalidate");
@@ -474,14 +474,22 @@ void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog)
gtk_container_add(GTK_CONTAINER(priv->pFloatingWin), pDrawingArea);
gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
- gtk_window_set_position(GTK_WINDOW(priv->pFloatingWin), GTK_WIN_POS_MOUSE);
gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
-
g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
+ gtk_window_set_type_hint(GTK_WINDOW(priv->pFloatingWin), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
+ gtk_window_set_screen(GTK_WINDOW(priv->pFloatingWin), gtk_window_get_screen(GTK_WINDOW(dialog)));
+
gtk_widget_show_all(priv->pFloatingWin);
gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
+
+ // Get the root coords of our new floating window
+ GdkWindow* pGdkWin = gtk_widget_get_window(GTK_WIDGET(dialog));
+ int nrX = 0;
+ int nrY = 0;
+ gdk_window_get_root_coords(pGdkWin, nX, nY, &nrX, &nrY);
+ gtk_window_move(GTK_WINDOW(priv->pFloatingWin), nrX, nrY);
}
void gtv_lok_dialog_child_close(GtvLokDialog* dialog)
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
index bce9edbadba1..ba565b4cebb0 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
@@ -39,7 +39,7 @@ GtkWidget* gtv_lok_dialog_new(LOKDocView* pDocView, const gchar* dialogId);
void gtv_lok_dialog_invalidate(GtvLokDialog* dialog);
-void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog);
+void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog, int nX, int nY);
void gtv_lok_dialog_child_close(GtvLokDialog* dialog);
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index 8896566499c1..1111d6774b4b 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -309,6 +309,18 @@ void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, g
boost::property_tree::read_json(aStream, aRoot);
//std::string aDialogId = aRoot.get<std::string>("dialogId");
std::string aAction = aRoot.get<std::string>("action");
+ std::string aPos = aRoot.get<std::string>("position");
+ gchar** ppCoordinates = g_strsplit(aPos.c_str(), ", ", 2);
+ int nX = 0;
+ int nY = 0;
+
+ if (*ppCoordinates)
+ nX = atoi(*ppCoordinates);
+ ++ppCoordinates;
+ if (*ppCoordinates)
+ nY = atoi(*ppCoordinates);
+
+ g_strfreev(ppCoordinates);
// temporary hack to invalidate/close floating window of all opened dialogs
GList* pChildWins = gtv_application_window_get_all_child_windows(window);
@@ -316,7 +328,7 @@ void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, g
for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
{
if (aAction == "invalidate")
- gtv_lok_dialog_child_invalidate(GTV_LOK_DIALOG(pIt->data));
+ gtv_lok_dialog_child_invalidate(GTV_LOK_DIALOG(pIt->data), nX, nY);
else if (aAction == "close")
gtv_lok_dialog_child_close(GTV_LOK_DIALOG(pIt->data));
}
commit 6dd2fe231b4a2bb5912ee4176734e5d54e1db6c8
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Thu Aug 3 14:42:55 2017 +0530
lokdialog: Support for rendering floating window dialog widgets
Now gtktiledviewer can show floating window dialog widgets when user
clicks any of such widget in the dialog.
Change-Id: I13d756f236379bc8b2041ed41cb7b502f7fd9b24
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 847fd4dc923a..ca1c61cd84b9 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -603,6 +603,8 @@ static char* doc_getPartHash(LibreOfficeKitDocument* pThis, int nPart);
static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
+static void doc_paintActiveFloatingWindow(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
+
LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XComponent> &xComponent)
: mxComponent(xComponent)
{
@@ -652,6 +654,7 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
m_pDocumentClass->getPartHash = doc_getPartHash;
m_pDocumentClass->paintDialog = doc_paintDialog;
+ m_pDocumentClass->paintActiveFloatingWindow = doc_paintActiveFloatingWindow;
gDocumentClass = m_pDocumentClass;
}
@@ -3038,6 +3041,24 @@ static void doc_paintDialog(LibreOfficeKitDocument* pThis, const char* pDialogId
comphelper::LibreOfficeKit::setDialogPainting(false);
}
+static void doc_paintActiveFloatingWindow(LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight)
+{
+ SolarMutexGuard aGuard;
+
+ IDialogRenderable* pDialogRenderable = getDialogRenderable(pThis);
+
+ ScopedVclPtrInstance<VirtualDevice> pDevice(nullptr, Size(1, 1), DeviceFormat::DEFAULT);
+ pDevice->SetBackground(Wallpaper(Color(COL_TRANSPARENT)));
+
+ pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(*nWidth, *nHeight), Fraction(1.0), Point(), pBuffer);
+
+ vcl::DialogID aDialogID = OUString::createFromAscii(pDialogId);
+
+ comphelper::LibreOfficeKit::setDialogPainting(true);
+ pDialogRenderable->paintActiveFloatingWindow(aDialogID, *pDevice.get(), *nWidth, *nHeight);
+ comphelper::LibreOfficeKit::setDialogPainting(false);
+}
+
static char* lo_getError (LibreOfficeKit *pThis)
{
SolarMutexGuard aGuard;
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 5a099f7c7f67..529a1336ca76 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -269,6 +269,8 @@ struct _LibreOfficeKitDocumentClass
/// WIP
void (*paintDialog) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
+ void (*paintActiveFloatingWindow) (LibreOfficeKitDocument* pThis, const char* pDialogId, unsigned char* pBuffer, int* nWidth, int* nHeight);
+
/// WIP
void (*postDialogKeyEvent) (LibreOfficeKitDocument* pThis,
const char* pDialogId,
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index fdad6919e0e1..4c70560690da 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -525,8 +525,26 @@ typedef enum
/**
* Dialog invalidation
*/
- LOK_CALLBACK_DIALOG_INVALIDATE = 36
+ LOK_CALLBACK_DIALOG_INVALIDATE = 36,
+ /**
+ * Invalidation corresponding to dialog's children.
+ * Eg: Floating window etc.
+ *
+ * Payload example:
+ * {
+ * "dialogID": "SpellDialog",
+ * "action": "close"
+ * }
+ *
+ * - dialogID is the UNO command of the dialog
+ * - action can be
+ * - close, means dialog child window is closed now
+ * - invalidate, means dialog child window is invalidated
+ * It also means that dialog child window is created if it's the first
+ * invalidate
+ */
+ LOK_CALLBACK_DIALOG_CHILD = 37
}
LibreOfficeKitCallbackType;
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index b37480df9da1..b57f30a0ccba 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -42,6 +42,8 @@ public:
static void notifyOtherView(SfxViewShell* pThisView, SfxViewShell const* pOtherView, int nType, const OString& rKey, const OString& rPayload);
/// Emits a LOK_CALLBACK_DIALOG_INVALIDATE
static void notifyDialogInvalidation(const OUString& rPayload);
+ /// 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.
static void notifyInvalidation(SfxViewShell* pThisView, const OString& rPayload);
/// A special value to signify 'infinity'.
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index b2c0dee552cd..351839e46d02 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -33,6 +33,9 @@ public:
virtual void paintDialog(const DialogID& rDialogID, VirtualDevice &rDevice,
int& nOutputWidth, int& nOutputHeight) = 0;
+ virtual void paintActiveFloatingWindow(const DialogID& rDialogID, VirtualDevice &rDevice,
+ int& nOutputWidth, int& nOutputHeight) = 0;
+
virtual void postDialogKeyEvent(const DialogID& rDialogID, int nType,
int nCharCode, int nKeyCode) = 0;
@@ -41,6 +44,8 @@ public:
// Callbacks
virtual void notifyDialogInvalidation(const DialogID& rDialogID) = 0;
+
+ virtual void notifyDialogChild(const DialogID& rDialogID, const OUString& rAction, const Point& rPos) = 0;
};
} // namespace vcl
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index ef3bcd5e8099..5ab85be1842e 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -80,6 +80,9 @@ public:
SAL_DLLPRIVATE bool IsInClose() const { return mbInClose; }
virtual void doDeferredInit(WinBits nBits) override;
virtual void LogicInvalidate(const tools::Rectangle* pRectangle) override;
+ void InvalidateFloatingWindow(const Point& rPos);
+ void CloseFloatingWindow();
+ Size PaintActiveFloatingWindow(VirtualDevice& rDevice);
/// Necessary to register dialog renderable instance to emit LOK callbacks
void registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable);
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
index 077e2577f384..8a5ff9a56d37 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx
@@ -315,6 +315,7 @@ static void setupDocView(GtvApplicationWindow* window)
g_signal_connect(window->lokdocview, "password-required", G_CALLBACK(LOKDocViewSigHandlers::passwordRequired), nullptr);
g_signal_connect(window->lokdocview, "comment", G_CALLBACK(LOKDocViewSigHandlers::comment), nullptr);
g_signal_connect(window->lokdocview, "dialog-invalidate", G_CALLBACK(LOKDocViewSigHandlers::dialogInvalidate), nullptr);
+ g_signal_connect(window->lokdocview, "dialog-child", G_CALLBACK(LOKDocViewSigHandlers::dialogChild), nullptr);
g_signal_connect(window->lokdocview, "configure-event", G_CALLBACK(LOKDocViewSigHandlers::configureEvent), nullptr);
}
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index bb8800e3d734..1bfb9d538ead 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -32,6 +32,7 @@ struct GtvLokDialogPrivate
{
LOKDocView* lokdocview;
GtkWidget* pDialogDrawingArea;
+ GtkWidget* pFloatingWin;
guint32 m_nLastButtonPressTime;
guint32 m_nLastButtonReleaseTime;
@@ -79,6 +80,8 @@ gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
GtvLokDialogPrivate* priv = getPrivate(pDialog);
+
+ g_info("panting dialog");
int nWidth = 1024;
int nHeight = 768;
cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
@@ -324,6 +327,7 @@ gtv_lok_dialog_init(GtvLokDialog* dialog)
GtkWidget* pContentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
priv->pDialogDrawingArea = gtk_drawing_area_new();
+ priv->pFloatingWin = nullptr;
priv->m_nLastButtonPressTime = 0;
priv->m_nLastButtonReleaseTime = 0;
@@ -421,14 +425,75 @@ gtv_lok_dialog_class_init(GtvLokDialogClass* klass)
g_object_class_install_properties (G_OBJECT_CLASS(klass), PROP_LAST, properties);
}
+static void
+gtv_lok_dialog_floating_win_draw(GtkWidget* pDrawingArea, cairo_t* pCairo, gpointer userdata)
+{
+ GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
+ GtvLokDialogPrivate* priv = getPrivate(pDialog);
+
+ g_info("gtv_lok_dialog_floating_win_draw triggered");
+ int nWidth = 800;
+ int nHeight = 600;
+ cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
+ unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
+ LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
+ pDocument->pClass->paintActiveFloatingWindow(pDocument, priv->dialogid, pBuffer, &nWidth, &nHeight);
+ g_info("Size of floating window: %d x %d", nWidth, nHeight);
+
+ gtk_widget_set_size_request(GTK_WIDGET(pDrawingArea), nWidth, nHeight);
+ gtk_widget_set_size_request(GTK_WIDGET(pDialog), nWidth, nHeight);
+ gtk_window_resize(GTK_WINDOW(pDialog), nWidth, nHeight);
+
+ cairo_surface_flush(pSurface);
+ cairo_surface_mark_dirty(pSurface);
+
+ cairo_set_source_surface(pCairo, pSurface, 0, 0);
+ cairo_paint(pCairo);
+}
+
void
gtv_lok_dialog_invalidate(GtvLokDialog* dialog)
{
- // trigger a draw on the drawing area
GtvLokDialogPrivate* priv = getPrivate(dialog);
+
+ // trigger a draw on the dialog drawing area
gtk_widget_queue_draw(priv->pDialogDrawingArea);
}
+void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog)
+{
+ g_info("Dialog's floating window invalidate");
+
+ GtvLokDialogPrivate* priv = getPrivate(dialog);
+ // remove any existing floating windows, for now
+ if (priv->pFloatingWin)
+ gtk_widget_destroy(priv->pFloatingWin);
+
+ priv->pFloatingWin = gtk_window_new(GTK_WINDOW_POPUP);
+ GtkWidget* pDrawingArea = gtk_drawing_area_new();
+ gtk_container_add(GTK_CONTAINER(priv->pFloatingWin), pDrawingArea);
+
+ gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
+ gtk_window_set_position(GTK_WINDOW(priv->pFloatingWin), GTK_WIN_POS_MOUSE);
+ gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);
+
+ g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
+
+ gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
+ gtk_widget_show_all(priv->pFloatingWin);
+ gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
+}
+
+void gtv_lok_dialog_child_close(GtvLokDialog* dialog)
+{
+ g_info("Dialog's floating window close");
+
+ GtvLokDialogPrivate* priv = getPrivate(dialog);
+ if (priv->pFloatingWin)
+ gtk_widget_destroy(priv->pFloatingWin);
+}
+
+
GtkWidget*
gtv_lok_dialog_new(LOKDocView* pDocView, const gchar* dialogId)
{
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
index 0205f2ede3f4..bce9edbadba1 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.hxx
@@ -39,6 +39,10 @@ GtkWidget* gtv_lok_dialog_new(LOKDocView* pDocView, const gchar* dialogId);
void gtv_lok_dialog_invalidate(GtvLokDialog* dialog);
+void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog);
+
+void gtv_lok_dialog_child_close(GtvLokDialog* dialog);
+
G_END_DECLS
#endif /* GTV_LOK_DIALOG_H */
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
index 8f86ecd43ca7..8896566499c1 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.cxx
@@ -281,7 +281,7 @@ void LOKDocViewSigHandlers::comment(LOKDocView* pDocView, gchar* pComment, gpoin
}
}
-void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* /*pDialogId*/, gpointer)
+void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* pPayload, gpointer)
{
GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
// GtkWindow* pDialog = gtv_application_window_get_child_window_by_id(window, pDialogId);
@@ -300,6 +300,28 @@ void LOKDocViewSigHandlers::dialogInvalidate(LOKDocView* pDocView, gchar* /*pDia
*/
}
+void LOKDocViewSigHandlers::dialogChild(LOKDocView* pDocView, gchar* pPayload, gpointer)
+{
+ GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
+
+ std::stringstream aStream(pPayload);
+ boost::property_tree::ptree aRoot;
+ boost::property_tree::read_json(aStream, aRoot);
+ //std::string aDialogId = aRoot.get<std::string>("dialogId");
+ std::string aAction = aRoot.get<std::string>("action");
+
+ // temporary hack to invalidate/close floating window of all opened dialogs
+ GList* pChildWins = gtv_application_window_get_all_child_windows(window);
+ GList* pIt = nullptr;
+ for (pIt = pChildWins; pIt != nullptr; pIt = pIt->next)
+ {
+ if (aAction == "invalidate")
+ gtv_lok_dialog_child_invalidate(GTV_LOK_DIALOG(pIt->data));
+ else if (aAction == "close")
+ gtv_lok_dialog_child_close(GTV_LOK_DIALOG(pIt->data));
+ }
+}
+
gboolean LOKDocViewSigHandlers::configureEvent(GtkWidget* pWidget, GdkEventConfigure* /*pEvent*/, gpointer /*pData*/)
{
GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pWidget)));
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
index 73bf9c2860ad..a455c3f1fc4c 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lokdocview-signal-handlers.hxx
@@ -26,6 +26,7 @@ namespace LOKDocViewSigHandlers {
void passwordRequired(LOKDocView* pDocView, char* pUrl, gboolean bModify, gpointer);
void comment(LOKDocView* pDocView, gchar* pComment, gpointer);
void dialogInvalidate(LOKDocView* pDocView, gchar* pDialogId, gpointer);
+ void dialogChild(LOKDocView* pDocView, gchar* pPayload, gpointer);
gboolean configureEvent(GtkWidget* pWidget, GdkEventConfigure* pEvent, gpointer pData);
}
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index b5fc11d82d9e..1bdb80c754ed 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -280,6 +280,7 @@ enum
COMMENT,
RULER,
DIALOG_INVALIDATE,
+ DIALOG_CHILD,
LAST_SIGNAL
};
@@ -439,6 +440,8 @@ callbackTypeToString (int nType)
return "LOK_CALLBACK_RULER_UPDATE";
case LOK_CALLBACK_DIALOG_INVALIDATE:
return "LOK_CALLBACK_DIALOG_INVALIDATE";
+ case LOK_CALLBACK_DIALOG_CHILD:
+ return "LOK_CALLBACK_DIALOG_CHILD";
}
g_assert(false);
return nullptr;
@@ -1414,6 +1417,9 @@ callback (gpointer pData)
case LOK_CALLBACK_DIALOG_INVALIDATE:
g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG_INVALIDATE], 0, pCallback->m_aPayload.c_str());
break;
+ case LOK_CALLBACK_DIALOG_CHILD:
+ g_signal_emit(pCallback->m_pDocView, doc_view_signals[DIALOG_CHILD], 0, pCallback->m_aPayload.c_str());
+ break;
default:
g_assert(false);
break;
@@ -3225,6 +3231,37 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass)
g_cclosure_marshal_generic,
G_TYPE_NONE, 1,
G_TYPE_STRING);
+
+ /**
+ * LOKDocView::dialog-child:
+ * @pDocView: the #LOKDocView on which the signal is emitted
+ * @pPayload: JSON described below:
+ *
+ * Invalidation corresponding to dialog's children.
+ * Eg: Floating window etc.
+ *
+ * Payload example:
+ * {
+ * "dialogID": "SpellDialog",
+ * "action": "close"
+ * }
+ *
+ * - dialogID is the UNO command of the dialog
+ * - action can be
+ * - close, means dialog child window is closed now
+ * - invalidate, means dialog child window is invalidated
+ * It also means that dialog child window is created if it's the first
+ * invalidate
+ */
+ doc_view_signals[DIALOG_CHILD] =
+ g_signal_new("dialog-child",
+ G_TYPE_FROM_CLASS(pGObjectClass),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ nullptr, nullptr,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
}
SAL_DLLPUBLIC_EXPORT GtkWidget*
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 46d736206ddf..c6e9d57027b2 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -157,6 +157,24 @@ void SfxLokHelper::notifyDialogInvalidation(const OUString& rDialogID)
}
}
+void SfxLokHelper::notifyDialogChild(const OUString& rDialogID, const OUString& rAction, const Point& rPos)
+{
+ if (SfxLokHelper::getViewsCount() <= 0)
+ return;
+
+ SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+ const OString aPayload = OString("{ \"dialogId\": \"") + OUStringToOString(rDialogID, RTL_TEXTENCODING_UTF8).getStr() +
+ OString("\", \"action\": \"") + OUStringToOString(rAction, RTL_TEXTENCODING_UTF8).getStr() +
+ OString("\", \"position\": \"") + OString::number(rPos.getX()) + OString(", ") + OString::number(rPos.getY()) +
+ + "\" }";
+
+ while (pViewShell)
+ {
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DIALOG_CHILD, aPayload.getStr());
+ pViewShell = SfxViewShell::GetNext(*pViewShell);
+ }
+}
+
void SfxLokHelper::notifyInvalidation(SfxViewShell* pThisView, const OString& rPayload)
{
OStringBuffer aBuf;
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index e93173451b3c..3d269dcadc03 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -432,6 +432,7 @@ public:
OUString getPostIts() override;
void paintDialog(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight) override;
+ void paintActiveFloatingWindow(const vcl::DialogID& rDialogID, VirtualDevice& rDevice, int& nWidth, int& nHeight) override;
void postDialogKeyEvent(const vcl::DialogID& rDialogID, int nType,
int nCharCode, int nKeyCode) override;
@@ -440,6 +441,8 @@ public:
void notifyDialogInvalidation(const vcl::DialogID& rDialogID) 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;
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 4e471f351866..aa685ac1ea72 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3748,6 +3748,33 @@ void SwXTextDocument::notifyDialogInvalidation(const vcl::DialogID& rDialogID)
SfxLokHelper::notifyDialogInvalidation(rDialogID);
}
+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)
+ {
+ SAL_WARN("lok.dialog", "No slot found for " << rDialogID);
+ return;
+ }
+ SfxChildWindow* pChild = pViewFrame->GetChildWindow(pSlot->GetSlotId());
+ if (!pChild)
+ return;
+
+ Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
+ // register the instance so that vcl::Dialog can emit LOK callbacks
+ const Size aSize = pDlg->PaintActiveFloatingWindow(rDevice);
+ SAL_DEBUG("Size of the floating window : " << aSize);
+ nWidth = aSize.getWidth();
+ nHeight = aSize.getHeight();
+}
+
void * SAL_CALL SwXTextDocument::operator new( size_t t) throw()
{
return SwXTextDocumentBaseClass::operator new(t);
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index e5d784e4f667..b626f7a8cbd6 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -883,10 +883,51 @@ void Dialog::paintDialog(VirtualDevice& rDevice)
PaintToDevice(&rDevice, Point(0, 0), Size());
}
-void Dialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
+Size Dialog::PaintActiveFloatingWindow(VirtualDevice& rDevice)
+{
+ Size aRet;
+ ImplSVData* pSVData = ImplGetSVData();
+ FloatingWindow* pFirstFloat = pSVData->maWinData.mpFirstFloat;
+ if (pFirstFloat)
+ {
+ // TODO:: run a while loop here and check all the active floating
+ // windows ( chained together, cf. pFirstFloat->mpNextFloat )
+ // For now just assume that the active floating window is the one we
+ // want to render
+ if (pFirstFloat->GetParentDialog() == this)
+ {
+ pFirstFloat->PaintToDevice(&rDevice, Point(0, 0), Size());
+ aRet = ::isLayoutEnabled(pFirstFloat) ? pFirstFloat->get_preferred_size() : pFirstFloat->GetSizePixel();
+ }
+
+ pFirstFloat = nullptr;
+ }
+
+ return aRet;
+}
+
+void Dialog::InvalidateFloatingWindow(const Point& rPos)
{
+ SAL_DEBUG("Dialog:: Invalidate Floating window");
if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable && !maID.isEmpty())
{
+ mpDialogRenderable->notifyDialogChild(maID, "invalidate", rPos);
+ }
+}
+
+void Dialog::CloseFloatingWindow()
+{
+ SAL_DEBUG("Dialog:: close Floating window");
+ if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable && !maID.isEmpty())
+ {
+ mpDialogRenderable->notifyDialogChild(maID, "close", Point(0, 0));
+ }
+}
+
+void Dialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
+{
+ if (!comphelper::LibreOfficeKit::isDialogPainting() && mpDialogRenderable && !maID.isEmpty())
+ {
mpDialogRenderable->notifyDialogInvalidation(maID);
}
}
diff --git a/vcl/source/window/floatwin.cxx b/vcl/source/window/floatwin.cxx
index 23e56ce6e669..44ce96c42843 100644
--- a/vcl/source/window/floatwin.cxx
+++ b/vcl/source/window/floatwin.cxx
@@ -38,6 +38,7 @@ public:
VclPtr<ToolBox> mpBox;
tools::Rectangle maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
+ Point maPos; // position of the floating window wrt. parent
};
FloatingWindow::ImplData::ImplData()
@@ -593,6 +594,17 @@ void FloatingWindow::StateChanged( StateChangedType nType )
SystemWindow::StateChanged( nType );
+ if (nType == StateChangedType::InitShow && IsVisible())
+ {
+ Dialog* pParentDlg = GetParentDialog();
+ pParentDlg->InvalidateFloatingWindow(mpImplData->maPos);
+ }
+ else if (!IsVisible())
+ {
+ Dialog* pParentDlg = GetParentDialog();
+ pParentDlg->CloseFloatingWindow();
+ }
+
if ( nType == StateChangedType::ControlBackground )
{
ImplInitSettings();
@@ -667,8 +679,8 @@ void FloatingWindow::StartPopupMode( const tools::Rectangle& rRect, FloatWinPopu
// compute window position according to flags and arrangement
sal_uInt16 nArrangeIndex;
- Point aPos = ImplCalcPos( this, rRect, nFlags, nArrangeIndex );
- SetPosPixel( aPos );
+ mpImplData->maPos = ImplCalcPos( this, rRect, nFlags, nArrangeIndex );
+ SetPosPixel( mpImplData->maPos );
// set data and display window
// convert maFloatRect to absolute device coordinates
@@ -714,10 +726,10 @@ void FloatingWindow::StartPopupMode( ToolBox* pBox, FloatWinPopupFlags nFlags )
// retrieve some data from the ToolBox
tools::Rectangle aRect = nItemId ? pBox->GetItemRect( nItemId ) : pBox->GetOverflowRect();
- Point aPos;
+
// convert to parent's screen coordinates
- aPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
- aRect.SetPos( aPos );
+ mpImplData->maPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
+ aRect.SetPos( mpImplData->maPos );
nFlags |=
FloatWinPopupFlags::AllMouseButtonClose |
commit afb1ab1c9da0cf8e716a7f79753e458a5a4e3ebe
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Thu Aug 3 14:42:21 2017 +0530
lokdialog: Register IDIalogRenderable with vcl::Dialog
Change-Id: I344f5a9c7167abfde15dcd21c747819cc79b12b1
diff --git a/include/sfx2/basedlgs.hxx b/include/sfx2/basedlgs.hxx
index 7609229db2a6..cb403c78a075 100644
--- a/include/sfx2/basedlgs.hxx
+++ b/include/sfx2/basedlgs.hxx
@@ -105,8 +105,6 @@ public:
SfxBindings& GetBindings()
{ return *pBindings; }
- virtual void LogicInvalidate(const tools::Rectangle* pRectangle) override;
-
DECL_LINK(TimerHdl, Timer *, void);
};
diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx
index cf9d41e54cde..b2c0dee552cd 100644
--- a/include/vcl/IDialogRenderable.hxx
+++ b/include/vcl/IDialogRenderable.hxx
@@ -38,6 +38,9 @@ public:
virtual void postDialogMouseEvent(const DialogID& rDialogID, int nType, int nX, int nY,
int nCount, int nButtons, int nModifier) = 0;
+
+ // Callbacks
+ virtual void notifyDialogInvalidation(const DialogID& rDialogID) = 0;
};
} // namespace vcl
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index 93f2080c8352..ef3bcd5e8099 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -25,7 +25,7 @@
#include <vcl/dllapi.h>
#include <vcl/syswin.hxx>
#include <vcl/vclptr.hxx>
-
+#include <vcl/IDialogRenderable.hxx>
struct DialogImpl;
class VclBox;
@@ -59,6 +59,8 @@ private:
VclPtr<VclButtonBox> mpActionArea;
VclPtr<VclBox> mpContentArea;
+ vcl::IDialogRenderable* mpDialogRenderable; // to emit LOK callbacks
+
SAL_DLLPRIVATE void ImplInitDialogData();
SAL_DLLPRIVATE void ImplInitSettings();
@@ -77,7 +79,10 @@ protected:
public:
SAL_DLLPRIVATE bool IsInClose() const { return mbInClose; }
virtual void doDeferredInit(WinBits nBits) override;
- virtual void LogicInvalidate(const tools::Rectangle* pRectangle) override { (void)pRectangle; }
+ virtual void LogicInvalidate(const tools::Rectangle* pRectangle) override;
+
+ /// Necessary to register dialog renderable instance to emit LOK callbacks
+ void registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable);
/// Paints the current dialog to the given virtual device
void paintDialog(VirtualDevice& rDevice);
void LogicMouseButtonDown(const MouseEvent& rMouseEvent);
diff --git a/sfx2/source/dialog/basedlgs.cxx b/sfx2/source/dialog/basedlgs.cxx
index 0d2d90d142de..bfc0ac45a39b 100644
--- a/sfx2/source/dialog/basedlgs.cxx
+++ b/sfx2/source/dialog/basedlgs.cxx
@@ -393,14 +393,6 @@ void SfxModelessDialog::FillInfo(SfxChildWinInfo& rInfo) const
rInfo.nFlags |= SfxChildWindowFlags::ZOOMIN;
}
-
-void SfxModelessDialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
-{
- if (!comphelper::LibreOfficeKit::isDialogPainting())
- SfxLokHelper::notifyDialogInvalidation(maID);
-}
-
-
bool SfxFloatingWindow::EventNotify( NotifyEvent& rEvt )
/* [Description]
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index 3df958033c5e..e93173451b3c 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -438,6 +438,8 @@ public:
void postDialogMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
int nCount, int nButtons, int nModifier) override;
+ void notifyDialogInvalidation(const vcl::DialogID& rDialogID) 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;
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 03fd94910c6b..4e471f351866 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -31,6 +31,7 @@
#include <vcl/svapp.hxx>
#include <vcl/print.hxx>
#include <sfx2/viewfrm.hxx>
+#include <sfx2/lokhelper.hxx>
#include <sfx2/sfxbasecontroller.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/msg.hxx>
@@ -3661,6 +3662,8 @@ void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice&
}
Dialog* pDlg = static_cast<Dialog*>(pChild->GetWindow());
+ // register the instance so that vcl::Dialog can emit LOK callbacks
+ pDlg->registerDialogRenderable(this);
pDlg->paintDialog(rDevice);
const Size aSize = pDlg->GetOptimalSize();
nWidth = aSize.getWidth();
@@ -3740,6 +3743,11 @@ void SwXTextDocument::postDialogMouseEvent(const vcl::DialogID& rDialogID, int n
}
}
+void SwXTextDocument::notifyDialogInvalidation(const vcl::DialogID& rDialogID)
+{
+ SfxLokHelper::notifyDialogInvalidation(rDialogID);
+}
+
void * SAL_CALL SwXTextDocument::operator new( size_t t) throw()
{
return SwXTextDocumentBaseClass::operator new(t);
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 3ca7fff70211..e5d784e4f667 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -348,6 +348,7 @@ struct DialogImpl
void Dialog::ImplInitDialogData()
{
+ mpDialogRenderable = nullptr;
mpWindowImpl->mbDialog = true;
mpPrevExecuteDlg = nullptr;
mbInExecute = false;
@@ -863,6 +864,14 @@ bool Dialog::selectPageByUIXMLDescription(const OString& /*rUIXMLDescription*/)
return true;
}
+void Dialog::registerDialogRenderable(vcl::IDialogRenderable* pDialogRenderable)
+{
+ if (pDialogRenderable && !mpDialogRenderable)
+ {
+ mpDialogRenderable = pDialogRenderable;
+ }
+}
+
void Dialog::paintDialog(VirtualDevice& rDevice)
{
setDeferredProperties();
@@ -874,6 +883,14 @@ void Dialog::paintDialog(VirtualDevice& rDevice)
PaintToDevice(&rDevice, Point(0, 0), Size());
}
+void Dialog::LogicInvalidate(const tools::Rectangle* /*pRectangle*/)
+{
+ if (comphelper::LibreOfficeKit::isActive() && mpDialogRenderable && !maID.isEmpty())
+ {
+ mpDialogRenderable->notifyDialogInvalidation(maID);
+ }
+}
+
void Dialog::LogicMouseButtonDown(const MouseEvent& rMouseEvent)
{
// When we're not doing tiled rendering, then positions must be passed as pixels.
commit 2dc85b5762025fcdc25a5d18a901e04a42a1ecc7
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Wed Aug 2 18:01:45 2017 +0530
Fix a comment
Change-Id: Icbd16aebf3ddabd1b0ffd310f1aab3641d5c40b4
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index 65cd5964af97..b37480df9da1 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -40,7 +40,7 @@ public:
static void notifyOtherViews(SfxViewShell* pThisView, int nType, const OString& rKey, const OString& rPayload);
/// Same as notifyOtherViews(), but works on a selected "other" view, not on all of them.
static void notifyOtherView(SfxViewShell* pThisView, SfxViewShell const* pOtherView, int nType, const OString& rKey, const OString& rPayload);
- /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed.
+ /// Emits a LOK_CALLBACK_DIALOG_INVALIDATE
static void notifyDialogInvalidation(const OUString& rPayload);
/// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed.
static void notifyInvalidation(SfxViewShell* pThisView, const OString& rPayload);
commit 841be080a2e296595377f119253a79c252d13efb
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Sun Jul 30 06:06:56 2017 +0530
lokdialog: Handle key events in core
Change-Id: If84aaac87beebf69d92db5446fc713d8cc20421e
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index a38a6ebc6c6a..93f2080c8352 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -84,6 +84,9 @@ public:
void LogicMouseButtonUp(const MouseEvent& rMouseEvent);
void LogicMouseMove(const MouseEvent& rMouseEvent);
+ void LOKKeyInput(const KeyEvent& rKeyEvent);
+ void LOKKeyUp(const KeyEvent& rKeyEvent);
+
protected:
explicit Dialog( WindowType nType );
explicit Dialog( vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription, WindowType nType, InitFlag eFlag = InitFlag::Default );
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 782d5f7f952c..03fd94910c6b 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3667,9 +3667,38 @@ void SwXTextDocument::paintDialog(const vcl::DialogID& rDialogID, VirtualDevice&
nHeight = aSize.getHeight();
}
-void SwXTextDocument::postDialogKeyEvent(const vcl::DialogID& /*rDialogID*/, int /*nType*/, int /*nCharCode*/, int /*nKeyCode*/)
+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)
+ {
+ 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)
+ {
+ case LOK_KEYEVENT_KEYINPUT:
+ pDialog->KeyInput(aEvent);
+ break;
+ case LOK_KEYEVENT_KEYUP:
+ pDialog->KeyUp(aEvent);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ }
}
void SwXTextDocument::postDialogMouseEvent(const vcl::DialogID& rDialogID, int nType, int nX, int nY,
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 375af4418abc..3ca7fff70211 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -898,6 +898,20 @@ void Dialog::LogicMouseMove(const MouseEvent& rMouseEvent)
ImplWindowFrameProc(this, SalEvent::ExternalMouseMove, &rMouseEvent);
}
+void Dialog::LOKKeyInput(const KeyEvent& rKeyEvent)
+{
+ assert(comphelper::LibreOfficeKit::isActive());
+
+ ImplWindowFrameProc(this, SalEvent::ExternalKeyInput, &rKeyEvent);
+}
+
+void Dialog::LOKKeyUp(const KeyEvent& rKeyEvent)
+{
+ assert(comphelper::LibreOfficeKit::isActive());
+
+ ImplWindowFrameProc(this, SalEvent::ExternalKeyUp, &rKeyEvent);
+}
+
void Dialog::ensureRepaint()
{
// ensure repaint
commit 11b8a9e6a1582468258382c69bf1a1981a7e9fae
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Sun Jul 30 05:18:33 2017 +0530
lokdialog: gtv: Forward key events on dialog to core
Change-Id: Icfc210b08c7f1d8ebaf9c731ed64bb128cfc4356
diff --git a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
index 7a9fa7712900..bb8800e3d734 100644
--- a/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtv-lok-dialog.cxx
@@ -8,9 +8,11 @@
*/
#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
#include <cmath>
#include <iostream>
+#include <sstream>
#include <LibreOfficeKit/LibreOfficeKitGtk.h>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
@@ -136,7 +138,7 @@ gtv_lok_dialog_signal_button(GtkWidget* pDialogDrawingArea, GdkEventButton* pEve
(pEvent->y),
nCount,
nEventButton,
- 0/* Modifier */);
+ priv->m_nKeyModifier);
break;
}
@@ -167,7 +169,7 @@ gtv_lok_dialog_signal_button(GtkWidget* pDialogDrawingArea, GdkEventButton* pEve
(pEvent->y),
nCount,
nEventButton,
- 0/* Modifier */);
+ priv->m_nKeyModifier);
break;
}
default:
@@ -198,7 +200,119 @@ gtv_lok_dialog_signal_motion(GtkWidget* pDialogDrawingArea, GdkEventButton* pEve
(pEvent->y),
1,
priv->m_nLastButtonPressed,
- 0/* Modifier */);
+ priv->m_nKeyModifier);
+
+ return FALSE;
+}
+
+static gboolean
+gtv_lok_dialog_signal_key(GtkWidget* pDialogDrawingArea, GdkEventKey* pEvent)
+{
+ GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
+ GtvLokDialogPrivate* priv = getPrivate(pDialog);
+ GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
+ LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));
+
+ int nCharCode = 0;
+ int nKeyCode = 0;
+ priv->m_nKeyModifier &= KEY_MOD2;
+ switch (pEvent->keyval)
+ {
+ case GDK_KEY_BackSpace:
+ nKeyCode = com::sun::star::awt::Key::BACKSPACE;
+ break;
+ case GDK_KEY_Delete:
+ nKeyCode = com::sun::star::awt::Key::DELETE;
+ break;
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ nKeyCode = com::sun::star::awt::Key::RETURN;
+ break;
+ case GDK_KEY_Escape:
+ nKeyCode = com::sun::star::awt::Key::ESCAPE;
+ break;
+ case GDK_KEY_Tab:
+ nKeyCode = com::sun::star::awt::Key::TAB;
+ break;
+ case GDK_KEY_Down:
+ nKeyCode = com::sun::star::awt::Key::DOWN;
+ break;
+ case GDK_KEY_Up:
+ nKeyCode = com::sun::star::awt::Key::UP;
+ break;
+ case GDK_KEY_Left:
+ nKeyCode = com::sun::star::awt::Key::LEFT;
+ break;
+ case GDK_KEY_Right:
+ nKeyCode = com::sun::star::awt::Key::RIGHT;
+ break;
+ case GDK_KEY_Page_Down:
+ nKeyCode = com::sun::star::awt::Key::PAGEDOWN;
+ break;
+ case GDK_KEY_Page_Up:
+ nKeyCode = com::sun::star::awt::Key::PAGEUP;
+ break;
+ case GDK_KEY_Insert:
+ nKeyCode = com::sun::star::awt::Key::INSERT;
+ break;
+ case GDK_KEY_Shift_L:
+ case GDK_KEY_Shift_R:
+ if (pEvent->type == GDK_KEY_PRESS)
+ priv->m_nKeyModifier |= KEY_SHIFT;
+ break;
+ case GDK_KEY_Control_L:
+ case GDK_KEY_Control_R:
+ if (pEvent->type == GDK_KEY_PRESS)
+ priv->m_nKeyModifier |= KEY_MOD1;
+ break;
+ case GDK_KEY_Alt_L:
+ case GDK_KEY_Alt_R:
+ if (pEvent->type == GDK_KEY_PRESS)
+ priv->m_nKeyModifier |= KEY_MOD2;
+ else
+ priv->m_nKeyModifier &= ~KEY_MOD2;
+ break;
+ default:
+ if (pEvent->keyval >= GDK_KEY_F1 && pEvent->keyval <= GDK_KEY_F26)
+ nKeyCode = com::sun::star::awt::Key::F1 + (pEvent->keyval - GDK_KEY_F1);
+ else
+ nCharCode = gdk_keyval_to_unicode(pEvent->keyval);
+ }
+
+ // rsc is not public API, but should be good enough for debugging purposes.
+ // If this is needed for real, then probably a new param of type
+ // css::awt::KeyModifier is needed in postKeyEvent().
+ if (pEvent->state & GDK_SHIFT_MASK)
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list