Add remaining files
[juce-lv2.git] / juce / source / src / gui / components / windows / juce_TopLevelWindow.cpp
blob5920f0361c2cb22e1b23bfc753b4698a2ab6303b
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../../core/juce_StandardHeader.h"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_TopLevelWindow.h"
31 #include "../windows/juce_ComponentPeer.h"
32 #include "../juce_Desktop.h"
33 #include "../lookandfeel/juce_LookAndFeel.h"
34 #include "../special/juce_DropShadower.h"
35 #include "../../../threads/juce_Process.h"
36 #include "../../../core/juce_Singleton.h"
39 //==============================================================================
40 /** Keeps track of the active top level window.
42 class TopLevelWindowManager : public Timer,
43 public DeletedAtShutdown
45 public:
46 //==============================================================================
47 TopLevelWindowManager()
48 : currentActive (nullptr)
52 ~TopLevelWindowManager()
54 clearSingletonInstance();
57 juce_DeclareSingleton_SingleThreaded_Minimal (TopLevelWindowManager);
59 void timerCallback()
61 startTimer (jmin (1731, getTimerInterval() * 2));
63 TopLevelWindow* active = nullptr;
65 if (Process::isForegroundProcess())
67 active = currentActive;
69 Component* const c = Component::getCurrentlyFocusedComponent();
70 TopLevelWindow* tlw = dynamic_cast <TopLevelWindow*> (c);
72 if (tlw == nullptr && c != nullptr)
73 // (unable to use the syntax findParentComponentOfClass <TopLevelWindow> () because of a VC6 compiler bug)
74 tlw = c->findParentComponentOfClass ((TopLevelWindow*) nullptr);
76 if (tlw != nullptr)
77 active = tlw;
80 if (active != currentActive)
82 currentActive = active;
84 for (int i = windows.size(); --i >= 0;)
86 TopLevelWindow* const tlw = windows.getUnchecked (i);
87 tlw->setWindowActive (isWindowActive (tlw));
89 i = jmin (i, windows.size() - 1);
92 Desktop::getInstance().triggerFocusCallback();
96 bool addWindow (TopLevelWindow* const w)
98 windows.add (w);
99 startTimer (10);
101 return isWindowActive (w);
104 void removeWindow (TopLevelWindow* const w)
106 startTimer (10);
108 if (currentActive == w)
109 currentActive = nullptr;
111 windows.removeValue (w);
113 if (windows.size() == 0)
114 deleteInstance();
117 Array <TopLevelWindow*> windows;
119 private:
120 TopLevelWindow* currentActive;
122 bool isWindowActive (TopLevelWindow* const tlw) const
124 return (tlw == currentActive
125 || tlw->isParentOf (currentActive)
126 || tlw->hasKeyboardFocus (true))
127 && tlw->isShowing();
130 JUCE_DECLARE_NON_COPYABLE (TopLevelWindowManager);
133 juce_ImplementSingleton_SingleThreaded (TopLevelWindowManager)
135 void juce_CheckCurrentlyFocusedTopLevelWindow()
137 if (TopLevelWindowManager::getInstanceWithoutCreating() != nullptr)
138 TopLevelWindowManager::getInstanceWithoutCreating()->startTimer (20);
141 //==============================================================================
142 TopLevelWindow::TopLevelWindow (const String& name,
143 const bool addToDesktop_)
144 : Component (name),
145 useDropShadow (true),
146 useNativeTitleBar (false),
147 windowIsActive_ (false)
149 setOpaque (true);
151 if (addToDesktop_)
152 Component::addToDesktop (TopLevelWindow::getDesktopWindowStyleFlags());
153 else
154 setDropShadowEnabled (true);
156 setWantsKeyboardFocus (true);
157 setBroughtToFrontOnMouseClick (true);
158 windowIsActive_ = TopLevelWindowManager::getInstance()->addWindow (this);
161 TopLevelWindow::~TopLevelWindow()
163 shadower = nullptr;
164 TopLevelWindowManager::getInstance()->removeWindow (this);
167 //==============================================================================
168 void TopLevelWindow::focusOfChildComponentChanged (FocusChangeType)
170 if (hasKeyboardFocus (true))
171 TopLevelWindowManager::getInstance()->timerCallback();
172 else
173 TopLevelWindowManager::getInstance()->startTimer (10);
176 void TopLevelWindow::setWindowActive (const bool isNowActive)
178 if (windowIsActive_ != isNowActive)
180 windowIsActive_ = isNowActive;
181 activeWindowStatusChanged();
185 void TopLevelWindow::activeWindowStatusChanged()
189 void TopLevelWindow::visibilityChanged()
191 if (isShowing()
192 && (getPeer()->getStyleFlags() & (ComponentPeer::windowIsTemporary
193 | ComponentPeer::windowIgnoresKeyPresses)) == 0)
195 toFront (true);
199 void TopLevelWindow::parentHierarchyChanged()
201 setDropShadowEnabled (useDropShadow);
204 int TopLevelWindow::getDesktopWindowStyleFlags() const
206 int styleFlags = ComponentPeer::windowAppearsOnTaskbar;
208 if (useDropShadow)
209 styleFlags |= ComponentPeer::windowHasDropShadow;
211 if (useNativeTitleBar)
212 styleFlags |= ComponentPeer::windowHasTitleBar;
214 return styleFlags;
217 void TopLevelWindow::setDropShadowEnabled (const bool useShadow)
219 useDropShadow = useShadow;
221 if (isOnDesktop())
223 shadower = nullptr;
224 Component::addToDesktop (getDesktopWindowStyleFlags());
226 else
228 if (useShadow && isOpaque())
230 if (shadower == nullptr)
232 shadower = getLookAndFeel().createDropShadowerForComponent (this);
234 if (shadower != nullptr)
235 shadower->setOwner (this);
238 else
240 shadower = nullptr;
245 void TopLevelWindow::setUsingNativeTitleBar (const bool useNativeTitleBar_)
247 if (useNativeTitleBar != useNativeTitleBar_)
249 useNativeTitleBar = useNativeTitleBar_;
250 recreateDesktopWindow();
251 sendLookAndFeelChange();
255 void TopLevelWindow::recreateDesktopWindow()
257 if (isOnDesktop())
259 Component::addToDesktop (getDesktopWindowStyleFlags());
260 toFront (true);
264 void TopLevelWindow::addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo)
266 /* It's not recommended to change the desktop window flags directly for a TopLevelWindow,
267 because this class needs to make sure its layout corresponds with settings like whether
268 it's got a native title bar or not.
270 If you need custom flags for your window, you can override the getDesktopWindowStyleFlags()
271 method. If you do this, it's best to call the base class's getDesktopWindowStyleFlags()
272 method, then add or remove whatever flags are necessary from this value before returning it.
275 jassert ((windowStyleFlags & ~ComponentPeer::windowIsSemiTransparent)
276 == (getDesktopWindowStyleFlags() & ~ComponentPeer::windowIsSemiTransparent));
278 Component::addToDesktop (windowStyleFlags, nativeWindowToAttachTo);
280 if (windowStyleFlags != getDesktopWindowStyleFlags())
281 sendLookAndFeelChange();
284 //==============================================================================
285 void TopLevelWindow::centreAroundComponent (Component* c, const int width, const int height)
287 if (c == nullptr)
288 c = TopLevelWindow::getActiveTopLevelWindow();
290 if (c == nullptr || c->getBounds().isEmpty())
292 centreWithSize (width, height);
294 else
296 Point<int> targetCentre (c->localPointToGlobal (c->getLocalBounds().getCentre()));
297 Rectangle<int> parentArea (c->getParentMonitorArea());
299 if (getParentComponent() != nullptr)
301 targetCentre = getParentComponent()->getLocalPoint (nullptr, targetCentre);
302 parentArea = getParentComponent()->getLocalBounds();
305 parentArea.reduce (12, 12);
307 setBounds (jlimit (parentArea.getX(), jmax (parentArea.getX(), parentArea.getRight() - width), targetCentre.getX() - width / 2),
308 jlimit (parentArea.getY(), jmax (parentArea.getY(), parentArea.getBottom() - height), targetCentre.getY() - height / 2),
309 width, height);
313 //==============================================================================
314 int TopLevelWindow::getNumTopLevelWindows() noexcept
316 return TopLevelWindowManager::getInstance()->windows.size();
319 TopLevelWindow* TopLevelWindow::getTopLevelWindow (const int index) noexcept
321 return static_cast <TopLevelWindow*> (TopLevelWindowManager::getInstance()->windows [index]);
324 TopLevelWindow* TopLevelWindow::getActiveTopLevelWindow() noexcept
326 TopLevelWindow* best = nullptr;
327 int bestNumTWLParents = -1;
329 for (int i = TopLevelWindow::getNumTopLevelWindows(); --i >= 0;)
331 TopLevelWindow* const tlw = TopLevelWindow::getTopLevelWindow (i);
333 if (tlw->isActiveWindow())
335 int numTWLParents = 0;
337 const Component* c = tlw->getParentComponent();
339 while (c != nullptr)
341 if (dynamic_cast <const TopLevelWindow*> (c) != nullptr)
342 ++numTWLParents;
344 c = c->getParentComponent();
347 if (bestNumTWLParents < numTWLParents)
349 best = tlw;
350 bestNumTWLParents = numTWLParents;
355 return best;
359 END_JUCE_NAMESPACE