From 461192b35506ef0c5feb43235c916d7b7db2d802 Mon Sep 17 00:00:00 2001 From: ed Date: Mon, 20 Dec 2021 09:40:42 +0000 Subject: [PATCH] Add FocusOutline class for indicating Component keyboard focus --- examples/GUI/AccessibilityDemo.h | 4 + .../components/juce_Component.h | 18 ++ .../juce_gui_basics/desktop/juce_Desktop.cpp | 20 ++ .../juce_gui_basics/desktop/juce_Desktop.h | 3 + modules/juce_gui_basics/juce_gui_basics.cpp | 1 + modules/juce_gui_basics/juce_gui_basics.h | 2 + .../lookandfeel/juce_LookAndFeel.h | 60 ++++-- .../lookandfeel/juce_LookAndFeel_V2.cpp | 23 ++- .../lookandfeel/juce_LookAndFeel_V2.h | 3 +- .../juce_gui_basics/misc/juce_DropShadower.h | 17 +- .../misc/juce_FocusOutline.cpp | 185 ++++++++++++++++++ .../juce_gui_basics/misc/juce_FocusOutline.h | 100 ++++++++++ .../native/juce_win32_Windowing.cpp | 2 +- .../windows/juce_TopLevelWindow.cpp | 10 +- 14 files changed, 416 insertions(+), 32 deletions(-) create mode 100644 modules/juce_gui_basics/misc/juce_FocusOutline.cpp create mode 100644 modules/juce_gui_basics/misc/juce_FocusOutline.h diff --git a/examples/GUI/AccessibilityDemo.h b/examples/GUI/AccessibilityDemo.h index d6fcc048b9..88255e982e 100644 --- a/examples/GUI/AccessibilityDemo.h +++ b/examples/GUI/AccessibilityDemo.h @@ -190,10 +190,13 @@ private: ButtonsComponent() { addAndMakeVisible (radioButtons); + + textButton.setHasFocusOutline (true); addAndMakeVisible (textButton); shapeButton.setShape (getJUCELogoPath(), false, true, false); shapeButton.onClick = [] { AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, "Alert", "This is an AlertWindow"); }; + shapeButton.setHasFocusOutline (true); addAndMakeVisible (shapeButton); } @@ -217,6 +220,7 @@ private: { b.setRadioGroupId (1); b.setButtonText ("Button " + String (index++)); + b.setHasFocusOutline (true); addAndMakeVisible (b); } diff --git a/modules/juce_gui_basics/components/juce_Component.h b/modules/juce_gui_basics/components/juce_Component.h index d1b1c538ff..a53392c196 100644 --- a/modules/juce_gui_basics/components/juce_Component.h +++ b/modules/juce_gui_basics/components/juce_Component.h @@ -1475,6 +1475,23 @@ public: */ virtual std::unique_ptr createKeyboardFocusTraverser(); + /** Use this to indicate that the component should have an outline drawn around it + when it has keyboard focus. + + If this is set to true, then when the component gains keyboard focus the + LookAndFeel::createFocusOutlineForComponent() method will be used to draw an outline + around it. + + @see FocusOutline, hasFocusOutline + */ + void setHasFocusOutline (bool hasFocusOutline) noexcept { flags.hasFocusOutlineFlag = hasFocusOutline; } + + /** Returns true if this component should have a focus outline. + + @see FocusOutline, setHasFocusOutline + */ + bool hasFocusOutline() const noexcept { return flags.hasFocusOutlineFlag; } + //============================================================================== /** Returns true if the component (and all its parents) are enabled. @@ -2548,6 +2565,7 @@ private: bool isKeyboardFocusContainerFlag : 1; bool childKeyboardFocusedFlag : 1; bool dontFocusOnMouseClickFlag : 1; + bool hasFocusOutlineFlag : 1; bool alwaysOnTopFlag : 1; bool bufferToImageFlag : 1; bool bringToFrontOnClickFlag : 1; diff --git a/modules/juce_gui_basics/desktop/juce_Desktop.cpp b/modules/juce_gui_basics/desktop/juce_Desktop.cpp index 8035b700eb..a6df54ff85 100644 --- a/modules/juce_gui_basics/desktop/juce_Desktop.cpp +++ b/modules/juce_gui_basics/desktop/juce_Desktop.cpp @@ -189,6 +189,24 @@ void Desktop::addFocusChangeListener (FocusChangeListener* l) { focusListen void Desktop::removeFocusChangeListener (FocusChangeListener* l) { focusListeners.remove (l); } void Desktop::triggerFocusCallback() { triggerAsyncUpdate(); } +void Desktop::updateFocusOutline() +{ + if (auto* currentFocus = Component::getCurrentlyFocusedComponent()) + { + if (currentFocus->hasFocusOutline()) + { + focusOutline = currentFocus->getLookAndFeel().createFocusOutlineForComponent (*currentFocus); + + if (focusOutline != nullptr) + focusOutline->setOwner (currentFocus); + + return; + } + } + + focusOutline = nullptr; +} + void Desktop::handleAsyncUpdate() { // The component may be deleted during this operation, but we'll use a SafePointer rather than a @@ -197,6 +215,8 @@ void Desktop::handleAsyncUpdate() { l.globalFocusChanged (currentFocus.get()); }); + + updateFocusOutline(); } //============================================================================== diff --git a/modules/juce_gui_basics/desktop/juce_Desktop.h b/modules/juce_gui_basics/desktop/juce_Desktop.h index 93b630a9ba..f01279fda2 100644 --- a/modules/juce_gui_basics/desktop/juce_Desktop.h +++ b/modules/juce_gui_basics/desktop/juce_Desktop.h @@ -436,6 +436,8 @@ private: std::unique_ptr defaultLookAndFeel; WeakReference currentLookAndFeel; + std::unique_ptr focusOutline; + Component* kioskModeComponent = nullptr; Rectangle kioskComponentOriginalBounds; bool kioskModeReentrant = false; @@ -458,6 +460,7 @@ private: void setKioskComponent (Component*, bool shouldBeEnabled, bool allowMenusAndBars); void triggerFocusCallback(); + void updateFocusOutline(); void handleAsyncUpdate() override; static Point getMousePositionFloat(); diff --git a/modules/juce_gui_basics/juce_gui_basics.cpp b/modules/juce_gui_basics/juce_gui_basics.cpp index 00144767d2..1b053562b3 100644 --- a/modules/juce_gui_basics/juce_gui_basics.cpp +++ b/modules/juce_gui_basics/juce_gui_basics.cpp @@ -246,6 +246,7 @@ namespace juce #include "application/juce_Application.cpp" #include "misc/juce_BubbleComponent.cpp" #include "misc/juce_DropShadower.cpp" +#include "misc/juce_FocusOutline.cpp" #include "misc/juce_JUCESplashScreen.cpp" #include "layout/juce_FlexBox.cpp" diff --git a/modules/juce_gui_basics/juce_gui_basics.h b/modules/juce_gui_basics/juce_gui_basics.h index 09c618605a..5ad7379bc5 100644 --- a/modules/juce_gui_basics/juce_gui_basics.h +++ b/modules/juce_gui_basics/juce_gui_basics.h @@ -161,6 +161,7 @@ namespace juce class FlexBox; class Grid; + class FocusOutline; #if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX Image createSnapshotOfNativeWindow (void* nativeWindowHandle); @@ -259,6 +260,7 @@ namespace juce #include "menus/juce_BurgerMenuComponent.h" #include "buttons/juce_ToolbarButton.h" #include "misc/juce_DropShadower.h" +#include "misc/juce_FocusOutline.h" #include "misc/juce_JUCESplashScreen.h" #include "widgets/juce_TreeView.h" #include "windows/juce_TopLevelWindow.h" diff --git a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.h b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.h index a62101604e..f0ba366640 100644 --- a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.h +++ b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.h @@ -153,7 +153,9 @@ public: Colour findColour (int colourId) const noexcept; /** Registers a colour to be used for a particular purpose. + For more details, see the comments for findColour(). + @see findColour, Component::findColour, Component::setColour */ void setColour (int colourId, Colour colour) noexcept; @@ -165,22 +167,27 @@ public: //============================================================================== /** Returns the typeface that should be used for a given font. + The default implementation just does what you'd expect it to, but you can override this if you want to intercept fonts and use your own custom typeface object. + @see setDefaultTypeface */ virtual Typeface::Ptr getTypefaceForFont (const Font&); /** Allows you to supply a default typeface that will be returned as the default sans-serif font. + Instead of a typeface object, you can specify a typeface by name using the setDefaultSansSerifTypefaceName() method. + You can perform more complex typeface substitutions by overloading getTypefaceForFont() but this lets you easily set a global typeface. */ void setDefaultSansSerifTypeface (Typeface::Ptr newDefaultTypeface); /** Allows you to change the default sans-serif font. + If you need to supply your own Typeface object for any of the default fonts, rather than just supplying the name (e.g. if you want to use an embedded font), then you can instead call setDefaultSansSerifTypeface() with an object to use. @@ -188,39 +195,64 @@ public: void setDefaultSansSerifTypefaceName (const String& newName); //============================================================================== - /** Override this to get the chance to swap a component's mouse cursor for a - customised one. + /** Sets whether native alert windows (if available) or standard JUCE AlertWindows + drawn with AlertWindow::LookAndFeelMethods will be used. + + @see isUsingNativeAlertWindows */ - virtual MouseCursor getMouseCursorFor (Component&); - - //============================================================================== - /** Creates a new graphics context object. */ - virtual std::unique_ptr createGraphicsContext (const Image& imageToRenderOn, - Point origin, - const RectangleList& initialClip); - void setUsingNativeAlertWindows (bool shouldUseNativeAlerts); + + /** Returns true if native alert windows will be used (if available). + + The default setting for this is false. + + @see setUsingNativeAlertWindows + */ bool isUsingNativeAlertWindows(); //============================================================================== /** Draws a small image that spins to indicate that something's happening. + This method should use the current time to animate itself, so just keep repainting it every so often. */ virtual void drawSpinningWaitAnimation (Graphics&, const Colour& colour, int x, int y, int w, int h) = 0; - //============================================================================== /** Returns a tick shape for use in yes/no boxes, etc. */ virtual Path getTickShape (float height) = 0; + /** Returns a cross shape for use in yes/no boxes, etc. */ virtual Path getCrossShape (float height) = 0; - //============================================================================== - virtual DropShadower* createDropShadowerForComponent (Component*) = 0; + /** Creates a drop-shadower for a given component, if required. + + @see DropShadower + */ + virtual std::unique_ptr createDropShadowerForComponent (Component&) = 0; + + /** Creates a focus outline for a given component, if required. + + @see FocusOutline + */ + virtual std::unique_ptr createFocusOutlineForComponent (Component&) = 0; //============================================================================== - /** Plays the system's default 'beep' noise, to alert the user about something very important. */ + /** Override this to get the chance to swap a component's mouse cursor for a + customised one. + + @see MouseCursor + */ + virtual MouseCursor getMouseCursorFor (Component&); + + /** Creates a new graphics context object. */ + virtual std::unique_ptr createGraphicsContext (const Image& imageToRenderOn, + Point origin, + const RectangleList& initialClip); + + /** Plays the system's default 'beep' noise, to alert the user about something + very important. This is only supported on some platforms. + */ virtual void playAlertSound(); private: diff --git a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp index 6295b0a51c..79d004bef4 100644 --- a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp +++ b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp @@ -2056,9 +2056,28 @@ int LookAndFeel_V2::getDefaultMenuBarHeight() } //============================================================================== -DropShadower* LookAndFeel_V2::createDropShadowerForComponent (Component*) +std::unique_ptr LookAndFeel_V2::createDropShadowerForComponent (Component&) { - return new DropShadower (DropShadow (Colours::black.withAlpha (0.4f), 10, Point (0, 2))); + return std::make_unique (DropShadow (Colours::black.withAlpha (0.4f), 10, Point (0, 2))); +} + +std::unique_ptr LookAndFeel_V2::createFocusOutlineForComponent (Component&) +{ + struct WindowProperties : public FocusOutline::OutlineWindowProperties + { + Rectangle getOutlineBounds (Component& c) override + { + return c.getScreenBounds(); + } + + void drawOutline (Graphics& g, int width, int height) override + { + g.setColour (Colours::yellow.withAlpha (0.6f)); + g.drawRoundedRectangle ({ (float) width, (float) height }, 3.0f, 3.0f); + } + }; + + return std::make_unique (std::make_unique()); } //============================================================================== diff --git a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h index 425b3410e1..0a2cd69e8c 100644 --- a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h +++ b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h @@ -299,7 +299,8 @@ public: bool positionTitleBarButtonsOnLeft) override; //============================================================================== - DropShadower* createDropShadowerForComponent (Component*) override; + std::unique_ptr createDropShadowerForComponent (Component&) override; + std::unique_ptr createFocusOutlineForComponent (Component&) override; //============================================================================== void drawStretchableLayoutResizerBar (Graphics&, int w, int h, bool isVerticalBar, diff --git a/modules/juce_gui_basics/misc/juce_DropShadower.h b/modules/juce_gui_basics/misc/juce_DropShadower.h index 38babb5a30..84384c4beb 100644 --- a/modules/juce_gui_basics/misc/juce_DropShadower.h +++ b/modules/juce_gui_basics/misc/juce_DropShadower.h @@ -55,17 +55,8 @@ public: /** Attaches the DropShadower to the component you want to shadow. */ void setOwner (Component* componentToFollow); - private: //============================================================================== - class ShadowWindow; - - WeakReference owner; - OwnedArray shadowWindows; - DropShadow shadow; - bool reentrant = false; - WeakReference lastParentComp; - void componentMovedOrResized (Component&, bool, bool) override; void componentBroughtToFront (Component&) override; void componentChildrenChanged (Component&) override; @@ -75,6 +66,14 @@ private: void updateParent(); void updateShadows(); + class ShadowWindow; + + WeakReference owner; + OwnedArray shadowWindows; + DropShadow shadow; + bool reentrant = false; + WeakReference lastParentComp; + class ParentVisibilityChangedListener; std::unique_ptr visibilityChangedListener; diff --git a/modules/juce_gui_basics/misc/juce_FocusOutline.cpp b/modules/juce_gui_basics/misc/juce_FocusOutline.cpp new file mode 100644 index 0000000000..b2171b6c3f --- /dev/null +++ b/modules/juce_gui_basics/misc/juce_FocusOutline.cpp @@ -0,0 +1,185 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2020 - Raw Material Software Limited + + JUCE is an open source library subject to commercial or open-source + licensing. + + By using JUCE, you agree to the terms of both the JUCE 6 End-User License + Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). + + End User License Agreement: www.juce.com/juce-6-licence + Privacy Policy: www.juce.com/juce-privacy-policy + + Or: You may also use this code under the terms of the GPL v3 (see + www.gnu.org/licenses). + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ + +//============================================================================== +struct OutlineWindowComponent : public Component +{ + OutlineWindowComponent (Component* c, FocusOutline::OutlineWindowProperties& p) + : target (c), props (p) + { + setVisible (true); + setInterceptsMouseClicks (false, false); + + if (target->isOnDesktop()) + { + setSize (1, 1); + addToDesktop (ComponentPeer::windowIgnoresMouseClicks + | ComponentPeer::windowIsTemporary + | ComponentPeer::windowIgnoresKeyPresses); + } + else if (auto* parent = target->getParentComponent()) + { + auto targetIndex = parent->getIndexOfChildComponent (target); + parent->addChildComponent (this, targetIndex + 1); + } + } + + void paint (Graphics& g) override + { + if (target != nullptr) + props.drawOutline (g, getWidth(), getHeight()); + } + + void resized() override + { + repaint(); + } + + float getDesktopScaleFactor() const override + { + return target != nullptr ? target->getDesktopScaleFactor() + : Component::getDesktopScaleFactor(); + } + +private: + WeakReference target; + FocusOutline::OutlineWindowProperties& props; + + JUCE_DECLARE_NON_COPYABLE (OutlineWindowComponent) +}; + +//============================================================================== +FocusOutline::FocusOutline (std::unique_ptr props) + : properties (std::move (props)) +{ +} + +FocusOutline::~FocusOutline() +{ + if (owner != nullptr) + owner->removeComponentListener (this); + + if (lastParentComp != nullptr) + lastParentComp->removeComponentListener (this); +} + +void FocusOutline::setOwner (Component* componentToFollow) +{ + if (componentToFollow != owner) + { + if (owner != nullptr) + owner->removeComponentListener (this); + + owner = componentToFollow; + + if (owner != nullptr) + owner->addComponentListener (this); + + updateParent(); + updateOutlineWindow(); + } +} + +void FocusOutline::componentMovedOrResized (Component& c, bool, bool) +{ + if (owner == &c) + updateOutlineWindow(); +} + +void FocusOutline::componentBroughtToFront (Component& c) +{ + if (owner == &c) + updateOutlineWindow(); +} + +void FocusOutline::componentParentHierarchyChanged (Component& c) +{ + if (owner == &c) + { + updateParent(); + updateOutlineWindow(); + } +} + +void FocusOutline::componentVisibilityChanged (Component& c) +{ + if (owner == &c) + updateOutlineWindow(); +} + +void FocusOutline::updateParent() +{ + lastParentComp = (owner != nullptr ? owner->getParentComponent() + : nullptr); +} + +void FocusOutline::updateOutlineWindow() +{ + if (reentrant) + return; + + const ScopedValueSetter setter (reentrant, true); + + if (owner == nullptr) + { + outlineWindow = nullptr; + return; + } + + if (owner->isShowing() + && owner->getWidth() > 0 && owner->getHeight() > 0) + { + if (outlineWindow == nullptr) + outlineWindow = std::make_unique (owner, *properties); + + WeakReference deletionChecker (outlineWindow.get()); + + outlineWindow->setAlwaysOnTop (owner->isAlwaysOnTop()); + + if (deletionChecker == nullptr) + return; + + const auto windowBounds = [this] + { + const auto bounds = properties->getOutlineBounds (*owner); + + if (lastParentComp != nullptr) + return lastParentComp->getLocalArea (nullptr, bounds); + + return bounds; + }(); + + outlineWindow->setBounds (windowBounds); + } + else + { + outlineWindow = nullptr; + } +} + +} // namespace juce diff --git a/modules/juce_gui_basics/misc/juce_FocusOutline.h b/modules/juce_gui_basics/misc/juce_FocusOutline.h new file mode 100644 index 0000000000..9bd94030da --- /dev/null +++ b/modules/juce_gui_basics/misc/juce_FocusOutline.h @@ -0,0 +1,100 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2020 - Raw Material Software Limited + + JUCE is an open source library subject to commercial or open-source + licensing. + + By using JUCE, you agree to the terms of both the JUCE 6 End-User License + Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). + + End User License Agreement: www.juce.com/juce-6-licence + Privacy Policy: www.juce.com/juce-privacy-policy + + Or: You may also use this code under the terms of the GPL v3 (see + www.gnu.org/licenses). + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ + +/** + Adds a focus outline to a component. + + This object creates and manages a component that sits on top of a target + component. It will track the position of the target component and will be + brought to the front with the tracked component. + + Use the Component::setHasFocusOutline() method to indicate that a component + should have a focus outline drawn around it, and when it receives keyboard + focus one of these objects will be created using the + LookAndFeel::createFocusOutlineForComponent() method. You can override this + method in your own LookAndFeel classes to draw a custom outline if required. + + @tags{GUI} +*/ +class JUCE_API FocusOutline : private ComponentListener +{ +public: + //============================================================================== + /** Defines the focus outline window properties. + + Pass an instance of one of these to the FocusOutline constructor to control + the bounds for the outline window and how it is drawn. + */ + struct JUCE_API OutlineWindowProperties + { + virtual ~OutlineWindowProperties() = default; + + /** Return the bounds for the outline window in screen coordinates. */ + virtual Rectangle getOutlineBounds (Component& focusedComponent) = 0; + + /** This method will be called to draw the focus outline. */ + virtual void drawOutline (Graphics&, int width, int height) = 0; + }; + + //============================================================================== + /** Creates a FocusOutline. + + Call setOwner to attach it to a component. + */ + FocusOutline (std::unique_ptr props); + + /** Destructor. */ + ~FocusOutline() override; + + /** Attaches the outline to a component. */ + void setOwner (Component* componentToFollow); + +private: + //============================================================================== + void componentMovedOrResized (Component&, bool, bool) override; + void componentBroughtToFront (Component&) override; + void componentParentHierarchyChanged (Component&) override; + void componentVisibilityChanged (Component&) override; + + void updateOutlineWindow(); + void updateParent(); + + //============================================================================== + std::unique_ptr properties; + + WeakReference owner; + std::unique_ptr outlineWindow; + WeakReference lastParentComp; + + bool reentrant = false; + + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FocusOutline) +}; + +} // namespace juce diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index 5276bde666..c58995d0cc 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -2452,7 +2452,7 @@ private: if (! component.isCurrentlyModal() && (styleFlags & windowHasDropShadow) != 0 && ((! hasTitleBar()) || SystemStats::getOperatingSystemType() < SystemStats::WinVista)) { - shadower.reset (component.getLookAndFeel().createDropShadowerForComponent (&component)); + shadower = component.getLookAndFeel().createDropShadowerForComponent (component); if (shadower != nullptr) shadower->setOwner (&component); diff --git a/modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp b/modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp index 5ad7efa7d7..9982ce03b1 100644 --- a/modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp +++ b/modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp @@ -150,7 +150,7 @@ TopLevelWindow::TopLevelWindow (const String& name, const bool shouldAddToDeskto TopLevelWindow::~TopLevelWindow() { - shadower.reset(); + shadower = nullptr; TopLevelWindowManager::getInstance()->removeWindow (this); } @@ -213,7 +213,7 @@ void TopLevelWindow::setDropShadowEnabled (const bool useShadow) if (isOnDesktop()) { - shadower.reset(); + shadower = nullptr; Component::addToDesktop (getDesktopWindowStyleFlags()); } else @@ -222,7 +222,7 @@ void TopLevelWindow::setDropShadowEnabled (const bool useShadow) { if (shadower == nullptr) { - shadower.reset (getLookAndFeel().createDropShadowerForComponent (this)); + shadower = getLookAndFeel().createDropShadowerForComponent (*this); if (shadower != nullptr) shadower->setOwner (this); @@ -230,7 +230,7 @@ void TopLevelWindow::setDropShadowEnabled (const bool useShadow) } else { - shadower.reset(); + shadower = nullptr; } } } @@ -257,7 +257,7 @@ void TopLevelWindow::recreateDesktopWindow() void TopLevelWindow::addToDesktop() { - shadower.reset(); + shadower = nullptr; Component::addToDesktop (getDesktopWindowStyleFlags()); setDropShadowEnabled (isDropShadowEnabled()); // force an update to clear away any fake shadows if necessary. }