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

New commits:
commit dbc22cf3ba6cbf00e64f04ae348fddd4ba4efb17
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Tue Oct 2 16:13:51 2018 +0200
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Mon Oct 8 15:00:12 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.
    
     Conflicts:
            vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx
    
    Reviewed-on: https://gerrit.libreoffice.org/61253
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>
    (cherry picked from commit 788716cebad012513cc2798589b817b86cbf1bbc)
    
    Change-Id: I3d663253f09320f7a8e0d9ec32a8fd6ec191c189
    Reviewed-on: https://gerrit.libreoffice.org/61534
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>
    Tested-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx 
b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx
index 34ebfa322f07..a190e522e500 100644
--- a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx
+++ b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx
@@ -110,6 +110,17 @@ OUString getResString(sal_Int32 aResId)
     return ResId(aResId, *ImplGetResMgr()).toString();
 }
 
+// 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()
@@ -147,9 +158,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();
@@ -208,14 +239,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 a6b6f9098300..68d2739e0f36 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,42 +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: */
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to