| @@ -363,7 +363,7 @@ struct Component::ComponentHelpers | |||
| static Rectangle<int> getParentOrMainMonitorBounds (const Component& comp) | |||
| { | |||
| 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 | |||
| { | |||
| 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 | |||
| @@ -29,7 +29,6 @@ Desktop::Desktop() | |||
| allowedOrientations (allOrientations) | |||
| { | |||
| createMouseInputSources(); | |||
| refreshMonitorSizes(); | |||
| } | |||
| Desktop::~Desktop() | |||
| @@ -54,79 +53,6 @@ Desktop& JUCE_CALLTYPE Desktop::getInstance() | |||
| 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 | |||
| { | |||
| @@ -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) | |||
| { | |||
| @@ -66,34 +66,6 @@ public: | |||
| */ | |||
| 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. | |||
| @@ -338,12 +310,60 @@ public: | |||
| 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 */ | |||
| static bool canUseSemiTransparentWindows() noexcept; | |||
| @@ -365,7 +385,8 @@ private: | |||
| ListenerList <FocusChangeListener> focusListeners; | |||
| Array <Component*> desktopComponents; | |||
| Array <Rectangle<int> > monitorCoordsClipped, monitorCoordsUnclipped; | |||
| Displays displays; | |||
| Point<int> lastFakeMouseMove; | |||
| void sendMouseMove(); | |||
| @@ -389,15 +410,11 @@ private: | |||
| void resetTimer(); | |||
| 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 removeDesktopComponent (Component*); | |||
| void componentBroughtToFront (Component*); | |||
| static void setKioskComponent (Component*, bool enableOrDisable, bool allowMenusAndBars); | |||
| void setKioskComponent (Component*, bool enableOrDisable, bool allowMenusAndBars); | |||
| void triggerFocusCallback(); | |||
| void handleAsyncUpdate(); | |||
| @@ -144,7 +144,7 @@ void ComponentBoundsConstrainer::setBoundsForComponent (Component* const compone | |||
| if (peer != nullptr) | |||
| border = peer->getFrameSize(); | |||
| limits = Desktop::getInstance().getMonitorAreaContaining (bounds.getCentre()); | |||
| limits = Desktop::getInstance().getDisplays().getDisplayContaining (bounds.getCentre()).userArea; | |||
| } | |||
| else | |||
| { | |||
| @@ -621,13 +621,13 @@ private: | |||
| //============================================================================== | |||
| 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; | |||
| @@ -796,7 +796,8 @@ private: | |||
| windowPos.getHeight() - (PopupMenuSettings::scrollZone + m->getHeight())), | |||
| 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; | |||
| @@ -261,7 +261,7 @@ public: | |||
| void setFullScreen (bool shouldBeFullScreen) | |||
| { | |||
| Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getMainMonitorArea() | |||
| Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getDisplays().getMainDisplay().userArea | |||
| : lastNonFullscreenBounds); | |||
| 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, | |||
| @@ -682,7 +687,7 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, setScreenSize, void, (JNIEnv | |||
| android.screenWidth = screenWidth; | |||
| 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)); | |||
| constrainer->checkBounds (pos, original, | |||
| Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), | |||
| Desktop::getInstance().getDisplays().getTotalBounds (true), | |||
| pos.getY() != original.getY() && pos.getBottom() == original.getBottom(), | |||
| pos.getX() != original.getX() && pos.getRight() == original.getRight(), | |||
| pos.getY() == original.getY() && pos.getBottom() != original.getBottom(), | |||
| @@ -586,7 +586,7 @@ void UIViewComponentPeer::setFullScreen (bool shouldBeFullScreen) | |||
| { | |||
| if (! isSharedWindow) | |||
| { | |||
| Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getMainMonitorArea() | |||
| Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getDisplays().getMainDisplay().userArea | |||
| : lastNonFullscreenBounds); | |||
| if ((! shouldBeFullScreen) && r.isEmpty()) | |||
| @@ -629,9 +629,11 @@ BOOL UIViewComponentPeer::shouldRotate (UIInterfaceOrientation interfaceOrientat | |||
| void UIViewComponentPeer::displayRotated() | |||
| { | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| 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) | |||
| { | |||
| @@ -645,7 +647,7 @@ void UIViewComponentPeer::displayRotated() | |||
| const float t = oldArea.getY() / (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()), | |||
| (int) (t * newDesktop.getHeight()), | |||
| @@ -918,7 +920,7 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis | |||
| [[UIApplication sharedApplication] setStatusBarHidden: enableOrDisable | |||
| withAnimation: UIStatusBarAnimationSlide]; | |||
| Desktop::getInstance().refreshMonitorSizes(); | |||
| displays.refresh(); | |||
| ComponentPeer* const peer = kioskModeComponent->getPeer(); | |||
| @@ -276,13 +276,21 @@ Desktop::DisplayOrientation Desktop::getCurrentOrientation() const | |||
| return convertToJuceOrientation ([[UIApplication sharedApplication] statusBarOrientation]); | |||
| } | |||
| void Desktop::getCurrentMonitorPositions (Array <Rectangle <int> >& monitorCoords, const bool clipToWorkArea) | |||
| void Desktop::Displays::findDisplays() | |||
| { | |||
| 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 (shouldBeFullScreen) | |||
| r = Desktop::getInstance().getMainMonitorArea(); | |||
| r = Desktop::getInstance().getDisplays().getMainDisplay().userArea; | |||
| if (! r.isEmpty()) | |||
| 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) | |||
| { | |||
| 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) | |||
| return; | |||
| @@ -2638,8 +2638,8 @@ void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords | |||
| ScopedXLock xlock; | |||
| 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 tXineramaQueryScreens xXineramaQueryScreens = 0; | |||
| @@ -2665,21 +2665,24 @@ void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords | |||
| int numMonitors = 0; | |||
| 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 | |||
| { | |||
| Atom hints = Atoms::getIfExists ("_NET_WORKAREA"); | |||
| @@ -2713,18 +2716,30 @@ void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords | |||
| const long* const position = (const long*) data; | |||
| 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); | |||
| } | |||
| } | |||
| } | |||
| 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> 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 ([window inLiveResize]) | |||
| @@ -1139,14 +1140,12 @@ NSRect NSViewComponentPeer::constrainRect (NSRect r) | |||
| && [window performSelector: @selector (inLiveResize)]) | |||
| #endif | |||
| { | |||
| constrainer->checkBounds (pos, original, | |||
| Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), | |||
| constrainer->checkBounds (pos, original, screenBounds, | |||
| false, false, true, true); | |||
| } | |||
| else | |||
| { | |||
| constrainer->checkBounds (pos, original, | |||
| Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), | |||
| constrainer->checkBounds (pos, original, screenBounds, | |||
| pos.getY() != original.getY() && pos.getBottom() == original.getBottom(), | |||
| pos.getX() != original.getX() && pos.getRight() == original.getRight(), | |||
| pos.getY() == original.getY() && pos.getBottom() != original.getBottom(), | |||
| @@ -1797,7 +1796,7 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis | |||
| [NSApp setPresentationOptions: (allowMenusAndBars ? (NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar) | |||
| : (NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar))]; | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getDisplays().getMainDisplay().totalArea); | |||
| peer->becomeKeyWindow(); | |||
| } | |||
| else | |||
| @@ -1815,7 +1814,7 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis | |||
| if (enableOrDisable) | |||
| { | |||
| SetSystemUIMode (kUIModeAllSuppressed, allowMenusAndBars ? kUIOptionAutoShowMenuBar : 0); | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getDisplays().getMainDisplay().totalArea); | |||
| } | |||
| else | |||
| { | |||
| @@ -285,7 +285,7 @@ public: | |||
| static void displayReconfigurationCallBack (CGDirectDisplayID, CGDisplayChangeSummaryFlags, void*) | |||
| { | |||
| Desktop::getInstance().refreshMonitorSizes(); | |||
| const_cast <Desktop::Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||
| } | |||
| juce_DeclareSingleton_SingleThreaded_Minimal (DisplaySettingsChangeCallback); | |||
| @@ -296,29 +296,39 @@ private: | |||
| 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 | |||
| DisplaySettingsChangeCallback::getInstance(); | |||
| monitorCoords.clear(); | |||
| 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) | |||
| { | |||
| 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 | |||
| // to block input from other app windows | |||
| 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, | |||
| mainMon.getY() + mainMon.getHeight() / 4, | |||
| 0, 0); | |||
| @@ -1961,7 +1961,7 @@ private: | |||
| Rectangle<int> pos (rectangleFromRECT (*r)); | |||
| 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_LEFT || wParam == WMSZ_TOPLEFT || wParam == WMSZ_BOTTOMLEFT, | |||
| wParam == WMSZ_BOTTOM || wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_BOTTOMRIGHT, | |||
| @@ -1986,7 +1986,7 @@ private: | |||
| const Rectangle<int> current (windowBorder.addedTo (component->getBounds())); | |||
| constrainer->checkBounds (pos, current, | |||
| Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), | |||
| Desktop::getInstance().getDisplays().getTotalBounds (true), | |||
| pos.getY() != current.getY() && pos.getBottom() == current.getBottom(), | |||
| pos.getX() != current.getX() && pos.getRight() == current.getRight(), | |||
| pos.getY() == current.getY() && pos.getBottom() != current.getBottom(), | |||
| @@ -2079,7 +2079,7 @@ private: | |||
| void doSettingChange() | |||
| { | |||
| Desktop::getInstance().refreshMonitorSizes(); | |||
| const_cast <Desktop::Displays&> (Desktop::getInstance().getDisplays()).refresh(); | |||
| if (fullScreen && ! isMinimised()) | |||
| { | |||
| @@ -3024,7 +3024,7 @@ String SystemClipboard::getTextFromClipboard() | |||
| void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool /*allowMenusAndBars*/) | |||
| { | |||
| 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; | |||
| } | |||
| 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 | |||
| 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; | |||
| 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(); | |||
| RectangleList allMonitors (desktop.getAllMonitorDisplayAreas()); | |||
| RectangleList allMonitors (desktop.getDisplays().getRectangleList (true)); | |||
| allMonitors.clipTo (newPos); | |||
| const Rectangle<int> onScreenArea (allMonitors.getBounds()); | |||
| 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()), | |||
| jmin (newPos.getHeight(), screen.getHeight())); | |||
| @@ -72,15 +72,16 @@ void TooltipWindow::showFor (const String& tip) | |||
| Point<int> mousePos (Desktop::getMousePosition()); | |||
| 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 | |||
| { | |||
| parentArea = Desktop::getInstance().getMonitorAreaContaining (mousePos); | |||
| parentArea = Desktop::getInstance().getDisplays().getDisplayContaining (mousePos).userArea; | |||
| } | |||
| int w, h; | |||
| @@ -98,18 +99,16 @@ void TooltipWindow::showFor (const String& tip) | |||
| else | |||
| 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); | |||
| setBounds (x, y, w, h); | |||
| setVisible (true); | |||
| if (getParentComponent() == nullptr) | |||
| { | |||
| if (parent == nullptr) | |||
| addToDesktop (ComponentPeer::windowHasDropShadow | |||
| | ComponentPeer::windowIsTemporary | |||
| | ComponentPeer::windowIgnoresKeyPresses); | |||
| } | |||
| toFront (false); | |||
| } | |||