Bug 1849162 - Clean-up scale management a bit. r=stransky

Always pull and track the scale from the topmost window. Keep that one
always up-to-date, which makes accessing it cheaper.

Differential Revision: https://phabricator.services.mozilla.com/D186465
This commit is contained in:
Emilio Cobos Álvarez 2023-08-31 13:57:23 +00:00
Родитель eae6af8066
Коммит a59976347b
3 изменённых файлов: 47 добавлений и 71 удалений

Просмотреть файл

@ -592,7 +592,7 @@ static void fractional_scale_handle_preferred_scale(
LOGWAYLAND("%s [%p] scale: %f\n", __func__, window.get(),
wl_container->current_fractional_scale);
MOZ_DIAGNOSTIC_ASSERT(window);
window->OnScaleChanged(/* aForce = */ true);
window->OnScaleChanged(/* aNotify = */ true);
}
static const struct wp_fractional_scale_v1_listener fractional_scale_listener =
@ -827,12 +827,8 @@ double moz_container_wayland_get_fractional_scale(MozContainer* container) {
}
double moz_container_wayland_get_scale(MozContainer* container) {
double scale = moz_container_wayland_get_fractional_scale(container);
if (scale != 0.0) {
return scale;
}
nsWindow* window = moz_container_get_nsWindow(container);
return window ? window->FractionalScaleFactor() : 1;
return window ? window->FractionalScaleFactor() : 1.0;
}
void moz_container_wayland_set_commit_to_parent(MozContainer* container) {

Просмотреть файл

@ -399,7 +399,6 @@ nsWindow::nsWindow()
mCreated(false),
mHandleTouchEvent(false),
mIsDragPopup(false),
mWindowScaleFactorChanged(true),
mCompositedScreen(gdk_screen_is_composited(gdk_screen_get_default())),
mIsAccelerated(false),
mWindowShouldStartDragging(false),
@ -4034,7 +4033,7 @@ gboolean nsWindow::OnConfigureEvent(GtkWidget* aWidget,
// Don't fire configure event for scale changes, we handle that
// OnScaleChanged event. Skip that for toplevel windows only.
if (mGdkWindow && IsTopLevelWindowType()) {
if (mWindowScaleFactor != gdk_window_get_scale_factor(mGdkWindow)) {
if (mCeiledScaleFactor != gdk_window_get_scale_factor(mGdkWindow)) {
LOG(" scale factor changed to %d,return early",
gdk_window_get_scale_factor(mGdkWindow));
return FALSE;
@ -5285,30 +5284,39 @@ void nsWindow::OnCompositedChanged() {
mCompositedScreen = gdk_screen_is_composited(gdk_screen_get_default());
}
void nsWindow::OnScaleChanged(bool aForce) {
// Force scale factor recalculation
if (!mGdkWindow) {
mWindowScaleFactorChanged = true;
void nsWindow::OnScaleChanged(bool aNotify) {
if (!IsTopLevelWindowType()) {
return;
}
LOG("OnScaleChanged -> %d, frac=%f\n",
gdk_window_get_scale_factor(mGdkWindow), FractionalScaleFactor());
if (!mGdkWindow) {
return; // We'll get there again when we configure the window.
}
gint newCeiled = gdk_window_get_scale_factor(mGdkWindow);
double newFractional =
GdkIsWaylandDisplay()
? moz_container_wayland_get_fractional_scale(mContainer)
: 0.0;
LOG("OnScaleChanged %d, %f -> %d, %f\n", int(mCeiledScaleFactor),
FractionalScaleFactor(), newCeiled, newFractional);
// Gtk supply us sometimes with doubled events so stay calm in such case.
if (!aForce &&
gdk_window_get_scale_factor(mGdkWindow) == mWindowScaleFactor) {
if (mCeiledScaleFactor == newCeiled &&
mFractionalScaleFactor == newFractional) {
return;
}
mCeiledScaleFactor = newCeiled;
mFractionalScaleFactor = newFractional;
if (!aNotify) {
return;
}
// We pause compositor to avoid rendering of obsoleted remote content which
// produces flickering.
// Re-enable compositor again when remote content is updated or
// timeout happens.
// Re-enable compositor again when remote content is updated or timeout
// happens.
PauseCompositorFlickering();
// Force scale factor recalculation
mWindowScaleFactorChanged = true;
GtkAllocation allocation;
gtk_widget_get_allocation(GTK_WIDGET(mContainer), &allocation);
LayoutDeviceIntSize size = GdkRectToDevicePixels(allocation).Size();
@ -5730,6 +5738,7 @@ void nsWindow::ConfigureGdkWindow() {
LOG("nsWindow::ConfigureGdkWindow()");
EnsureGdkWindow();
OnScaleChanged(/* aNotify = */ false);
#ifdef MOZ_X11
if (GdkIsX11Display()) {
@ -8367,7 +8376,7 @@ static void scale_changed_cb(GtkWidget* widget, GParamSpec* aPSpec,
return;
}
window->OnScaleChanged(/* aForce = */ false);
window->OnScaleChanged(/* aNotify = */ true);
}
static gboolean touch_event_cb(GtkWidget* aWidget, GdkEventTouch* aEvent) {
@ -8922,57 +8931,30 @@ GtkWindow* nsWindow::GetCurrentTopmostWindow() const {
return topmostParentWindow;
}
// We're called from Renderer/Compositor thread where EGL Window size is set.
// Just return what we have and keep scale update to main thread.
gint nsWindow::GetCachedCeiledScaleFactor() const { return mWindowScaleFactor; }
gint nsWindow::GdkCeiledScaleFactor() {
MOZ_ASSERT(NS_IsMainThread());
// We depend on notify::scale-factor callback which is reliable for toplevel
// windows only, so don't use scale cache for popup windows.
if (mWindowType == WindowType::TopLevel && !mWindowScaleFactorChanged) {
return mWindowScaleFactor;
if (IsTopLevelWindowType()) {
return mCeiledScaleFactor;
}
GdkWindow* scaledGdkWindow = nullptr;
if (GdkIsWaylandDisplay()) {
// For popup windows/dialogs with parent window we need to get scale factor
// of the topmost window. Otherwise the scale factor of the popup is
// not updated during it's hidden.
if (mWindowType == WindowType::Popup || mWindowType == WindowType::Dialog) {
// Get toplevel window for scale factor:
GtkWindow* topmostParentWindow = GetCurrentTopmostWindow();
if (topmostParentWindow) {
scaledGdkWindow =
gtk_widget_get_window(GTK_WIDGET(topmostParentWindow));
} else {
NS_WARNING("Popup/Dialog has no parent.");
if (nsWindow* topmost = GetTopmostWindow()) {
return topmost->mCeiledScaleFactor;
}
}
}
// Fallback for windows which parent has been unrealized.
if (!scaledGdkWindow) {
scaledGdkWindow = mGdkWindow;
}
if (scaledGdkWindow) {
mWindowScaleFactor = gdk_window_get_scale_factor(scaledGdkWindow);
mWindowScaleFactorChanged = false;
} else {
mWindowScaleFactor = ScreenHelperGTK::GetGTKMonitorScaleFactor();
}
return mWindowScaleFactor;
return ScreenHelperGTK::GetGTKMonitorScaleFactor();
}
double nsWindow::FractionalScaleFactor() {
#ifdef MOZ_WAYLAND
if (mContainer) {
double fractional_scale =
moz_container_wayland_get_fractional_scale(mContainer);
double fractional_scale = [&] {
if (IsTopLevelWindowType()) {
return mFractionalScaleFactor;
}
if (nsWindow* topmost = GetTopmostWindow()) {
return topmost->mFractionalScaleFactor;
}
return 0.0;
}();
if (fractional_scale != 0.0) {
return fractional_scale;
}
}
#endif
return GdkCeiledScaleFactor();
}
@ -9743,8 +9725,7 @@ void nsWindow::SetEGLNativeWindowSize(
// SetEGLNativeWindowSize() may be called from Renderer/Compositor thread.
// In such case use cached scale factor.
gint scale =
NS_IsMainThread() ? GdkCeiledScaleFactor() : GetCachedCeiledScaleFactor();
gint scale = GdkCeiledScaleFactor();
LOG("nsWindow::SetEGLNativeWindowSize() %d x %d scale %d (unscaled %d x %d)",
aEGLWindowSize.width, aEGLWindowSize.height, scale,
aEGLWindowSize.width / scale, aEGLWindowSize.height / scale);

Просмотреть файл

@ -271,7 +271,7 @@ class nsWindow final : public nsBaseWidget {
void OnDPIChanged();
void OnCheckResize();
void OnCompositedChanged();
void OnScaleChanged(bool aForce);
void OnScaleChanged(bool aNotify);
void DispatchResized();
static guint32 sLastButtonPressTime;
@ -374,7 +374,6 @@ class nsWindow final : public nsBaseWidget {
// HiDPI scale conversion
gint GdkCeiledScaleFactor();
gint GetCachedCeiledScaleFactor() const;
double FractionalScaleFactor();
// To GDK
@ -475,7 +474,8 @@ class nsWindow final : public nsBaseWidget {
nsCOMPtr<nsIWidget> mParent;
PopupType mPopupHint{};
mozilla::Atomic<int, mozilla::Relaxed> mWindowScaleFactor{1};
mozilla::Atomic<int, mozilla::Relaxed> mCeiledScaleFactor{1};
double mFractionalScaleFactor = 0.0;
void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface,
nsIntRect aBoundsRect);
@ -647,7 +647,6 @@ class nsWindow final : public nsBaseWidget {
bool mHandleTouchEvent : 1;
// true if this is a drag and drop feedback popup
bool mIsDragPopup : 1;
bool mWindowScaleFactorChanged : 1;
bool mCompositedScreen : 1;
bool mIsAccelerated : 1;
bool mWindowShouldStartDragging : 1;