From 596686a957c80b82771483ef489d76a9feacd95c Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 16 Nov 2020 17:30:53 +0000 Subject: [PATCH] One more fix from upstream --- .../native/juce_linux_Windowing.cpp | 16 +- .../native/x11/juce_linux_XWindowSystem.cpp | 143 +++++++++++++----- .../native/x11/juce_linux_XWindowSystem.h | 34 ++++- 3 files changed, 144 insertions(+), 49 deletions(-) diff --git a/libs/juce-current/source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp b/libs/juce-current/source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp index df074840..6e6cfbed 100644 --- a/libs/juce-current/source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp +++ b/libs/juce-current/source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp @@ -330,11 +330,17 @@ private: class LinuxRepaintManager : public Timer { public: - LinuxRepaintManager (LinuxComponentPeer& p) : peer (p) {} + LinuxRepaintManager (LinuxComponentPeer& p) + : peer (p), + isSemiTransparentWindow ((peer.getStyleFlags() & ComponentPeer::windowIsSemiTransparent) != 0) + { + } void timerCallback() override { - if (XWindowSystem::getInstance()->getNumPaintsPending (peer.windowH) > 0) + XWindowSystem::getInstance()->processPendingPaintsForWindow (peer.windowH); + + if (XWindowSystem::getInstance()->getNumPaintsPendingForWindow (peer.windowH) > 0) return; if (! regionsNeedingRepaint.isEmpty()) @@ -359,7 +365,7 @@ private: void performAnyPendingRepaintsNow() { - if (XWindowSystem::getInstance()->getNumPaintsPending (peer.windowH) > 0) + if (XWindowSystem::getInstance()->getNumPaintsPendingForWindow (peer.windowH) > 0) { startTimer (repaintTimerPeriod); return; @@ -374,7 +380,8 @@ private: if (image.isNull() || image.getWidth() < totalArea.getWidth() || image.getHeight() < totalArea.getHeight()) { - image = XWindowSystem::getInstance()->createImage (totalArea.getWidth(), totalArea.getHeight(), + image = XWindowSystem::getInstance()->createImage (isSemiTransparentWindow, + totalArea.getWidth(), totalArea.getHeight(), useARGBImagesForRendering); } @@ -407,6 +414,7 @@ private: enum { repaintTimerPeriod = 1000 / 100 }; LinuxComponentPeer& peer; + const bool isSemiTransparentWindow; Image image; uint32 lastTimeImageUsed = 0; RectangleList regionsNeedingRepaint; diff --git a/libs/juce-current/source/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp b/libs/juce-current/source/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp index 4daaf102..af659001 100644 --- a/libs/juce-current/source/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp +++ b/libs/juce-current/source/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp @@ -643,16 +643,13 @@ namespace Visuals } //================================= X11 - Bitmap =============================== -static std::unordered_map<::Window, int> shmPaintsPendingMap; - class XBitmapImage : public ImagePixelData { public: - XBitmapImage (::Display* d, Image::PixelFormat format, int w, int h, + XBitmapImage (Image::PixelFormat format, int w, int h, bool clearImage, unsigned int imageDepth_, Visual* visual) : ImagePixelData (format, w, h), - imageDepth (imageDepth_), - display (d) + imageDepth (imageDepth_) { jassert (format == Image::RGB || format == Image::ARGB); @@ -807,6 +804,11 @@ public: { XWindowSystemUtilities::ScopedXLock xLock; + #if JUCE_USE_XSHM + if (isUsingXShm()) + XWindowSystem::getInstance()->addPendingPaintForWindow (window); + #endif + if (gc == None) { XGCValues gcvalues; @@ -856,10 +858,7 @@ public: // blit results to screen. #if JUCE_USE_XSHM if (isUsingXShm()) - { X11Symbols::getInstance()->xShmPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh, True); - ++shmPaintsPendingMap[window]; - } else #endif X11Symbols::getInstance()->xPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh); @@ -878,7 +877,7 @@ private: int pixelStride, lineStride; uint8* imageData = nullptr; GC gc = None; - ::Display* display = nullptr; + ::Display* display = XWindowSystem::getInstance()->getDisplay(); #if JUCE_USE_XSHM XShmSegmentInfo segmentInfo; @@ -1305,6 +1304,13 @@ static int getAllEventsMask (bool ignoresMouseClicks) XWindowSystemUtilities::ScopedXLock xLock; + auto root = X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)); + + auto visualAndDepth = displayVisuals->getBestVisualForWindow ((styleFlags & ComponentPeer::windowIsSemiTransparent) != 0); + + auto colormap = X11Symbols::getInstance()->xCreateColormap (display, root, visualAndDepth.visual, AllocNone); + X11Symbols::getInstance()->xInstallColormap (display, colormap); + // Set up the window attributes XSetWindowAttributes swa; swa.border_pixel = 0; @@ -1313,11 +1319,9 @@ static int getAllEventsMask (bool ignoresMouseClicks) swa.override_redirect = ((styleFlags & ComponentPeer::windowIsTemporary) != 0) ? True : False; swa.event_mask = getAllEventsMask (styleFlags & ComponentPeer::windowIgnoresMouseClicks); - auto root = X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display)); - auto windowH = X11Symbols::getInstance()->xCreateWindow (display, parentToAddTo != 0 ? parentToAddTo : root, 0, 0, 1, 1, - 0, depth, InputOutput, visual, + 0, visualAndDepth.depth, InputOutput, visualAndDepth.visual, CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect, &swa); @@ -1423,7 +1427,10 @@ void XWindowSystem::destroyWindow (::Window windowH) &event) == True) {} - shmPaintsPendingMap.erase (windowH); + #if JUCE_USE_XSHM + if (XSHMHelpers::isShmAvailable (display)) + shmPaintsPendingMap.erase (windowH); + #endif } //============================================================================== @@ -1808,16 +1815,18 @@ bool XWindowSystem::canUseARGBImages() const return canUseARGB; } -Image XWindowSystem::createImage (int width, int height, bool argb) const +Image XWindowSystem::createImage (bool isSemiTransparent, int width, int height, bool argb) const { + auto visualAndDepth = displayVisuals->getBestVisualForWindow (isSemiTransparent); + #if JUCE_USE_XSHM - return Image (new XBitmapImage (display, argb ? Image::ARGB : Image::RGB, + return Image (new XBitmapImage (argb ? Image::ARGB : Image::RGB, #else - return Image (new XBitmapImage (display, Image::RGB, + return Image (new XBitmapImage (Image::RGB, #endif (width + 31) & ~31, (height + 31) & ~31, - false, (unsigned int) depth, visual)); + false, (unsigned int) visualAndDepth.depth, visualAndDepth.visual)); } void XWindowSystem::blitToWindow (::Window windowH, Image image, Rectangle destinationRect, Rectangle totalRect) const @@ -1833,20 +1842,47 @@ void XWindowSystem::blitToWindow (::Window windowH, Image image, Rectangle destinationRect.getX() - totalRect.getX(), destinationRect.getY() - totalRect.getY()); } -int XWindowSystem::getNumPaintsPending (::Window windowH) const +void XWindowSystem::processPendingPaintsForWindow (::Window windowH) { #if JUCE_USE_XSHM - if (shmPaintsPendingMap[windowH] != 0) + if (! XSHMHelpers::isShmAvailable (display)) + return; + + if (getNumPaintsPendingForWindow (windowH) > 0) { XWindowSystemUtilities::ScopedXLock xLock; XEvent evt; while (X11Symbols::getInstance()->xCheckTypedWindowEvent (display, windowH, shmCompletionEvent, &evt)) - --shmPaintsPendingMap[windowH]; + removePendingPaintForWindow (windowH); } #endif +} + +int XWindowSystem::getNumPaintsPendingForWindow (::Window windowH) +{ + #if JUCE_USE_XSHM + if (XSHMHelpers::isShmAvailable (display)) + return shmPaintsPendingMap[windowH]; + #endif + + return 0; +} + +void XWindowSystem::addPendingPaintForWindow (::Window windowH) +{ + #if JUCE_USE_XSHM + if (XSHMHelpers::isShmAvailable (display)) + ++shmPaintsPendingMap[windowH]; + #endif +} - return shmPaintsPendingMap[windowH]; +void XWindowSystem::removePendingPaintForWindow (::Window windowH) +{ + #if JUCE_USE_XSHM + if (XSHMHelpers::isShmAvailable (display)) + --shmPaintsPendingMap[windowH]; + #endif } void XWindowSystem::setScreenSaverEnabled (bool enabled) const @@ -2710,6 +2746,40 @@ long XWindowSystem::getUserTime (::Window windowH) const return result; } +XWindowSystem::DisplayVisuals::DisplayVisuals (::Display* xDisplay) +{ + auto findVisualWithDepthOrNull = [&] (int desiredDepth) -> Visual* + { + int matchedDepth = 0; + auto* visual = Visuals::findVisualFormat (xDisplay, desiredDepth, matchedDepth); + + if (desiredDepth == matchedDepth) + return visual; + + return nullptr; + }; + + visual16Bit = findVisualWithDepthOrNull (16); + visual24Bit = findVisualWithDepthOrNull (24); + visual32Bit = findVisualWithDepthOrNull (32); +} + +XWindowSystem::VisualAndDepth XWindowSystem::DisplayVisuals::getBestVisualForWindow (bool isSemiTransparent) const +{ + if (isSemiTransparent && visual32Bit != nullptr) + return { visual32Bit, 32 }; + + if (visual24Bit != nullptr) + return { visual24Bit, 24 }; + + return { visual16Bit, 16 }; +} + +bool XWindowSystem::DisplayVisuals::isValid() const noexcept +{ + return (visual32Bit != nullptr || visual24Bit != nullptr || visual16Bit != nullptr); +} + //============================================================================== bool XWindowSystem::initialiseXDisplay() { @@ -2743,7 +2813,8 @@ bool XWindowSystem::initialiseXDisplay() // Create our message window (this will never be mapped) auto screen = X11Symbols::getInstance()->xDefaultScreen (display); - juce_messageWindowHandle = X11Symbols::getInstance()->xCreateWindow (display, X11Symbols::getInstance()->xRootWindow (display, screen), + auto root = X11Symbols::getInstance()->xRootWindow (display, screen); + juce_messageWindowHandle = X11Symbols::getInstance()->xCreateWindow (display, root, 0, 0, 1, 1, 0, 0, InputOnly, X11Symbols::getInstance()->xDefaultVisual (display, screen), CWEventMask, &swa); @@ -2752,22 +2823,6 @@ bool XWindowSystem::initialiseXDisplay() atoms = XWindowSystemUtilities::Atoms (display); - // Get defaults for various properties - auto root = X11Symbols::getInstance()->xRootWindow (display, screen); - - // Try to obtain a 32-bit visual or fallback to 24 or 16 - visual = Visuals::findVisualFormat (display, 32, depth); - - if (visual == nullptr) - { - Logger::outputDebugString ("ERROR: System doesn't support 32, 24 or 16 bit RGB display.\n"); - Process::terminate(); - } - - // Create and install a colormap suitable for our visual - colormap = X11Symbols::getInstance()->xCreateColormap (display, root, visual, AllocNone); - X11Symbols::getInstance()->xInstallColormap (display, colormap); - initialisePointerMap(); updateModifierMappings(); @@ -2776,6 +2831,14 @@ bool XWindowSystem::initialiseXDisplay() shmCompletionEvent = X11Symbols::getInstance()->xShmGetEventBase (display) + ShmCompletion; #endif + displayVisuals = std::make_unique (display); + + if (! displayVisuals->isValid()) + { + Logger::outputDebugString ("ERROR: System doesn't support 32, 24 or 16 bit RGB display.\n"); + Process::terminate(); + } + // Setup input event handler LinuxEventLoop::registerFdCallback (X11Symbols::getInstance()->xConnectionNumber (display), [this] (int) @@ -2823,10 +2886,10 @@ void XWindowSystem::destroyXDisplay() X11Symbols::getInstance()->xSync (display, True); LinuxEventLoop::unregisterFdCallback (X11Symbols::getInstance()->xConnectionNumber (display)); - visual = nullptr; X11Symbols::getInstance()->xCloseDisplay (display); display = nullptr; + displayVisuals = nullptr; } } @@ -2905,7 +2968,7 @@ void XWindowSystem::handleWindowMessage (LinuxComponentPeer<::Window>* peer, XEv XWindowSystemUtilities::ScopedXLock xLock; if (event.xany.type == shmCompletionEvent) - --shmPaintsPendingMap[(::Window) peer->getNativeHandle()]; + XWindowSystem::getInstance()->removePendingPaintForWindow ((::Window) peer->getNativeHandle()); } #endif break; diff --git a/libs/juce-current/source/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h b/libs/juce-current/source/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h index 6644a65f..7d20959e 100644 --- a/libs/juce-current/source/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h +++ b/libs/juce-current/source/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h @@ -126,9 +126,12 @@ public: bool canUseSemiTransparentWindows() const; bool canUseARGBImages() const; - int getNumPaintsPending (::Window windowH) const; + int getNumPaintsPendingForWindow (::Window windowH); + void processPendingPaintsForWindow (::Window windowH); + void addPendingPaintForWindow (::Window windowH); + void removePendingPaintForWindow (::Window windowH); - Image createImage (int width, int height, bool argb) const; + Image createImage (bool isSemiTransparentWindow, int width, int height, bool argb) const; void blitToWindow (::Window windowH, Image image, Rectangle destinationRect, Rectangle totalRect) const; void setScreenSaverEnabled (bool enabled) const; @@ -171,6 +174,24 @@ private: ~XWindowSystem(); //============================================================================== + struct VisualAndDepth + { + Visual* visual; + int depth; + }; + + struct DisplayVisuals + { + explicit DisplayVisuals (::Display* d); + + VisualAndDepth getBestVisualForWindow (bool isSemiTransparent) const; + bool isValid() const noexcept; + + Visual* visual16Bit = nullptr; + Visual* visual24Bit = nullptr; + Visual* visual32Bit = nullptr; + }; + bool initialiseXDisplay(); void destroyXDisplay(); @@ -217,10 +238,13 @@ private: XWindowSystemUtilities::Atoms atoms; ::Display* display = nullptr; - Colormap colormap = {}; - Visual* visual = nullptr; + std::unique_ptr displayVisuals; + + #if JUCE_USE_XSHM + std::map<::Window, int> shmPaintsPendingMap; + #endif - int depth = 0, shmCompletionEvent = 0; + int shmCompletionEvent = 0; int pointerMap[5] = {}; String localClipboardContent;