1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/modules/juce_gui_basics/detail/juce_TopLevelWindowManager.h
2023-10-20 11:22:47 +01:00

136 lines
3.5 KiB
C++

/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce::detail
{
/* Keeps track of the active top level window. */
class TopLevelWindowManager : private Timer,
private DeletedAtShutdown
{
public:
TopLevelWindowManager() = default;
~TopLevelWindowManager() override
{
clearSingletonInstance();
}
JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL (TopLevelWindowManager)
static void checkCurrentlyFocusedTopLevelWindow()
{
if (auto* wm = TopLevelWindowManager::getInstanceWithoutCreating())
wm->checkFocusAsync();
}
void checkFocusAsync()
{
startTimer (10);
}
void checkFocus()
{
startTimer (jmin (1731, getTimerInterval() * 2));
auto* newActive = findCurrentlyActiveWindow();
if (newActive != currentActive)
{
currentActive = newActive;
for (int i = windows.size(); --i >= 0;)
if (auto* tlw = windows[i])
tlw->setWindowActive (isWindowActive (tlw));
Desktop::getInstance().triggerFocusCallback();
}
}
bool addWindow (TopLevelWindow* const w)
{
windows.add (w);
checkFocusAsync();
return isWindowActive (w);
}
void removeWindow (TopLevelWindow* const w)
{
checkFocusAsync();
if (currentActive == w)
currentActive = nullptr;
windows.removeFirstMatchingValue (w);
if (windows.isEmpty())
deleteInstance();
}
Array<TopLevelWindow*> windows;
private:
TopLevelWindow* currentActive = nullptr;
void timerCallback() override
{
checkFocus();
}
bool isWindowActive (TopLevelWindow* const tlw) const
{
return (tlw == currentActive
|| tlw->isParentOf (currentActive)
|| tlw->hasKeyboardFocus (true))
&& tlw->isShowing();
}
TopLevelWindow* findCurrentlyActiveWindow() const
{
if (Process::isForegroundProcess())
{
auto* focusedComp = Component::getCurrentlyFocusedComponent();
auto* w = dynamic_cast<TopLevelWindow*> (focusedComp);
if (w == nullptr && focusedComp != nullptr)
w = focusedComp->findParentComponentOfClass<TopLevelWindow>();
if (w == nullptr)
w = currentActive;
if (w != nullptr && w->isShowing())
return w;
}
return nullptr;
}
JUCE_DECLARE_NON_COPYABLE (TopLevelWindowManager)
};
JUCE_IMPLEMENT_SINGLETON (TopLevelWindowManager)
} // namespace juce::detail