| @@ -1009,7 +1009,7 @@ int Component::getParentHeight() const noexcept | |||
| Rectangle<int> Component::getParentMonitorArea() const | |||
| { | |||
| return Desktop::getInstance().getDisplays().getDisplayContaining (getScreenBounds().getCentre()).userArea; | |||
| return Desktop::getInstance().getDisplays().findDisplayForRect (getScreenBounds()).userArea; | |||
| } | |||
| int Component::getScreenX() const { return getScreenPosition().x; } | |||
| @@ -261,95 +261,6 @@ void Desktop::sendMouseMove() | |||
| } | |||
| } | |||
| //============================================================================== | |||
| Desktop::Displays::Displays (Desktop& desktop) { init (desktop); } | |||
| Desktop::Displays::~Displays() {} | |||
| const Desktop::Displays::Display& Desktop::Displays::getMainDisplay() const noexcept | |||
| { | |||
| ASSERT_MESSAGE_MANAGER_IS_LOCKED | |||
| jassert (displays.getReference(0).isMain); | |||
| return displays.getReference(0); | |||
| } | |||
| const Desktop::Displays::Display& Desktop::Displays::getDisplayContaining (Point<int> position) const noexcept | |||
| { | |||
| ASSERT_MESSAGE_MANAGER_IS_LOCKED | |||
| auto* best = &displays.getReference(0); | |||
| double bestDistance = 1.0e10; | |||
| for (auto& d : displays) | |||
| { | |||
| if (d.totalArea.contains (position)) | |||
| { | |||
| best = &d; | |||
| break; | |||
| } | |||
| auto distance = d.totalArea.getCentre().getDistanceFrom (position); | |||
| if (distance < bestDistance) | |||
| { | |||
| bestDistance = distance; | |||
| best = &d; | |||
| } | |||
| } | |||
| return *best; | |||
| } | |||
| RectangleList<int> Desktop::Displays::getRectangleList (bool userAreasOnly) const | |||
| { | |||
| ASSERT_MESSAGE_MANAGER_IS_LOCKED | |||
| RectangleList<int> rl; | |||
| for (auto& d : displays) | |||
| rl.addWithoutMerging (userAreasOnly ? d.userArea : d.totalArea); | |||
| return rl; | |||
| } | |||
| Rectangle<int> Desktop::Displays::getTotalBounds (bool userAreasOnly) const | |||
| { | |||
| return getRectangleList (userAreasOnly).getBounds(); | |||
| } | |||
| bool operator== (const Desktop::Displays::Display& d1, const Desktop::Displays::Display& d2) noexcept; | |||
| bool operator== (const Desktop::Displays::Display& d1, const Desktop::Displays::Display& d2) noexcept | |||
| { | |||
| return d1.userArea == d2.userArea | |||
| && d1.totalArea == d2.totalArea | |||
| && d1.scale == d2.scale | |||
| && d1.isMain == d2.isMain; | |||
| } | |||
| bool operator!= (const Desktop::Displays::Display& d1, const Desktop::Displays::Display& d2) noexcept; | |||
| bool operator!= (const Desktop::Displays::Display& d1, const Desktop::Displays::Display& d2) noexcept | |||
| { | |||
| return ! (d1 == d2); | |||
| } | |||
| void Desktop::Displays::init (Desktop& desktop) | |||
| { | |||
| findDisplays (desktop.getGlobalScaleFactor()); | |||
| } | |||
| void Desktop::Displays::refresh() | |||
| { | |||
| Array<Display> oldDisplays; | |||
| oldDisplays.swapWith (displays); | |||
| init (Desktop::getInstance()); | |||
| if (oldDisplays != displays) | |||
| { | |||
| for (int i = ComponentPeer::getNumPeers(); --i >= 0;) | |||
| if (auto* peer = ComponentPeer::getPeer (i)) | |||
| peer->handleScreenSizeChange(); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void Desktop::setKioskModeComponent (Component* componentToUse, bool allowMenusAndBars) | |||
| { | |||
| @@ -51,7 +51,6 @@ public: | |||
| /** | |||
| Describes and controls aspects of the computer's desktop. | |||
| @tags{GUI} | |||
| */ | |||
| class JUCE_API Desktop : private DeletedAtShutdown, | |||
| @@ -327,69 +326,6 @@ public: | |||
| bool isOrientationEnabled (DisplayOrientation orientation) const noexcept; | |||
| //============================================================================== | |||
| /** Manages details about connected display devices */ | |||
| class JUCE_API Displays | |||
| { | |||
| public: | |||
| /** Contains details about a display device. */ | |||
| struct Display | |||
| { | |||
| /** This is the bounds of the area of this display which isn't covered by | |||
| OS-dependent objects like the taskbar, menu bar, etc. */ | |||
| Rectangle<int> userArea; | |||
| /** This is the total physical area of this display, including any taskbars, etc */ | |||
| Rectangle<int> totalArea; | |||
| /** This is the scale-factor of this display. | |||
| If you create a component with size 1x1, this scale factor indicates the actual | |||
| size of the component in terms of physical pixels. | |||
| For higher-resolution displays, it may be a value greater than 1.0 | |||
| */ | |||
| double scale; | |||
| /** The DPI of the display. | |||
| This is the number of physical pixels per inch. To get the number of logical | |||
| pixels per inch, divide this by the Display::scale value. | |||
| */ | |||
| double dpi; | |||
| /** This will be true if this is the user's main screen. */ | |||
| bool isMain; | |||
| }; | |||
| /** Returns the display which acts as user's main screen. */ | |||
| const Display& getMainDisplay() const noexcept; | |||
| /** Returns the display which contains a particular point. | |||
| If the point lies outside all the displays, the nearest one will be returned. | |||
| */ | |||
| const Display& getDisplayContaining (Point<int> position) const noexcept; | |||
| /** Returns a RectangleList made up of all the displays. */ | |||
| RectangleList<int> getRectangleList (bool userAreasOnly) const; | |||
| /** Returns the smallest bounding box which contains all the displays. */ | |||
| Rectangle<int> getTotalBounds (bool userAreasOnly) const; | |||
| /** The list of displays. */ | |||
| Array<Display> displays; | |||
| #ifndef DOXYGEN | |||
| /** @internal */ | |||
| void refresh(); | |||
| /** @internal */ | |||
| ~Displays(); | |||
| #endif | |||
| private: | |||
| friend class Desktop; | |||
| Displays (Desktop&); | |||
| void init (Desktop&); | |||
| void findDisplays (float masterScale); | |||
| }; | |||
| const Displays& getDisplays() const noexcept { return *displays; } | |||
| //============================================================================== | |||
| @@ -0,0 +1,348 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2017 - ROLI Ltd. | |||
| 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 5 End-User License | |||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||
| 27th April 2017). | |||
| End User License Agreement: www.juce.com/juce-5-licence | |||
| Privacy Policy: www.juce.com/juce-5-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 | |||
| { | |||
| Displays::Displays (Desktop& desktop) | |||
| { | |||
| init (desktop); | |||
| } | |||
| void Displays::init (Desktop& desktop) | |||
| { | |||
| findDisplays (desktop.getGlobalScaleFactor()); | |||
| } | |||
| const Displays::Display& Displays::findDisplayForRect (Rectangle<int> rect, bool isPhysical) const noexcept | |||
| { | |||
| int maxArea = -1; | |||
| Display* retVal = nullptr; | |||
| for (auto& display : displays) | |||
| { | |||
| auto displayArea = display.totalArea; | |||
| if (isPhysical) | |||
| displayArea = (displayArea.withZeroOrigin() * display.scale) + display.topLeftPhysical; | |||
| displayArea = displayArea.getIntersection (rect); | |||
| auto area = displayArea.getWidth() * displayArea.getHeight(); | |||
| if (area >= maxArea) | |||
| { | |||
| maxArea = area; | |||
| retVal = &display; | |||
| } | |||
| } | |||
| return *retVal; | |||
| } | |||
| const Displays::Display& Displays::findDisplayForPoint (Point<int> point, bool isPhysical) const noexcept | |||
| { | |||
| auto minDistance = std::numeric_limits<int>::max(); | |||
| Display* retVal = nullptr; | |||
| for (auto& display : displays) | |||
| { | |||
| auto displayArea = display.totalArea; | |||
| if (isPhysical) | |||
| displayArea = (displayArea.withZeroOrigin() * display.scale) + display.topLeftPhysical; | |||
| if (displayArea.contains (point)) | |||
| return display; | |||
| auto distance = displayArea.getCentre().getDistanceFrom (point); | |||
| if (distance <= minDistance) | |||
| { | |||
| minDistance = distance; | |||
| retVal = &display; | |||
| } | |||
| } | |||
| return *retVal; | |||
| } | |||
| Rectangle<int> Displays::physicalToLogical (Rectangle<int> rect, const Display* useScaleFactorOfDisplay) const noexcept | |||
| { | |||
| auto& display = useScaleFactorOfDisplay != nullptr ? *useScaleFactorOfDisplay | |||
| : findDisplayForRect (rect, true); | |||
| return ((rect.toFloat() - display.topLeftPhysical.toFloat()) / display.scale).toNearestInt() + display.totalArea.getTopLeft(); | |||
| } | |||
| Rectangle<int> Displays::logicalToPhysical (Rectangle<int> rect, const Display* useScaleFactorOfDisplay) const noexcept | |||
| { | |||
| auto& display = useScaleFactorOfDisplay != nullptr ? *useScaleFactorOfDisplay | |||
| : findDisplayForRect (rect, false); | |||
| return ((rect.toFloat() - display.totalArea.getTopLeft().toFloat()) * display.scale).toNearestInt() + display.topLeftPhysical; | |||
| } | |||
| template <typename ValueType> | |||
| Point<ValueType> Displays::physicalToLogical (Point<ValueType> point, const Display* useScaleFactorOfDisplay) const noexcept | |||
| { | |||
| auto& display = useScaleFactorOfDisplay != nullptr ? *useScaleFactorOfDisplay | |||
| : findDisplayForPoint (point.roundToInt(), true); | |||
| Point<ValueType> logicalTopLeft (display.totalArea.getX(), display.totalArea.getY()); | |||
| Point<ValueType> physicalTopLeft (display.topLeftPhysical.getX(), display.topLeftPhysical.getY()); | |||
| return ((point - physicalTopLeft) / display.scale) + logicalTopLeft; | |||
| } | |||
| template <typename ValueType> | |||
| Point<ValueType> Displays::logicalToPhysical (Point<ValueType> point, const Display* useScaleFactorOfDisplay) const noexcept | |||
| { | |||
| auto& display = useScaleFactorOfDisplay != nullptr ? *useScaleFactorOfDisplay | |||
| : findDisplayForPoint (point.roundToInt(), false); | |||
| Point<ValueType> logicalTopLeft (display.totalArea.getX(), display.totalArea.getY()); | |||
| Point<ValueType> physicalTopLeft (display.topLeftPhysical.getX(), display.topLeftPhysical.getY()); | |||
| return ((point - logicalTopLeft) * display.scale) + physicalTopLeft; | |||
| } | |||
| const Displays::Display& Displays::getMainDisplay() const noexcept | |||
| { | |||
| ASSERT_MESSAGE_MANAGER_IS_LOCKED | |||
| jassert (displays.getReference(0).isMain); | |||
| return displays.getReference(0); | |||
| } | |||
| RectangleList<int> Displays::getRectangleList (bool userAreasOnly) const | |||
| { | |||
| ASSERT_MESSAGE_MANAGER_IS_LOCKED | |||
| RectangleList<int> rl; | |||
| for (auto& d : displays) | |||
| rl.addWithoutMerging (userAreasOnly ? d.userArea : d.totalArea); | |||
| return rl; | |||
| } | |||
| Rectangle<int> Displays::getTotalBounds (bool userAreasOnly) const | |||
| { | |||
| return getRectangleList (userAreasOnly).getBounds(); | |||
| } | |||
| void Displays::refresh() | |||
| { | |||
| Array<Display> oldDisplays; | |||
| oldDisplays.swapWith (displays); | |||
| init (Desktop::getInstance()); | |||
| if (oldDisplays != displays) | |||
| { | |||
| for (int i = ComponentPeer::getNumPeers(); --i >= 0;) | |||
| if (auto* peer = ComponentPeer::getPeer (i)) | |||
| peer->handleScreenSizeChange(); | |||
| } | |||
| } | |||
| bool operator== (const Displays::Display& d1, const Displays::Display& d2) noexcept; | |||
| bool operator== (const Displays::Display& d1, const Displays::Display& d2) noexcept | |||
| { | |||
| return d1.isMain == d2.isMain | |||
| && d1.totalArea == d2.totalArea | |||
| && d1.userArea == d2.userArea | |||
| && d1.topLeftPhysical == d2.topLeftPhysical | |||
| && d1.scale == d2.scale | |||
| && d1.dpi == d2.dpi; | |||
| } | |||
| bool operator!= (const Displays::Display& d1, const Displays::Display& d2) noexcept; | |||
| bool operator!= (const Displays::Display& d1, const Displays::Display& d2) noexcept { return ! (d1 == d2); } | |||
| // Deprecated method | |||
| const Displays::Display& Displays::getDisplayContaining (Point<int> position) const noexcept | |||
| { | |||
| ASSERT_MESSAGE_MANAGER_IS_LOCKED | |||
| auto* best = &displays.getReference(0); | |||
| double bestDistance = 1.0e10; | |||
| for (auto& d : displays) | |||
| { | |||
| if (d.totalArea.contains (position)) | |||
| { | |||
| best = &d; | |||
| break; | |||
| } | |||
| auto distance = d.totalArea.getCentre().getDistanceFrom (position); | |||
| if (distance < bestDistance) | |||
| { | |||
| bestDistance = distance; | |||
| best = &d; | |||
| } | |||
| } | |||
| return *best; | |||
| } | |||
| //============================================================================== | |||
| // These methods are used for converting the totalArea and userArea Rectangles in Display from physical to logical | |||
| // pixels. We do this by constructing a graph of connected displays where the root node has position (0, 0); this can be | |||
| // safely converted to logical pixels using its scale factor and we can then traverse the graph and work out the logical pixels | |||
| // for all the other connected displays. We need to do this as the logical bounds of a display depend not only on its scale | |||
| // factor but also the scale factor of the displays connected to it. | |||
| /** | |||
| Represents a node in our graph of displays. | |||
| */ | |||
| struct DisplayNode | |||
| { | |||
| /** The Display object that this represents. */ | |||
| Displays::Display* display; | |||
| /** True if this represents the 'root' display with position (0, 0). */ | |||
| bool isRoot = false; | |||
| /** The parent node of this node in our display graph. This will have a correct logicalArea. */ | |||
| DisplayNode* parent = nullptr; | |||
| /** The logical area to be calculated. This will be valid after processDisplay() has | |||
| been called on this node. | |||
| */ | |||
| Rectangle<double> logicalArea; | |||
| }; | |||
| /** Recursive - will calculate and set the logicalArea member of current. */ | |||
| static void processDisplay (DisplayNode* currentNode, const Array<DisplayNode>& allNodes) | |||
| { | |||
| const auto physicalArea = currentNode->display->totalArea.toDouble(); | |||
| const auto scale = currentNode->display->scale; | |||
| if (! currentNode->isRoot) | |||
| { | |||
| const auto logicalWidth = physicalArea.getWidth() / scale; | |||
| const auto logicalHeight = physicalArea.getHeight() / scale; | |||
| const auto physicalParentArea = currentNode->parent->display->totalArea.toDouble(); | |||
| const auto logicalParentArea = currentNode->parent->logicalArea; // logical area of parent has already been calculated | |||
| const auto parentScale = currentNode->parent->display->scale; | |||
| Rectangle<double> logicalArea (0.0, 0.0, logicalWidth, logicalHeight); | |||
| if (physicalArea.getRight() == physicalParentArea.getX()) logicalArea.setPosition ({ logicalParentArea.getX() - logicalWidth, physicalArea.getY() / parentScale }); // on left | |||
| else if (physicalArea.getX() == physicalParentArea.getRight()) logicalArea.setPosition ({ logicalParentArea.getRight(), physicalArea.getY() / parentScale }); // on right | |||
| else if (physicalArea.getBottom() == physicalParentArea.getY()) logicalArea.setPosition ({ physicalArea.getX() / parentScale, logicalParentArea.getY() - logicalHeight }); // on top | |||
| else if (physicalArea.getY() == physicalParentArea.getBottom()) logicalArea.setPosition ({ physicalArea.getX() / parentScale, logicalParentArea.getBottom() }); // on bottom | |||
| else jassertfalse; | |||
| currentNode->logicalArea = logicalArea; | |||
| } | |||
| else | |||
| { | |||
| // If currentNode is the root (position (0, 0)) then we can just scale the physical area | |||
| currentNode->logicalArea = physicalArea / scale; | |||
| currentNode->parent = currentNode; | |||
| } | |||
| // Find child nodes | |||
| Array<DisplayNode*> children; | |||
| for (auto& node : allNodes) | |||
| { | |||
| // Already calculated | |||
| if (node.parent != nullptr) | |||
| continue; | |||
| const auto otherPhysicalArea = node.display->totalArea.toDouble(); | |||
| // If the displays are touching on any side | |||
| if (otherPhysicalArea.getX() == physicalArea.getRight() || otherPhysicalArea.getRight() == physicalArea.getX() | |||
| || otherPhysicalArea.getY() == physicalArea.getBottom() || otherPhysicalArea.getBottom() == physicalArea.getY()) | |||
| { | |||
| node.parent = currentNode; | |||
| children.add (&node); | |||
| } | |||
| } | |||
| // Recursively process all child nodes | |||
| for (auto child : children) | |||
| processDisplay (child, allNodes); | |||
| } | |||
| /** This is called when the displays Array has been filled out with the info for all connected displays and the | |||
| totalArea and userArea Rectangles need to be converted from physical to logical coordinates. | |||
| */ | |||
| void Displays::updateToLogical() | |||
| { | |||
| if (displays.size() == 1) | |||
| { | |||
| auto& display = displays.getReference (0); | |||
| display.totalArea = (display.totalArea.toDouble() / display.scale).toNearestInt(); | |||
| display.userArea = (display.userArea.toDouble() / display.scale).toNearestInt(); | |||
| return; | |||
| } | |||
| Array<DisplayNode> displayNodes; | |||
| for (auto& d : displays) | |||
| { | |||
| DisplayNode node; | |||
| node.display = &d; | |||
| displayNodes.add (node); | |||
| } | |||
| DisplayNode* root = nullptr; | |||
| for (auto& node : displayNodes) | |||
| { | |||
| if (node.display->totalArea.getTopLeft() == Point<int>()) | |||
| { | |||
| root = &node; | |||
| root->isRoot = true; | |||
| break; | |||
| } | |||
| } | |||
| // Must have a root node! | |||
| jassert (root != nullptr); | |||
| // Recursively traverse the display graph from the root and work out logical bounds | |||
| processDisplay (root, displayNodes); | |||
| for (auto& node : displayNodes) | |||
| { | |||
| // All of the nodes should have a parent | |||
| jassert (node.parent != nullptr); | |||
| auto relativeUserArea = (node.display->userArea.toDouble() - node.display->totalArea.toDouble().getTopLeft()) / node.display->scale; | |||
| // Now set Display::totalArea and ::userArea using the logical area that we have calculated | |||
| node.display->topLeftPhysical = node.display->totalArea.getTopLeft(); | |||
| node.display->totalArea = node.logicalArea.toNearestInt(); | |||
| node.display->userArea = (relativeUserArea + node.logicalArea.getTopLeft()).toNearestInt(); | |||
| } | |||
| } | |||
| } // namespace juce | |||
| @@ -0,0 +1,145 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2017 - ROLI Ltd. | |||
| 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 5 End-User License | |||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||
| 27th April 2017). | |||
| End User License Agreement: www.juce.com/juce-5-licence | |||
| Privacy Policy: www.juce.com/juce-5-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 | |||
| { | |||
| //============================================================================== | |||
| /** | |||
| Manages details about connected display devices. | |||
| @tags{GUI} | |||
| */ | |||
| class JUCE_API Displays | |||
| { | |||
| private: | |||
| Displays (Desktop&); | |||
| public: | |||
| /** Represents a connected display device. */ | |||
| struct Display | |||
| { | |||
| /** This will be true if this is the user's main display device. */ | |||
| bool isMain; | |||
| /** The total area of this display in logical pixels including any OS-dependent objects | |||
| like the taskbar, menu bar, etc. */ | |||
| Rectangle<int> totalArea; | |||
| /** The total area of this display in logical pixels which isn't covered by OS-dependent | |||
| objects like the taskbar, menu bar, etc. | |||
| */ | |||
| Rectangle<int> userArea; | |||
| /** The top-left of this display in physical coordinates. */ | |||
| Point<int> topLeftPhysical; | |||
| /** The scale factor of this display. | |||
| For higher-resolution displays, or displays with a user-defined scale factor set, | |||
| this may be a value other than 1.0. | |||
| This value is used to convert between physical and logical pixels. For example, a Component | |||
| with size 10x10 will use 20x20 physical pixels on a display with a scale factor of 2.0. | |||
| */ | |||
| double scale; | |||
| /** The DPI of the display. | |||
| This is the number of physical pixels per inch. To get the number of logical | |||
| pixels per inch, divide this by the Display::scale value. | |||
| */ | |||
| double dpi; | |||
| }; | |||
| /** Converts a Rectangle from physical to logical pixels. | |||
| If useScaleFactorOfDisplay is not null then its scale factor will be used for the conversion | |||
| regardless of the display that the Rectangle to be converted is on. | |||
| */ | |||
| Rectangle<int> physicalToLogical (Rectangle<int>, const Display* useScaleFactorOfDisplay = nullptr) const noexcept; | |||
| /** Converts a Rectangle from logical to physical pixels. | |||
| If useScaleFactorOfDisplay is not null then its scale factor will be used for the conversion | |||
| regardless of the display that the Rectangle to be converted is on. | |||
| */ | |||
| Rectangle<int> logicalToPhysical (Rectangle<int>, const Display* useScaleFactorOfDisplay = nullptr) const noexcept; | |||
| /** Converts a Point from physical to logical pixels. */ | |||
| template <typename ValueType> | |||
| Point<ValueType> physicalToLogical (Point<ValueType>, const Display* useScaleFactorOfDisplay = nullptr) const noexcept; | |||
| /** Converts a Point from logical to physical pixels. */ | |||
| template <typename ValueType> | |||
| Point<ValueType> logicalToPhysical (Point<ValueType>, const Display* useScaleFactorOfDisplay = nullptr) const noexcept; | |||
| /** Returns the Display object representing the display containing a given Rectangle (either | |||
| in logical or physical pixels). | |||
| If the Rectangle lies outside all the displays then the nearest one will be returned. | |||
| */ | |||
| const Display& findDisplayForRect (Rectangle<int>, bool isPhysical = false) const noexcept; | |||
| /** Returns the Display object representing the display containing a given Point (either | |||
| in logical or physical pixels). | |||
| If the Point lies outside all the displays then the nearest one will be returned. | |||
| */ | |||
| const Display& findDisplayForPoint (Point<int>, bool isPhysical = false) const noexcept; | |||
| /** Returns the Display object representing the display acting as the user's main screen. */ | |||
| const Display& getMainDisplay() const noexcept; | |||
| /** Returns a RectangleList made up of all the displays in LOGICAL pixels. */ | |||
| RectangleList<int> getRectangleList (bool userAreasOnly) const; | |||
| /** Returns the smallest bounding box which contains all the displays in LOGICAL pixels. */ | |||
| Rectangle<int> getTotalBounds (bool userAreasOnly) const; | |||
| /** An Array containing the Display objects for all of the connected displays. */ | |||
| Array<Display> displays; | |||
| #ifndef DOXYGEN | |||
| /** @internal */ | |||
| void refresh(); | |||
| /** @internal */ | |||
| ~Displays() {} | |||
| // This method has been deprecated - use the findDisplayForPoint() or findDisplayForRect() methods instead | |||
| // as they can deal with converting between logical and physical pixels | |||
| JUCE_DEPRECATED (const Display& getDisplayContaining (Point<int> position) const noexcept); | |||
| #endif | |||
| private: | |||
| friend class Desktop; | |||
| void init (Desktop&); | |||
| void findDisplays (float masterScale); | |||
| void updateToLogical(); | |||
| }; | |||
| } // namespace juce | |||
| @@ -153,7 +153,8 @@ namespace juce | |||
| #include "components/juce_Component.cpp" | |||
| #include "components/juce_ComponentListener.cpp" | |||
| #include "mouse/juce_MouseInputSource.cpp" | |||
| #include "components/juce_Desktop.cpp" | |||
| #include "desktop/juce_Displays.cpp" | |||
| #include "desktop/juce_Desktop.cpp" | |||
| #include "components/juce_ModalComponentManager.cpp" | |||
| #include "mouse/juce_ComponentDragger.cpp" | |||
| #include "mouse/juce_DragAndDropContainer.cpp" | |||
| @@ -148,6 +148,7 @@ namespace juce | |||
| class KeyPressMappingSet; | |||
| class ApplicationCommandManagerListener; | |||
| class DrawableButton; | |||
| class Displays; | |||
| class FlexBox; | |||
| #if JUCE_HAS_CONSTEXPR | |||
| @@ -168,7 +169,8 @@ namespace juce | |||
| #include "components/juce_CachedComponentImage.h" | |||
| #include "components/juce_Component.h" | |||
| #include "layout/juce_ComponentAnimator.h" | |||
| #include "components/juce_Desktop.h" | |||
| #include "desktop/juce_Desktop.h" | |||
| #include "desktop/juce_Displays.h" | |||
| #include "layout/juce_ComponentBoundsConstrainer.h" | |||
| #include "mouse/juce_ComponentDragger.h" | |||
| #include "mouse/juce_DragAndDropTarget.h" | |||
| @@ -159,8 +159,7 @@ public: | |||
| else | |||
| jassertfalse; // seem to be trying to animate a component that's not visible.. | |||
| auto scale = (float) Desktop::getInstance().getDisplays() | |||
| .getDisplayContaining (getScreenBounds().getCentre()).scale; | |||
| auto scale = (float) Desktop::getInstance().getDisplays().findDisplayForRect (getScreenBounds()).scale; | |||
| image = c.createComponentSnapshot (c.getLocalBounds(), false, scale); | |||
| @@ -117,7 +117,7 @@ void ComponentBoundsConstrainer::setBoundsForComponent (Component* component, | |||
| if (auto* peer = component->getPeer()) | |||
| border = peer->getFrameSize(); | |||
| auto screenBounds = Desktop::getInstance().getDisplays().getDisplayContaining (targetBounds.getCentre()).userArea; | |||
| auto screenBounds = Desktop::getInstance().getDisplays().findDisplayForPoint (targetBounds.getCentre()).userArea; | |||
| limits = component->getLocalArea (nullptr, screenBounds) + component->getPosition(); | |||
| } | |||
| @@ -597,7 +597,7 @@ struct MenuWindow : public Component | |||
| if (relativeTo != nullptr) | |||
| targetPoint = relativeTo->localPointToGlobal (targetPoint); | |||
| auto parentArea = Desktop::getInstance().getDisplays().getDisplayContaining (targetPoint) | |||
| auto parentArea = Desktop::getInstance().getDisplays().findDisplayForPoint (targetPoint) | |||
| #if JUCE_MAC | |||
| .userArea; | |||
| #else | |||
| @@ -1034,7 +1034,7 @@ bool juce_areThereAnyAlwaysOnTopWindows() | |||
| } | |||
| //============================================================================== | |||
| void Desktop::Displays::findDisplays (float masterScale) | |||
| void Displays::findDisplays (float masterScale) | |||
| { | |||
| Display d; | |||
| @@ -1057,7 +1057,7 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, setScreenSize, void, (JNIEnv | |||
| android.screenHeight = screenHeight; | |||
| android.dpi = dpi; | |||
| const_cast<Desktop::Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||
| const_cast<Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||
| } | |||
| //============================================================================== | |||
| @@ -717,7 +717,7 @@ void UIViewComponentPeer::updateTransformAndScreenBounds() | |||
| const Rectangle<int> oldArea (component.getBounds()); | |||
| const Rectangle<int> oldDesktop (desktop.getDisplays().getMainDisplay().userArea); | |||
| const_cast<Desktop::Displays&> (desktop.getDisplays()).refresh(); | |||
| const_cast<Displays&> (desktop.getDisplays()).refresh(); | |||
| window.transform = Orientations::getCGTransformFor (desktop.getCurrentOrientation()); | |||
| view.transform = CGAffineTransformIdentity; | |||
| @@ -730,7 +730,7 @@ Desktop::DisplayOrientation Desktop::getCurrentOrientation() const | |||
| return Orientations::convertToJuce (orientation); | |||
| } | |||
| void Desktop::Displays::findDisplays (float masterScale) | |||
| void Displays::findDisplays (float masterScale) | |||
| { | |||
| JUCE_AUTORELEASEPOOL | |||
| { | |||
| @@ -758,7 +758,7 @@ public: | |||
| //============================================================================== | |||
| struct ExtendedInfo | |||
| { | |||
| // Unlike Desktop::Displays::Display, the following is in | |||
| // Unlike Displays::Display, the following is in | |||
| // physical pixels, i.e. the area is not scaled | |||
| Rectangle<int> totalBounds; | |||
| // Usable bounds is the usable area in local coordinates | |||
| @@ -3779,7 +3779,7 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindowToAtt | |||
| } | |||
| //============================================================================== | |||
| void Desktop::Displays::findDisplays (float masterScale) | |||
| void Displays::findDisplays (float masterScale) | |||
| { | |||
| ScopedXDisplay xDisplay; | |||
| @@ -3806,7 +3806,7 @@ void Desktop::Displays::findDisplays (float masterScale) | |||
| { | |||
| auto& info = geometry.infos.getReference (mainDisplayIdx); | |||
| Desktop::Displays::Display d; | |||
| Displays::Display d; | |||
| d.isMain = true; | |||
| d.scale = masterScale * info.scale; | |||
| d.dpi = info.dpi; | |||
| @@ -3824,7 +3824,7 @@ void Desktop::Displays::findDisplays (float masterScale) | |||
| auto& info = geometry.infos.getReference (i); | |||
| Desktop::Displays::Display d; | |||
| Displays::Display d; | |||
| d.isMain = false; | |||
| d.scale = masterScale * info.scale; | |||
| d.dpi = info.dpi; | |||
| @@ -477,7 +477,7 @@ struct DisplaySettingsChangeCallback : private DeletedAtShutdown | |||
| static void displayReconfigurationCallBack (CGDirectDisplayID, CGDisplayChangeSummaryFlags, void*) | |||
| { | |||
| const_cast<Desktop::Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||
| const_cast<Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||
| } | |||
| JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL (DisplaySettingsChangeCallback) | |||
| @@ -493,9 +493,9 @@ static Rectangle<int> convertDisplayRect (NSRect r, CGFloat mainScreenBottom) | |||
| return convertToRectInt (r); | |||
| } | |||
| static Desktop::Displays::Display getDisplayFromScreen (NSScreen* s, CGFloat& mainScreenBottom, const float masterScale) | |||
| static Displays::Display getDisplayFromScreen (NSScreen* s, CGFloat& mainScreenBottom, const float masterScale) | |||
| { | |||
| Desktop::Displays::Display d; | |||
| Displays::Display d; | |||
| d.isMain = (mainScreenBottom == 0); | |||
| @@ -517,7 +517,7 @@ static Desktop::Displays::Display getDisplayFromScreen (NSScreen* s, CGFloat& ma | |||
| return d; | |||
| } | |||
| void Desktop::Displays::findDisplays (const float masterScale) | |||
| void Displays::findDisplays (const float masterScale) | |||
| { | |||
| JUCE_AUTORELEASEPOOL | |||
| { | |||
| @@ -2998,7 +2998,7 @@ private: | |||
| static void forceDisplayUpdate() | |||
| { | |||
| const_cast<Desktop::Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||
| const_cast<Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||
| } | |||
| void handleDPIChange() // happens when a window moves to a screen with a different DPI. | |||
| @@ -4033,7 +4033,7 @@ static BOOL CALLBACK enumMonitorsProc (HMONITOR hm, HDC, LPRECT r, LPARAM userIn | |||
| return TRUE; | |||
| } | |||
| void Desktop::Displays::findDisplays (float masterScale) | |||
| void Displays::findDisplays (float masterScale) | |||
| { | |||
| setDPIAwareness(); | |||
| @@ -42,8 +42,7 @@ CallOutBox::CallOutBox (Component& c, Rectangle<int> area, Component* const pare | |||
| { | |||
| setAlwaysOnTop (juce_areThereAnyAlwaysOnTopWindows()); | |||
| updatePosition (area, Desktop::getInstance().getDisplays() | |||
| .getDisplayContaining (area.getCentre()).userArea); | |||
| updatePosition (area, Desktop::getInstance().getDisplays().findDisplayForRect (area).userArea); | |||
| addToDesktop (ComponentPeer::windowIsTemporary); | |||
| @@ -565,7 +565,7 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) | |||
| if (onScreenArea.getWidth() * onScreenArea.getHeight() < 32 * 32) | |||
| { | |||
| auto screen = desktop.getDisplays().getDisplayContaining (newPos.getCentre()).userArea; | |||
| auto screen = desktop.getDisplays().findDisplayForRect (newPos).userArea; | |||
| newPos.setSize (jmin (newPos.getWidth(), screen.getWidth()), | |||
| jmin (newPos.getHeight(), screen.getHeight())); | |||
| @@ -92,8 +92,7 @@ void TooltipWindow::displayTip (Point<int> screenPos, const String& tip) | |||
| } | |||
| else | |||
| { | |||
| updatePosition (tip, screenPos, Desktop::getInstance().getDisplays() | |||
| .getDisplayContaining (screenPos).userArea); | |||
| updatePosition (tip, screenPos, Desktop::getInstance().getDisplays().findDisplayForPoint (screenPos).userArea); | |||
| addToDesktop (ComponentPeer::windowHasDropShadow | |||
| | ComponentPeer::windowIsTemporary | |||
| @@ -282,8 +282,7 @@ public: | |||
| { | |||
| lastScreenBounds = component.getTopLevelComponent()->getScreenBounds(); | |||
| auto newScale = Desktop::getInstance().getDisplays() | |||
| .getDisplayContaining (lastScreenBounds.getCentre()).scale; | |||
| auto newScale = Desktop::getInstance().getDisplays().findDisplayForRect (lastScreenBounds).scale; | |||
| auto localBounds = component.getLocalBounds(); | |||
| @@ -260,7 +260,7 @@ public: | |||
| //============================================================================== | |||
| /** Returns the scale factor used by the display that is being rendered. | |||
| The scale is that of the display - see Desktop::Displays::Display::scale | |||
| The scale is that of the display - see Displays::Display::scale | |||
| Note that this should only be called during an OpenGLRenderer::renderOpenGL() | |||
| callback - at other times the value it returns is undefined. | |||