From effdc661caac041fbedf4f54945ad60f11549e95 Mon Sep 17 00:00:00 2001 From: hogliux Date: Wed, 8 Jul 2015 17:09:59 +0100 Subject: [PATCH] Fix correct repainting of OpenGLContexts if a non-compositing window manager is used on linux --- .../native/juce_linux_Windowing.cpp | 39 +++++++++++++++++ .../juce_opengl/native/juce_OpenGL_linux.h | 43 +++++++++++++++++-- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp index 03cb822817..06b40e7b69 100644 --- a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp @@ -2320,6 +2320,10 @@ public: XEvent nextEvent; ScopedXLock xlock; + // if we have opengl contexts then just repaint them all + // regardless if this is really necessary + repaintOpenGLContexts (); + if (exposeEvent.window != windowH) { Window child; @@ -2509,6 +2513,28 @@ public: return currentScaleFactor; } + //=============================================================================== + void addOpenGLRepaintListener (Component* dummy) + { + if (dummy != nullptr) + glRepaintListeners.addIfNotAlreadyThere (dummy); + } + + void removeOpenGLRepaintListener (Component* dummy) + { + if (dummy != nullptr) + glRepaintListeners.removeAllInstancesOf (dummy); + } + + void repaintOpenGLContexts() + { + for (int i = 0; i < glRepaintListeners.size(); ++i) + { + if (Component* c = glRepaintListeners [i]) + c->handleCommandMessage (0); + } + } + //============================================================================== bool dontRepaint; @@ -2668,6 +2694,7 @@ private: BorderSize windowBorder; bool isAlwaysOnTop; double currentScaleFactor; + Array glRepaintListeners; enum { KeyPressEventType = 2 }; struct MotifWmHints @@ -4124,6 +4151,18 @@ Rectangle juce_LinuxScaledToPhysicalBounds(ComponentPeer* peer, const Recta return retval; } +void juce_LinuxAddRepaintListener (ComponentPeer* peer, Component* dummy) +{ + if (LinuxComponentPeer* linuxPeer = dynamic_cast (peer)) + linuxPeer->addOpenGLRepaintListener (dummy); +} + +void juce_LinuxRemoveRepaintListener (ComponentPeer* peer, Component* dummy) +{ + if (LinuxComponentPeer* linuxPeer = dynamic_cast (peer)) + linuxPeer->removeOpenGLRepaintListener (dummy); +} + //============================================================================== #if JUCE_MODAL_LOOPS_PERMITTED void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType iconType, diff --git a/modules/juce_opengl/native/juce_OpenGL_linux.h b/modules/juce_opengl/native/juce_OpenGL_linux.h index f5d8991a72..9af3ad7f19 100644 --- a/modules/juce_opengl/native/juce_OpenGL_linux.h +++ b/modules/juce_opengl/native/juce_OpenGL_linux.h @@ -28,11 +28,31 @@ extern XContext windowHandleXContext; //============================================================================== // Defined juce_linux_Windowing.cpp -Rectangle juce_LinuxScaledToPhysicalBounds(ComponentPeer* peer, const Rectangle& bounds); +Rectangle juce_LinuxScaledToPhysicalBounds (ComponentPeer* peer, const Rectangle& bounds); +void juce_LinuxAddRepaintListener (ComponentPeer* peer, Component* dummy); +void juce_LinuxRemoveRepaintListener (ComponentPeer* peer, Component* dummy); //============================================================================== class OpenGLContext::NativeContext { +private: + class DummyComponent : public Component + { + public: + DummyComponent (OpenGLContext::NativeContext& nativeParentContext) + : native (nativeParentContext) + { + } + + void handleCommandMessage (int commandId) override + { + if (commandId == 0) + native.triggerRepaint(); + } + private: + OpenGLContext::NativeContext& native; + }; + public: NativeContext (Component& comp, const OpenGLPixelFormat& cPixelFormat, @@ -40,7 +60,7 @@ public: bool /*useMultisampling*/, OpenGLVersion) : component (comp), renderContext (0), embeddedWindow (0), swapFrames (0), bestVisual (0), - contextToShareWith (shareContext) + contextToShareWith (shareContext), context (nullptr), dummy (*this) { ScopedXLock xlock; XSync (display, False); @@ -96,10 +116,14 @@ public: XFreeColormap (display, colourMap); XSync (display, False); + + juce_LinuxAddRepaintListener (peer, &dummy); } ~NativeContext() { + juce_LinuxRemoveRepaintListener (component.getPeer(), &dummy); + if (embeddedWindow != 0) { ScopedXLock xlock; @@ -111,15 +135,17 @@ public: XFree (bestVisual); } - void initialiseOnRenderThread (OpenGLContext& context) + void initialiseOnRenderThread (OpenGLContext& c) { ScopedXLock xlock; renderContext = glXCreateContext (display, bestVisual, (GLXContext) contextToShareWith, GL_TRUE); - context.makeActive(); + c.makeActive(); + context = &c; } void shutdownOnRenderThread() { + context = nullptr; deactivateCurrentContext(); glXDestroyContext (display, renderContext); renderContext = nullptr; @@ -183,6 +209,12 @@ public: void* getRawContext() const noexcept { return renderContext; } GLuint getFrameBufferID() const noexcept { return 0; } + void triggerRepaint() + { + if (context != nullptr) + context->triggerRepaint(); + } + struct Locker { Locker (NativeContext&) {} }; private: @@ -195,6 +227,9 @@ private: XVisualInfo* bestVisual; void* contextToShareWith; + OpenGLContext* context; + DummyComponent dummy; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext) };