30 : mouseSources (new detail::MouseInputSourceList()),
31 masterScaleFactor ((
float) getDefaultMasterScale()),
32 nativeDarkModeChangeDetectorImpl (createNativeDarkModeChangeDetectorImpl())
34 displays.reset (
new Displays (*
this));
39 setScreenSaverEnabled (
true);
40 animator.cancelAllAnimations (
false);
47 jassert (desktopComponents.size() == 0);
52 if (instance ==
nullptr)
58Desktop* Desktop::instance =
nullptr;
61int Desktop::getNumComponents() const noexcept
63 return desktopComponents.size();
66Component* Desktop::getComponent (
int index)
const noexcept
68 return desktopComponents [index];
75 for (
int i = desktopComponents.size(); --i >= 0;)
77 auto* c = desktopComponents.getUnchecked (i);
81 auto relative = c->getLocalPoint (
nullptr, screenPosition);
83 if (c->contains (relative))
84 return c->getComponentAt (relative);
94 if (
auto lf = currentLookAndFeel.get())
97 if (defaultLookAndFeel ==
nullptr)
100 auto lf = defaultLookAndFeel.get();
102 currentLookAndFeel = lf;
106void Desktop::setDefaultLookAndFeel (
LookAndFeel* newDefaultLookAndFeel)
109 currentLookAndFeel = newDefaultLookAndFeel;
111 for (
int i = getNumComponents(); --i >= 0;)
112 if (
auto* c = getComponent (i))
113 c->sendLookAndFeelChange();
117void Desktop::addDesktopComponent (
Component* c)
120 jassert (! desktopComponents.contains (c));
121 desktopComponents.addIfNotAlreadyThere (c);
124void Desktop::removeDesktopComponent (Component* c)
126 desktopComponents.removeFirstMatchingValue (c);
129void Desktop::componentBroughtToFront (Component* c)
131 auto index = desktopComponents.indexOf (c);
138 if (! c->isAlwaysOnTop())
140 newIndex = desktopComponents.size();
142 while (newIndex > 0 && desktopComponents.getUnchecked (newIndex - 1)->isAlwaysOnTop())
148 desktopComponents.move (index, newIndex);
160 return getInstance().getMainMouseSource().getScreenPosition();
165 getInstance().getMainMouseSource().setScreenPosition (newPosition.
toFloat());
170 return getInstance().getMainMouseSource().getLastMouseDownPosition().
roundToInt();
173int Desktop::getMouseButtonClickCounter() const noexcept {
return mouseClickCounter; }
174int Desktop::getMouseWheelMoveCounter() const noexcept {
return mouseWheelCounter; }
176void Desktop::incrementMouseClickCounter() noexcept { ++mouseClickCounter; }
177void Desktop::incrementMouseWheelCounter() noexcept { ++mouseWheelCounter; }
180int Desktop::getNumMouseSources() const noexcept {
return mouseSources->sources.
size(); }
181int Desktop::getNumDraggingMouseSources() const noexcept {
return mouseSources->getNumDraggingMouseSources(); }
182MouseInputSource* Desktop::getMouseSource (
int index)
const noexcept {
return mouseSources->getMouseSource (index); }
183MouseInputSource* Desktop::getDraggingMouseSource (
int index)
const noexcept {
return mouseSources->getDraggingMouseSource (index); }
185void Desktop::beginDragAutoRepeat (
int interval) { mouseSources->beginDragAutoRepeat (interval); }
190void Desktop::triggerFocusCallback() { triggerAsyncUpdate(); }
192void Desktop::updateFocusOutline()
194 if (
auto* currentFocus = Component::getCurrentlyFocusedComponent())
196 if (currentFocus->hasFocusOutline())
198 focusOutline = currentFocus->getLookAndFeel().createFocusOutlineForComponent (*currentFocus);
200 if (focusOutline !=
nullptr)
201 focusOutline->setOwner (currentFocus);
207 focusOutline =
nullptr;
210void Desktop::handleAsyncUpdate()
214 focusListeners.call ([currentFocus = WeakReference<Component> { Component::getCurrentlyFocusedComponent() }] (FocusChangeListener& l)
216 l.globalFocusChanged (currentFocus.get());
219 updateFocusOutline();
226void Desktop::darkModeChanged() { darkModeSettingListeners.call ([] (
auto& l) { l.darkModeSettingChanged(); }); }
229void Desktop::resetTimer()
231 if (mouseListeners.size() == 0)
236 lastFakeMouseMove = getMousePositionFloat();
239ListenerList<MouseListener>& Desktop::getMouseListeners()
242 return mouseListeners;
248 mouseListeners.add (listener);
255 mouseListeners.remove (listener);
259void Desktop::timerCallback()
261 if (lastFakeMouseMove != getMousePositionFloat())
265void Desktop::sendMouseMove()
267 if (! mouseListeners.isEmpty())
271 lastFakeMouseMove = getMousePositionFloat();
273 if (
auto* target = findComponentAt (lastFakeMouseMove.roundToInt()))
275 Component::BailOutChecker checker (target);
276 auto pos = target->getLocalPoint (
nullptr, lastFakeMouseMove);
277 auto now = Time::getCurrentTime();
279 const MouseEvent me (getMainMouseSource(), pos, ModifierKeys::currentModifiers, MouseInputSource::defaultPressure,
280 MouseInputSource::defaultOrientation, MouseInputSource::defaultRotation,
281 MouseInputSource::defaultTiltX, MouseInputSource::defaultTiltY,
282 target, target, now, pos, now, 0,
false);
284 if (me.mods.isAnyMouseButtonDown())
285 mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseDrag (me); });
287 mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseMove (me); });
293void Desktop::setKioskModeComponent (
Component* componentToUse,
bool allowMenusAndBars)
295 if (kioskModeReentrant)
300 if (kioskModeComponent != componentToUse)
303 jassert (kioskModeComponent ==
nullptr || ComponentPeer::getPeerFor (kioskModeComponent) !=
nullptr);
305 if (
auto* oldKioskComp = kioskModeComponent)
307 kioskModeComponent =
nullptr;
308 setKioskComponent (oldKioskComp,
false, allowMenusAndBars);
309 oldKioskComp->setBounds (kioskComponentOriginalBounds);
312 kioskModeComponent = componentToUse;
314 if (kioskModeComponent !=
nullptr)
317 jassert (ComponentPeer::getPeerFor (kioskModeComponent) !=
nullptr);
319 kioskComponentOriginalBounds = kioskModeComponent->getBounds();
320 setKioskComponent (kioskModeComponent,
true, allowMenusAndBars);
326void Desktop::setOrientationsEnabled (
int newOrientations)
328 if (allowedOrientations != newOrientations)
331 jassert (newOrientations != 0 && (newOrientations & ~allOrientations) == 0);
333 allowedOrientations = newOrientations;
334 allowedOrientationsChanged();
338int Desktop::getOrientationsEnabled() const noexcept
340 return allowedOrientations;
346 jassert (orientation == upright || orientation == upsideDown
347 || orientation == rotatedClockwise || orientation == rotatedAntiClockwise);
349 return (allowedOrientations & orientation) != 0;
352void Desktop::setGlobalScaleFactor (
float newScaleFactor)
noexcept
358 masterScaleFactor = newScaleFactor;
363bool Desktop::isHeadless() const noexcept
365 return displays->displays.isEmpty();
Holds a resizable array of primitive or copy-by-value objects.
int size() const noexcept
Returns the current number of elements in the array.
The base class for all JUCE user-interface objects.
Classes can implement this interface and register themselves with the Desktop class to receive callba...
Describes and controls aspects of the computer's desktop.
DisplayOrientation
In a tablet/mobile device which can be turned around, this is used to indicate the orientation.
Classes can implement this interface and register themselves with the Desktop class to receive callba...
The latest JUCE look-and-feel style, as introduced in 2017.
LookAndFeel objects define the appearance of all the JUCE widgets, and subclasses can be used to appl...
A MouseListener can be registered with a component to receive callbacks about mouse events that happe...
A pair of (x, y) coordinates.
constexpr Point< float > toFloat() const noexcept
Casts this point to a Point<float> object.
constexpr Point< int > roundToInt() const noexcept
Casts this point to a Point<int> object using roundToInt() to convert the values.
Helper class providing an RAII-based mechanism for temporarily setting and then re-setting a value.
#define JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
This macro is used to catch unsafe use of functions which expect to only be called on the message thr...
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.