diff --git a/modules/juce_gui_basics/components/juce_Component.cpp b/modules/juce_gui_basics/components/juce_Component.cpp index 3feb3cdf00..dfdd16b587 100644 --- a/modules/juce_gui_basics/components/juce_Component.cpp +++ b/modules/juce_gui_basics/components/juce_Component.cpp @@ -363,7 +363,7 @@ struct Component::ComponentHelpers static Rectangle getParentOrMainMonitorBounds (const Component& comp) { return comp.getParentComponent() != nullptr ? comp.getParentComponent()->getLocalBounds() - : Desktop::getInstance().getMainMonitorArea(); + : Desktop::getInstance().getDisplays().getMainDisplay().userArea; } }; @@ -983,7 +983,7 @@ Rectangle Component::getScreenBounds() const { return localAreaToGlobal Rectangle Component::getParentMonitorArea() const { - return Desktop::getInstance().getMonitorAreaContaining (getScreenBounds().getCentre()); + return Desktop::getInstance().getDisplays().getDisplayContaining (getScreenBounds().getCentre()).userArea; } Point Component::getLocalPoint (const Component* source, const Point& point) const diff --git a/modules/juce_gui_basics/components/juce_Desktop.cpp b/modules/juce_gui_basics/components/juce_Desktop.cpp index 4f5e62eb84..72088f3b91 100644 --- a/modules/juce_gui_basics/components/juce_Desktop.cpp +++ b/modules/juce_gui_basics/components/juce_Desktop.cpp @@ -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 > 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 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 Desktop::getMainMonitorArea (const bool clippedToWorkArea) const noexcept -{ - return getDisplayMonitorCoordinates (0, clippedToWorkArea); -} - -Rectangle Desktop::getMonitorAreaContaining (const Point& position, const bool clippedToWorkArea) const -{ - Rectangle best (getMainMonitorArea (clippedToWorkArea)); - double bestDistance = 1.0e10; - - for (int i = getNumDisplayMonitors(); --i >= 0;) - { - const Rectangle 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& 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 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 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) { diff --git a/modules/juce_gui_basics/components/juce_Desktop.h b/modules/juce_gui_basics/components/juce_Desktop.h index 7be50d5b6a..5b5c5ee169 100644 --- a/modules/juce_gui_basics/components/juce_Desktop.h +++ b/modules/juce_gui_basics/components/juce_Desktop.h @@ -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 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 getMonitorAreaContaining (const Point& 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 userArea; + + /** This is the total physical area of this display, including any taskbars, etc */ + Rectangle 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& 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 getTotalBounds (bool userAreasOnly) const; + + /** The list of displays. */ + Array 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 focusListeners; Array desktopComponents; - Array > monitorCoordsClipped, monitorCoordsUnclipped; + + Displays displays; Point lastFakeMouseMove; void sendMouseMove(); @@ -389,15 +410,11 @@ private: void resetTimer(); ListenerList & getMouseListeners(); - int getNumDisplayMonitors() const noexcept; - Rectangle getDisplayMonitorCoordinates (int index, bool clippedToWorkArea) const noexcept; - static void getCurrentMonitorPositions (Array >&, 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(); diff --git a/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.cpp b/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.cpp index 2ac1af81ff..d67d0183d1 100644 --- a/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.cpp +++ b/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.cpp @@ -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 { diff --git a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp index 46c77cf13b..ad7ce03070 100644 --- a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp +++ b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp @@ -621,13 +621,13 @@ private: //============================================================================== void calculateWindowPos (const Rectangle& target, const bool alignToRectangle) { - const Rectangle 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 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 mon (Desktop::getInstance().getMonitorAreaContaining (windowPos.getPosition(), true)); + const Rectangle mon (Desktop::getInstance().getDisplays() + .getDisplayContaining (windowPos.getPosition()).userArea); int deltaY = wantedY - currentY; diff --git a/modules/juce_gui_basics/native/juce_android_Windowing.cpp b/modules/juce_gui_basics/native/juce_android_Windowing.cpp index 5f119536cf..c5b2cefa89 100644 --- a/modules/juce_gui_basics/native/juce_android_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_android_Windowing.cpp @@ -261,7 +261,7 @@ public: void setFullScreen (bool shouldBeFullScreen) { - Rectangle r (shouldBeFullScreen ? Desktop::getInstance().getMainMonitorArea() + Rectangle 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 >& monitorCoords, const bool clipToWorkArea) +void Desktop::Displays::findDisplays() { - monitorCoords.add (Rectangle (android.screenWidth, android.screenHeight)); + Display d; + d.userArea = d.totalArea = Rectangle (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::getInstance().getDisplays()).refresh(); } //============================================================================== diff --git a/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm index 8b8d2afc70..05ade32a69 100644 --- a/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm @@ -553,7 +553,7 @@ CGRect UIViewComponentPeer::constrainRect (CGRect r) Rectangle 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 r (shouldBeFullScreen ? Desktop::getInstance().getMainMonitorArea() + Rectangle 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 oldArea (component->getBounds()); - const Rectangle oldDesktop (Desktop::getInstance().getMainMonitorArea()); - Desktop::getInstance().refreshMonitorSizes(); + const Rectangle oldDesktop (desktop.getDisplays().getMainDisplay().userArea); + + const_cast (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 newDesktop (Desktop::getInstance().getMainMonitorArea()); + const Rectangle 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(); diff --git a/modules/juce_gui_basics/native/juce_ios_Windowing.mm b/modules/juce_gui_basics/native/juce_ios_Windowing.mm index ce27ccb6ba..867fbeb622 100644 --- a/modules/juce_gui_basics/native/juce_ios_Windowing.mm +++ b/modules/juce_gui_basics/native/juce_ios_Windowing.mm @@ -276,13 +276,21 @@ Desktop::DisplayOrientation Desktop::getCurrentOrientation() const return convertToJuceOrientation ([[UIApplication sharedApplication] statusBarOrientation]); } -void Desktop::getCurrentMonitorPositions (Array >& 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); } diff --git a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp index a45bfb4474..5a000c7f9c 100644 --- a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp @@ -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 >& monitorCoords, const bool /*clipToWorkArea*/) +void Desktop::Displays::findDisplays() { if (display == 0) return; @@ -2638,8 +2638,8 @@ void Desktop::getCurrentMonitorPositions (Array >& 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 >& 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()); - - monitorCoords.set (index, Rectangle (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 (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 >& monitorCoords } } - if (monitorCoords.size() == 0) + if (displays.size() == 0) #endif { Atom hints = Atoms::getIfExists ("_NET_WORKAREA"); @@ -2713,18 +2716,30 @@ void Desktop::getCurrentMonitorPositions (Array >& monitorCoords const long* const position = (const long*) data; if (actualType == XA_CARDINAL && actualFormat == 32 && nitems == 4) - monitorCoords.add (Rectangle (position[0], position[1], - position[2], position[3])); + { + Display d; + d.userArea = d.totalArea = Rectangle (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 (DisplayWidth (display, DefaultScreen (display)), - DisplayHeight (display, DefaultScreen (display)))); + Display d; + d.userArea = d.totalArea = Rectangle (DisplayWidth (display, DefaultScreen (display)), + DisplayHeight (display, DefaultScreen (display))); + d.isMain = true; + d.scale = 1.0; + + displays.add (d); } } } diff --git a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index 37571cc8f9..565dca62c8 100644 --- a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -1131,6 +1131,7 @@ NSRect NSViewComponentPeer::constrainRect (NSRect r) Rectangle pos (convertToRectInt (r)); Rectangle original (convertToRectInt (current)); + const Rectangle 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 { diff --git a/modules/juce_gui_basics/native/juce_mac_Windowing.mm b/modules/juce_gui_basics/native/juce_mac_Windowing.mm index 1f8d93cd5d..6cf783d911 100644 --- a/modules/juce_gui_basics/native/juce_mac_Windowing.mm +++ b/modules/juce_gui_basics/native/juce_mac_Windowing.mm @@ -285,7 +285,7 @@ public: static void displayReconfigurationCallBack (CGDirectDisplayID, CGDisplayChangeSummaryFlags, void*) { - Desktop::getInstance().refreshMonitorSizes(); + const_cast (Desktop::getInstance().getDisplays()).refresh(); } juce_DeclareSingleton_SingleThreaded_Minimal (DisplaySettingsChangeCallback); @@ -296,29 +296,39 @@ private: juce_ImplementSingleton_SingleThreaded (DisplaySettingsChangeCallback); -void Desktop::getCurrentMonitorPositions (Array >& monitorCoords, const bool clipToWorkArea) +static Rectangle 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); } //============================================================================== diff --git a/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp b/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp index 42c3de4b80..fa9db5c1a8 100644 --- a/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp +++ b/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp @@ -157,7 +157,7 @@ void FileChooser::showPlatformDialog (Array& 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 mainMon (Desktop::getInstance().getMainMonitorArea()); + const Rectangle mainMon (Desktop::getInstance().getDisplays().getMainDisplay().userArea); parentWindow.setBounds (mainMon.getX() + mainMon.getWidth() / 4, mainMon.getY() + mainMon.getHeight() / 4, 0, 0); diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index b3d4371fbd..77351f85d8 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -1961,7 +1961,7 @@ private: Rectangle 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 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::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 >& monitorCoords, const bool clipToWorkArea) +void Desktop::Displays::findDisplays() { - EnumDisplayMonitors (0, 0, &enumMonitorsProc, (LPARAM) &monitorCoords); + Array > 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& screen = monitorCoords.getReference (0); - screen = screen.getIntersection (rectangleFromRECT (r)); + displays.add (d); } } diff --git a/modules/juce_gui_basics/windows/juce_ResizableWindow.cpp b/modules/juce_gui_basics/windows/juce_ResizableWindow.cpp index 6b64e6f4e3..3709ffcc51 100644 --- a/modules/juce_gui_basics/windows/juce_ResizableWindow.cpp +++ b/modules/juce_gui_basics/windows/juce_ResizableWindow.cpp @@ -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 onScreenArea (allMonitors.getBounds()); if (onScreenArea.getWidth() * onScreenArea.getHeight() < 32 * 32) { - const Rectangle screen (desktop.getMonitorAreaContaining (newPos.getCentre())); + const Rectangle screen (desktop.getDisplays().getDisplayContaining (newPos.getCentre()).userArea); newPos.setSize (jmin (newPos.getWidth(), screen.getWidth()), jmin (newPos.getHeight(), screen.getHeight())); diff --git a/modules/juce_gui_basics/windows/juce_TooltipWindow.cpp b/modules/juce_gui_basics/windows/juce_TooltipWindow.cpp index 6ccbb11899..7c57e69fb1 100644 --- a/modules/juce_gui_basics/windows/juce_TooltipWindow.cpp +++ b/modules/juce_gui_basics/windows/juce_TooltipWindow.cpp @@ -72,15 +72,16 @@ void TooltipWindow::showFor (const String& tip) Point mousePos (Desktop::getMousePosition()); Rectangle 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); }