Bug 1875369 [Linux] Get renderer again after WillPaintWindow() r=emilio

WillPaintWindow() spins event loop which can lead to any action related to nsWindow - it can be hid, shown or destroyed.
If the nsWindow visibility is changed, compositor/renderer is deleted and we need to get it again.

Differential Revision: https://phabricator.services.mozilla.com/D200272
This commit is contained in:
stransky 2024-02-13 09:15:34 +00:00
Родитель 68c3134ed5
Коммит 6eeb6c8e7f
2 изменённых файлов: 40 добавлений и 34 удалений

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

@ -3753,6 +3753,26 @@ void nsWindow::CreateCompositorVsyncDispatcher() {
} }
#endif #endif
void nsWindow::RequestRepaint(LayoutDeviceIntRegion& aRepaintRegion) {
WindowRenderer* renderer = GetWindowRenderer();
WebRenderLayerManager* layerManager = renderer->AsWebRender();
KnowsCompositor* knowsCompositor = renderer->AsKnowsCompositor();
if (knowsCompositor && layerManager && mCompositorSession) {
if (!mConfiguredClearColor && !IsPopup()) {
layerManager->WrBridge()->SendSetDefaultClearColor(LookAndFeel::Color(
LookAndFeel::ColorID::Window, PreferenceSheet::ColorSchemeForChrome(),
LookAndFeel::UseStandins::No));
mConfiguredClearColor = true;
}
// We need to paint to the screen even if nothing changed, since if we
// don't have a compositing window manager, our pixels could be stale.
layerManager->SetNeedsComposite(true);
layerManager->SendInvalidRegion(aRepaintRegion.ToUnknownRegion());
}
}
gboolean nsWindow::OnExposeEvent(cairo_t* cr) { gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
// This might destroy us. // This might destroy us.
NotifyOcclusionState(OcclusionState::VISIBLE); NotifyOcclusionState(OcclusionState::VISIBLE);
@ -3777,8 +3797,7 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
} }
#endif #endif
nsIWidgetListener* listener = GetListener(); if (!GetListener()) {
if (!listener) {
return FALSE; return FALSE;
} }
@ -3795,45 +3814,30 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
LayoutDeviceIntRegion region = exposeRegion; LayoutDeviceIntRegion region = exposeRegion;
region.ScaleRoundOut(scale, scale); region.ScaleRoundOut(scale, scale);
WindowRenderer* renderer = GetWindowRenderer(); RequestRepaint(region);
WebRenderLayerManager* layerManager = renderer->AsWebRender();
KnowsCompositor* knowsCompositor = renderer->AsKnowsCompositor();
if (knowsCompositor && layerManager && mCompositorSession) {
if (!mConfiguredClearColor && !IsPopup()) {
layerManager->WrBridge()->SendSetDefaultClearColor(LookAndFeel::Color(
LookAndFeel::ColorID::Window, PreferenceSheet::ColorSchemeForChrome(),
LookAndFeel::UseStandins::No));
mConfiguredClearColor = true;
}
// We need to paint to the screen even if nothing changed, since if we
// don't have a compositing window manager, our pixels could be stale.
layerManager->SetNeedsComposite(true);
layerManager->SendInvalidRegion(region.ToUnknownRegion());
}
RefPtr<nsWindow> strongThis(this); RefPtr<nsWindow> strongThis(this);
// Dispatch WillPaintWindow notification to allow scripts etc. to run // Dispatch WillPaintWindow notification to allow scripts etc. to run
// before we paint // before we paint. It also spins event loop which may show/hide the window
{ // so we may have new renderer etc.
listener->WillPaintWindow(this); GetListener()->WillPaintWindow(this);
// If the window has been destroyed during the will paint notification, // If the window has been destroyed during the will paint notification,
// there is nothing left to do. // there is nothing left to do.
if (!mGdkWindow) { if (!mGdkWindow || mIsDestroyed) {
return TRUE; return TRUE;
}
// Re-get the listener since the will paint notification might have
// killed it.
listener = GetListener();
if (!listener) {
return FALSE;
}
} }
// Re-get all rendering components since the will paint notification
// might have killed it.
nsIWidgetListener* listener = GetListener();
if (!listener) return FALSE;
WindowRenderer* renderer = GetWindowRenderer();
WebRenderLayerManager* layerManager = renderer->AsWebRender();
KnowsCompositor* knowsCompositor = renderer->AsKnowsCompositor();
if (knowsCompositor && layerManager && layerManager->NeedsComposite()) { if (knowsCompositor && layerManager && layerManager->NeedsComposite()) {
layerManager->ScheduleComposite(wr::RenderReasons::WIDGET); layerManager->ScheduleComposite(wr::RenderReasons::WIDGET);
layerManager->SetNeedsComposite(false); layerManager->SetNeedsComposite(false);

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

@ -986,6 +986,8 @@ class nsWindow final : public nsBaseWidget {
void EmulateResizeDrag(GdkEventMotion* aEvent); void EmulateResizeDrag(GdkEventMotion* aEvent);
void RequestRepaint(LayoutDeviceIntRegion& aRepaintRegion);
#ifdef MOZ_X11 #ifdef MOZ_X11
typedef enum {GTK_WIDGET_COMPOSIDED_DEFAULT = 0, typedef enum {GTK_WIDGET_COMPOSIDED_DEFAULT = 0,
GTK_WIDGET_COMPOSIDED_DISABLED = 1, GTK_WIDGET_COMPOSIDED_DISABLED = 1,