From 7a7619d64ec8e3fd9b0727f40ac8c7aaade95319 Mon Sep 17 00:00:00 2001 From: hogliux Date: Wed, 26 Apr 2017 19:18:39 +0100 Subject: [PATCH] Fixed resizing issues and memory leaks in linux web browser component --- .../messages/juce_ApplicationBase.cpp | 9 +++ .../embedding/juce_XEmbedComponent.h | 6 +- .../juce_linux_X11_WebBrowserComponent.cpp | 60 ++++++++++++++++--- .../native/juce_linux_XEmbedComponent.cpp | 20 ++++--- 4 files changed, 78 insertions(+), 17 deletions(-) diff --git a/modules/juce_events/messages/juce_ApplicationBase.cpp b/modules/juce_events/messages/juce_ApplicationBase.cpp index ac6e8e1645..323e1c335d 100644 --- a/modules/juce_events/messages/juce_ApplicationBase.cpp +++ b/modules/juce_events/messages/juce_ApplicationBase.cpp @@ -177,6 +177,10 @@ StringArray JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameterArray() extern void initialiseNSApplication(); #endif +#if JUCE_LINUX && JUCE_MODULE_AVAILABLE_juce_gui_extra + extern int juce_gtkWebkitMain (int argc, const char* argv[]); +#endif + #if JUCE_WINDOWS const char* const* juce_argv = nullptr; int juce_argc = 0; @@ -218,6 +222,11 @@ int JUCEApplicationBase::main (int argc, const char* argv[], void* customDelegat initialiseNSApplication(); #endif + #if JUCE_LINUX && JUCE_MODULE_AVAILABLE_juce_gui_extra + if (argc >= 2 && String (argv[1]) == "--juce-gtkwebkitfork-child") + return juce_gtkWebkitMain (argc, argv); + #endif + #if JUCE_IOS return juce_iOSMain (argc, argv, customDelegate); #else diff --git a/modules/juce_gui_extra/embedding/juce_XEmbedComponent.h b/modules/juce_gui_extra/embedding/juce_XEmbedComponent.h index 6937fd1267..e951047a66 100644 --- a/modules/juce_gui_extra/embedding/juce_XEmbedComponent.h +++ b/modules/juce_gui_extra/embedding/juce_XEmbedComponent.h @@ -69,14 +69,16 @@ public: of the XEmbedProtocol. When using this version of the protocol you must call getHostWindowID() and pass this id to the foreign toolkit. */ - XEmbedComponent (bool wantsKeyboardFocus = true); + XEmbedComponent (bool wantsKeyboardFocus = true, + bool allowForeignWidgetToResizeComponent = false); /** Create a JUCE component wrapping the foreign widget with id wID Use this constructor if you are using the client initiated version of the XEmbedProtocol. */ - XEmbedComponent (unsigned long wID, bool wantsKeyboardFocus = true); + XEmbedComponent (unsigned long wID, bool wantsKeyboardFocus = true, + bool allowForeignWidgetToResizeComponent = false); /** Destructor. */ diff --git a/modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp b/modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp index 7aacb50d12..0baca3d3aa 100644 --- a/modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp +++ b/modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp @@ -21,6 +21,10 @@ ============================================================================== */ + +//============================================================================== +extern int juce_gtkWebkitMain (int argc, const char* argv[]); + class CommandReceiver { public: @@ -150,7 +154,7 @@ public: : outChannel (outChannelToUse), receiver (this, inChannel) {} - void entry() + int entry() { CommandReceiver::setBlocking (outChannel, true); @@ -197,6 +201,7 @@ public: receiver.tryNextRead(); gtk_main(); + return 0; } void goToURL (const var& params) @@ -256,7 +261,7 @@ public: void quit() { - exit (-1); + gtk_main_quit(); } bool onNavigation (String frameName, @@ -502,12 +507,25 @@ private: { xembed = nullptr; - kill (childProcess, SIGTERM); + int status = 0, result; - int status = 0; + result = waitpid (childProcess, &status, WNOHANG); + for (int i = 0; i < 15 && (! WIFEXITED(status) || result != childProcess); ++i) + { + Thread::sleep (100); + result = waitpid (childProcess, &status, WNOHANG); + } - while (! WIFEXITED(status)) - waitpid (childProcess, &status, 0); + // clean-up any zombies + status = 0; + if (! WIFEXITED(status) || result != childProcess) + { + do + { + kill (childProcess, SIGTERM); + waitpid (childProcess, &status, 0); + } while (! WIFEXITED(status)); + } childProcess = 0; } @@ -530,8 +548,24 @@ private: close (inPipe[0]); close (outPipe[1]); - GtkChildProcess child (outPipe[0], inPipe[1]); - child.entry(); + HeapBlock argv (5); + StringArray arguments; + + arguments.add (File::getSpecialLocation (File::currentExecutableFile).getFullPathName()); + arguments.add ("--juce-gtkwebkitfork-child"); + arguments.add (String (outPipe[0])); + arguments.add (String (inPipe [1])); + + for (int i = 0; i < arguments.size(); ++i) + argv[i] = arguments[i].toRawUTF8(); + + argv[4] = nullptr; + + #if JUCE_STANDALONE_APPLICATION + execv (arguments[0].toRawUTF8(), (char**) argv.getData()); + #else + juce_gtkWebkitMain (4, (const char**) argv.getData()); + #endif exit (0); } @@ -766,3 +800,13 @@ void WebBrowserComponent::clearCookies() // store cookies on linux jassertfalse; } + +int juce_gtkWebkitMain (int argc, const char* argv[]) +{ + if (argc != 4) return -1; + + + GtkChildProcess child (String (argv[2]).getIntValue(), + String (argv[3]).getIntValue()); + return child.entry(); +} diff --git a/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp b/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp index 6a735f187a..b6fcbdb76e 100644 --- a/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp +++ b/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp @@ -203,9 +203,10 @@ public: public: //============================================================================== - Pimpl (XEmbedComponent& parent, Window x11Window, bool wantsKeyboardFocus, bool isClientInitiated) + Pimpl (XEmbedComponent& parent, Window x11Window, + bool wantsKeyboardFocus, bool isClientInitiated, bool shouldAllowResize) : owner (parent), atoms (x11display.get()), clientInitiated (isClientInitiated), - wantsFocus (wantsKeyboardFocus) + wantsFocus (wantsKeyboardFocus), allowResize (shouldAllowResize) { if (widgets == nullptr) widgets = new Array; @@ -337,6 +338,7 @@ private: bool clientInitiated; bool wantsFocus = false; + bool allowResize = false; bool supportsXembed = false; bool hasBeenMapped = false; int xembedVersion = maxXEmbedVersionToSupport; @@ -582,7 +584,11 @@ private: propertyChanged (e.xproperty.atom); return true; case ConfigureNotify: - configureNotify(); + if (allowResize) + configureNotify(); + else + MessageManager::callAsync([this] () {componentMovedOrResized (owner, true, true);}); + return true; } } @@ -713,14 +719,14 @@ Array* XEmbedComponent::Pimpl::widgets = nullptr; HashMap* XEmbedComponent::Pimpl::SharedKeyWindow::keyWindows = nullptr; //============================================================================== -XEmbedComponent::XEmbedComponent (bool wantsKeyboardFocus) - : pimpl (new Pimpl (*this, 0, wantsKeyboardFocus, false)) +XEmbedComponent::XEmbedComponent (bool wantsKeyboardFocus, bool allowForeignWidgetToResizeComponent) + : pimpl (new Pimpl (*this, 0, wantsKeyboardFocus, false, allowForeignWidgetToResizeComponent)) { setOpaque (true); } -XEmbedComponent::XEmbedComponent (unsigned long wID, bool wantsKeyboardFocus) - : pimpl (new Pimpl (*this, wID, wantsKeyboardFocus, true)) +XEmbedComponent::XEmbedComponent (unsigned long wID, bool wantsKeyboardFocus, bool allowForeignWidgetToResizeComponent) + : pimpl (new Pimpl (*this, wID, wantsKeyboardFocus, true, allowForeignWidgetToResizeComponent)) { setOpaque (true); }