From 9cdaccc0cc5664ffb22035f65135b6be876de92f Mon Sep 17 00:00:00 2001 From: Pranav Kant Date: Thu, 3 Aug 2017 14:42:55 +0530 Subject: 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 --- .../qa/gtktiledviewer/gtv-application-window.cxx | 1 + .../qa/gtktiledviewer/gtv-lok-dialog.cxx | 67 +++++++++++++++++++++- .../qa/gtktiledviewer/gtv-lok-dialog.hxx | 4 ++ .../gtv-lokdocview-signal-handlers.cxx | 24 +++++++- .../gtv-lokdocview-signal-handlers.hxx | 1 + libreofficekit/source/gtk/lokdocview.cxx | 37 ++++++++++++ 6 files changed, 132 insertions(+), 2 deletions(-) (limited to 'libreofficekit') 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("dialogId"); + std::string aAction = aRoot.get("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* -- cgit