| @@ -1,6 +1,31 @@ | |||||
| JUCE breaking changes | JUCE breaking changes | ||||
| ===================== | ===================== | ||||
| develop | |||||
| ======= | |||||
| Change | |||||
| ------ | |||||
| The return type of XWindowSystem::getBorderSize() was changed to | |||||
| ComponentPeer::OptionalBorderSize. | |||||
| Possible Issues | |||||
| --------------- | |||||
| User code that uses XWindowSystem::getBorderSize() will fail to build. | |||||
| Workaround | |||||
| ---------- | |||||
| Use operator bool() to determine the validity of the new return value and | |||||
| access the contained value using operator*(). | |||||
| Rationale | |||||
| --------- | |||||
| The XWindow system cannot immediately report the correct border size after | |||||
| window creation. The underlying X11 calls will signal whether querying the | |||||
| border size was successful, but there was no way to forward this information | |||||
| through XWindowSystem::getBorderSize() until this change. | |||||
| Version 6.1.5 | Version 6.1.5 | ||||
| ============= | ============= | ||||
| @@ -270,6 +270,7 @@ private: | |||||
| bool isFocused() const override { return true; } | bool isFocused() const override { return true; } | ||||
| void grabFocus() override {} | void grabFocus() override {} | ||||
| void* getNativeHandle() const override { return nullptr; } | void* getNativeHandle() const override { return nullptr; } | ||||
| OptionalBorderSize getFrameSizeIfPresent() const override { return {}; } | |||||
| BorderSize<int> getFrameSize() const override { return {}; } | BorderSize<int> getFrameSize() const override { return {}; } | ||||
| void setVisible (bool) override {} | void setVisible (bool) override {} | ||||
| void setTitle (const String&) override {} | void setTitle (const String&) override {} | ||||
| @@ -631,6 +631,12 @@ public: | |||||
| (float) localPos.y * scale)); | (float) localPos.y * scale)); | ||||
| } | } | ||||
| OptionalBorderSize getFrameSizeIfPresent() const override | |||||
| { | |||||
| // TODO | |||||
| return {}; | |||||
| } | |||||
| BorderSize<int> getFrameSize() const override | BorderSize<int> getFrameSize() const override | ||||
| { | { | ||||
| // TODO | // TODO | ||||
| @@ -211,24 +211,25 @@ public: | |||||
| controller = [newController retain]; | controller = [newController retain]; | ||||
| } | } | ||||
| Rectangle<int> getBounds() const override { return getBounds (! isSharedWindow); } | |||||
| Rectangle<int> getBounds() const override { return getBounds (! isSharedWindow); } | |||||
| Rectangle<int> getBounds (bool global) const; | Rectangle<int> getBounds (bool global) const; | ||||
| Point<float> localToGlobal (Point<float> relativePosition) override; | Point<float> localToGlobal (Point<float> relativePosition) override; | ||||
| Point<float> globalToLocal (Point<float> screenPosition) override; | Point<float> globalToLocal (Point<float> screenPosition) override; | ||||
| using ComponentPeer::localToGlobal; | using ComponentPeer::localToGlobal; | ||||
| using ComponentPeer::globalToLocal; | using ComponentPeer::globalToLocal; | ||||
| void setAlpha (float newAlpha) override; | void setAlpha (float newAlpha) override; | ||||
| void setMinimised (bool) override {} | |||||
| bool isMinimised() const override { return false; } | |||||
| void setMinimised (bool) override {} | |||||
| bool isMinimised() const override { return false; } | |||||
| void setFullScreen (bool shouldBeFullScreen) override; | void setFullScreen (bool shouldBeFullScreen) override; | ||||
| bool isFullScreen() const override { return fullScreen; } | |||||
| bool isFullScreen() const override { return fullScreen; } | |||||
| bool contains (Point<int> localPos, bool trueIfInAChildWindow) const override; | bool contains (Point<int> localPos, bool trueIfInAChildWindow) const override; | ||||
| BorderSize<int> getFrameSize() const override { return BorderSize<int>(); } | |||||
| OptionalBorderSize getFrameSizeIfPresent() const override { return {}; } | |||||
| BorderSize<int> getFrameSize() const override { return BorderSize<int>(); } | |||||
| bool setAlwaysOnTop (bool alwaysOnTop) override; | bool setAlwaysOnTop (bool alwaysOnTop) override; | ||||
| void toFront (bool makeActiveWindow) override; | void toFront (bool makeActiveWindow) override; | ||||
| void toBehind (ComponentPeer* other) override; | void toBehind (ComponentPeer* other) override; | ||||
| void setIcon (const Image& newIcon) override; | void setIcon (const Image& newIcon) override; | ||||
| StringArray getAvailableRenderingEngines() override { return StringArray ("CoreGraphics Renderer"); } | |||||
| StringArray getAvailableRenderingEngines() override { return StringArray ("CoreGraphics Renderer"); } | |||||
| void drawRect (CGRect); | void drawRect (CGRect); | ||||
| bool canBecomeKeyWindow(); | bool canBecomeKeyWindow(); | ||||
| @@ -141,11 +141,17 @@ public: | |||||
| return bounds; | return bounds; | ||||
| } | } | ||||
| BorderSize<int> getFrameSize() const override | |||||
| OptionalBorderSize getFrameSizeIfPresent() const override | |||||
| { | { | ||||
| return windowBorder; | return windowBorder; | ||||
| } | } | ||||
| BorderSize<int> getFrameSize() const override | |||||
| { | |||||
| const auto optionalBorderSize = getFrameSizeIfPresent(); | |||||
| return optionalBorderSize ? (*optionalBorderSize) : BorderSize<int>(); | |||||
| } | |||||
| Point<float> localToGlobal (Point<float> relativePosition) override | Point<float> localToGlobal (Point<float> relativePosition) override | ||||
| { | { | ||||
| return relativePosition + getScreenPosition (false).toFloat(); | return relativePosition + getScreenPosition (false).toFloat(); | ||||
| @@ -362,9 +368,14 @@ public: | |||||
| void updateBorderSize() | void updateBorderSize() | ||||
| { | { | ||||
| if ((styleFlags & windowHasTitleBar) == 0) | if ((styleFlags & windowHasTitleBar) == 0) | ||||
| windowBorder = {}; | |||||
| else if (windowBorder.getTopAndBottom() == 0 && windowBorder.getLeftAndRight() == 0) | |||||
| { | |||||
| windowBorder = ComponentPeer::OptionalBorderSize { BorderSize<int>() }; | |||||
| } | |||||
| else if (! windowBorder | |||||
| || ((*windowBorder).getTopAndBottom() == 0 && (*windowBorder).getLeftAndRight() == 0)) | |||||
| { | |||||
| windowBorder = XWindowSystem::getInstance()->getBorderSize (windowH); | windowBorder = XWindowSystem::getInstance()->getBorderSize (windowH); | ||||
| } | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -504,7 +515,7 @@ private: | |||||
| ::Window windowH = {}, parentWindow = {}; | ::Window windowH = {}, parentWindow = {}; | ||||
| Rectangle<int> bounds; | Rectangle<int> bounds; | ||||
| BorderSize<int> windowBorder; | |||||
| ComponentPeer::OptionalBorderSize windowBorder; | |||||
| bool fullScreen = false, isAlwaysOnTop = false; | bool fullScreen = false, isAlwaysOnTop = false; | ||||
| double currentScaleFactor = 1.0; | double currentScaleFactor = 1.0; | ||||
| Array<Component*> glRepaintListeners; | Array<Component*> glRepaintListeners; | ||||
| @@ -493,12 +493,12 @@ public: | |||||
| : (v == view); | : (v == view); | ||||
| } | } | ||||
| BorderSize<int> getFrameSize() const override | |||||
| OptionalBorderSize getFrameSizeIfPresent() const override | |||||
| { | { | ||||
| BorderSize<int> b; | |||||
| if (! isSharedWindow) | if (! isSharedWindow) | ||||
| { | { | ||||
| BorderSize<int> b; | |||||
| NSRect v = [view convertRect: [view frame] toView: nil]; | NSRect v = [view convertRect: [view frame] toView: nil]; | ||||
| NSRect w = [window frame]; | NSRect w = [window frame]; | ||||
| @@ -506,9 +506,19 @@ public: | |||||
| b.setBottom ((int) v.origin.y); | b.setBottom ((int) v.origin.y); | ||||
| b.setLeft ((int) v.origin.x); | b.setLeft ((int) v.origin.x); | ||||
| b.setRight ((int) (w.size.width - (v.origin.x + v.size.width))); | b.setRight ((int) (w.size.width - (v.origin.x + v.size.width))); | ||||
| return OptionalBorderSize { b }; | |||||
| } | } | ||||
| return b; | |||||
| return {}; | |||||
| } | |||||
| BorderSize<int> getFrameSize() const override | |||||
| { | |||||
| if (const auto frameSize = getFrameSizeIfPresent()) | |||||
| return *frameSize; | |||||
| return {}; | |||||
| } | } | ||||
| bool hasNativeTitleBar() const | bool hasNativeTitleBar() const | ||||
| @@ -1764,6 +1764,11 @@ public: | |||||
| return w == hwnd || (trueIfInAChildWindow && (IsChild (hwnd, w) != 0)); | return w == hwnd || (trueIfInAChildWindow && (IsChild (hwnd, w) != 0)); | ||||
| } | } | ||||
| OptionalBorderSize getFrameSizeIfPresent() const override | |||||
| { | |||||
| return ComponentPeer::OptionalBorderSize { windowBorder }; | |||||
| } | |||||
| BorderSize<int> getFrameSize() const override | BorderSize<int> getFrameSize() const override | ||||
| { | { | ||||
| return windowBorder; | return windowBorder; | ||||
| @@ -1802,7 +1802,7 @@ bool XWindowSystem::contains (::Window windowH, Point<int> localPos) const | |||||
| && child == None; | && child == None; | ||||
| } | } | ||||
| BorderSize<int> XWindowSystem::getBorderSize (::Window windowH) const | |||||
| ComponentPeer::OptionalBorderSize XWindowSystem::getBorderSize (::Window windowH) const | |||||
| { | { | ||||
| jassert (windowH != 0); | jassert (windowH != 0); | ||||
| @@ -1824,7 +1824,7 @@ BorderSize<int> XWindowSystem::getBorderSize (::Window windowH) const | |||||
| data += sizeof (unsigned long); | data += sizeof (unsigned long); | ||||
| } | } | ||||
| return { (int) sizes[2], (int) sizes[0], (int) sizes[3], (int) sizes[1] }; | |||||
| return ComponentPeer::OptionalBorderSize ({ (int) sizes[2], (int) sizes[0], (int) sizes[3], (int) sizes[1] }); | |||||
| } | } | ||||
| } | } | ||||
| @@ -181,8 +181,8 @@ public: | |||||
| void setBounds (::Window, Rectangle<int>, bool fullScreen) const; | void setBounds (::Window, Rectangle<int>, bool fullScreen) const; | ||||
| void updateConstraints (::Window) const; | void updateConstraints (::Window) const; | ||||
| BorderSize<int> getBorderSize (::Window) const; | |||||
| Rectangle<int> getWindowBounds (::Window, ::Window parentWindow); | |||||
| ComponentPeer::OptionalBorderSize getBorderSize (::Window) const; | |||||
| Rectangle<int> getWindowBounds (::Window, ::Window parentWindow); | |||||
| Point<int> getPhysicalParentScreenPosition() const; | Point<int> getPhysicalParentScreenPosition() const; | ||||
| bool contains (::Window, Point<int> localPos) const; | bool contains (::Window, Point<int> localPos) const; | ||||
| @@ -76,6 +76,31 @@ public: | |||||
| }; | }; | ||||
| class OptionalBorderSize final | |||||
| { | |||||
| public: | |||||
| OptionalBorderSize() : valid (false) {} | |||||
| explicit OptionalBorderSize (BorderSize<int> size) : valid (true), borderSize (std::move (size)) {} | |||||
| explicit operator bool() const noexcept { return valid; } | |||||
| const auto& operator*() const noexcept | |||||
| { | |||||
| jassert (valid); | |||||
| return borderSize; | |||||
| } | |||||
| const auto* operator->() const noexcept | |||||
| { | |||||
| jassert (valid); | |||||
| return &borderSize; | |||||
| } | |||||
| private: | |||||
| bool valid; | |||||
| BorderSize<int> borderSize; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Creates a peer. | /** Creates a peer. | ||||
| @@ -219,6 +244,18 @@ public: | |||||
| */ | */ | ||||
| virtual bool contains (Point<int> localPos, bool trueIfInAChildWindow) const = 0; | virtual bool contains (Point<int> localPos, bool trueIfInAChildWindow) const = 0; | ||||
| /** Returns the size of the window frame that's around this window. | |||||
| Depending on the platform the border size may be invalid for a short transient | |||||
| after creating a new window. Hence the returned value must be checked using | |||||
| operator bool() and the contained value can be accessed using operator*() only | |||||
| if it is present. | |||||
| Whether or not the window has a normal window frame depends on the flags | |||||
| that were set when the window was created by Component::addToDesktop() | |||||
| */ | |||||
| virtual OptionalBorderSize getFrameSizeIfPresent() const = 0; | |||||
| /** Returns the size of the window frame that's around this window. | /** Returns the size of the window frame that's around this window. | ||||
| Whether or not the window has a normal window frame depends on the flags | Whether or not the window has a normal window frame depends on the flags | ||||
| that were set when the window was created by Component::addToDesktop() | that were set when the window was created by Component::addToDesktop() | ||||
| @@ -566,10 +566,12 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) | |||||
| if (peer != nullptr) | if (peer != nullptr) | ||||
| { | { | ||||
| peer->getFrameSize().addTo (newPos); | |||||
| if (const auto frameSize = peer->getFrameSizeIfPresent()) | |||||
| frameSize->addTo (newPos); | |||||
| } | } | ||||
| #if JUCE_LINUX | #if JUCE_LINUX | ||||
| else | |||||
| if (peer == nullptr || ! peer->getFrameSizeIfPresent()) | |||||
| { | { | ||||
| // We need to adjust for the frame size before we create a peer, as X11 | // We need to adjust for the frame size before we create a peer, as X11 | ||||
| // doesn't provide this information at construction time. | // doesn't provide this information at construction time. | ||||
| @@ -580,7 +582,9 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) | |||||
| tokens[firstCoord + 7].getIntValue(), | tokens[firstCoord + 7].getIntValue(), | ||||
| tokens[firstCoord + 8].getIntValue() }; | tokens[firstCoord + 8].getIntValue() }; | ||||
| frame.addTo (newPos); | |||||
| newPos.setX (newPos.getX() - frame.getLeft()); | |||||
| newPos.setY (newPos.getY() - frame.getTop()); | |||||
| setBounds (newPos); | setBounds (newPos); | ||||
| } | } | ||||
| } | } | ||||