plugins/screencast: send frame callbacks if the window is otherwise invisible

If we don't send frame callbacks, the application might stop rendering or
throttle to single digit fps.

BUG: 464217
This commit is contained in:
Xaver Hugl 2023-01-17 16:27:58 +01:00 committed by Vlad Zahorodnii
parent 7c58f169e0
commit b89009f9e1
4 changed files with 63 additions and 3 deletions

View file

@ -18,7 +18,6 @@
#include "scene/itemrenderer.h"
#include "scene/windowitem.h"
#include "scene/workspacescene.h"
#include "window.h"
namespace KWin
{
@ -26,6 +25,7 @@ namespace KWin
WindowScreenCastSource::WindowScreenCastSource(Window *window, QObject *parent)
: ScreenCastSource(parent)
, m_window(window)
, m_offscreenRef(window)
{
connect(m_window, &Window::windowClosed, this, &ScreenCastSource::closed);
}

View file

@ -7,14 +7,14 @@
#pragma once
#include "screencastsource.h"
#include "window.h"
#include <QPointer>
#include <QTimer>
namespace KWin
{
class Window;
class WindowScreenCastSource : public ScreenCastSource
{
Q_OBJECT
@ -31,6 +31,7 @@ public:
private:
QPointer<Window> m_window;
WindowOffscreenRenderRef m_offscreenRef;
};
} // namespace KWin

View file

@ -119,6 +119,7 @@ Window::Window()
connect(Workspace::self()->applicationMenu(), &ApplicationMenu::applicationMenuEnabledChanged, this, [this] {
Q_EMIT hasApplicationMenuChanged(hasApplicationMenu());
});
connect(&m_offscreenFramecallbackTimer, &QTimer::timeout, this, &Window::maybeSendFrameCallback);
}
Window::~Window()
@ -4537,6 +4538,45 @@ bool Window::isLockScreenOverlay() const
return m_lockScreenOverlay;
}
void Window::refOffscreenRendering()
{
if (m_offscreenRenderCount == 0) {
m_offscreenFramecallbackTimer.start(1'000'000 / output()->refreshRate());
}
m_offscreenRenderCount++;
}
void Window::unrefOffscreenRendering()
{
Q_ASSERT(m_offscreenRenderCount);
m_offscreenRenderCount--;
if (m_offscreenRenderCount == 0) {
m_offscreenFramecallbackTimer.stop();
}
}
void Window::maybeSendFrameCallback()
{
if (m_surface && !m_windowItem->isVisible()) {
m_surface->frameRendered(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
// update refresh rate, it might have changed
m_offscreenFramecallbackTimer.start(1'000'000 / output()->refreshRate());
}
}
WindowOffscreenRenderRef::WindowOffscreenRenderRef(Window *window)
: m_window(window)
{
window->refOffscreenRendering();
}
WindowOffscreenRenderRef::~WindowOffscreenRenderRef()
{
if (m_window) {
m_window->unrefOffscreenRendering();
}
}
} // namespace KWin
#include "moc_window.cpp"

View file

@ -27,6 +27,7 @@
#include <QObject>
#include <QPointer>
#include <QRectF>
#include <QTimer>
#include <QUuid>
class QMouseEvent;
@ -1429,6 +1430,9 @@ public:
void setTile(Tile *tile);
void refOffscreenRendering();
void unrefOffscreenRendering();
public Q_SLOTS:
virtual void closeWindow() = 0;
@ -1913,6 +1917,8 @@ private Q_SLOTS:
void shadeUnhover();
private:
void maybeSendFrameCallback();
// when adding new data members, check also copyToDeleted()
QUuid m_internalId;
Xcb::Window m_client;
@ -2029,6 +2035,8 @@ private:
WindowRules m_rules;
quint32 m_lastUsageSerial = 0;
bool m_lockScreenOverlay = false;
uint32_t m_offscreenRenderCount = 0;
QTimer m_offscreenFramecallbackTimer;
};
/**
@ -2375,6 +2383,17 @@ inline void Window::setPendingMoveResizeMode(MoveResizeMode mode)
KWIN_EXPORT QDebug operator<<(QDebug debug, const Window *window);
class KWIN_EXPORT WindowOffscreenRenderRef
{
public:
WindowOffscreenRenderRef(Window *window);
WindowOffscreenRenderRef() = default;
~WindowOffscreenRenderRef();
private:
QPointer<Window> m_window;
};
} // namespace KWin
Q_DECLARE_METATYPE(KWin::Window *)