diff --git a/modules/juce_gui_basics/native/juce_android_Windowing.cpp b/modules/juce_gui_basics/native/juce_android_Windowing.cpp index d4cda489e9..aed6291607 100644 --- a/modules/juce_gui_basics/native/juce_android_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_android_Windowing.cpp @@ -703,6 +703,12 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis // TODO } +//============================================================================== +bool juce_areThereAnyAlwaysOnTopWindows() +{ + return false; +} + //============================================================================== void Desktop::Displays::findDisplays() { diff --git a/modules/juce_gui_basics/native/juce_ios_Windowing.mm b/modules/juce_gui_basics/native/juce_ios_Windowing.mm index 12d37b8f64..db82d002a4 100644 --- a/modules/juce_gui_basics/native/juce_ios_Windowing.mm +++ b/modules/juce_gui_basics/native/juce_ios_Windowing.mm @@ -245,6 +245,12 @@ bool Desktop::isScreenSaverEnabled() return ! [[UIApplication sharedApplication] isIdleTimerDisabled]; } +//============================================================================== +bool juce_areThereAnyAlwaysOnTopWindows() +{ + return false; +} + //============================================================================== Image juce_createIconForFile (const File& file) { diff --git a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp index ecd4942bc4..88ee129e73 100644 --- a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp @@ -3159,6 +3159,12 @@ bool Desktop::isScreenSaverEnabled() return screenSaverAllowed; } +//============================================================================== +bool juce_areThereAnyAlwaysOnTopWindows() +{ + return false; // XXX should be implemented +} + //============================================================================== void* CustomMouseCursorInfo::create() const { diff --git a/modules/juce_gui_basics/native/juce_mac_Windowing.mm b/modules/juce_gui_basics/native/juce_mac_Windowing.mm index ed442ab9fe..6dc991b0ae 100644 --- a/modules/juce_gui_basics/native/juce_mac_Windowing.mm +++ b/modules/juce_gui_basics/native/juce_mac_Windowing.mm @@ -325,6 +325,24 @@ void Desktop::Displays::findDisplays() } } +//============================================================================== +bool juce_areThereAnyAlwaysOnTopWindows() +{ + NSArray* windows = [NSApp windows]; + + for (unsigned int i = 0; i < [windows count]; ++i) + { + const NSInteger level = [((NSWindow*) [windows objectAtIndex: i]) level]; + + if (level == NSFloatingWindowLevel + || level == NSStatusWindowLevel + || level == NSModalPanelWindowLevel) + return true; + } + + return false; +} + //============================================================================== Image juce_createIconForFile (const File& file) { diff --git a/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp b/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp index 4045e4b2e9..66c2a29f47 100644 --- a/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp +++ b/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp @@ -23,21 +23,10 @@ ============================================================================== */ +extern bool juce_areThereAnyAlwaysOnTopWindows(); + namespace FileChooserHelpers { - static bool areThereAnyAlwaysOnTopWindows() - { - for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) - { - Component* const c = Desktop::getInstance().getComponent (i); - - if (c != nullptr && c->isAlwaysOnTop() && c->isShowing()) - return true; - } - - return false; - } - struct FileChooserCallbackInfo { String initialPath; @@ -162,7 +151,7 @@ void FileChooser::showPlatformDialog (Array& results, const String& title_ mainMon.getY() + mainMon.getHeight() / 4, 0, 0); parentWindow.setOpaque (true); - parentWindow.setAlwaysOnTop (areThereAnyAlwaysOnTopWindows()); + parentWindow.setAlwaysOnTop (juce_areThereAnyAlwaysOnTopWindows()); parentWindow.addToDesktop (0); if (extraInfoComponent == nullptr) diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index 38144f40be..a78f812738 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -790,10 +790,7 @@ public: void toBehind (ComponentPeer* other) { - HWNDComponentPeer* const otherPeer = dynamic_cast (other); - jassert (otherPeer != nullptr); // wrong type of window? - - if (otherPeer != nullptr) + if (HWNDComponentPeer* const otherPeer = dynamic_cast (other)) { setMinimised (false); @@ -804,6 +801,10 @@ public: else if (otherPeer->getComponent().isAlwaysOnTop()) SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); } + else + { + jassertfalse; // wrong type of window? + } } bool isFocused() const @@ -2665,9 +2666,7 @@ private: void moveCandidateWindowToLeftAlignWithSelection (HIMC hImc, ComponentPeer& peer, TextInputTarget* target) const { - Component* const targetComp = dynamic_cast (target); - - if (targetComp != nullptr) + if (Component* const targetComp = dynamic_cast (target)) { const Rectangle area (peer.getComponent().getLocalArea (targetComp, target->getCaretRectangle())); @@ -2780,6 +2779,37 @@ void Process::makeForegroundProcess() // is this possible in Windows? } +//============================================================================== +static BOOL CALLBACK enumAlwaysOnTopWindows (HWND hwnd, LPARAM lParam) +{ + if (IsWindowVisible (hwnd)) + { + DWORD processID = 0; + GetWindowThreadProcessId (hwnd, &processID); + + if (processID == GetCurrentProcessId()) + { + WINDOWINFO info; + + if (GetWindowInfo (hwnd, &info) + && (info.dwExStyle & WS_EX_TOPMOST) != 0) + { + *reinterpret_cast (lParam) = true; + return FALSE; + } + } + } + + return TRUE; +} + +bool juce_areThereAnyAlwaysOnTopWindows() +{ + bool anyAlwaysOnTopFound = false; + EnumWindows (&enumAlwaysOnTopWindows, (LPARAM) &anyAlwaysOnTopFound); + return anyAlwaysOnTopFound; +} + //============================================================================== class WindowsMessageBox : public AsyncUpdater { diff --git a/modules/juce_gui_basics/windows/juce_AlertWindow.cpp b/modules/juce_gui_basics/windows/juce_AlertWindow.cpp index 15b20b42b1..8080e62d7c 100644 --- a/modules/juce_gui_basics/windows/juce_AlertWindow.cpp +++ b/modules/juce_gui_basics/windows/juce_AlertWindow.cpp @@ -32,6 +32,8 @@ static juce_wchar getDefaultPasswordChar() noexcept #endif } +extern bool juce_areThereAnyAlwaysOnTopWindows(); + //============================================================================== AlertWindow::AlertWindow (const String& title, const String& message, @@ -42,24 +44,13 @@ AlertWindow::AlertWindow (const String& title, associatedComponent (comp), escapeKeyCancels (true) { + setAlwaysOnTop (juce_areThereAnyAlwaysOnTopWindows()); + if (message.isEmpty()) text = " "; // to force an update if the message is empty setMessage (message); - Desktop& desktop = Desktop::getInstance(); - for (int i = desktop.getNumComponents(); --i >= 0;) - { - if (Component* const c = desktop.getComponent (i)) - { - if (c->isAlwaysOnTop() && c->isShowing()) - { - setAlwaysOnTop (true); - break; - } - } - } - AlertWindow::lookAndFeelChanged(); constrainer.setMinimumOnscreenAmounts (0x10000, 0x10000, 0x10000, 0x10000); }