Browse Source

Linux: Fix sporadic positioning error after window creation

pull/22/head
attila 3 years ago
parent
commit
751c4177a4
2 changed files with 40 additions and 8 deletions
  1. +10
    -0
      modules/juce_gui_basics/components/juce_Component.cpp
  2. +30
    -8
      modules/juce_gui_basics/native/juce_linux_Windowing.cpp

+ 10
- 0
modules/juce_gui_basics/components/juce_Component.cpp View File

@@ -752,6 +752,16 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo)
peer->setConstrainer (currentConstrainer);
repaint();
#if JUCE_LINUX
// Creating the peer Image on Linux will change the reported position of the window. If
// the Image creation is interleaved with the coming configureNotifyEvents the window
// will appear in the wrong position. To avoid this, we force the Image creation here,
// before handling any of the configureNotifyEvents. The Linux implementation of
// performAnyPendingRepaintsNow() will force update the peer position if necessary.
peer->performAnyPendingRepaintsNow();
#endif
internalHierarchyChanged();
if (auto* handler = getAccessibilityHandler())


+ 30
- 8
modules/juce_gui_basics/native/juce_linux_Windowing.cpp View File

@@ -92,14 +92,8 @@ public:
}
//==============================================================================
void setBounds (const Rectangle<int>& newBounds, bool isNowFullScreen) override
void forceSetBounds (const Rectangle<int>& correctedNewBounds, bool isNowFullScreen)
{
const auto correctedNewBounds = newBounds.withSize (jmax (1, newBounds.getWidth()),
jmax (1, newBounds.getHeight()));
if (bounds == correctedNewBounds && fullScreen == isNowFullScreen)
return;
bounds = correctedNewBounds;
updateScaleFactorFromNewBounds (bounds, false);
@@ -120,6 +114,15 @@ public:
}
}
void setBounds (const Rectangle<int>& newBounds, bool isNowFullScreen) override
{
const auto correctedNewBounds = newBounds.withSize (jmax (1, newBounds.getWidth()),
jmax (1, newBounds.getHeight()));
if (bounds != correctedNewBounds || fullScreen != isNowFullScreen)
forceSetBounds (correctedNewBounds, isNowFullScreen);
}
Point<int> getScreenPosition (bool physical) const
{
auto physicalParentPosition = XWindowSystem::getInstance()->getPhysicalParentScreenPosition();
@@ -434,12 +437,31 @@ private:
if (! totalArea.isEmpty())
{
if (image.isNull() || image.getWidth() < totalArea.getWidth()
const auto wasImageNull = image.isNull();
if (wasImageNull || image.getWidth() < totalArea.getWidth()
|| image.getHeight() < totalArea.getHeight())
{
image = XWindowSystem::getInstance()->createImage (isSemiTransparentWindow,
totalArea.getWidth(), totalArea.getHeight(),
useARGBImagesForRendering);
if (wasImageNull)
{
// After calling createImage() XWindowSystem::getWindowBounds() will return
// changed coordinates that look like the result of some position
// defaulting mechanism. If we handle a configureNotifyEvent after
// createImage() and before we would issue new, valid coordinates, we will
// apply these default, unwanted coordinates to our window. To avoid that
// we immediately send another positioning message to guarantee that the
// next configureNotifyEvent will read valid values.
//
// This issue only occurs right after peer creation, when the image is
// null. Updating when only the width or height is changed would lead to
// incorrect behaviour.
peer.forceSetBounds (ScalingHelpers::scaledScreenPosToUnscaled (peer.component,
peer.component.getBoundsInParent()),
peer.isFullScreen());
}
}
startTimer (repaintTimerPeriod);


Loading…
Cancel
Save