From f29fded5a52f4c2fc1aae307e1f43326dd04108c Mon Sep 17 00:00:00 2001 From: Michael Meeks Date: Thu, 9 May 2019 18:25:22 +0100 Subject: unipoll: add a --unipoll parameter to gtktiledviewer. Arguably should be the default. Implementation is a bit cute - re-starting the main-loop as a child of a callback from its idle handler. Change-Id: I95e87c8a4ae3de745d7ca1f636859dd1d8deca17 Reviewed-on: https://gerrit.libreoffice.org/72072 Tested-by: Jenkins Reviewed-by: Michael Meeks --- .../qa/gtktiledviewer/gtv-application-window.cxx | 15 ++++-- .../qa/gtktiledviewer/gtv-application-window.hxx | 2 + .../qa/gtktiledviewer/gtv-application.cxx | 5 +- libreofficekit/source/gtk/lokdocview.cxx | 63 ++++++++++++++++++++++ 4 files changed, 81 insertions(+), 4 deletions(-) (limited to 'libreofficekit') diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx index 1de1aa94568d..564c1de137c6 100644 --- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx +++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.cxx @@ -356,9 +356,18 @@ gtv_application_window_load_document(GtvApplicationWindow* window, *(priv->m_pRenderingArgs) = *aArgs; // setup lokdocview - window->lokdocview = lok_doc_view_new_from_user_profile(priv->m_pRenderingArgs->m_aLoPath.c_str(), - priv->m_pRenderingArgs->m_aUserProfile.empty() ? nullptr : priv->m_pRenderingArgs->m_aUserProfile.c_str(), - nullptr, nullptr); + const char *pUserProfile = priv->m_pRenderingArgs->m_aUserProfile.empty() ? + nullptr : priv->m_pRenderingArgs->m_aUserProfile.c_str(); + + window->lokdocview = GTK_WIDGET( + g_initable_new(LOK_TYPE_DOC_VIEW, nullptr, nullptr, + "lopath", priv->m_pRenderingArgs->m_aLoPath.c_str(), + "unipoll", priv->m_pRenderingArgs->m_bUnipoll, + "userprofileurl", pUserProfile, + "halign", GTK_ALIGN_CENTER, + "valign", GTK_ALIGN_CENTER, + nullptr)); + gtk_container_add(GTK_CONTAINER(window->scrolledwindow), window->lokdocview); setupDocView(window); diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx b/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx index 748195c5aff0..21508097e077 100644 --- a/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx +++ b/libreofficekit/qa/gtktiledviewer/gtv-application-window.hxx @@ -24,6 +24,7 @@ struct GtvRenderingArgs std::string m_aLoPath; std::string m_aUserProfile; bool m_bEnableTiledAnnotations; + bool m_bUnipoll; std::string m_aBackgroundColor; bool m_bHidePageShadow; @@ -31,6 +32,7 @@ struct GtvRenderingArgs GtvRenderingArgs() : m_bEnableTiledAnnotations(false), + m_bUnipoll(false), m_bHidePageShadow(false), m_bHideWhiteSpace(false) { } diff --git a/libreofficekit/qa/gtktiledviewer/gtv-application.cxx b/libreofficekit/qa/gtktiledviewer/gtv-application.cxx index 3d802ee325d4..15e5f15f1697 100644 --- a/libreofficekit/qa/gtktiledviewer/gtv-application.cxx +++ b/libreofficekit/qa/gtktiledviewer/gtv-application.cxx @@ -46,6 +46,7 @@ gtv_application_init(GtvApplication* app) { { "version", 0, 0, G_OPTION_ARG_NONE, nullptr, "Show LOkit version", nullptr }, { "lo-path", 0, 0, G_OPTION_ARG_STRING, nullptr, "LO path", nullptr }, + { "unipoll", 0, 0, G_OPTION_ARG_NONE, nullptr, "Enable unified polling loop", nullptr }, { "user-profile", 0, 0, G_OPTION_ARG_STRING, nullptr, "User profile to use", nullptr }, { "enable-tiled-annotations", 0, 0, G_OPTION_ARG_NONE, nullptr, "Whether tiled annotations should be enabled", nullptr }, { "background-color", 0, 0, G_OPTION_ARG_STRING, nullptr, "Background color", nullptr }, @@ -92,11 +93,13 @@ gtv_application_handle_local_options(GApplication* app, GVariantDict* options) return 1; // Cannot afford to continue in absence of this param } + if (g_variant_dict_contains(options, "unipoll")) + priv->m_pRenderingArgs->m_bUnipoll = true; + if (g_variant_dict_contains(options, "version")) { if (!priv->m_pRenderingArgs->m_aLoPath.empty()) { - // FIXME: Crashes for some reason GtkWidget* pDocView = lok_doc_view_new(priv->m_pRenderingArgs->m_aLoPath.c_str(), nullptr, nullptr); const gchar* versionInfo = lok_doc_view_get_version_info(LOK_DOC_VIEW(pDocView)); if (versionInfo) diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 3187daed6a41..54c63de3674a 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -85,6 +85,7 @@ struct LOKDocViewPrivateImpl gboolean m_bInit; // initializeForRendering() has been called gboolean m_bCanZoomIn; gboolean m_bCanZoomOut; + gboolean m_bUnipoll; LibreOfficeKit* m_pOffice; LibreOfficeKitDocument* m_pDocument; @@ -198,6 +199,7 @@ struct LOKDocViewPrivateImpl m_bInit(false), m_bCanZoomIn(true), m_bCanZoomOut(true), + m_bUnipoll(false), m_pOffice(nullptr), m_pDocument(nullptr), lokThreadPool(nullptr), @@ -287,6 +289,7 @@ enum PROP_0, PROP_LO_PATH, + PROP_LO_UNIPOLL, PROP_LO_POINTER, PROP_USER_PROFILE_URL, PROP_DOC_PATH, @@ -2524,6 +2527,9 @@ static void lok_doc_view_set_property (GObject* object, guint propId, const GVal case PROP_LO_PATH: priv->m_aLOPath = g_value_get_string (value); break; + case PROP_LO_UNIPOLL: + priv->m_bUnipoll = g_value_get_boolean (value); + break; case PROP_LO_POINTER: priv->m_pOffice = static_cast(g_value_get_pointer(value)); break; @@ -2586,6 +2592,9 @@ static void lok_doc_view_get_property (GObject* object, guint propId, GValue *va case PROP_LO_PATH: g_value_set_string (value, priv->m_aLOPath.c_str()); break; + case PROP_LO_UNIPOLL: + g_value_set_boolean (value, priv->m_bUnipoll); + break; case PROP_LO_POINTER: g_value_set_pointer(value, priv->m_pOffice); break; @@ -2711,6 +2720,41 @@ static void lok_doc_view_finalize (GObject* object) G_OBJECT_CLASS (lok_doc_view_parent_class)->finalize (object); } +// kicks the mainloop awake +static gboolean timeout_wakeup(void *) +{ + return FALSE; +} + +// integrate our mainloop with LOK's +static int lok_poll_callback(void*, int timeoutUs) +{ + if (timeoutUs) + { + guint timeout = g_timeout_add(timeoutUs / 1000, timeout_wakeup, nullptr); + g_main_context_iteration(nullptr, TRUE); + g_source_remove(timeout); + } + else + g_main_context_iteration(nullptr, FALSE); + + return 0; +} + +// thread-safe wakeup of our mainloop +static void lok_wake_callback(void *) +{ + g_main_context_wakeup(nullptr); +} + +static gboolean spin_lok_loop(void *pData) +{ + LOKDocView *pDocView = LOK_DOC_VIEW (pData); + LOKDocViewPrivate& priv = getPrivate(pDocView); + priv->m_pOffice->pClass->runLoop(priv->m_pOffice, lok_poll_callback, lok_wake_callback, nullptr); + return FALSE; +} + static gboolean lok_doc_view_initable_init (GInitable *initable, GCancellable* /*cancellable*/, GError **error) { LOKDocView *pDocView = LOK_DOC_VIEW (initable); @@ -2719,6 +2763,9 @@ static gboolean lok_doc_view_initable_init (GInitable *initable, GCancellable* / if (priv->m_pOffice != nullptr) return TRUE; + if (priv->m_bUnipoll) + g_setenv("SAL_LOK_OPTIONS", "unipoll", FALSE); + priv->m_pOffice = lok_init_2(priv->m_aLOPath.c_str(), priv->m_aUserProfileURL.empty() ? nullptr : priv->m_aUserProfileURL.c_str()); if (priv->m_pOffice == nullptr) @@ -2733,6 +2780,9 @@ static gboolean lok_doc_view_initable_init (GInitable *initable, GCancellable* / priv->m_nLOKFeatures |= LOK_FEATURE_VIEWID_IN_VISCURSOR_INVALIDATION_CALLBACK; priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, priv->m_nLOKFeatures); + if (priv->m_bUnipoll) + g_idle_add(spin_lok_loop, pDocView); + return TRUE; } @@ -2772,6 +2822,19 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + /** + * LOKDocView:unipoll: + * + * Whether we use our own unified polling mainloop in place of glib's + */ + properties[PROP_LO_UNIPOLL] = + g_param_spec_boolean("unipoll", + "Unified Polling", + "Whether we use a custom unified polling loop", + FALSE, + static_cast(G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); /** * LOKDocView:lopointer: * -- cgit