| @@ -363,7 +363,7 @@ struct Component::ComponentHelpers | |||||
| static Rectangle<int> getParentOrMainMonitorBounds (const Component& comp) | static Rectangle<int> getParentOrMainMonitorBounds (const Component& comp) | ||||
| { | { | ||||
| return comp.getParentComponent() != nullptr ? comp.getParentComponent()->getLocalBounds() | return comp.getParentComponent() != nullptr ? comp.getParentComponent()->getLocalBounds() | ||||
| : Desktop::getInstance().getMainMonitorArea(); | |||||
| : Desktop::getInstance().getDisplays().getMainDisplay().userArea; | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -983,7 +983,7 @@ Rectangle<int> Component::getScreenBounds() const { return localAreaToGlobal | |||||
| Rectangle<int> Component::getParentMonitorArea() const | Rectangle<int> Component::getParentMonitorArea() const | ||||
| { | { | ||||
| return Desktop::getInstance().getMonitorAreaContaining (getScreenBounds().getCentre()); | |||||
| return Desktop::getInstance().getDisplays().getDisplayContaining (getScreenBounds().getCentre()).userArea; | |||||
| } | } | ||||
| Point<int> Component::getLocalPoint (const Component* source, const Point<int>& point) const | Point<int> Component::getLocalPoint (const Component* source, const Point<int>& point) const | ||||
| @@ -29,7 +29,6 @@ Desktop::Desktop() | |||||
| allowedOrientations (allOrientations) | allowedOrientations (allOrientations) | ||||
| { | { | ||||
| createMouseInputSources(); | createMouseInputSources(); | ||||
| refreshMonitorSizes(); | |||||
| } | } | ||||
| Desktop::~Desktop() | Desktop::~Desktop() | ||||
| @@ -54,79 +53,6 @@ Desktop& JUCE_CALLTYPE Desktop::getInstance() | |||||
| Desktop* Desktop::instance = nullptr; | Desktop* Desktop::instance = nullptr; | ||||
| //============================================================================== | |||||
| void Desktop::refreshMonitorSizes() | |||||
| { | |||||
| Array <Rectangle<int> > oldClipped, oldUnclipped; | |||||
| oldClipped.swapWithArray (monitorCoordsClipped); | |||||
| oldUnclipped.swapWithArray (monitorCoordsUnclipped); | |||||
| getCurrentMonitorPositions (monitorCoordsClipped, true); | |||||
| getCurrentMonitorPositions (monitorCoordsUnclipped, false); | |||||
| jassert (monitorCoordsClipped.size() == monitorCoordsUnclipped.size()); | |||||
| if (oldClipped != monitorCoordsClipped | |||||
| || oldUnclipped != monitorCoordsUnclipped) | |||||
| { | |||||
| for (int i = ComponentPeer::getNumPeers(); --i >= 0;) | |||||
| { | |||||
| ComponentPeer* const p = ComponentPeer::getPeer (i); | |||||
| if (p != nullptr) | |||||
| p->handleScreenSizeChange(); | |||||
| } | |||||
| } | |||||
| } | |||||
| int Desktop::getNumDisplayMonitors() const noexcept | |||||
| { | |||||
| return monitorCoordsClipped.size(); | |||||
| } | |||||
| Rectangle<int> Desktop::getDisplayMonitorCoordinates (const int index, const bool clippedToWorkArea) const noexcept | |||||
| { | |||||
| return clippedToWorkArea ? monitorCoordsClipped [index] | |||||
| : monitorCoordsUnclipped [index]; | |||||
| } | |||||
| RectangleList Desktop::getAllMonitorDisplayAreas (const bool clippedToWorkArea) const | |||||
| { | |||||
| RectangleList rl; | |||||
| for (int i = 0; i < getNumDisplayMonitors(); ++i) | |||||
| rl.addWithoutMerging (getDisplayMonitorCoordinates (i, clippedToWorkArea)); | |||||
| return rl; | |||||
| } | |||||
| Rectangle<int> Desktop::getMainMonitorArea (const bool clippedToWorkArea) const noexcept | |||||
| { | |||||
| return getDisplayMonitorCoordinates (0, clippedToWorkArea); | |||||
| } | |||||
| Rectangle<int> Desktop::getMonitorAreaContaining (const Point<int>& position, const bool clippedToWorkArea) const | |||||
| { | |||||
| Rectangle<int> best (getMainMonitorArea (clippedToWorkArea)); | |||||
| double bestDistance = 1.0e10; | |||||
| for (int i = getNumDisplayMonitors(); --i >= 0;) | |||||
| { | |||||
| const Rectangle<int> rect (getDisplayMonitorCoordinates (i, clippedToWorkArea)); | |||||
| if (rect.contains (position)) | |||||
| return rect; | |||||
| const double distance = rect.getCentre().getDistanceFrom (position); | |||||
| if (distance < bestDistance) | |||||
| { | |||||
| bestDistance = distance; | |||||
| best = rect; | |||||
| } | |||||
| } | |||||
| return best; | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| int Desktop::getNumComponents() const noexcept | int Desktop::getNumComponents() const noexcept | ||||
| { | { | ||||
| @@ -400,6 +326,94 @@ void Desktop::sendMouseMove() | |||||
| } | } | ||||
| } | } | ||||
| //============================================================================== | |||||
| Desktop::Displays::Displays() { refresh(); } | |||||
| Desktop::Displays::~Displays() {} | |||||
| const Desktop::Displays::Display& Desktop::Displays::getMainDisplay() const noexcept | |||||
| { | |||||
| jassert (displays.getReference(0).isMain); | |||||
| return displays.getReference(0); | |||||
| } | |||||
| const Desktop::Displays::Display& Desktop::Displays::getDisplayContaining (const Point<int>& position) const noexcept | |||||
| { | |||||
| const Display* best = &displays.getReference(0); | |||||
| double bestDistance = 1.0e10; | |||||
| for (int i = displays.size(); --i >= 0;) | |||||
| { | |||||
| const Display& d = displays.getReference(i); | |||||
| if (d.totalArea.contains (position)) | |||||
| { | |||||
| best = &d; | |||||
| break; | |||||
| } | |||||
| const double distance = d.totalArea.getCentre().getDistanceFrom (position); | |||||
| if (distance < bestDistance) | |||||
| { | |||||
| bestDistance = distance; | |||||
| best = &d; | |||||
| } | |||||
| } | |||||
| return *best; | |||||
| } | |||||
| RectangleList Desktop::Displays::getRectangleList (bool userAreasOnly) const | |||||
| { | |||||
| RectangleList rl; | |||||
| for (int i = 0; i < displays.size(); ++i) | |||||
| { | |||||
| const Display& d = displays.getReference(i); | |||||
| 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 | |||||
| { | |||||
| 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 | |||||
| { | |||||
| return ! (d1 == d2); | |||||
| } | |||||
| void Desktop::Displays::refresh() | |||||
| { | |||||
| Array<Display> oldDisplays; | |||||
| oldDisplays.swapWithArray (displays); | |||||
| findDisplays(); | |||||
| jassert (displays.size() > 0); | |||||
| if (oldDisplays != displays) | |||||
| { | |||||
| for (int i = ComponentPeer::getNumPeers(); --i >= 0;) | |||||
| { | |||||
| ComponentPeer* const p = ComponentPeer::getPeer (i); | |||||
| if (p != nullptr) | |||||
| p->handleScreenSizeChange(); | |||||
| } | |||||
| } | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| void Desktop::setKioskModeComponent (Component* componentToUse, const bool allowMenusAndBars) | void Desktop::setKioskModeComponent (Component* componentToUse, const bool allowMenusAndBars) | ||||
| { | { | ||||
| @@ -66,34 +66,6 @@ public: | |||||
| */ | */ | ||||
| static Desktop& JUCE_CALLTYPE getInstance(); | static Desktop& JUCE_CALLTYPE getInstance(); | ||||
| //============================================================================== | |||||
| /** Returns a list of the positions of all the monitors available. | |||||
| The first rectangle in the list will be the main monitor area. | |||||
| If clippedToWorkArea is true, it will exclude any areas like the taskbar on Windows, | |||||
| or the menu bar on Mac. If clippedToWorkArea is false, the entire monitor area is returned. | |||||
| */ | |||||
| RectangleList getAllMonitorDisplayAreas (bool clippedToWorkArea = true) const; | |||||
| /** Returns the position and size of the main monitor. | |||||
| If clippedToWorkArea is true, it will exclude any areas like the taskbar on Windows, | |||||
| or the menu bar on Mac. If clippedToWorkArea is false, the entire monitor area is returned. | |||||
| */ | |||||
| Rectangle<int> getMainMonitorArea (bool clippedToWorkArea = true) const noexcept; | |||||
| /** Returns the position and size of the monitor which contains this co-ordinate. | |||||
| If none of the monitors contains the point, this will just return the | |||||
| main monitor. | |||||
| If clippedToWorkArea is true, it will exclude any areas like the taskbar on Windows, | |||||
| or the menu bar on Mac. If clippedToWorkArea is false, the entire monitor area is returned. | |||||
| */ | |||||
| Rectangle<int> getMonitorAreaContaining (const Point<int>& position, bool clippedToWorkArea = true) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns the mouse position. | /** Returns the mouse position. | ||||
| @@ -338,12 +310,60 @@ public: | |||||
| bool isOrientationEnabled (DisplayOrientation orientation) const noexcept; | bool isOrientationEnabled (DisplayOrientation orientation) const noexcept; | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Tells this object to refresh its idea of what the screen resolution is. | |||||
| 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. | |||||
| For higher-resolution displays, this may be a value greater than 1.0 | |||||
| */ | |||||
| double scale; | |||||
| /** 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 (const Point<int>& position) const noexcept; | |||||
| /** Returns a RectangleList made up of all the displays. */ | |||||
| RectangleList 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(); | |||||
| #endif | |||||
| private: | |||||
| friend class Desktop; | |||||
| Displays(); | |||||
| ~Displays(); | |||||
| void findDisplays(); | |||||
| }; | |||||
| (Called internally by the native code). | |||||
| */ | |||||
| void refreshMonitorSizes(); | |||||
| const Displays& getDisplays() const noexcept { return displays; } | |||||
| //============================================================================== | |||||
| /** True if the OS supports semitransparent windows */ | /** True if the OS supports semitransparent windows */ | ||||
| static bool canUseSemiTransparentWindows() noexcept; | static bool canUseSemiTransparentWindows() noexcept; | ||||
| @@ -365,7 +385,8 @@ private: | |||||
| ListenerList <FocusChangeListener> focusListeners; | ListenerList <FocusChangeListener> focusListeners; | ||||
| Array <Component*> desktopComponents; | Array <Component*> desktopComponents; | ||||
| Array <Rectangle<int> > monitorCoordsClipped, monitorCoordsUnclipped; | |||||
| Displays displays; | |||||
| Point<int> lastFakeMouseMove; | Point<int> lastFakeMouseMove; | ||||
| void sendMouseMove(); | void sendMouseMove(); | ||||
| @@ -389,15 +410,11 @@ private: | |||||
| void resetTimer(); | void resetTimer(); | ||||
| ListenerList <MouseListener>& getMouseListeners(); | ListenerList <MouseListener>& getMouseListeners(); | ||||
| int getNumDisplayMonitors() const noexcept; | |||||
| Rectangle<int> getDisplayMonitorCoordinates (int index, bool clippedToWorkArea) const noexcept; | |||||
| static void getCurrentMonitorPositions (Array <Rectangle<int> >&, const bool clipToWorkArea); | |||||
| void addDesktopComponent (Component*); | void addDesktopComponent (Component*); | ||||
| void removeDesktopComponent (Component*); | void removeDesktopComponent (Component*); | ||||
| void componentBroughtToFront (Component*); | void componentBroughtToFront (Component*); | ||||
| static void setKioskComponent (Component*, bool enableOrDisable, bool allowMenusAndBars); | |||||
| void setKioskComponent (Component*, bool enableOrDisable, bool allowMenusAndBars); | |||||
| void triggerFocusCallback(); | void triggerFocusCallback(); | ||||
| void handleAsyncUpdate(); | void handleAsyncUpdate(); | ||||
| @@ -144,7 +144,7 @@ void ComponentBoundsConstrainer::setBoundsForComponent (Component* const compone | |||||
| if (peer != nullptr) | if (peer != nullptr) | ||||
| border = peer->getFrameSize(); | border = peer->getFrameSize(); | ||||
| limits = Desktop::getInstance().getMonitorAreaContaining (bounds.getCentre()); | |||||
| limits = Desktop::getInstance().getDisplays().getDisplayContaining (bounds.getCentre()).userArea; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -621,13 +621,13 @@ private: | |||||
| //============================================================================== | //============================================================================== | ||||
| void calculateWindowPos (const Rectangle<int>& target, const bool alignToRectangle) | void calculateWindowPos (const Rectangle<int>& target, const bool alignToRectangle) | ||||
| { | { | ||||
| const Rectangle<int> mon (Desktop::getInstance() | |||||
| .getMonitorAreaContaining (target.getCentre(), | |||||
| #if JUCE_MAC | |||||
| true)); | |||||
| #else | |||||
| false)); // on windows, don't stop the menu overlapping the taskbar | |||||
| #endif | |||||
| const Rectangle<int> mon (Desktop::getInstance().getDisplays() | |||||
| .getDisplayContaining (target.getCentre()) | |||||
| #if JUCE_MAC | |||||
| .userArea); | |||||
| #else | |||||
| .totalArea); // on windows, don't stop the menu overlapping the taskbar | |||||
| #endif | |||||
| const int maxMenuHeight = mon.getHeight() - 24; | const int maxMenuHeight = mon.getHeight() - 24; | ||||
| @@ -796,7 +796,8 @@ private: | |||||
| windowPos.getHeight() - (PopupMenuSettings::scrollZone + m->getHeight())), | windowPos.getHeight() - (PopupMenuSettings::scrollZone + m->getHeight())), | ||||
| currentY); | currentY); | ||||
| const Rectangle<int> mon (Desktop::getInstance().getMonitorAreaContaining (windowPos.getPosition(), true)); | |||||
| const Rectangle<int> mon (Desktop::getInstance().getDisplays() | |||||
| .getDisplayContaining (windowPos.getPosition()).userArea); | |||||
| int deltaY = wantedY - currentY; | int deltaY = wantedY - currentY; | ||||
| @@ -261,7 +261,7 @@ public: | |||||
| void setFullScreen (bool shouldBeFullScreen) | void setFullScreen (bool shouldBeFullScreen) | ||||
| { | { | ||||
| Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getMainMonitorArea() | |||||
| Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getDisplays().getMainDisplay().userArea | |||||
| : lastNonFullscreenBounds); | : lastNonFullscreenBounds); | ||||
| if ((! shouldBeFullScreen) && r.isEmpty()) | if ((! shouldBeFullScreen) && r.isEmpty()) | ||||
| @@ -670,9 +670,14 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords, const bool clipToWorkArea) | |||||
| void Desktop::Displays::findDisplays() | |||||
| { | { | ||||
| monitorCoords.add (Rectangle<int> (android.screenWidth, android.screenHeight)); | |||||
| Display d; | |||||
| d.userArea = d.totalArea = Rectangle<int> (android.screenWidth, android.screenHeight); | |||||
| d.isMain = true; | |||||
| d.scale = 1.0; | |||||
| displays.add (d); | |||||
| } | } | ||||
| JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, setScreenSize, void, (JNIEnv* env, jobject activity, | JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, setScreenSize, void, (JNIEnv* env, jobject activity, | ||||
| @@ -682,7 +687,7 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, setScreenSize, void, (JNIEnv | |||||
| android.screenWidth = screenWidth; | android.screenWidth = screenWidth; | ||||
| android.screenHeight = screenHeight; | android.screenHeight = screenHeight; | ||||
| Desktop::getInstance().refreshMonitorSizes(); | |||||
| const_cast <Desktop::Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -553,7 +553,7 @@ CGRect UIViewComponentPeer::constrainRect (CGRect r) | |||||
| Rectangle<int> original (convertToRectInt (current)); | Rectangle<int> original (convertToRectInt (current)); | ||||
| constrainer->checkBounds (pos, original, | constrainer->checkBounds (pos, original, | ||||
| Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), | |||||
| Desktop::getInstance().getDisplays().getTotalBounds (true), | |||||
| pos.getY() != original.getY() && pos.getBottom() == original.getBottom(), | pos.getY() != original.getY() && pos.getBottom() == original.getBottom(), | ||||
| pos.getX() != original.getX() && pos.getRight() == original.getRight(), | pos.getX() != original.getX() && pos.getRight() == original.getRight(), | ||||
| pos.getY() == original.getY() && pos.getBottom() != original.getBottom(), | pos.getY() == original.getY() && pos.getBottom() != original.getBottom(), | ||||
| @@ -586,7 +586,7 @@ void UIViewComponentPeer::setFullScreen (bool shouldBeFullScreen) | |||||
| { | { | ||||
| if (! isSharedWindow) | if (! isSharedWindow) | ||||
| { | { | ||||
| Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getMainMonitorArea() | |||||
| Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getDisplays().getMainDisplay().userArea | |||||
| : lastNonFullscreenBounds); | : lastNonFullscreenBounds); | ||||
| if ((! shouldBeFullScreen) && r.isEmpty()) | if ((! shouldBeFullScreen) && r.isEmpty()) | ||||
| @@ -629,9 +629,11 @@ BOOL UIViewComponentPeer::shouldRotate (UIInterfaceOrientation interfaceOrientat | |||||
| void UIViewComponentPeer::displayRotated() | void UIViewComponentPeer::displayRotated() | ||||
| { | { | ||||
| Desktop& desktop = Desktop::getInstance(); | |||||
| const Rectangle<int> oldArea (component->getBounds()); | const Rectangle<int> oldArea (component->getBounds()); | ||||
| const Rectangle<int> oldDesktop (Desktop::getInstance().getMainMonitorArea()); | |||||
| Desktop::getInstance().refreshMonitorSizes(); | |||||
| const Rectangle<int> oldDesktop (desktop.getDisplays().getMainDisplay().userArea); | |||||
| const_cast <Desktop::Displays&> (desktop.getDisplays()).refresh(); | |||||
| if (fullScreen) | if (fullScreen) | ||||
| { | { | ||||
| @@ -645,7 +647,7 @@ void UIViewComponentPeer::displayRotated() | |||||
| const float t = oldArea.getY() / (float) oldDesktop.getHeight(); | const float t = oldArea.getY() / (float) oldDesktop.getHeight(); | ||||
| const float b = oldArea.getBottom() / (float) oldDesktop.getHeight(); | const float b = oldArea.getBottom() / (float) oldDesktop.getHeight(); | ||||
| const Rectangle<int> newDesktop (Desktop::getInstance().getMainMonitorArea()); | |||||
| const Rectangle<int> newDesktop (desktop.getDisplays().getMainDisplay().userArea); | |||||
| setBounds ((int) (l * newDesktop.getWidth()), | setBounds ((int) (l * newDesktop.getWidth()), | ||||
| (int) (t * newDesktop.getHeight()), | (int) (t * newDesktop.getHeight()), | ||||
| @@ -918,7 +920,7 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis | |||||
| [[UIApplication sharedApplication] setStatusBarHidden: enableOrDisable | [[UIApplication sharedApplication] setStatusBarHidden: enableOrDisable | ||||
| withAnimation: UIStatusBarAnimationSlide]; | withAnimation: UIStatusBarAnimationSlide]; | ||||
| Desktop::getInstance().refreshMonitorSizes(); | |||||
| displays.refresh(); | |||||
| ComponentPeer* const peer = kioskModeComponent->getPeer(); | ComponentPeer* const peer = kioskModeComponent->getPeer(); | ||||
| @@ -276,13 +276,21 @@ Desktop::DisplayOrientation Desktop::getCurrentOrientation() const | |||||
| return convertToJuceOrientation ([[UIApplication sharedApplication] statusBarOrientation]); | return convertToJuceOrientation ([[UIApplication sharedApplication] statusBarOrientation]); | ||||
| } | } | ||||
| void Desktop::getCurrentMonitorPositions (Array <Rectangle <int> >& monitorCoords, const bool clipToWorkArea) | |||||
| void Desktop::Displays::findDisplays() | |||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| monitorCoords.clear(); | |||||
| CGRect r = clipToWorkArea ? [[UIScreen mainScreen] applicationFrame] | |||||
| : [[UIScreen mainScreen] bounds]; | |||||
| UIScreen* s = [UIScreen mainScreen]; | |||||
| monitorCoords.add (UIViewComponentPeer::realScreenPosToRotated (convertToRectInt (r))); | |||||
| Display d; | |||||
| d.userArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s applicationFrame])); | |||||
| d.totalArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s bounds])); | |||||
| d.isMain = true; | |||||
| if ([s respondsToSelector: @selector (scale)]) | |||||
| d.scale = s.scale; | |||||
| else | |||||
| d.scale = 1.0; | |||||
| displays.add (d); | |||||
| } | } | ||||
| @@ -959,7 +959,7 @@ public: | |||||
| if (fullScreen != shouldBeFullScreen) | if (fullScreen != shouldBeFullScreen) | ||||
| { | { | ||||
| if (shouldBeFullScreen) | if (shouldBeFullScreen) | ||||
| r = Desktop::getInstance().getMainMonitorArea(); | |||||
| r = Desktop::getInstance().getDisplays().getMainDisplay().userArea; | |||||
| if (! r.isEmpty()) | if (! r.isEmpty()) | ||||
| setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen); | setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen); | ||||
| @@ -2588,7 +2588,7 @@ ModifierKeys ModifierKeys::getCurrentModifiersRealtime() noexcept | |||||
| void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool allowMenusAndBars) | void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool allowMenusAndBars) | ||||
| { | { | ||||
| if (enableOrDisable) | if (enableOrDisable) | ||||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||||
| kioskModeComponent->setBounds (Desktop::getInstance().getDisplays().getMainDisplay().totalArea); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -2627,7 +2627,7 @@ void juce_windowMessageReceive (XEvent* event) | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords, const bool /*clipToWorkArea*/) | |||||
| void Desktop::Displays::findDisplays() | |||||
| { | { | ||||
| if (display == 0) | if (display == 0) | ||||
| return; | return; | ||||
| @@ -2638,8 +2638,8 @@ void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords | |||||
| ScopedXLock xlock; | ScopedXLock xlock; | ||||
| if (XQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error)) | if (XQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error)) | ||||
| { | { | ||||
| typedef Bool (*tXineramaIsActive) (Display*); | |||||
| typedef XineramaScreenInfo* (*tXineramaQueryScreens) (Display*, int*); | |||||
| typedef Bool (*tXineramaIsActive) (::Display*); | |||||
| typedef XineramaScreenInfo* (*tXineramaQueryScreens) (::Display*, int*); | |||||
| static tXineramaIsActive xXineramaIsActive = 0; | static tXineramaIsActive xXineramaIsActive = 0; | ||||
| static tXineramaQueryScreens xXineramaQueryScreens = 0; | static tXineramaQueryScreens xXineramaQueryScreens = 0; | ||||
| @@ -2665,21 +2665,24 @@ void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords | |||||
| int numMonitors = 0; | int numMonitors = 0; | ||||
| XineramaScreenInfo* const screens = xXineramaQueryScreens (display, &numMonitors); | XineramaScreenInfo* const screens = xXineramaQueryScreens (display, &numMonitors); | ||||
| if (screens != 0) | |||||
| if (screens != nullptr) | |||||
| { | { | ||||
| for (int i = numMonitors; --i >= 0;) | |||||
| for (int index = 0; index < numMonitors; ++index) | |||||
| { | { | ||||
| int index = screens[i].screen_number; | |||||
| if (index >= 0) | |||||
| for (int j = numMonitors; --j >= 0;) | |||||
| { | { | ||||
| while (monitorCoords.size() < index) | |||||
| monitorCoords.add (Rectangle<int>()); | |||||
| monitorCoords.set (index, Rectangle<int> (screens[i].x_org, | |||||
| screens[i].y_org, | |||||
| screens[i].width, | |||||
| screens[i].height)); | |||||
| if (screens[j].screen_number == index) | |||||
| { | |||||
| Display d; | |||||
| d.userArea = d.totalArea = Rectangle<int> (screens[j].x_org, | |||||
| screens[j].y_org, | |||||
| screens[j].width, | |||||
| screens[j].height); | |||||
| d.isMain = (index == 0); | |||||
| d.scale = 1.0; | |||||
| displays.add (d); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -2688,7 +2691,7 @@ void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords | |||||
| } | } | ||||
| } | } | ||||
| if (monitorCoords.size() == 0) | |||||
| if (displays.size() == 0) | |||||
| #endif | #endif | ||||
| { | { | ||||
| Atom hints = Atoms::getIfExists ("_NET_WORKAREA"); | Atom hints = Atoms::getIfExists ("_NET_WORKAREA"); | ||||
| @@ -2713,18 +2716,30 @@ void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords | |||||
| const long* const position = (const long*) data; | const long* const position = (const long*) data; | ||||
| if (actualType == XA_CARDINAL && actualFormat == 32 && nitems == 4) | if (actualType == XA_CARDINAL && actualFormat == 32 && nitems == 4) | ||||
| monitorCoords.add (Rectangle<int> (position[0], position[1], | |||||
| position[2], position[3])); | |||||
| { | |||||
| Display d; | |||||
| d.userArea = d.totalArea = Rectangle<int> (position[0], position[1], | |||||
| position[2], position[3]); | |||||
| d.isMain = (displays.size() == 0); | |||||
| d.scale = 1.0; | |||||
| displays.add (d); | |||||
| } | |||||
| XFree (data); | XFree (data); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (monitorCoords.size() == 0) | |||||
| if (displays.size() == 0) | |||||
| { | { | ||||
| monitorCoords.add (Rectangle<int> (DisplayWidth (display, DefaultScreen (display)), | |||||
| DisplayHeight (display, DefaultScreen (display)))); | |||||
| Display d; | |||||
| d.userArea = d.totalArea = Rectangle<int> (DisplayWidth (display, DefaultScreen (display)), | |||||
| DisplayHeight (display, DefaultScreen (display))); | |||||
| d.isMain = true; | |||||
| d.scale = 1.0; | |||||
| displays.add (d); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1131,6 +1131,7 @@ NSRect NSViewComponentPeer::constrainRect (NSRect r) | |||||
| Rectangle<int> pos (convertToRectInt (r)); | Rectangle<int> pos (convertToRectInt (r)); | ||||
| Rectangle<int> original (convertToRectInt (current)); | Rectangle<int> original (convertToRectInt (current)); | ||||
| const Rectangle<int> screenBounds (Desktop::getInstance().getDisplays().getTotalBounds (true)); | |||||
| #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_ALLOWED >= MAC_OS_X_VERSION_10_6 | #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_ALLOWED >= MAC_OS_X_VERSION_10_6 | ||||
| if ([window inLiveResize]) | if ([window inLiveResize]) | ||||
| @@ -1139,14 +1140,12 @@ NSRect NSViewComponentPeer::constrainRect (NSRect r) | |||||
| && [window performSelector: @selector (inLiveResize)]) | && [window performSelector: @selector (inLiveResize)]) | ||||
| #endif | #endif | ||||
| { | { | ||||
| constrainer->checkBounds (pos, original, | |||||
| Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), | |||||
| constrainer->checkBounds (pos, original, screenBounds, | |||||
| false, false, true, true); | false, false, true, true); | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| constrainer->checkBounds (pos, original, | |||||
| Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), | |||||
| constrainer->checkBounds (pos, original, screenBounds, | |||||
| pos.getY() != original.getY() && pos.getBottom() == original.getBottom(), | pos.getY() != original.getY() && pos.getBottom() == original.getBottom(), | ||||
| pos.getX() != original.getX() && pos.getRight() == original.getRight(), | pos.getX() != original.getX() && pos.getRight() == original.getRight(), | ||||
| pos.getY() == original.getY() && pos.getBottom() != original.getBottom(), | pos.getY() == original.getY() && pos.getBottom() != original.getBottom(), | ||||
| @@ -1797,7 +1796,7 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis | |||||
| [NSApp setPresentationOptions: (allowMenusAndBars ? (NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar) | [NSApp setPresentationOptions: (allowMenusAndBars ? (NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar) | ||||
| : (NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar))]; | : (NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar))]; | ||||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||||
| kioskModeComponent->setBounds (Desktop::getInstance().getDisplays().getMainDisplay().totalArea); | |||||
| peer->becomeKeyWindow(); | peer->becomeKeyWindow(); | ||||
| } | } | ||||
| else | else | ||||
| @@ -1815,7 +1814,7 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis | |||||
| if (enableOrDisable) | if (enableOrDisable) | ||||
| { | { | ||||
| SetSystemUIMode (kUIModeAllSuppressed, allowMenusAndBars ? kUIOptionAutoShowMenuBar : 0); | SetSystemUIMode (kUIModeAllSuppressed, allowMenusAndBars ? kUIOptionAutoShowMenuBar : 0); | ||||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||||
| kioskModeComponent->setBounds (Desktop::getInstance().getDisplays().getMainDisplay().totalArea); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -285,7 +285,7 @@ public: | |||||
| static void displayReconfigurationCallBack (CGDirectDisplayID, CGDisplayChangeSummaryFlags, void*) | static void displayReconfigurationCallBack (CGDirectDisplayID, CGDisplayChangeSummaryFlags, void*) | ||||
| { | { | ||||
| Desktop::getInstance().refreshMonitorSizes(); | |||||
| const_cast <Desktop::Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||||
| } | } | ||||
| juce_DeclareSingleton_SingleThreaded_Minimal (DisplaySettingsChangeCallback); | juce_DeclareSingleton_SingleThreaded_Minimal (DisplaySettingsChangeCallback); | ||||
| @@ -296,29 +296,39 @@ private: | |||||
| juce_ImplementSingleton_SingleThreaded (DisplaySettingsChangeCallback); | juce_ImplementSingleton_SingleThreaded (DisplaySettingsChangeCallback); | ||||
| void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords, const bool clipToWorkArea) | |||||
| static Rectangle<int> convertDisplayRect (NSRect r, CGFloat mainScreenBottom) | |||||
| { | |||||
| r.origin.y = mainScreenBottom - (r.origin.y + r.size.height); | |||||
| return convertToRectInt (r); | |||||
| } | |||||
| void Desktop::Displays::findDisplays() | |||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| DisplaySettingsChangeCallback::getInstance(); | DisplaySettingsChangeCallback::getInstance(); | ||||
| monitorCoords.clear(); | |||||
| NSArray* screens = [NSScreen screens]; | NSArray* screens = [NSScreen screens]; | ||||
| const CGFloat mainScreenBottom = [[[NSScreen screens] objectAtIndex: 0] frame].size.height; | |||||
| const CGFloat mainScreenBottom = [[screens objectAtIndex: 0] frame].size.height; | |||||
| for (unsigned int i = 0; i < [screens count]; ++i) | for (unsigned int i = 0; i < [screens count]; ++i) | ||||
| { | { | ||||
| NSScreen* s = (NSScreen*) [screens objectAtIndex: i]; | NSScreen* s = (NSScreen*) [screens objectAtIndex: i]; | ||||
| NSRect r = clipToWorkArea ? [s visibleFrame] | |||||
| : [s frame]; | |||||
| Display d; | |||||
| d.userArea = convertDisplayRect ([s visibleFrame], mainScreenBottom); | |||||
| d.totalArea = convertDisplayRect ([s frame], mainScreenBottom); | |||||
| d.isMain = (i == 0); | |||||
| r.origin.y = mainScreenBottom - (r.origin.y + r.size.height); | |||||
| #if defined (MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6) | |||||
| if ([s respondsToSelector: @selector (backingScaleFactor)]) | |||||
| d.scale = s.backingScaleFactor; | |||||
| else | |||||
| #endif | |||||
| d.scale = 1.0; | |||||
| monitorCoords.add (convertToRectInt (r)); | |||||
| displays.add (d); | |||||
| } | } | ||||
| jassert (monitorCoords.size() > 0); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -157,7 +157,7 @@ void FileChooser::showPlatformDialog (Array<File>& results, const String& title_ | |||||
| // use a modal window as the parent for this dialog box | // use a modal window as the parent for this dialog box | ||||
| // to block input from other app windows | // to block input from other app windows | ||||
| Component parentWindow (String::empty); | Component parentWindow (String::empty); | ||||
| const Rectangle<int> mainMon (Desktop::getInstance().getMainMonitorArea()); | |||||
| const Rectangle<int> mainMon (Desktop::getInstance().getDisplays().getMainDisplay().userArea); | |||||
| parentWindow.setBounds (mainMon.getX() + mainMon.getWidth() / 4, | parentWindow.setBounds (mainMon.getX() + mainMon.getWidth() / 4, | ||||
| mainMon.getY() + mainMon.getHeight() / 4, | mainMon.getY() + mainMon.getHeight() / 4, | ||||
| 0, 0); | 0, 0); | ||||
| @@ -1961,7 +1961,7 @@ private: | |||||
| Rectangle<int> pos (rectangleFromRECT (*r)); | Rectangle<int> pos (rectangleFromRECT (*r)); | ||||
| constrainer->checkBounds (pos, windowBorder.addedTo (component->getBounds()), | constrainer->checkBounds (pos, windowBorder.addedTo (component->getBounds()), | ||||
| Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), | |||||
| Desktop::getInstance().getDisplays().getTotalBounds (true), | |||||
| wParam == WMSZ_TOP || wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOPRIGHT, | wParam == WMSZ_TOP || wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOPRIGHT, | ||||
| wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT || wParam == WMSZ_BOTTOMLEFT, | wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT || wParam == WMSZ_BOTTOMLEFT, | ||||
| wParam == WMSZ_BOTTOM || wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_BOTTOMRIGHT, | wParam == WMSZ_BOTTOM || wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_BOTTOMRIGHT, | ||||
| @@ -1986,7 +1986,7 @@ private: | |||||
| const Rectangle<int> current (windowBorder.addedTo (component->getBounds())); | const Rectangle<int> current (windowBorder.addedTo (component->getBounds())); | ||||
| constrainer->checkBounds (pos, current, | constrainer->checkBounds (pos, current, | ||||
| Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), | |||||
| Desktop::getInstance().getDisplays().getTotalBounds (true), | |||||
| pos.getY() != current.getY() && pos.getBottom() == current.getBottom(), | pos.getY() != current.getY() && pos.getBottom() == current.getBottom(), | ||||
| pos.getX() != current.getX() && pos.getRight() == current.getRight(), | pos.getX() != current.getX() && pos.getRight() == current.getRight(), | ||||
| pos.getY() == current.getY() && pos.getBottom() != current.getBottom(), | pos.getY() == current.getY() && pos.getBottom() != current.getBottom(), | ||||
| @@ -2079,7 +2079,7 @@ private: | |||||
| void doSettingChange() | void doSettingChange() | ||||
| { | { | ||||
| Desktop::getInstance().refreshMonitorSizes(); | |||||
| const_cast <Desktop::Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||||
| if (fullScreen && ! isMinimised()) | if (fullScreen && ! isMinimised()) | ||||
| { | { | ||||
| @@ -3024,7 +3024,7 @@ String SystemClipboard::getTextFromClipboard() | |||||
| void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool /*allowMenusAndBars*/) | void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool /*allowMenusAndBars*/) | ||||
| { | { | ||||
| if (enableOrDisable) | if (enableOrDisable) | ||||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||||
| kioskModeComponent->setBounds (getDisplays().getMainDisplay().totalArea); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -3035,30 +3035,37 @@ static BOOL CALLBACK enumMonitorsProc (HMONITOR, HDC, LPRECT r, LPARAM userInfo) | |||||
| return TRUE; | return TRUE; | ||||
| } | } | ||||
| void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords, const bool clipToWorkArea) | |||||
| void Desktop::Displays::findDisplays() | |||||
| { | { | ||||
| EnumDisplayMonitors (0, 0, &enumMonitorsProc, (LPARAM) &monitorCoords); | |||||
| Array <Rectangle<int> > monitors; | |||||
| EnumDisplayMonitors (0, 0, &enumMonitorsProc, (LPARAM) &monitors); | |||||
| // make sure the first in the list is the main monitor | // make sure the first in the list is the main monitor | ||||
| for (int i = 1; i < monitorCoords.size(); ++i) | |||||
| if (monitorCoords[i].getX() == 0 && monitorCoords[i].getY() == 0) | |||||
| monitorCoords.swap (i, 0); | |||||
| for (int i = 1; i < monitors.size(); ++i) | |||||
| if (monitors.getReference(i).getX() == 0 && monitors.getReference(i).getY() == 0) | |||||
| monitors.swap (i, 0); | |||||
| if (monitorCoords.size() == 0) | |||||
| if (monitors.size() == 0) | |||||
| { | { | ||||
| RECT r; | RECT r; | ||||
| GetWindowRect (GetDesktopWindow(), &r); | GetWindowRect (GetDesktopWindow(), &r); | ||||
| monitorCoords.add (rectangleFromRECT (r)); | |||||
| monitors.add (rectangleFromRECT (r)); | |||||
| } | } | ||||
| if (clipToWorkArea) | |||||
| RECT workArea; | |||||
| SystemParametersInfo (SPI_GETWORKAREA, 0, &workArea, 0); | |||||
| for (int i = 0; i < monitors.size(); ++i) | |||||
| { | { | ||||
| // clip the main monitor to the active non-taskbar area | |||||
| RECT r; | |||||
| SystemParametersInfo (SPI_GETWORKAREA, 0, &r, 0); | |||||
| Display d; | |||||
| d.userArea = d.totalArea = monitors.getReference(i); | |||||
| d.isMain = (i == 0); | |||||
| d.scale = 1.0; | |||||
| if (i == 0) | |||||
| d.userArea = d.userArea.getIntersection (rectangleFromRECT (workArea)); | |||||
| Rectangle<int>& screen = monitorCoords.getReference (0); | |||||
| screen = screen.getIntersection (rectangleFromRECT (r)); | |||||
| displays.add (d); | |||||
| } | } | ||||
| } | } | ||||
| @@ -538,13 +538,13 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) | |||||
| { | { | ||||
| Desktop& desktop = Desktop::getInstance(); | Desktop& desktop = Desktop::getInstance(); | ||||
| RectangleList allMonitors (desktop.getAllMonitorDisplayAreas()); | |||||
| RectangleList allMonitors (desktop.getDisplays().getRectangleList (true)); | |||||
| allMonitors.clipTo (newPos); | allMonitors.clipTo (newPos); | ||||
| const Rectangle<int> onScreenArea (allMonitors.getBounds()); | const Rectangle<int> onScreenArea (allMonitors.getBounds()); | ||||
| if (onScreenArea.getWidth() * onScreenArea.getHeight() < 32 * 32) | if (onScreenArea.getWidth() * onScreenArea.getHeight() < 32 * 32) | ||||
| { | { | ||||
| const Rectangle<int> screen (desktop.getMonitorAreaContaining (newPos.getCentre())); | |||||
| const Rectangle<int> screen (desktop.getDisplays().getDisplayContaining (newPos.getCentre()).userArea); | |||||
| newPos.setSize (jmin (newPos.getWidth(), screen.getWidth()), | newPos.setSize (jmin (newPos.getWidth(), screen.getWidth()), | ||||
| jmin (newPos.getHeight(), screen.getHeight())); | jmin (newPos.getHeight(), screen.getHeight())); | ||||
| @@ -72,15 +72,16 @@ void TooltipWindow::showFor (const String& tip) | |||||
| Point<int> mousePos (Desktop::getMousePosition()); | Point<int> mousePos (Desktop::getMousePosition()); | ||||
| Rectangle<int> parentArea; | Rectangle<int> parentArea; | ||||
| Component* const parent = getParentComponent(); | |||||
| if (getParentComponent() != nullptr) | |||||
| if (parent != nullptr) | |||||
| { | { | ||||
| mousePos = getParentComponent()->getLocalPoint (nullptr, mousePos); | |||||
| parentArea = getParentComponent()->getLocalBounds(); | |||||
| mousePos = parent->getLocalPoint (nullptr, mousePos); | |||||
| parentArea = parent->getLocalBounds(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| parentArea = Desktop::getInstance().getMonitorAreaContaining (mousePos); | |||||
| parentArea = Desktop::getInstance().getDisplays().getDisplayContaining (mousePos).userArea; | |||||
| } | } | ||||
| int w, h; | int w, h; | ||||
| @@ -98,18 +99,16 @@ void TooltipWindow::showFor (const String& tip) | |||||
| else | else | ||||
| y += 6; | y += 6; | ||||
| x = jlimit (parentArea.getX(), parentArea.getRight() - w, x); | |||||
| x = jlimit (parentArea.getX(), parentArea.getRight() - w, x); | |||||
| y = jlimit (parentArea.getY(), parentArea.getBottom() - h, y); | y = jlimit (parentArea.getY(), parentArea.getBottom() - h, y); | ||||
| setBounds (x, y, w, h); | setBounds (x, y, w, h); | ||||
| setVisible (true); | setVisible (true); | ||||
| if (getParentComponent() == nullptr) | |||||
| { | |||||
| if (parent == nullptr) | |||||
| addToDesktop (ComponentPeer::windowHasDropShadow | addToDesktop (ComponentPeer::windowHasDropShadow | ||||
| | ComponentPeer::windowIsTemporary | | ComponentPeer::windowIsTemporary | ||||
| | ComponentPeer::windowIgnoresKeyPresses); | | ComponentPeer::windowIgnoresKeyPresses); | ||||
| } | |||||
| toFront (false); | toFront (false); | ||||
| } | } | ||||