make software cursors work per output
This commit is contained in:
parent
8a2f64fbe1
commit
6a99bfd2f4
34 changed files with 165 additions and 388 deletions
|
@ -1736,27 +1736,27 @@ void PointerInputTest::testMoveCursor()
|
|||
|
||||
void PointerInputTest::testHideShowCursor()
|
||||
{
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), false);
|
||||
kwinApp()->platform()->hideCursor();
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), true);
|
||||
kwinApp()->platform()->showCursor();
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), false);
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), false);
|
||||
Cursors::self()->hideCursor();
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), true);
|
||||
Cursors::self()->showCursor();
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), false);
|
||||
|
||||
kwinApp()->platform()->hideCursor();
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), true);
|
||||
kwinApp()->platform()->hideCursor();
|
||||
kwinApp()->platform()->hideCursor();
|
||||
kwinApp()->platform()->hideCursor();
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), true);
|
||||
Cursors::self()->hideCursor();
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), true);
|
||||
Cursors::self()->hideCursor();
|
||||
Cursors::self()->hideCursor();
|
||||
Cursors::self()->hideCursor();
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), true);
|
||||
|
||||
kwinApp()->platform()->showCursor();
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), true);
|
||||
kwinApp()->platform()->showCursor();
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), true);
|
||||
kwinApp()->platform()->showCursor();
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), true);
|
||||
kwinApp()->platform()->showCursor();
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), false);
|
||||
Cursors::self()->showCursor();
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), true);
|
||||
Cursors::self()->showCursor();
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), true);
|
||||
Cursors::self()->showCursor();
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), true);
|
||||
Cursors::self()->showCursor();
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), false);
|
||||
}
|
||||
|
||||
void PointerInputTest::testDefaultInputRegion()
|
||||
|
|
|
@ -122,26 +122,26 @@ AbstractClient *TouchInputTest::showWindow(bool decorated)
|
|||
|
||||
void TouchInputTest::testTouchHidesCursor()
|
||||
{
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), false);
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), false);
|
||||
quint32 timestamp = 1;
|
||||
kwinApp()->platform()->touchDown(1, QPointF(125, 125), timestamp++);
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), true);
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), true);
|
||||
kwinApp()->platform()->touchDown(2, QPointF(130, 125), timestamp++);
|
||||
kwinApp()->platform()->touchUp(2, timestamp++);
|
||||
kwinApp()->platform()->touchUp(1, timestamp++);
|
||||
|
||||
// now a mouse event should show the cursor again
|
||||
kwinApp()->platform()->pointerMotion(QPointF(0, 0), timestamp++);
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), false);
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), false);
|
||||
|
||||
// touch should hide again
|
||||
kwinApp()->platform()->touchDown(1, QPointF(125, 125), timestamp++);
|
||||
kwinApp()->platform()->touchUp(1, timestamp++);
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), true);
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), true);
|
||||
|
||||
// wheel should also show
|
||||
kwinApp()->platform()->pointerAxisVertical(1.0, timestamp++);
|
||||
QCOMPARE(kwinApp()->platform()->isCursorHidden(), false);
|
||||
QCOMPARE(Cursors::self()->isCursorHidden(), false);
|
||||
}
|
||||
|
||||
void TouchInputTest::testMultipleTouchPoints_data()
|
||||
|
|
|
@ -166,4 +166,9 @@ std::chrono::milliseconds AbstractOutput::dimAnimationTime()
|
|||
return std::chrono::milliseconds (KSharedConfig::openConfig()->group("Effect-Kscreen").readEntry("Duration", 250));
|
||||
}
|
||||
|
||||
bool AbstractOutput::usesSoftwareCursor() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -213,6 +213,8 @@ public:
|
|||
Q_ENUM(Transform)
|
||||
virtual Transform transform() const { return Transform::Normal; }
|
||||
|
||||
virtual bool usesSoftwareCursor() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal is emitted when the geometry of this output has changed.
|
||||
|
|
|
@ -20,26 +20,6 @@ DrmAbstractOutput::DrmAbstractOutput(DrmGpu *gpu)
|
|||
{
|
||||
}
|
||||
|
||||
bool DrmAbstractOutput::showCursor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DrmAbstractOutput::hideCursor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DrmAbstractOutput::updateCursor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DrmAbstractOutput::moveCursor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
DrmGpu *DrmAbstractOutput::gpu() const
|
||||
{
|
||||
return m_gpu;
|
||||
|
|
|
@ -22,11 +22,6 @@ class DrmAbstractOutput : public AbstractWaylandOutput
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual bool showCursor();
|
||||
virtual bool hideCursor();
|
||||
virtual bool updateCursor();
|
||||
virtual bool moveCursor();
|
||||
|
||||
virtual bool present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion) = 0;
|
||||
|
||||
virtual bool needsSoftwareTransformation() const = 0;
|
||||
|
|
|
@ -158,7 +158,6 @@ void DrmBackend::reactivate()
|
|||
// While the session had been inactive, an output could have been added or
|
||||
// removed, we need to re-scan outputs.
|
||||
updateOutputs();
|
||||
updateCursor();
|
||||
Q_EMIT activeChanged();
|
||||
}
|
||||
|
||||
|
@ -210,8 +209,6 @@ bool DrmBackend::initialize()
|
|||
return false;
|
||||
}
|
||||
|
||||
initCursor();
|
||||
|
||||
// setup udevMonitor
|
||||
if (m_udevMonitor) {
|
||||
m_udevMonitor->filterSubsystemDevType("drm");
|
||||
|
@ -240,7 +237,6 @@ void DrmBackend::handleUdevEvent()
|
|||
qCDebug(KWIN_DRM) << "New gpu found:" << device->devNode();
|
||||
if (addGpu(device->devNode())) {
|
||||
updateOutputs();
|
||||
updateCursor();
|
||||
}
|
||||
} else if (device->action() == QStringLiteral("remove")) {
|
||||
DrmGpu *gpu = findGpu(device->devNum());
|
||||
|
@ -255,7 +251,6 @@ void DrmBackend::handleUdevEvent()
|
|||
m_gpus.removeOne(gpu);
|
||||
delete gpu;
|
||||
updateOutputs();
|
||||
updateCursor();
|
||||
}
|
||||
}
|
||||
} else if (device->action() == QStringLiteral("change")) {
|
||||
|
@ -266,7 +261,6 @@ void DrmBackend::handleUdevEvent()
|
|||
if (gpu) {
|
||||
qCDebug(KWIN_DRM) << "Received change event for monitored drm device" << gpu->devNode();
|
||||
updateOutputs();
|
||||
updateCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -517,85 +511,6 @@ void DrmBackend::enableOutput(DrmAbstractOutput *output, bool enable)
|
|||
}
|
||||
}
|
||||
|
||||
void DrmBackend::initCursor()
|
||||
{
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &DrmBackend::updateCursor);
|
||||
connect(Cursors::self(), &Cursors::positionChanged, this, &DrmBackend::moveCursor);
|
||||
}
|
||||
|
||||
void DrmBackend::updateCursor()
|
||||
{
|
||||
if (isSoftwareCursorForced() || isCursorHidden()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto cursor = Cursors::self()->currentCursor();
|
||||
if (cursor->image().isNull()) {
|
||||
doHideCursor();
|
||||
return;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
|
||||
for (DrmAbstractOutput *output : qAsConst(m_outputs)) {
|
||||
success = output->updateCursor();
|
||||
if (!success) {
|
||||
qCDebug(KWIN_DRM) << "Failed to update cursor on output" << output->name();
|
||||
break;
|
||||
}
|
||||
success = output->showCursor();
|
||||
if (!success) {
|
||||
qCDebug(KWIN_DRM) << "Failed to show cursor on output" << output->name();
|
||||
break;
|
||||
}
|
||||
success = output->moveCursor();
|
||||
if (!success) {
|
||||
qCDebug(KWIN_DRM) << "Failed to move cursor on output" << output->name();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setSoftwareCursor(!success);
|
||||
}
|
||||
|
||||
void DrmBackend::doShowCursor()
|
||||
{
|
||||
if (usesSoftwareCursor()) {
|
||||
return;
|
||||
}
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
void DrmBackend::doHideCursor()
|
||||
{
|
||||
if (usesSoftwareCursor()) {
|
||||
return;
|
||||
}
|
||||
for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) {
|
||||
(*it)->hideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void DrmBackend::doSetSoftwareCursor()
|
||||
{
|
||||
if (isCursorHidden() || !usesSoftwareCursor()) {
|
||||
return;
|
||||
}
|
||||
for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) {
|
||||
(*it)->hideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void DrmBackend::moveCursor()
|
||||
{
|
||||
if (isCursorHidden() || usesSoftwareCursor()) {
|
||||
return;
|
||||
}
|
||||
for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) {
|
||||
(*it)->moveCursor();
|
||||
}
|
||||
}
|
||||
|
||||
InputBackend *DrmBackend::createInputBackend()
|
||||
{
|
||||
return new LibinputBackend();
|
||||
|
@ -723,7 +638,6 @@ bool DrmBackend::applyOutputChanges(const WaylandOutputConfig &config)
|
|||
output->applyChanges(config);
|
||||
}
|
||||
};
|
||||
updateCursor();
|
||||
if (Compositor::compositing()) {
|
||||
Compositor::self()->scene()->addRepaintFull();
|
||||
}
|
||||
|
|
|
@ -76,9 +76,6 @@ Q_SIGNALS:
|
|||
void gpuAdded(DrmGpu *gpu);
|
||||
|
||||
protected:
|
||||
void doHideCursor() override;
|
||||
void doShowCursor() override;
|
||||
void doSetSoftwareCursor() override;
|
||||
bool applyOutputChanges(const WaylandOutputConfig &config) override;
|
||||
|
||||
private:
|
||||
|
@ -89,9 +86,6 @@ private:
|
|||
void reactivate();
|
||||
void deactivate();
|
||||
void updateOutputs();
|
||||
void updateCursor();
|
||||
void moveCursor();
|
||||
void initCursor();
|
||||
void readOutputsConfiguration(const QVector<DrmAbstractOutput*> &outputs);
|
||||
void handleUdevEvent();
|
||||
DrmGpu *addGpu(const QString &fileName);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "session.h"
|
||||
#include "waylandoutputconfig.h"
|
||||
#include "dumb_swapchain.h"
|
||||
#include "cursor.h"
|
||||
// Qt
|
||||
#include <QMatrix4x4>
|
||||
#include <QCryptographicHash>
|
||||
|
@ -69,6 +70,9 @@ DrmOutput::DrmOutput(DrmPipeline *pipeline)
|
|||
connect(&m_turnOffTimer, &QTimer::timeout, this, [this] {
|
||||
setDrmDpmsMode(DpmsMode::Off);
|
||||
});
|
||||
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &DrmOutput::updateCursor);
|
||||
connect(Cursors::self(), &Cursors::positionChanged, this, &DrmOutput::moveCursor);
|
||||
}
|
||||
|
||||
DrmOutput::~DrmOutput()
|
||||
|
@ -76,23 +80,6 @@ DrmOutput::~DrmOutput()
|
|||
m_pipeline->setOutput(nullptr);
|
||||
}
|
||||
|
||||
bool DrmOutput::hideCursor()
|
||||
{
|
||||
if (!isEnabled() || !m_connector->isConnected()) {
|
||||
return true;
|
||||
}
|
||||
return m_pipeline->setCursor(nullptr);
|
||||
}
|
||||
|
||||
bool DrmOutput::showCursor()
|
||||
{
|
||||
if (!isEnabled() || !m_connector->isConnected()) {
|
||||
return true;
|
||||
}
|
||||
const Cursor * const cursor = Cursors::self()->currentCursor();
|
||||
return m_pipeline->setCursor(m_cursor->currentBuffer(), logicalToNativeMatrix(cursor->rect(), scale(), transform()).map(cursor->hotspot()));
|
||||
}
|
||||
|
||||
static bool isCursorSpriteCompatible(const QImage *buffer, const QImage *sprite)
|
||||
{
|
||||
// Note that we need compare the rects in the device independent pixels because the
|
||||
|
@ -103,23 +90,24 @@ static bool isCursorSpriteCompatible(const QImage *buffer, const QImage *sprite)
|
|||
return bufferRect.contains(spriteRect);
|
||||
}
|
||||
|
||||
bool DrmOutput::updateCursor()
|
||||
void DrmOutput::updateCursor()
|
||||
{
|
||||
if (!isEnabled() || !m_connector->isConnected()) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
const Cursor *cursor = Cursors::self()->currentCursor();
|
||||
if (!cursor) {
|
||||
hideCursor();
|
||||
return true;
|
||||
m_pipeline->setCursor(nullptr);
|
||||
return;
|
||||
}
|
||||
const QImage cursorImage = cursor->image();
|
||||
if (cursorImage.isNull()) {
|
||||
hideCursor();
|
||||
return true;
|
||||
m_pipeline->setCursor(nullptr);
|
||||
return;
|
||||
}
|
||||
if (m_cursor && m_cursor->isEmpty()) {
|
||||
return false;
|
||||
m_pipeline->setCursor(nullptr);
|
||||
return;
|
||||
}
|
||||
const auto plane = m_pipeline->pending.crtc->cursorPlane();
|
||||
if (!m_cursor || (plane && !plane->formats()[m_cursor->drmFormat()].contains(DRM_FORMAT_MOD_LINEAR))) {
|
||||
|
@ -135,14 +123,13 @@ bool DrmOutput::updateCursor()
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!m_cursor || m_cursor->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
m_cursor = QSharedPointer<DumbSwapchain>::create(m_gpu, m_gpu->cursorSize(), DRM_FORMAT_XRGB8888, QImage::Format::Format_ARGB32_Premultiplied);
|
||||
if (m_cursor->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!m_cursor || m_cursor->isEmpty()) {
|
||||
m_pipeline->setCursor(nullptr);
|
||||
m_setCursorSuccessful = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_cursor->releaseBuffer(m_cursor->currentBuffer());
|
||||
|
@ -151,7 +138,9 @@ bool DrmOutput::updateCursor()
|
|||
c->setDevicePixelRatio(scale());
|
||||
if (!isCursorSpriteCompatible(c, &cursorImage)) {
|
||||
// If the cursor image is too big, fall back to rendering the software cursor.
|
||||
return false;
|
||||
m_pipeline->setCursor(nullptr);
|
||||
m_setCursorSuccessful = false;
|
||||
return;
|
||||
}
|
||||
c->fill(Qt::transparent);
|
||||
QPainter p;
|
||||
|
@ -160,18 +149,22 @@ bool DrmOutput::updateCursor()
|
|||
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
p.drawImage(QPoint(0, 0), cursorImage);
|
||||
p.end();
|
||||
return m_pipeline->setCursor(m_cursor->currentBuffer(), logicalToNativeMatrix(cursor->rect(), scale(), transform()).map(cursor->hotspot()));
|
||||
m_setCursorSuccessful = m_pipeline->setCursor(m_cursor->currentBuffer(), logicalToNativeMatrix(cursor->rect(), scale(), transform()).map(cursor->hotspot()));
|
||||
moveCursor();
|
||||
}
|
||||
|
||||
bool DrmOutput::moveCursor()
|
||||
void DrmOutput::moveCursor()
|
||||
{
|
||||
if (!isEnabled() || !m_connector->isConnected()) {
|
||||
return true;
|
||||
if (!m_setCursorSuccessful) {
|
||||
return;
|
||||
}
|
||||
Cursor *cursor = Cursors::self()->currentCursor();
|
||||
const QMatrix4x4 monitorMatrix = logicalToNativeMatrix(geometry(), scale(), transform());
|
||||
const QMatrix4x4 hotspotMatrix = logicalToNativeMatrix(cursor->rect(), scale(), transform());
|
||||
return m_pipeline->moveCursor(monitorMatrix.map(cursor->pos()) - hotspotMatrix.map(cursor->hotspot()));
|
||||
m_moveCursorSuccessful = m_pipeline->moveCursor(monitorMatrix.map(cursor->pos()) - hotspotMatrix.map(cursor->hotspot()));
|
||||
if (!m_moveCursorSuccessful) {
|
||||
m_pipeline->setCursor(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<AbstractWaylandOutput::Mode> DrmOutput::getModes() const
|
||||
|
@ -491,4 +484,9 @@ int DrmOutput::maxBpc() const
|
|||
return prop ? prop->maxValue() : 8;
|
||||
}
|
||||
|
||||
bool DrmOutput::usesSoftwareCursor() const
|
||||
{
|
||||
return !m_setCursorSuccessful || !m_moveCursorSuccessful;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,11 +43,6 @@ public:
|
|||
DrmOutput(DrmPipeline *pipeline);
|
||||
~DrmOutput() override;
|
||||
|
||||
bool showCursor() override;
|
||||
bool hideCursor() override;
|
||||
bool updateCursor() override;
|
||||
bool moveCursor() override;
|
||||
|
||||
bool present(const QSharedPointer<DrmBuffer> &buffer, QRegion damagedRegion) override;
|
||||
|
||||
DrmConnector *connector() const;
|
||||
|
@ -66,6 +61,7 @@ public:
|
|||
|
||||
void pageFlipped(std::chrono::nanoseconds timestamp);
|
||||
void presentFailed();
|
||||
bool usesSoftwareCursor() const override;
|
||||
|
||||
private:
|
||||
void initOutputDevice();
|
||||
|
@ -80,11 +76,16 @@ private:
|
|||
|
||||
int gammaRampSize() const override;
|
||||
bool setGammaRamp(const GammaRamp &gamma) override;
|
||||
void updateCursor();
|
||||
void moveCursor();
|
||||
|
||||
DrmPipeline *m_pipeline;
|
||||
DrmConnector *m_connector;
|
||||
|
||||
QSharedPointer<DumbSwapchain> m_cursor;
|
||||
bool m_setCursorSuccessful = false;
|
||||
bool m_moveCursorSuccessful = false;
|
||||
QRect m_lastCursorGeometry;
|
||||
QTimer m_turnOffTimer;
|
||||
};
|
||||
|
||||
|
|
|
@ -773,7 +773,7 @@ QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *output
|
|||
|
||||
bool EglGbmBackend::directScanoutAllowed(AbstractOutput *output) const
|
||||
{
|
||||
return !m_backend->usesSoftwareCursor() && !output->directScanoutInhibited();
|
||||
return !output->usesSoftwareCursor() && !output->directScanoutInhibited();
|
||||
}
|
||||
|
||||
bool EglGbmBackend::hasOutput(AbstractOutput *output) const
|
||||
|
|
|
@ -108,8 +108,6 @@ Session *FramebufferBackend::session() const
|
|||
|
||||
bool FramebufferBackend::initialize()
|
||||
{
|
||||
setSoftwareCursorForced(true);
|
||||
|
||||
QString framebufferDevice = deviceIdentifier();
|
||||
if (framebufferDevice.isEmpty()) {
|
||||
const auto fbs = Udev().listFramebuffers();
|
||||
|
|
|
@ -195,8 +195,6 @@ bool VirtualBackend::initialize()
|
|||
Q_EMIT outputAdded(dummyOutput);
|
||||
Q_EMIT outputEnabled(dummyOutput);
|
||||
}
|
||||
|
||||
setSoftwareCursorForced(true);
|
||||
setReady(true);
|
||||
|
||||
Q_EMIT screensQueried();
|
||||
|
|
|
@ -703,8 +703,6 @@ bool WaylandBackend::initialize()
|
|||
return;
|
||||
}
|
||||
m_waylandCursor->installImage();
|
||||
auto c = Cursors::self()->currentCursor();
|
||||
Q_EMIT c->rendered(c->geometry());
|
||||
}
|
||||
);
|
||||
connect(Cursors::self(), &Cursors::positionChanged, this,
|
||||
|
@ -1051,6 +1049,7 @@ void WaylandBackend::removeVirtualOutput(AbstractOutput *output)
|
|||
delete waylandOutput;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // KWin
|
||||
|
|
|
@ -98,4 +98,9 @@ QSize X11Output::pixelSize() const
|
|||
return geometry().size();
|
||||
}
|
||||
|
||||
bool X11Output::usesSoftwareCursor() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
void setPhysicalSize(const QSize &size);
|
||||
|
||||
QSize pixelSize() const override;
|
||||
bool usesSoftwareCursor() const override;
|
||||
|
||||
private:
|
||||
void setCrtc(xcb_randr_crtc_t crtc);
|
||||
|
|
|
@ -142,6 +142,8 @@ bool X11StandalonePlatform::initialize()
|
|||
if (Xcb::Extensions::self()->isRandrAvailable()) {
|
||||
m_randrEventFilter.reset(new XrandrEventFilter(this));
|
||||
}
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &X11StandalonePlatform::updateCursor);
|
||||
updateCursor();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -333,14 +335,13 @@ PlatformCursorImage X11StandalonePlatform::cursorImage() const
|
|||
return PlatformCursorImage(qcursorimg.copy(), QPoint(cursor->xhot, cursor->yhot));
|
||||
}
|
||||
|
||||
void X11StandalonePlatform::doHideCursor()
|
||||
void X11StandalonePlatform::updateCursor()
|
||||
{
|
||||
xcb_xfixes_hide_cursor(kwinApp()->x11Connection(), kwinApp()->x11RootWindow());
|
||||
}
|
||||
|
||||
void X11StandalonePlatform::doShowCursor()
|
||||
{
|
||||
xcb_xfixes_show_cursor(kwinApp()->x11Connection(), kwinApp()->x11RootWindow());
|
||||
if (Cursors::self()->isCursorHidden()) {
|
||||
xcb_xfixes_hide_cursor(kwinApp()->x11Connection(), kwinApp()->x11RootWindow());
|
||||
} else {
|
||||
xcb_xfixes_show_cursor(kwinApp()->x11Connection(), kwinApp()->x11RootWindow());
|
||||
}
|
||||
}
|
||||
|
||||
void X11StandalonePlatform::startInteractiveWindowSelection(std::function<void(KWin::Toplevel*)> callback, const QByteArray &cursorName)
|
||||
|
|
|
@ -68,10 +68,6 @@ public:
|
|||
Outputs outputs() const override;
|
||||
Outputs enabledOutputs() const override;
|
||||
|
||||
protected:
|
||||
void doHideCursor() override;
|
||||
void doShowCursor() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Tests whether GLX is supported and returns @c true
|
||||
|
@ -88,6 +84,7 @@ private:
|
|||
template <typename T>
|
||||
void doUpdateOutputs();
|
||||
void updateRefreshRate();
|
||||
void updateCursor();
|
||||
|
||||
Session *m_session;
|
||||
XInputIntegration *m_xinputIntegration = nullptr;
|
||||
|
|
|
@ -180,4 +180,9 @@ void X11WindowedOutput::vblank(std::chrono::nanoseconds timestamp)
|
|||
renderLoopPrivate->notifyFrameCompleted(timestamp);
|
||||
}
|
||||
|
||||
bool X11WindowedOutput::usesSoftwareCursor() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ public:
|
|||
*/
|
||||
QPointF mapFromGlobal(const QPointF &pos) const;
|
||||
|
||||
bool usesSoftwareCursor() const override;
|
||||
|
||||
private:
|
||||
void initXInputForWindow();
|
||||
void vblank(std::chrono::nanoseconds timestamp);
|
||||
|
|
|
@ -649,9 +649,6 @@ void Compositor::composite(RenderLoop *renderLoop)
|
|||
surface->frameRendered(frameTime.count());
|
||||
}
|
||||
}
|
||||
if (!kwinApp()->platform()->isCursorHidden()) {
|
||||
Cursors::self()->currentCursor()->markAsRendered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include "platform.h"
|
||||
#include "utils.h"
|
||||
#include "xcbutils.h"
|
||||
#include "abstract_output.h"
|
||||
#include "composite.h"
|
||||
#include "scene.h"
|
||||
// KDE
|
||||
#include <KConfig>
|
||||
#include <KConfigGroup>
|
||||
|
@ -60,6 +63,27 @@ void Cursors::removeCursor(Cursor* cursor)
|
|||
}
|
||||
}
|
||||
|
||||
void Cursors::hideCursor()
|
||||
{
|
||||
m_cursorHideCounter++;
|
||||
if (m_cursorHideCounter == 1) {
|
||||
Q_EMIT currentCursorChanged(m_currentCursor);
|
||||
}
|
||||
}
|
||||
|
||||
void Cursors::showCursor()
|
||||
{
|
||||
m_cursorHideCounter--;
|
||||
if (m_cursorHideCounter == 0) {
|
||||
Q_EMIT currentCursorChanged(m_currentCursor);
|
||||
}
|
||||
}
|
||||
|
||||
bool Cursors::isCursorHidden() const
|
||||
{
|
||||
return m_cursorHideCounter > 0;
|
||||
}
|
||||
|
||||
void Cursors::setCurrentCursor(Cursor* cursor)
|
||||
{
|
||||
if (m_currentCursor == cursor)
|
||||
|
@ -68,11 +92,9 @@ void Cursors::setCurrentCursor(Cursor* cursor)
|
|||
Q_ASSERT(m_cursors.contains(cursor) || !cursor);
|
||||
|
||||
if (m_currentCursor) {
|
||||
disconnect(m_currentCursor, &Cursor::rendered, this, &Cursors::currentCursorRendered);
|
||||
disconnect(m_currentCursor, &Cursor::cursorChanged, this, &Cursors::emitCurrentCursorChanged);
|
||||
}
|
||||
m_currentCursor = cursor;
|
||||
connect(m_currentCursor, &Cursor::rendered, this, &Cursors::currentCursorRendered);
|
||||
connect(m_currentCursor, &Cursor::cursorChanged, this, &Cursors::emitCurrentCursorChanged);
|
||||
|
||||
Q_EMIT currentCursorChanged(m_currentCursor);
|
||||
|
|
11
src/cursor.h
11
src/cursor.h
|
@ -166,9 +166,6 @@ public:
|
|||
QRect rect() const;
|
||||
|
||||
void updateCursor(const QImage &image, const QPoint &hotspot);
|
||||
void markAsRendered() {
|
||||
Q_EMIT rendered(geometry());
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void posChanged(const QPoint& pos);
|
||||
|
@ -186,8 +183,6 @@ Q_SIGNALS:
|
|||
void cursorChanged();
|
||||
void themeChanged();
|
||||
|
||||
void rendered(const QRect &geometry);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Performs the actual warping of the cursor.
|
||||
|
@ -275,11 +270,14 @@ public:
|
|||
return m_currentCursor;
|
||||
}
|
||||
|
||||
void hideCursor();
|
||||
void showCursor();
|
||||
bool isCursorHidden() const;
|
||||
|
||||
static Cursors* self();
|
||||
|
||||
Q_SIGNALS:
|
||||
void currentCursorChanged(Cursor* cursor);
|
||||
void currentCursorRendered(const QRect &geometry);
|
||||
void positionChanged(Cursor* cursor, const QPoint &position);
|
||||
|
||||
private:
|
||||
|
@ -290,6 +288,7 @@ private:
|
|||
Cursor* m_currentCursor = nullptr;
|
||||
Cursor* m_mouse = nullptr;
|
||||
QVector<Cursor*> m_cursors;
|
||||
int m_cursorHideCounter = 0;
|
||||
};
|
||||
|
||||
class InputConfig
|
||||
|
|
|
@ -1595,12 +1595,12 @@ PlatformCursorImage EffectsHandlerImpl::cursorImage() const
|
|||
|
||||
void EffectsHandlerImpl::hideCursor()
|
||||
{
|
||||
kwinApp()->platform()->hideCursor();
|
||||
Cursors::self()->hideCursor();
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::showCursor()
|
||||
{
|
||||
kwinApp()->platform()->showCursor();
|
||||
Cursors::self()->showCursor();
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::startInteractiveWindowSelection(std::function<void(KWin::EffectWindow*)> callback)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "main.h"
|
||||
#include "platform.h"
|
||||
#include "input_event.h"
|
||||
#include "cursor.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -49,7 +50,7 @@ void HideCursorSpy::showCursor()
|
|||
return;
|
||||
}
|
||||
m_cursorHidden = false;
|
||||
kwinApp()->platform()->showCursor();
|
||||
Cursors::self()->showCursor();
|
||||
}
|
||||
|
||||
void HideCursorSpy::hideCursor()
|
||||
|
@ -58,7 +59,7 @@ void HideCursorSpy::hideCursor()
|
|||
return;
|
||||
}
|
||||
m_cursorHidden = true;
|
||||
kwinApp()->platform()->hideCursor();
|
||||
Cursors::self()->hideCursor();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,9 +39,6 @@ Platform::Platform(QObject *parent)
|
|||
: QObject(parent)
|
||||
, m_eglDisplay(EGL_NO_DISPLAY)
|
||||
{
|
||||
setSoftwareCursorForced(false);
|
||||
connect(Cursors::self(), &Cursors::currentCursorRendered, this, &Platform::cursorRendered);
|
||||
|
||||
connect(this, &Platform::outputDisabled, this, [this] (AbstractOutput *output) {
|
||||
if (m_primaryOutput == output) {
|
||||
setPrimaryOutput(enabledOutputs().value(0, nullptr));
|
||||
|
@ -64,30 +61,6 @@ PlatformCursorImage Platform::cursorImage() const
|
|||
return PlatformCursorImage(cursor->image(), cursor->hotspot());
|
||||
}
|
||||
|
||||
void Platform::hideCursor()
|
||||
{
|
||||
m_hideCursorCounter++;
|
||||
if (m_hideCursorCounter == 1) {
|
||||
doHideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void Platform::doHideCursor()
|
||||
{
|
||||
}
|
||||
|
||||
void Platform::showCursor()
|
||||
{
|
||||
m_hideCursorCounter--;
|
||||
if (m_hideCursorCounter == 0) {
|
||||
doShowCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void Platform::doShowCursor()
|
||||
{
|
||||
}
|
||||
|
||||
InputBackend *Platform::createInputBackend()
|
||||
{
|
||||
return nullptr;
|
||||
|
@ -236,55 +209,6 @@ AbstractOutput *Platform::outputAt(const QPoint &pos) const
|
|||
return bestOutput;
|
||||
}
|
||||
|
||||
bool Platform::usesSoftwareCursor() const
|
||||
{
|
||||
return m_softwareCursor;
|
||||
}
|
||||
|
||||
void Platform::setSoftwareCursor(bool set)
|
||||
{
|
||||
if (m_softwareCursor == set) {
|
||||
return;
|
||||
}
|
||||
m_softwareCursor = set;
|
||||
doSetSoftwareCursor();
|
||||
if (m_softwareCursor) {
|
||||
connect(Cursors::self(), &Cursors::positionChanged, this, &Platform::triggerCursorRepaint);
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &Platform::triggerCursorRepaint);
|
||||
} else {
|
||||
disconnect(Cursors::self(), &Cursors::positionChanged, this, &Platform::triggerCursorRepaint);
|
||||
disconnect(Cursors::self(), &Cursors::currentCursorChanged, this, &Platform::triggerCursorRepaint);
|
||||
}
|
||||
triggerCursorRepaint();
|
||||
}
|
||||
|
||||
void Platform::doSetSoftwareCursor()
|
||||
{
|
||||
}
|
||||
|
||||
bool Platform::isSoftwareCursorForced() const
|
||||
{
|
||||
return m_softwareCursorForced;
|
||||
}
|
||||
|
||||
void Platform::setSoftwareCursorForced(bool forced)
|
||||
{
|
||||
if (qEnvironmentVariableIsSet("KWIN_FORCE_SW_CURSOR")) {
|
||||
forced = true;
|
||||
}
|
||||
if (m_softwareCursorForced == forced) {
|
||||
return;
|
||||
}
|
||||
m_softwareCursorForced = forced;
|
||||
if (m_softwareCursorForced) {
|
||||
setSoftwareCursor(true);
|
||||
} else {
|
||||
// Do not unset the software cursor yet, the platform will choose the right
|
||||
// moment when it can be done. There is still a chance that we must continue
|
||||
// using the software cursor.
|
||||
}
|
||||
}
|
||||
|
||||
void Platform::triggerCursorRepaint()
|
||||
{
|
||||
if (Compositor::compositing()) {
|
||||
|
@ -295,9 +219,7 @@ void Platform::triggerCursorRepaint()
|
|||
|
||||
void Platform::cursorRendered(const QRect &geometry)
|
||||
{
|
||||
if (m_softwareCursor) {
|
||||
m_cursor.lastRenderedGeometry = geometry;
|
||||
}
|
||||
m_cursor.lastRenderedGeometry = geometry;
|
||||
}
|
||||
|
||||
void Platform::keyboardKeyPressed(quint32 key, quint32 time)
|
||||
|
|
|
@ -219,26 +219,6 @@ public:
|
|||
*/
|
||||
virtual void setupActionForGlobalAccel(QAction *action);
|
||||
|
||||
/**
|
||||
* Returns @c true if the software cursor is being used; otherwise returns @c false.
|
||||
*/
|
||||
bool usesSoftwareCursor() const;
|
||||
|
||||
/**
|
||||
* Returns @c true if the software cursor is being forced; otherwise returns @c false.
|
||||
*
|
||||
* Note that the value returned by this function not always matches usesSoftwareCursor().
|
||||
* If this function returns @c true, then it is guaranteed that the compositor will
|
||||
* use the software cursor. However, this doesn't apply vice versa.
|
||||
*
|
||||
* If the compositor uses a software cursor, this function may return @c false. This
|
||||
* is typically the case if the current cursor image can't be displayed using hardware
|
||||
* cursors, for example due to buffer size limitations, etc.
|
||||
*
|
||||
* @see usesSoftwareCursor()
|
||||
*/
|
||||
bool isSoftwareCursorForced() const;
|
||||
|
||||
/**
|
||||
* Returns a PlatformCursorImage. By default this is created by softwareCursor and
|
||||
* softwareCursorHotspot. An implementing subclass can use this to provide a better
|
||||
|
@ -250,33 +230,6 @@ public:
|
|||
*/
|
||||
virtual PlatformCursorImage cursorImage() const;
|
||||
|
||||
/**
|
||||
* The Platform cursor image should be hidden.
|
||||
* @see showCursor
|
||||
* @see doHideCursor
|
||||
* @see isCursorHidden
|
||||
* @since 5.9
|
||||
*/
|
||||
void hideCursor();
|
||||
|
||||
/**
|
||||
* The Platform cursor image should be shown again.
|
||||
* @see hideCursor
|
||||
* @see doShowCursor
|
||||
* @see isCursorHidden
|
||||
* @since 5.9
|
||||
*/
|
||||
void showCursor();
|
||||
|
||||
/**
|
||||
* Whether the cursor is currently hidden.
|
||||
* @see showCursor
|
||||
* @see hideCursor
|
||||
* @since 5.9
|
||||
*/
|
||||
bool isCursorHidden() const {
|
||||
return m_hideCursorCounter > 0;
|
||||
}
|
||||
bool isReady() const {
|
||||
return m_ready;
|
||||
}
|
||||
|
@ -478,8 +431,6 @@ Q_SIGNALS:
|
|||
|
||||
protected:
|
||||
explicit Platform(QObject *parent = nullptr);
|
||||
void setSoftwareCursor(bool set);
|
||||
void setSoftwareCursorForced(bool forced);
|
||||
void repaint(const QRect &rect);
|
||||
void setReady(bool ready);
|
||||
void setPerScreenRenderingEnabled(bool enabled);
|
||||
|
@ -503,35 +454,8 @@ protected:
|
|||
m_supportsOutputChanges = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actual platform specific way to hide the cursor.
|
||||
* Sub-classes need to implement if they support hiding the cursor.
|
||||
*
|
||||
* This method is invoked by hideCursor if the cursor needs to be hidden.
|
||||
* The default implementation does nothing.
|
||||
*
|
||||
* @see doShowCursor
|
||||
* @see hideCursor
|
||||
* @see showCursor
|
||||
*/
|
||||
virtual void doHideCursor();
|
||||
/**
|
||||
* Actual platform specific way to show the cursor.
|
||||
* Sub-classes need to implement if they support showing the cursor.
|
||||
*
|
||||
* This method is invoked by showCursor if the cursor needs to be shown again.
|
||||
*
|
||||
* @see doShowCursor
|
||||
* @see hideCursor
|
||||
* @see showCursor
|
||||
*/
|
||||
virtual void doShowCursor();
|
||||
virtual void doSetSoftwareCursor();
|
||||
|
||||
private:
|
||||
void triggerCursorRepaint();
|
||||
bool m_softwareCursor = false;
|
||||
bool m_softwareCursorForced = false;
|
||||
struct {
|
||||
QRect lastRenderedGeometry;
|
||||
} m_cursor;
|
||||
|
@ -543,7 +467,6 @@ private:
|
|||
qreal m_initialOutputScale = 1;
|
||||
EGLDisplay m_eglDisplay;
|
||||
EGLContext m_globalShareContext = EGL_NO_CONTEXT;
|
||||
int m_hideCursorCounter = 0;
|
||||
bool m_supportsGammaControl = false;
|
||||
bool m_supportsOutputChanges = false;
|
||||
bool m_isPerScreenRenderingEnabled = false;
|
||||
|
|
|
@ -121,13 +121,13 @@ void PointerInputRedirection::init()
|
|||
InputDeviceHandler::init();
|
||||
|
||||
if (!input()->hasPointer()) {
|
||||
kwinApp()->platform()->hideCursor();
|
||||
Cursors::self()->hideCursor();
|
||||
}
|
||||
connect(input(), &InputRedirection::hasPointerChanged, this, [this]() {
|
||||
connect(input(), &InputRedirection::hasPointerChanged, this, []() {
|
||||
if (input()->hasPointer()) {
|
||||
kwinApp()->platform()->showCursor();
|
||||
Cursors::self()->showCursor();
|
||||
} else {
|
||||
kwinApp()->platform()->hideCursor();
|
||||
Cursors::self()->hideCursor();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -138,8 +138,6 @@ void PointerInputRedirection::init()
|
|||
});
|
||||
Q_EMIT m_cursor->changed();
|
||||
|
||||
connect(Cursors::self()->mouse(), &Cursor::rendered, m_cursor, &CursorImage::markAsRendered);
|
||||
|
||||
connect(screens(), &Screens::changed, this, &PointerInputRedirection::updateAfterScreenChange);
|
||||
if (waylandServer()->hasScreenLockerIntegration()) {
|
||||
connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this,
|
||||
|
|
|
@ -107,6 +107,23 @@ void Scene::initialize()
|
|||
connect(workspace(), &Workspace::geometryChanged, this, [this]() {
|
||||
setGeometry(workspace()->geometry());
|
||||
});
|
||||
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &Scene::addCursorRepaints);
|
||||
connect(Cursors::self(), &Cursors::positionChanged, this, &Scene::addCursorRepaints);
|
||||
}
|
||||
|
||||
void Scene::addCursorRepaints()
|
||||
{
|
||||
const auto outputs = kwinApp()->platform()->enabledOutputs();
|
||||
QRegion repaintRegion = Cursors::self()->currentCursor()->geometry();
|
||||
repaintRegion |= m_lastCursorGeometry;
|
||||
for (const auto &output : outputs) {
|
||||
auto intersection = repaintRegion.intersected(output->geometry());
|
||||
if (!intersection.isEmpty() && output->usesSoftwareCursor()) {
|
||||
addRepaint(intersection);
|
||||
}
|
||||
}
|
||||
m_lastCursorGeometry = Cursors::self()->currentCursor()->geometry();
|
||||
}
|
||||
|
||||
void Scene::addRepaintFull()
|
||||
|
|
|
@ -207,7 +207,7 @@ protected:
|
|||
QRegion *updateRegion, QRegion *validRegion, RenderLoop *renderLoop,
|
||||
const QMatrix4x4 &projection = QMatrix4x4());
|
||||
// Render cursor texture in case hardware cursor is disabled/non-applicable
|
||||
virtual void paintCursor(const QRegion ®ion) = 0;
|
||||
virtual void paintCursor(AbstractOutput *output, const QRegion ®ion) = 0;
|
||||
friend class EffectsHandlerImpl;
|
||||
// called after all effects had their paintScreen() called
|
||||
void finalPaintScreen(int mask, const QRegion ®ion, ScreenPaintData& data);
|
||||
|
@ -261,12 +261,15 @@ protected:
|
|||
QVector< Window* > stacking_order;
|
||||
private:
|
||||
void removeRepaints(AbstractOutput *output);
|
||||
void addCursorRepaints();
|
||||
|
||||
std::chrono::milliseconds m_expectedPresentTimestamp = std::chrono::milliseconds::zero();
|
||||
QHash< Toplevel*, Window* > m_windows;
|
||||
QMap<AbstractOutput *, QRegion> m_repaints;
|
||||
QRect m_geometry;
|
||||
// how many times finalPaintScreen() has been called
|
||||
int m_paintScreenCount = 0;
|
||||
QRect m_lastCursorGeometry;
|
||||
};
|
||||
|
||||
// The base class for windows representations in composite backends
|
||||
|
|
|
@ -151,14 +151,14 @@ void SceneOpenGL::handleGraphicsReset(GLenum status)
|
|||
* Render cursor texture in case hardware cursor is disabled.
|
||||
* Useful for screen recording apps or backends that can't do planes.
|
||||
*/
|
||||
void SceneOpenGL::paintCursor(const QRegion &rendered)
|
||||
void SceneOpenGL::paintCursor(AbstractOutput *output, const QRegion &rendered)
|
||||
{
|
||||
Cursor* cursor = Cursors::self()->currentCursor();
|
||||
|
||||
// don't paint if we use hardware cursor or the cursor is hidden
|
||||
if (!kwinApp()->platform()->usesSoftwareCursor() ||
|
||||
kwinApp()->platform()->isCursorHidden() ||
|
||||
cursor->image().isNull()) {
|
||||
if (!output || !output->usesSoftwareCursor()
|
||||
|| Cursors::self()->isCursorHidden()
|
||||
|| cursor->image().isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -316,7 +316,7 @@ void SceneOpenGL::paint(AbstractOutput *output, const QRegion &damage, const QLi
|
|||
|
||||
paintScreen(damage.intersected(geo), repaint, &update, &valid,
|
||||
renderLoop, projectionMatrix()); // call generic implementation
|
||||
paintCursor(valid);
|
||||
paintCursor(output, valid);
|
||||
|
||||
if (!GLPlatform::instance()->isGLES() && !output) {
|
||||
const QRegion displayRegion(geometry());
|
||||
|
|
|
@ -71,7 +71,7 @@ protected:
|
|||
void paintGenericScreen(int mask, const ScreenPaintData &data) override;
|
||||
Scene::Window *createWindow(Toplevel *t) override;
|
||||
void finalDrawWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data) override;
|
||||
void paintCursor(const QRegion ®ion) override;
|
||||
void paintCursor(AbstractOutput *output, const QRegion ®ion) override;
|
||||
|
||||
private:
|
||||
void doPaintBackground(const QVector< float >& vertices);
|
||||
|
|
|
@ -87,7 +87,7 @@ void SceneQPainter::paint(AbstractOutput *output, const QRegion &damage, const Q
|
|||
|
||||
QRegion updateRegion, validRegion;
|
||||
paintScreen(damage.intersected(geometry), repaint, &updateRegion, &validRegion, renderLoop);
|
||||
paintCursor(updateRegion);
|
||||
paintCursor(output, updateRegion);
|
||||
|
||||
m_painter->end();
|
||||
renderLoop->endFrame();
|
||||
|
@ -105,9 +105,9 @@ void SceneQPainter::paintBackground(const QRegion ®ion)
|
|||
}
|
||||
}
|
||||
|
||||
void SceneQPainter::paintCursor(const QRegion &rendered)
|
||||
void SceneQPainter::paintCursor(AbstractOutput *output, const QRegion &rendered)
|
||||
{
|
||||
if (!kwinApp()->platform()->usesSoftwareCursor()) {
|
||||
if (!output || output->usesSoftwareCursor() || Cursors::self()->isCursorHidden()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
protected:
|
||||
void paintBackground(const QRegion ®ion) override;
|
||||
Scene::Window *createWindow(Toplevel *toplevel) override;
|
||||
void paintCursor(const QRegion ®ion) override;
|
||||
void paintCursor(AbstractOutput *output, const QRegion ®ion) override;
|
||||
void paintOffscreenQuickView(OffscreenQuickView *w) override;
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue