Fix rendering so that moving the cursor doesn't cause the whole screen to rerender
This commit is contained in:
parent
638105667e
commit
205c80445a
|
|
@ -67,4 +67,6 @@ target_link_libraries(breezy_desktop
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/breezy_desktop)
|
install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/breezy_desktop)
|
||||||
|
install(FILES qml/cursorOverlay.frag DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/breezy_desktop/qml)
|
||||||
|
install(FILES qml/cursorOverlay.vert DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/breezy_desktop/qml)
|
||||||
|
|
@ -540,6 +540,11 @@ QString BreezyDesktopEffect::cursorImageSource() const
|
||||||
return m_cursorImageSource;
|
return m_cursorImageSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize BreezyDesktopEffect::cursorImageSize() const
|
||||||
|
{
|
||||||
|
return m_cursorImageSize;
|
||||||
|
}
|
||||||
|
|
||||||
QPointF BreezyDesktopEffect::cursorPos() const
|
QPointF BreezyDesktopEffect::cursorPos() const
|
||||||
{
|
{
|
||||||
return m_cursorPos;
|
return m_cursorPos;
|
||||||
|
|
@ -566,10 +571,12 @@ void BreezyDesktopEffect::updateCursorImage()
|
||||||
cursor.image().save(&buffer, "PNG");
|
cursor.image().save(&buffer, "PNG");
|
||||||
|
|
||||||
m_cursorImageSource = QStringLiteral("data:image/png;base64,%1").arg(QString::fromLatin1(data.toBase64()));
|
m_cursorImageSource = QStringLiteral("data:image/png;base64,%1").arg(QString::fromLatin1(data.toBase64()));
|
||||||
|
m_cursorImageSize = cursor.image().size();
|
||||||
} else {
|
} else {
|
||||||
m_cursorImageSource = QString();
|
m_cursorImageSource = QString();
|
||||||
|
m_cursorImageSize = QSize();
|
||||||
}
|
}
|
||||||
Q_EMIT cursorImageChanged();
|
Q_EMIT cursorImageSourceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreezyDesktopEffect::updateCursorPos()
|
void BreezyDesktopEffect::updateCursorPos()
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,12 @@ namespace KWin
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool isEnabled READ isEnabled NOTIFY enabledStateChanged)
|
Q_PROPERTY(bool isEnabled READ isEnabled NOTIFY enabledStateChanged)
|
||||||
Q_PROPERTY(bool zoomOnFocusEnabled READ isZoomOnFocusEnabled WRITE setZoomOnFocusEnabled NOTIFY zoomOnFocusChanged)
|
Q_PROPERTY(bool zoomOnFocusEnabled READ isZoomOnFocusEnabled WRITE setZoomOnFocusEnabled NOTIFY zoomOnFocusChanged)
|
||||||
Q_PROPERTY(bool imuResetState READ imuResetState NOTIFY imuRotationsChanged)
|
Q_PROPERTY(bool imuResetState READ imuResetState)
|
||||||
Q_PROPERTY(QList<QQuaternion> imuRotations READ imuRotations NOTIFY imuRotationsChanged)
|
Q_PROPERTY(QList<QQuaternion> imuRotations READ imuRotations)
|
||||||
Q_PROPERTY(quint32 imuTimeElapsedMs READ imuTimeElapsedMs NOTIFY imuRotationsChanged)
|
Q_PROPERTY(quint32 imuTimeElapsedMs READ imuTimeElapsedMs)
|
||||||
Q_PROPERTY(quint64 imuTimestamp READ imuTimestamp NOTIFY imuRotationsChanged)
|
Q_PROPERTY(quint64 imuTimestamp READ imuTimestamp)
|
||||||
Q_PROPERTY(QString cursorImageSource READ cursorImageSource NOTIFY cursorImageChanged)
|
Q_PROPERTY(QString cursorImageSource READ cursorImageSource NOTIFY cursorImageSourceChanged)
|
||||||
|
Q_PROPERTY(QSize cursorImageSize READ cursorImageSize NOTIFY cursorImageSourceChanged)
|
||||||
Q_PROPERTY(QPointF cursorPos READ cursorPos NOTIFY cursorPosChanged)
|
Q_PROPERTY(QPointF cursorPos READ cursorPos NOTIFY cursorPosChanged)
|
||||||
Q_PROPERTY(QList<qreal> lookAheadConfig READ lookAheadConfig NOTIFY devicePropertiesChanged)
|
Q_PROPERTY(QList<qreal> lookAheadConfig READ lookAheadConfig NOTIFY devicePropertiesChanged)
|
||||||
Q_PROPERTY(QList<quint32> displayResolution READ displayResolution NOTIFY devicePropertiesChanged)
|
Q_PROPERTY(QList<quint32> displayResolution READ displayResolution NOTIFY devicePropertiesChanged)
|
||||||
|
|
@ -44,6 +45,7 @@ namespace KWin
|
||||||
int requestedEffectChainPosition() const override;
|
int requestedEffectChainPosition() const override;
|
||||||
|
|
||||||
QString cursorImageSource() const;
|
QString cursorImageSource() const;
|
||||||
|
QSize cursorImageSize() const;
|
||||||
QPointF cursorPos() const;
|
QPointF cursorPos() const;
|
||||||
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
|
|
@ -91,7 +93,7 @@ namespace KWin
|
||||||
void enabledStateChanged();
|
void enabledStateChanged();
|
||||||
void zoomOnFocusChanged();
|
void zoomOnFocusChanged();
|
||||||
void imuRotationsChanged();
|
void imuRotationsChanged();
|
||||||
void cursorImageChanged();
|
void cursorImageSourceChanged();
|
||||||
void cursorPosChanged();
|
void cursorPosChanged();
|
||||||
void devicePropertiesChanged();
|
void devicePropertiesChanged();
|
||||||
|
|
||||||
|
|
@ -107,6 +109,7 @@ namespace KWin
|
||||||
|
|
||||||
QTimer *m_shutdownTimer;
|
QTimer *m_shutdownTimer;
|
||||||
QString m_cursorImageSource;
|
QString m_cursorImageSource;
|
||||||
|
QSize m_cursorImageSize;
|
||||||
|
|
||||||
bool m_enabled = false;
|
bool m_enabled = false;
|
||||||
bool m_zoomOnFocusEnabled = false;
|
bool m_zoomOnFocusEnabled = false;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ Node {
|
||||||
property var screens: root.screens
|
property var screens: root.screens
|
||||||
property var fovDetails: root.fovDetails
|
property var fovDetails: root.fovDetails
|
||||||
property var monitorPlacements: root.monitorPlacements
|
property var monitorPlacements: root.monitorPlacements
|
||||||
property var imuRotations: effect.imuRotations
|
|
||||||
property int focusedMonitorIndex: -1
|
property int focusedMonitorIndex: -1
|
||||||
|
|
||||||
Displays {
|
Displays {
|
||||||
|
|
@ -29,10 +28,17 @@ Node {
|
||||||
delegate: BreezyDesktopDisplay {
|
delegate: BreezyDesktopDisplay {
|
||||||
screen: breezyDesktop.screens[index]
|
screen: breezyDesktop.screens[index]
|
||||||
monitorPlacement: breezyDesktop.monitorPlacements[index]
|
monitorPlacement: breezyDesktop.monitorPlacements[index]
|
||||||
|
|
||||||
property real monitorDistance: effect.allDisplaysDistance
|
property real monitorDistance: effect.allDisplaysDistance
|
||||||
property real targetDistance: effect.allDisplaysDistance
|
property real targetDistance: effect.allDisplaysDistance
|
||||||
property real screenRotationY: displays.radianToDegree(monitorPlacement.rotationAngleRadians.y)
|
property real screenRotationY: displays.radianToDegree(monitorPlacement.rotationAngleRadians.y)
|
||||||
property real screenRotationX: displays.radianToDegree(monitorPlacement.rotationAngleRadians.x)
|
property real screenRotationX: displays.radianToDegree(monitorPlacement.rotationAngleRadians.x)
|
||||||
|
property matrix4x4 rotationMatrix: {
|
||||||
|
const matrix = Qt.matrix4x4();
|
||||||
|
matrix.rotate(screenRotationY, Qt.vector3d(0, 1, 0));
|
||||||
|
matrix.rotate(screenRotationX, Qt.vector3d(1, 0, 0));
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
property vector3d screenScale: {
|
property vector3d screenScale: {
|
||||||
const geometry = screen.geometry;
|
const geometry = screen.geometry;
|
||||||
|
|
@ -45,19 +51,12 @@ Node {
|
||||||
eulerRotation.y: screenRotationY
|
eulerRotation.y: screenRotationY
|
||||||
eulerRotation.x: screenRotationX
|
eulerRotation.x: screenRotationX
|
||||||
position: {
|
position: {
|
||||||
// camera looks along the negative Z axis
|
const displayNwu =
|
||||||
const positionVector =
|
monitorPlacement.centerNoRotate
|
||||||
displays.nwuToEusVector(monitorPlacement.centerNoRotate)
|
.times(monitorDistance / effect.allDisplaysDistance);
|
||||||
.times(monitorDistance / effect.allDisplaysDistance);
|
|
||||||
|
|
||||||
// position vector is only translated in flat directions, without rotations applied, so apply them here
|
|
||||||
const rotationMatrix = Qt.matrix4x4();
|
|
||||||
|
|
||||||
// only one of these should ever be non-zero, since we only rotate in the direction of the "wrap" preference
|
return rotationMatrix.times(displays.nwuToEusVector(displayNwu));
|
||||||
rotationMatrix.rotate(screenRotationY, Qt.vector3d(0, 1, 0));
|
|
||||||
rotationMatrix.rotate(screenRotationX, Qt.vector3d(1, 0, 0));
|
|
||||||
|
|
||||||
return rotationMatrix.times(positionVector);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -67,12 +66,12 @@ Node {
|
||||||
repeat: true
|
repeat: true
|
||||||
running: true
|
running: true
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (breezyDesktop.imuRotations && breezyDesktop.imuRotations.length > 0) {
|
if (effect.imuRotations && effect.imuRotations.length > 0) {
|
||||||
let focusedIndex = -1;
|
let focusedIndex = -1;
|
||||||
|
|
||||||
if (effect.zoomOnFocusEnabled) {
|
if (effect.zoomOnFocusEnabled) {
|
||||||
focusedIndex = displays.findFocusedMonitor(
|
focusedIndex = displays.findFocusedMonitor(
|
||||||
displays.eusToNwuQuat(breezyDesktop.imuRotations[0]),
|
displays.eusToNwuQuat(effect.imuRotations[0]),
|
||||||
breezyDesktop.monitorPlacements.map(monitorVectors => monitorVectors.centerLook),
|
breezyDesktop.monitorPlacements.map(monitorVectors => monitorVectors.centerLook),
|
||||||
breezyDesktop.focusedMonitorIndex,
|
breezyDesktop.focusedMonitorIndex,
|
||||||
false, // TODO smooth follow
|
false, // TODO smooth follow
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,46 @@ Model {
|
||||||
required property var monitorPlacement
|
required property var monitorPlacement
|
||||||
required property int index
|
required property int index
|
||||||
|
|
||||||
|
property string cursorImageSource: effect.cursorImageSource
|
||||||
|
property size cursorImageSize: effect.cursorImageSize
|
||||||
|
property point cursorPos: effect.cursorPos
|
||||||
|
|
||||||
source: "#Rectangle"
|
source: "#Rectangle"
|
||||||
materials: [
|
materials: [
|
||||||
DefaultMaterial {
|
CustomMaterial {
|
||||||
cullMode: Material.NoCulling
|
id: customMat
|
||||||
lighting: DefaultMaterial.NoLighting
|
depthDrawMode: CustomMaterial.AlwaysDepthDraw
|
||||||
depthDrawMode: Material.AlwaysDepthDraw
|
shadingMode: CustomMaterial.Unshaded
|
||||||
diffuseMap: Texture {
|
|
||||||
sourceItem: DesktopView {
|
property real screenWidth: display.screen.geometry.width
|
||||||
screen: display.screen
|
property real screenHeight: display.screen.geometry.height
|
||||||
width: display.screen.geometry.width
|
property real cursorX: display.cursorPos.x - display.screen.geometry.x
|
||||||
height: display.screen.geometry.height
|
property real cursorY: display.cursorPos.y - display.screen.geometry.y
|
||||||
|
property real cursorW: display.cursorImageSize.width
|
||||||
|
property real cursorH: display.cursorImageSize.height
|
||||||
|
property bool showCursor: cursorX >= 0 && cursorX < screenWidth && cursorY >= 0 && cursorY < screenHeight
|
||||||
|
|
||||||
|
property TextureInput desktopTex: TextureInput {
|
||||||
|
texture: Texture {
|
||||||
|
sourceItem: DesktopView {
|
||||||
|
screen: display.screen
|
||||||
|
width: display.screen.geometry.width
|
||||||
|
height: display.screen.geometry.height
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
property TextureInput cursorTex: TextureInput {
|
||||||
|
texture: Texture {
|
||||||
|
sourceItem: Image {
|
||||||
|
source: effect.cursorImageSource
|
||||||
|
width: effect.cursorImageSize.width
|
||||||
|
height: effect.cursorImageSize.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragmentShader: "cursorOverlay.frag"
|
||||||
|
vertexShader: "cursorOverlay.vert"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,6 @@ Item {
|
||||||
|
|
||||||
required property Camera camera
|
required property Camera camera
|
||||||
|
|
||||||
property var imuRotations: effect.imuRotations
|
|
||||||
property int imuTimeElapsedMs: effect.imuTimeElapsedMs
|
|
||||||
property double imuTimestamp: effect.imuTimestamp
|
|
||||||
property var lookAheadConfig: effect.lookAheadConfig
|
|
||||||
property var displayResolution: effect.displayResolution
|
property var displayResolution: effect.displayResolution
|
||||||
property real diagonalFOV: effect.diagonalFOV
|
property real diagonalFOV: effect.diagonalFOV
|
||||||
property real lensDistanceRatio: effect.lensDistanceRatio
|
property real lensDistanceRatio: effect.lensDistanceRatio
|
||||||
|
|
@ -67,14 +63,18 @@ Item {
|
||||||
|
|
||||||
onDisplayResolutionChanged: updateFOV();
|
onDisplayResolutionChanged: updateFOV();
|
||||||
onDiagonalFOVChanged: updateFOV();
|
onDiagonalFOVChanged: updateFOV();
|
||||||
onImuRotationsChanged: {
|
|
||||||
if (root.imuRotations && root.imuRotations.length > 0) {
|
FrameAnimation {
|
||||||
updateCamera(applyLookAhead(
|
running: true
|
||||||
root.imuRotations[0],
|
onTriggered: {
|
||||||
root.imuRotations[1],
|
if (effect.imuRotations && effect.imuRotations.length > 0) {
|
||||||
root.imuTimeElapsedMs,
|
updateCamera(applyLookAhead(
|
||||||
lookAheadMS(root.imuTimestamp, root.lookAheadConfig, -1)
|
effect.imuRotations[0],
|
||||||
));
|
effect.imuRotations[1],
|
||||||
|
effect.imuTimeElapsedMs,
|
||||||
|
lookAheadMS(effect.imuTimestamp, effect.lookAheadConfig, -1)
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,18 +40,4 @@ Item {
|
||||||
visible: onThisScreen && !model.window.minimized
|
visible: onThisScreen && !model.window.minimized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
|
||||||
id: cursorImg
|
|
||||||
source: effect.cursorImageSource
|
|
||||||
cache: false
|
|
||||||
visible: true // TODO - cursor position bounds check?
|
|
||||||
x: effect.cursorPos.x - desktopView.screen.geometry.x
|
|
||||||
y: effect.cursorPos.y - desktopView.screen.geometry.y
|
|
||||||
z: 9999 // ensure on top
|
|
||||||
anchors.centerIn: undefined
|
|
||||||
|
|
||||||
layer.enabled: true
|
|
||||||
layer.smooth: true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: singleDesktopView
|
||||||
|
property point cursorPos: effect.cursorPos
|
||||||
|
|
||||||
|
function cursorInBounds() {
|
||||||
|
const x = cursorPos.x
|
||||||
|
const y = cursorPos.y
|
||||||
|
const screenGeom = targetScreen.geometry
|
||||||
|
return x >= screenGeom.x &&
|
||||||
|
x < screenGeom.x + screenGeom.width &&
|
||||||
|
y >= screenGeom.y &&
|
||||||
|
y < screenGeom.y + screenGeom.height
|
||||||
|
}
|
||||||
|
|
||||||
|
DesktopView {
|
||||||
|
screen: targetScreen
|
||||||
|
width: targetScreen.geometry.width
|
||||||
|
height: targetScreen.geometry.height
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: cursorImg
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
z: 9999 // ensure on top
|
||||||
|
}
|
||||||
|
|
||||||
|
onCursorPosChanged: {
|
||||||
|
if (singleDesktopView.cursorInBounds()) {
|
||||||
|
const newX = effect.cursorPos.x - targetScreen.geometry.x
|
||||||
|
const newY = effect.cursorPos.y - targetScreen.geometry.y
|
||||||
|
const newSrc = effect.cursorImageSource
|
||||||
|
if (cursorImg.x !== newX) cursorImg.x = newX
|
||||||
|
if (cursorImg.y !== newY) cursorImg.y = newY
|
||||||
|
if (cursorImg.source !== newSrc) cursorImg.source = newSrc
|
||||||
|
if (!cursorImg.visible) cursorImg.visible = true
|
||||||
|
} else if (cursorImg.visible) {
|
||||||
|
cursorImg.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
VARYING vec3 pos;
|
||||||
|
VARYING vec2 texcoord;
|
||||||
|
|
||||||
|
void MAIN() {
|
||||||
|
vec2 tex = vec2(texcoord.x, 1.0 - texcoord.y);
|
||||||
|
vec4 color = texture(desktopTex, tex);
|
||||||
|
if (showCursor) {
|
||||||
|
vec2 fragCoord = tex * vec2(screenWidth, screenHeight);
|
||||||
|
vec2 cursorTopLeft = vec2(cursorX, cursorY);
|
||||||
|
vec2 cursorBottomRight = cursorTopLeft + vec2(cursorW, cursorH);
|
||||||
|
if (fragCoord.x >= cursorTopLeft.x && fragCoord.x < cursorBottomRight.x && fragCoord.y >= cursorTopLeft.y && fragCoord.y < cursorBottomRight.y) {
|
||||||
|
vec2 rel = (fragCoord - cursorTopLeft) / vec2(cursorW, cursorH);
|
||||||
|
vec4 cursorCol = texture(cursorTex, rel);
|
||||||
|
color = mix(color, cursorCol, cursorCol.a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FRAGCOLOR = color;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
VARYING vec3 pos;
|
||||||
|
VARYING vec2 texcoord;
|
||||||
|
|
||||||
|
// this is a no-op vertex shader, CustomMaterial required one
|
||||||
|
void MAIN()
|
||||||
|
{
|
||||||
|
pos = VERTEX;
|
||||||
|
texcoord = UV0;
|
||||||
|
POSITION = MODELVIEWPROJECTION_MATRIX * vec4(pos, 1.0);
|
||||||
|
}
|
||||||
|
|
@ -89,11 +89,7 @@ Item {
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: desktopViewComponent
|
id: desktopViewComponent
|
||||||
DesktopView {
|
SingleDesktopView {}
|
||||||
screen: root.targetScreen
|
|
||||||
width: root.targetScreen.geometry.width
|
|
||||||
height: root.targetScreen.geometry.height
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue