summaryrefslogtreecommitdiff
path: root/vcl/unx/gtk3_kde5
diff options
context:
space:
mode:
authorMichael Weghorn <m.weghorn@posteo.de>2018-10-02 16:13:51 +0200
committerMichael Weghorn <m.weghorn@posteo.de>2018-10-08 09:00:08 +0200
commit788716cebad012513cc2798589b817b86cbf1bbc (patch)
tree03d312458ee33a3833144b012e0e2d42fc5e8f5f /vcl/unx/gtk3_kde5
parent3b36855e48f6ef3f4e52e998c52c531fe5191477 (diff)
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@posteo.de>
Diffstat (limited to 'vcl/unx/gtk3_kde5')
-rw-r--r--vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx43
-rw-r--r--vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx55
2 files changed, 57 insertions, 41 deletions
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: */