Browse Source

Work towards supporting a global scaling factor: Desktop::setGlobalScaleFactor().

tags/2021-05-28
jules 12 years ago
parent
commit
b91983c480
7 changed files with 127 additions and 105 deletions
  1. +50
    -51
      modules/juce_gui_basics/components/juce_Component.cpp
  2. +10
    -12
      modules/juce_gui_basics/components/juce_Desktop.cpp
  3. +12
    -4
      modules/juce_gui_basics/components/juce_Desktop.h
  4. +10
    -16
      modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.cpp
  5. +1
    -0
      modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.h
  6. +22
    -15
      modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp
  7. +22
    -7
      modules/juce_gui_basics/windows/juce_ComponentPeer.cpp

+ 50
- 51
modules/juce_gui_basics/components/juce_Component.cpp View File

@@ -196,44 +196,64 @@ struct Component::ComponentHelpers
static inline bool hitTest (Component& comp, Point<int> localPoint) static inline bool hitTest (Component& comp, Point<int> localPoint)
{ {
return isPositiveAndBelow (localPoint.x, comp.getWidth()) return isPositiveAndBelow (localPoint.x, comp.getWidth())
&& isPositiveAndBelow (localPoint.y, comp.getHeight())
&& comp.hitTest (localPoint.x, localPoint.y);
&& isPositiveAndBelow (localPoint.y, comp.getHeight())
&& comp.hitTest (localPoint.x, localPoint.y);
} }
static Point<int> convertFromParentSpace (const Component& comp, Point<int> pointInParentSpace)
template <typename PointOrRect>
static PointOrRect unscaledScreenPosToScaled (PointOrRect pos) noexcept
{ {
if (comp.affineTransform == nullptr)
return pointInParentSpace - comp.getPosition();
const float scale = Desktop::getInstance().masterScaleFactor;
return scale != 1.0f ? pos / scale : pos;
}
return pointInParentSpace.toFloat().transformedBy (comp.affineTransform->inverted()).toInt() - comp.getPosition();
template <typename PointOrRect>
static PointOrRect scaledScreenPosToUnscaled (PointOrRect pos) noexcept
{
const float scale = Desktop::getInstance().masterScaleFactor;
return scale != 1.0f ? pos * scale : pos;
} }
static Rectangle<int> convertFromParentSpace (const Component& comp, const Rectangle<int>& areaInParentSpace)
// converts an unscaled position within a peer to the local position within that peer's component
template <typename PointOrRect>
static PointOrRect rawPeerPositionToLocal (const Component& comp, PointOrRect pos) noexcept
{ {
if (comp.affineTransform == nullptr)
return areaInParentSpace - comp.getPosition();
if (comp.isTransformed())
pos = pos.transformedBy (comp.getTransform().inverted());
return unscaledScreenPosToScaled (pos);
}
// converts a position within a peer's component to the unscaled position within the peer
template <typename PointOrRect>
static PointOrRect localPositionToRawPeerPos (const Component& comp, PointOrRect pos) noexcept
{
if (comp.isTransformed())
pos = pos.transformedBy (comp.getTransform());
return areaInParentSpace.toFloat().transformedBy (comp.affineTransform->inverted()).getSmallestIntegerContainer() - comp.getPosition();
return scaledScreenPosToUnscaled (pos);
} }
static Point<int> convertToParentSpace (const Component& comp, Point<int> pointInLocalSpace)
template <typename PointOrRect>
static PointOrRect convertFromParentSpace (const Component& comp, PointOrRect pointInParentSpace)
{ {
if (comp.affineTransform == nullptr) if (comp.affineTransform == nullptr)
return pointInLocalSpace + comp.getPosition();
return pointInParentSpace - comp.getPosition();
return (pointInLocalSpace + comp.getPosition()).toFloat().transformedBy (*comp.affineTransform).toInt();
return pointInParentSpace.transformedBy (comp.affineTransform->inverted()) - comp.getPosition();
} }
static Rectangle<int> convertToParentSpace (const Component& comp, const Rectangle<int>& areaInLocalSpace)
template <typename PointOrRect>
static PointOrRect convertToParentSpace (const Component& comp, PointOrRect pointInLocalSpace)
{ {
if (comp.affineTransform == nullptr) if (comp.affineTransform == nullptr)
return areaInLocalSpace + comp.getPosition();
return pointInLocalSpace + comp.getPosition();
return (areaInLocalSpace + comp.getPosition()).transformedBy (*comp.affineTransform);
return (pointInLocalSpace + comp.getPosition()).transformedBy (*comp.affineTransform);
} }
template <typename Type>
static Type convertFromDistantParentSpace (const Component* parent, const Component& target, const Type& coordInParent)
template <typename PointOrRect>
static PointOrRect convertFromDistantParentSpace (const Component* parent, const Component& target, const PointOrRect& coordInParent)
{ {
const Component* const directParent = target.getParentComponent(); const Component* const directParent = target.getParentComponent();
jassert (directParent != nullptr); jassert (directParent != nullptr);
@@ -244,8 +264,8 @@ struct Component::ComponentHelpers
return convertFromParentSpace (target, convertFromDistantParentSpace (parent, *directParent, coordInParent)); return convertFromParentSpace (target, convertFromDistantParentSpace (parent, *directParent, coordInParent));
} }
template <typename Type>
static Type convertCoordinate (const Component* target, const Component* source, Type p)
template <typename PointOrRect>
static PointOrRect convertCoordinate (const Component* target, const Component* source, PointOrRect p)
{ {
while (source != nullptr) while (source != nullptr)
{ {
@@ -255,19 +275,8 @@ struct Component::ComponentHelpers
if (source->isParentOf (target)) if (source->isParentOf (target))
return convertFromDistantParentSpace (source, *target, p); return convertFromDistantParentSpace (source, *target, p);
if (source->isOnDesktop())
{
if (source->isTransformed())
p = p.transformedBy (source->getTransform());
p = source->getPeer()->localToGlobal (p);
source = nullptr;
}
else
{
p = convertToParentSpace (*source, p);
source = source->getParentComponent();
}
p = convertToParentSpace (*source, p);
source = source->getParentComponent();
} }
jassert (source == nullptr); jassert (source == nullptr);
@@ -276,17 +285,7 @@ struct Component::ComponentHelpers
const Component* const topLevelComp = target->getTopLevelComponent(); const Component* const topLevelComp = target->getTopLevelComponent();
if (topLevelComp->isOnDesktop())
{
p = topLevelComp->getPeer()->globalToLocal (p);
if (topLevelComp->isTransformed())
p = p.transformedBy (topLevelComp->getTransform().inverted());
}
else
{
p = convertFromParentSpace (*topLevelComp, p);
}
p = convertFromParentSpace (*topLevelComp, p);
if (topLevelComp == target) if (topLevelComp == target)
return p; return p;
@@ -1218,11 +1217,6 @@ void Component::setBoundsToFit (int x, int y, int width, int height,
} }
//============================================================================== //==============================================================================
bool Component::isTransformed() const noexcept
{
return affineTransform != nullptr;
}
void Component::setTransform (const AffineTransform& newTransform) void Component::setTransform (const AffineTransform& newTransform)
{ {
// If you pass in a transform with no inverse, the component will have no dimensions, // If you pass in a transform with no inverse, the component will have no dimensions,
@@ -1256,6 +1250,11 @@ void Component::setTransform (const AffineTransform& newTransform)
} }
} }
bool Component::isTransformed() const noexcept
{
return affineTransform != nullptr;
}
AffineTransform Component::getTransform() const AffineTransform Component::getTransform() const
{ {
return affineTransform != nullptr ? *affineTransform : AffineTransform::identity; return affineTransform != nullptr ? *affineTransform : AffineTransform::identity;
@@ -1802,8 +1801,8 @@ void Component::internalRepaintUnchecked (const Rectangle<int>& area, const bool
CHECK_MESSAGE_MANAGER_IS_LOCKED CHECK_MESSAGE_MANAGER_IS_LOCKED
if (ComponentPeer* const peer = getPeer()) if (ComponentPeer* const peer = getPeer())
peer->repaint (affineTransform != nullptr ? area.transformedBy (*affineTransform)
: area);
peer->repaint (ComponentHelpers::scaledScreenPosToUnscaled (affineTransform != nullptr ? area.transformedBy (*affineTransform)
: area));
} }
else else
{ {


+ 10
- 12
modules/juce_gui_basics/components/juce_Desktop.cpp View File

@@ -142,18 +142,6 @@ void Desktop::componentBroughtToFront (Component* const c)
} }
} }
//==============================================================================
void Desktop::addPeer (ComponentPeer* peer)
{
peers.add (peer);
}
void Desktop::removePeer (ComponentPeer* peer)
{
peers.removeFirstMatchingValue (peer);
triggerFocusCallback();
}
//============================================================================== //==============================================================================
Point<int> Desktop::getMousePosition() Point<int> Desktop::getMousePosition()
{ {
@@ -489,3 +477,13 @@ bool Desktop::isOrientationEnabled (const DisplayOrientation orientation) const
return (allowedOrientations & orientation) != 0; return (allowedOrientations & orientation) != 0;
} }
void Desktop::setGlobalScaleFactor (float newScaleFactor) noexcept
{
if (masterScaleFactor != newScaleFactor)
{
masterScaleFactor = newScaleFactor;
displays->refresh();
}
}

+ 12
- 4
modules/juce_gui_basics/components/juce_Desktop.h View File

@@ -375,7 +375,18 @@ public:
void findDisplays (float masterScale); void findDisplays (float masterScale);
}; };
const Displays& getDisplays() const noexcept { return *displays; }
const Displays& getDisplays() const noexcept { return *displays; }
//==============================================================================
/** Sets a global scale factor to be used for all desktop windows.
Setting this will also scale the monitor sizes that are returned by getDisplays().
*/
void setGlobalScaleFactor (float newScaleFactor) noexcept;
/** Returns the current global scale factor, as set by setGlobalScaleFactor().
@see setGlobalScaleFactor
*/
float getGlobalScaleFactor() const noexcept { return masterScaleFactor; }
//============================================================================== //==============================================================================
/** True if the OS supports semitransparent windows */ /** True if the OS supports semitransparent windows */
@@ -401,9 +412,6 @@ private:
Array <Component*> desktopComponents; Array <Component*> desktopComponents;
Array <ComponentPeer*> peers; Array <ComponentPeer*> peers;
void addPeer (ComponentPeer*);
void removePeer (ComponentPeer*);
ScopedPointer<Displays> displays; ScopedPointer<Displays> displays;
Point<int> lastFakeMouseMove; Point<int> lastFakeMouseMove;


+ 10
- 16
modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.cpp View File

@@ -123,18 +123,8 @@ bool FileChooserDialogBox::show (int w, int h)
bool FileChooserDialogBox::showAt (int x, int y, int w, int h) bool FileChooserDialogBox::showAt (int x, int y, int w, int h)
{ {
if (w <= 0)
{
Component* const previewComp = content->chooserComponent.getPreviewComponent();
if (previewComp != nullptr)
w = 400 + previewComp->getWidth();
else
w = 600;
}
if (h <= 0)
h = 500;
if (w <= 0) w = getDefaultWidth();
if (h <= 0) h = 500;
if (x < 0 || y < 0) if (x < 0 || y < 0)
centreWithSize (w, h); centreWithSize (w, h);
@@ -149,11 +139,15 @@ bool FileChooserDialogBox::showAt (int x, int y, int w, int h)
void FileChooserDialogBox::centreWithDefaultSize (Component* componentToCentreAround) void FileChooserDialogBox::centreWithDefaultSize (Component* componentToCentreAround)
{ {
Component* const previewComp = content->chooserComponent.getPreviewComponent();
centreAroundComponent (componentToCentreAround, getDefaultWidth(), 500);
}
int FileChooserDialogBox::getDefaultWidth() const
{
if (Component* const previewComp = content->chooserComponent.getPreviewComponent())
return 400 + previewComp->getWidth();
centreAroundComponent (componentToCentreAround,
previewComp != nullptr ? 400 + previewComp->getWidth() : 600,
500);
return 600;
} }
//============================================================================== //==============================================================================


+ 1
- 0
modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.h View File

@@ -146,6 +146,7 @@ private:
void fileClicked (const File&, const MouseEvent&) override; void fileClicked (const File&, const MouseEvent&) override;
void fileDoubleClicked (const File&) override; void fileDoubleClicked (const File&) override;
void browserRootChanged (const File&) override; void browserRootChanged (const File&) override;
int getDefaultWidth() const;
void okButtonPressed(); void okButtonPressed();
void createNewFolder(); void createNewFolder();


+ 22
- 15
modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp View File

@@ -57,12 +57,18 @@ public:
return lastPeer; return lastPeer;
} }
static Point<int> screenPosToLocalPos (Component& comp, Point<int> pos)
{
return comp.getLocalPoint (nullptr, Component::ComponentHelpers::unscaledScreenPosToScaled (pos));
}
Component* findComponentAt (Point<int> screenPos) Component* findComponentAt (Point<int> screenPos)
{ {
if (ComponentPeer* const peer = getPeer()) if (ComponentPeer* const peer = getPeer())
{ {
Component& comp = peer->getComponent(); Component& comp = peer->getComponent();
const Point<int> relativePos (comp.getLocalPoint (nullptr, screenPos));
Point<int> relativePos (Component::ComponentHelpers::convertFromParentSpace (comp,
Component::ComponentHelpers::unscaledScreenPosToScaled (screenPos)));
// (the contains() call is needed to test for overlapping desktop windows) // (the contains() call is needed to test for overlapping desktop windows)
if (comp.contains (relativePos)) if (comp.contains (relativePos))
@@ -76,20 +82,21 @@ public:
{ {
// This needs to return the live position if possible, but it mustn't update the lastScreenPos // This needs to return the live position if possible, but it mustn't update the lastScreenPos
// value, because that can cause continuity problems. // value, because that can cause continuity problems.
return unboundedMouseOffset + (isMouseDevice ? MouseInputSource::getCurrentRawMousePosition()
: lastScreenPos);
return Component::ComponentHelpers::unscaledScreenPosToScaled
(unboundedMouseOffset + (isMouseDevice ? MouseInputSource::getCurrentRawMousePosition()
: lastScreenPos));
} }
void setScreenPosition (Point<int> p) void setScreenPosition (Point<int> p)
{ {
MouseInputSource::setRawMousePosition (p);
MouseInputSource::setRawMousePosition (Component::ComponentHelpers::scaledScreenPosToUnscaled (p));
} }
//============================================================================== //==============================================================================
#if JUCE_DUMP_MOUSE_EVENTS #if JUCE_DUMP_MOUSE_EVENTS
#define JUCE_MOUSE_EVENT_DBG(desc) DBG ("Mouse " desc << " #" << source.getIndex() \ #define JUCE_MOUSE_EVENT_DBG(desc) DBG ("Mouse " desc << " #" << source.getIndex() \
<< ": " << comp->getLocalPoint (nullptr, screenPos).toString() \
<< " - Comp: " << String::toHexString ((int) comp));
<< ": " << screenPosToLocalPos (comp, screenPos).toString() \
<< " - Comp: " << String::toHexString ((int) &comp));
#else #else
#define JUCE_MOUSE_EVENT_DBG(desc) #define JUCE_MOUSE_EVENT_DBG(desc)
#endif #endif
@@ -97,49 +104,49 @@ public:
void sendMouseEnter (Component& comp, Point<int> screenPos, Time time) void sendMouseEnter (Component& comp, Point<int> screenPos, Time time)
{ {
JUCE_MOUSE_EVENT_DBG ("enter") JUCE_MOUSE_EVENT_DBG ("enter")
comp.internalMouseEnter (source, comp.getLocalPoint (nullptr, screenPos), time);
comp.internalMouseEnter (source, screenPosToLocalPos (comp, screenPos), time);
} }
void sendMouseExit (Component& comp, Point<int> screenPos, Time time) void sendMouseExit (Component& comp, Point<int> screenPos, Time time)
{ {
JUCE_MOUSE_EVENT_DBG ("exit") JUCE_MOUSE_EVENT_DBG ("exit")
comp.internalMouseExit (source, comp.getLocalPoint (nullptr, screenPos), time);
comp.internalMouseExit (source, screenPosToLocalPos (comp, screenPos), time);
} }
void sendMouseMove (Component& comp, Point<int> screenPos, Time time) void sendMouseMove (Component& comp, Point<int> screenPos, Time time)
{ {
JUCE_MOUSE_EVENT_DBG ("move") JUCE_MOUSE_EVENT_DBG ("move")
comp.internalMouseMove (source, comp.getLocalPoint (nullptr, screenPos), time);
comp.internalMouseMove (source, screenPosToLocalPos (comp, screenPos), time);
} }
void sendMouseDown (Component& comp, Point<int> screenPos, Time time) void sendMouseDown (Component& comp, Point<int> screenPos, Time time)
{ {
JUCE_MOUSE_EVENT_DBG ("down") JUCE_MOUSE_EVENT_DBG ("down")
comp.internalMouseDown (source, comp.getLocalPoint (nullptr, screenPos), time);
comp.internalMouseDown (source, screenPosToLocalPos (comp, screenPos), time);
} }
void sendMouseDrag (Component& comp, Point<int> screenPos, Time time) void sendMouseDrag (Component& comp, Point<int> screenPos, Time time)
{ {
JUCE_MOUSE_EVENT_DBG ("drag") JUCE_MOUSE_EVENT_DBG ("drag")
comp.internalMouseDrag (source, comp.getLocalPoint (nullptr, screenPos), time);
comp.internalMouseDrag (source, screenPosToLocalPos (comp, screenPos), time);
} }
void sendMouseUp (Component& comp, Point<int> screenPos, Time time, const ModifierKeys oldMods) void sendMouseUp (Component& comp, Point<int> screenPos, Time time, const ModifierKeys oldMods)
{ {
JUCE_MOUSE_EVENT_DBG ("up") JUCE_MOUSE_EVENT_DBG ("up")
comp.internalMouseUp (source, comp.getLocalPoint (nullptr, screenPos), time, oldMods);
comp.internalMouseUp (source, screenPosToLocalPos (comp, screenPos), time, oldMods);
} }
void sendMouseWheel (Component& comp, Point<int> screenPos, Time time, const MouseWheelDetails& wheel) void sendMouseWheel (Component& comp, Point<int> screenPos, Time time, const MouseWheelDetails& wheel)
{ {
JUCE_MOUSE_EVENT_DBG ("wheel") JUCE_MOUSE_EVENT_DBG ("wheel")
comp.internalMouseWheel (source, comp.getLocalPoint (nullptr, screenPos), time, wheel);
comp.internalMouseWheel (source, screenPosToLocalPos (comp, screenPos), time, wheel);
} }
void sendMagnifyGesture (Component& comp, Point<int> screenPos, Time time, const float amount) void sendMagnifyGesture (Component& comp, Point<int> screenPos, Time time, const float amount)
{ {
JUCE_MOUSE_EVENT_DBG ("magnify") JUCE_MOUSE_EVENT_DBG ("magnify")
comp.internalMagnifyGesture (source, comp.getLocalPoint (nullptr, screenPos), time, amount);
comp.internalMagnifyGesture (source, screenPosToLocalPos (comp, screenPos), time, amount);
} }
//============================================================================== //==============================================================================
@@ -330,7 +337,7 @@ public:
//============================================================================== //==============================================================================
Time getLastMouseDownTime() const noexcept { return mouseDowns[0].time; } Time getLastMouseDownTime() const noexcept { return mouseDowns[0].time; }
Point<int> getLastMouseDownPosition() const noexcept { return mouseDowns[0].position; }
Point<int> getLastMouseDownPosition() const noexcept { return Component::ComponentHelpers::unscaledScreenPosToScaled (mouseDowns[0].position); }
int getNumberOfMultipleClicks() const noexcept int getNumberOfMultipleClicks() const noexcept
{ {


+ 22
- 7
modules/juce_gui_basics/windows/juce_ComponentPeer.cpp View File

@@ -33,12 +33,14 @@ ComponentPeer::ComponentPeer (Component& comp, const int flags)
uniqueID (lastUniqueID += 2), // increment by 2 so that this can never hit 0 uniqueID (lastUniqueID += 2), // increment by 2 so that this can never hit 0
isWindowMinimised (false) isWindowMinimised (false)
{ {
Desktop::getInstance().addPeer (this);
Desktop::getInstance().peers.add (this);
} }
ComponentPeer::~ComponentPeer() ComponentPeer::~ComponentPeer()
{ {
Desktop::getInstance().removePeer (this);
Desktop& desktop = Desktop::getInstance();
desktop.peers.removeFirstMatchingValue (this);
desktop.triggerFocusCallback();
} }
//============================================================================== //==============================================================================
@@ -74,7 +76,7 @@ bool ComponentPeer::isValidPeer (const ComponentPeer* const peer) noexcept
void ComponentPeer::updateBounds() void ComponentPeer::updateBounds()
{ {
setBounds (component.getBoundsInParent(), false);
setBounds (Component::ComponentHelpers::scaledScreenPosToUnscaled (component.getBoundsInParent()), false);
} }
//============================================================================== //==============================================================================
@@ -105,7 +107,14 @@ void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo)
ModifierKeys::updateCurrentModifiers(); ModifierKeys::updateCurrentModifiers();
Graphics g (&contextToPaintTo); Graphics g (&contextToPaintTo);
g.addTransform (component.getTransform());
if (component.isTransformed())
g.addTransform (component.getTransform());
float masterScale = Desktop::getInstance().masterScaleFactor;
if (masterScale != 1.0f)
g.addTransform (AffineTransform::scale (masterScale));
#if JUCE_ENABLE_REPAINT_DEBUGGING #if JUCE_ENABLE_REPAINT_DEBUGGING
g.saveState(); g.saveState();
@@ -284,12 +293,18 @@ void ComponentPeer::handleMovedOrResized()
{ {
const WeakReference<Component> deletionChecker (&component); const WeakReference<Component> deletionChecker (&component);
const Rectangle<int> newBounds (getBounds().transformedBy (component.getTransform().inverted()));
const bool wasMoved = (component.getPosition() != newBounds.getPosition());
const bool wasResized = (component.getWidth() != newBounds.getWidth() || component.getHeight() != newBounds.getHeight());
Rectangle<int> newBounds (getBounds());
Rectangle<int> oldBounds (component.getBounds());
oldBounds = Component::ComponentHelpers::localPositionToRawPeerPos (component, oldBounds);
const bool wasMoved = (oldBounds.getPosition() != newBounds.getPosition());
const bool wasResized = (oldBounds.getWidth() != newBounds.getWidth() || oldBounds.getHeight() != newBounds.getHeight());
if (wasMoved || wasResized) if (wasMoved || wasResized)
{ {
newBounds = Component::ComponentHelpers::rawPeerPositionToLocal (component, newBounds);
component.bounds = newBounds; component.bounds = newBounds;
if (wasResized) if (wasResized)


Loading…
Cancel
Save