[Libreoffice-commits] core.git: Branch 'libreoffice-6-1' - vcl/unx

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Thu Oct 11 08:05:05 UTC 2018


 vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx |   43 +++++++++++++++----
 vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx |   55 ++++++++++---------------
 2 files changed, 57 insertions(+), 41 deletions(-)

New commits:
commit c6cd5656e5b398502e55bc83c4bfc94180f72606
Author:     Michael Weghorn <m.weghorn at posteo.de>
AuthorDate: Tue Oct 2 16:13:51 2018 +0200
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Thu Oct 11 10:04:41 2018 +0200

    tdf#120261 gtk3_kde5: Leave event handling on gtk3 side to gtk
    
    This introduces a new thread that takes care of handling the IPC
    command and result for executing the file picker
    ('Commands::Execute'), which is the only command in the file
    picker that may block for a longer time until it receives its
    result from the kde5 side (namely, when the dialog has been
    closed).
    
    While the file dialog is being executed, activate a dummy GTK dialog
    that also takes care of handling events in its main loop as long
    as the file dialog is shown. The dummy dialog is closed together
    with the KDE file dialog.
    (Since the actual KDE file dialog is run as a separate process,
    this one is mostly "transparent" to the soffice process from the
    point of view of a dialog.)
    
    This allows dropping the custom event processing previously done
    in 'Gtk3KDE5FilePickerIpc::readResponse()' that had the potential
    to cause all kinds of problems, e.g. when another event related to
    the file picker was triggered from a Java process via UNO.
    
    Change-Id: I3d663253f09320f7a8e0d9ec32a8fd6ec191c189
    Reviewed-on: https://gerrit.libreoffice.org/61253
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.weghorn at posteo.de>
    (cherry picked from commit 788716cebad012513cc2798589b817b86cbf1bbc)
    Reviewed-on: https://gerrit.libreoffice.org/61511
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx
index 8cec9d853fbc..36ddcaf40f6e 100644
--- a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx
+++ b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx
@@ -106,6 +106,17 @@ OUString getResString(const char* pResId)
     return VclResId(pResId);
 }
 
+// handles the IPC commands for dialog execution and ends the dummy Gtk dialog once the IPC response is there
+void handleIpcForExecute(Gtk3KDE5FilePickerIpc* pFilePickerIpc, GtkWidget* pDummyDialog,
+                         bool* bResult)
+{
+    auto id = pFilePickerIpc->sendCommand(Commands::Execute);
+    pFilePickerIpc->readResponse(id, *bResult);
+
+    // end the dummy dialog
+    gtk_widget_hide(pDummyDialog);
+}
+
 // Gtk3KDE5FilePicker
 
 Gtk3KDE5FilePickerIpc::Gtk3KDE5FilePickerIpc()
@@ -143,9 +154,29 @@ sal_Int16 Gtk3KDE5FilePickerIpc::execute()
 {
     auto restoreMainWindow = blockMainWindow();
 
-    auto id = sendCommand(Commands::Execute);
+    // dummy gtk dialog that will take care of processing events,
+    // not meant to be actually seen by user
+    GtkWidget* pDummyDialog = gtk_dialog_new();
+
     bool accepted = false;
-    readResponse(id, accepted);
+
+    // send IPC command and read response in a separate thread
+    std::thread aIpcHandler(&handleIpcForExecute, this, pDummyDialog, &accepted);
+
+    // make dummy dialog not to be seen by user
+    gtk_window_set_decorated(GTK_WINDOW(pDummyDialog), false);
+    gtk_window_set_default_size(GTK_WINDOW(pDummyDialog), 0, 0);
+    gtk_window_set_accept_focus(GTK_WINDOW(pDummyDialog), false);
+    // gtk_widget_set_opacity() only has the desired effect when widget is already shown
+    gtk_widget_show(pDummyDialog);
+    gtk_widget_set_opacity(pDummyDialog, 0);
+    // run dialog, leaving event processing to GTK
+    // dialog will be closed by the separate 'aIpcHandler' thread once the IPC response is there
+    gtk_dialog_run(GTK_DIALOG(pDummyDialog));
+
+    aIpcHandler.join();
+
+    gtk_widget_destroy(pDummyDialog);
 
     if (restoreMainWindow)
         restoreMainWindow();
@@ -204,14 +235,6 @@ std::function<void()> Gtk3KDE5FilePickerIpc::blockMainWindow()
     };
 }
 
-void Gtk3KDE5FilePickerIpc::await(const std::future<void>& future)
-{
-    while (future.wait_for(std::chrono::milliseconds(1)) != std::future_status::ready)
-    {
-        GetGtkSalData()->Yield(false, true);
-    }
-}
-
 void Gtk3KDE5FilePickerIpc::writeResponseLine(const std::string& line)
 {
     sal_uInt64 bytesWritten = 0;
diff --git a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx
index 90ec4e1d55ab..a9584b11fcd2 100644
--- a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx
+++ b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx
@@ -30,7 +30,6 @@
 #include "filepicker_ipc_commands.hxx"
 
 #include <functional>
-#include <future>
 #include <mutex>
 #include <thread>
 #include <sstream>
@@ -105,43 +104,37 @@ public:
 
     template <typename... Args> void readResponse(uint64_t id, Args&... args)
     {
-        // read synchronously from a background thread and run the eventloop until the value becomes available
-        // this allows us to keep the GUI responsive and also enables access to the LO clipboard
         ArgsReader<Args...> argsReader(args...);
-        await(std::async(std::launch::async, [&]() {
-            while (true)
+        while (true)
+        {
+            // only let one thread read at any given time
+            std::lock_guard<std::mutex> lock(m_mutex);
+
+            // check if we need to read (and potentially wait) a response ID
+            if (m_incomingResponse == 0)
+            {
+                m_responseStream.clear();
+                m_responseStream.str(readResponseLine());
+                readIpcArgs(m_responseStream, m_incomingResponse);
+            }
+
+            if (m_incomingResponse == id)
             {
-                // only let one thread read at any given time
-                std::lock_guard<std::mutex> lock(m_mutex);
-
-                // check if we need to read (and potentially wait) a response ID
-                if (m_incomingResponse == 0)
-                {
-                    m_responseStream.clear();
-                    m_responseStream.str(readResponseLine());
-                    readIpcArgs(m_responseStream, m_incomingResponse);
-                }
-
-                if (m_incomingResponse == id)
-                {
-                    // the response we are waiting for came in
-                    argsReader(m_responseStream);
-                    m_incomingResponse = 0;
-                    break;
-                }
-                else
-                {
-                    // the next response answers some other request, yield
-                    std::this_thread::yield();
-                }
+                // the response we are waiting for came in
+                argsReader(m_responseStream);
+                m_incomingResponse = 0;
+                break;
             }
-        }));
+            else
+            {
+                // the next response answers some other request, yield
+                std::this_thread::yield();
+            }
+        }
     }
 
 private:
     std::function<void()> blockMainWindow();
-
-    static void await(const std::future<void>& future);
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list