| @@ -1,6 +1,31 @@ | |||
| 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 | |||
| ============= | |||
| @@ -270,6 +270,7 @@ private: | |||
| bool isFocused() const override { return true; } | |||
| void grabFocus() override {} | |||
| void* getNativeHandle() const override { return nullptr; } | |||
| OptionalBorderSize getFrameSizeIfPresent() const override { return {}; } | |||
| BorderSize<int> getFrameSize() const override { return {}; } | |||
| void setVisible (bool) override {} | |||
| void setTitle (const String&) override {} | |||
| @@ -631,6 +631,12 @@ public: | |||
| (float) localPos.y * scale)); | |||
| } | |||
| OptionalBorderSize getFrameSizeIfPresent() const override | |||
| { | |||
| // TODO | |||
| return {}; | |||
| } | |||
| BorderSize<int> getFrameSize() const override | |||
| { | |||
| // TODO | |||
| @@ -211,24 +211,25 @@ public: | |||
| 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; | |||
| Point<float> localToGlobal (Point<float> relativePosition) override; | |||
| Point<float> globalToLocal (Point<float> screenPosition) override; | |||
| using ComponentPeer::localToGlobal; | |||
| using ComponentPeer::globalToLocal; | |||
| 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; | |||
| bool isFullScreen() const override { return fullScreen; } | |||
| bool isFullScreen() const override { return fullScreen; } | |||
| 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; | |||
| void toFront (bool makeActiveWindow) override; | |||
| void toBehind (ComponentPeer* other) override; | |||
| void setIcon (const Image& newIcon) override; | |||
| StringArray getAvailableRenderingEngines() override { return StringArray ("CoreGraphics Renderer"); } | |||
| StringArray getAvailableRenderingEngines() override { return StringArray ("CoreGraphics Renderer"); } | |||
| void drawRect (CGRect); | |||
| bool canBecomeKeyWindow(); | |||
| @@ -141,11 +141,17 @@ public: | |||
| return bounds; | |||
| } | |||
| BorderSize<int> getFrameSize() const override | |||
| OptionalBorderSize getFrameSizeIfPresent() const override | |||
| { | |||
| return windowBorder; | |||
| } | |||
| BorderSize<int> getFrameSize() const override | |||
| { | |||
| const auto optionalBorderSize = getFrameSizeIfPresent(); | |||
| return optionalBorderSize ? (*optionalBorderSize) : BorderSize<int>(); | |||
| } | |||
| Point<float> localToGlobal (Point<float> relativePosition) override | |||
| { | |||
| return relativePosition + getScreenPosition (false).toFloat(); | |||
| @@ -362,9 +368,14 @@ public: | |||
| void updateBorderSize() | |||
| { | |||
| 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); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| @@ -504,7 +515,7 @@ private: | |||
| ::Window windowH = {}, parentWindow = {}; | |||
| Rectangle<int> bounds; | |||
| BorderSize<int> windowBorder; | |||
| ComponentPeer::OptionalBorderSize windowBorder; | |||
| bool fullScreen = false, isAlwaysOnTop = false; | |||
| double currentScaleFactor = 1.0; | |||
| Array<Component*> glRepaintListeners; | |||
| @@ -493,12 +493,12 @@ public: | |||
| : (v == view); | |||
| } | |||
| BorderSize<int> getFrameSize() const override | |||
| OptionalBorderSize getFrameSizeIfPresent() const override | |||
| { | |||
| BorderSize<int> b; | |||
| if (! isSharedWindow) | |||
| { | |||
| BorderSize<int> b; | |||
| NSRect v = [view convertRect: [view frame] toView: nil]; | |||
| NSRect w = [window frame]; | |||
| @@ -506,9 +506,19 @@ public: | |||
| b.setBottom ((int) v.origin.y); | |||
| b.setLeft ((int) v.origin.x); | |||
| 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 | |||
| @@ -1764,6 +1764,11 @@ public: | |||
| return w == hwnd || (trueIfInAChildWindow && (IsChild (hwnd, w) != 0)); | |||
| } | |||
| OptionalBorderSize getFrameSizeIfPresent() const override | |||
| { | |||
| return ComponentPeer::OptionalBorderSize { windowBorder }; | |||
| } | |||
| BorderSize<int> getFrameSize() const override | |||
| { | |||
| return windowBorder; | |||
| @@ -1802,7 +1802,7 @@ bool XWindowSystem::contains (::Window windowH, Point<int> localPos) const | |||
| && child == None; | |||
| } | |||
| BorderSize<int> XWindowSystem::getBorderSize (::Window windowH) const | |||
| ComponentPeer::OptionalBorderSize XWindowSystem::getBorderSize (::Window windowH) const | |||
| { | |||
| jassert (windowH != 0); | |||
| @@ -1824,7 +1824,7 @@ BorderSize<int> XWindowSystem::getBorderSize (::Window windowH) const | |||
| 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 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; | |||
| 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. | |||
| @@ -219,6 +244,18 @@ public: | |||
| */ | |||
| 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. | |||
| 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() | |||
| @@ -566,10 +566,12 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) | |||
| if (peer != nullptr) | |||
| { | |||
| peer->getFrameSize().addTo (newPos); | |||
| if (const auto frameSize = peer->getFrameSizeIfPresent()) | |||
| frameSize->addTo (newPos); | |||
| } | |||
| #if JUCE_LINUX | |||
| else | |||
| if (peer == nullptr || ! peer->getFrameSizeIfPresent()) | |||
| { | |||
| // We need to adjust for the frame size before we create a peer, as X11 | |||
| // doesn't provide this information at construction time. | |||
| @@ -580,7 +582,9 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) | |||
| tokens[firstCoord + 7].getIntValue(), | |||
| tokens[firstCoord + 8].getIntValue() }; | |||
| frame.addTo (newPos); | |||
| newPos.setX (newPos.getX() - frame.getLeft()); | |||
| newPos.setY (newPos.getY() - frame.getTop()); | |||
| setBounds (newPos); | |||
| } | |||
| } | |||