LMMS
Loading...
Searching...
No Matches
juce_DropShadower.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
30{
31public:
33 : target (comp), shadow (ds)
34 {
35 setVisible (true);
36 setAccessible (false);
37 setInterceptsMouseClicks (false, false);
38
39 if (comp->isOnDesktop())
40 {
41 #if JUCE_WINDOWS
42 const auto scope = [&]() -> std::unique_ptr<ScopedThreadDPIAwarenessSetter>
43 {
44 if (comp != nullptr)
45 if (auto* handle = comp->getWindowHandle())
46 return std::make_unique<ScopedThreadDPIAwarenessSetter> (handle);
47
48 return nullptr;
49 }();
50 #endif
51
52 setSize (1, 1); // to keep the OS happy by not having zero-size windows
56 }
57 else if (Component* const parent = comp->getParentComponent())
58 {
59 parent->addChildComponent (this);
60 }
61 }
62
63 void paint (Graphics& g) override
64 {
65 if (Component* c = target)
66 shadow.drawForRectangle (g, getLocalArea (c, c->getLocalBounds()));
67 }
68
69 void resized() override
70 {
71 repaint(); // (needed for correct repainting)
72 }
73
74 float getDesktopScaleFactor() const override
75 {
76 if (target != nullptr)
77 return target->getDesktopScaleFactor();
78
80 }
81
82private:
85
87};
88
90 private Timer
91{
92public:
104
106 {
107 for (auto& compEntry : observedComponents)
108 if (auto* comp = compEntry.get())
109 comp->removeComponentListener (this);
110 }
111
112 void componentVisibilityChanged (Component& component) override
113 {
114 if (root != &component)
115 listener->componentVisibilityChanged (*root);
116 }
117
119 {
120 if (root == &component)
122 }
123
125
126private:
128 {
129 public:
131 : ptr (&c), ref (&c) {}
132
133 Component* get() const { return ref.get(); }
134
135 bool operator< (const ComponentWithWeakReference& other) const { return ptr < other.ptr; }
136
137 private:
140 };
141
143 {
144 const auto lastSeenComponents = std::exchange (observedComponents, [&]
145 {
146 std::set<ComponentWithWeakReference> result;
147
148 for (auto node = root; node != nullptr; node = node->getParentComponent())
149 result.emplace (*node);
150
151 return result;
152 }());
153
154 const auto withDifference = [] (const auto& rangeA, const auto& rangeB, auto&& callback)
155 {
156 std::vector<ComponentWithWeakReference> result;
157 std::set_difference (rangeA.begin(), rangeA.end(), rangeB.begin(), rangeB.end(), std::back_inserter (result));
158
159 for (const auto& item : result)
160 if (auto* c = item.get())
161 callback (*c);
162 };
163
164 withDifference (lastSeenComponents, observedComponents, [this] (auto& comp) { comp.removeComponentListener (this); });
165 withDifference (observedComponents, lastSeenComponents, [this] (auto& comp) { comp.addComponentListener (this); });
166 }
167
168 void timerCallback() override
169 {
170 WeakReference<DropShadower> deletionChecker { static_cast<DropShadower*> (listener) };
171
172 const auto wasOnVirtualDesktop = std::exchange (isOnVirtualDesktop,
173 isWindowOnCurrentVirtualDesktop (root->getWindowHandle()));
174
175 // on Windows, isWindowOnCurrentVirtualDesktop() may cause synchronous messages to be dispatched
176 // to the HWND so we need to check if the shadower is still valid after calling
177 if (deletionChecker == nullptr)
178 return;
179
180 if (isOnVirtualDesktop != wasOnVirtualDesktop)
181 listener->componentVisibilityChanged (*root);
182 }
183
184 Component* root = nullptr;
186 std::set<ComponentWithWeakReference> observedComponents;
188
191};
192
193//==============================================================================
195
197{
198 if (owner != nullptr)
199 {
200 owner->removeComponentListener (this);
201 owner = nullptr;
202 }
203
204 updateParent();
205
206 const ScopedValueSetter<bool> setter (reentrant, true);
207 shadowWindows.clear();
208}
209
210void DropShadower::setOwner (Component* componentToFollow)
211{
212 if (componentToFollow != owner)
213 {
214 if (owner != nullptr)
215 owner->removeComponentListener (this);
216
217 // (the component can't be null)
218 jassert (componentToFollow != nullptr);
219
220 owner = componentToFollow;
221 jassert (owner != nullptr);
222
223 updateParent();
224 owner->addComponentListener (this);
225
226 // The visibility of `owner` is transitively affected by the visibility of its parents. Thus we need to trigger the
227 // componentVisibilityChanged() event in case it changes for any of the parents.
228 visibilityChangedListener = std::make_unique<ParentVisibilityChangedListener> (*owner,
229 static_cast<ComponentListener&> (*this));
230
232 }
233}
234
236{
238 p->removeComponentListener (this);
239
240 lastParentComp = owner != nullptr ? owner->getParentComponent() : nullptr;
241
243 p->addComponentListener (this);
244}
245
246void DropShadower::componentMovedOrResized (Component& c, bool /*wasMoved*/, bool /*wasResized*/)
247{
248 if (owner == &c)
250}
251
257
262
264{
265 if (owner == &c)
266 {
267 updateParent();
269 }
270}
271
277
279{
280 if (reentrant)
281 return;
282
283 const ScopedValueSetter<bool> setter (reentrant, true);
284
285 if (owner != nullptr
286 && owner->isShowing()
287 && owner->getWidth() > 0 && owner->getHeight() > 0
288 && (Desktop::canUseSemiTransparentWindows() || owner->getParentComponent() != nullptr)
289 && (visibilityChangedListener != nullptr && visibilityChangedListener->isWindowOnVirtualDesktop()))
290 {
291 while (shadowWindows.size() < 4)
293
294 const int shadowEdge = jmax (shadow.offset.x, shadow.offset.y) + shadow.radius;
295 const int x = owner->getX();
296 const int y = owner->getY() - shadowEdge;
297 const int w = owner->getWidth();
298 const int h = owner->getHeight() + shadowEdge + shadowEdge;
299
300 for (int i = 4; --i >= 0;)
301 {
302 // there seem to be rare situations where the dropshadower may be deleted by
303 // callbacks during this loop, so use a weak ref to watch out for this..
305
306 if (sw != nullptr)
307 {
308 sw->setAlwaysOnTop (owner->isAlwaysOnTop());
309
310 if (sw == nullptr)
311 return;
312
313 switch (i)
314 {
315 case 0: sw->setBounds (x - shadowEdge, y, shadowEdge, h); break;
316 case 1: sw->setBounds (x + w, y, shadowEdge, h); break;
317 case 2: sw->setBounds (x, y, w, shadowEdge); break;
318 case 3: sw->setBounds (x, owner->getBottom(), w, shadowEdge); break;
319 default: break;
320 }
321
322 if (sw == nullptr)
323 return;
324
325 sw->toBehind (i == 3 ? owner.get() : shadowWindows.getUnchecked (i + 1));
326 }
327 }
328 }
329 else
330 {
331 shadowWindows.clear();
332 }
333}
334
335} // namespace juce
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
static Audio_Scope * scope
Definition player.cpp:26
Definition juce_Component.h:36
void setAccessible(bool shouldBeAccessible)
Definition juce_Component.cpp:3273
void setInterceptsMouseClicks(bool allowClicksOnThisComponent, bool allowClicksOnChildComponents) noexcept
Definition juce_Component.cpp:1420
Rectangle< int > getLocalArea(const Component *sourceComponent, Rectangle< int > areaRelativeToSourceComponent) const
Definition juce_Component.cpp:1138
void repaint()
Definition juce_Component.cpp:1917
Component() noexcept
Definition juce_Component.cpp:517
virtual void addToDesktop(int windowStyleFlags, void *nativeWindowToAttachTo=nullptr)
Definition juce_Component.cpp:658
void setSize(int newWidth, int newHeight)
Definition juce_Component.cpp:1262
virtual void setVisible(bool shouldBeVisible)
Definition juce_Component.cpp:575
virtual float getDesktopScaleFactor() const
Definition juce_Component.cpp:826
Definition juce_ComponentListener.h:43
@ windowIsTemporary
Definition juce_ComponentPeer.h:52
@ windowIgnoresKeyPresses
Definition juce_ComponentPeer.h:71
@ windowIgnoresMouseClicks
Definition juce_ComponentPeer.h:54
static bool canUseSemiTransparentWindows() noexcept
Definition juce_linux_Windowing.cpp:603
WeakReference< Component > ref
Definition juce_DropShadower.cpp:139
ComponentWithWeakReference(Component &c)
Definition juce_DropShadower.cpp:130
Component * get() const
Definition juce_DropShadower.cpp:133
Definition juce_DropShadower.cpp:91
void updateParentHierarchy()
Definition juce_DropShadower.cpp:142
bool isWindowOnVirtualDesktop() const noexcept
Definition juce_DropShadower.cpp:124
ParentVisibilityChangedListener(Component &r, ComponentListener &l)
Definition juce_DropShadower.cpp:93
~ParentVisibilityChangedListener() override
Definition juce_DropShadower.cpp:105
Component * root
Definition juce_DropShadower.cpp:184
void componentVisibilityChanged(Component &component) override
Definition juce_DropShadower.cpp:112
void timerCallback() override
Definition juce_DropShadower.cpp:168
bool isOnVirtualDesktop
Definition juce_DropShadower.cpp:187
ComponentListener * listener
Definition juce_DropShadower.cpp:185
void componentParentHierarchyChanged(Component &component) override
Definition juce_DropShadower.cpp:118
std::set< ComponentWithWeakReference > observedComponents
Definition juce_DropShadower.cpp:186
Definition juce_DropShadower.cpp:30
float getDesktopScaleFactor() const override
Definition juce_DropShadower.cpp:74
void paint(Graphics &g) override
Definition juce_DropShadower.cpp:63
DropShadow shadow
Definition juce_DropShadower.cpp:84
void resized() override
Definition juce_DropShadower.cpp:69
WeakReference< Component > target
Definition juce_DropShadower.cpp:83
ShadowWindow(Component *comp, const DropShadow &ds)
Definition juce_DropShadower.cpp:32
std::unique_ptr< ParentVisibilityChangedListener > visibilityChangedListener
Definition juce_DropShadower.h:78
OwnedArray< Component > shadowWindows
Definition juce_DropShadower.h:72
void componentParentHierarchyChanged(Component &) override
Definition juce_DropShadower.cpp:263
void componentChildrenChanged(Component &) override
Definition juce_DropShadower.cpp:258
void componentBroughtToFront(Component &) override
Definition juce_DropShadower.cpp:252
bool reentrant
Definition juce_DropShadower.h:74
void updateShadows()
Definition juce_DropShadower.cpp:278
DropShadower(const DropShadow &shadowType)
Definition juce_DropShadower.cpp:194
DropShadow shadow
Definition juce_DropShadower.h:73
void componentVisibilityChanged(Component &) override
Definition juce_DropShadower.cpp:272
~DropShadower() override
Definition juce_DropShadower.cpp:196
void setOwner(Component *componentToFollow)
Definition juce_DropShadower.cpp:210
void componentMovedOrResized(Component &, bool, bool) override
Definition juce_DropShadower.cpp:246
void updateParent()
Definition juce_DropShadower.cpp:235
WeakReference< Component > lastParentComp
Definition juce_DropShadower.h:75
WeakReference< Component > owner
Definition juce_DropShadower.h:71
Definition juce_GraphicsContext.h:45
Definition juce_ScopedValueSetter.h:55
@ Windows
Definition juce_SystemStats.h:49
static OperatingSystemType getOperatingSystemType()
Definition juce_linux_SystemStats.cpp:52
Timer() noexcept
Definition juce_Timer.cpp:316
void startTimerHz(int timerFrequencyHz) noexcept
Definition juce_Timer.cpp:349
Definition juce_WeakReference.h:78
UINT_D64 w
Definition inflate.c:942
int * l
Definition inflate.c:1579
int y
Definition inflate.c:1588
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
unsigned x[BMAX+1]
Definition inflate.c:1586
static uintptr_t parent
Definition pugl.h:1644
#define jassert(expression)
#define JUCE_DECLARE_NON_MOVEABLE(className)
#define JUCE_DECLARE_NON_COPYABLE(className)
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
Definition carla_juce.cpp:31
bool isWindowOnCurrentVirtualDesktop(void *)
Definition juce_gui_basics.cpp:408
Definition juce_DropShadowEffect.h:36
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
int r
Definition crypt.c:458
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
int result
Definition process.c:1455
#define const
Definition zconf.h:137