The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. extern XContext windowHandleXContext;
  21. /* Attaches a pointer to a given window, so that it can be retrieved with XFindContext on
  22. the windowHandleXContext.
  23. */
  24. class ScopedWindowAssociation
  25. {
  26. public:
  27. ScopedWindowAssociation() = default;
  28. ScopedWindowAssociation (void* associatedIn, Window windowIn)
  29. : associatedPointer ([&]() -> void*
  30. {
  31. if (associatedIn == nullptr)
  32. return nullptr;
  33. // If you hit this, there's already a pointer associated with this window.
  34. const auto display = XWindowSystem::getInstance()->getDisplay();
  35. jassert (! getAssociatedPointer (display, windowIn).has_value());
  36. if (X11Symbols::getInstance()->xSaveContext (display,
  37. static_cast<XID> (windowIn),
  38. windowHandleXContext,
  39. unalignedPointerCast<XPointer> (associatedIn)) != 0)
  40. {
  41. jassertfalse;
  42. return nullptr;
  43. }
  44. return associatedIn;
  45. }()),
  46. window (static_cast<XID> (windowIn)) {}
  47. ScopedWindowAssociation (const ScopedWindowAssociation&) = delete;
  48. ScopedWindowAssociation& operator= (const ScopedWindowAssociation&) = delete;
  49. ScopedWindowAssociation (ScopedWindowAssociation&& other) noexcept
  50. : associatedPointer (std::exchange (other.associatedPointer, nullptr)), window (other.window) {}
  51. ScopedWindowAssociation& operator= (ScopedWindowAssociation&& other) noexcept
  52. {
  53. ScopedWindowAssociation { std::move (other) }.swap (*this);
  54. return *this;
  55. }
  56. ~ScopedWindowAssociation() noexcept
  57. {
  58. if (associatedPointer == nullptr)
  59. return;
  60. const auto display = XWindowSystem::getInstance()->getDisplay();
  61. const auto ptr = getAssociatedPointer (display, window);
  62. if (! ptr.has_value())
  63. {
  64. // If you hit this, something else has cleared this association before we were able to.
  65. jassertfalse;
  66. return;
  67. }
  68. jassert (unalignedPointerCast<XPointer> (associatedPointer) == *ptr);
  69. if (X11Symbols::getInstance()->xDeleteContext (display, window, windowHandleXContext) != 0)
  70. jassertfalse;
  71. }
  72. bool isValid() const { return associatedPointer != nullptr; }
  73. private:
  74. static std::optional<XPointer> getAssociatedPointer (Display* display, Window window)
  75. {
  76. XPointer ptr{};
  77. if (X11Symbols::getInstance()->xFindContext (display, window, windowHandleXContext, &ptr) != 0)
  78. return std::nullopt;
  79. return ptr;
  80. }
  81. void swap (ScopedWindowAssociation& other) noexcept
  82. {
  83. std::swap (other.associatedPointer, associatedPointer);
  84. std::swap (other.window, window);
  85. }
  86. void* associatedPointer = nullptr;
  87. XID window{};
  88. };
  89. } // namespace juce