KWin
Loading...
Searching...
No Matches
trackmouse.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
6 SPDX-FileCopyrightText: 2010 Jorge Mata <matamax123@gmail.com>
7 SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
8
9 SPDX-License-Identifier: GPL-2.0-or-later
10*/
11
12#include "trackmouse.h"
13
14// KConfigSkeleton
15#include "trackmouseconfig.h"
16
17#include <QAction>
18#include <QMatrix4x4>
19#include <QPainter>
20#include <QTime>
21
22#include "core/rendertarget.h"
23#include "core/renderviewport.h"
25#include "opengl/glutils.h"
26
27#include <KGlobalAccel>
28#include <KLocalizedString>
29
30#include <cmath>
31
32namespace KWin
33{
34
36 : m_angle(0)
37{
38 TrackMouseConfig::instance(effects->config());
40 m_angleBase = 90.0;
41 }
42 m_mousePolling = false;
43
44 m_action = new QAction(this);
45 m_action->setObjectName(QStringLiteral("TrackMouse"));
46 m_action->setText(i18n("Track mouse"));
47 KGlobalAccel::self()->setDefaultShortcut(m_action, QList<QKeySequence>());
48 KGlobalAccel::self()->setShortcut(m_action, QList<QKeySequence>());
49
50 connect(m_action, &QAction::triggered, this, &TrackMouseEffect::toggle);
51
52 connect(effects, &EffectsHandler::mouseChanged, this, &TrackMouseEffect::slotMouseChanged);
54}
55
57{
58 if (m_mousePolling) {
60 }
61}
62
63void TrackMouseEffect::reconfigure(ReconfigureFlags)
64{
65 m_modifiers = Qt::KeyboardModifiers();
66 TrackMouseConfig::self()->read();
67 if (TrackMouseConfig::shift()) {
68 m_modifiers |= Qt::ShiftModifier;
69 }
70 if (TrackMouseConfig::alt()) {
71 m_modifiers |= Qt::AltModifier;
72 }
73 if (TrackMouseConfig::control()) {
74 m_modifiers |= Qt::ControlModifier;
75 }
76 if (TrackMouseConfig::meta()) {
77 m_modifiers |= Qt::MetaModifier;
78 }
79
80 if (m_modifiers) {
81 if (!m_mousePolling) {
83 }
84 m_mousePolling = true;
85 } else if (m_mousePolling) {
87 m_mousePolling = false;
88 }
89}
90
91void TrackMouseEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime)
92{
93 QTime t = QTime::currentTime();
94 m_angle = ((t.second() % 4) * m_angleBase) + (t.msec() / 1000.0 * m_angleBase);
95 m_lastRect[0].moveCenter(cursorPos().toPoint());
96 m_lastRect[1].moveCenter(cursorPos().toPoint());
97 data.paint += m_lastRect[0].adjusted(-1, -1, 1, 1);
98
99 effects->prePaintScreen(data, presentTime);
100}
101
102void TrackMouseEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion &region, Output *screen)
103{
104 effects->paintScreen(renderTarget, viewport, mask, region, screen); // paint normal screen
105
106 if (effects->isOpenGLCompositing() && m_texture[0] && m_texture[1]) {
108 GLShader *shader(binder.shader());
109 if (!shader) {
110 return;
111 }
112 shader->setColorspaceUniformsFromSRGB(renderTarget.colorDescription());
113 glEnable(GL_BLEND);
114 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
115 QMatrix4x4 matrix(viewport.projectionMatrix());
116 const QPointF p = m_lastRect[0].topLeft() + QPoint(m_lastRect[0].width() / 2.0, m_lastRect[0].height() / 2.0);
117 const float x = p.x();
118 const float y = p.y();
119 const auto scale = viewport.scale();
120 for (int i = 0; i < 2; ++i) {
121 matrix.translate(x * scale, y * scale, 0.0);
122 matrix.rotate(i ? -2 * m_angle : m_angle, 0, 0, 1.0);
123 matrix.translate(-x * scale, -y * scale, 0.0);
124 QMatrix4x4 mvp(matrix);
125 mvp.translate(m_lastRect[i].x() * scale, m_lastRect[i].y() * scale);
127 m_texture[i]->render(m_lastRect[i].size() * scale);
128 }
129 glDisable(GL_BLEND);
130 } else if (effects->compositingType() == QPainterCompositing && !m_image[0].isNull() && !m_image[1].isNull()) {
131 QPainter *painter = effects->scenePainter();
132 const QPointF p = m_lastRect[0].topLeft() + QPoint(m_lastRect[0].width() / 2.0, m_lastRect[0].height() / 2.0);
133 for (int i = 0; i < 2; ++i) {
134 painter->save();
135 painter->translate(p.x(), p.y());
136 painter->rotate(i ? -2 * m_angle : m_angle);
137 painter->translate(-p.x(), -p.y());
138 painter->drawImage(m_lastRect[i], m_image[i]);
139 painter->restore();
140 }
141 }
142}
143
145{
146 effects->addRepaint(m_lastRect[0].adjusted(-1, -1, 1, 1));
148}
149
150bool TrackMouseEffect::init()
151{
153 if (!m_texture[0] && m_image[0].isNull()) {
154 loadTexture();
155 if (!m_texture[0] && m_image[0].isNull()) {
156 return false;
157 }
158 }
159 m_lastRect[0].moveCenter(cursorPos().toPoint());
160 m_lastRect[1].moveCenter(cursorPos().toPoint());
161 m_angle = 0;
162 return true;
163}
164
165void TrackMouseEffect::toggle()
166{
167 switch (m_state) {
168 case State::ActivatedByModifiers:
169 m_state = State::ActivatedByShortcut;
170 break;
171
172 case State::ActivatedByShortcut:
173 m_state = State::Inactive;
174 break;
175
176 case State::Inactive:
177 if (!init()) {
178 return;
179 }
180 m_state = State::ActivatedByShortcut;
181 break;
182
183 default:
184 Q_UNREACHABLE();
185 break;
186 }
187
188 effects->addRepaint(m_lastRect[0].adjusted(-1, -1, 1, 1));
189}
190
191void TrackMouseEffect::slotMouseChanged(const QPointF &, const QPointF &,
192 Qt::MouseButtons, Qt::MouseButtons,
193 Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers)
194{
195 if (!m_mousePolling) { // we didn't ask for it but maybe someone else did...
196 return;
197 }
198
199 switch (m_state) {
200 case State::ActivatedByModifiers:
201 if (modifiers == m_modifiers) {
202 return;
203 }
204 m_state = State::Inactive;
205 break;
206
207 case State::ActivatedByShortcut:
208 return;
209
210 case State::Inactive:
211 if (modifiers != m_modifiers) {
212 return;
213 }
214 if (!init()) {
215 return;
216 }
217 m_state = State::ActivatedByModifiers;
218 break;
219
220 default:
221 Q_UNREACHABLE();
222 break;
223 }
224
225 effects->addRepaint(m_lastRect[0].adjusted(-1, -1, 1, 1));
226}
227
228void TrackMouseEffect::loadTexture()
229{
230 QString f[2] = {QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("tm_outer.png")),
231 QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("tm_inner.png"))};
232 if (f[0].isEmpty() || f[1].isEmpty()) {
233 return;
234 }
235
236 for (int i = 0; i < 2; ++i) {
238 QImage img(f[i]);
239 m_texture[i] = GLTexture::upload(img);
240 m_lastRect[i].setSize(img.size());
241 }
243 m_image[i] = QImage(f[i]);
244 m_lastRect[i].setSize(m_image[i].size());
245 }
246 }
247}
248
250{
251 return m_state != State::Inactive;
252}
253
254} // namespace
255
256#include "moc_trackmouse.cpp"
void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion &region, Output *screen)
Q_SCRIPTABLE void addRepaint(const QRectF &r)
bool makeOpenGLContextCurrent()
Makes the OpenGL compositing context current.
CompositingType compositingType
void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime)
bool isOpenGLCompositing() const
Whether the Compositor is OpenGL based (either GL 1 or 2).
void mouseChanged(const QPointF &pos, const QPointF &oldpos, Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons, Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers)
KSharedConfigPtr config() const
QPainter * scenePainter()
Provides access to the QPainter which is rendering to the back buffer.
bool setColorspaceUniformsFromSRGB(const ColorDescription &dst)
Definition glshader.cpp:457
bool setUniform(const char *name, float value)
Definition glshader.cpp:301
static std::unique_ptr< GLTexture > upload(const QImage &image)
const ColorDescription & colorDescription() const
QMatrix4x4 projectionMatrix() const
void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override
void postPaintScreen() override
void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion &region, Output *screen) override
void reconfigure(ReconfigureFlags) override
~TrackMouseEffect() override
Qt::KeyboardModifiers modifiers
Definition trackmouse.h:26
bool isActive() const override
static QPointF cursorPos()
Definition effect.cpp:478
@ ReconfigureAll
Definition effect.h:601
@ QPainterCompositing
Definition globals.h:39
EffectsHandler * effects