From ea6d095ab5884cf731d433ae0a07ced4e8a1a7e5 Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 14 Sep 2021 17:03:46 +0100 Subject: [PATCH] XWindowSystem: Implement createSnapshotOfNativeWindow --- modules/juce_gui_basics/juce_gui_basics.h | 2 +- .../native/x11/juce_linux_X11_Symbols.cpp | 1 + .../native/x11/juce_linux_X11_Symbols.h | 4 ++ .../native/x11/juce_linux_XWindowSystem.cpp | 68 ++++++++++++++++--- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/modules/juce_gui_basics/juce_gui_basics.h b/modules/juce_gui_basics/juce_gui_basics.h index 9c2947267e..1ba0c2832e 100644 --- a/modules/juce_gui_basics/juce_gui_basics.h +++ b/modules/juce_gui_basics/juce_gui_basics.h @@ -162,7 +162,7 @@ namespace juce class FlexBox; class Grid; - #if JUCE_MAC || JUCE_WINDOWS + #if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX Image createSnapshotOfNativeWindow (void* nativeWindowHandle); #endif } diff --git a/modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp b/modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp index 0be22fa56b..aecb639fb1 100644 --- a/modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp +++ b/modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp @@ -127,6 +127,7 @@ bool X11Symbols::loadAllSymbols() makeSymbolBinding (xGetErrorDatabaseText, "XGetErrorDatabaseText"), makeSymbolBinding (xGetErrorText, "XGetErrorText"), makeSymbolBinding (xGetGeometry, "XGetGeometry"), + makeSymbolBinding (xGetImage, "XGetImage"), makeSymbolBinding (xGetInputFocus, "XGetInputFocus"), makeSymbolBinding (xGetModifierMapping, "XGetModifierMapping"), makeSymbolBinding (xGetPointerMapping, "XGetPointerMapping"), diff --git a/modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h b/modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h index f7ab58bca7..3cb386061e 100644 --- a/modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h +++ b/modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h @@ -237,6 +237,10 @@ public: (::Display*, ::Drawable, ::Window*, int*, int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*), Status) + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetImage, xGetImage, + (::Display*, ::Drawable, int, int, unsigned int, unsigned int, unsigned long, int), + XImage*) + JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XGetInputFocus, xGetInputFocus, (::Display*, ::Window*, int*), void) diff --git a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp index ca8668aa09..e595d9e527 100644 --- a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp +++ b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp @@ -676,6 +676,16 @@ namespace Visuals class XBitmapImage : public ImagePixelData { public: + explicit XBitmapImage (XImage* image) + : ImagePixelData (image->depth == 24 ? Image::RGB : Image::ARGB, image->width, image->height), + xImage (image), + imageDepth ((unsigned int) xImage->depth) + { + pixelStride = xImage->bits_per_pixel / 8; + lineStride = xImage->bytes_per_line; + imageData = reinterpret_cast (xImage->data); + } + XBitmapImage (Image::PixelFormat format, int w, int h, bool clearImage, unsigned int imageDepth_, Visual* visual) : ImagePixelData (format, w, h), @@ -699,8 +709,8 @@ public: segmentInfo.shmaddr = (char *) -1; segmentInfo.readOnly = False; - xImage = X11Symbols::getInstance()->xShmCreateImage (display, visual, imageDepth, ZPixmap, nullptr, - &segmentInfo, (unsigned int) w, (unsigned int) h); + xImage.reset (X11Symbols::getInstance()->xShmCreateImage (display, visual, imageDepth, ZPixmap, nullptr, + &segmentInfo, (unsigned int) w, (unsigned int) h)); if (xImage != nullptr) { @@ -739,7 +749,7 @@ public: imageDataAllocated.allocate ((size_t) (lineStride * h), format == Image::ARGB && clearImage); imageData = imageDataAllocated; - xImage = (XImage*) ::calloc (1, sizeof (XImage)); + xImage.reset ((XImage*) ::calloc (1, sizeof (XImage))); xImage->width = w; xImage->height = h; @@ -773,7 +783,7 @@ public: xImage->blue_mask = visual->blue_mask; } - if (! X11Symbols::getInstance()->xInitImage (xImage)) + if (! X11Symbols::getInstance()->xInitImage (xImage.get())) jassertfalse; } } @@ -791,7 +801,6 @@ public: X11Symbols::getInstance()->xShmDetach (display, &segmentInfo); X11Symbols::getInstance()->xFlush (display); - X11Symbols::getInstance()->xDestroyImage (xImage); shmdt (segmentInfo.shmaddr); shmctl (segmentInfo.shmid, IPC_RMID, nullptr); @@ -800,7 +809,6 @@ public: #endif { xImage->data = nullptr; - X11Symbols::getInstance()->xDestroyImage (xImage); } } @@ -877,7 +885,7 @@ public: auto* pixel = (PixelRGB*) p; p += srcData.pixelStride; - X11Symbols::getInstance()->xPutPixel (xImage, x, y, + X11Symbols::getInstance()->xPutPixel (xImage.get(), x, y, (((((uint32) pixel->getRed()) << rShiftL) >> rShiftR) & rMask) | (((((uint32) pixel->getGreen()) << gShiftL) >> gShiftR) & gMask) | (((((uint32) pixel->getBlue()) << bShiftL) >> bShiftR) & bMask)); @@ -888,10 +896,10 @@ 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); + X11Symbols::getInstance()->xShmPutImage (display, (::Drawable) window, gc, xImage.get(), sx, sy, dx, dy, dw, dh, True); else #endif - X11Symbols::getInstance()->xPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh); + X11Symbols::getInstance()->xPutImage (display, (::Drawable) window, gc, xImage.get(), sx, sy, dx, dy, dw, dh); } #if JUCE_USE_XSHM @@ -900,7 +908,15 @@ public: private: //============================================================================== - XImage* xImage = nullptr; + struct Deleter + { + void operator() (XImage* img) const noexcept + { + X11Symbols::getInstance()->xDestroyImage (img); + } + }; + + std::unique_ptr xImage; const unsigned int imageDepth; HeapBlock imageDataAllocated; HeapBlock imageData16Bit; @@ -3709,4 +3725,36 @@ void XWindowSystem::windowMessageReceive (XEvent& event) //============================================================================== JUCE_IMPLEMENT_SINGLETON (XWindowSystem) +Image createSnapshotOfNativeWindow (void* window) +{ + ::Window root; + int wx, wy; + unsigned int ww, wh, bw, bitDepth; + + XWindowSystemUtilities::ScopedXLock xLock; + + const auto display = XWindowSystem::getInstance()->getDisplay(); + + if (! X11Symbols::getInstance()->xGetGeometry (display, (::Drawable) window, &root, &wx, &wy, &ww, &wh, &bw, &bitDepth)) + return {}; + + const auto scale = [] + { + if (auto* d = Desktop::getInstance().getDisplays().getPrimaryDisplay()) + return d->scale; + + return 1.0; + }(); + + auto image = Image { new XBitmapImage { X11Symbols::getInstance()->xGetImage (display, + (::Drawable) window, + 0, + 0, + ww, + wh, + AllPlanes, + ZPixmap) } }; + return image.rescaled ((int) ((double) ww / scale), (int) ((double) wh / scale)); +} + } // namespace juce